Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/scenarios/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { SSERetryScenario } from './client/sse-retry';
import { ServerInitializeScenario } from './server/lifecycle';

import {
PingScenario,
LoggingSetLevelScenario,
CompletionCompleteScenario
} from './server/utils';
Expand Down Expand Up @@ -80,6 +81,7 @@ const allClientScenariosList: ClientScenario[] = [

// Utilities scenarios
new LoggingSetLevelScenario(),
new PingScenario(),
new CompletionCompleteScenario(),

// Tools scenarios
Expand Down
89 changes: 89 additions & 0 deletions src/scenarios/server/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<ConformanceCheck[]> {
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.
Expand Down
Loading