Examples

September 6, 2026 ยท View on GitHub

Three runnable MCP servers built with the toolkit.

FileWhat it shows
basic-auth-server.tsAPI key auth, JWT auth, reading the auth context in a handler
full-middleware-stack.tsAll five packages composed on one server
production-server.tsAuth + rate limit + cache + logging with realistic tools and stats

Prerequisites

Build the workspace first. The examples import the packages by their published names (@mcp-toolkit/auth and friends), which npm workspaces resolve to each package's dist/, so an unbuilt checkout fails at import time:

npm install
npm run build

The examples are run with tsx, which is not a dependency of this repo. npx tsx fetches it on demand:

npx tsx examples/basic-auth-server.ts

examples/ is typechecked by npm run typecheck:examples, which CI runs, so these files stay compilable against the current SDK.

Environment variables

VariableUsed byDefault
MCP_API_KEYall threedev-api-key-12345 (basic, full), prod-key-abc123 (production)
JWT_SECRETbasic-auth-server (jwt mode)super-secret-jwt-key
MCP_ALLOWED_ORIGINSfull-middleware-stackunset, so the origin allowlist is skipped
LOG_LEVELproduction-serverinfo
LOG_FILEproduction-serverunset, so logs go to stderr only

The defaults are development placeholders. Set real values before exposing any of these.

basic-auth-server.ts takes a mode argument: npx tsx examples/basic-auth-server.ts jwt starts the JWT variant instead of the API key one.

Exercising a running server

With the MCP Inspector

npx @modelcontextprotocol/inspector npx tsx examples/production-server.ts

The Inspector lists the tools and calls them interactively. Note that a call it sends carries no credential, so every tool answers with an auth error -- which is itself the useful signal that the middleware is active.

With raw JSON-RPC on stdin

To see auth accept and reject, the credential has to travel somewhere the server can read it. Under stdio that is the request's params._meta:

printf '%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"probe","version":"1.0.0"}}}' \
  '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"greet","arguments":{"name":"Sagar"},"_meta":{"x-api-key":"dev-api-key-12345"}}}' \
  '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"greet","arguments":{"name":"Sagar"}}}' \
  | npx tsx examples/basic-auth-server.ts

Request 2 returns the greeting; request 3 returns Missing API key in "x-api-key" header. On a Streamable HTTP or SSE transport the same credential arrives as a real HTTP header instead.

What these examples do not show

Every example uses StdioServerTransport, so:

  • Logs go to stderr. Writing them to stdout would corrupt the JSON-RPC stream, which is why the logger defaults to stderr.
  • withCors has no Origin to validate. full-middleware-stack.ts applies it only when MCP_ALLOWED_ORIGINS is set, because an allowlist with no origin present rejects every call by design.

See the root README for the full list of limitations.