Community-maintained FDE reference. Not an official Vercel or Anthropic project. About this project
Examples
The runnable code lives in the top-level examples (in the repository)
directory: thirteen standalone TypeScript packages, one per directory, each
with its own quick-start README.md. This page is the narrative index. Use it
to pick the right example for what you are trying to learn; use the
per-example README to get it running. Every example is a deployable Vercel
unit and an offline-testable protocol demonstration at the same time, and the
tension between those two identities is most of what they teach.
Stack and wire versions (read this first). The examples build on the v2 packages:
mcp-handler2.1.1 with@modelcontextprotocol/server2.0.0 (and@modelcontextprotocol/client2.0.0 in tests), onzod4.2.0 or newer, which SDK v2 requires. The docs on this site describe the published 2026-07-28 spec revision as normative. Wire status: the pinned stack (mcp-handler2.1.1 on@modelcontextprotocol/server2.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 SDKClientdefaults to that legacy handshake unless you opt in to modern version negotiation, so the examples’ in-memory test suites exercise only the legacy path. Concretely: a deployed example answersserver/discover, tags results withresultType, and carriesttlMs/cacheScopeon list results for any client that sends the 2026-07-28 headers (the message trace has thecurl), while the vitest suites, and a default SDKClient, still open with the legacyinitializehandshake and see none of those fields. The decision behind this split is the repository’s ADR 0005 (docs describe the published revision as normative, examples adopt the v2 packages, and wire claims carry this shared status sentence), whose 2026-08-26 status note records the verified wire behavior above; the full record isplanning/decisions/0005-v2-migration-split.mdin the repository.
What every example shares
- The house split. Protocol logic lives in
src/behind an exportedconfigureServer(server); the Next.js route atapp/api/mcp/route.tsis a thin shell:withOriginCheck(createMcpHandler(configureServer, { serverInfo }), allowlist), wherewithOriginCheckcomes fromsrc/origin.ts(the Streamable HTTP Origin allowlist, driven byMCP_ALLOWED_ORIGINS, copied byte for byte into every example) andauth-serverandsecure-tools-serveraddwithMcpAuthinside it. Tests importsrc/and never touch the framework. - A
vercel.jsonwith an explicitmaxDurationon the route, so “deployable unit” is a fact you canvercel deploy, not a caption, and a runaway invocation is bounded by the platform; each package’stests/vercel-config.test.tsfails if the entry disappears. - Offline tests. vitest drives a real client over
InMemoryTransport.createLinkedPair(): no network, no Vercel account, no deployed infrastructure. See testing for the idiom. - Verified error semantics. Against SDK v2 (
2.0.0, the pin chosen in ADR 0005,planning/decisions/0005-v2-migration-split.mdin the repository), an unknown tool name is rejected with a JSON-RPC protocol error, matching the spec, while schema-invalid arguments on a known tool still surface as anisError: truetool result. That is a behavior change from the v1 stack, which returnedisErrorresults for both. Tests assert both shapes. - The negatives are asserted. Validation rejects, authorization denies, unknown handles throw, redaction removes, consent gates block. A control you do not assert against is a control you do not have.
- Status: learning code, not production. Each README says what a real deployment would do differently.
Start here
-
Build-it-yourself prompts - copy one prompt into your AI coding agent and rebuild any example locally, exact pins and tests included.
-
examples/minimal-server(in the repository) - the smallest end-to-end server: oneechotool over Streamable HTTP, exercising lifecycle, discovery, and invocation. The 10-minute path in getting started and the structural template every other example copies. -
examples/secure-tools-server(in the repository) - the house-style showcase: Zod input validation as the schema surface, default-deny authorization keyed off the verified token (withMcpAuthplusprincipalFromAuthInfo, never a tool argument), honest tool annotations, output minimization. When you build your own server, copy this one, not minimal-server. -
examples/resources-server(in the repository) - resources and resource templates: what application-controlled context looks like next to model-controlled tools.
Patterns in code
Each of these lands in the same PR as its pattern page and links back to it.
examples/db-adapter-server(in the repository) - the adapter pattern over an untouched read-only backend: parameterized queries, a scoped read-only credential, output sanitization (an internal column dropped, control characters escaped), and schema-expressed bounds that round-trip into the advertisedinputSchema.examples/facade-server(in the repository) - the facade pattern: one namespaced surface over two in-process backends, exception containment at aBackendErrorboundary, and an audit log that records backend and scope but never keys or results.examples/query-command-server(in the repository) - query vs command: tool annotations (readOnlyHint,destructiveHint,idempotentHint) carrying the read/write split, plus an idempotency-key store with first-write-wins replay.examples/async-jobs-server(in the repository) - async jobs: opaque CSPRNG handles, progress notifications, cooperative cancellation, idempotent result fetch. Itsvercel.jsonsketches the Vercel Queues consumer (Queues is in public beta) that the deployed shape would use;maxDurationis why the pattern exists on Vercel at all.examples/least-privilege-server(in the repository) - least privilege: declared per-tool scope requirements, startup config validation that rejects both missing and excess grants, a registration drift guard, and per-principal tool visibility plus call-time authorization, both keyed off the verified token (principalFromAuthInfo(ctx.http.authInfo), never an argument); see where the principal comes from.examples/sandbox-isolation-server(in the repository) - the sidecar pattern’s Vercel shape: a tool that runs untrusted work inside a Vercel Sandbox with a deny-by-default egressnetworkPolicyallowlist,persistent: false, a pinned image, and noenvpassed in; the output comes back capped and framed as untrusted data. Tests stub the Sandbox client and assert the exactSandbox.createoptions.
Security and identity
examples/auth-server(in the repository) - authorization in practice:withMcpAuthandverifyToken, the RFC 9728 protected-resource metadata handler at/.well-known/oauth-protected-resource, scope-gated tools, and the 401 versus 403 semantics. Tests drive the token and authorization paths with stub tokens; no live identity provider.
Server-initiated features
Both are driven in tests by registering the client-side capability handler on
the in-memory client, since on the legacy handshake the in-memory suites
speak, the server initiates the exchange. Under the 2026-07-28 contract, which
the deployed handler serves to modern clients, these flows become multi
round-trip requests instead: the server returns an input_required result
and the client retries with the answers (the v2 client answers those through
the same registered handlers). The
sampling and
elicitation pages cover the new shape.
examples/sampling-server(in the repository) - a tool that issues sampling (sampling/createMessage) back to the client mid-call; the test client returns a canned completion and the assertions inspect the server’s outbound request. Sampling is deprecated in 2026-07-28 (SEP-2577); the suggested migration is calling the LLM provider directly (on Vercel: the AI SDK or AI Gateway). The example stays through the deprecation window, with the banner in its README.examples/elicitation-server(in the repository) - mid-tool elicitation with a flat, primitives-only schema, handling accept, decline, and cancel distinctly. Accept withapproved: falseis an explicit no, and the tests prove the server treats it as one.
The client side
examples/orchestrator-host(in the repository) - the one client-side example, paired with the orchestrator pattern: a host connecting to two of the other servers, one session each, aggregating tools under<server>.<tool>names (bare names absent), with a fail-closed consent gate proven to block before dispatch and serverisErrorresults surfaced as typed errors, never as success.
Status of this page
status: draft is deliberate. The per-example READMEs are complete and
canonical for running the code; this index grows into longer-form
walkthroughs (annotated traces, what to observe run by run) as the site
matures. The code does not wait for the prose.
Where to look now
- Testing - the in-memory client idiom every example’s tests are built on, and the determinism rules they follow.
- Getting started - the 10-minute path from
clone to a deployed
minimal-server. - Patterns - the design intent behind the pattern-paired examples.
- Security checklist - the controls the security-focused examples assert, item by item.
Bibliography
- Model Context Protocol Specification, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28
- Model Context Protocol Specification, Changelog, version 2026-07-28 - https://modelcontextprotocol.io/specification/2026-07-28/changelog
- Model Context Protocol, Deprecated features registry - https://modelcontextprotocol.io/specification/2026-07-28/deprecated
- Vercel Documentation, Deploy MCP servers to Vercel - https://vercel.com/docs/mcp/deploy-mcp-servers-to-vercel
- mcp-handler (Vercel) - https://github.com/vercel/mcp-handler
- RFC 9728, OAuth 2.0 Protected Resource Metadata - https://www.rfc-editor.org/rfc/rfc9728