@kedoupi/wecombot-mcp
Version:
A Model Context Protocol (MCP) server for WeChat Work (企业微信) group bot integration
246 lines • 10.6 kB
JavaScript
import { describe, it } from 'node:test';
import assert from 'node:assert';
describe('MCP Protocol Compatibility', () => {
describe('Tool Definition Compliance', () => {
it('should have valid tool definition structure', () => {
const toolDefinition = {
name: 'send_wecom_message',
description: 'Send message to WeChat Work group via webhook',
inputSchema: {
type: 'object',
properties: {
message_type: {
type: 'string',
enum: ['text', 'markdown', 'image', 'news'],
description: 'Type of message to send',
},
content: {
type: 'string',
description: 'Message content (text/markdown) or base64 image data',
},
mentioned_list: {
type: 'array',
items: { type: 'string' },
description: 'List of users to mention (@all for everyone)',
},
},
required: ['message_type', 'content'],
},
};
// Validate required fields
assert.ok(toolDefinition.name);
assert.ok(toolDefinition.description);
assert.ok(toolDefinition.inputSchema);
// Validate name format (should be valid identifier)
assert.match(toolDefinition.name, /^[a-zA-Z_][a-zA-Z0-9_]*$/);
// Validate description is meaningful
assert.ok(toolDefinition.description.length > 10);
// Validate input schema is JSON Schema compliant
assert.strictEqual(toolDefinition.inputSchema.type, 'object');
assert.ok(toolDefinition.inputSchema.properties);
assert.ok(Array.isArray(toolDefinition.inputSchema.required));
});
it('should have JSON Schema compliant input schema', () => {
const schema = {
type: 'object',
properties: {
message_type: {
type: 'string',
enum: ['text', 'markdown', 'image', 'news'],
description: 'Type of message to send',
},
content: {
type: 'string',
description: 'Message content (text/markdown) or base64 image data',
},
mentioned_list: {
type: 'array',
items: { type: 'string' },
description: 'List of users to mention (@all for everyone)',
},
},
required: ['message_type', 'content'],
};
// Validate top-level schema
assert.strictEqual(schema.type, 'object');
assert.ok(schema.properties);
assert.ok(Array.isArray(schema.required));
// Validate each property
Object.values(schema.properties).forEach(prop => {
assert.ok(prop.type);
assert.ok(prop.description);
});
// Validate enum constraint
assert.ok(Array.isArray(schema.properties.message_type.enum));
assert.ok(schema.properties.message_type.enum.length > 0);
// Validate array schema
assert.ok(schema.properties.mentioned_list.items);
assert.strictEqual(schema.properties.mentioned_list.items.type, 'string');
});
});
describe('Request/Response Format Compliance', () => {
it('should handle ListTools request format', () => {
const request = {
method: 'tools/list',
params: {},
};
// Validate request structure matches MCP spec
assert.strictEqual(request.method, 'tools/list');
assert.ok(request.params !== undefined);
});
it('should handle CallTool request format', () => {
const request = {
method: 'tools/call',
params: {
name: 'send_wecom_message',
arguments: {
message_type: 'text',
content: 'Test message',
},
},
};
// Validate request structure
assert.strictEqual(request.method, 'tools/call');
assert.ok(request.params.name);
assert.ok(request.params.arguments);
assert.strictEqual(typeof request.params.arguments, 'object');
});
it('should return proper CallTool response format', () => {
const response = {
content: [
{
type: 'text',
text: 'Message sent successfully to WeChat Work group. Type: text',
},
],
};
// Validate response structure
assert.ok(Array.isArray(response.content));
assert.ok(response.content.length > 0);
assert.strictEqual(response.content[0].type, 'text');
assert.ok(response.content[0].text);
});
});
describe('Error Handling Compliance', () => {
it('should use standard MCP error codes', () => {
const errorCodes = {
ParseError: -32700,
InvalidRequest: -32600,
MethodNotFound: -32601,
InvalidParams: -32602,
InternalError: -32603,
};
// Validate error codes match MCP specification
assert.strictEqual(errorCodes.ParseError, -32700);
assert.strictEqual(errorCodes.InvalidRequest, -32600);
assert.strictEqual(errorCodes.MethodNotFound, -32601);
assert.strictEqual(errorCodes.InvalidParams, -32602);
assert.strictEqual(errorCodes.InternalError, -32603);
});
it('should format error responses correctly', () => {
const errorResponse = {
error: {
code: -32602,
message: 'Invalid params',
data: {
details: 'message_type is required',
},
},
};
// Validate error response structure
assert.ok(errorResponse.error);
assert.ok(typeof errorResponse.error.code === 'number');
assert.ok(errorResponse.error.message);
assert.ok(errorResponse.error.code < 0); // MCP error codes are negative
});
});
describe('Client Compatibility', () => {
it('should be compatible with Claude Desktop config format', () => {
const config = {
mcpServers: {
wecombot: {
command: 'node',
args: ['dist/index.js'],
env: {
WECOM_WEBHOOK_URL: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=test',
},
},
},
};
// Validate config structure
assert.ok(config.mcpServers);
assert.ok(config.mcpServers.wecombot);
assert.ok(config.mcpServers.wecombot.command);
assert.ok(Array.isArray(config.mcpServers.wecombot.args));
assert.ok(config.mcpServers.wecombot.env);
});
it('should be compatible with Continue/Cline config format', () => {
const config = {
mcpServers: [
{
name: 'wecombot',
command: 'node',
args: ['dist/index.js'],
env: {
WECOM_WEBHOOK_URL: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=test',
},
},
],
};
// Validate array-based config structure
assert.ok(Array.isArray(config.mcpServers));
assert.ok(config.mcpServers[0].name);
assert.ok(config.mcpServers[0].command);
assert.ok(Array.isArray(config.mcpServers[0].args));
});
});
describe('Transport Compatibility', () => {
it('should support stdio transport', () => {
const transportConfig = {
type: 'stdio',
command: 'node',
args: ['dist/index.js'],
};
// Validate stdio transport config
assert.strictEqual(transportConfig.type, 'stdio');
assert.ok(transportConfig.command);
assert.ok(Array.isArray(transportConfig.args));
});
it('should handle environment variable configuration', () => {
const envConfig = {
WECOM_WEBHOOK_URL: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=test',
};
// Validate environment variable format
assert.ok(envConfig.WECOM_WEBHOOK_URL);
assert.ok(envConfig.WECOM_WEBHOOK_URL.startsWith('https://'));
assert.ok(envConfig.WECOM_WEBHOOK_URL.includes('key='));
});
});
describe('Protocol Version Compatibility', () => {
it('should support MCP version 1.0', () => {
const serverInfo = {
protocolVersion: '1.0.0',
capabilities: {
tools: {},
},
};
// Validate protocol version
assert.match(serverInfo.protocolVersion, /^1\.0\.\d+$/);
assert.ok(serverInfo.capabilities);
assert.ok(serverInfo.capabilities.tools !== undefined);
});
it('should declare proper server capabilities', () => {
const capabilities = {
tools: {},
// Note: We don't support these capabilities in this server
// resources: undefined,
// prompts: undefined,
// logging: undefined,
};
// Validate only supported capabilities are declared
assert.ok(capabilities.tools !== undefined);
assert.strictEqual(Object.keys(capabilities).length, 1);
});
});
});
//# sourceMappingURL=compatibility.test.js.map