Skip to main content

Documentation Index

Fetch the complete documentation index at: https://smithery.ai/docs/llms.txt

Use this file to discover all available pages before exploring further.

Triggers are in preview. Breaking changes may happen without notice.
Triggers let an MCP server surface events from its upstream service. When a consumer activates a trigger via Smithery, Smithery proxies the subscribe call straight through to your server with the consumer’s webhook URL and signing secret. When the upstream provider fires, your server POSTs the event directly to the consumer — Smithery is not in the delivery path. Your server is not in the hot path for events — only for setup and teardown. This keeps trigger support compatible with serverless runtimes.

Alignment with the MCP Events proposal

This extension tracks the webhook slice of the MCP committee’s events proposal. Smithery is intentionally minimal: it implements only what the spec requires for webhook delivery, and skips optional surface area while the proposal is still draft. What Smithery implements today:
  • events/list — full parity
  • events/subscribe in webhook mode only, with mandatory TTL refresh
  • events/unsubscribe
What Smithery does not implement:
  • poll and push (events/stream) delivery modes
  • Cursor replay — events start “from now”
  • truncated, maxAge, maxEvents parameters
  • Control envelopes (gap, terminated)
  • deliveryStatus reporting
  • Asymmetric endpoint verification or server signing
Smithery acts as the spec’s “client” against your server: it forwards the consumer’s delivery.url and Standard Webhooks delivery.secret unchanged. Your server signs deliveries with that secret and POSTs them to that URL.

How it works

  1. The consumer creates a trigger through Smithery, supplying their own webhook URL and Standard Webhooks secret.
  2. Smithery, authenticated as the connection’s principal, calls your ai.smithery/events/subscribe and forwards the consumer’s delivery.url and delivery.secret unchanged.
  3. Your server uses the connection’s credentials to register an upstream webhook (or start whatever event source it needs) and returns { id, refreshBefore }.
  4. Before refreshBefore, the consumer re-POSTs through Smithery, which re-calls subscribe with the same key — your server treats this as an idempotent upsert and resets the TTL.
  5. When the upstream fires, your server POSTs the event directly to the consumer’s delivery.url, signed with delivery.secret. Smithery is not involved in delivery.
  6. When the consumer deletes the trigger (or stops refreshing), Smithery calls ai.smithery/events/unsubscribe to tear down the upstream registration.

Negotiation

Advertise the extension in your initialize response:
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-11-25",
    "capabilities": {
      "extensions": {
        "ai.smithery/events": {}
      }
    },
    "serverInfo": { "name": "NotionMCP", "version": "1.0.0" }
  }
}

Methods

ai.smithery/events/list

Return the catalog of event types your server supports. Each entry declares the params a subscriber must provide and the payload your server will deliver.
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "events": [
      {
        "name": "page.updated",
        "description": "Fires when a page in the watched workspace is updated.",
        "delivery": ["webhook"],
        "inputSchema": {
          "type": "object",
          "properties": {
            "workspace_id": { "type": "string" }
          },
          "required": ["workspace_id"]
        },
        "payloadSchema": {
          "type": "object",
          "properties": {
            "page_id": { "type": "string" },
            "updated_at": { "type": "string", "format": "date-time" }
          }
        }
      }
    ]
  }
}
FieldTypeDescription
namestringUnique event name scoped to your server.
descriptionstringHuman-readable summary of when this event fires.
deliverystring[]Delivery modes this event supports. For Smithery, return ["webhook"].
inputSchemaobjectJSON Schema for the params a subscriber must supply (e.g. workspace or channel scoping). Mirrors the inputSchema convention from tools.
payloadSchemaobjectJSON Schema describing the data object your server emits.

ai.smithery/events/subscribe

Smithery calls this when a consumer activates a trigger, and again before each refreshBefore to keep the subscription alive. Register an upstream webhook pointing at delivery.url, retain delivery.secret to sign each POST, and return a stable subscription id plus a fresh refreshBefore. Request:
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "ai.smithery/events/subscribe",
  "params": {
    "name": "page.updated",
    "params": { "workspace_id": "w_123" },
    "delivery": {
      "mode": "webhook",
      "url": "https://my-app.example.com/events",
      "secret": "whsec_<base64 of 24-64 random bytes>"
    }
  }
}
Response:
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "id": "sub_a3f1c8e2b0d49f7e",
    "refreshBefore": "2026-04-22T13:00:00.000Z"
  }
}
ParamDescription
nameThe event name from events/list.
paramsSubscriber-supplied arguments conforming to the event’s inputSchema.
delivery.modeAlways "webhook" for this extension.
delivery.urlThe consumer’s HTTPS webhook endpoint. POSTs go here directly.
delivery.secretThe consumer’s Standard Webhooks whsec_ secret. Sign each POST to delivery.url with this secret.
Result fieldDescription
idStable subscription handle deterministic over (principal, name, params, delivery.url). The receiver uses it to look up the right secret via the X-MCP-Subscription-Id header.
refreshBeforeISO 8601 timestamp at which the subscription expires unless refreshed. Pick a TTL that reflects how long you can hold soft state for (e.g. 30 minutes).

Idempotent upsert and TTL refresh

ai.smithery/events/subscribe is keyed by (principal, name, params, delivery.url). If a subscription with the same key already exists, treat the call as an upsert:
  • TTL — reset, return a new refreshBefore.
  • delivery.secret — replace. During rotation, the spec recommends dual-signing with the old and new secrets for a short grace window using Standard Webhooks’ multi-signature support.
  • id — unchanged.
If the subscription has expired (or your server lost it on restart), create a fresh one for the same key and return a new id. If Smithery stops refreshing before refreshBefore, expire the subscription and tear down the upstream webhook — no explicit unsubscribe is required.

ai.smithery/events/unsubscribe

Smithery calls this on eager teardown (consumer deleted the trigger). Tear down the upstream registration you created.
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "ai.smithery/events/unsubscribe",
  "params": {
    "name": "page.updated",
    "params": { "workspace_id": "w_123" },
    "delivery": {
      "url": "https://my-app.example.com/events"
    }
  }
}
Response:
{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {}
}
Look up the subscription by (principal, name, params, delivery.url) and deregister the corresponding upstream webhook. The subscription id is not accepted here — the key is the canonical identifier.

Event delivery

When an upstream event arrives, POST it to delivery.url, signed with the Standard Webhooks headers and the consumer’s delivery.secret. The consumer verifies the signature and processes the event. You are responsible for:
  1. Declaring a payloadSchema that accurately describes the data field.
  2. Configuring upstream webhook registration so the payload delivered to the consumer matches that schema.
  3. Never including secrets or PII the consumer shouldn’t see.
If the upstream payload requires transformation (unwrapping envelopes, hydrating IDs, redacting fields), do it at registration time — use the provider’s webhook filter or payload-shape features. The body sent to the consumer is an EventOccurrence:
{
  "eventId": "evt_01HW...",
  "name": "page.updated",
  "timestamp": "2026-04-22T12:00:00.000Z",
  "data": {
    "page_id": "...",
    "updated_at": "2026-04-22T12:00:00.000Z"
  }
}
FieldDescription
eventIdStable event identifier. Use the upstream’s stable id (Stripe evt_*, GitHub delivery GUID, Gmail message id) so the receiver can dedupe across retries.
nameThe event name from events/list.
timestampISO 8601 timestamp of the upstream event.
dataPayload conforming to the event’s payloadSchema.

Webhook signing

Sign every POST with the Standard Webhooks HMAC profile. Required headers:
HeaderValue
webhook-idStable event id for deduplication
webhook-timestampUnix seconds
webhook-signaturev1,<base64 HMAC-SHA256(delivery.secret, "id.timestamp.body")>
X-MCP-Subscription-IdThe subscription id you returned from events/subscribe. The receiver uses this to look up the right secret before parsing the body.
Sign the raw request body with a Standard Webhooks library. Each retry attempt MUST regenerate the timestamp and signature so receivers do not reject a later attempt as stale.

API reference

Extension capability

Advertise during initialize under capabilities.extensions:
{ "ai.smithery/events": {} }

MCP methods (Smithery → server)

MethodParamsResult
ai.smithery/events/list{ events: [{ name, description, delivery, inputSchema, payloadSchema }] }
ai.smithery/events/subscribe{ name, params, delivery: { mode, url, secret } }{ id, refreshBefore }
ai.smithery/events/unsubscribe{ name, params, delivery: { url } }{}

Learn more