Create a complete Model Context Protocol (MCP) server in TypeScript using the MCP TypeScript SDK v2 with the following specifications:
@modelcontextprotocol/sdk package is retired. Use the focused v2 packages:
@modelcontextprotocol/server — server implementation (stdio transport via the @modelcontextprotocol/server/stdio subpath)@modelcontextprotocol/node — Node HTTP transport (NodeStreamableHTTPServerTransport), or a framework adapter: @modelcontextprotocol/express, @modelcontextprotocol/hono, @modelcontextprotocol/fastify — each adapter requires its peer framework to be installed alongside it (e.g. @modelcontextprotocol/express + express)@modelcontextprotocol/core — shared protocol schemas (import *Schema constants from here, not from sdk/types.js)zod@^4.2 — v2 requires Zod 4.2+; do not use zod@3"type": "module" (a CommonJS build is also shipped, so require() works if needed)npm init and create package.json@modelcontextprotocol/server, zod@^4.2, and the transport package — @modelcontextprotocol/node for plain Node HTTP, or a framework adapter together with its peer framework (e.g. npm install @modelcontextprotocol/express express)"type": "module" in package.jsontsx or ts-node for developmentMcpServer class from @modelcontextprotocol/server for high-level implementationNodeStreamableHTTPServerTransport from @modelcontextprotocol/node
WebStandardStreamableHTTPServerTransport from @modelcontextprotocol/server
StdioServerTransport from @modelcontextprotocol/server/stdio
@modelcontextprotocol/express, etc.) with proper middleware and error handlingHeaders/Request types; read headers with ctx.http?.req?.headers.get('x-custom')
registerTool() with a config object — v1 variadic .tool() signatures are gone:
server.registerTool('greet', {
description: 'Greet user',
inputSchema: z.object({ name: z.string() })
}, async ({ name }, ctx) => {
return { content: [{ type: 'text', text: `Hello, ${name}!` }] };
});
z.object({...})) — raw shape objects ({ name: z.string() }) are deprecatedtitle and description fieldscontent and structuredContent in resultsctx object (replaces v1 extra): ctx.mcpReq.signal, ctx.mcpReq.id, ctx.mcpReq.send(...), ctx.mcpReq.notify(...)
ProtocolError, SdkError, SdkHttpError with .status) instead of v1 McpError/StreamableHTTPError
registerResource() with ResourceTemplate for dynamic URIsregisterPrompt() with argument schemas (same config-object style as registerTool())completable() wrapper order: completable(z.string(), callback).optional() (optional applied outside)input_required pattern)For HTTP Servers:
Content-Type handling: v2 rejects non-application/json POST bodiesFor stdio Servers:
npx @modelcontextprotocol/codemod@latest v1-to-v2 .
@mcp-codemod-error markers for the parts requiring manual judgment (transport choice, header reads, error classification)McpError + ErrorCode checks for the new error classes; HTTP status now lives on error.status, not error.code
Server.createMessage(), listRoots(), sendLoggingMessage() and the roots/sampling/logging capability fields are deprecated in v2 — avoid them in new codenpm start or npx tsx server.ts)npx @modelcontextprotocol/inspector
http://localhost:PORT/mcp
input_required pattern (the v2 replacement for the deprecated sampling subsystem)Generate a complete, production-ready MCP server with comprehensive documentation, type safety, and error handling.