Skip to content

Commit b858bea

Browse files
committed
create some checks
1 parent 2644074 commit b858bea

8 files changed

Lines changed: 206 additions & 5 deletions

File tree

src/checks.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,38 @@ export function createServerInfoCheck(serverInfo: { name: string; version: strin
4545
}
4646
};
4747
}
48+
49+
export function createServerInitializationCheck(initializeResponse: any, expectedSpecVersion: string = '2025-06-18'): ConformanceCheck {
50+
const result = initializeResponse?.result;
51+
const protocolVersion = result?.protocolVersion;
52+
const serverInfo = result?.serverInfo;
53+
const capabilities = result?.capabilities;
54+
55+
const errors: string[] = [];
56+
if (!initializeResponse?.jsonrpc) errors.push('Missing jsonrpc field');
57+
if (!initializeResponse?.id) errors.push('Missing id field');
58+
if (!result) errors.push('Missing result field');
59+
if (!protocolVersion) errors.push('Missing protocolVersion in result');
60+
if (protocolVersion !== expectedSpecVersion) errors.push(`Protocol version mismatch: expected ${expectedSpecVersion}, got ${protocolVersion}`);
61+
if (!serverInfo) errors.push('Missing serverInfo in result');
62+
if (!serverInfo?.name) errors.push('Missing server name in serverInfo');
63+
if (!serverInfo?.version) errors.push('Missing server version in serverInfo');
64+
if (capabilities === undefined) errors.push('Missing capabilities in result');
65+
66+
const status: CheckStatus = errors.length === 0 ? 'SUCCESS' : 'FAILURE';
67+
68+
return {
69+
id: 'mcp-server-initialization',
70+
name: 'MCPServerInitialization',
71+
description: 'Validates that MCP server properly responds to initialize request',
72+
status,
73+
timestamp: new Date().toISOString(),
74+
specReferences: [{ id: 'MCP-Lifecycle', url: 'https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle' }],
75+
details: {
76+
expectedSpecVersion,
77+
...initializeResponse
78+
},
79+
errorMessage: errors.length > 0 ? errors.join('; ') : undefined,
80+
logs: errors.length > 0 ? errors : undefined
81+
};
82+
}

src/checks/client.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { ConformanceCheck, CheckStatus } from '../types.js';
2+
3+
export function createServerInfoCheck(serverInfo: { name: string; version: string }): ConformanceCheck {
4+
return {
5+
id: 'server-info',
6+
name: 'ServerInfo',
7+
description: 'Test server info returned to client',
8+
status: 'INFO',
9+
timestamp: new Date().toISOString(),
10+
specReferences: [{ id: 'MCP-Lifecycle', url: 'https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle' }],
11+
details: {
12+
serverName: serverInfo.name,
13+
serverVersion: serverInfo.version
14+
}
15+
};
16+
}
17+
18+
export function createClientInitializationCheck(initializeRequest: any, expectedSpecVersion: string = '2025-06-18'): ConformanceCheck {
19+
const protocolVersionSent = initializeRequest?.protocolVersion;
20+
const versionMatch = protocolVersionSent === expectedSpecVersion;
21+
22+
const errors: string[] = [];
23+
if (!protocolVersionSent) errors.push('Protocol version not provided');
24+
if (!versionMatch) errors.push(`Version mismatch: expected ${expectedSpecVersion}, got ${protocolVersionSent}`);
25+
if (!initializeRequest?.clientInfo?.name) errors.push('Client name missing');
26+
if (!initializeRequest?.clientInfo?.version) errors.push('Client version missing');
27+
28+
const status: CheckStatus = errors.length === 0 ? 'SUCCESS' : 'FAILURE';
29+
30+
return {
31+
id: 'mcp-client-initialization',
32+
name: 'MCPClientInitialization',
33+
description: 'Validates that MCP client properly initializes with server',
34+
status,
35+
timestamp: new Date().toISOString(),
36+
specReferences: [{ id: 'MCP-Lifecycle', url: 'https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle' }],
37+
details: {
38+
protocolVersionSent,
39+
expectedSpecVersion,
40+
versionMatch,
41+
clientName: initializeRequest?.clientInfo?.name,
42+
clientVersion: initializeRequest?.clientInfo?.version
43+
},
44+
errorMessage: errors.length > 0 ? errors.join('; ') : undefined,
45+
logs: errors.length > 0 ? errors : undefined
46+
};
47+
}

src/checks/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// Namespaced exports for client and server checks
2+
import * as client from './client.js';
3+
import * as server from './server.js';
4+
5+
6+
export const clientChecks = client;
7+
export const serverChecks = server;

src/checks/server.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { ConformanceCheck, CheckStatus } from '../types.js';
2+
3+
export function createServerInitializationCheck(initializeResponse: any, expectedSpecVersion: string = '2025-06-18'): ConformanceCheck {
4+
const result = initializeResponse?.result;
5+
const protocolVersion = result?.protocolVersion;
6+
const serverInfo = result?.serverInfo;
7+
const capabilities = result?.capabilities;
8+
9+
const errors: string[] = [];
10+
if (!initializeResponse?.jsonrpc) errors.push('Missing jsonrpc field');
11+
if (!initializeResponse?.id) errors.push('Missing id field');
12+
if (!result) errors.push('Missing result field');
13+
if (!protocolVersion) errors.push('Missing protocolVersion in result');
14+
if (protocolVersion !== expectedSpecVersion) errors.push(`Protocol version mismatch: expected ${expectedSpecVersion}, got ${protocolVersion}`);
15+
if (!serverInfo) errors.push('Missing serverInfo in result');
16+
if (!serverInfo?.name) errors.push('Missing server name in serverInfo');
17+
if (!serverInfo?.version) errors.push('Missing server version in serverInfo');
18+
if (capabilities === undefined) errors.push('Missing capabilities in result');
19+
20+
const status: CheckStatus = errors.length === 0 ? 'SUCCESS' : 'FAILURE';
21+
22+
return {
23+
id: 'mcp-server-initialization',
24+
name: 'MCPServerInitialization',
25+
description: 'Validates that MCP server properly responds to initialize request',
26+
status,
27+
timestamp: new Date().toISOString(),
28+
specReferences: [{ id: 'MCP-Lifecycle', url: 'https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle' }],
29+
details: {
30+
expectedSpecVersion,
31+
...initializeResponse
32+
},
33+
errorMessage: errors.length > 0 ? errors.join('; ') : undefined,
34+
logs: errors.length > 0 ? errors : undefined
35+
};
36+
}

src/scenarios/client/initialize.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import http from 'http';
22
import { Scenario, ScenarioUrls, ConformanceCheck } from '../../types.js';
3-
import { createClientInitializationCheck, createServerInfoCheck } from '../../checks.js';
3+
import { clientChecks } from '../../checks/index.js';
44

55
export class InitializeScenario implements Scenario {
66
name = 'initialize';
@@ -96,16 +96,15 @@ export class InitializeScenario implements Scenario {
9696
private handleInitialize(request: any, res: http.ServerResponse): void {
9797
const initializeRequest = request.params;
9898

99-
const check = createClientInitializationCheck(initializeRequest);
99+
const check = clientChecks.createClientInitializationCheck(initializeRequest);
100100
this.checks.push(check);
101101

102102
const serverInfo = {
103103
name: 'test-server',
104104
version: '1.0.0'
105105
};
106106

107-
const serverInfoCheck = createServerInfoCheck(serverInfo);
108-
this.checks.push(serverInfoCheck);
107+
this.checks.push(clientChecks.createServerInfoCheck(serverInfo));
109108

110109
const response = {
111110
jsonrpc: '2.0',

src/scenarios/index.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
import { Scenario } from '../types.js';
1+
import { Scenario, ClientScenario } from '../types.js';
22
import { InitializeScenario } from './client/initialize.js';
33
import { ToolsCallScenario } from './client/tools_call.js';
4+
import { ServerInitializeClientScenario } from './server/server_initialize.js';
45

56
export const scenarios = new Map<string, Scenario>([
67
['initialize', new InitializeScenario()],
78
['tools-call', new ToolsCallScenario()]
89
]);
910

11+
export const clientScenarios = new Map<string, ClientScenario>([
12+
['server-initialize', new ServerInitializeClientScenario()]
13+
]);
14+
1015
export function registerScenario(name: string, scenario: Scenario): void {
1116
scenarios.set(name, scenario);
1217
}
@@ -15,6 +20,14 @@ export function getScenario(name: string): Scenario | undefined {
1520
return scenarios.get(name);
1621
}
1722

23+
export function getClientScenario(name: string): ClientScenario | undefined {
24+
return clientScenarios.get(name);
25+
}
26+
1827
export function listScenarios(): string[] {
1928
return Array.from(scenarios.keys());
2029
}
30+
31+
export function listClientScenarios(): string[] {
32+
return Array.from(clientScenarios.keys());
33+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { ClientScenario, ConformanceCheck } from '../../types.js';
2+
import { serverChecks } from '../../checks/index.js';
3+
4+
export class ServerInitializeClientScenario implements ClientScenario {
5+
name = 'server-initialize';
6+
description = 'Acts as MCP client to test external server initialization';
7+
8+
async run(serverUrl: string): Promise<ConformanceCheck[]> {
9+
const checks: ConformanceCheck[] = [];
10+
11+
try {
12+
const response = await fetch(serverUrl, {
13+
method: 'POST',
14+
headers: {
15+
'Content-Type': 'application/json',
16+
},
17+
body: JSON.stringify({
18+
jsonrpc: '2.0',
19+
id: 1,
20+
method: 'initialize',
21+
params: {
22+
protocolVersion: '2025-06-18',
23+
capabilities: {},
24+
clientInfo: {
25+
name: 'conformance-test-client',
26+
version: '1.0.0'
27+
}
28+
}
29+
})
30+
});
31+
32+
if (!response.ok) {
33+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
34+
}
35+
36+
const result = await response.json();
37+
const check = serverChecks.createServerInitializationCheck(result);
38+
checks.push(check);
39+
} catch (error) {
40+
checks.push({
41+
id: 'server-initialize-request',
42+
name: 'ServerInitializeRequest',
43+
description: 'Tests server response to initialize request',
44+
status: 'FAILURE',
45+
timestamp: new Date().toISOString(),
46+
errorMessage: `Failed to send initialize request: ${error instanceof Error ? error.message : String(error)}`,
47+
specReferences: [
48+
{
49+
id: 'MCP-Initialize',
50+
url: 'https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle#initialization'
51+
}
52+
]
53+
});
54+
}
55+
56+
return checks;
57+
}
58+
}

src/types.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,9 @@ export interface Scenario {
3030
stop(): Promise<void>;
3131
getChecks(): ConformanceCheck[];
3232
}
33+
34+
export interface ClientScenario {
35+
name: string;
36+
description: string;
37+
run(serverUrl: string): Promise<ConformanceCheck[]>;
38+
}

0 commit comments

Comments
 (0)