Skip to content

Commit 39f7fdf

Browse files
committed
fix stateless example
1 parent 70608b5 commit 39f7fdf

File tree

1 file changed

+99
-106
lines changed

1 file changed

+99
-106
lines changed

src/examples/server/simpleStatelessStreamableHttp.ts

Lines changed: 99 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -4,108 +4,114 @@ import { StreamableHTTPServerTransport } from '../../server/streamableHttp.js';
44
import { z } from 'zod';
55
import { CallToolResult, GetPromptResult, ReadResourceResult } from '../../types.js';
66

7-
// Create an MCP server with implementation details
8-
const server = new McpServer({
9-
name: 'stateless-streamable-http-server',
10-
version: '1.0.0',
11-
}, { capabilities: { logging: {} } });
12-
13-
// Register a simple prompt
14-
server.prompt(
15-
'greeting-template',
16-
'A simple greeting prompt template',
17-
{
18-
name: z.string().describe('Name to include in greeting'),
19-
},
20-
async ({ name }): Promise<GetPromptResult> => {
21-
return {
22-
messages: [
23-
{
24-
role: 'user',
25-
content: {
26-
type: 'text',
27-
text: `Please greet ${name} in a friendly manner.`,
7+
const getServer = () => {
8+
// Create an MCP server with implementation details
9+
const server = new McpServer({
10+
name: 'stateless-streamable-http-server',
11+
version: '1.0.0',
12+
}, { capabilities: { logging: {} } });
13+
14+
// Register a simple prompt
15+
server.prompt(
16+
'greeting-template',
17+
'A simple greeting prompt template',
18+
{
19+
name: z.string().describe('Name to include in greeting'),
20+
},
21+
async ({ name }): Promise<GetPromptResult> => {
22+
return {
23+
messages: [
24+
{
25+
role: 'user',
26+
content: {
27+
type: 'text',
28+
text: `Please greet ${name} in a friendly manner.`,
29+
},
2830
},
29-
},
30-
],
31-
};
32-
}
33-
);
34-
35-
// Register a tool specifically for testing resumability
36-
server.tool(
37-
'start-notification-stream',
38-
'Starts sending periodic notifications for testing resumability',
39-
{
40-
interval: z.number().describe('Interval in milliseconds between notifications').default(100),
41-
count: z.number().describe('Number of notifications to send (0 for 100)').default(10),
42-
},
43-
async ({ interval, count }, { sendNotification }): Promise<CallToolResult> => {
44-
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
45-
let counter = 0;
46-
47-
while (count === 0 || counter < count) {
48-
counter++;
49-
try {
50-
await sendNotification({
51-
method: "notifications/message",
52-
params: {
53-
level: "info",
54-
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
55-
}
56-
});
57-
}
58-
catch (error) {
59-
console.error("Error sending notification:", error);
60-
}
61-
// Wait for the specified interval
62-
await sleep(interval);
31+
],
32+
};
6333
}
34+
);
35+
36+
// Register a tool specifically for testing resumability
37+
server.tool(
38+
'start-notification-stream',
39+
'Starts sending periodic notifications for testing resumability',
40+
{
41+
interval: z.number().describe('Interval in milliseconds between notifications').default(100),
42+
count: z.number().describe('Number of notifications to send (0 for 100)').default(10),
43+
},
44+
async ({ interval, count }, { sendNotification }): Promise<CallToolResult> => {
45+
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
46+
let counter = 0;
6447

65-
return {
66-
content: [
67-
{
68-
type: 'text',
69-
text: `Started sending periodic notifications every ${interval}ms`,
48+
while (count === 0 || counter < count) {
49+
counter++;
50+
try {
51+
await sendNotification({
52+
method: "notifications/message",
53+
params: {
54+
level: "info",
55+
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
56+
}
57+
});
7058
}
71-
],
72-
};
73-
}
74-
);
75-
76-
// Create a simple resource at a fixed URI
77-
server.resource(
78-
'greeting-resource',
79-
'https://example.com/greetings/default',
80-
{ mimeType: 'text/plain' },
81-
async (): Promise<ReadResourceResult> => {
82-
return {
83-
contents: [
84-
{
85-
uri: 'https://example.com/greetings/default',
86-
text: 'Hello, world!',
87-
},
88-
],
89-
};
90-
}
91-
);
59+
catch (error) {
60+
console.error("Error sending notification:", error);
61+
}
62+
// Wait for the specified interval
63+
await sleep(interval);
64+
}
65+
66+
return {
67+
content: [
68+
{
69+
type: 'text',
70+
text: `Started sending periodic notifications every ${interval}ms`,
71+
}
72+
],
73+
};
74+
}
75+
);
76+
77+
// Create a simple resource at a fixed URI
78+
server.resource(
79+
'greeting-resource',
80+
'https://example.com/greetings/default',
81+
{ mimeType: 'text/plain' },
82+
async (): Promise<ReadResourceResult> => {
83+
return {
84+
contents: [
85+
{
86+
uri: 'https://example.com/greetings/default',
87+
text: 'Hello, world!',
88+
},
89+
],
90+
};
91+
}
92+
);
93+
return server;
94+
}
9295

9396
const app = express();
9497
app.use(express.json());
9598

96-
const transport: StreamableHTTPServerTransport = new StreamableHTTPServerTransport({
97-
sessionIdGenerator: undefined,
98-
});
9999

100-
// Setup routes for the server
101-
const setupServer = async () => {
102-
await server.connect(transport);
103-
};
100+
104101

105102
app.post('/mcp', async (req: Request, res: Response) => {
106-
console.log('Received MCP request:', req.body);
103+
const server = getServer();
107104
try {
108-
await transport.handleRequest(req, res, req.body);
105+
const transport: StreamableHTTPServerTransport = new StreamableHTTPServerTransport({
106+
sessionIdGenerator: undefined,
107+
});
108+
await server.connect(transport);
109+
await transport.handleRequest(req, res, req.body);
110+
res.on('close', () => {
111+
console.log('Request closed');
112+
transport.close();
113+
server.close();
114+
});
109115
} catch (error) {
110116
console.error('Error handling MCP request:', error);
111117
if (!res.headersSent) {
@@ -145,28 +151,15 @@ app.delete('/mcp', async (req: Request, res: Response) => {
145151
}));
146152
});
147153

154+
148155
// Start the server
149156
const PORT = 3000;
150-
setupServer().then(() => {
151-
app.listen(PORT, () => {
152-
console.log(`MCP Streamable HTTP Server listening on port ${PORT}`);
153-
});
154-
}).catch(error => {
155-
console.error('Failed to set up the server:', error);
156-
process.exit(1);
157+
app.listen(PORT, () => {
158+
console.log(`MCP Stateless Streamable HTTP Server listening on port ${PORT}`);
157159
});
158160

159161
// Handle server shutdown
160162
process.on('SIGINT', async () => {
161163
console.log('Shutting down server...');
162-
try {
163-
console.log(`Closing transport`);
164-
await transport.close();
165-
} catch (error) {
166-
console.error(`Error closing transport:`, error);
167-
}
168-
169-
await server.close();
170-
console.log('Server shutdown complete');
171164
process.exit(0);
172165
});

0 commit comments

Comments
 (0)