#!/usr/bin/env node
/**
* Cloud Orchestrator MCP Server
* Exposes 100+ AI capabilities to Claude Code as native tools
*/
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
const ORCHESTRATOR_URL = process.env.ORCHESTRATOR_URL || 'https://web-production-bdfb4.up.railway.app';
// Helper to call orchestrator
async function callOrchestrator(endpoint, method = 'GET', body = null) {
const options = {
method,
headers: { 'Content-Type': 'application/json' }
};
if (body) options.body = JSON.stringify(body);
const response = await fetch(`${ORCHESTRATOR_URL}${endpoint}`, options);
return await response.json();
}
// Create server
const server = new Server(
{ name: 'orchestrator-mcp', version: '1.0.0' },
{ capabilities: { tools: {} } }
);
// Define available tools
const TOOLS = [
// === THINKING & REASONING ===
{
name: 'think',
description: 'Deep reasoning using cognitive orchestrator. Auto-routes to best AI capabilities. Use for complex analysis, multi-step reasoning, research questions.',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'The question or task requiring deep thought' },
context: { type: 'string', description: 'Optional additional context' }
},
required: ['query']
}
},
{
name: 'consensus',
description: 'Get multiple AI perspectives (Claude, GPT, Gemini) and synthesize consensus. Use for important decisions.',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'Question to get consensus on' },
detailed: { type: 'boolean', description: 'Include individual AI responses' }
},
required: ['query']
}
},
{
name: 'fast_ai',
description: 'Ultra-fast AI response via Groq (~100ms). Use for quick questions.',
inputSchema: {
type: 'object',
properties: {
content: { type: 'string', description: 'Quick question' }
},
required: ['content']
}
},
// === WEB & RESEARCH ===
{
name: 'web_search',
description: 'Real-time web search via Perplexity. Use for current events, recent info, live data.',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'Search query' }
},
required: ['query']
}
},
{
name: 'scrape_url',
description: 'Scrape and extract content from any URL via Firecrawl.',
inputSchema: {
type: 'object',
properties: {
url: { type: 'string', description: 'URL to scrape' },
formats: { type: 'array', items: { type: 'string' }, description: 'Output formats: markdown, html, text' }
},
required: ['url']
}
},
// === CODE EXECUTION ===
{
name: 'run_python',
description: 'Execute Python code in secure E2B sandbox. Use for data analysis, calculations, testing.',
inputSchema: {
type: 'object',
properties: {
code: { type: 'string', description: 'Python code to execute' },
timeout: { type: 'number', description: 'Timeout in ms (default 30000)' }
},
required: ['code']
}
},
{
name: 'run_javascript',
description: 'Execute JavaScript code in secure E2B sandbox.',
inputSchema: {
type: 'object',
properties: {
code: { type: 'string', description: 'JavaScript code to execute' }
},
required: ['code']
}
},
// === MEMORY & KNOWLEDGE ===
{
name: 'mem0_add',
description: 'Store information in Mem0 long-term memory.',
inputSchema: {
type: 'object',
properties: {
content: { type: 'string', description: 'Information to remember' },
userId: { type: 'string', description: 'User ID (default: matt)' },
metadata: { type: 'object', description: 'Optional metadata' }
},
required: ['content']
}
},
{
name: 'mem0_search',
description: 'Search Mem0 long-term memory.',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'Search query' },
userId: { type: 'string', description: 'User ID (default: matt)' },
limit: { type: 'number', description: 'Max results (default 5)' }
},
required: ['query']
}
},
{
name: 'neo4j_query',
description: 'Query Neo4j knowledge graph for entity relationships.',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'Natural language query about entities/relationships' },
labels: { type: 'array', items: { type: 'string' }, description: 'Entity types to search' }
},
required: ['query']
}
},
// === RAILWAY MANAGEMENT ===
{
name: 'railway_status',
description: 'Get deployment status of all Railway services.',
inputSchema: { type: 'object', properties: {} }
},
{
name: 'railway_set_variable',
description: 'Set environment variable on a Railway service.',
inputSchema: {
type: 'object',
properties: {
service: { type: 'string', enum: ['cloud-orchestrator', 'rei-api', 'claude-remote'], description: 'Service name' },
key: { type: 'string', description: 'Variable name' },
value: { type: 'string', description: 'Variable value' }
},
required: ['service', 'key', 'value']
}
},
{
name: 'railway_redeploy',
description: 'Trigger redeployment of a Railway service.',
inputSchema: {
type: 'object',
properties: {
service: { type: 'string', enum: ['cloud-orchestrator', 'rei-api', 'claude-remote'], description: 'Service to redeploy' }
},
required: ['service']
}
},
// === GITHUB ===
{
name: 'github_repos',
description: 'List GitHub repositories.',
inputSchema: { type: 'object', properties: {} }
},
{
name: 'github_file',
description: 'Read a file from a GitHub repository.',
inputSchema: {
type: 'object',
properties: {
repo: { type: 'string', description: 'Repository name' },
path: { type: 'string', description: 'File path in repo' }
},
required: ['repo', 'path']
}
},
// === HEALTH ===
{
name: 'health',
description: 'Check health status of cloud orchestrator and all connected services.',
inputSchema: { type: 'object', properties: {} }
},
// === WOLFRAM ALPHA ===
{
name: 'wolfram_query',
description: 'Query Wolfram Alpha for math, science, calculations, conversions, real-time data. Use for any computational question.',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string', description: 'Natural language query (e.g., "derivative of x^2", "convert 100 miles to km", "weather in NYC")' }
},
required: ['query']
}
},
{
name: 'wolfram_calculate',
description: 'Calculate a math expression using Wolfram Alpha.',
inputSchema: {
type: 'object',
properties: {
expr: { type: 'string', description: 'Math expression (e.g., "sqrt(144)", "2^10", "sin(45 degrees)")' }
},
required: ['expr']
}
},
{
name: 'wolfram_convert',
description: 'Convert between units using Wolfram Alpha.',
inputSchema: {
type: 'object',
properties: {
from: { type: 'string', description: 'Value with unit (e.g., "100 miles", "72 fahrenheit")' },
to: { type: 'string', description: 'Target unit (e.g., "kilometers", "celsius")' }
},
required: ['from', 'to']
}
},
// === OPENROUTER (Access ALL AI models) ===
{
name: 'openrouter_chat',
description: 'Query ANY AI model via OpenRouter. Access Claude, GPT, Llama, Mistral, and 100+ models through single API.',
inputSchema: {
type: 'object',
properties: {
content: { type: 'string', description: 'The prompt/message' },
model: { type: 'string', description: 'Model ID (e.g., "meta-llama/llama-3.1-70b-instruct", "anthropic/claude-3.5-sonnet", "openai/gpt-4o"). Default: claude-3.5-sonnet' }
},
required: ['content']
}
},
{
name: 'openrouter_models',
description: 'List all available AI models on OpenRouter.',
inputSchema: { type: 'object', properties: {} }
},
// === SENTRY ERROR TRACKING ===
{
name: 'sentry_stats',
description: 'Get error tracking statistics from Sentry.',
inputSchema: { type: 'object', properties: {} }
},
{
name: 'sentry_errors',
description: 'Get recent errors captured by Sentry.',
inputSchema: {
type: 'object',
properties: {
limit: { type: 'number', description: 'Number of errors to return (default: 20)' }
}
}
},
// === API KEYS MANAGEMENT ===
{
name: 'api_keys_summary',
description: 'Get summary of all API keys status from the configuration sheet. Shows active, missing, and high-impact services.',
inputSchema: { type: 'object', properties: {} }
},
{
name: 'api_keys_missing',
description: 'List all services that are still missing API keys.',
inputSchema: { type: 'object', properties: {} }
},
{
name: 'api_keys_ready',
description: 'List services that have API keys filled in and are ready to inject to Railway.',
inputSchema: { type: 'object', properties: {} }
},
{
name: 'api_keys_inject',
description: 'Inject a specific service API key from the sheet to Railway.',
inputSchema: {
type: 'object',
properties: {
serviceName: { type: 'string', description: 'Service name (e.g., "OpenRouter", "Mistral AI")' },
targets: { type: 'array', items: { type: 'string' }, description: 'Railway services to inject to (default: cloud-orchestrator)' }
},
required: ['serviceName']
}
},
{
name: 'api_keys_inject_all',
description: 'Inject ALL ready API keys from the sheet to Railway services.',
inputSchema: {
type: 'object',
properties: {
targets: { type: 'array', items: { type: 'string' }, description: 'Railway services to inject to (default: cloud-orchestrator)' }
}
}
}
];
// Handle list tools
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: TOOLS
}));
// Handle tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
let result;
switch (name) {
case 'think':
result = await callOrchestrator('/think', 'POST', {
query: args.query,
context: args.context
});
break;
case 'consensus':
result = await callOrchestrator('/ai/consensus', 'POST', {
content: args.query,
detailed: args.detailed
});
break;
case 'fast_ai':
result = await callOrchestrator('/ai/fast', 'POST', {
content: args.content
});
break;
case 'web_search':
result = await callOrchestrator('/ai/web_search', 'POST', {
query: args.query
});
break;
case 'scrape_url':
result = await callOrchestrator('/firecrawl/scrape', 'POST', {
url: args.url,
formats: args.formats || ['markdown']
});
break;
case 'run_python':
result = await callOrchestrator('/e2b/python', 'POST', {
code: args.code,
timeout: args.timeout || 30000
});
break;
case 'run_javascript':
result = await callOrchestrator('/e2b/javascript', 'POST', {
code: args.code
});
break;
case 'mem0_add':
result = await callOrchestrator('/mem0/add', 'POST', {
content: args.content,
userId: args.userId || 'matt',
metadata: args.metadata
});
break;
case 'mem0_search':
result = await callOrchestrator('/mem0/search', 'POST', {
query: args.query,
userId: args.userId || 'matt',
options: { limit: args.limit || 5 }
});
break;
case 'neo4j_query':
result = await callOrchestrator('/neo4j/query', 'POST', {
query: args.query,
labels: args.labels
});
break;
case 'railway_status':
result = await callOrchestrator('/railway/status');
break;
case 'railway_set_variable':
result = await callOrchestrator(`/railway/variables/${args.service}`, 'POST', {
key: args.key,
value: args.value
});
break;
case 'railway_redeploy':
result = await callOrchestrator(`/railway/redeploy/${args.service}`, 'POST');
break;
case 'github_repos':
result = await callOrchestrator('/github/repos');
break;
case 'github_file':
result = await callOrchestrator(`/github/repos/sabriotcore-code/${args.repo}/file/${args.path}`);
break;
case 'health':
result = await callOrchestrator('/health');
break;
case 'wolfram_query':
result = await callOrchestrator(`/wolfram/query?q=${encodeURIComponent(args.query)}`);
break;
case 'wolfram_calculate':
result = await callOrchestrator(`/wolfram/calculate?expr=${encodeURIComponent(args.expr)}`);
break;
case 'wolfram_convert':
result = await callOrchestrator(`/wolfram/convert?from=${encodeURIComponent(args.from)}&to=${encodeURIComponent(args.to)}`);
break;
case 'openrouter_chat':
result = await callOrchestrator('/ai/openrouter', 'POST', {
content: args.content,
model: args.model
});
break;
case 'openrouter_models':
result = await callOrchestrator('/ai/openrouter/models');
break;
case 'sentry_stats':
result = await callOrchestrator('/sentry/stats');
break;
case 'sentry_errors':
result = await callOrchestrator(`/sentry/errors?limit=${args.limit || 20}`);
break;
case 'api_keys_summary':
result = await callOrchestrator('/api-keys/summary');
break;
case 'api_keys_missing':
result = await callOrchestrator('/api-keys/missing');
break;
case 'api_keys_ready':
result = await callOrchestrator('/api-keys/ready');
break;
case 'api_keys_inject':
result = await callOrchestrator(`/api-keys/inject/${encodeURIComponent(args.serviceName)}`, 'POST', {
targets: args.targets || ['cloud-orchestrator']
});
break;
case 'api_keys_inject_all':
result = await callOrchestrator('/api-keys/inject-all', 'POST', {
targets: args.targets || ['cloud-orchestrator']
});
break;
default:
throw new Error(`Unknown tool: ${name}`);
}
return {
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }]
};
} catch (error) {
return {
content: [{ type: 'text', text: `Error: ${error.message}` }],
isError: true
};
}
});
// Start server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('Orchestrator MCP server running');
}
main().catch(console.error);