Folded resource

At a glance. Multiple internal services live behind one MCP boundary. AuthPlane sees one Resource (mcp-a). The MCP internally calls other services using its own mesh auth (mTLS, service tokens, whatever) — AuthPlane doesn’t participate in the internal hop. Simplest way to compose internal microservices behind an MCP without exposing each as a separate resource.

Topology

flowchart TD
    Agent["Agent"]
    MCP["MCP-A<br/>(visible to AuthPlane)"]
    Svc1["Svc1<br/>(int.)"]
    Svc2["Svc2<br/>(..)"]
    Svc3["Svc3<br/>(..)"]

    Agent -->|"Bearer<br/>aud=mcp-a"| MCP
    MCP -->|"mesh auth<br/>(mTLS, SA token, etc.)<br/>invisible to AuthPlane"| Svc1
    MCP -->|"mesh auth<br/>(mTLS, SA token, etc.)<br/>invisible to AuthPlane"| Svc2
    MCP -->|"mesh auth<br/>(mTLS, SA token, etc.)<br/>invisible to AuthPlane"| Svc3

Only MCP-A is a Resource. Svc1/2/3 are AuthPlane-invisible — their mesh auth is your own concern (Istio, Linkerd, SPIFFE, whatever your infra provides).

Flow

sequenceDiagram
    participant Agent
    participant MCP as MCP-A
    participant Svc1
    participant Svc2
    participant Svc3

    Agent->>MCP: POST /mcp Authorization: Bearer <token, aud=mcp-a>
    MCP->>MCP: validates the token against AuthPlane's JWKS (cached)
    MCP->>MCP: tool handler decides internally to fan out
    MCP->>Svc1: mesh call (mTLS SAN=svc1, no AuthPlane involvement)
    MCP->>Svc2: mesh call
    MCP->>Svc3: mesh call
    MCP-->>Agent: assembles response, returns to Agent

Steps 3a-3c are outside AuthPlane’s model — the internal hop is your service mesh’s concern.

When to use

  • Backend services are internal implementation details of one MCP.
  • You don’t want per-service consent / per-service audience — the boundary is the MCP.
  • You have a service mesh with strong internal auth already.
  • Fan-out scopes are decided by tool-handler logic, not by user consent.

Don’t use when:

  • Users need visibility/consent into individual downstream services → each service is its own Resource, use direct-fanout.
  • The internal hop wants an agent-attributed audit trail → use mcp-gateway-mint instead — the gateway becomes an OAuth client that hits real Mint resources with delegated tokens.

How to configure

Only the outer MCP needs registration — same as single-mcp:

authserver admin resource create \
    --slug mcp-a \
    --uri https://mcp-a.example.com/mcp \
    --backend-kind mint \
    --scopes 'tools/query||Query tools' \
    --scopes 'tools/write||Write tools'

authserver admin client create \
    --name my-agent \
    --grant-types authorization_code,refresh_token \
    --auth-method none \
    --scopes 'tools/query||Query tools' \
    --scopes 'tools/write||Write tools'

Internal services get no AuthPlane config. Register them with your mesh instead.

How AuthPlane handles it

Nothing special. The topology is single-mcp from AuthPlane’s perspective. The “folded” part is entirely internal to MCP-A’s process — an implementation detail of the tool handler.

If you later want to expose an internal service as its own Resource (per-service consent, per-service audit), promote it out of the fold and register it individually.

Verify

# Only one resource visible to AuthPlane
authserver admin resource list
# → mcp-a  (Svc1/2/3 do NOT appear)

# Only one issuance per (agent, user)
authserver admin issuance list --client my-agent --resource mcp-a

Internal hop is not audited by AuthPlane — instrument it with your mesh’s observability (OTEL traces from MCP-A carry through to Svc1/2/3 with traceparent).

See also