MCP security
This content is for v1.0. Switch to the latest version for up-to-date documentation.
Stop agents from presenting a valid token for tool A to tool B. Starfly registers MCP tools with a resource_uri, binds that value to aud on the WIMSE JWT, and returns 403 when they do not match — the confused-deputy fix for agentic tool calling.
Why it’s worth your time
Section titled “Why it’s worth your time”- One check, every MCP call — verify audience before the tool executes, not after an incident.
- Works with your existing exchange flow — same RFC 8693 endpoint;
audiencemust equal the tool’sresource_uri. - Visible in ops — denials show on the MCP Security dashboard tab and in audit.
How it works
Section titled “How it works”Register tool (resource_uri) → Exchange with audience = resource_uri → WIMSE JWT ↓ POST /v1/mcp/verify on each call ↓ 200 match · 403 confused deputyFor multi-protocol tool servers, add UTC middleware in front of handlers; PEP-side registration and verify stay the same.
Wire it up
Section titled “Wire it up”1. Register the tool
Section titled “1. Register the tool”curl -s -X POST "$STARFLY_URL/v1/mcp/tools" \ -H "Content-Type: application/json" \ -d '{ "tool_id": "code-search", "name": "Code Search", "resource_uri": "https://mcp.example.com/tools/code-search", "server_id": "my-mcp-server" }' | jqList registered tools: GET /v1/mcp/tools
2. Exchange for a tool-scoped token
Section titled “2. Exchange for a tool-scoped token”curl -s -X POST "$STARFLY_URL/v1/exchange/token" \ -H "Content-Type: application/json" \ -d '{ "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange", "subject_token": "<AGENT_OR_STUB_JWT>", "subject_token_type": "urn:ietf:params:oauth:token-type:jwt", "audience": "https://mcp.example.com/tools/code-search" }' | jq -r .access_tokenThe audience must equal the tool’s resource_uri. See token exchange for credential types and fields.
3. Verify on each call
Section titled “3. Verify on each call”curl -s -X POST "$STARFLY_URL/v1/mcp/verify" \ -H "Content-Type: application/json" \ -d '{ "token": "<WIMSE_JWT>", "tool_id": "code-search" }' | jq| Result | Meaning |
|---|---|
| HTTP 200 | Token audience matches tool |
| HTTP 403 | Wrong tool or audience — confused deputy blocked |
4. Revoke when compromised
Section titled “4. Revoke when compromised”Send CAEP session-revoked or tool-specific signals via POST /v1/signals/events. See revocation.
Prove it in the sandbox
Section titled “Prove it in the sandbox”./sandbox/run.sh mcpExpected: allow on code-search, 403 on sql-admin with the same token.
Code in this repo
Section titled “Code in this repo”| Path | Status |
|---|---|
pkg/mcp/ | Shipped — registry, verify middleware, client |
| OpenAPI — MCP operations | Reference |
Related
Section titled “Related”- Token exchange
- UTC — same identity on non-MCP wire shapes
- Glossary: MCP
- Documentation voice