initial runner for checking server conformance (#3)

* create some checks

* basic initialize working

* rename
This commit is contained in:
Paul Carleton 2025-11-03 16:43:43 +00:00 • committed by GitHub
commit 3b9da98c6a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 267 additions and 23 deletions

84
src/checks/checks.test.ts Normal file
View file

@ -0,0 +1,84 @@
import { createClientInitializationCheck } from './client';
describe('createClientInitializationCheck', () => {
it('should return SUCCESS for a valid initialize request', () => {
const validRequest = {
protocolVersion: '2025-06-18',
clientInfo: {
name: 'TestClient',
version: '1.0.0'
}
};
const check = createClientInitializationCheck(validRequest);
expect(check.status).toBe('SUCCESS');
expect(check.errorMessage).toBeUndefined();
});
it('should return FAILURE when protocol version is missing', () => {
const invalidRequest = {
clientInfo: {
name: 'TestClient',
version: '1.0.0'
}
};
const check = createClientInitializationCheck(invalidRequest);
expect(check.status).toBe('FAILURE');
expect(check.errorMessage).toContain('Protocol version not provided');
});
it('should return FAILURE when protocol version does not match', () => {
const invalidRequest = {
protocolVersion: '2024-11-05',
clientInfo: {
name: 'TestClient',
version: '1.0.0'
}
};
const check = createClientInitializationCheck(invalidRequest);
expect(check.status).toBe('FAILURE');
expect(check.errorMessage).toContain('Version mismatch');
});
it('should return FAILURE when client name is missing', () => {
const invalidRequest = {
protocolVersion: '2025-06-18',
clientInfo: {
version: '1.0.0'
}
};
const check = createClientInitializationCheck(invalidRequest);
expect(check.status).toBe('FAILURE');
expect(check.errorMessage).toContain('Client name missing');
});
it('should return FAILURE when client version is missing', () => {
const invalidRequest = {
protocolVersion: '2025-06-18',
clientInfo: {
name: 'TestClient'
}
};
const check = createClientInitializationCheck(invalidRequest);
expect(check.status).toBe('FAILURE');
expect(check.errorMessage).toContain('Client version missing');
});
it('should support custom expected spec version', () => {
const request = {
protocolVersion: '2024-11-05',
clientInfo: {
name: 'TestClient',
version: '1.0.0'
}
};
const check = createClientInitializationCheck(request, '2024-11-05');
expect(check.status).toBe('SUCCESS');
expect(check.errorMessage).toBeUndefined();
});
});

47
src/checks/client.ts Normal file
View file

@ -0,0 +1,47 @@
import { ConformanceCheck, CheckStatus } from '../types.js';
export function createServerInfoCheck(serverInfo: { name: string; version: string }): ConformanceCheck {
return {
id: 'server-info',
name: 'ServerInfo',
description: 'Test server info returned to client',
status: 'INFO',
timestamp: new Date().toISOString(),
specReferences: [{ id: 'MCP-Lifecycle', url: 'https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle' }],
details: {
serverName: serverInfo.name,
serverVersion: serverInfo.version
}
};
}
export function createClientInitializationCheck(initializeRequest: any, expectedSpecVersion: string = '2025-06-18'): ConformanceCheck {
const protocolVersionSent = initializeRequest?.protocolVersion;
const versionMatch = protocolVersionSent === expectedSpecVersion;
const errors: string[] = [];
if (!protocolVersionSent) errors.push('Protocol version not provided');
if (!versionMatch) errors.push(`Version mismatch: expected ${expectedSpecVersion}, got ${protocolVersionSent}`);
if (!initializeRequest?.clientInfo?.name) errors.push('Client name missing');
if (!initializeRequest?.clientInfo?.version) errors.push('Client version missing');
const status: CheckStatus = errors.length === 0 ? 'SUCCESS' : 'FAILURE';
return {
id: 'mcp-client-initialization',
name: 'MCPClientInitialization',
description: 'Validates that MCP client properly initializes with server',
status,
timestamp: new Date().toISOString(),
specReferences: [{ id: 'MCP-Lifecycle', url: 'https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle' }],
details: {
protocolVersionSent,
expectedSpecVersion,
versionMatch,
clientName: initializeRequest?.clientInfo?.name,
clientVersion: initializeRequest?.clientInfo?.version
},
errorMessage: errors.length > 0 ? errors.join('; ') : undefined,
logs: errors.length > 0 ? errors : undefined
};
}

7
src/checks/index.ts Normal file
View file

@ -0,0 +1,7 @@
// Namespaced exports for client and server checks
import * as client from './client.js';
import * as server from './server.js';
export const clientChecks = client;
export const serverChecks = server;

36
src/checks/server.ts Normal file
View file

@ -0,0 +1,36 @@
import { ConformanceCheck, CheckStatus } from '../types.js';
export function createServerInitializationCheck(initializeResponse: any, expectedSpecVersion: string = '2025-06-18'): ConformanceCheck {
const result = initializeResponse?.result;
const protocolVersion = result?.protocolVersion;
const serverInfo = result?.serverInfo;
const capabilities = result?.capabilities;
const errors: string[] = [];
if (!initializeResponse?.jsonrpc) errors.push('Missing jsonrpc field');
if (!initializeResponse?.id) errors.push('Missing id field');
if (!result) errors.push('Missing result field');
if (!protocolVersion) errors.push('Missing protocolVersion in result');
if (protocolVersion !== expectedSpecVersion) errors.push(`Protocol version mismatch: expected ${expectedSpecVersion}, got ${protocolVersion}`);
if (!serverInfo) errors.push('Missing serverInfo in result');
if (!serverInfo?.name) errors.push('Missing server name in serverInfo');
if (!serverInfo?.version) errors.push('Missing server version in serverInfo');
if (capabilities === undefined) errors.push('Missing capabilities in result');
const status: CheckStatus = errors.length === 0 ? 'SUCCESS' : 'FAILURE';
return {
id: 'mcp-server-initialization',
name: 'MCPServerInitialization',
description: 'Validates that MCP server properly responds to initialize request',
status,
timestamp: new Date().toISOString(),
specReferences: [{ id: 'MCP-Lifecycle', url: 'https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle' }],
details: {
expectedSpecVersion,
response: initializeResponse
},
errorMessage: errors.length > 0 ? errors.join('; ') : undefined,
logs: errors.length > 0 ? errors : undefined
};
}