Skip to content

MCP delegation boundary: serveMcp accepts an inbound chain (stage 3)#6

Merged
ZubeidHendricks merged 1 commit into
mainfrom
delegation-mcp-boundary
Jun 17, 2026
Merged

MCP delegation boundary: serveMcp accepts an inbound chain (stage 3)#6
ZubeidHendricks merged 1 commit into
mainfrom
delegation-mcp-boundary

Conversation

@ZubeidHendricks

Copy link
Copy Markdown
Owner

What

Stage 3 of the delegation/authz design: the cross-process half of the confused-deputy defense. A gateway (Kagenti's MCP gateway, an Istio policy, an Envoy filter) can sit in front of an MCP-served TOAD agent, set the delegation chain, and the served agent honors it — so the agent's own tool calls authorize against the full chain, not just whatever the agent started with.

Builds on stages 1–2 (PR #5: chain propagation + deny-capable authorizeToolCall).

How

  • Wire codec in delegation.tsencodeDelegationHeader / parseDelegationHeader for the Toad-Delegation form: subject=<id>; chain=<id>,<id>,…, ids percent-encoded so any character is safe. Identities-only; the structured object form carries scopes/claims for full fidelity.
  • serveMcp accepts inbound — a tools/call may carry a chain in its MCP _meta under toad/delegation, as either the structured DelegationContext object or the header string. serveMcp reads it, extends it by the served agent (this hop), and runs the agent with that chain.
  • Absent _meta ⇒ identical behavior to before. Fully opt-in.

Verified

  • 82 runtime tests (+8): header round-trip, percent-encoding of grammar-breaking ids, empty/garbage tolerance; and the boundary accepting both structured and string chains, extending by the served agent, and running chain-free when _meta is absent.
  • typecheck + prettier clean; runtime builds.

New exports

encodeDelegationHeader, parseDelegationHeader, DELEGATION_HEADER.

Still future (stage 4, in the doc)

Outbound emission (a TOAD agent acting as an MCP client), optional JWS signing, and a declarative .agent allow: block compiled by toac.

🤖 Generated with Claude Code

Lets a gateway sit in front of an MCP-served TOAD agent and have the agent
honor the delegation chain — the cross-process half of the confused-deputy
defense.

- Toad-Delegation wire codec: encodeDelegationHeader / parseDelegationHeader
  (ids percent-encoded; identities-only — structured form carries scopes/claims).
- serveMcp reads a chain from a tools/call's `_meta["toad/delegation"]` (the
  structured DelegationContext object or the header string), extends it by the
  served agent, and runs the agent with it — so the agent's own tool calls
  authorize against the full chain. Absent _meta ⇒ unchanged behavior.
- New exports: encodeDelegationHeader, parseDelegationHeader, DELEGATION_HEADER.

8 new tests (82 runtime total): header round-trip + percent-encoding + tolerance,
and the boundary accepting structured/string chains and extending by the agent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ZubeidHendricks ZubeidHendricks merged commit fc0d75b into main Jun 17, 2026
1 check passed
@ZubeidHendricks ZubeidHendricks deleted the delegation-mcp-boundary branch June 17, 2026 22:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant