Jake Shore f3c4cd817b Add all MCP servers + factory infra to MCPEngine — 2026-02-06
=== NEW SERVERS ADDED (7) ===
- servers/closebot — 119 tools, 14 modules, 4,656 lines TS (Stage 7)
- servers/google-console — Google Search Console MCP (Stage 7)
- servers/meta-ads — Meta/Facebook Ads MCP (Stage 8)
- servers/twilio — Twilio communications MCP (Stage 8)
- servers/competitor-research — Competitive intel MCP (Stage 6)
- servers/n8n-apps — n8n workflow MCP apps (Stage 6)
- servers/reonomy — Commercial real estate MCP (Stage 1)

=== FACTORY INFRASTRUCTURE ADDED ===
- infra/factory-tools — mcp-jest, mcp-validator, mcp-add, MCP Inspector
  - 60 test configs, 702 auto-generated test cases
  - All 30 servers score 100/100 protocol compliance
- infra/command-center — Pipeline state, operator playbook, dashboard config
- infra/factory-reviews — Automated eval reports

=== DOCS ADDED ===
- docs/MCP-FACTORY.md — Factory overview
- docs/reports/ — 5 pipeline evaluation reports
- docs/research/ — Browser MCP research

=== RULES ESTABLISHED ===
- CONTRIBUTING.md — All MCP work MUST go in this repo
- README.md — Full inventory of 37 servers + infra docs
- .gitignore — Updated for Python venvs

TOTAL: 37 MCP servers + full factory pipeline in one repo.
This is now the single source of truth for all MCP work.
2026-02-06 06:32:29 -05:00

213 lines
6.4 KiB
JavaScript

#!/usr/bin/env node
import { config } from 'dotenv';
import { AuthManager } from './auth/oauth.js';
import { MetaApiClient } from './client/meta-client.js';
import { RateLimiter } from './client/rate-limiter.js';
import {
createMcpServer,
connectServer,
ToolRegistry,
ModuleRegistry,
createGatewayTool,
} from './server.js';
// Import Tier 1 (core) tool modules
import { registerAccountTools } from './tools/account.js';
import { registerCampaignTools } from './tools/campaigns.js';
import { registerAdSetTools } from './tools/ad-sets.js';
import { registerAdTools } from './tools/ads.js';
/**
* Main entry point for Meta Ads MCP server
*/
async function main() {
// Load environment variables
config();
const accessToken = process.env.META_ACCESS_TOKEN;
const appId = process.env.META_APP_ID;
const appSecret = process.env.META_APP_SECRET;
const apiVersion = process.env.META_API_VERSION || 'v21.0';
if (!accessToken) {
console.error('Error: META_ACCESS_TOKEN environment variable is required');
process.exit(1);
}
console.error('[MCP] Initializing Meta Ads MCP Server...');
// Initialize auth and client
const authManager = new AuthManager(accessToken, appId, appSecret);
const rateLimiter = new RateLimiter(5); // Max 5 concurrent requests
// Cache available for future use
// const cache = new SimpleCache(1000, 300); // 1000 entries, 5 minute TTL
const client = new MetaApiClient(authManager, { apiVersion }, rateLimiter);
// Validate token on startup
try {
console.error('[MCP] Validating access token...');
const tokenInfo = await authManager.validateToken();
console.error(`[MCP] Token valid. User ID: ${tokenInfo.userId}, Expires: ${tokenInfo.expiresAt ? new Date(tokenInfo.expiresAt).toISOString() : 'never'}`);
// Warn if token expires soon
if (authManager.isTokenExpired(60)) {
console.error('[MCP] WARNING: Access token expires within 1 hour. Consider refreshing.');
}
} catch (error) {
console.error(`[MCP] Token validation failed: ${error instanceof Error ? error.message : String(error)}`);
console.error('[MCP] Server will start but API calls may fail. Please check your META_ACCESS_TOKEN.');
}
// Create tool and module registries
const toolRegistry = new ToolRegistry(client);
const moduleRegistry = new ModuleRegistry(toolRegistry);
// Register Tier 1 (core) modules - loaded immediately
console.error('[MCP] Registering core modules (Tier 1)...');
moduleRegistry.registerModule({
category: 'account',
tier: 'core',
loaded: false,
register: registerAccountTools,
});
moduleRegistry.registerModule({
category: 'campaigns',
tier: 'core',
loaded: false,
register: registerCampaignTools,
});
moduleRegistry.registerModule({
category: 'adsets',
tier: 'core',
loaded: false,
register: registerAdSetTools,
});
moduleRegistry.registerModule({
category: 'ads',
tier: 'core',
loaded: false,
register: registerAdTools,
});
// Load core modules immediately
await moduleRegistry.loadModule('account');
await moduleRegistry.loadModule('campaigns');
await moduleRegistry.loadModule('adsets');
await moduleRegistry.loadModule('ads');
// Register Tier 2 (advanced) modules - lazy loaded via gateway tools
console.error('[MCP] Registering advanced modules (Tier 2) as gateway tools...');
// Analytics module (gateway)
moduleRegistry.registerModule({
category: 'analytics',
tier: 'advanced',
loaded: false,
register: async (registry) => {
// This would be implemented in src/tools/analytics.ts
// For now, just a placeholder
console.error('[MCP] Analytics module loaded (placeholder)');
registry.registerTool({
name: 'get_insights_placeholder',
description: 'Placeholder for insights tool',
inputSchema: require('zod').z.object({}),
handler: async () => ({
content: [{ type: 'text', text: 'Analytics module loaded but not yet implemented' }],
}),
});
},
});
toolRegistry.registerTool(
createGatewayTool(
'analytics',
moduleRegistry,
'Load analytics and insights tools for campaign performance analysis'
)
);
// Audiences module (gateway)
moduleRegistry.registerModule({
category: 'audiences',
tier: 'advanced',
loaded: false,
register: async (registry) => {
console.error('[MCP] Audiences module loaded (placeholder)');
registry.registerTool({
name: 'list_audiences_placeholder',
description: 'Placeholder for audience tools',
inputSchema: require('zod').z.object({}),
handler: async () => ({
content: [{ type: 'text', text: 'Audiences module loaded but not yet implemented' }],
}),
});
},
});
toolRegistry.registerTool(
createGatewayTool(
'audiences',
moduleRegistry,
'Load audience management tools for custom audiences, lookalikes, and saved audiences'
)
);
// Budget optimization module (gateway)
moduleRegistry.registerModule({
category: 'budget',
tier: 'advanced',
loaded: false,
register: async (registry) => {
console.error('[MCP] Budget module loaded (placeholder)');
registry.registerTool({
name: 'optimize_budget_placeholder',
description: 'Placeholder for budget tools',
inputSchema: require('zod').z.object({}),
handler: async () => ({
content: [{ type: 'text', text: 'Budget module loaded but not yet implemented' }],
}),
});
},
});
toolRegistry.registerTool(
createGatewayTool(
'budget',
moduleRegistry,
'Load budget optimization tools for CBO management and budget recommendations'
)
);
// Create and connect MCP server
const server = createMcpServer(toolRegistry);
// Graceful shutdown handling
const shutdown = async () => {
console.error('[MCP] Shutting down...');
process.exit(0);
};
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
// Connect to stdio transport
await connectServer(server);
// Log module status
const moduleStatus = moduleRegistry.getModuleStatus();
console.error('[MCP] Module status:', JSON.stringify(moduleStatus, null, 2));
console.error(`[MCP] Registered ${toolRegistry.getTools().length} tools`);
console.error('[MCP] Server ready!');
}
// Run the server
main().catch((error) => {
console.error('[MCP] Fatal error:', error);
process.exit(1);
});