import { describe, it, expect, beforeAll } from 'vitest'; import { pool } from '../../lib/db/pool.js'; import { resetDb } from '../helpers/db.js'; import { migrateUp } from '../../lib/db/migrate.js'; import { listMcpTools, callMcpTool } from '../../lib/mcp/companion-stdio.js'; let spaceId, agentId; beforeAll(async () => { await resetDb(); await migrateUp(); ({ rows: [{ id: spaceId }] } = await pool.query( `INSERT INTO spaces(slug,name) VALUES('mcp-test','MCP Test') RETURNING id` )); ({ rows: [{ id: agentId }] } = await pool.query( `SELECT id FROM agents WHERE slug='companion'` )); }); const suggestAgent = (id) => ({ kind: 'agent', id, capabilities: { read: true, suggest: true, write: false }, scopes: {} }); describe('listMcpTools()', () => { it('returns exactly the five companion tools sorted by name', () => { const tools = listMcpTools(); expect(tools.map(t => t.name).sort()).toEqual(['context', 'propose_change', 'propose_improvement', 'read', 'search']); }); it('each tool has name, description, and input_schema', () => { const tools = listMcpTools(); for (const t of tools) { expect(t.name).toBeTruthy(); expect(t.description).toBeTruthy(); expect(t.input_schema).toBeTruthy(); expect(t.input_schema.type).toBe('object'); } }); }); describe('callMcpTool()', () => { it('propose_change writes a pending_changes row (pending) and returns applied:false', async () => { const ctx = { agent: suggestAgent(agentId), space_id: spaceId }; const result = await callMcpTool( 'propose_change', { entity_type: 'task', action: 'create', payload: { space_id: spaceId, title: 'MCP test task' } }, ctx ); expect(result.pending_change_id).toBeTruthy(); expect(result.applied).toBe(false); // Check DB: the row exists and is pending const { rows } = await pool.query( `SELECT * FROM pending_changes WHERE id=$1`, [result.pending_change_id] ); expect(rows).toHaveLength(1); expect(rows[0].status).toBe('pending'); expect(rows[0].agent_id).toBe(agentId); // The task was NOT created const { rows: tasks } = await pool.query( `SELECT * FROM tasks WHERE title='MCP test task'` ); expect(tasks).toHaveLength(0); }); });