Repository navigation
Conversation
alexluong
force-pushed
the
feat/mcp-schemas
branch
from
October 30, 2026 13:15
d4f4d08 to
c0dbca8
Compare
alexluong
force-pushed
the
feat/mcp-subscribe-endpoints
branch
from
October 30, 2026 13:15
16aa48c to
bc3ef43
Compare
alexluong
force-pushed
the
feat/mcp-schemas
branch
from
October 30, 2026 20:51
f486fc3 to
6129b03
Compare
alexluong
force-pushed
the
feat/mcp-subscribe-endpoints
branch
from
October 30, 2026 20:51
c374170 to
5cf245d
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add endpoints that serve the MCP Events (draft SEP-3415)
events/subscribeandevents/unsubscribemethods, so an operator's MCP server forwards them to Outpost in one call instead of managingmcpdestinations itself. Experimental, behindEXPERIMENTAL_MCP_ENABLED.Stacked on #1182. Deviations from the draft, including what these endpoints leave out: see #1181.
Why this approach
The protocol rules live in one tested place in Outpost: ID derivation, lifetime grants, refresh and expiry, error codes. The MCP server stays a thin forwarder that works in any language, and a subscribe is one Outpost call. The cost is that Outpost owns the MCP wire format and moves with the draft, which is acceptable while the feature is experimental.
Changes
POST /tenants/{tenant_id}/mcp/subscribewith{"principal", "params", "allowed_topics"?}, whereparamsare the MCP request params as received. It creates themcpdestination, running the same checks as destination create, and answers with the MCP result (id,refreshBefore,cursor: null,truncated: false).idis derived from principal, callback URL, event name and arguments. Subscribing again with the same values refreshes it: sameid, new expiry, rotated secret, re-enabled if it was suspended. The refresh result'sdeliveryStatus.activesays whether it was active before the refresh. An expired subscription is replaced by a new one. Concurrent subscribes for the same subscription can't create duplicates (fix: make concurrent tenant and destination writes safe #1172).ttlMsis clamped toEXPERIMENTAL_MCP_SUBSCRIPTION_TTL_MIN_SECONDS(300) andEXPERIMENTAL_MCP_SUBSCRIPTION_TTL_MAX_SECONDS(86400). NottlMsgetsEXPERIMENTAL_MCP_SUBSCRIPTION_TTL_DEFAULT_SECONDS(3600), andnullgets the maximum, so every grant is finite, which the draft allows.POST /tenants/{tenant_id}/mcp/unsubscribedeletes the subscription identified by the same principal, event, arguments and callback URL (not found otherwise).422with anmcp_error(code,message, anddataonly where the draft defines it) for the MCP server to return as its JSON-RPC error.dataholds only the fields the draft defines; Outpost's own detail (field names, reasons,retryAfterMs) stays in logs and the REST422mapping.-32602invalid params and-32024forbidden carry nodata.-32023not found hasdata.kind,-32025resource exhausted hasdata.limit(anddata.maxwhen there is one),-32026unsupported hasdata.featureanddata.value(a delivery mode other thanwebhook),-32027callback endpoint error hasdata.reason(a fixed category, never endpoint output). A callback verification rate limit maps to-32025. A verification store outage is not a client error: it returns an internal error. A subscribe that keeps losing to concurrent changes of the same subscription, or whose tenant is deleted meanwhile, returns503withRetry-After; a retry succeeds.allowed_topicsrestricts the events a principal may subscribe to: omitted allows all, an empty list allows none. A subscription to a refused event answersForbidden; the check runs before the catalog lookup, so an unknown name outside the list isForbiddentoo.Both routes are Admin API key only and return
404while MCP is off.Behavior changes
EXPERIMENTAL_MCP_SUBSCRIPTION_TTL_DEFAULT_SECONDS,EXPERIMENTAL_MCP_SUBSCRIPTION_TTL_MIN_SECONDS,EXPERIMENTAL_MCP_SUBSCRIPTION_TTL_MAX_SECONDS. Startup fails unless min <= default <= max.Not in this PR
🤖 Generated with Claude Code