23f7624596
ADR-166 MCP Bridge Security Lock / Static-source security lock (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / Compose default binds loopback + Mongo has auth (push) Failing after 2s
CodeQL Advanced / Analyze (rust) (push) Failing after 0s
ADR-166 MCP Bridge Security Lock / plugin-agent-federation bindHost default (push) Failing after 1s
ADR-166 MCP Bridge Security Lock / Runtime behavior — 401 + terminal gate + fail-closed (push) Failing after 4s
business-pods-smoke / smoke (push) Failing after 1s
all-plugins-smoke / smoke-all (push) Failing after 2s
CI/CD Pipeline / Security & Code Quality (push) Failing after 1s
CI/CD Pipeline / Test Suite (ubuntu-latest) (push) Failing after 1s
CI/CD Pipeline / Build & Package (macos-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (ubuntu-latest) (push) Has been skipped
CI/CD Pipeline / Build & Package (windows-latest) (push) Has been skipped
CI/CD Pipeline / Documentation & Examples (push) Failing after 1s
Clone Tracker (14-day rolling) / Snapshot clones for ruflo ecosystem (push) Failing after 1s
CodeQL Advanced / Analyze (actions) (push) Failing after 1s
CodeQL Advanced / Analyze (javascript-typescript) (push) Failing after 1s
federation-peer-rust / stable-noop (push) Failing after 1s
metaharness-ci / score (push) Failing after 1s
metaharness-ci / router-compat (push) Failing after 0s
metaharness-ci / similarity-tests (push) Failing after 0s
no-agentbbs-smoke / smoke-without-agentbbs (push) Failing after 1s
V3 CI/CD Pipeline / Build V3 (windows-latest) (push) Has been skipped
codex-integration-audit / Codex integration audit (push) Failing after 1s
helpers-manifest-guard / guard (push) Failing after 1s
🔗 Cross-Agent Integration Tests / 🤝 Agent Coordination Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🧠 Memory Sharing Integration (push) Has been skipped
🔗 Cross-Agent Integration Tests / 🛡️ Fault Tolerance Tests (push) Has been skipped
🔗 Cross-Agent Integration Tests / ⚡ Performance Integration Tests (push) Has been skipped
metaharness-ci / mcp-scan (push) Failing after 1s
metaharness-ci / eject-dryrun (push) Failing after 1s
metaharness-ci / metaharness-real-data (push) Failing after 0s
no-cli-optdep-bloat-2561 / guard (push) Failing after 1s
no-metaharness-smoke / smoke-without-metaharness (push) Failing after 1s
no-phantom-agentic-flow-subpath / guard (push) Failing after 1s
🔄 Automated Rollback Manager / 🚨 Failure Detection (push) Failing after 1s
V3 CI/CD Pipeline / Plugin hooks smoke / ubuntu-latest / Node 22 (push) Failing after 1s
V3 CI/CD Pipeline / ruflo-graph-intelligence build + test smoke (#2044, ADR-123) (push) Failing after 1s
CVE Audit Gate / Audit root (critical-blocking) (push) Failing after 2s
cost-tracker-smoke / smoke (push) Failing after 3s
oia-audit-weekly / audit (push) Failing after 2s
ruflo-agent-smoke / ruflo-agent structural smoke (push) Failing after 1s
📊 Status Badges Update / 📊 Update Status Badges (push) Failing after 1s
V3 CI/CD Pipeline / Static regression guards (#2267 YAML + (push) Failing after 1s
V3 CI/CD Pipeline / Test V3 Packages (push) Failing after 0s
V3 CI/CD Pipeline / agent_execute provider routing smoke (#2042) (push) Failing after 0s
CVE Audit Gate / Audit v3 (critical-blocking) (push) Failing after 1s
federation-peer-rust / stable-native (push) Failing after 2s
🔗 Cross-Agent Integration Tests / 🚀 Integration Test Setup (push) Failing after 2s
neural-trader-smoke / runtime-smoke (push) Failing after 1s
V3 CI/CD Pipeline / Build V3 (macos-latest) (push) Has been skipped
V3 CI/CD Pipeline / Build V3 (ubuntu-latest) (push) Has been skipped
V3 CI/CD Pipeline / Type Check V3 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 24 (push) Failing after 1s
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / ubuntu-latest / Node 22 (push) Failing after 2s
V3 CI/CD Pipeline / browser rvf create flag smoke (#2015) (push) Failing after 0s
V3 CI/CD Pipeline / Dependency review (#2046) (push) Has been skipped
V3 CI/CD Pipeline / Supply-chain audit (#2046) (push) Failing after 0s
V3 CI/CD Pipeline / witness marker drift smoke (#2021) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader portfolio CG smoke (#2068, ADR-126 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / neural-trader backtest signing smoke (#2068, ADR-126 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / kg-extract type-import classification smoke (#2049) (push) Failing after 0s
V3 CI/CD Pipeline / witness verify precondition smoke (#1880) (push) Failing after 2s
V3 CI/CD Pipeline / neural-trader pipeline risk-gate smoke (#2068, ADR-126 Phase 5) (push) Failing after 0s
V3 CI/CD Pipeline / neural-trader feature attribution smoke (#2068, ADR-126 Phase 6) (push) Failing after 0s
V3 CI/CD Pipeline / plugin-registry signature verification smoke (#1922, CWE-347) (push) Failing after 4s
V3 CI/CD Pipeline / memory stats legacy-DB smoke (#2120) (push) Failing after 4s
V3 CI/CD Pipeline / github deprecated actions smoke (#2089, ADR-127 Phase 3) (push) Failing after 1s
V3 CI/CD Pipeline / graph query + pathfinder smoke (ADR-130 P2+P5) (push) Has been skipped
V3 CI/CD Pipeline / graph trajectory hooks smoke (ADR-130 P3) (push) Has been skipped
V3 CI/CD Pipeline / graph plugin adapter smoke (ADR-130 P4) (push) Has been skipped
V3 CI/CD Pipeline / graph benchmark (ADR-130 P6) (push) Has been skipped
V3 CI/CD Pipeline / statusline generator delegation smoke (#2195) (push) Failing after 1s
V3 CI/CD Pipeline / wizard init regression guard (#2206 (push) Failing after 1s
V3 CI/CD Pipeline / memory no-stray-db smoke (ADR-125 P7) (push) Failing after 1s
V3 CI/CD Pipeline / github-safe injection smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github actions pin smoke (#2089, ADR-127 Phase 1) (push) Failing after 1s
V3 CI/CD Pipeline / github attribution opt-in smoke (#2089, ADR-127 Phase 4) (push) Failing after 1s
V3 CI/CD Pipeline / pre-bash hook safety smoke (#2017) (push) Failing after 1s
V3 CI/CD Pipeline / Memory import smoke / ubuntu-latest (push) Failing after 0s
V3 CI/CD Pipeline / MCP protocol smoke / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / ruvllm WASM auto-init smoke (#2086) (push) Failing after 4s
V3 CI/CD Pipeline / MCP paired-tool round-trip smoke (#1889) (push) Failing after 1s
V3 CI/CD Pipeline / Plugin package install-safety (#1902/#1903/#1904) (push) Failing after 1s
V3 CI/CD Pipeline / Tool description discoverability (ADR-112) (push) Failing after 3s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (22) (push) Failing after 1s
V3 CI/CD Pipeline / CLI npx-install smoke (#1147 / (24) (push) Failing after 1s
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / ubuntu-latest (push) Failing after 2s
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / ubuntu-latest (push) Failing after 1s
V3 CI/CD Pipeline / Vector-index dimension audit (#1947) (push) Failing after 0s
V3 CI/CD Pipeline / Hook-command install safety (#1921) (push) Failing after 1s
V3 CI/CD Pipeline / ToolOutputGuardrail smoke (ADR-131, (push) Failing after 1s
V3 CI/CD Pipeline / init-bundle invariants smoke (#2095, ADR-128 Phase 5) (push) Failing after 1s
V3 CI/CD Pipeline / wasm provider bridge smoke (ADR-129 P1) (push) Failing after 2s
V3 CI/CD Pipeline / wasm gallery CRUD smoke (ADR-129 P3) (push) Failing after 1s
V3 CI/CD Pipeline / wasm plugin bridge smoke (ADR-129 P4) (push) Failing after 0s
V3 CI/CD Pipeline / wasm compose smoke (ADR-129 P2) (push) Failing after 4s
V3 CI/CD Pipeline / graph schema smoke (ADR-130 P1) (push) Failing after 0s
Validate Marketplace / validate (push) Failing after 1s
🔍 Verification Pipeline / 🚀 Setup Verification (push) Failing after 1s
🔍 Verification Pipeline / 🛡️ Security Verification (push) Has been skipped
🔍 Verification Pipeline / 📝 Code Quality (push) Has been skipped
🔍 Verification Pipeline / 🧪 Test Verification (${{ matrix.os }}, Node ${{ matrix.node }}) (push) Has been skipped
🔍 Verification Pipeline / 🏗️ Build Verification (push) Has been skipped
🔍 Verification Pipeline / 📚 Documentation Verification (push) Has been skipped
CVE Audit Gate / High-severity report (warn only) (push) Has been cancelled
🔄 Automated Rollback Manager / 🔄 Execute Rollback (push) Has been cancelled
🔄 Automated Rollback Manager / ✅ Post-Rollback Verification (push) Has been cancelled
🔄 Automated Rollback Manager / 📊 Rollback Monitoring (push) Has been cancelled
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook execution smoke (#2132) / windows-latest (push) Has been cancelled
🔄 Automated Rollback Manager / ⏳ Manual Rollback Approval (push) Has been cancelled
V3 CI/CD Pipeline / MCP protocol smoke / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Memory import smoke / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows hook shim smoke (#2132) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Windows init hooks smoke (#2132) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / macos-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / ubuntu-latest (push) Has been cancelled
V3 CI/CD Pipeline / Witness verify (signed manifest) / windows-latest (push) Has been cancelled
V3 CI/CD Pipeline / Publish to npm (alpha) (push) Has been cancelled
V3 CI/CD Pipeline / Smoke (no better-sqlite3) / macos-latest / Node 22 (push) Has been cancelled
V3 CI/CD Pipeline / Plugin hooks smoke / macos-latest / Node 22 (push) Has been cancelled
CI/CD Pipeline / Deploy & Release (push) Has been cancelled
CI/CD Pipeline / CI Status (push) Has been cancelled
🔗 Cross-Agent Integration Tests / 📊 Integration Test Report (push) Has been cancelled
🔄 Automated Rollback Manager / 🔍 Pre-Rollback Validation (push) Has been cancelled
🔍 Verification Pipeline / ⚡ Performance Verification (push) Has been cancelled
🔍 Verification Pipeline / 📊 Verification Report (push) Has been cancelled
1202 lines
49 KiB
TypeScript
1202 lines
49 KiB
TypeScript
/**
|
|
* Deep MCP Tools Test Suite
|
|
*
|
|
* Comprehensive tests for all MCP tool files covering:
|
|
* - Schema validation (name, description, inputSchema)
|
|
* - Array schemas have `items` field
|
|
* - Handler existence and error handling
|
|
* - Tool registration across all 24 tool modules
|
|
* - System tools version/status correctness
|
|
*
|
|
* Uses vitest with mocks to isolate from external dependencies.
|
|
*/
|
|
|
|
import { describe, it, expect, vi, beforeAll, afterAll } from 'vitest';
|
|
|
|
// ============================================================================
|
|
// Mock setup - must be before imports
|
|
// ============================================================================
|
|
|
|
// Mock fs to prevent actual file I/O during tests
|
|
vi.mock('node:fs', () => {
|
|
const memStore = new Map<string, string>();
|
|
return {
|
|
existsSync: vi.fn((p: string) => memStore.has(p)),
|
|
readFileSync: vi.fn((p: string) => memStore.get(p) || '{}'),
|
|
writeFileSync: vi.fn((p: string, d: string) => memStore.set(p, d)),
|
|
mkdirSync: vi.fn(),
|
|
readdirSync: vi.fn(() => []),
|
|
unlinkSync: vi.fn(),
|
|
statSync: vi.fn(() => ({ size: 100, isFile: () => true, isDirectory: () => false })),
|
|
};
|
|
});
|
|
|
|
vi.mock('fs', () => {
|
|
const memStore = new Map<string, string>();
|
|
return {
|
|
existsSync: vi.fn((p: string) => memStore.has(p)),
|
|
readFileSync: vi.fn((p: string) => memStore.get(p) || '{}'),
|
|
writeFileSync: vi.fn((p: string, d: string) => memStore.set(p, d)),
|
|
mkdirSync: vi.fn(),
|
|
readdirSync: vi.fn(() => []),
|
|
unlinkSync: vi.fn(),
|
|
statSync: vi.fn(() => ({ size: 100, isFile: () => true, isDirectory: () => false })),
|
|
};
|
|
});
|
|
|
|
// Mock child_process for browser/security tools
|
|
vi.mock('child_process', () => ({
|
|
execSync: vi.fn(() => '{}'),
|
|
spawnSync: vi.fn(() => ({ status: 0, stdout: '' })),
|
|
}));
|
|
|
|
// Mock the memory bridge for agentdb tools
|
|
vi.mock('../src/memory/memory-bridge.js', () => ({
|
|
bridgeHealthCheck: vi.fn(async () => ({ available: true, status: 'healthy' })),
|
|
bridgeListControllers: vi.fn(async () => []),
|
|
bridgeStorePattern: vi.fn(async () => ({ success: true })),
|
|
bridgeSearchPatterns: vi.fn(async () => ({ results: [] })),
|
|
bridgeRecordFeedback: vi.fn(async () => ({ success: true })),
|
|
bridgeRecordCausalEdge: vi.fn(async () => ({ success: true })),
|
|
bridgeRouteTask: vi.fn(async () => ({ route: 'general', confidence: 0.5, agents: ['coder'] })),
|
|
bridgeSessionStart: vi.fn(async () => ({ success: true })),
|
|
bridgeSessionEnd: vi.fn(async () => ({ success: true })),
|
|
bridgeHierarchicalStore: vi.fn(async () => ({ success: true })),
|
|
bridgeHierarchicalRecall: vi.fn(async () => ({ results: [] })),
|
|
bridgeConsolidate: vi.fn(async () => ({ success: true })),
|
|
bridgeBatchOperation: vi.fn(async () => ({ success: true })),
|
|
bridgeContextSynthesize: vi.fn(async () => ({ success: true })),
|
|
bridgeSemanticRoute: vi.fn(async () => ({ route: null })),
|
|
}));
|
|
|
|
// Mock memory-initializer
|
|
vi.mock('../src/memory/memory-initializer.js', () => ({
|
|
generateEmbedding: vi.fn(async () => ({ embedding: new Array(384).fill(0.1), dimensions: 384, model: 'mock' })),
|
|
storeEntry: vi.fn(async () => ({ success: true, id: 'mock-id' })),
|
|
searchEntries: vi.fn(async () => ({ success: true, results: [], searchTime: 1 })),
|
|
listEntries: vi.fn(async () => ({ success: true, entries: [] })),
|
|
getEntry: vi.fn(async () => null),
|
|
deleteEntry: vi.fn(async () => ({ success: true })),
|
|
getStats: vi.fn(async () => ({ totalEntries: 0 })),
|
|
initializeDatabase: vi.fn(async () => ({ success: true })),
|
|
initializeMemoryDatabase: vi.fn(async () => ({ success: true })),
|
|
checkMemoryInitialization: vi.fn(async () => ({ initialized: true, version: '3.0.0' })),
|
|
migrateFromLegacy: vi.fn(async () => ({ success: true, migrated: 0 })),
|
|
}));
|
|
|
|
// Mock intelligence module
|
|
vi.mock('../src/memory/intelligence.js', () => ({
|
|
getIntelligenceStats: vi.fn(() => ({
|
|
patternsLearned: 0,
|
|
trajectoriesRecorded: 0,
|
|
reasoningBankSize: 0,
|
|
sonaEnabled: false,
|
|
lastAdaptation: null,
|
|
})),
|
|
initializeIntelligence: vi.fn(async () => {}),
|
|
benchmarkAdaptation: vi.fn(() => ({ avgMs: 0.01, minMs: 0.005, maxMs: 0.02, targetMet: true })),
|
|
}));
|
|
|
|
// Mock ruvector modules
|
|
vi.mock('../src/ruvector/model-router.js', () => ({
|
|
getModelRouter: vi.fn(() => ({ route: async () => ({ model: 'sonnet', routedBy: 'router' }) })),
|
|
}));
|
|
|
|
vi.mock('../src/ruvector/enhanced-model-router.js', () => ({
|
|
getEnhancedModelRouter: vi.fn(() => ({
|
|
route: async () => ({ tier: 2, model: 'sonnet', canSkipLLM: false }),
|
|
})),
|
|
}));
|
|
|
|
vi.mock('../src/ruvector/diff-classifier.js', () => ({
|
|
analyzeDiff: vi.fn(async () => ({
|
|
ref: 'HEAD', timestamp: new Date().toISOString(), files: [],
|
|
risk: { overall: 'low', score: 10 }, classification: { type: 'patch' },
|
|
summary: 'No changes', fileRisks: [], recommendedReviewers: [],
|
|
})),
|
|
assessFileRisk: vi.fn(() => ({ risk: 'low', score: 10, reasons: [] })),
|
|
assessOverallRisk: vi.fn(() => ({ overall: 'low', score: 10 })),
|
|
classifyDiff: vi.fn(() => ({ type: 'patch' })),
|
|
suggestReviewers: vi.fn(() => []),
|
|
getGitDiffNumstat: vi.fn(() => []),
|
|
}));
|
|
|
|
vi.mock('../src/ruvector/moe-router.js', () => ({
|
|
getMoERouter: vi.fn(async () => null),
|
|
}));
|
|
|
|
vi.mock('../src/memory/sona-optimizer.js', () => ({
|
|
getSONAOptimizer: vi.fn(async () => null),
|
|
}));
|
|
|
|
vi.mock('../src/memory/ewc-consolidation.js', () => ({
|
|
getEWCConsolidator: vi.fn(async () => null),
|
|
}));
|
|
|
|
// Mock transfer modules
|
|
vi.mock('../src/transfer/anonymization/index.js', () => ({
|
|
detectPII: vi.fn(() => ({ hasPII: false, entities: [] })),
|
|
}));
|
|
|
|
vi.mock('../src/transfer/ipfs/client.js', () => ({
|
|
resolveIPNS: vi.fn(async () => 'QmMock'),
|
|
}));
|
|
|
|
// Mock module for auto-install
|
|
vi.mock('../src/mcp-tools/auto-install.js', () => ({
|
|
autoInstallPackage: vi.fn(async () => false),
|
|
}));
|
|
|
|
// Mock security package
|
|
vi.mock('@claude-flow/aidefence', () => {
|
|
throw new Error('Cannot find package');
|
|
});
|
|
|
|
// Mock embeddings package
|
|
vi.mock('@claude-flow/embeddings', () => {
|
|
throw new Error('Cannot find package');
|
|
});
|
|
|
|
vi.mock('agentic-flow/reasoningbank', () => {
|
|
throw new Error('Cannot find package');
|
|
});
|
|
|
|
// ============================================================================
|
|
// Import all tool modules (after mocks are set up)
|
|
// ============================================================================
|
|
|
|
import { agentTools } from '../src/mcp-tools/agent-tools.js';
|
|
import { agentdbTools } from '../src/mcp-tools/agentdb-tools.js';
|
|
import { analyzeTools } from '../src/mcp-tools/analyze-tools.js';
|
|
import { browserTools } from '../src/mcp-tools/browser-tools.js';
|
|
import { claimsTools } from '../src/mcp-tools/claims-tools.js';
|
|
import { configTools } from '../src/mcp-tools/config-tools.js';
|
|
import { coordinationTools } from '../src/mcp-tools/coordination-tools.js';
|
|
import { daaTools } from '../src/mcp-tools/daa-tools.js';
|
|
import { embeddingsTools } from '../src/mcp-tools/embeddings-tools.js';
|
|
import { githubTools } from '../src/mcp-tools/github-tools.js';
|
|
import { hiveMindTools } from '../src/mcp-tools/hive-mind-tools.js';
|
|
import { memoryTools } from '../src/mcp-tools/memory-tools.js';
|
|
import { neuralTools } from '../src/mcp-tools/neural-tools.js';
|
|
import { performanceTools } from '../src/mcp-tools/performance-tools.js';
|
|
import { progressTools } from '../src/mcp-tools/progress-tools.js';
|
|
import { securityTools } from '../src/mcp-tools/security-tools.js';
|
|
import { sessionTools } from '../src/mcp-tools/session-tools.js';
|
|
import { swarmTools } from '../src/mcp-tools/swarm-tools.js';
|
|
import { systemTools } from '../src/mcp-tools/system-tools.js';
|
|
import { taskTools } from '../src/mcp-tools/task-tools.js';
|
|
import { terminalTools } from '../src/mcp-tools/terminal-tools.js';
|
|
import { transferTools } from '../src/mcp-tools/transfer-tools.js';
|
|
import { workflowTools } from '../src/mcp-tools/workflow-tools.js';
|
|
import { hooksTools } from '../src/mcp-tools/hooks-tools.js';
|
|
|
|
import type { MCPTool } from '../src/mcp-tools/types.js';
|
|
|
|
// ============================================================================
|
|
// Collect all tool modules
|
|
// ============================================================================
|
|
|
|
interface ToolModule {
|
|
name: string;
|
|
tools: MCPTool[];
|
|
}
|
|
|
|
const ALL_MODULES: ToolModule[] = [
|
|
{ name: 'agent-tools', tools: agentTools },
|
|
{ name: 'agentdb-tools', tools: agentdbTools },
|
|
{ name: 'analyze-tools', tools: analyzeTools },
|
|
{ name: 'browser-tools', tools: browserTools },
|
|
{ name: 'claims-tools', tools: claimsTools },
|
|
{ name: 'config-tools', tools: configTools },
|
|
{ name: 'coordination-tools', tools: coordinationTools },
|
|
{ name: 'daa-tools', tools: daaTools },
|
|
{ name: 'embeddings-tools', tools: embeddingsTools },
|
|
{ name: 'github-tools', tools: githubTools },
|
|
{ name: 'hive-mind-tools', tools: hiveMindTools },
|
|
{ name: 'hooks-tools', tools: hooksTools },
|
|
{ name: 'memory-tools', tools: memoryTools },
|
|
{ name: 'neural-tools', tools: neuralTools },
|
|
{ name: 'performance-tools', tools: performanceTools },
|
|
{ name: 'progress-tools', tools: progressTools },
|
|
{ name: 'security-tools', tools: securityTools },
|
|
{ name: 'session-tools', tools: sessionTools },
|
|
{ name: 'swarm-tools', tools: swarmTools },
|
|
{ name: 'system-tools', tools: systemTools },
|
|
{ name: 'task-tools', tools: taskTools },
|
|
{ name: 'terminal-tools', tools: terminalTools },
|
|
{ name: 'transfer-tools', tools: transferTools },
|
|
{ name: 'workflow-tools', tools: workflowTools },
|
|
];
|
|
|
|
const ALL_TOOLS: MCPTool[] = ALL_MODULES.flatMap(m => m.tools);
|
|
|
|
// ============================================================================
|
|
// Tests
|
|
// ============================================================================
|
|
|
|
describe('MCP Tools Deep Test Suite', () => {
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 1. Module Loading & Registration
|
|
// --------------------------------------------------------------------------
|
|
describe('Module Loading & Registration', () => {
|
|
it('should load all 24 tool modules', () => {
|
|
expect(ALL_MODULES).toHaveLength(24);
|
|
});
|
|
|
|
it('should have at least 100 total tools across all modules', () => {
|
|
expect(ALL_TOOLS.length).toBeGreaterThanOrEqual(100);
|
|
});
|
|
|
|
it('should export arrays from each module', () => {
|
|
for (const mod of ALL_MODULES) {
|
|
expect(Array.isArray(mod.tools)).toBe(true);
|
|
expect(mod.tools.length).toBeGreaterThan(0);
|
|
}
|
|
});
|
|
|
|
it('should have no duplicate tool names across all modules', () => {
|
|
const names = ALL_TOOLS.map(t => t.name);
|
|
const uniqueNames = new Set(names);
|
|
const duplicates = names.filter((n, i) => names.indexOf(n) !== i);
|
|
expect(duplicates).toEqual([]);
|
|
expect(uniqueNames.size).toBe(names.length);
|
|
});
|
|
|
|
it('should register expected tool counts per module', () => {
|
|
const minCounts: Record<string, number> = {
|
|
'agent-tools': 7,
|
|
'agentdb-tools': 15,
|
|
'analyze-tools': 6,
|
|
'browser-tools': 20,
|
|
'claims-tools': 12,
|
|
'config-tools': 6,
|
|
'coordination-tools': 7,
|
|
'daa-tools': 8,
|
|
'embeddings-tools': 7,
|
|
'github-tools': 5,
|
|
'hive-mind-tools': 9,
|
|
'memory-tools': 7,
|
|
'neural-tools': 6,
|
|
'performance-tools': 6,
|
|
'progress-tools': 4,
|
|
'security-tools': 6,
|
|
'session-tools': 5,
|
|
'swarm-tools': 4,
|
|
'system-tools': 7,
|
|
'task-tools': 7,
|
|
'terminal-tools': 5,
|
|
'transfer-tools': 11,
|
|
'workflow-tools': 10,
|
|
};
|
|
|
|
for (const mod of ALL_MODULES) {
|
|
const min = minCounts[mod.name];
|
|
if (min !== undefined) {
|
|
expect(mod.tools.length).toBeGreaterThanOrEqual(min);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 2. Schema Validation
|
|
// --------------------------------------------------------------------------
|
|
describe('Schema Validation - All Tools', () => {
|
|
it('every tool has a non-empty name', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
expect(tool.name).toBeDefined();
|
|
expect(typeof tool.name).toBe('string');
|
|
expect(tool.name.length).toBeGreaterThan(0);
|
|
}
|
|
});
|
|
|
|
it('every tool has a non-empty description', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
expect(tool.description).toBeDefined();
|
|
expect(typeof tool.description).toBe('string');
|
|
expect(tool.description.length).toBeGreaterThan(0);
|
|
}
|
|
});
|
|
|
|
it('every tool has an inputSchema with type "object"', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
expect(tool.inputSchema).toBeDefined();
|
|
expect(tool.inputSchema.type).toBe('object');
|
|
}
|
|
});
|
|
|
|
it('every tool inputSchema has a properties field', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
expect(tool.inputSchema.properties).toBeDefined();
|
|
expect(typeof tool.inputSchema.properties).toBe('object');
|
|
}
|
|
});
|
|
|
|
it('every tool has a handler function', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
expect(tool.handler).toBeDefined();
|
|
expect(typeof tool.handler).toBe('function');
|
|
}
|
|
});
|
|
|
|
it('required field is either absent or an array of strings', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
if (tool.inputSchema.required !== undefined) {
|
|
expect(Array.isArray(tool.inputSchema.required)).toBe(true);
|
|
for (const req of tool.inputSchema.required!) {
|
|
expect(typeof req).toBe('string');
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it('required fields reference existing properties', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
if (tool.inputSchema.required) {
|
|
const propNames = Object.keys(tool.inputSchema.properties);
|
|
for (const req of tool.inputSchema.required) {
|
|
expect(propNames).toContain(req);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
it('tool names follow naming conventions (category_action or category_action-detail)', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
// Names should contain underscore or hyphen as separators
|
|
// and not have spaces or special chars
|
|
expect(tool.name).toMatch(/^[a-z][a-z0-9_-]+$/);
|
|
}
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 3. Array Schema Validation - items field
|
|
// --------------------------------------------------------------------------
|
|
describe('Array Schema Validation', () => {
|
|
function findArrayProperties(tool: MCPTool): Array<{ toolName: string; propName: string; prop: any }> {
|
|
const results: Array<{ toolName: string; propName: string; prop: any }> = [];
|
|
const properties = tool.inputSchema.properties;
|
|
for (const [propName, prop] of Object.entries(properties)) {
|
|
const p = prop as Record<string, unknown>;
|
|
if (p.type === 'array') {
|
|
results.push({ toolName: tool.name, propName, prop: p });
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
|
|
it('all array-typed properties have an items field', () => {
|
|
const missingItems: string[] = [];
|
|
|
|
for (const tool of ALL_TOOLS) {
|
|
const arrayProps = findArrayProperties(tool);
|
|
for (const { toolName, propName, prop } of arrayProps) {
|
|
if (!prop.items) {
|
|
missingItems.push(`${toolName}.${propName}`);
|
|
}
|
|
}
|
|
}
|
|
|
|
expect(missingItems).toEqual([]);
|
|
});
|
|
|
|
it('array items field specifies a type', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
const arrayProps = findArrayProperties(tool);
|
|
for (const { prop } of arrayProps) {
|
|
if (prop.items) {
|
|
expect(prop.items.type).toBeDefined();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 4. Category Consistency
|
|
// --------------------------------------------------------------------------
|
|
describe('Category Consistency', () => {
|
|
it('tool name prefix matches category when category is set', () => {
|
|
const exceptions = new Set([
|
|
'mcp_status', // system-tools exports mcp_status
|
|
'mcp_start', // system-tools exports mcp_start (#1916 — in-process no-op)
|
|
'mcp_stop', // system-tools exports mcp_stop (#1916 — in-process no-op)
|
|
'task_summary', // system-tools exports task_summary
|
|
]);
|
|
|
|
for (const tool of ALL_TOOLS) {
|
|
if (tool.category && !exceptions.has(tool.name)) {
|
|
const prefix = tool.name.split('_')[0].replace(/-/g, '');
|
|
const cat = tool.category.replace(/-/g, '');
|
|
// Prefix should match category (e.g., agent_spawn -> agent category)
|
|
expect(prefix).toBe(cat);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 5. Handler Invocation - Agent Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Agent Tools - Handler Invocation', () => {
|
|
it('agent_spawn creates an agent with required agentType', async () => {
|
|
const tool = agentTools.find(t => t.name === 'agent_spawn')!;
|
|
const result: any = await tool.handler({ agentType: 'coder' });
|
|
expect(result.success).toBe(true);
|
|
expect(result.agentId).toBeDefined();
|
|
expect(result.agentType).toBe('coder');
|
|
});
|
|
|
|
it('agent_list returns agents array', async () => {
|
|
const tool = agentTools.find(t => t.name === 'agent_list')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.agents).toBeDefined();
|
|
expect(Array.isArray(result.agents)).toBe(true);
|
|
});
|
|
|
|
it('agent_status returns not_found for unknown agent', async () => {
|
|
const tool = agentTools.find(t => t.name === 'agent_status')!;
|
|
const result: any = await tool.handler({ agentId: 'nonexistent' });
|
|
expect(result.status).toBe('not_found');
|
|
});
|
|
|
|
it('agent_terminate returns error for unknown agent', async () => {
|
|
const tool = agentTools.find(t => t.name === 'agent_terminate')!;
|
|
const result: any = await tool.handler({ agentId: 'nonexistent' });
|
|
expect(result.success).toBe(false);
|
|
});
|
|
|
|
it('agent_pool status action returns pool info', async () => {
|
|
const tool = agentTools.find(t => t.name === 'agent_pool')!;
|
|
const result: any = await tool.handler({ action: 'status' });
|
|
expect(result.action).toBe('status');
|
|
expect(result.poolId).toBeDefined();
|
|
});
|
|
|
|
it('agent_health returns overall health info', async () => {
|
|
const tool = agentTools.find(t => t.name === 'agent_health')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.overall).toBeDefined();
|
|
});
|
|
|
|
it('agent_update returns error for unknown agent', async () => {
|
|
const tool = agentTools.find(t => t.name === 'agent_update')!;
|
|
const result: any = await tool.handler({ agentId: 'nonexistent' });
|
|
expect(result.success).toBe(false);
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 6. Handler Invocation - System Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('System Tools - Handler Invocation', () => {
|
|
it('system_status returns version and status', async () => {
|
|
const tool = systemTools.find(t => t.name === 'system_status')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.version).toBeDefined();
|
|
expect(result.status).toBeDefined();
|
|
});
|
|
|
|
it('system_info returns system information', async () => {
|
|
const tool = systemTools.find(t => t.name === 'system_info')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.version).toBeDefined();
|
|
expect(result.platform).toBeDefined();
|
|
});
|
|
|
|
it('system_health returns health checks', async () => {
|
|
const tool = systemTools.find(t => t.name === 'system_health')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.overall).toBeDefined();
|
|
expect(result.checks).toBeDefined();
|
|
});
|
|
|
|
it('system_metrics returns metrics data', async () => {
|
|
const tool = systemTools.find(t => t.name === 'system_metrics')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('mcp_status returns MCP server info', async () => {
|
|
const tool = systemTools.find(t => t.name === 'mcp_status')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.running).toBeDefined();
|
|
expect(result.transport).toBeDefined();
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 7. Handler Invocation - Config Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Config Tools - Handler Invocation', () => {
|
|
it('config_get returns value for known key', async () => {
|
|
const tool = configTools.find(t => t.name === 'config_get')!;
|
|
const result: any = await tool.handler({ key: 'logging.level' });
|
|
expect(result.key).toBe('logging.level');
|
|
expect(result.exists).toBeDefined();
|
|
});
|
|
|
|
it('config_set stores a value', async () => {
|
|
const tool = configTools.find(t => t.name === 'config_set')!;
|
|
const result: any = await tool.handler({ key: 'test.key', value: 'test-value' });
|
|
expect(result.success).toBe(true);
|
|
});
|
|
|
|
it('config_list returns configurations', async () => {
|
|
const tool = configTools.find(t => t.name === 'config_list')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.configs).toBeDefined();
|
|
expect(Array.isArray(result.configs)).toBe(true);
|
|
});
|
|
|
|
it('config_reset returns success', async () => {
|
|
const tool = configTools.find(t => t.name === 'config_reset')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.success).toBe(true);
|
|
});
|
|
|
|
it('config_export returns config data', async () => {
|
|
const tool = configTools.find(t => t.name === 'config_export')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.config).toBeDefined();
|
|
});
|
|
|
|
it('config_import returns success', async () => {
|
|
const tool = configTools.find(t => t.name === 'config_import')!;
|
|
const result: any = await tool.handler({ config: { 'test.k': 'v' } });
|
|
expect(result.success).toBe(true);
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 8. Handler Invocation - Swarm Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Swarm Tools - Handler Invocation', () => {
|
|
it('swarm_init returns swarmId and topology', async () => {
|
|
const tool = swarmTools.find(t => t.name === 'swarm_init')!;
|
|
const result: any = await tool.handler({ topology: 'hierarchical' });
|
|
expect(result.success).toBe(true);
|
|
expect(result.swarmId).toBeDefined();
|
|
expect(result.persisted).toBe(true);
|
|
});
|
|
|
|
it('swarm_status returns running status after init', async () => {
|
|
// Init a swarm first so status has something to report
|
|
const initTool = swarmTools.find(t => t.name === 'swarm_init')!;
|
|
const initResult: any = await initTool.handler({ topology: 'mesh' });
|
|
const tool = swarmTools.find(t => t.name === 'swarm_status')!;
|
|
const result: any = await tool.handler({ swarmId: initResult.swarmId });
|
|
expect(result.status).toBe('running');
|
|
});
|
|
|
|
it('swarm_shutdown returns success after init', async () => {
|
|
const initTool = swarmTools.find(t => t.name === 'swarm_init')!;
|
|
const initResult: any = await initTool.handler({ topology: 'hierarchical' });
|
|
const tool = swarmTools.find(t => t.name === 'swarm_shutdown')!;
|
|
const result: any = await tool.handler({ swarmId: initResult.swarmId });
|
|
expect(result.success).toBe(true);
|
|
expect(result.terminated).toBe(true);
|
|
});
|
|
|
|
it('swarm_health returns healthy checks after init', async () => {
|
|
const initTool = swarmTools.find(t => t.name === 'swarm_init')!;
|
|
const initResult: any = await initTool.handler({ topology: 'hierarchical' });
|
|
const tool = swarmTools.find(t => t.name === 'swarm_health')!;
|
|
const result: any = await tool.handler({ swarmId: initResult.swarmId });
|
|
expect(result.status).toBe('healthy');
|
|
expect(result.checks).toBeDefined();
|
|
expect(result.healthy).toBe(true);
|
|
});
|
|
|
|
it('swarm_health returns not_found for nonexistent swarm ID', async () => {
|
|
const tool = swarmTools.find(t => t.name === 'swarm_health')!;
|
|
const result: any = await tool.handler({ swarmId: 'nonexistent-id-999' });
|
|
expect(result.status).toBe('not_found');
|
|
expect(result.healthy).toBe(false);
|
|
expect(result.checks).toBeDefined();
|
|
});
|
|
|
|
it('swarm_init rejects invalid topology', async () => {
|
|
const tool = swarmTools.find(t => t.name === 'swarm_init')!;
|
|
const result: any = await tool.handler({ topology: 'invalid-topo' });
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('Invalid topology');
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 9. Handler Invocation - Task Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Task Tools - Handler Invocation', () => {
|
|
it('task_create creates a task', async () => {
|
|
const tool = taskTools.find(t => t.name === 'task_create')!;
|
|
const result: any = await tool.handler({ type: 'feature', description: 'Test task' });
|
|
expect(result.taskId).toBeDefined();
|
|
expect(result.type).toBe('feature');
|
|
expect(result.status).toBe('pending');
|
|
});
|
|
|
|
it('task_list returns tasks array', async () => {
|
|
const tool = taskTools.find(t => t.name === 'task_list')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.tasks).toBeDefined();
|
|
expect(Array.isArray(result.tasks)).toBe(true);
|
|
});
|
|
|
|
it('task_status returns not_found for unknown task', async () => {
|
|
const tool = taskTools.find(t => t.name === 'task_status')!;
|
|
const result: any = await tool.handler({ taskId: 'nonexistent' });
|
|
expect(result.status).toBe('not_found');
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 10. Handler Invocation - Session Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Session Tools - Handler Invocation', () => {
|
|
it('session_list returns sessions', async () => {
|
|
const tool = sessionTools.find(t => t.name === 'session_list')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.sessions).toBeDefined();
|
|
});
|
|
|
|
it('session_save creates a session', async () => {
|
|
const tool = sessionTools.find(t => t.name === 'session_save')!;
|
|
const result: any = await tool.handler({ name: 'Test Session' });
|
|
expect(result.sessionId).toBeDefined();
|
|
expect(result.name).toBe('Test Session');
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 11. Handler Invocation - Hive Mind Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Hive Mind Tools - Handler Invocation', () => {
|
|
it('hive-mind_init initializes the hive', async () => {
|
|
const tool = hiveMindTools.find(t => t.name === 'hive-mind_init')!;
|
|
const result: any = await tool.handler({ topology: 'mesh' });
|
|
expect(result.success).toBe(true);
|
|
expect(result.topology).toBe('mesh');
|
|
});
|
|
|
|
it('hive-mind_status returns status info', async () => {
|
|
const tool = hiveMindTools.find(t => t.name === 'hive-mind_status')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('hive-mind_consensus with list action returns data', async () => {
|
|
const tool = hiveMindTools.find(t => t.name === 'hive-mind_consensus')!;
|
|
const result: any = await tool.handler({ action: 'list' });
|
|
expect(result.action).toBe('list');
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 12. Handler Invocation - Workflow Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Workflow Tools - Handler Invocation', () => {
|
|
it('workflow_list returns workflows', async () => {
|
|
const tool = workflowTools.find(t => t.name === 'workflow_list')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.workflows).toBeDefined();
|
|
});
|
|
|
|
it('workflow_create creates a workflow', async () => {
|
|
const tool = workflowTools.find(t => t.name === 'workflow_create')!;
|
|
const result: any = await tool.handler({ name: 'test-wf', description: 'Test workflow' });
|
|
expect(result.workflowId).toBeDefined();
|
|
expect(result.name).toBe('test-wf');
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 13. Handler Invocation - DAA Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('DAA Tools - Handler Invocation', () => {
|
|
it('daa_agent_create creates an agent', async () => {
|
|
const tool = daaTools.find(t => t.name === 'daa_agent_create')!;
|
|
const result: any = await tool.handler({ id: 'test-daa-1' });
|
|
expect(result.success).toBe(true);
|
|
expect(result.agent.id).toBe('test-daa-1');
|
|
});
|
|
|
|
it('daa_learning_status returns summary', async () => {
|
|
const tool = daaTools.find(t => t.name === 'daa_learning_status')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.success).toBe(true);
|
|
expect(result.summary).toBeDefined();
|
|
});
|
|
|
|
it('daa_cognitive_pattern returns patterns info', async () => {
|
|
const tool = daaTools.find(t => t.name === 'daa_cognitive_pattern')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.success).toBe(true);
|
|
expect(result.patterns).toBeDefined();
|
|
});
|
|
|
|
it('daa_performance_metrics returns metrics', async () => {
|
|
const tool = daaTools.find(t => t.name === 'daa_performance_metrics')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.success).toBe(true);
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 14. Handler Invocation - Coordination Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Coordination Tools - Handler Invocation', () => {
|
|
it('coordination_topology get action returns topology', async () => {
|
|
const tool = coordinationTools.find(t => t.name === 'coordination_topology')!;
|
|
const result: any = await tool.handler({ action: 'get' });
|
|
expect(result.success).toBe(true);
|
|
expect(result.topology).toBeDefined();
|
|
});
|
|
|
|
it('coordination_sync status returns sync state', async () => {
|
|
const tool = coordinationTools.find(t => t.name === 'coordination_sync')!;
|
|
const result: any = await tool.handler({ action: 'status' });
|
|
expect(result.success).toBe(true);
|
|
});
|
|
|
|
it('coordination_node list returns nodes', async () => {
|
|
const tool = coordinationTools.find(t => t.name === 'coordination_node')!;
|
|
const result: any = await tool.handler({ action: 'list' });
|
|
expect(result.success).toBe(true);
|
|
expect(result.nodes).toBeDefined();
|
|
});
|
|
|
|
it('coordination_metrics returns metrics', async () => {
|
|
const tool = coordinationTools.find(t => t.name === 'coordination_metrics')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.success).toBe(true);
|
|
});
|
|
|
|
it('coordination_orchestrate accepts task', async () => {
|
|
const tool = coordinationTools.find(t => t.name === 'coordination_orchestrate')!;
|
|
const result: any = await tool.handler({ task: 'test task' });
|
|
expect(result.success).toBe(true);
|
|
expect(result.orchestrationId).toBeDefined();
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 15. Handler Invocation - GitHub Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('GitHub Tools - Handler Invocation', () => {
|
|
it('github_repo_analyze returns analysis', async () => {
|
|
const tool = githubTools.find(t => t.name === 'github_repo_analyze')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.success).toBe(true);
|
|
expect(result.repository).toBeDefined();
|
|
});
|
|
|
|
it('github_pr_manage list returns PRs', async () => {
|
|
const tool = githubTools.find(t => t.name === 'github_pr_manage')!;
|
|
const result: any = await tool.handler({ action: 'list' });
|
|
expect(result.success).toBe(true);
|
|
});
|
|
|
|
it('github_metrics returns all metrics', async () => {
|
|
const tool = githubTools.find(t => t.name === 'github_metrics')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.success).toBe(true);
|
|
expect(result.commits).toBeDefined();
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 16. Handler Invocation - Terminal Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Terminal Tools - Handler Invocation', () => {
|
|
it('terminal_create creates a session', async () => {
|
|
const tool = terminalTools.find(t => t.name === 'terminal_create')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.success).toBe(true);
|
|
expect(result.sessionId).toBeDefined();
|
|
});
|
|
|
|
it('terminal_list returns sessions', async () => {
|
|
const tool = terminalTools.find(t => t.name === 'terminal_list')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.sessions).toBeDefined();
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 17. Handler Invocation - Claims Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Claims Tools - Handler Invocation', () => {
|
|
it('claims_list returns claims', async () => {
|
|
const tool = claimsTools.find(t => t.name === 'claims_list')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.success).toBe(true);
|
|
expect(result.claims).toBeDefined();
|
|
});
|
|
|
|
it('claims_claim with invalid claimant returns error', async () => {
|
|
const tool = claimsTools.find(t => t.name === 'claims_claim')!;
|
|
const result: any = await tool.handler({ issueId: 'issue-1', claimant: 'invalid' });
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('Invalid claimant');
|
|
});
|
|
|
|
it('claims_board returns board view', async () => {
|
|
const tool = claimsTools.find(t => t.name === 'claims_board')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.success).toBe(true);
|
|
expect(result.board).toBeDefined();
|
|
});
|
|
|
|
it('claims_stealable returns stealable issues', async () => {
|
|
const tool = claimsTools.find(t => t.name === 'claims_stealable')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.success).toBe(true);
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 18. Handler Invocation - Performance Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Performance Tools - Handler Invocation', () => {
|
|
it('performance_report returns a report', async () => {
|
|
const tool = performanceTools.find(t => t.name === 'performance_report')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('performance_metrics returns metrics', async () => {
|
|
const tool = performanceTools.find(t => t.name === 'performance_metrics')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('performance_benchmark runs a benchmark', async () => {
|
|
const tool = performanceTools.find(t => t.name === 'performance_benchmark')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 19. Handler Invocation - Neural Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Neural Tools - Handler Invocation', () => {
|
|
it('neural_status returns status', async () => {
|
|
const tool = neuralTools.find(t => t.name === 'neural_status')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('neural_patterns returns patterns list', async () => {
|
|
const tool = neuralTools.find(t => t.name === 'neural_patterns')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 20. Handler Invocation - AgentDB Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('AgentDB Tools - Handler Invocation', () => {
|
|
it('agentdb_health returns availability', async () => {
|
|
const tool = agentdbTools.find(t => t.name === 'agentdb_health')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('agentdb_controllers returns controllers list', async () => {
|
|
const tool = agentdbTools.find(t => t.name === 'agentdb_controllers')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('agentdb_pattern-store requires pattern param', async () => {
|
|
const tool = agentdbTools.find(t => t.name === 'agentdb_pattern-store')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toMatch(/pattern.*(required|must be)/i);
|
|
});
|
|
|
|
it('agentdb_pattern-search requires query param', async () => {
|
|
const tool = agentdbTools.find(t => t.name === 'agentdb_pattern-search')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.error).toMatch(/query.*(required|must be)/i);
|
|
});
|
|
|
|
it('agentdb_causal-edge validates required fields', async () => {
|
|
const tool = agentdbTools.find(t => t.name === 'agentdb_causal-edge')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.success).toBe(false);
|
|
});
|
|
|
|
it('agentdb_route requires task param', async () => {
|
|
const tool = agentdbTools.find(t => t.name === 'agentdb_route')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.error).toMatch(/task.*(required|must be)/i);
|
|
});
|
|
|
|
it('agentdb_batch validates entries array', async () => {
|
|
const tool = agentdbTools.find(t => t.name === 'agentdb_batch')!;
|
|
const result: any = await tool.handler({ operation: 'insert' });
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('entries is required');
|
|
});
|
|
|
|
it('agentdb_batch validates operation type', async () => {
|
|
const tool = agentdbTools.find(t => t.name === 'agentdb_batch')!;
|
|
const result: any = await tool.handler({ operation: 'invalid', entries: [{ key: 'k' }] });
|
|
expect(result.success).toBe(false);
|
|
expect(result.error).toContain('Invalid operation');
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 21. Error Handling
|
|
// --------------------------------------------------------------------------
|
|
describe('Error Handling', () => {
|
|
it('tools handle empty input gracefully', async () => {
|
|
// Test a selection of tools with empty input
|
|
const toolsToTest = [
|
|
agentTools.find(t => t.name === 'agent_list')!,
|
|
configTools.find(t => t.name === 'config_list')!,
|
|
swarmTools.find(t => t.name === 'swarm_status')!,
|
|
taskTools.find(t => t.name === 'task_list')!,
|
|
daaTools.find(t => t.name === 'daa_learning_status')!,
|
|
coordinationTools.find(t => t.name === 'coordination_metrics')!,
|
|
performanceTools.find(t => t.name === 'performance_report')!,
|
|
];
|
|
|
|
for (const tool of toolsToTest) {
|
|
const result = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
}
|
|
});
|
|
|
|
it('tools do not throw on invalid input types', async () => {
|
|
// These should return errors gracefully instead of throwing
|
|
const tool = agentTools.find(t => t.name === 'agent_spawn')!;
|
|
// Pass number instead of string for agentType
|
|
const result: any = await tool.handler({ agentType: 123 as any });
|
|
// Should still succeed - type coercion
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('agentdb tools validate string inputs', async () => {
|
|
const tool = agentdbTools.find(t => t.name === 'agentdb_pattern-store')!;
|
|
// Empty string should fail validation
|
|
const result: any = await tool.handler({ pattern: '' });
|
|
expect(result.success).toBe(false);
|
|
});
|
|
|
|
it('agentdb tools enforce max string length', async () => {
|
|
const tool = agentdbTools.find(t => t.name === 'agentdb_feedback')!;
|
|
// Very long taskId should be rejected
|
|
const longId = 'x'.repeat(1000);
|
|
const result: any = await tool.handler({ taskId: longId });
|
|
expect(result.success).toBe(false);
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 22. Security Checks
|
|
// --------------------------------------------------------------------------
|
|
describe('Security Checks', () => {
|
|
it('no tool schemas contain hardcoded paths', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
const schema = JSON.stringify(tool.inputSchema);
|
|
expect(schema).not.toContain('/home/');
|
|
expect(schema).not.toContain('/etc/');
|
|
expect(schema).not.toContain('C:\\');
|
|
}
|
|
});
|
|
|
|
it('no tool schemas contain hardcoded secrets or tokens', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
const schema = JSON.stringify(tool.inputSchema);
|
|
expect(schema).not.toMatch(/sk-[a-zA-Z0-9]{20,}/);
|
|
expect(schema).not.toMatch(/password.*=.*[a-zA-Z0-9]{8,}/i);
|
|
}
|
|
});
|
|
|
|
it('no tool names expose internal implementation details', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
expect(tool.name).not.toContain('internal');
|
|
expect(tool.name).not.toContain('debug');
|
|
expect(tool.name).not.toContain('_raw');
|
|
}
|
|
});
|
|
|
|
it('session tools sanitize sessionId against path traversal', () => {
|
|
// session_save should handle path traversal attempts
|
|
const tool = sessionTools.find(t => t.name === 'session_save')!;
|
|
// The session file path should be sanitized
|
|
expect(tool).toBeDefined();
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 23. Return Format Consistency
|
|
// --------------------------------------------------------------------------
|
|
describe('Return Format Consistency', () => {
|
|
it('agent_spawn returns success field', async () => {
|
|
const tool = agentTools.find(t => t.name === 'agent_spawn')!;
|
|
const result: any = await tool.handler({ agentType: 'coder' });
|
|
expect(typeof result.success).toBe('boolean');
|
|
});
|
|
|
|
it('config tools return success field', async () => {
|
|
const setTool = configTools.find(t => t.name === 'config_set')!;
|
|
const result: any = await setTool.handler({ key: 'test', value: 'v' });
|
|
expect(typeof result.success).toBe('boolean');
|
|
});
|
|
|
|
it('task_create returns taskId and status', async () => {
|
|
const tool = taskTools.find(t => t.name === 'task_create')!;
|
|
const result: any = await tool.handler({ type: 'bugfix', description: 'Fix the bug' });
|
|
expect(result.taskId).toBeDefined();
|
|
expect(typeof result.taskId).toBe('string');
|
|
expect(result.status).toBe('pending');
|
|
});
|
|
|
|
it('swarm_init returns success and swarmId', async () => {
|
|
const tool = swarmTools.find(t => t.name === 'swarm_init')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result.success).toBe(true);
|
|
expect(result.swarmId).toBeDefined();
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 24. Progress & Embeddings Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Progress Tools - Handler Invocation', () => {
|
|
it('progress_check returns progress metrics', async () => {
|
|
const tool = progressTools.find(t => t.name === 'progress_check')!;
|
|
expect(tool).toBeDefined();
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('progress_summary returns summary', async () => {
|
|
const tool = progressTools.find(t => t.name === 'progress_summary')!;
|
|
expect(tool).toBeDefined();
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
});
|
|
|
|
describe('Embeddings Tools - Handler Invocation', () => {
|
|
it('embeddings_status returns initialization state', async () => {
|
|
const tool = embeddingsTools.find(t => t.name === 'embeddings_status')!;
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('embeddings_init initializes the subsystem', async () => {
|
|
const tool = embeddingsTools.find(t => t.name === 'embeddings_init')!;
|
|
const result: any = await tool.handler({ force: true });
|
|
expect(result.success).toBe(true);
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 25. Hooks Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Hooks Tools - Handler Invocation', () => {
|
|
it('hooks_list returns hooks list', async () => {
|
|
const tool = hooksTools.find(t => t.name === 'hooks_list')!;
|
|
expect(tool).toBeDefined();
|
|
const result: any = await tool.handler({});
|
|
expect(result.hooks).toBeDefined();
|
|
});
|
|
|
|
it('hooks_metrics returns metrics', async () => {
|
|
const tool = hooksTools.find(t => t.name === 'hooks_metrics')!;
|
|
expect(tool).toBeDefined();
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('hooks_worker-list returns workers', async () => {
|
|
const tool = hooksTools.find(t => t.name === 'hooks_worker-list')!;
|
|
expect(tool).toBeDefined();
|
|
const result: any = await tool.handler({});
|
|
expect(result.workers).toBeDefined();
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 26. Memory Tools
|
|
// --------------------------------------------------------------------------
|
|
describe('Memory Tools - Handler Invocation', () => {
|
|
it('memory_store stores an entry', async () => {
|
|
const tool = memoryTools.find(t => t.name === 'memory_store')!;
|
|
expect(tool).toBeDefined();
|
|
const result: any = await tool.handler({ key: 'test-key', value: 'test-value' });
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('memory_list returns entries', async () => {
|
|
const tool = memoryTools.find(t => t.name === 'memory_list')!;
|
|
expect(tool).toBeDefined();
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
|
|
it('memory_stats returns statistics', async () => {
|
|
const tool = memoryTools.find(t => t.name === 'memory_stats')!;
|
|
expect(tool).toBeDefined();
|
|
const result: any = await tool.handler({});
|
|
expect(result).toBeDefined();
|
|
});
|
|
});
|
|
|
|
// --------------------------------------------------------------------------
|
|
// 27. Cross-Module Integrity
|
|
// --------------------------------------------------------------------------
|
|
describe('Cross-Module Integrity', () => {
|
|
it('all tool names are valid MCP tool identifiers', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
// MCP tool names should be alphanumeric with underscores/hyphens
|
|
expect(tool.name).toMatch(/^[a-z][a-z0-9_-]*$/);
|
|
// No double underscores or hyphens
|
|
expect(tool.name).not.toMatch(/__/);
|
|
expect(tool.name).not.toMatch(/--/);
|
|
}
|
|
});
|
|
|
|
it('all descriptions are human-readable sentences', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
// Description should start with uppercase or lowercase letter
|
|
expect(tool.description).toMatch(/^[A-Za-z]/);
|
|
// Should be at least 10 characters
|
|
expect(tool.description.length).toBeGreaterThanOrEqual(10);
|
|
}
|
|
});
|
|
|
|
it('no tool has an empty properties object with required fields', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
if (tool.inputSchema.required && tool.inputSchema.required.length > 0) {
|
|
const propCount = Object.keys(tool.inputSchema.properties).length;
|
|
expect(propCount).toBeGreaterThan(0);
|
|
}
|
|
}
|
|
});
|
|
|
|
it('every property in schema has a type or description', () => {
|
|
for (const tool of ALL_TOOLS) {
|
|
for (const [propName, prop] of Object.entries(tool.inputSchema.properties)) {
|
|
const p = prop as Record<string, unknown>;
|
|
// Every property should have at least a type or description
|
|
const hasType = p.type !== undefined;
|
|
const hasDesc = p.description !== undefined;
|
|
expect(hasType || hasDesc).toBe(true);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
});
|