Update server examples and docs (#1285)
This commit is contained in:
parent
06a4fd2332
commit
67d79d45ee
8 changed files with 65 additions and 48 deletions
|
|
@ -31,8 +31,7 @@ Key examples:
|
|||
- [`jsonResponseStreamableHttp.ts`](../src/examples/server/jsonResponseStreamableHttp.ts) – `enableJsonResponse: true`, no SSE
|
||||
- [`standaloneSseWithGetStreamableHttp.ts`](../src/examples/server/standaloneSseWithGetStreamableHttp.ts) – notifications with Streamable HTTP GET + SSE
|
||||
|
||||
See the MCP spec for full transport details:
|
||||
`https://modelcontextprotocol.io/specification/2025-03-26/basic/transports`
|
||||
See the MCP spec for full transport details: `https://modelcontextprotocol.io/specification/2025-11-25/basic/transports`
|
||||
|
||||
### Stateless vs stateful sessions
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ npx tsx src/examples/client/simpleClientCredentials.ts
|
|||
|
||||
### Backwards Compatible Client
|
||||
|
||||
A client that implements backwards compatibility according to the [MCP specification](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#backwards-compatibility), allowing it to work with both new and legacy servers. This client demonstrates:
|
||||
A client that implements backwards compatibility according to the [MCP specification](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#backwards-compatibility), allowing it to work with both new and legacy servers. This client demonstrates:
|
||||
|
||||
- The client first POSTs an initialize request to the server URL:
|
||||
- If successful, it uses the Streamable HTTP transport
|
||||
|
|
@ -83,7 +83,7 @@ These examples demonstrate how to set up an MCP server on a single node with dif
|
|||
|
||||
##### Simple Streamable HTTP Server
|
||||
|
||||
A server that implements the Streamable HTTP transport (protocol version 2025-03-26).
|
||||
A server that implements the Streamable HTTP transport (protocol version 2025-11-25).
|
||||
|
||||
- Basic server setup with Express and the Streamable HTTP transport
|
||||
- Session management with an in-memory event store for resumability
|
||||
|
|
@ -166,7 +166,7 @@ npx tsx src/examples/server/simpleSseServer.ts
|
|||
|
||||
#### Streamable Http Backwards Compatible Server with SSE
|
||||
|
||||
A server that supports both Streamable HTTP and SSE transports, adhering to the [MCP specification for backwards compatibility](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#backwards-compatibility).
|
||||
A server that supports both Streamable HTTP and SSE transports, adhering to the [MCP specification for backwards compatibility](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#backwards-compatibility).
|
||||
|
||||
- Single MCP server instance with multiple transport options
|
||||
- Support for Streamable HTTP requests at `/mcp` endpoint (GET/POST/DELETE)
|
||||
|
|
@ -337,7 +337,7 @@ To test the backwards compatibility features:
|
|||
# Legacy SSE server (protocol version 2024-11-05)
|
||||
npx tsx src/examples/server/simpleSseServer.ts
|
||||
|
||||
# Streamable HTTP server (protocol version 2025-03-26)
|
||||
# Streamable HTTP server (protocol version 2025-11-25)
|
||||
npx tsx src/examples/server/simpleStreamableHttp.ts
|
||||
|
||||
# Backwards compatible server (supports both protocols)
|
||||
|
|
|
|||
|
|
@ -21,11 +21,13 @@ const getServer = () => {
|
|||
);
|
||||
|
||||
// Register a simple tool that returns a greeting
|
||||
server.tool(
|
||||
server.registerTool(
|
||||
'greet',
|
||||
'A simple greeting tool',
|
||||
{
|
||||
name: z.string().describe('Name to greet')
|
||||
description: 'A simple greeting tool',
|
||||
inputSchema: {
|
||||
name: z.string().describe('Name to greet')
|
||||
}
|
||||
},
|
||||
async ({ name }): Promise<CallToolResult> => {
|
||||
return {
|
||||
|
|
@ -40,11 +42,13 @@ const getServer = () => {
|
|||
);
|
||||
|
||||
// Register a tool that sends multiple greetings with notifications
|
||||
server.tool(
|
||||
server.registerTool(
|
||||
'multi-greet',
|
||||
'A tool that sends different greetings with delays between them',
|
||||
{
|
||||
name: z.string().describe('Name to greet')
|
||||
description: 'A tool that sends different greetings with delays between them',
|
||||
inputSchema: {
|
||||
name: z.string().describe('Name to greet')
|
||||
}
|
||||
},
|
||||
async ({ name }, extra): Promise<CallToolResult> => {
|
||||
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
|
|
|||
|
|
@ -25,12 +25,14 @@ const getServer = () => {
|
|||
{ capabilities: { logging: {} } }
|
||||
);
|
||||
|
||||
server.tool(
|
||||
server.registerTool(
|
||||
'start-notification-stream',
|
||||
'Starts sending periodic notifications',
|
||||
{
|
||||
interval: z.number().describe('Interval in milliseconds between notifications').default(1000),
|
||||
count: z.number().describe('Number of notifications to send').default(10)
|
||||
description: 'Starts sending periodic notifications',
|
||||
inputSchema: {
|
||||
interval: z.number().describe('Interval in milliseconds between notifications').default(1000),
|
||||
count: z.number().describe('Number of notifications to send').default(10)
|
||||
}
|
||||
},
|
||||
async ({ interval, count }, extra): Promise<CallToolResult> => {
|
||||
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@ const getServer = () => {
|
|||
);
|
||||
|
||||
// Register a simple prompt
|
||||
server.prompt(
|
||||
server.registerPrompt(
|
||||
'greeting-template',
|
||||
'A simple greeting prompt template',
|
||||
{
|
||||
name: z.string().describe('Name to include in greeting')
|
||||
description: 'A simple greeting prompt template',
|
||||
argsSchema: {
|
||||
name: z.string().describe('Name to include in greeting')
|
||||
}
|
||||
},
|
||||
async ({ name }): Promise<GetPromptResult> => {
|
||||
return {
|
||||
|
|
@ -38,12 +40,14 @@ const getServer = () => {
|
|||
);
|
||||
|
||||
// Register a tool specifically for testing resumability
|
||||
server.tool(
|
||||
server.registerTool(
|
||||
'start-notification-stream',
|
||||
'Starts sending periodic notifications for testing resumability',
|
||||
{
|
||||
interval: z.number().describe('Interval in milliseconds between notifications').default(100),
|
||||
count: z.number().describe('Number of notifications to send (0 for 100)').default(10)
|
||||
description: 'Starts sending periodic notifications for testing resumability',
|
||||
inputSchema: {
|
||||
interval: z.number().describe('Interval in milliseconds between notifications').default(100),
|
||||
count: z.number().describe('Number of notifications to send (0 for 100)').default(10)
|
||||
}
|
||||
},
|
||||
async ({ interval, count }, extra): Promise<CallToolResult> => {
|
||||
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
|
@ -78,7 +82,7 @@ const getServer = () => {
|
|||
);
|
||||
|
||||
// Create a simple resource at a fixed URI
|
||||
server.resource(
|
||||
server.registerResource(
|
||||
'greeting-resource',
|
||||
'https://example.com/greetings/default',
|
||||
{ mimeType: 'text/plain' },
|
||||
|
|
|
|||
|
|
@ -67,16 +67,18 @@ const getServer = () => {
|
|||
);
|
||||
|
||||
// Register a tool that sends multiple greetings with notifications (with annotations)
|
||||
server.tool(
|
||||
server.registerTool(
|
||||
'multi-greet',
|
||||
'A tool that sends different greetings with delays between them',
|
||||
{
|
||||
name: z.string().describe('Name to greet')
|
||||
},
|
||||
{
|
||||
title: 'Multiple Greeting Tool',
|
||||
readOnlyHint: true,
|
||||
openWorldHint: false
|
||||
description: 'A tool that sends different greetings with delays between them',
|
||||
inputSchema: {
|
||||
name: z.string().describe('Name to greet')
|
||||
},
|
||||
annotations: {
|
||||
title: 'Multiple Greeting Tool',
|
||||
readOnlyHint: true,
|
||||
openWorldHint: false
|
||||
}
|
||||
},
|
||||
async ({ name }, extra): Promise<CallToolResult> => {
|
||||
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
|
@ -121,11 +123,13 @@ const getServer = () => {
|
|||
);
|
||||
// Register a tool that demonstrates form elicitation (user input collection with a schema)
|
||||
// This creates a closure that captures the server instance
|
||||
server.tool(
|
||||
server.registerTool(
|
||||
'collect-user-info',
|
||||
'A tool that collects user information through form elicitation',
|
||||
{
|
||||
infoType: z.enum(['contact', 'preferences', 'feedback']).describe('Type of information to collect')
|
||||
description: 'A tool that collects user information through form elicitation',
|
||||
inputSchema: {
|
||||
infoType: z.enum(['contact', 'preferences', 'feedback']).describe('Type of information to collect')
|
||||
}
|
||||
},
|
||||
async ({ infoType }, extra): Promise<CallToolResult> => {
|
||||
let message: string;
|
||||
|
|
@ -302,12 +306,14 @@ const getServer = () => {
|
|||
);
|
||||
|
||||
// Register a tool specifically for testing resumability
|
||||
server.tool(
|
||||
server.registerTool(
|
||||
'start-notification-stream',
|
||||
'Starts sending periodic notifications for testing resumability',
|
||||
{
|
||||
interval: z.number().describe('Interval in milliseconds between notifications').default(100),
|
||||
count: z.number().describe('Number of notifications to send (0 for 100)').default(50)
|
||||
description: 'Starts sending periodic notifications for testing resumability',
|
||||
inputSchema: {
|
||||
interval: z.number().describe('Interval in milliseconds between notifications').default(100),
|
||||
count: z.number().describe('Number of notifications to send (0 for 100)').default(50)
|
||||
}
|
||||
},
|
||||
async ({ interval, count }, extra): Promise<CallToolResult> => {
|
||||
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { createMcpExpressApp } from '../../server/express.js';
|
|||
/**
|
||||
* This example server demonstrates backwards compatibility with both:
|
||||
* 1. The deprecated HTTP+SSE transport (protocol version 2024-11-05)
|
||||
* 2. The Streamable HTTP transport (protocol version 2025-03-26)
|
||||
* 2. The Streamable HTTP transport (protocol version 2025-11-25)
|
||||
*
|
||||
* It maintains a single MCP server instance but exposes two transport options:
|
||||
* - /mcp: The new Streamable HTTP endpoint (supports GET/POST/DELETE)
|
||||
|
|
@ -29,12 +29,14 @@ const getServer = () => {
|
|||
);
|
||||
|
||||
// Register a simple tool that sends notifications over time
|
||||
server.tool(
|
||||
server.registerTool(
|
||||
'start-notification-stream',
|
||||
'Starts sending periodic notifications for testing resumability',
|
||||
{
|
||||
interval: z.number().describe('Interval in milliseconds between notifications').default(100),
|
||||
count: z.number().describe('Number of notifications to send (0 for 100)').default(50)
|
||||
description: 'Starts sending periodic notifications for testing resumability',
|
||||
inputSchema: {
|
||||
interval: z.number().describe('Interval in milliseconds between notifications').default(100),
|
||||
count: z.number().describe('Number of notifications to send (0 for 100)').default(50)
|
||||
}
|
||||
},
|
||||
async ({ interval, count }, extra): Promise<CallToolResult> => {
|
||||
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
|
@ -77,7 +79,7 @@ const app = createMcpExpressApp();
|
|||
const transports: Record<string, StreamableHTTPServerTransport | SSEServerTransport> = {};
|
||||
|
||||
//=============================================================================
|
||||
// STREAMABLE HTTP TRANSPORT (PROTOCOL VERSION 2025-03-26)
|
||||
// STREAMABLE HTTP TRANSPORT (PROTOCOL VERSION 2025-11-25)
|
||||
//=============================================================================
|
||||
|
||||
// Handle all MCP Streamable HTTP requests (GET, POST, DELETE) on a single endpoint
|
||||
|
|
@ -214,10 +216,10 @@ app.listen(PORT, error => {
|
|||
==============================================
|
||||
SUPPORTED TRANSPORT OPTIONS:
|
||||
|
||||
1. Streamable Http(Protocol version: 2025-03-26)
|
||||
1. Streamable Http(Protocol version: 2025-11-25)
|
||||
Endpoint: /mcp
|
||||
Methods: GET, POST, DELETE
|
||||
Usage:
|
||||
Usage:
|
||||
- Initialize with POST to /mcp
|
||||
- Establish SSE stream with GET to /mcp
|
||||
- Send requests with POST to /mcp
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ const transports: { [sessionId: string]: StreamableHTTPServerTransport } = {};
|
|||
|
||||
const addResource = (name: string, content: string) => {
|
||||
const uri = `https://mcp-example.com/dynamic/${encodeURIComponent(name)}`;
|
||||
server.resource(
|
||||
server.registerResource(
|
||||
name,
|
||||
uri,
|
||||
{ mimeType: 'text/plain', description: `Dynamic resource: ${name}` },
|
||||
|
|
|
|||
Loading…
Reference in a new issue