Files
proffesor-for-testing__agen…/tests/integration/opencode/mcp-opencode.test.ts
Dragan Spiridonov 4e513b431d fix: resolve 3 P0 blockers and CI failures from QE v3.8.13 audit
- Delete dead MCP server.ts (911 lines, never used in production — entry.ts
  imports MCPProtocolServer). Add legacy aliases in index.ts for backwards compat.
- Fix ESLint: rename .eslintrc.js to .eslintrc.cjs (CommonJS in ESM project)
- Fix hardcoded version '3.0.0' in protocol-server.ts and http-server.ts —
  now reads dynamically from package.json
- Fix vitest process hang: add worker-level afterAll force-exit (setup-worker.ts)
  and global teardown safety net. Native modules (better-sqlite3, hnswlib-node)
  held open handles preventing fork worker exit.
- Add test gate to npm-publish.yml — 194 unit test files must pass before publish
- Disable benchmark.yml release trigger (benchmarks/suite.ts doesn't exist)
- Remove continue-on-error from test steps in optimized-ci.yml (was masking failures)
- Add getToolDefinitions() to MCPProtocolServer for test introspection
- Update e2e and integration tests to use production server API

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 16:51:59 +00:00

112 lines
4.2 KiB
TypeScript

/**
* AQE MCP Server - OpenCode Compatibility Integration Tests
*
* Validates that the AQE MCP server exposes a tool surface compatible
* with OpenCode's agent/skill/tool consumption model:
* - tools/list returns all registered tools with valid schemas
* - Tool output stays within OpenCode's token budget
* - Health endpoint returns structured status
* - MCP config template is valid JSON
*
* Note: These tests use ToolRegistry directly. The production server
* (MCPProtocolServer) registers the same tools but exposes them via
* JSON-RPC over stdio, which requires a full transport layer to test.
*/
import { describe, it, expect, beforeEach } from 'vitest';
import { MCPProtocolServer, createMCPProtocolServer } from '../../../src/mcp/protocol-server';
describe('AQE MCP Server - OpenCode Compatibility', () => {
let server: MCPProtocolServer;
beforeEach(() => {
server = createMCPProtocolServer();
});
// -------------------------------------------------------------------------
// T1-1: Tool listing
// -------------------------------------------------------------------------
it('should list all registered tools via tool registry', async () => {
const tools = server.getToolDefinitions();
// The AQE MCP server registers tools across multiple categories.
// Total varies as features are added. Verify a reasonable minimum.
expect(tools.length).toBeGreaterThanOrEqual(30);
// Every tool must have a name
for (const tool of tools) {
expect(tool.name).toBeDefined();
expect(typeof tool.name).toBe('string');
expect(tool.name.length).toBeGreaterThan(0);
}
});
// -------------------------------------------------------------------------
// T1-2: Tool input schemas
// -------------------------------------------------------------------------
it('should return valid tool input schemas for OpenCode consumption', async () => {
const tools = server.getToolDefinitions();
for (const tool of tools) {
// Every tool must have a description (OpenCode displays this in the tool panel)
expect(tool.description).toBeDefined();
expect(typeof tool.description).toBe('string');
expect(tool.description.length).toBeGreaterThan(0);
// Every tool must have parameters defined
expect(tool.parameters).toBeDefined();
expect(Array.isArray(tool.parameters)).toBe(true);
// Each parameter must have name, type, and description
for (const param of tool.parameters) {
expect(param.name).toBeDefined();
expect(typeof param.name).toBe('string');
expect(param.type).toBeDefined();
expect(typeof param.description).toBe('string');
}
}
});
// -------------------------------------------------------------------------
// T1-5: Tool categories cover expected domains
// -------------------------------------------------------------------------
it('should have tools in all expected categories', async () => {
const tools = server.getToolDefinitions();
const categories = new Set(tools.map((t) => t.category));
// OpenCode agents rely on these tool categories being present
const expectedCategories = ['core', 'task', 'agent', 'domain', 'memory'];
for (const cat of expectedCategories) {
expect(categories.has(cat), `Missing tool category: ${cat}`).toBe(true);
}
});
// -------------------------------------------------------------------------
// T1-7: MCP config template validation
// -------------------------------------------------------------------------
it('should have valid opencode.json MCP config template', async () => {
const mcpConfig = {
mcpServers: {
'agentic-qe': {
command: 'npx',
args: ['@agentic-qe/v3', 'mcp'],
},
},
};
expect(mcpConfig.mcpServers).toBeDefined();
expect(mcpConfig.mcpServers['agentic-qe']).toBeDefined();
expect(mcpConfig.mcpServers['agentic-qe'].command).toBe('npx');
expect(mcpConfig.mcpServers['agentic-qe'].args).toContain('mcp');
const serialized = JSON.stringify(mcpConfig);
const parsed = JSON.parse(serialized);
expect(parsed.mcpServers['agentic-qe'].command).toBe('npx');
expect(parsed.mcpServers['agentic-qe'].args).toContain('mcp');
});
});