# Orchestrator

Canonical URL: https://vercel-mcp-reference.vercel.app/patterns/orchestrator/
Markdown: https://vercel-mcp-reference.vercel.app/patterns/orchestrator.md
Audience: engineer, architect, security, non-technical. MCP spec version: 2026-07-28. Last reviewed: 2026-08-26. Status: stable.

## Summary

An [orchestrator](https://vercel-mcp-reference.vercel.app/glossary/#orchestrator) is a [host](https://vercel-mcp-reference.vercel.app/glossary/#host) or agent runtime that coordinates many MCP [servers](https://vercel-mcp-reference.vercel.app/glossary/#server) as one tool layer for a model. It decides which servers to connect to, which [tools](https://vercel-mcp-reference.vercel.app/glossary/#tool) to expose for a given task, how to mediate cross-server work, and how to enforce [consent](https://vercel-mcp-reference.vercel.app/glossary/#consent) and policy across the whole surface. It is the one pattern in this repository that lives in the host, not in a deployed server: on Vercel the servers it composes are Function routes in separate projects, and the orchestrator reaches each one over the [Streamable HTTP transport](https://vercel-mcp-reference.vercel.app/glossary/#streamable-http-transport).

## Problem addressed

A model that can call one tool on one server is a demo. A model that plans across a dozen tools on several servers is a product, and the moment more than one server is involved, somebody has to own which server a call routes to, how name collisions are disambiguated, how progress is surfaced, where consent is gated, and how one server's compromise is kept out of another server's context.

That coordination cannot live inside any single server: each server sees only the requests the host chooses to send it. It belongs in the host, the only component with direct user trust. The orchestrator pattern names that responsibility explicitly and puts it where MCP's architecture already points.

## When to use

- The host connects to more than one MCP server at the same time.
- The model's plans regularly span tools from multiple servers within a single task.
- You need uniform policy (consent, audit, rate limiting, redaction) that the servers cannot enforce coherently on their own.
- You want one place to filter the per-task tool list shown to the model, rather than handing it the union of every server's `tools/list`.
- Output of server A becomes input to server B, and you refuse to let that flow happen anywhere except under the host's mediation.

## When not to use

- The host only ever talks to one server. A trivial orchestrator is complexity with no benefit.
- The composition you want is server-side: many backends behind one MCP surface is a [facade](https://vercel-mcp-reference.vercel.app/patterns/facade/), not an orchestrator.
- You are tempted to put orchestration inside a server. Don't. A server cannot observe other servers' sessions, and on Vercel it has no privileged path to its siblings anyway.

## Architecture / flow diagram

```mermaid
flowchart LR
    User[User] --> Host[Host as orchestrator]
    Host --> C1[MCP Client 1]
    Host --> C2[MCP Client 2]
    C1 -->|Streamable HTTP| S1[Server project A]
    C2 -->|Streamable HTTP| S2[Server project B]
```

## Protocol implications

- The host runs one [client](https://vercel-mcp-reference.vercel.app/glossary/#client) per connected server, each against a distinct origin with distinct credentials. Under MCP 2026-07-28 there is no per-server `initialize` handshake and no `Mcp-Session-Id` (SEP-2575, SEP-2567): every request carries the protocol version and client capabilities in `_meta`, and the client MAY call the mandatory `server/discover` RPC up front to learn a server's identity and capabilities before offering its tools to the model.
- The orchestrator aggregates each server's [discovery](https://vercel-mcp-reference.vercel.app/glossary/#discovery) results into the tool list it offers the model, namespacing by server id so collisions cannot happen. MCP's official [tool-naming guidance](https://modelcontextprotocol.io/specification/2026-07-28/server/tools) (SEP-986) governs the names servers register; the aggregated, host-side names shown to the model (for example `minimal.echo`) are the orchestrator's own vocabulary, and it owns keeping them unambiguous.
- [Sampling](https://vercel-mcp-reference.vercel.app/glossary/#sampling) is deprecated as of 2026-07-28 (SEP-2577), and server-initiated requests are replaced by Multi Round-Trip Requests (SEP-2322): a server that needs model output or user input returns an `input_required` result, and the host retries the original request with the responses attached. The consent gate moves with it; the orchestrator applies one policy to every `input_required` round trip, regardless of which server asked, exactly as it did for sampling requests from stacks still speaking the deprecated feature.
- [Roots](https://vercel-mcp-reference.vercel.app/glossary/#root) are deprecated as of 2026-07-28 (SEP-2577); prefer tool parameters or server configuration for scoping. Where a composed stdio server still speaks roots during the deprecation window, the orchestrator decides which roots each server may see based on the user's working context.
- [Progress notifications](https://vercel-mcp-reference.vercel.app/glossary/#progress-notification) and [cancellation](https://vercel-mcp-reference.vercel.app/glossary/#cancellation) flow on the originating request's response stream; the orchestrator surfaces both to the user and issues cancellation against the right server in response to user action.
- Wire status: the pinned stack (`mcp-handler` 2.1.1 on `@modelcontextprotocol/server` 2.0.0) serves the 2026-07-28 contract natively over Streamable HTTP and falls back to stateless 2025-11-25 Streamable HTTP for legacy clients; the SDK `Client` defaults to that legacy handshake unless you opt in to modern version negotiation, so the examples' in-memory test suites exercise only the legacy path.

## Vercel mapping

- **The orchestrator is not something you deploy; the servers are.** Each composed server is its own Vercel project exposing `app/api/mcp/route.ts`. The host runs wherever the user is: a desktop app, a CLI, or itself a [Vercel Function](https://vercel-mcp-reference.vercel.app/glossary/#vercel-function) serving a chat UI.
- **One origin each, no protocol session.** 2026-07-28 removed the `Mcp-Session-Id` header; anything a server must remember across calls comes back to the orchestrator as an explicit handle it passes into the next call, and the instance answering is recycled best-effort under [Fluid compute](https://vercel-mcp-reference.vercel.app/glossary/#fluid-compute), never guaranteed. Read [Serverless sessions](https://vercel-mcp-reference.vercel.app/internals/serverless-sessions/) before assuming any server remembers you.
- **There is no server-to-server path to abuse.** Vercel projects share no private network (Secure Compute, Enterprise-only, changes egress, not ingress), so any cross-server data flow must transit the host. The platform topology enforces the mediation this pattern demands: the missing network is a feature.
- **The registry is host state.** Pin production URLs per server. Composing against [preview deployments](https://vercel-mcp-reference.vercel.app/glossary/#preview-deployment) behind [Deployment Protection](https://vercel-mcp-reference.vercel.app/glossary/#deployment-protection) requires the `x-vercel-protection-bypass` secret, and those secrets belong in the host's credential store, one per server; see [credential brokering](https://vercel-mcp-reference.vercel.app/client-side/credential-brokering/).
- **When the host is itself a Function.** `maxDuration` (Hobby 300s; Pro and Enterprise 800s) bounds the entire plan-and-execute loop, and N connected servers can mean N cold starts before the first useful token. Connect lazily, in parallel, and treat every connection as rebuildable.

## Security considerations

- Cross-server tool chaining must be mediated by the orchestrator, never by direct server-to-server calls. A server learns another server's results only because the host chose to pass them. See [Trust boundaries](https://vercel-mcp-reference.vercel.app/security/checklist/#trust-boundaries).
- Forward each server only the context strictly required for the current request, never the full transcript. Every extra token you forward is a disclosure to a party that did not need it. See [Trust boundaries](https://vercel-mcp-reference.vercel.app/security/checklist/#trust-boundaries).
- Scope approval state per server: an "always allow" granted to server A must not transfer to server B, even for an identically named tool. See [Consent & user approval](https://vercel-mcp-reference.vercel.app/security/checklist/#consent--user-approval).
- The orchestrator is the only place a coherent per-user authorization view exists, because it is the only component that sees every server's `tools/list`. Filter that list per user and per task before the model does the choosing. See [Authorization & scoping](https://vercel-mcp-reference.vercel.app/security/checklist/#authorization--scoping).
- Keep an inventory of every connected server: URL, version, owner, and the credential used to reach it. A drive-by server registration is a user compromise. See [Inventory & supply chain](https://vercel-mcp-reference.vercel.app/security/checklist/#inventory--supply-chain).
- A server result with `isError: true` is a failure; surface it as one. Rendering it as ordinary success lets a compromised server smuggle content past the consent gate. See [Output trust](https://vercel-mcp-reference.vercel.app/security/checklist/#output-trust).
- Log every invocation at the orchestrator layer with the routing server, principal, and an argument hash. See [Monitoring & audit](https://vercel-mcp-reference.vercel.app/security/checklist/#monitoring--audit).

The orchestrator is the only component the user actually trusts. Build it like it knows that.

## Example implementation

- `examples/orchestrator-host` (in the repository) is the runnable implementation of this pattern and the only host-side example in the repository. It composes two of the server examples, `examples/minimal-server` (in the repository) and `examples/secure-tools-server` (in the repository), and its tests wire both through in-memory transport pairs so the whole flow runs offline. It demonstrates the host's core responsibilities concretely:
  - **one client per server**: a separate MCP client and connection for each connected server, each independently negotiated;
  - **namespaced aggregation**: every server's `tools/list` merged into one list under `<server>.<tool>` names, with the bare names asserted absent so collisions are structurally impossible;
  - **a fail-closed consent gate**: destructive calls pass a host-owned consent check proven by test to block before dispatch, including on a malformed consent callback;
  - **honest error surfacing**: a server's `isError` result becomes a typed error in the host, never a success the model can build on.

## Trade-offs

| Pros | Cons |
|---|---|
| One coherent policy, consent, and audit surface for the user. | Real complexity: the host owns multi-server lifecycle, routing, and retry. |
| Servers stay small, mutually unaware, and separately deployable. | An orchestrator bug affects every connected server at once. |
| Cross-cutting concerns (redaction, rate limits, logging) live in one place. | The orchestrator is a high-value target; its compromise is the user's compromise. |
| Per-user, per-task filtering of the tool list shown to the model. | Namespacing, routing, and data-flow rules are explicit decisions you must make and test. |

## Related patterns

- [facade](https://vercel-mcp-reference.vercel.app/patterns/facade/) - the server-side counterpart that aggregates backends inside one process; an orchestrator composes without collapsing credentials.
- [sidecar](https://vercel-mcp-reference.vercel.app/patterns/sidecar/) - the isolation shape for individual servers; its service form is just another entry in the orchestrator's registry.
- [adapter](https://vercel-mcp-reference.vercel.app/patterns/adapter/) - the typical content of each composed server.
- [trust-boundaries](https://vercel-mcp-reference.vercel.app/patterns/trust-boundaries/) - the principles the orchestrator enforces between servers.
- [least-privilege](https://vercel-mcp-reference.vercel.app/patterns/least-privilege/) - applied per server and per credential, coordinated at the host.

## Vercel deployment (Terraform)

There is deliberately no `terraform/patterns/orchestrator/`. The orchestrator lives in the host, not in a deployed server, so there is nothing to provision: no project, route, or environment variable would express the pattern. Its runnable expression is `examples/orchestrator-host` (in the repository); see the "What's deliberately not here" section of `terraform/README.md` (in the repository) for the reasoning.

## Bibliography

- Model Context Protocol Specification, *Architecture overview*, version 2026-07-28 - <https://modelcontextprotocol.io/specification/2026-07-28/architecture>
- Model Context Protocol Specification, *Versioning*, version 2026-07-28 - <https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning>
- Model Context Protocol Specification, *Tools*, version 2026-07-28 - <https://modelcontextprotocol.io/specification/2026-07-28/server/tools>
- Model Context Protocol Specification, *Multi Round-Trip Requests (MRTR)*, version 2026-07-28 - <https://modelcontextprotocol.io/specification/2026-07-28/basic/patterns/mrtr>
- Model Context Protocol Specification, *Sampling (deprecated)*, version 2026-07-28 - <https://modelcontextprotocol.io/specification/2026-07-28/client/sampling>
- Model Context Protocol Specification, *Roots (deprecated)*, version 2026-07-28 - <https://modelcontextprotocol.io/specification/2026-07-28/client/roots>
- Model Context Protocol Specification, *Transports*, version 2026-07-28 - <https://modelcontextprotocol.io/specification/2026-07-28/basic/transports>
- Model Context Protocol Documentation, *Security Best Practices* - <https://modelcontextprotocol.io/docs/2026-07-28/tutorials/security/security_best_practices>
- Vercel Documentation, *Deploy MCP servers to Vercel* - <https://vercel.com/docs/mcp/deploy-mcp-servers-to-vercel>
- Vercel Documentation, *Methods to bypass Deployment Protection* - <https://vercel.com/docs/deployment-protection/methods-to-bypass-deployment-protection>
