=== 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.
157 lines
4.8 KiB
JavaScript
157 lines
4.8 KiB
JavaScript
#!/usr/bin/env node
|
|
// ============================================================================
|
|
// CloseBot MCP Server — Main Entry Point
|
|
// Lazy-loaded tool groups, 6 rich UI tool apps, ~55 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";
|
|
import { CloseBotClient } from "./client.js";
|
|
import type { ToolDefinition, ToolResult } from "./types.js";
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Lazy-loaded module registry
|
|
// ---------------------------------------------------------------------------
|
|
|
|
interface ToolModule {
|
|
tools: ToolDefinition[];
|
|
handle: (
|
|
client: CloseBotClient,
|
|
name: string,
|
|
args: Record<string, unknown>
|
|
) => Promise<ToolResult>;
|
|
}
|
|
|
|
interface LazyGroup {
|
|
/** File path (relative) for dynamic import */
|
|
path: string;
|
|
/** Cached module after first load */
|
|
module?: ToolModule;
|
|
/** Tool metadata — populated eagerly, handler loaded lazily */
|
|
toolNames: string[];
|
|
}
|
|
|
|
// Tool groups — we import metadata eagerly but handler code lazily
|
|
const groups: LazyGroup[] = [
|
|
{ path: "./tools/bot-management.js", toolNames: [] },
|
|
{ path: "./tools/source-management.js", toolNames: [] },
|
|
{ path: "./tools/lead-management.js", toolNames: [] },
|
|
{ path: "./tools/analytics.js", toolNames: [] },
|
|
{ path: "./tools/bot-testing.js", toolNames: [] },
|
|
{ path: "./tools/library.js", toolNames: [] },
|
|
{ path: "./tools/agency-billing.js", toolNames: [] },
|
|
{ path: "./tools/configuration.js", toolNames: [] },
|
|
// Apps
|
|
{ path: "./apps/bot-dashboard.js", toolNames: [] },
|
|
{ path: "./apps/analytics-dashboard.js", toolNames: [] },
|
|
{ path: "./apps/test-console.js", toolNames: [] },
|
|
{ path: "./apps/lead-manager.js", toolNames: [] },
|
|
{ path: "./apps/library-manager.js", toolNames: [] },
|
|
{ path: "./apps/leaderboard.js", toolNames: [] },
|
|
];
|
|
|
|
// Map: toolName → group index (for fast dispatch)
|
|
const toolToGroup = new Map<string, number>();
|
|
// All tool definitions (populated on init)
|
|
let allTools: ToolDefinition[] = [];
|
|
|
|
async function loadGroupMetadata(): Promise<void> {
|
|
const toolDefs: ToolDefinition[] = [];
|
|
for (let i = 0; i < groups.length; i++) {
|
|
const mod = (await import(groups[i].path)) as ToolModule;
|
|
groups[i].module = mod;
|
|
groups[i].toolNames = mod.tools.map((t) => t.name);
|
|
for (const tool of mod.tools) {
|
|
toolToGroup.set(tool.name, i);
|
|
toolDefs.push(tool);
|
|
}
|
|
}
|
|
allTools = toolDefs;
|
|
}
|
|
|
|
async function getHandler(
|
|
toolName: string
|
|
): Promise<ToolModule["handle"] | null> {
|
|
const idx = toolToGroup.get(toolName);
|
|
if (idx === undefined) return null;
|
|
const group = groups[idx];
|
|
if (!group.module) {
|
|
group.module = (await import(group.path)) as ToolModule;
|
|
}
|
|
return group.module.handle;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Server setup
|
|
// ---------------------------------------------------------------------------
|
|
|
|
async function main(): Promise<void> {
|
|
// Init client (validates API key)
|
|
let client: CloseBotClient;
|
|
try {
|
|
client = new CloseBotClient();
|
|
} catch (e) {
|
|
console.error(
|
|
(e as Error).message ||
|
|
"Failed to initialize. Set CLOSEBOT_API_KEY env var."
|
|
);
|
|
process.exit(1);
|
|
}
|
|
|
|
// Load all tool metadata
|
|
await loadGroupMetadata();
|
|
|
|
const server = new Server(
|
|
{
|
|
name: "closebot-mcp",
|
|
version: "1.0.0",
|
|
},
|
|
{
|
|
capabilities: {
|
|
tools: {},
|
|
},
|
|
}
|
|
);
|
|
|
|
// --- List Tools ---
|
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
return {
|
|
tools: allTools.map((t) => ({
|
|
name: t.name,
|
|
description: t.description,
|
|
inputSchema: t.inputSchema,
|
|
})),
|
|
};
|
|
});
|
|
|
|
// --- Call Tool ---
|
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
const { name, arguments: args } = request.params;
|
|
const handler = await getHandler(name);
|
|
if (!handler) {
|
|
return {
|
|
content: [{ type: "text" as const, text: `Unknown tool: ${name}` }],
|
|
isError: true,
|
|
} as Record<string, unknown>;
|
|
}
|
|
const result = await handler(client, name, (args as Record<string, unknown>) || {});
|
|
return result as unknown as Record<string, unknown>;
|
|
});
|
|
|
|
// --- Connect stdio transport ---
|
|
const transport = new StdioServerTransport();
|
|
await server.connect(transport);
|
|
console.error(
|
|
`CloseBot MCP server running — ${allTools.length} tools loaded across ${groups.length} modules`
|
|
);
|
|
}
|
|
|
|
main().catch((err) => {
|
|
console.error("Fatal error:", err);
|
|
process.exit(1);
|
|
});
|