Skip to main content
Glama
dev-tools-list.test.ts3.58 kB
import { describe, expect, it } from '@jest/globals'; import { spawn } from 'child_process'; import path from 'path'; const hasTeamCityEnv = Boolean( (process.env['TEAMCITY_URL'] ?? process.env['TEAMCITY_SERVER_URL']) && (process.env['TEAMCITY_TOKEN'] ?? process.env['TEAMCITY_API_TOKEN']) ); // Expected dev-mode tools as per docs/mcp-tools-mode-matrix.md const EXPECTED_DEV_TOOLS = new Set([ 'ping', // Projects 'list_projects', 'get_project', 'list_project_hierarchy', // Builds 'list_builds', 'get_build', 'trigger_build', 'cancel_queued_build', 'get_build_status', 'fetch_build_log', 'get_build_results', 'download_build_artifact', 'download_build_artifacts', 'analyze_build_problems', // Changes & diagnostics 'list_changes', 'list_problems', 'list_problem_occurrences', 'list_investigations', 'list_muted_tests', 'get_versioned_settings_status', // Build Configs 'list_build_configs', 'get_build_config', // Tests 'list_test_failures', 'get_test_details', // VCS 'list_vcs_roots', 'get_vcs_root', // Queue 'list_queued_builds', // Server 'get_server_info', 'check_teamcity_connection', 'check_availability_guard', // Agents (read-only) 'list_agents', 'list_agent_pools', 'get_agent_enabled_info', // Users & roles 'list_users', 'list_roles', // Compatibility (read-only) 'get_compatible_build_types_for_agent', 'get_incompatible_build_types_for_agent', 'get_compatible_agents_for_build_type', 'count_compatible_agents_for_build_type', 'get_compatible_agents_for_queued_build', // Branches & Params 'list_branches', 'list_parameters', ]); describe('Dev mode tool surface', () => { it('matches the expected dev-mode tool set exactly', async () => { if (!hasTeamCityEnv) { return expect(true).toBe(true); } // Invoke the e2e CLI directly via tsx to avoid ESM import issues in tests const tsx = path.resolve(process.cwd(), 'node_modules/tsx/dist/cli.cjs'); const entry = path.resolve(process.cwd(), 'tests/e2e/index.ts'); const child = spawn(process.execPath, [tsx, entry, 'tools', '--mode', 'dev'], { env: { ...process.env }, stdio: ['ignore', 'pipe', 'pipe'], }); const chunks: Buffer[] = []; await new Promise<void>((resolve, reject) => { child.stdout.on('data', (c: Buffer) => chunks.push(c)); const errs: Buffer[] = []; child.stderr.on('data', (c: Buffer) => errs.push(c)); child.on('error', reject); child.on('close', (code) => { if (code !== 0) { console.error(Buffer.concat(errs).toString('utf8')); reject(new Error(`Process exited with code ${code}`)); } else resolve(); }); }); // Output is multiple JSON objects; take the last complete JSON block const out = Buffer.concat(chunks).toString('utf8'); const matches = out.match(/\{[\s\S]*\}/g) ?? []; const last = matches[matches.length - 1] ?? '{}'; const parsed = JSON.parse(last) as { tools?: string[] }; const tools = parsed.tools ?? []; const actual = new Set(tools); // Compare symmetric difference for helpful diff on failure const missing = [...EXPECTED_DEV_TOOLS].filter((t) => !actual.has(t)); const extra = [...actual].filter((t) => !EXPECTED_DEV_TOOLS.has(t)); if (missing.length || extra.length) { // Provide readable assertion output console.error('Dev tools mismatch', { missing, extra, actual: tools }); } expect(missing).toEqual([]); expect(extra).toEqual([]); }, 120000); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Daghis/teamcity-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server