/** * Type-checked examples for docs/server.md. * * Regions are synced into markdown code fences via `pnpm sync:snippets`. * Each function wraps a single region. The function name matches the region name. * * @module */ //#region imports import { randomUUID } from 'node:crypto'; import { createMcpExpressApp } from '@modelcontextprotocol/express'; import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node'; import type { CallToolResult, ResourceLink } from '@modelcontextprotocol/server'; import { completable, McpServer, ResourceTemplate, TRACEPARENT_META_KEY } from '@modelcontextprotocol/server'; import { StdioServerTransport } from '@modelcontextprotocol/server/stdio'; import * as z from 'zod/v4'; //#endregion imports // --------------------------------------------------------------------------- // Server instructions // --------------------------------------------------------------------------- /** Example: McpServer with instructions for LLM guidance. */ function instructions_basic() { //#region instructions_basic const server = new McpServer( { name: 'db-server', version: '1.0.0' }, { instructions: 'Always call list_tables before running queries. Use validate_schema before migrate_schema for safe migrations. Results are limited to 1000 rows.' } ); //#endregion instructions_basic return server; } // --------------------------------------------------------------------------- // Tools, resources, and prompts // --------------------------------------------------------------------------- /** Example: Registering a tool with inputSchema, outputSchema, and structuredContent. */ function registerTool_basic(server: McpServer) { //#region registerTool_basic server.registerTool( 'calculate-bmi', { title: 'BMI Calculator', description: 'Calculate Body Mass Index', inputSchema: z.object({ weightKg: z.number(), heightM: z.number() }), outputSchema: z.object({ bmi: z.number() }) }, async ({ weightKg, heightM }) => { const output = { bmi: weightKg / (heightM * heightM) }; return { content: [{ type: 'text', text: JSON.stringify(output) }], structuredContent: output }; } ); //#endregion registerTool_basic } /** Example: Tool returning resource_link content items. */ function registerTool_resourceLink(server: McpServer) { //#region registerTool_resourceLink server.registerTool( 'list-files', { title: 'List Files', description: 'Returns files as resource links without embedding content' }, async (): Promise => { const links: ResourceLink[] = [ { type: 'resource_link', uri: 'file:///projects/readme.md', name: 'README', mimeType: 'text/markdown' }, { type: 'resource_link', uri: 'file:///projects/config.json', name: 'Config', mimeType: 'application/json' } ]; return { content: links }; } ); //#endregion registerTool_resourceLink } /** Example: Tool with explicit error handling using isError. */ function registerTool_errorHandling(server: McpServer) { //#region registerTool_errorHandling server.registerTool( 'fetch-data', { description: 'Fetch data from a URL', inputSchema: z.object({ url: z.string() }) }, async ({ url }): Promise => { try { const res = await fetch(url); if (!res.ok) { return { content: [{ type: 'text', text: `HTTP ${res.status}: ${res.statusText}` }], isError: true }; } const text = await res.text(); return { content: [{ type: 'text', text }] }; } catch (error) { return { content: [{ type: 'text', text: `Failed: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); //#endregion registerTool_errorHandling } /** Example: Tool with annotations hinting at behavior. */ function registerTool_annotations(server: McpServer) { //#region registerTool_annotations server.registerTool( 'delete-file', { description: 'Delete a file from the project', inputSchema: z.object({ path: z.string() }), annotations: { title: 'Delete File', destructiveHint: true, idempotentHint: true } }, async ({ path }): Promise => { // ... perform deletion ... return { content: [{ type: 'text', text: `Deleted ${path}` }] }; } ); //#endregion registerTool_annotations } /** Example: Advertising icons a client can render in its UI for a tool. */ function registerTool_icons(server: McpServer) { //#region registerTool_icons server.registerTool( 'generate-chart', { title: 'Generate Chart', description: 'Render a chart from a series of numbers', inputSchema: z.object({ data: z.array(z.number()) }), // Icons a client may render in its UI. `src` is required; `mimeType`, // `sizes`, and `theme` ('light' | 'dark') are optional hints. icons: [ { src: 'https://example.com/icons/chart.svg', mimeType: 'image/svg+xml', sizes: ['any'] }, { src: 'https://example.com/icons/chart-48.png', mimeType: 'image/png', sizes: ['48x48'], theme: 'light' } ] }, async ({ data }): Promise => { // ... render chart ... return { content: [{ type: 'text', text: `Charted ${data.length} points` }] }; } ); //#endregion registerTool_icons } /** Example: Registering a static resource at a fixed URI. */ function registerResource_static(server: McpServer) { //#region registerResource_static server.registerResource( 'config', 'config://app', { title: 'Application Config', description: 'Application configuration data', mimeType: 'text/plain' }, async uri => ({ contents: [{ uri: uri.href, text: 'App configuration here' }] }) ); //#endregion registerResource_static } /** Example: Dynamic resource with ResourceTemplate and listing. */ function registerResource_template(server: McpServer) { //#region registerResource_template server.registerResource( 'user-profile', new ResourceTemplate('user://{userId}/profile', { list: async () => ({ resources: [ { uri: 'user://123/profile', name: 'Alice' }, { uri: 'user://456/profile', name: 'Bob' } ] }) }), { title: 'User Profile', description: 'User profile data', mimeType: 'application/json' }, async (uri, { userId }) => ({ contents: [ { uri: uri.href, text: JSON.stringify({ userId, name: 'Example User' }) } ] }) ); //#endregion registerResource_template } /** Example: Registering a prompt with argsSchema. */ function registerPrompt_basic(server: McpServer) { //#region registerPrompt_basic server.registerPrompt( 'review-code', { title: 'Code Review', description: 'Review code for best practices and potential issues', argsSchema: z.object({ code: z.string() }) }, ({ code }) => ({ messages: [ { role: 'user' as const, content: { type: 'text' as const, text: `Please review this code:\n\n${code}` } } ] }) ); //#endregion registerPrompt_basic } /** Example: Prompt with completable argsSchema for autocompletion. */ function registerPrompt_completion(server: McpServer) { //#region registerPrompt_completion server.registerPrompt( 'review-code', { title: 'Code Review', description: 'Review code for best practices', argsSchema: z.object({ language: completable(z.string().describe('Programming language'), value => ['typescript', 'javascript', 'python', 'rust', 'go'].filter(lang => lang.startsWith(value)) ) }) }, ({ language }) => ({ messages: [ { role: 'user' as const, content: { type: 'text' as const, text: `Review this ${language} code for best practices.` } } ] }) ); //#endregion registerPrompt_completion } // --------------------------------------------------------------------------- // Logging // --------------------------------------------------------------------------- /** Example: Server with logging capability + tool that logs progress messages. */ function registerTool_logging() { //#region logging_capability const server = new McpServer({ name: 'my-server', version: '1.0.0' }, { capabilities: { logging: {} } }); //#endregion logging_capability //#region registerTool_logging server.registerTool( 'fetch-data', { description: 'Fetch data from an API', inputSchema: z.object({ url: z.string() }) }, async ({ url }, ctx): Promise => { await ctx.mcpReq.log('info', `Fetching ${url}`); const res = await fetch(url); await ctx.mcpReq.log('debug', `Response status: ${res.status}`); const text = await res.text(); return { content: [{ type: 'text', text }] }; } ); //#endregion registerTool_logging return server; } // --------------------------------------------------------------------------- // Progress // --------------------------------------------------------------------------- /** Example: Tool that sends progress notifications during a long-running operation. */ function registerTool_progress(server: McpServer) { //#region registerTool_progress server.registerTool( 'process-files', { description: 'Process files with progress updates', inputSchema: z.object({ files: z.array(z.string()) }) }, async ({ files }, ctx): Promise => { const progressToken = ctx.mcpReq._meta?.progressToken; for (let i = 0; i < files.length; i++) { // ... process files[i] ... if (progressToken !== undefined) { await ctx.mcpReq.notify({ method: 'notifications/progress', params: { progressToken, progress: i + 1, total: files.length, message: `Processed ${files[i]}` } }); } } return { content: [{ type: 'text', text: `Processed ${files.length} files` }] }; } ); //#endregion registerTool_progress } /** Example: Tool that reads W3C Trace Context from request `_meta`. */ function registerTool_traceContext(server: McpServer) { //#region registerTool_traceContext server.registerTool( 'traced-operation', { description: 'Operation that participates in distributed tracing', inputSchema: z.object({ query: z.string() }) }, async ({ query }, ctx): Promise => { // e.g. '00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01' const traceparent = ctx.mcpReq._meta?.[TRACEPARENT_META_KEY]; if (typeof traceparent === 'string') { // Continue the caller's trace, e.g. start a child span with your // OpenTelemetry tracer using this trace context. } return { content: [{ type: 'text', text: `Results for ${query}` }] }; } ); //#endregion registerTool_traceContext } // --------------------------------------------------------------------------- // Server-initiated requests // --------------------------------------------------------------------------- /** Example: Tool that uses sampling to request an LLM completion from the client. */ function registerTool_sampling(server: McpServer) { //#region registerTool_sampling server.registerTool( 'summarize', { description: 'Summarize text using the client LLM', inputSchema: z.object({ text: z.string() }) }, async ({ text }, ctx): Promise => { const response = await ctx.mcpReq.requestSampling({ messages: [ { role: 'user', content: { type: 'text', text: `Please summarize:\n\n${text}` } } ], maxTokens: 500 }); return { content: [ { type: 'text', text: `Model (${response.model}): ${JSON.stringify(response.content)}` } ] }; } ); //#endregion registerTool_sampling } /** Example: Tool that uses form elicitation to collect user input. */ function registerTool_elicitation(server: McpServer) { //#region registerTool_elicitation server.registerTool( 'collect-feedback', { description: 'Collect user feedback via a form', inputSchema: z.object({}) }, async (_args, ctx): Promise => { const result = await ctx.mcpReq.elicitInput({ mode: 'form', message: 'Please share your feedback:', requestedSchema: { type: 'object', properties: { rating: { type: 'number', title: 'Rating (1\u20135)', minimum: 1, maximum: 5 }, comment: { type: 'string', title: 'Comment' } }, required: ['rating'] } }); if (result.action === 'accept') { return { content: [ { type: 'text', text: `Thanks! ${JSON.stringify(result.content)}` } ] }; } return { content: [{ type: 'text', text: 'Feedback declined.' }] }; } ); //#endregion registerTool_elicitation } /** Example: Tool that requests the client's filesystem roots. */ function registerTool_roots(server: McpServer) { //#region registerTool_roots server.registerTool( 'list-workspace-files', { description: 'List files across all workspace roots', inputSchema: z.object({}) }, async (_args, _ctx): Promise => { const { roots } = await server.server.listRoots(); const summary = roots.map(r => `${r.name ?? r.uri}: ${r.uri}`).join('\n'); return { content: [{ type: 'text', text: summary }] }; } ); //#endregion registerTool_roots } // --------------------------------------------------------------------------- // Transports // --------------------------------------------------------------------------- /** Example: Stateful Streamable HTTP transport with session management. */ async function streamableHttp_stateful() { //#region streamableHttp_stateful const server = new McpServer({ name: 'my-server', version: '1.0.0' }); const transport = new NodeStreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID() }); await server.connect(transport); //#endregion streamableHttp_stateful } /** Example: Stateless Streamable HTTP transport (no session persistence). */ async function streamableHttp_stateless() { //#region streamableHttp_stateless const server = new McpServer({ name: 'my-server', version: '1.0.0' }); const transport = new NodeStreamableHTTPServerTransport({ sessionIdGenerator: undefined }); await server.connect(transport); //#endregion streamableHttp_stateless } /** Example: Streamable HTTP with JSON response mode (no SSE). */ async function streamableHttp_jsonResponse() { //#region streamableHttp_jsonResponse const server = new McpServer({ name: 'my-server', version: '1.0.0' }); const transport = new NodeStreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID(), enableJsonResponse: true }); await server.connect(transport); //#endregion streamableHttp_jsonResponse } /** Example: stdio transport for local process-spawned integrations. */ async function stdio_basic() { //#region stdio_basic const server = new McpServer({ name: 'my-server', version: '1.0.0' }); const transport = new StdioServerTransport(); await server.connect(transport); //#endregion stdio_basic } // --------------------------------------------------------------------------- // Shutdown // --------------------------------------------------------------------------- /** Example: Graceful shutdown for a stateful multi-session HTTP server. */ function shutdown_statefulHttp(app: ReturnType, transports: Map) { //#region shutdown_statefulHttp // Capture the http.Server so it can be closed on shutdown const httpServer = app.listen(3000); process.on('SIGINT', async () => { httpServer.close(); for (const [sessionId, transport] of transports) { await transport.close(); transports.delete(sessionId); } process.exit(0); }); //#endregion shutdown_statefulHttp } /** Example: Graceful shutdown for a stdio server. */ function shutdown_stdio(server: McpServer) { //#region shutdown_stdio process.on('SIGINT', async () => { await server.close(); process.exit(0); }); //#endregion shutdown_stdio } // --------------------------------------------------------------------------- // DNS rebinding protection // --------------------------------------------------------------------------- /** Example: createMcpExpressApp with different host bindings. */ function dnsRebinding_basic() { //#region dnsRebinding_basic // Default: DNS rebinding protection auto-enabled (host is 127.0.0.1) const app = createMcpExpressApp(); // DNS rebinding protection also auto-enabled for localhost const appLocal = createMcpExpressApp({ host: 'localhost' }); // No automatic protection when binding to all interfaces const appOpen = createMcpExpressApp({ host: '0.0.0.0' }); //#endregion dnsRebinding_basic return { app, appLocal, appOpen }; } /** Example: createMcpExpressApp with allowedHosts for non-localhost binding. */ function dnsRebinding_allowedHosts() { //#region dnsRebinding_allowedHosts const app = createMcpExpressApp({ host: '0.0.0.0', allowedHosts: ['localhost', '127.0.0.1', 'myhost.local'] }); //#endregion dnsRebinding_allowedHosts return app; } // Suppress unused-function warnings (functions exist solely for type-checking) void instructions_basic; void registerTool_basic; void registerTool_resourceLink; void registerTool_errorHandling; void registerTool_annotations; void registerTool_icons; void registerTool_logging; void registerTool_progress; void registerTool_traceContext; void registerTool_sampling; void registerTool_elicitation; void registerTool_roots; void registerResource_static; void registerResource_template; void registerPrompt_basic; void registerPrompt_completion; void streamableHttp_stateful; void streamableHttp_stateless; void streamableHttp_jsonResponse; void stdio_basic; void shutdown_statefulHttp; void shutdown_stdio; void dnsRebinding_basic; void dnsRebinding_allowedHosts;