Automatic handling of logging level (#882)

Co-authored-by: Felix Weinberger <3823880+felixweinberger@users.noreply.github.com>
This commit is contained in:
Cliff Hall 2025-08-27 15:09:07 -04:00 • committed by GitHub
commit 79d11dc53f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 116 additions and 79 deletions

View file

@ -44,27 +44,27 @@ const getServer = () => {
{
name: z.string().describe('Name to greet'),
},
async ({ name }, { sendNotification }): Promise<CallToolResult> => {
async ({ name }, extra): Promise<CallToolResult> => {
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
await sendNotification({
method: "notifications/message",
params: { level: "debug", data: `Starting multi-greet for ${name}` }
});
await server.sendLoggingMessage({
level: "debug",
data: `Starting multi-greet for ${name}`
}, extra.sessionId);
await sleep(1000); // Wait 1 second before first greeting
await sendNotification({
method: "notifications/message",
params: { level: "info", data: `Sending first greeting to ${name}` }
});
await server.sendLoggingMessage({
level: "info",
data: `Sending first greeting to ${name}`
}, extra.sessionId);
await sleep(1000); // Wait another second before second greeting
await sendNotification({
method: "notifications/message",
params: { level: "info", data: `Sending second greeting to ${name}` }
});
await server.sendLoggingMessage({
level: "info",
data: `Sending second greeting to ${name}`
}, extra.sessionId);
return {
content: [
@ -170,4 +170,4 @@ app.listen(PORT, (error) => {
process.on('SIGINT', async () => {
console.log('Shutting down server...');
process.exit(0);
});
});

View file

@ -5,13 +5,13 @@ import { z } from 'zod';
import { CallToolResult } from '../../types.js';
/**
* This example server demonstrates the deprecated HTTP+SSE transport
* This example server demonstrates the deprecated HTTP+SSE transport
* (protocol version 2024-11-05). It mainly used for testing backward compatible clients.
*
*
* The server exposes two endpoints:
* - /mcp: For establishing the SSE stream (GET)
* - /messages: For receiving client messages (POST)
*
*
*/
// Create an MCP server instance
@ -28,18 +28,15 @@ const getServer = () => {
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 }, { sendNotification }): Promise<CallToolResult> => {
async ({ interval, count }, extra): Promise<CallToolResult> => {
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
let counter = 0;
// Send the initial notification
await sendNotification({
method: "notifications/message",
params: {
level: "info",
data: `Starting notification stream with ${count} messages every ${interval}ms`
}
});
await server.sendLoggingMessage({
level: "info",
data: `Starting notification stream with ${count} messages every ${interval}ms`
}, extra.sessionId);
// Send periodic notifications
while (counter < count) {
@ -47,13 +44,10 @@ const getServer = () => {
await sleep(interval);
try {
await sendNotification({
method: "notifications/message",
params: {
await server.sendLoggingMessage({
level: "info",
data: `Notification #${counter} at ${new Date().toISOString()}`
}
});
}, extra.sessionId);
}
catch (error) {
console.error("Error sending notification:", error);
@ -169,4 +163,4 @@ process.on('SIGINT', async () => {
}
console.log('Server shutdown complete');
process.exit(0);
});
});

View file

@ -42,20 +42,17 @@ const getServer = () => {
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 }, { sendNotification }): Promise<CallToolResult> => {
async ({ interval, count }, extra): Promise<CallToolResult> => {
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
let counter = 0;
while (count === 0 || counter < count) {
counter++;
try {
await sendNotification({
method: "notifications/message",
params: {
level: "info",
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
}
});
await server.sendLoggingMessage({
level: "info",
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
}, extra.sessionId);
}
catch (error) {
console.error("Error sending notification:", error);
@ -170,4 +167,4 @@ app.listen(PORT, (error) => {
process.on('SIGINT', async () => {
console.log('Shutting down server...');
process.exit(0);
});
});

View file

@ -58,27 +58,27 @@ const getServer = () => {
readOnlyHint: true,
openWorldHint: false
},
async ({ name }, { sendNotification }): Promise<CallToolResult> => {
async ({ name }, extra): Promise<CallToolResult> => {
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
await sendNotification({
method: "notifications/message",
params: { level: "debug", data: `Starting multi-greet for ${name}` }
});
await server.sendLoggingMessage({
level: "debug",
data: `Starting multi-greet for ${name}`
}, extra.sessionId);
await sleep(1000); // Wait 1 second before first greeting
await sendNotification({
method: "notifications/message",
params: { level: "info", data: `Sending first greeting to ${name}` }
});
await server.sendLoggingMessage({
level: "info",
data: `Sending first greeting to ${name}`
}, extra.sessionId);
await sleep(1000); // Wait another second before second greeting
await sendNotification({
method: "notifications/message",
params: { level: "info", data: `Sending second greeting to ${name}` }
});
await server.sendLoggingMessage({
level: "info",
data: `Sending second greeting to ${name}`
}, extra.sessionId);
return {
content: [
@ -273,20 +273,17 @@ const getServer = () => {
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 }, { sendNotification }): Promise<CallToolResult> => {
async ({ interval, count }, extra): Promise<CallToolResult> => {
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
let counter = 0;
while (count === 0 || counter < count) {
counter++;
try {
await sendNotification({
method: "notifications/message",
params: {
level: "info",
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
}
});
await server.sendLoggingMessage( {
level: "info",
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
}, extra.sessionId);
}
catch (error) {
console.error("Error sending notification:", error);

View file

@ -12,7 +12,7 @@ import cors from 'cors';
* 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)
*
*
* It maintains a single MCP server instance but exposes two transport options:
* - /mcp: The new Streamable HTTP endpoint (supports GET/POST/DELETE)
* - /sse: The deprecated SSE endpoint for older clients (GET to establish stream)
@ -33,20 +33,17 @@ const getServer = () => {
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 }, { sendNotification }): Promise<CallToolResult> => {
async ({ interval, count }, extra): Promise<CallToolResult> => {
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
let counter = 0;
while (count === 0 || counter < count) {
counter++;
try {
await sendNotification({
method: "notifications/message",
params: {
level: "info",
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
}
});
await server.sendLoggingMessage({
level: "info",
data: `Periodic notification #${counter} at ${new Date().toISOString()}`
}, extra.sessionId);
}
catch (error) {
console.error("Error sending notification:", error);
@ -254,4 +251,4 @@ process.on('SIGINT', async () => {
}
console.log('Server shutdown complete');
process.exit(0);
});
});