Skip to main content
Triggers are in draft. Breaking change may happen without notice.
Triggers let an MCP server surface events from its upstream service. When a user activates a trigger, Smithery hands your server a callback URL to register with the upstream provider. When the provider fires, it POSTs to Smithery, which re-signs the payload and delivers it to the consumer’s subscription URL. 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. Method names, field names, and wire shapes for the methods we do implement match the proposal, so that once MCP ships a standard events primitive, migration for webhook-only servers is a prefix drop: ai.smithery/events/listevents/list. Servers that also want to support poll or push will need additional work when that happens. What Smithery implements today:
  • events/list — full parity
  • events/subscribe in webhook mode only
  • events/unsubscribe
What Smithery does not implement (yet):
  • poll and push (events/stream) delivery modes
  • Cursor replay — events start “from now”
  • TTL refresh — subscriptions persist until unsubscribe is called
  • deliveryStatus reporting
Smithery generates the subscription id and supplies a delivery.url on the callbacks.smithery.run domain.

How it works

  1. The consumer creates a trigger through Smithery.
  2. Smithery calls your ai.smithery/events/subscribe with a high-entropy id and a delivery.url on callbacks.smithery.run.
  3. Your server uses the connection’s credentials to register or start whatever event source it needs.
  4. Your MCP server POSTs events directly to Smithery. Smithery signs and fans out.
  5. When the consumer deletes the trigger, 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. Smithery trust-passes the upstream payload without transformation.

ai.smithery/events/subscribe

Smithery calls this once when a consumer activates a trigger. Register a webhook with the upstream service pointing at delivery.url. Smithery does not call subscribe again for the same id; the subscription stays active until unsubscribe is called. Request:
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "ai.smithery/events/subscribe",
  "params": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "name": "page.updated",
    "params": { "workspace_id": "w_123" },
    "delivery": {
      "mode": "webhook",
      "url": "https://callbacks.smithery.run/t/f47ac10b-58cc-4372-a567-0e02b2c3d479"
    }
  }
}
Response:
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {}
}
ParamDescription
idHigh-entropy subscription identifier generated by Smithery. Persist this with your upstream webhook record so unsubscribe can find it.
nameThe event name from events/list.
paramsSubscriber-supplied arguments conforming to the event’s inputSchema.
delivery.modeAlways "webhook" for this extension.
delivery.urlHTTPS URL on callbacks.smithery.run where events should be POSTed.

ai.smithery/events/unsubscribe

Smithery calls this when the consumer deletes the trigger, or on eager cleanup. Tear down the upstream registration you created.
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "ai.smithery/events/unsubscribe",
  "params": {
    "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
    "delivery": {
      "url": "https://callbacks.smithery.run/t/f47ac10b-58cc-4372-a567-0e02b2c3d479"
    }
  }
}
Response:
{
  "jsonrpc": "2.0",
  "id": 4,
  "result": {}
}
Your server looks up the subscription by (id, delivery.url) and deregisters the corresponding upstream webhook.

Event delivery

Your server is not involved at event time. The upstream provider POSTs directly to delivery.url; Smithery wraps the payload in the standard envelope, signs it per Standard Webhooks, and delivers it to the consumer’s subscription URL. You are responsible for:
  1. Declaring a payloadSchema that accurately describes the data field.
  2. Configuring upstream webhook registration so the payload delivered to Smithery 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. Smithery does not run code per event.

Callback URL contract

Smithery mints one delivery.url per subscription. It is:
  • HTTPS only.
  • Stable for the lifetime of the subscription — no rotation.
  • Unique per id — inferring tenancy from the URL is safe.
Some providers require pre-approved destination domains (Stripe, corporate-managed SaaS). Smithery’s callback domain is callbacks.smithery.run and is stable — you can allow-list it with your upstream provider. Field shapes elsewhere in this doc are still draft and may change, but the callback host will not.

Authentication of upstream deliveries

The id segment in delivery.url is high-entropy and functions as a bearer capability — Smithery trusts any POST to that URL as belonging to the named subscription. Upstream provider signatures (e.g. GitHub’s X-Hub-Signature-256, Stripe’s Stripe-Signature) are not verified by Smithery in v1. If your upstream supports a configurable webhook secret, you may set one at registration time and include verification logic in a future ai.smithery/events/deliver hook; until then, treat delivery.url secrecy as the authentication boundary.

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{ id, name, params, delivery: { mode, url } }{}
ai.smithery/events/unsubscribe{ id, delivery: { url } }{}

Callback URL contract

PropertyValue
Schemehttps:// only
Hostcallbacks.smithery.run
Path/t/{id} — unique per subscription
LifetimeStable for the lifetime of the subscription
PayloadRaw upstream body, unmodified by Smithery before delivery

Learn more