From 23afb9fc7704d0603532103803b7f2add7f00e33 Mon Sep 17 00:00:00 2001 From: Nate Barbettini Date: Sun, 30 Nov 2025 21:25:32 -0800 Subject: [PATCH] Add server ping scenario --- src/scenarios/index.ts | 2 + src/scenarios/server/utils.ts | 89 +++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/src/scenarios/index.ts b/src/scenarios/index.ts index de76cd6..470ffed 100644 --- a/src/scenarios/index.ts +++ b/src/scenarios/index.ts @@ -8,6 +8,7 @@ import { SSERetryScenario } from './client/sse-retry'; import { ServerInitializeScenario } from './server/lifecycle'; import { + PingScenario, LoggingSetLevelScenario, CompletionCompleteScenario } from './server/utils'; @@ -80,6 +81,7 @@ const allClientScenariosList: ClientScenario[] = [ // Utilities scenarios new LoggingSetLevelScenario(), + new PingScenario(), new CompletionCompleteScenario(), // Tools scenarios diff --git a/src/scenarios/server/utils.ts b/src/scenarios/server/utils.ts index e65c814..07b2ca6 100644 --- a/src/scenarios/server/utils.ts +++ b/src/scenarios/server/utils.ts @@ -83,6 +83,95 @@ export class LoggingSetLevelScenario implements ClientScenario { } } +export class PingScenario implements ClientScenario { + name = 'ping'; + description = `Test ping utility for connection health check. + +**Server Implementation Requirements:** + +**Endpoint**: \`ping\` + +**Requirements**: +- Accept ping request with no parameters +- Respond promptly with empty object \`{}\` + +**Request Format**: + +\`\`\`json +{ + "jsonrpc": "2.0", + "id": "123", + "method": "ping" +} +\`\`\` + +**Response Format**: + +\`\`\`json +{ + "jsonrpc": "2.0", + "id": "123", + "result": {} +} +\`\`\` + +**Implementation Note**: The ping utility allows either party to verify that their counterpart is still responsive and the connection is alive.`; + + async run(serverUrl: string): Promise { + const checks: ConformanceCheck[] = []; + + try { + const connection = await connectToServer(serverUrl); + + // Send ping request + const result = await connection.client.ping(); + + // Validate response (should return empty object {}) + const errors: string[] = []; + if (result && Object.keys(result).length > 0) { + errors.push('Expected empty object {} response'); + } + + checks.push({ + id: 'ping', + name: 'Ping', + description: 'Server responds to ping requests', + status: errors.length === 0 ? 'SUCCESS' : 'FAILURE', + timestamp: new Date().toISOString(), + errorMessage: errors.length > 0 ? errors.join('; ') : undefined, + specReferences: [ + { + id: 'MCP-Ping', + url: 'https://modelcontextprotocol.io/specification/2025-06-18/basic/utilities/ping' + } + ], + details: { + result + } + }); + + await connection.close(); + } catch (error) { + checks.push({ + id: 'ping', + name: 'Ping', + description: 'Server responds to ping requests', + status: 'FAILURE', + timestamp: new Date().toISOString(), + errorMessage: `Failed: ${error instanceof Error ? error.message : String(error)}`, + specReferences: [ + { + id: 'MCP-Ping', + url: 'https://modelcontextprotocol.io/specification/2025-06-18/basic/utilities/ping' + } + ] + }); + } + + return checks; + } +} + export class CompletionCompleteScenario implements ClientScenario { name = 'completion-complete'; description = `Test completion endpoint.