MCP COMPREHENSIVE ARCHITECTURE REVIEW
Comprehensive guidelines for AI-assisted development within the Editor platform
MCP & Backend-AI-API: FINAL Architecture Plan
Date: February 4, 2026
Session: editor2-session-87
Status: FINAL - No More Revisions
The Hard Truth
121 tools is unacceptable. Period.
Both previous reviews were too accommodating. The backend services are well-built, but that's not the point. The point is: agents cannot effectively use 121 tools. LLMs have cognitive limits. Tool selection accuracy degrades exponentially with tool count.
The "sunk cost" argument ("we built it, so keep it") is a trap. Good engineering means ruthless consolidation.
FINAL Tool Architecture: 25 Tools
| # | Tool Name | Type | What It Replaces | Chains Internally |
|---|---|---|---|---|
| 1 | mcp_init |
Entry | - | health check, mode selection, tool discovery |
| 2 | preflight |
Core | - | context, similar decisions, episodes (optional) |
| 3 | log_decision |
Core | - | auto-schedules outcome check |
| 4 | find_similar |
Core | - | - |
| 5 | session |
Gateway | 7 session tools | set, get, update, lock, register, summary, info |
| 6 | outcome |
Gateway | 3 outcome tools | report, track, validate |
| 7 | stats |
Gateway | 3 stats tools | basic, enhanced, session summary |
| 8 | convention |
Gateway | 2 convention tools | get, add |
| 9 | agent |
Gateway | 10 multi-agent tools | status, connect, events, handoff, respond, message, broadcast, find, call, watch |
| 10 | browser |
Gateway | 9 browser tools | navigate, click, fill, screenshot, extract, execute, wait, status, close |
| 11 | desktop |
Gateway | 7 desktop tools | read, write, list, execute, clipboard_get, clipboard_set, status |
| 12 | task |
Gateway | 6 task tools | create, execute, list, workflow_create, workflow_run, status |
| 13 | intelligence |
Gateway | 29 tools | ALL super intelligence, self-healing, calibration, evolution, code DNA, time machine |
| 14 | code |
Gateway | 8 code tools | review, test_gen, validate, analyze, suggest |
| 15 | platform |
Gateway | 4 platform tools | describe, query, mutate, automate |
| 16 | research |
Gateway | 2 search tools | web_search, docs_search |
| 17 | graph |
Existing | Already consolidated | - |
| 18 | behavior_mode |
Existing | Already consolidated | - |
| 19 | persona |
Existing | Already consolidated | - |
| 20 | token_efficiency |
Existing | Already consolidated | - |
| 21 | self_healing |
Existing | Already consolidated | - |
| 22 | docs_intelligence |
Existing | Already consolidated | - |
| 23 | workflow |
Existing | Already consolidated | - |
| 24 | space_generate |
Existing | - | - |
| 25 | discover_tools |
Discovery | - | - |
Reduction: 121 → 25 tools (79% reduction)
The intelligence Gateway: The Key Innovation
This is where the magic happens. One tool that chains ALL intelligence services:
{
name: 'intelligence',
description: 'Unified AI intelligence gateway. Actions: recall (episodic memory), simulate (what-if), reflect (post-task learning), explain (causal reasoning), detect_gaps (knowledge gaps), diagnose (health), heal (self-repair), calibrate (confidence), evolve (agent tracking), analyze_dna (code conventions), enforce_dna (convention check), trace (decision history), pivot (find pivots), loops (detect patterns).',
inputSchema: {
type: 'object',
properties: {
action: {
type: 'string',
enum: [
// Super Intelligence
'recall', 'simulate', 'reflect', 'explain', 'detect_gaps', 'get_lessons',
// Self-Healing
'diagnose', 'heal', 'health_report',
// Calibration
'calibrate', 'calibration_curve',
// Evolution
'agent_evolution', 'predict_best_agent', 'specializations', 'complexity',
// Code DNA
'analyze_dna', 'enforce_dna', 'violations',
// Time Machine
'trace', 'pivots', 'simulate_alt', 'loops',
// Collective (archived but accessible)
'collective_join', 'collective_share', 'collective_query', 'collective_stats'
]
},
// Action-specific params follow...
},
required: ['action']
}
}
Internal Chaining Example:
async function handleIntelligence(args: IntelligenceInput): Promise<any> {
switch (args.action) {
case 'recall':
return handleSuperRecallEpisodes(args);
case 'simulate':
// Chain: recall similar episodes → run simulation → return combined result
const episodes = await handleSuperRecallEpisodes({ situation: args.context, limit: 3 });
const simulation = await handleSuperSimulate(args);
return {
...simulation,
relatedEpisodes: episodes.episodes,
enhancedConfidence: calculateEnhancedConfidence(simulation, episodes)
};
case 'reflect':
// Chain: reflect → detect gaps → suggest next learning
const reflection = await handleSuperReflect(args);
const gaps = await handleSuperDetectGaps({ domain: args.domain });
return {
...reflection,
knowledgeGaps: gaps.gaps,
suggestedLearning: gaps.recommendations
};
case 'diagnose':
// Chain: diagnose → auto-heal if safe → report
const diagnosis = await handleSelfDiagnose();
if (diagnosis.healthScore < 0.7 && args.autoHeal !== false) {
const healing = await handleSelfHeal({ action: 'auto' });
return { ...diagnosis, healingPerformed: healing };
}
return diagnosis;
// ... other actions
}
}
This is the chaining you asked for. One tool call triggers 2-3 internal operations intelligently.
The agent Gateway: Multi-Agent Simplified
{
name: 'agent',
description: 'Multi-agent operations. Actions: status, connect, events, handoff_create, handoff_respond, handoff_get, handoff_pending, message, broadcast, find, call, watch.',
inputSchema: {
type: 'object',
properties: {
action: {
type: 'string',
enum: ['status', 'connect', 'events', 'handoff_create', 'handoff_respond', 'handoff_get', 'handoff_pending', 'message', 'broadcast', 'find', 'call', 'watch']
},
// Action-specific params...
},
required: ['action']
}
}
Replaces: agent_status, agent_connect, agent_events, create_handoff, respond_to_handoff, get_handoff, get_pending_handoffs, send_agent_message, agent_broadcast, find_agents_for_task, call_agent, watch_handoffs
The session Gateway: Session Management Unified
{
name: 'session',
description: 'Session management. Actions: set, get, update, lock, unlock, register, summary.',
inputSchema: {
type: 'object',
properties: {
action: {
type: 'string',
enum: ['set', 'get', 'update', 'lock', 'unlock', 'register', 'summary']
},
sessionNumber: { type: 'number' },
subSessionNumber: { type: 'number' },
description: { type: 'string' },
lockSession: { type: 'boolean' }
},
required: ['action']
}
}
Replaces: set_session, get_session_info, update_chat_session, lock_chat_session, register_chat_context, get_session_summary, get_chat_context
Enhanced preflight: The Smart Entry Point
{
name: 'preflight',
description: 'Intelligent context retrieval. Optionally chains to similar decisions, episodic memory, and health check.',
inputSchema: {
type: 'object',
properties: {
task: { type: 'string', description: 'Brief task description' },
sessionNumber: { type: 'number' },
subSessionNumber: { type: 'number' },
lite: { type: 'boolean', default: false },
// NEW: Auto-chaining options
withSimilar: { type: 'boolean', default: true, description: 'Auto-fetch similar decisions' },
withEpisodes: { type: 'boolean', default: false, description: 'Auto-fetch similar episodes from memory' },
withHealth: { type: 'boolean', default: false, description: 'Include system health check' }
},
required: ['task']
}
}
Internal Flow:
async function handlePreflight(args) {
const context = await getPreflightContext(args.task);
// Auto-chain: similar decisions
if (args.withSimilar !== false) {
context.similarDecisions = await handleFindSimilar({ query: args.task, limit: 3 });
}
// Auto-chain: episodic memory
if (args.withEpisodes) {
context.similarEpisodes = await handleSuperRecallEpisodes({
situation: args.task,
limit: 3,
minRelevance: 0.5
});
}
// Auto-chain: health check
if (args.withHealth) {
context.systemHealth = await handleSelfDiagnose();
}
return context;
}
Enhanced log_decision: Auto-Outcome Scheduling
{
name: 'log_decision',
description: 'Log a decision. Auto-schedules outcome verification.',
inputSchema: {
type: 'object',
properties: {
type: { type: 'string', enum: ['architecture', 'implementation', 'refactor', 'bugfix', 'fix', 'pattern', 'convention', 'documentation', 'milestone'] },
question: { type: 'string' },
options: { type: 'array', items: { type: 'string' } },
chosen: { type: 'string' },
reasoning: { type: 'string' },
confidence: { type: 'number' },
files: { type: 'array', items: { type: 'string' } },
// NEW: Auto-outcome options
autoOutcome: { type: 'boolean', default: true, description: 'Auto-schedule outcome check' },
outcomeDelayMs: { type: 'number', default: 300000, description: 'Delay before outcome check (default 5 min)' }
},
required: ['type', 'question', 'chosen', 'reasoning', 'confidence']
}
}
Internal Flow:
async function handleLogDecision(args) {
const decision = await saveDecision(args);
// Auto-schedule outcome check
if (args.autoOutcome !== false && decision.files?.length > 0) {
scheduleOutcomeCheck(decision.id, {
checkAfterMs: args.outcomeDelayMs || 5 * 60 * 1000,
method: 'git_diff',
files: decision.files
});
}
// Auto-create episode for significant decisions
if (decision.type === 'architecture' || decision.confidence >= 0.8) {
await handleSuperReflect({
taskSummary: decision.question,
outcome: 'pending',
lessonsLearned: [decision.reasoning]
});
}
return decision;
}
Outcome Automation: The Missing Piece
Git-Based Outcome Detection (Backend Service)
// apis/backend-ai-api/src/app/learning/services/outcome-automation.service.ts
@Injectable()
export class OutcomeAutomationService {
private pendingChecks: Map<string, NodeJS.Timeout> = new Map();
scheduleCheck(decisionId: string, options: OutcomeCheckOptions) {
const timeout = setTimeout(async () => {
await this.performCheck(decisionId, options);
}, options.checkAfterMs);
this.pendingChecks.set(decisionId, timeout);
}
async performCheck(decisionId: string, options: OutcomeCheckOptions) {
const decision = await this.decisionService.findById(decisionId);
if (!decision || decision.outcome) return; // Already has outcome
// Check git status of files
const gitStatus = await this.gitService.checkFilesStatus(decision.files);
const wasSuccessful =
!gitStatus.reverted &&
!gitStatus.hasConflicts &&
gitStatus.stillExists;
// Auto-report outcome
await this.outcomeService.report({
decisionId,
wasSuccessful,
feedback: this.generateFeedback(gitStatus),
rating: wasSuccessful ? 4 : 2,
source: 'auto-git'
});
this.logger.log(`Auto-outcome for ${decisionId}: ${wasSuccessful ? 'SUCCESS' : 'FAILURE'}`);
}
}
What Gets Removed (Archived, Not Deleted)
These tools move to MCP/mcp-gograb-ai/src/tools/archived/:
| Tool | Reason |
|---|---|
mcp_init |
Keep (entry point) |
select_mode |
Merged into mcp_init |
poc_websocket_test |
POC complete, not needed |
list_contexts |
Merged into discover_tools |
load_tools |
Merged into discover_tools |
self_modify_system |
Too dangerous for general use |
get_modification_history |
Merged into intelligence |
rollback_modification |
Merged into intelligence |
debug_logs |
Dev-only, not for agents |
git_session_analyzer |
Merged into session |
| All individual super_* tools | Merged into intelligence |
| All individual self_* tools | Merged into intelligence |
| All individual calibration tools | Merged into intelligence |
| All individual evolution tools | Merged into intelligence |
| All individual code DNA tools | Merged into intelligence |
| All individual time machine tools | Merged into intelligence |
| All individual collective tools | Merged into intelligence |
| All individual browser_* tools | Merged into browser |
| All individual desktop_* tools | Merged into desktop |
| All individual task_* tools | Merged into task |
| All individual agent_* tools | Merged into agent |
| All individual session tools | Merged into session |
| All individual outcome tools | Merged into outcome |
| All individual stats tools | Merged into stats |
Archive, don't delete. The handlers still exist, they're just not exposed as individual tools.
Implementation Plan
Week 1: Core Gateways (P0)
| Day | Task | Deliverable |
|---|---|---|
| 1 | Create session gateway |
Replace 7 tools → 1 |
| 2 | Create agent gateway |
Replace 12 tools → 1 |
| 3 | Create outcome gateway + auto-scheduling |
Replace 3 tools → 1, add automation |
| 4 | Create stats gateway |
Replace 3 tools → 1 |
| 5 | Create convention gateway |
Replace 2 tools → 1 |
Week 1 Result: 121 → 94 tools
Week 2: Intelligence Gateway (P0)
| Day | Task | Deliverable |
|---|---|---|
| 1-2 | Create intelligence gateway |
Replace 29 tools → 1 |
| 3 | Implement internal chaining (recall → simulate, reflect → gaps) | Smart tool chains |
| 4 | Create code gateway |
Replace 8 tools → 1 |
| 5 | Create platform gateway |
Replace 4 tools → 1 |
Week 2 Result: 94 → 53 tools
Week 3: Automation Gateways (P1)
| Day | Task | Deliverable |
|---|---|---|
| 1 | Create browser gateway |
Replace 9 tools → 1 |
| 2 | Create desktop gateway |
Replace 7 tools → 1 |
| 3 | Create task gateway |
Replace 6 tools → 1 |
| 4 | Create research gateway |
Replace 2 tools → 1 |
| 5 | Cleanup: archive old tools, update docs | Final cleanup |
Week 3 Result: 53 → 25 tools
Week 4: Polish & Testing (P2)
| Day | Task | Deliverable |
|---|---|---|
| 1-2 | Enhance preflight with auto-chaining |
withSimilar, withEpisodes, withHealth |
| 3 | Enhance log_decision with auto-outcome |
autoOutcome, outcomeDelayMs |
| 4 | Update mcp_init with tool discovery |
Show relevant tools per task |
| 5 | Integration testing, documentation | Production-ready |
Success Metrics
| Metric | Current | Target (30 days) | Target (90 days) |
|---|---|---|---|
| Tool count | 121 | 25 | 25 |
| Tool usage coverage | 21% | 60% | 85% |
| Outcome feedback rate | 0.3% | 50% | 80% |
| Avg tools per task | 4+ | 1-2 | 1 |
| Agent cognitive load | HIGH | MEDIUM | LOW |
Phase 5: Backend-AI-API Hardening
5.1 VITTO Resilience
VITTO is currently a single point of failure. If it crashes, all autonomous handoffs stop.
| Issue | Current State | Fix | Priority |
|---|---|---|---|
| Single point of failure | VITTO runs inside NestJS process | Run as separate process with PM2/systemd | P1 |
| No rate limiting | Direct Anthropic API calls without throttling | Add @nestjs/throttler to Claude API calls |
P0 |
| Memory bloat | In-memory triggerIndex in EpisodicMemoryService |
Move to Redis with TTL eviction | P2 |
| No circuit breaker | External API failures cascade | Add circuit breaker pattern for Anthropic/external calls | P1 |
| No graceful shutdown | Pending handoffs lost on restart | Persist handoff queue to Redis/MongoDB | P1 |
Implementation: VITTO Process Isolation
# ecosystem.config.js for PM2
module.exports = {
apps: [
{
name: 'backend-ai-api',
script: 'dist/apis/backend-ai-api/main.js',
instances: 1,
env: {
VITTO_AUTO_START: false // Don't start VITTO in main process
}
},
{
name: 'vitto-orchestrator',
script: 'dist/apis/backend-ai-api/vitto-standalone.js',
instances: 1,
max_restarts: 10,
restart_delay: 5000,
env: {
VITTO_STANDALONE: true
}
}
]
};
Implementation: Rate Limiting for Anthropic API
// apis/backend-ai-api/src/app/vitto/vitto-orchestrator.service.ts
import { Throttle } from '@nestjs/throttler';
import Bottleneck from 'bottleneck';
@Injectable()
export class VittoOrchestratorService {
private readonly limiter = new Bottleneck({
maxConcurrent: 3, // Max 3 concurrent Claude calls
minTime: 1000, // At least 1 second between calls
reservoir: 60, // 60 requests per minute
reservoirRefreshAmount: 60,
reservoirRefreshInterval: 60 * 1000
});
private async executeWithAI(step: ExecutionStep, handoff: Handoff): Promise<string> {
return this.limiter.schedule(async () => {
return this.anthropic.messages.create({
model: 'claude-sonnet-4-20250514',
max_tokens: 4096,
messages: [/* ... */]
});
});
}
}
Implementation: Redis-Based Trigger Index
// apis/backend-ai-api/src/app/super-intelligence/services/episodic-memory.service.ts
@Injectable()
export class EpisodicMemoryService {
constructor(
@InjectRedis() private readonly redis: Redis,
// ...
) {}
// Replace in-memory Map with Redis
private async addToTriggerIndex(trigger: string, episodeId: string): Promise<void> {
await this.redis.sadd(`triggers:${trigger}`, episodeId);
await this.redis.expire(`triggers:${trigger}`, 7 * 24 * 60 * 60); // 7 day TTL
}
private async getTriggerEpisodes(trigger: string): Promise<string[]> {
return this.redis.smembers(`triggers:${trigger}`);
}
}
5.2 MCP Error Boundaries
Currently, tool failures can crash the MCP server or return cryptic errors. We need defensive wrappers.
Implementation: Safe Tool Call Wrapper
// MCP/mcp-gograb-ai/src/utils/safe-tool-call.ts
import { debugLogger } from './debug-logger.js';
export interface SafeToolResult<T = any> {
success: boolean;
data?: T;
error?: string;
errorCode?: string;
recoverable: boolean;
duration: number;
}
export async function safeToolCall<T>(
toolName: string,
handler: () => Promise<T>,
options: { timeout?: number; retries?: number } = {}
): Promise<SafeToolResult<T>> {
const startTime = Date.now();
const { timeout = 30000, retries = 0 } = options;
let lastError: Error | null = null;
for (let attempt = 0; attempt <= retries; attempt++) {
try {
debugLogger.info('tool_call_start', {
tool: toolName,
attempt: attempt + 1,
maxAttempts: retries + 1
});
// Wrap with timeout
const result = await Promise.race([
handler(),
new Promise<never>((_, reject) =>
setTimeout(() => reject(new Error(`Tool ${toolName} timed out after ${timeout}ms`)), timeout)
)
]);
const duration = Date.now() - startTime;
debugLogger.info('tool_call_success', { tool: toolName, duration });
return {
success: true,
data: result,
recoverable: true,
duration
};
} catch (error: any) {
lastError = error;
debugLogger.warn('tool_call_attempt_failed', {
tool: toolName,
attempt: attempt + 1,
error: error.message
});
if (attempt < retries) {
await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1))); // Exponential backoff
}
}
}
const duration = Date.now() - startTime;
debugLogger.error('tool_call_failed', {
tool: toolName,
error: lastError?.message,
duration
});
return {
success: false,
error: `Tool ${toolName} failed: ${lastError?.message}`,
errorCode: classifyError(lastError),
recoverable: isRecoverableError(lastError),
duration
};
}
function classifyError(error: Error | null): string {
if (!error) return 'UNKNOWN';
const msg = error.message.toLowerCase();
if (msg.includes('timeout')) return 'TIMEOUT';
if (msg.includes('network') || msg.includes('fetch')) return 'NETWORK';
if (msg.includes('auth') || msg.includes('401')) return 'AUTH';
if (msg.includes('rate') || msg.includes('429')) return 'RATE_LIMIT';
if (msg.includes('not found') || msg.includes('404')) return 'NOT_FOUND';
return 'INTERNAL';
}
function isRecoverableError(error: Error | null): boolean {
if (!error) return false;
const code = classifyError(error);
return ['TIMEOUT', 'NETWORK', 'RATE_LIMIT'].includes(code);
}
Usage in Gateway Handlers:
// MCP/mcp-gograb-ai/src/tools/gateways/intelligence-gateway.ts
export async function handleIntelligence(args: IntelligenceInput): Promise<any> {
return safeToolCall('intelligence', async () => {
switch (args.action) {
case 'recall':
return handleSuperRecallEpisodes(args);
case 'simulate':
const episodes = await handleSuperRecallEpisodes({ situation: args.context, limit: 3 });
const simulation = await handleSuperSimulate(args);
return { ...simulation, relatedEpisodes: episodes.episodes };
// ... other actions
}
}, { timeout: 15000, retries: 1 });
}
5.3 Observability & Monitoring
| Component | Current | Target | Implementation |
|---|---|---|---|
| Tool call metrics | None | Per-tool latency, success rate | Prometheus + Grafana |
| VITTO health | None | Healthcheck endpoint | /health/vitto |
| Decision pipeline | Partial | Full tracing | OpenTelemetry spans |
| Error alerting | None | Slack/PagerDuty | Alert on error rate > 5% |
Implementation: Healthcheck Endpoint
// apis/backend-ai-api/src/app/health/health.controller.ts
@Controller('health')
export class HealthController {
constructor(
private readonly vittoService: VittoOrchestratorService,
private readonly learningService: LearningService,
private readonly selfHealingService: SelfHealingService,
) {}
@Get('vitto')
async vittoHealth(): Promise<HealthCheckResult> {
return {
status: this.vittoService.isConnected ? 'healthy' : 'degraded',
uptime: this.vittoService.getUptime(),
pendingHandoffs: this.vittoService.getPendingCount(),
lastActivity: this.vittoService.getLastActivityTime(),
websocketState: this.vittoService.getSocketState(),
};
}
@Get('learning')
async learningHealth(): Promise<HealthCheckResult> {
const metrics = await this.selfHealingService.collectMetrics();
return {
status: metrics.every(m => m.status !== 'critical') ? 'healthy' : 'degraded',
metrics,
lastHealthCheck: this.selfHealingService.getLastCheckTime(),
};
}
@Get()
async fullHealth(): Promise<HealthCheckResult> {
const [vitto, learning] = await Promise.all([
this.vittoHealth(),
this.learningHealth(),
]);
return {
status: vitto.status === 'healthy' && learning.status === 'healthy' ? 'healthy' : 'degraded',
components: { vitto, learning },
timestamp: new Date().toISOString(),
};
}
}
Implementation: Tool Metrics
// MCP/mcp-gograb-ai/src/utils/metrics.ts
interface ToolMetrics {
calls: number;
successes: number;
failures: number;
totalDuration: number;
lastCall: Date | null;
}
class MetricsCollector {
private metrics: Map<string, ToolMetrics> = new Map();
recordCall(toolName: string, success: boolean, duration: number): void {
const existing = this.metrics.get(toolName) || {
calls: 0, successes: 0, failures: 0, totalDuration: 0, lastCall: null
};
existing.calls++;
existing.totalDuration += duration;
existing.lastCall = new Date();
if (success) existing.successes++;
else existing.failures++;
this.metrics.set(toolName, existing);
}
getMetrics(): Record<string, ToolMetrics & { avgDuration: number; successRate: number }> {
const result: Record<string, any> = {};
for (const [name, m] of this.metrics) {
result[name] = {
...m,
avgDuration: m.calls > 0 ? m.totalDuration / m.calls : 0,
successRate: m.calls > 0 ? m.successes / m.calls : 0,
};
}
return result;
}
}
export const metricsCollector = new MetricsCollector();
Phase 6: Code Quality & Cleanup
6.1 Naming Standardization
| Current | Issue | Fix |
|---|---|---|
log_decision |
snake_case | Keep (consistent with MCP convention) |
handleLogDecision |
camelCase handler | Keep (TypeScript convention) |
| Tool descriptions use "camelCase" | Inconsistent | Standardize to snake_case in descriptions |
super_recall_episodes |
Verbose | Consolidate into intelligence gateway |
Rule: All tool names use snake_case. All TypeScript functions use camelCase.
6.2 Dead Code Removal
| File | Issue | Action |
|---|---|---|
server.ts:538 |
References "Session 1007" | Remove comment |
poc_websocket_test |
POC complete | Archive to tools/archived/ |
list_contexts, load_tools |
Superseded by discover_tools |
Archive |
self_modify_system |
Too dangerous | Archive with warning |
6.3 Prompts Audit
32 prompts exist in /Users/fguijarro/.cursor/projects/Users-fguijarro-developer-repos-editor2/mcps/user-mcp-gograb-ai/prompts/.
| Prompt | Usage | Verdict |
|---|---|---|
preflight.json |
HIGH | Keep |
log.json |
HIGH | Keep |
find_similar.json |
HIGH | Keep |
session.json |
MEDIUM | Keep |
graph_*.json (6) |
LOW | Consolidate into graph.json |
validate_outcomes.json |
ZERO | Archive |
learn_outcomes.json |
ZERO | Archive |
transfer.json |
ZERO | Archive |
Action: Reduce from 32 prompts to ~15 prompts by consolidating and archiving unused.
Phase 7: Advanced Enhancements
7.1 Predictive Tool Suggestion
When mcp_init is called, suggest tools based on task classification:
// MCP/mcp-gograb-ai/src/tools/mcp-init.ts
const TASK_TOOL_MAP: Record<string, string[]> = {
'debug': ['intelligence', 'code', 'find_similar'],
'implement': ['preflight', 'code', 'intelligence'],
'refactor': ['code', 'intelligence', 'convention'],
'test': ['code', 'intelligence'],
'review': ['code', 'convention'],
'deploy': ['task', 'agent'],
'research': ['research', 'intelligence'],
};
function classifyTask(task: string): string {
const taskLower = task.toLowerCase();
if (taskLower.includes('bug') || taskLower.includes('error') || taskLower.includes('fix')) return 'debug';
if (taskLower.includes('implement') || taskLower.includes('create') || taskLower.includes('add')) return 'implement';
if (taskLower.includes('refactor') || taskLower.includes('clean')) return 'refactor';
if (taskLower.includes('test')) return 'test';
if (taskLower.includes('review')) return 'review';
if (taskLower.includes('deploy') || taskLower.includes('release')) return 'deploy';
if (taskLower.includes('research') || taskLower.includes('find') || taskLower.includes('search')) return 'research';
return 'implement'; // Default
}
async function handleMcpInit(args: McpInitInput): Promise<any> {
const result = await initializeSession(args);
if (args.task) {
const taskType = classifyTask(args.task);
result.suggestedTools = TASK_TOOL_MAP[taskType] || [];
result.taskClassification = taskType;
}
return result;
}
7.2 Tool Chain Learning
Track which tool sequences lead to successful outcomes, then suggest optimal chains:
// Backend service
@Injectable()
export class ToolChainLearningService {
async recordChain(chain: string[], outcome: 'success' | 'failure'): Promise<void> {
const chainKey = chain.join('→');
await this.chainModel.updateOne(
{ chain: chainKey },
{
$inc: {
totalUses: 1,
successes: outcome === 'success' ? 1 : 0
},
$set: { lastUsed: new Date() }
},
{ upsert: true }
);
}
async suggestNextTool(currentChain: string[]): Promise<string | null> {
// Find chains that start with currentChain and have high success rate
const candidates = await this.chainModel.find({
chain: { $regex: `^${currentChain.join('→')}→` },
totalUses: { $gte: 5 },
}).sort({ successRate: -1 }).limit(3);
if (candidates.length === 0) return null;
// Extract the next tool from the best chain
const bestChain = candidates[0].chain.split('→');
return bestChain[currentChain.length] || null;
}
}
7.3 Automatic Fallback Chains
When a tool fails, automatically try alternative approaches:
// MCP/mcp-gograb-ai/src/utils/fallback-chains.ts
const FALLBACK_CHAINS: Record<string, string[]> = {
'intelligence:recall': ['find_similar', 'research'],
'browser:navigate': ['desktop:execute_command'],
'code:review': ['intelligence:analyze_dna'],
};
export async function executeWithFallback(
toolName: string,
action: string,
args: any
): Promise<any> {
const key = `${toolName}:${action}`;
const fallbacks = FALLBACK_CHAINS[key] || [];
// Try primary
const result = await safeToolCall(toolName, () => executeGateway(toolName, action, args));
if (result.success) return result;
// Try fallbacks
for (const fallback of fallbacks) {
const [fbTool, fbAction] = fallback.includes(':')
? fallback.split(':')
: [fallback, action];
const fbResult = await safeToolCall(fbTool, () => executeGateway(fbTool, fbAction, args));
if (fbResult.success) {
return { ...fbResult, usedFallback: fallback };
}
}
return result; // Return original failure
}
Complete Implementation Roadmap
| Phase | Week | Days | Deliverable | Tools After |
|---|---|---|---|---|
| 1 | 1 | 1-5 | Core gateways (session, agent, outcome, stats, convention) | 94 |
| 2 | 2 | 1-5 | Intelligence + code + platform gateways | 53 |
| 3 | 3 | 1-5 | Automation gateways (browser, desktop, task, research) | 25 |
| 4 | 4 | 1-3 | Preflight/log_decision enhancements, mcp_init discovery | 25 |
| 5 | 4 | 4-5 | VITTO resilience (PM2, rate limiting) | 25 |
| 6 | 5 | 1-2 | Error boundaries, safe tool calls | 25 |
| 7 | 5 | 3-4 | Observability (healthchecks, metrics) | 25 |
| 8 | 5 | 5 | Code cleanup, naming standardization | 25 |
| 9 | 6 | 1-3 | Prompts audit, dead code removal | 25 |
| 10 | 6 | 4-5 | Advanced: predictive suggestions, chain learning | 25 |
Total: 6 weeks / ~30 engineering days
Success Metrics (Complete)
| Metric | Current | Target (30 days) | Target (90 days) | How to Measure |
|---|---|---|---|---|
| Tool count | 121 | 25 | 25 | ls tools/*.json | wc -l |
| Tool usage coverage | 21% | 60% | 85% | Usage log analysis |
| Outcome feedback rate | 0.3% | 50% | 80% | report_outcome / log_decision |
| Preflight cache hit rate | Unknown | 50% | 70% | Add metric to preflight handler |
| VITTO uptime | Unknown | 95% | 99.9% | Healthcheck endpoint |
| Avg tool latency | Unknown | <500ms | <200ms | Metrics collector |
| Tool error rate | Unknown | <10% | <2% | Error boundary logs |
| Agent cognitive load | HIGH | MEDIUM | LOW | User feedback |
What This Achieves (Complete)
Cognitive Simplicity: 25 tools is manageable. Agents can learn and remember them.
Intelligent Chaining: One
intelligencecall can trigger recall → simulate → reflect internally.Auto-Outcome: Every
log_decisionautomatically schedules outcome verification.Preserved Investment: All backend services remain. Only the MCP surface changes.
Discoverability:
mcp_initshows relevant tools.discover_toolsprovides full catalog.Backward Compatibility: Old tool names can be aliased to new gateways during transition.
Resilience: VITTO runs as separate process with rate limiting and circuit breakers.
Observability: Healthchecks, metrics, and error tracking for all components.
Self-Healing: Error boundaries with automatic fallback chains.
Continuous Learning: Tool chain learning improves suggestions over time.
What This Does NOT Do
- ❌ Delete backend services (they're valuable)
- ❌ Remove functionality (it's consolidated, not removed)
- ❌ Break existing workflows (aliases provide migration path)
- ❌ Require massive refactoring (handlers stay the same, routing changes)
- ❌ Ignore operational concerns (resilience, monitoring added)
Risk Mitigation
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Gateway consolidation breaks existing scripts | MEDIUM | HIGH | Maintain aliases for 90 days |
| VITTO process isolation introduces latency | LOW | MEDIUM | Use Unix sockets for IPC |
| Redis dependency adds complexity | MEDIUM | LOW | Make Redis optional with in-memory fallback |
| Error boundaries mask real issues | LOW | MEDIUM | Log all errors, alert on patterns |
| Tool chain learning suggests bad chains | LOW | LOW | Require minimum 5 uses before suggesting |
The Bottom Line
121 tools was a mistake. Not because the features are bad, but because the surface area is unmanageable.
25 tools is the target. Each tool is either:
- A core operation (preflight, log_decision, find_similar)
- A gateway that chains multiple operations intelligently
The backend is solid. The MCP layer needs surgery.
Operational hardening is critical. VITTO resilience, error boundaries, and observability are not optional.
This is the final plan. Execute it.
Appendix A: Gateway Implementation Template
// Example: session gateway
export async function handleSession(args: SessionGatewayInput): Promise<any> {
return safeToolCall('session', async () => {
switch (args.action) {
case 'set':
return handleSetSession({
sessionNumber: args.sessionNumber,
subSessionNumber: args.subSessionNumber,
description: args.description
});
case 'get':
return handleGetSessionInfo({ projectId: args.projectId });
case 'update':
return handleUpdateChatSession({
sessionNumber: args.sessionNumber,
subSessionNumber: args.subSessionNumber,
reason: args.reason,
forceSwitch: args.forceSwitch,
relock: args.relock,
continueExisting: args.continueExisting
});
case 'lock':
return handleLockChatSession({ lock: true });
case 'unlock':
return handleLockChatSession({ lock: false });
case 'register':
return handleRegisterChatContext({
taskDescription: args.taskDescription,
sessionNumber: args.sessionNumber,
subSessionNumber: args.subSessionNumber,
lockSession: args.lockSession
});
case 'summary':
return handleGetSessionSummary({ sessionID: args.sessionID });
default:
throw new Error(`Unknown session action: ${args.action}`);
}
}, { timeout: 10000 });
}
Appendix B: File Changes Summary
| File/Directory | Action | Details |
|---|---|---|
MCP/mcp-gograb-ai/src/server.ts |
MODIFY | Replace 121 tool definitions with 25 |
MCP/mcp-gograb-ai/src/tools/gateways/ |
CREATE | New directory for gateway handlers |
MCP/mcp-gograb-ai/src/tools/archived/ |
CREATE | Archive old individual tools |
MCP/mcp-gograb-ai/src/utils/safe-tool-call.ts |
CREATE | Error boundary wrapper |
MCP/mcp-gograb-ai/src/utils/metrics.ts |
CREATE | Tool metrics collector |
apis/backend-ai-api/src/app/health/ |
CREATE | Healthcheck endpoints |
apis/backend-ai-api/src/app/vitto/vitto-standalone.ts |
CREATE | Standalone VITTO entry point |
apis/backend-ai-api/ecosystem.config.js |
CREATE | PM2 configuration |
prompts/*.json |
ARCHIVE | Reduce from 32 to ~15 |
Appendix C: Migration Guide
For Existing Scripts Using Old Tool Names
// Alias mapping (temporary, remove after 90 days)
const TOOL_ALIASES: Record<string, { gateway: string; action: string }> = {
'set_session': { gateway: 'session', action: 'set' },
'get_session_info': { gateway: 'session', action: 'get' },
'create_handoff': { gateway: 'agent', action: 'handoff_create' },
'super_recall_episodes': { gateway: 'intelligence', action: 'recall' },
'self_diagnose': { gateway: 'intelligence', action: 'diagnose' },
// ... etc
};
// In server.ts tool router
if (TOOL_ALIASES[toolName]) {
const { gateway, action } = TOOL_ALIASES[toolName];
console.warn(`DEPRECATED: ${toolName} is deprecated. Use ${gateway}({ action: '${action}' }) instead.`);
return handleGateway(gateway, { action, ...args });
}
End of Final Plan
Next Action: Start Week 1, Day 1 - Create session gateway.