Add JSDoc @example tags with companion .examples.ts files (#1524)

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jonathan Hefner 2026-02-13 11:42:40 -06:00 • committed by GitHub
commit c9ac842309
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 511 additions and 45 deletions

View file

@ -0,0 +1,56 @@
/**
* Type-checked examples for `streamableHttp.ts`.
*
* These examples are synced into JSDoc comments via the sync-snippets script.
* Each function's region markers define the code snippet that appears in the docs.
*
* @module
*/
import { randomUUID } from 'node:crypto';
import type { IncomingMessage, ServerResponse } from 'node:http';
import { McpServer } from '@modelcontextprotocol/server';
import { NodeStreamableHTTPServerTransport } from './streamableHttp.js';
/**
* Example: Stateful Streamable HTTP transport (Node.js).
*/
async function NodeStreamableHTTPServerTransport_stateful() {
//#region NodeStreamableHTTPServerTransport_stateful
const server = new McpServer({ name: 'my-server', version: '1.0.0' });
const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: () => randomUUID()
});
await server.connect(transport);
//#endregion NodeStreamableHTTPServerTransport_stateful
}
/**
* Example: Stateless Streamable HTTP transport (Node.js).
*/
async function NodeStreamableHTTPServerTransport_stateless() {
//#region NodeStreamableHTTPServerTransport_stateless
const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined
});
//#endregion NodeStreamableHTTPServerTransport_stateless
return transport;
}
// Stubs for Express-style app
declare const app: { post(path: string, handler: (req: IncomingMessage & { body?: unknown }, res: ServerResponse) => void): void };
/**
* Example: Using with a pre-parsed request body (e.g. Express).
*/
function NodeStreamableHTTPServerTransport_express(transport: NodeStreamableHTTPServerTransport) {
//#region NodeStreamableHTTPServerTransport_express
app.post('/mcp', (req, res) => {
transport.handleRequest(req, res, req.body);
});
//#endregion NodeStreamableHTTPServerTransport_express
}

View file

@ -28,25 +28,6 @@ export type StreamableHTTPServerTransportOptions = WebStandardStreamableHTTPServ
* This is a wrapper around {@linkcode WebStandardStreamableHTTPServerTransport} that provides Node.js HTTP compatibility.
* It uses the `@hono/node-server` library to convert between Node.js HTTP and Web Standard APIs.
*
* Usage example:
*
* ```typescript
* // Stateful mode - server sets the session ID
* const statefulTransport = new StreamableHTTPServerTransport({
* sessionIdGenerator: () => randomUUID(),
* });
*
* // Stateless mode - explicitly set session ID to undefined
* const statelessTransport = new StreamableHTTPServerTransport({
* sessionIdGenerator: undefined,
* });
*
* // Using with pre-parsed request body
* app.post('/mcp', (req, res) => {
* transport.handleRequest(req, res, req.body);
* });
* ```
*
* In stateful mode:
* - Session ID is generated and included in response headers
* - Session ID is always included in initialization responses
@ -57,6 +38,31 @@ export type StreamableHTTPServerTransportOptions = WebStandardStreamableHTTPServ
* In stateless mode:
* - No Session ID is included in any responses
* - No session validation is performed
*
* @example Stateful setup
* ```ts source="./streamableHttp.examples.ts#NodeStreamableHTTPServerTransport_stateful"
* const server = new McpServer({ name: 'my-server', version: '1.0.0' });
*
* const transport = new NodeStreamableHTTPServerTransport({
* sessionIdGenerator: () => randomUUID()
* });
*
* await server.connect(transport);
* ```
*
* @example Stateless setup
* ```ts source="./streamableHttp.examples.ts#NodeStreamableHTTPServerTransport_stateless"
* const transport = new NodeStreamableHTTPServerTransport({
* sessionIdGenerator: undefined
* });
* ```
*
* @example Using with a pre-parsed request body (e.g. Express)
* ```ts source="./streamableHttp.examples.ts#NodeStreamableHTTPServerTransport_express"
* app.post('/mcp', (req, res) => {
* transport.handleRequest(req, res, req.body);
* });
* ```
*/
export class NodeStreamableHTTPServerTransport implements Transport {
private _webStandardTransport: WebStandardStreamableHTTPServerTransport;

View file

@ -0,0 +1,46 @@
/**
* Type-checked examples for `completable.ts`.
*
* These examples are synced into JSDoc comments via the sync-snippets script.
* Each function's region markers define the code snippet that appears in the docs.
*
* @module
*/
import * as z from 'zod/v4';
import { completable } from './completable.js';
import { McpServer } from './mcp.js';
/**
* Example: Using completable() in a prompt registration.
*/
function completable_basicUsage() {
const server = new McpServer({ name: 'my-server', version: '1.0.0' });
//#region completable_basicUsage
server.registerPrompt(
'review-code',
{
title: 'Code Review',
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.`
}
}
]
})
);
//#endregion completable_basicUsage
return server;
}

View file

@ -21,6 +21,32 @@ export type CompletableSchema<T extends AnySchema> = T & {
/**
* Wraps a Zod type to provide autocompletion capabilities. Useful for, e.g., prompt arguments in MCP.
*
* @example
* ```ts source="./completable.examples.ts#completable_basicUsage"
* server.registerPrompt(
* 'review-code',
* {
* title: 'Code Review',
* 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.`
* }
* }
* ]
* })
* );
* ```
*
* @see {@linkcode server/mcp.McpServer.registerPrompt | McpServer.registerPrompt} for using completable schemas in prompt argument definitions
*/
export function completable<T extends AnySchema>(schema: T, complete: CompleteCallback<T>): CompletableSchema<T> {

View file

@ -0,0 +1,145 @@
/**
* Type-checked examples for `mcp.ts`.
*
* These examples are synced into JSDoc comments via the sync-snippets script.
* Each function's region markers define the code snippet that appears in the docs.
*
* @module
*/
import type { CallToolResult } from '@modelcontextprotocol/core';
import * as z from 'zod/v4';
import { McpServer } from './mcp.js';
import { StdioServerTransport } from './stdio.js';
/**
* Example: Creating a new McpServer.
*/
function McpServer_basicUsage() {
//#region McpServer_basicUsage
const server = new McpServer({
name: 'my-server',
version: '1.0.0'
});
//#endregion McpServer_basicUsage
return server;
}
/**
* Example: Registering a tool with inputSchema and outputSchema.
*/
function McpServer_registerTool_basic(server: McpServer) {
//#region McpServer_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 McpServer_registerTool_basic
}
/**
* Example: Registering a static resource at a fixed URI.
*/
function McpServer_registerResource_static(server: McpServer) {
//#region McpServer_registerResource_static
server.registerResource(
'config',
'config://app',
{
title: 'Application Config',
mimeType: 'text/plain'
},
async uri => ({
contents: [{ uri: uri.href, text: 'App configuration here' }]
})
);
//#endregion McpServer_registerResource_static
}
/**
* Example: Registering a prompt with an argument schema.
*/
function McpServer_registerPrompt_basic(server: McpServer) {
//#region McpServer_registerPrompt_basic
server.registerPrompt(
'review-code',
{
title: 'Code Review',
description: 'Review code for best practices',
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 McpServer_registerPrompt_basic
}
/**
* Example: Connecting an McpServer to a stdio transport.
*/
async function McpServer_connect_stdio() {
//#region McpServer_connect_stdio
const server = new McpServer({ name: 'my-server', version: '1.0.0' });
const transport = new StdioServerTransport();
await server.connect(transport);
//#endregion McpServer_connect_stdio
}
/**
* Example: Sending a log message to the client.
*/
async function McpServer_sendLoggingMessage_basic(server: McpServer) {
//#region McpServer_sendLoggingMessage_basic
await server.sendLoggingMessage({
level: 'info',
data: 'Processing complete'
});
//#endregion McpServer_sendLoggingMessage_basic
}
/**
* Example: Logging from inside a tool handler via ctx.mcpReq.log().
*/
function McpServer_registerTool_logging(server: McpServer) {
//#region McpServer_registerTool_logging
server.registerTool(
'fetch-data',
{
description: 'Fetch data from an API',
inputSchema: z.object({ url: z.string() })
},
async ({ url }, ctx): Promise<CallToolResult> => {
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 McpServer_registerTool_logging
}

View file

@ -54,6 +54,14 @@ import { Server } from './server.js';
* High-level MCP server that provides a simpler API for working with resources, tools, and prompts.
* For advanced usage (like sending notifications or setting custom request handlers), use the underlying
* {@linkcode Server} instance available via the {@linkcode McpServer.server | server} property.
*
* @example
* ```ts source="./mcp.examples.ts#McpServer_basicUsage"
* const server = new McpServer({
* name: 'my-server',
* version: '1.0.0'
* });
* ```
*/
export class McpServer {
/**
@ -93,6 +101,13 @@ export class McpServer {
* Attaches to the given transport, starts it, and starts listening for messages.
*
* The `server` object assumes ownership of the {@linkcode Transport}, replacing any callbacks that have already been set, and expects that it is the only user of the {@linkcode Transport} instance going forward.
*
* @example
* ```ts source="./mcp.examples.ts#McpServer_connect_stdio"
* const server = new McpServer({ name: 'my-server', version: '1.0.0' });
* const transport = new StdioServerTransport();
* await server.connect(transport);
* ```
*/
async connect(transport: Transport): Promise<void> {
return await this.server.connect(transport);
@ -549,6 +564,21 @@ export class McpServer {
/**
* Registers a resource with a config object and callback.
* For static resources, use a URI string. For dynamic resources, use a {@linkcode ResourceTemplate}.
*
* @example
* ```ts source="./mcp.examples.ts#McpServer_registerResource_static"
* server.registerResource(
* 'config',
* 'config://app',
* {
* title: 'Application Config',
* mimeType: 'text/plain'
* },
* async uri => ({
* contents: [{ uri: uri.href, text: 'App configuration here' }]
* })
* );
* ```
*/
registerResource(name: string, uriOrTemplate: string, config: ResourceMetadata, readCallback: ReadResourceCallback): RegisteredResource;
registerResource(
@ -812,6 +842,29 @@ export class McpServer {
/**
* Registers a tool with a config object and callback.
*
* @example
* ```ts source="./mcp.examples.ts#McpServer_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
* };
* }
* );
* ```
*/
registerTool<OutputArgs extends AnySchema, InputArgs extends AnySchema | undefined = undefined>(
name: string,
@ -846,6 +899,29 @@ export class McpServer {
/**
* Registers a prompt with a config object and callback.
*
* @example
* ```ts source="./mcp.examples.ts#McpServer_registerPrompt_basic"
* server.registerPrompt(
* 'review-code',
* {
* title: 'Code Review',
* description: 'Review code for best practices',
* 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}`
* }
* }
* ]
* })
* );
* ```
*/
registerPrompt<Args extends AnySchema>(
name: string,
@ -890,6 +966,14 @@ export class McpServer {
* @see {@linkcode LoggingMessageNotification}
* @param params
* @param sessionId Optional for stateless transports and backward compatibility.
*
* @example
* ```ts source="./mcp.examples.ts#McpServer_sendLoggingMessage_basic"
* await server.sendLoggingMessage({
* level: 'info',
* data: 'Processing complete'
* });
* ```
*/
async sendLoggingMessage(params: LoggingMessageNotification['params'], sessionId?: string) {
return this.server.sendLoggingMessage(params, sessionId);

View file

@ -0,0 +1,22 @@
/**
* Type-checked examples for `stdio.ts`.
*
* These examples are synced into JSDoc comments via the sync-snippets script.
* Each function's region markers define the code snippet that appears in the docs.
*
* @module
*/
import { McpServer } from './mcp.js';
import { StdioServerTransport } from './stdio.js';
/**
* Example: Basic stdio transport usage.
*/
async function StdioServerTransport_basicUsage() {
//#region StdioServerTransport_basicUsage
const server = new McpServer({ name: 'my-server', version: '1.0.0' });
const transport = new StdioServerTransport();
await server.connect(transport);
//#endregion StdioServerTransport_basicUsage
}

View file

@ -8,6 +8,13 @@ import { process } from '@modelcontextprotocol/server/_shims';
* Server transport for stdio: this communicates with an MCP client by reading from the current process' `stdin` and writing to `stdout`.
*
* This transport is only available in Node.js environments.
*
* @example
* ```ts source="./stdio.examples.ts#StdioServerTransport_basicUsage"
* const server = new McpServer({ name: 'my-server', version: '1.0.0' });
* const transport = new StdioServerTransport();
* await server.connect(transport);
* ```
*/
export class StdioServerTransport implements Transport {
private _readBuffer: ReadBuffer = new ReadBuffer();

View file

@ -0,0 +1,66 @@
/**
* Type-checked examples for `streamableHttp.ts`.
*
* These examples are synced into JSDoc comments via the sync-snippets script.
* Each function's region markers define the code snippet that appears in the docs.
*
* @module
*/
import { McpServer } from './mcp.js';
import { WebStandardStreamableHTTPServerTransport } from './streamableHttp.js';
/**
* Example: Stateful Streamable HTTP transport (Web Standard).
*/
async function WebStandardStreamableHTTPServerTransport_stateful() {
//#region WebStandardStreamableHTTPServerTransport_stateful
const server = new McpServer({ name: 'my-server', version: '1.0.0' });
const transport = new WebStandardStreamableHTTPServerTransport({
sessionIdGenerator: () => crypto.randomUUID()
});
await server.connect(transport);
//#endregion WebStandardStreamableHTTPServerTransport_stateful
}
/**
* Example: Stateless Streamable HTTP transport (Web Standard).
*/
async function WebStandardStreamableHTTPServerTransport_stateless() {
//#region WebStandardStreamableHTTPServerTransport_stateless
const transport = new WebStandardStreamableHTTPServerTransport({
sessionIdGenerator: undefined
});
//#endregion WebStandardStreamableHTTPServerTransport_stateless
return transport;
}
// Stubs for framework-specific examples
declare const app: { all(path: string, handler: (c: { req: { raw: Request } }) => Promise<Response>): void };
/**
* Example: Using with Hono.js.
*/
function WebStandardStreamableHTTPServerTransport_hono(transport: WebStandardStreamableHTTPServerTransport) {
//#region WebStandardStreamableHTTPServerTransport_hono
app.all('/mcp', async c => {
return transport.handleRequest(c.req.raw);
});
//#endregion WebStandardStreamableHTTPServerTransport_hono
}
/**
* Example: Using with Cloudflare Workers.
*/
function WebStandardStreamableHTTPServerTransport_workers(transport: WebStandardStreamableHTTPServerTransport) {
//#region WebStandardStreamableHTTPServerTransport_workers
const worker = {
async fetch(request: Request): Promise<Response> {
return transport.handleRequest(request);
}
};
//#endregion WebStandardStreamableHTTPServerTransport_workers
return worker;
}

View file

@ -176,32 +176,6 @@ export interface HandleRequestOptions {
*
* This transport works on any runtime that supports Web Standards: Node.js 18+, Cloudflare Workers, Deno, Bun, etc.
*
* Usage example:
*
* ```typescript
* // Stateful mode - server sets the session ID
* const statefulTransport = new WebStandardStreamableHTTPServerTransport({
* sessionIdGenerator: () => crypto.randomUUID(),
* });
*
* // Stateless mode - explicitly set session ID to undefined
* const statelessTransport = new WebStandardStreamableHTTPServerTransport({
* sessionIdGenerator: undefined,
* });
*
* // Hono.js usage
* app.all('/mcp', async (c) => {
* return transport.handleRequest(c.req.raw);
* });
*
* // Cloudflare Workers usage
* export default {
* async fetch(request: Request): Promise<Response> {
* return transport.handleRequest(request);
* }
* };
* ```
*
* In stateful mode:
* - Session ID is generated and included in response headers
* - Session ID is always included in initialization responses
@ -212,6 +186,40 @@ export interface HandleRequestOptions {
* In stateless mode:
* - No Session ID is included in any responses
* - No session validation is performed
*
* @example Stateful setup
* ```ts source="./streamableHttp.examples.ts#WebStandardStreamableHTTPServerTransport_stateful"
* const server = new McpServer({ name: 'my-server', version: '1.0.0' });
*
* const transport = new WebStandardStreamableHTTPServerTransport({
* sessionIdGenerator: () => crypto.randomUUID()
* });
*
* await server.connect(transport);
* ```
*
* @example Stateless setup
* ```ts source="./streamableHttp.examples.ts#WebStandardStreamableHTTPServerTransport_stateless"
* const transport = new WebStandardStreamableHTTPServerTransport({
* sessionIdGenerator: undefined
* });
* ```
*
* @example Hono.js
* ```ts source="./streamableHttp.examples.ts#WebStandardStreamableHTTPServerTransport_hono"
* app.all('/mcp', async c => {
* return transport.handleRequest(c.req.raw);
* });
* ```
*
* @example Cloudflare Workers
* ```ts source="./streamableHttp.examples.ts#WebStandardStreamableHTTPServerTransport_workers"
* const worker = {
* async fetch(request: Request): Promise<Response> {
* return transport.handleRequest(request);
* }
* };
* ```
*/
export class WebStandardStreamableHTTPServerTransport implements Transport {
// when sessionId is not set (undefined), it means the transport is in stateless mode