Skip to main content
The official MCP TypeScript SDK (@modelcontextprotocol/sdk) is the most capable TypeScript option: it can be a full OAuth authorization server with dynamic client registration, or a plain resource server that verifies bearer tokens. Either way it serves Streamable HTTP, so it fits any of MCP Manager’s three authentication modes. This page covers the decisions and gotchas for running it behind MCP Manager — the SDK’s own docs and source are authoritative. It also covers Vercel’s mcp-handler for Next.js at the end.
Start with Building Your Own MCP Server for the cross-framework requirements and the auth-mode decision tree. This page is the TypeScript layer on top.

Serve Streamable HTTP — never SSE-only

Use StreamableHTTPServerTransport (from @modelcontextprotocol/sdk/server/streamableHttp.js). For a stateless deployment behind a load balancer, construct it with sessionIdGenerator: undefined; for stateful sessions, supply a generator (the transport then issues an Mcp-Session-Id). The SDK also ships a legacy SSEServerTransport for the old two-endpoint transport — don’t ship that as your only transport. See the server guide.
Illustrative — see the SDK server guide
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";

// Stateless: no session bound to one instance's memory.
const transport =
	new StreamableHTTPServerTransport({
		sessionIdGenerator: undefined,
	});
A server that only mounts SSEServerTransport (the 2024-11-05 HTTP+SSE transport) will not connect to MCP Manager, which speaks Streamable HTTP only. Streamable HTTP responses themselves may be text/event-stream — that’s supported.

Match the SDK’s auth to an MCP Manager mode

The SDK splits cleanly into authorization-server mode and resource-server mode. Pick the one that matches your chosen MCP Manager mode.
You wantUse in the SDKNotes
Standard OAuth + DCRmcpAuthRouter (mounts the authorization-server endpoints, including /register)/register only appears if your clientsStore.registerClient is implemented
OAuth + DCR proxying an IdPProxyOAuthServerProvider with endpoints.registrationUrl setForwards dynamic registration to your upstream IdP
Pre-registration / tokenmcpAuthMetadataRouter + requireBearerAuth({ verifier, requiredScopes, resourceMetadataUrl })Resource-server only: you verify tokens an external authorization server issued
For the DCR path, the registration endpoint is mounted only when clientsStore.registerClient exists — so dynamic registration is opt-in by implementing it. See the SDK’s src/server/auth/ (router, providers, middleware).
The only client store that ships is the in-memory DemoInMemoryClientsStore — a Map, for examples only. On any multi-instance or serverless deployment you must implement a persistent OAuthRegisteredClientsStore (backed by a database or Redis), and persist authorization codes and tokens too. An in-memory store loses MCP Manager’s registration between the register and authorize hops — the DCR failure in a nutshell.

Get the metadata path right

The SDK serves protected-resource metadata at a path-suffixed well-known URL when your MCP endpoint isn’t at the root — for example /.well-known/oauth-protected-resource/mcp for an endpoint at /mcp. Use the SDK’s getOAuthProtectedResourceMetadataUrl(serverUrl) helper to build it rather than hand-writing the path, and make sure the advertised issuer and resource are your public HTTPS URL, not an internal host. A mismatch here is what makes MCP Manager fall back to manual entry or reject tokens.

Vercel mcp-handler (Next.js)

If you’re shipping an MCP server as Next.js route handlers on Vercel, mcp-handler wraps the SDK with createMcpHandler(...). It is a resource server only — it verifies tokens with withMcpAuth(handler, verifyToken, options) and serves RFC 9728 protected-resource metadata, but it does not implement an authorization server or dynamic client registration. That maps to MCP Manager’s pre-registration or token-in-header modes: an external authorization server (or a static token) handles credentials, and mcp-handler validates them. See mcp-handler authorization docs.
On Vercel/serverless, the SSE response path needs a Redis URL for its pub/sub backing — pure request/response Streamable HTTP works statelessly, but don’t rely on in-process state across invocations.

MCP Manager compatibility checklist

1

Streamable HTTP at a fixed path

Mount StreamableHTTPServerTransport at a stable path (/mcp); don’t ship only SSEServerTransport.
2

Stateless or shared session state

Use sessionIdGenerator: undefined for stateless, or externalize session state — don’t keep it in one instance’s memory.
3

For DCR, implement registerClient + a persistent store

Mount mcpAuthRouter, implement clientsStore.registerClient, and back it (plus codes and tokens) with a database or Redis — not the demo in-memory Map.
4

Public metadata, correct path suffix

Serve oauth-protected-resource (and, for an authorization server, oauth-authorization-server) at your public URL with the right path suffix; advertise the canonical resource.
5

Allow MCP Manager's callback

If you enforce a redirect allowlist, include https://mcp.mcpmanager.ai/api/v1/mcpm/inbound/oauth/callback.

TypeScript gotchas

DemoInMemoryClientsStore is a Map for examples. On more than one instance it loses MCP Manager’s registration between the register and authorize hops. Implement a persistent OAuthRegisteredClientsStore. See Debug Self-Hosted OAuth.
mcpAuthRouter mounts the registration endpoint only when clientsStore.registerClient is defined. If MCP Manager can’t find a registration_endpoint, that’s usually why — implement it or use pre-registration.
For an endpoint at /mcp, the metadata lives at /.well-known/oauth-protected-resource/mcp. Build it with getOAuthProtectedResourceMetadataUrl() rather than hand-rolling, or discovery fails.

Further reading

Debug Self-Hosted OAuth

The dynamic-client-registration failure and the persistent-store fix.

MCP TypeScript SDK

The authoritative repo, including the server guide and auth source.

Vercel mcp-handler

The Next.js resource-server adapter and its authorization docs.

Building Your Own MCP Server

The cross-framework requirements, decision tree, and troubleshooting catalog.