Derive the /mcp agent endpoint from the agent-tagged routes#37
Merged
Conversation
czpython
force-pushed
the
eng/mcp-endpoint
branch
from
July 20, 2026 14:35
8857944 to
4692499
Compare
czpython
force-pushed
the
eng/mcp-endpoint
branch
from
July 20, 2026 15:23
fed43e3 to
5829598
Compare
czpython
marked this pull request as ready for review
July 20, 2026 16:21
The gateway's five operations live at their nouns — /api/gates/{run_id}
(+/answer), /api/agent-calls/{call_id}, /api/runs/{run_id}/cancel beside
resume, /api/usage/summary — tagged "agent": the tag, not a URL umbrella,
marks the agent surface, and the route docstrings carry the tool
descriptions.
/mcp serves tools derived from those routes (FastMCP's OpenAPIProvider
over an in-process ASGI client), so a route is an operation's single
declaration — schema, docstring, operation_id — and a tagged extension
route joins tools/list by declaration alone. mcp_app mounts at exactly
/mcp (a bare Route; JSON 404 owns the subpaths) with its lifespan
composed through combine_lifespans.
PAT bearer gates the transport; CallerPat re-stamps each caller's bearer
onto the internal route call (the derivation strips authorization when
replaying headers), so every route runs as the presenting account. The
transport is built with raise_app_exceptions=False: failures reach the
tool as the app's sanitized HTTP responses — the domain taxonomy
{code, message, retryable} travels, validation errors carry
VALIDATION_ERROR.
Caddy serves /mcp on both listeners ahead of the identity gate (a bearer
client can't do interactive SSO); the public integrations host is the
canonical address. read_slice stays a plain byte window — the one stale
seam expectation aligns to it. docs/connect-your-agent.md covers the five
tools, the parkedAt echo contract, and both CLIs' configuration.
czpython
force-pushed
the
eng/mcp-endpoint
branch
from
July 20, 2026 16:22
e94d584 to
d1ceaac
Compare
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.
What
/api/gates/{run_id}(+/answer),/api/agent-calls/{call_id},/api/runs/{run_id}/cancelbeside the existing resume,/api/usage/summary— withtags=["agent"]as the one grouping signal and unchanged operation_ids;/mcpbelongs to the protocol endpoint alone. Route docstrings carry the agent-facing descriptions both surfaces read./mcpserves tools derived from theagent-tagged routes (FastMCPOpenAPIProviderover an in-process ASGI client) — the route is an operation's single declaration (schema, docstring, operation_id), so an extension's tagged route joinstools/listby declaration alone.mcp_appmounts at exactly/mcpwith its lifespan composed viacombine_lifespans; annotations come from a per-operation map, and the tools/list test guards unmapped tagged routes.PatTokenVerifier), andCallerPatre-stamps each caller's bearer onto the internal route call (the derivation stripsauthorizationwhen replaying headers), so every route runs as the presenting account.raise_app_exceptions=False, so an app crash reaches the tool as the app's sanitized 500 — no masking needed, and the domain taxonomy{code, message, retryable}travels embedded in tool-error text. Validation failures carryVALIDATION_ERRORdetail instead; documented.eng/agent-servicescarries the fuller sweep and supersedes it on merge)./mcpon both listeners — ahead of the identity gate on the dashboard listener, beside the HMAC webhooks on the public integrations listener (the canonical corporate address).connect-your-agent.md(five tools, theparkedAtecho contract, the claude one-liner and codexconfig.tomlform, honest v1 caveats: polling only, no discovery tool) plus deploy, configuration, and troubleshooting links.Deliberately not ported from the old branch
/api/auth/patsrename — main's shipped/api/auth/personal-tokensis the contract, pinned by the boundary test.list_work/get_work_item/dispatch) returns later asagent-tagged routes on build's own router, the extension-contribution seam's first proof.Known semantic, flagged not changed
Two concurrent different answers to the same gate round can both report
answered; DBOS's idempotency key keeps only the first payload. Pre-existing and shared with the Slack notification path — a fix belongs to the resume contract, not this surface.