UNPKG

@kedoupi/wecombot-mcp

Version:

A Model Context Protocol (MCP) server for WeChat Work (企业微信) group bot integration

158 lines 6.65 kB
import { describe, it, beforeEach, afterEach } from 'node:test'; import assert from 'node:assert'; import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'; import nock from 'nock'; describe('MCP Server Integration', () => { let server; const originalEnv = process.env.WECOM_WEBHOOK_URL; beforeEach(() => { process.env.WECOM_WEBHOOK_URL = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=test-key'; server = new Server({ name: 'wecombot-mcp', version: '1.0.0', }, { capabilities: { tools: {}, }, }); // Setup handlers (simplified version of the actual server) server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { 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'], }, }, ], }; }); nock.cleanAll(); }); afterEach(() => { process.env.WECOM_WEBHOOK_URL = originalEnv; nock.cleanAll(); }); describe('ListTools', () => { it('should return available tools', async () => { const result = await server.request({ method: 'tools/list' }, ListToolsRequestSchema); assert.strictEqual(result.tools.length, 1); assert.strictEqual(result.tools[0].name, 'send_wecom_message'); assert.ok(result.tools[0].description.includes('WeChat Work')); // Validate schema structure const schema = result.tools[0].inputSchema; assert.strictEqual(schema.type, 'object'); assert.ok(schema.properties); assert.ok(schema.properties.message_type); assert.ok(schema.properties.content); assert.deepStrictEqual(schema.required, ['message_type', 'content']); }); }); describe('Tool Parameter Validation', () => { it('should validate message_type enum values', () => { const schema = { type: 'object', properties: { message_type: { type: 'string', enum: ['text', 'markdown', 'image', 'news'], }, content: { type: 'string', }, }, required: ['message_type', 'content'], }; // Test valid enum values const validTypes = ['text', 'markdown', 'image', 'news']; validTypes.forEach(type => { assert.ok(schema.properties.message_type.enum.includes(type)); }); // Verify enum length assert.strictEqual(schema.properties.message_type.enum.length, 4); }); it('should have correct required fields', () => { const schema = { type: 'object', properties: { message_type: { type: 'string' }, content: { type: 'string' }, mentioned_list: { type: 'array' }, }, required: ['message_type', 'content'], }; assert.deepStrictEqual(schema.required, ['message_type', 'content']); assert.strictEqual(schema.required.length, 2); }); }); describe('Error Handling', () => { it('should handle missing environment variable', async () => { delete process.env.WECOM_WEBHOOK_URL; try { // This would be handled in the actual CallTool handler const webhookUrl = process.env.WECOM_WEBHOOK_URL; if (!webhookUrl) { throw new Error('WECOM_WEBHOOK_URL environment variable is required'); } assert.fail('Should have thrown an error'); } catch (error) { assert.ok(error instanceof Error); assert.ok(error.message.includes('WECOM_WEBHOOK_URL')); } }); it('should validate webhook URL format', () => { const validUrl = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=test-key'; const invalidUrls = [ 'http://example.com', 'not-a-url', 'https://wrong-domain.com/webhook', '', ]; // Test valid URL assert.ok(validUrl.startsWith('https://qyapi.weixin.qq.com')); // Test invalid URLs invalidUrls.forEach(url => { assert.ok(!url.startsWith('https://qyapi.weixin.qq.com')); }); }); }); describe('MCP Protocol Compliance', () => { it('should use correct MCP server metadata', () => { const serverInfo = { name: 'wecombot-mcp', version: '1.0.0', }; assert.strictEqual(serverInfo.name, 'wecombot-mcp'); assert.match(serverInfo.version, /^\d+\.\d+\.\d+$/); }); it('should declare correct capabilities', () => { const capabilities = { tools: {}, }; assert.ok(capabilities.tools !== undefined); assert.strictEqual(typeof capabilities.tools, 'object'); }); }); }); //# sourceMappingURL=mcp-server.test.js.map