UNPKG

@battle-racing/br-common-lib

Version:

Common library for all Battle Racing Repositorios

175 lines (174 loc) 6.6 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js"); const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js"); const zod_1 = require("zod"); const fs = __importStar(require("fs")); const path = __importStar(require("path")); /** * MCP Server for Battle Racing Common Library * This server allows other AI agents to query types, schemas and constants * from the br-common-lib repository locally. */ const DOMAINS_DIR = path.resolve(__dirname, "../../src/domains"); const server = new mcp_js_1.McpServer({ name: "br-common-lib-mcp", version: "1.1.1", }); /** * List all available domains in src/domains */ async function listDomains() { if (!fs.existsSync(DOMAINS_DIR)) { throw new Error(`Domains directory not found at ${DOMAINS_DIR}`); } const entries = fs.readdirSync(DOMAINS_DIR, { withFileTypes: true }); return entries .filter((entry) => entry.isDirectory()) .map((entry) => entry.name); } /** * Get details for a specific domain (recursive) */ async function getDomainDetails(domain) { const domainPath = path.join(DOMAINS_DIR, domain); if (!fs.existsSync(domainPath)) { throw new Error(`Domain "${domain}" not found at ${domainPath}`); } let output = `## Domain: ${domain}\n\n`; function readDirRecursive(dir) { const entries = fs.readdirSync(dir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) { readDirRecursive(fullPath); } else if (entry.name.endsWith(".types.ts") || entry.name.endsWith(".schema.ts") || entry.name.endsWith(".const.ts") || entry.name === "index.ts") { const relativePath = path.relative(domainPath, fullPath); const content = fs.readFileSync(fullPath, "utf-8"); output += `### File: ${relativePath}\n\`\`\`typescript\n${content}\n\`\`\`\n\n`; } } } readDirRecursive(domainPath); return output; } /** * Search for a symbol (type, constant, etc) across all domains */ async function searchSymbol(query) { const domains = await listDomains(); let results = []; for (const domain of domains) { const domainPath = path.join(DOMAINS_DIR, domain); function searchInDir(dir) { const entries = fs.readdirSync(dir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) { searchInDir(fullPath); } else if (entry.isFile() && (entry.name.endsWith(".ts"))) { const content = fs.readFileSync(fullPath, "utf-8"); if (content.includes(query)) { const lines = content.split("\n"); const matchLine = lines.find(l => l.includes(query)) || ""; results.push({ domain, file: path.relative(DOMAINS_DIR, fullPath), match: matchLine.trim() }); } } } } searchInDir(domainPath); } if (results.length === 0) return `No results found for "${query}"`; return results .map(r => `- [${r.domain}] ${r.file}: \`${r.match}\``) .join("\n"); } // Register tools using the high-level McpServer API (registerTool) server.registerTool("list_domains", { description: "List all available domains in br-common-lib (e.g., kart, game, powerUp)", }, async () => { const domains = await listDomains(); return { content: [ { type: "text", text: `Available domains: ${domains.join(", ")}`, }, ], }; }); server.registerTool("get_domain_details", { description: "Get all types, schemas, and constants for a specific domain (recursive)", inputSchema: zod_1.z.object({ domain: zod_1.z.string().describe("The name of the domain (e.g., 'kart')"), }), }, async ({ domain }) => { const details = await getDomainDetails(domain); return { content: [{ type: "text", text: details }], }; }); server.registerTool("search_symbol", { description: "Search for a specific type, constant or property across all domains", inputSchema: zod_1.z.object({ query: zod_1.z.string().describe("The symbol or string to search for (e.g., 'hardwareState')"), }), }, async ({ query }) => { const results = await searchSymbol(query); return { content: [{ type: "text", text: results }], }; }); // Start the server async function main() { const transport = new stdio_js_1.StdioServerTransport(); await server.connect(transport); console.error("Battle Racing Common Lib MCP Server running on stdio"); } main().catch((error) => { console.error("Fatal error in main():", error); process.exit(1); });