UNPKG

il2cpp-dump-analyzer-mcp

Version:

Agentic RAG system for analyzing IL2CPP dump.cs files from Unity games

291 lines 10.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.initializeVectorStore = initializeVectorStore; exports.startMcpServer = startMcpServer; const express_1 = __importDefault(require("express")); // Global vector store instance let vectorStore = null; /** * Initialize the MCP server with a vector store * @param store Vector store instance */ function initializeVectorStore(store) { vectorStore = store; } /** * Start the MCP server * @param port Port to listen on * @param host Host to bind to */ function startMcpServer(port, host) { const app = (0, express_1.default)(); // Middleware for parsing JSON app.use(express_1.default.json()); // Metadata endpoint app.get('/metadata', (req, res) => { const metadata = { name: 'IL2CPP Dump Analyzer', description: 'A specialized RAG system for analyzing IL2CPP dump.cs files from Unity games', schema_version: '1.0', human_can_retrieve: true, retrieval_options: { top_k: { type: 'integer', description: 'Number of results to return', required: false, default: 5 }, filter_type: { type: 'string', description: 'Filter results by entity type (class, method, enum, interface)', required: false }, filter_namespace: { type: 'string', description: 'Filter results by namespace', required: false }, filter_monobehaviour: { type: 'boolean', description: 'Filter results to only include MonoBehaviour classes', required: false, default: false } } }; res.json(metadata); }); // Retrieval endpoint app.post('/retrieve', async (req, res) => { try { if (!vectorStore) { const error = { error: { message: 'Vector store not initialized', type: 'server_error' } }; return res.status(500).json(error); } const retrievalRequest = req.body; if (!retrievalRequest.query) { const error = { error: { message: 'Query is required', type: 'invalid_request_error', param: 'query' } }; return res.status(400).json(error); } // Extract options const options = retrievalRequest.options || {}; const topK = options.top_k || 5; // Build filter const filter = {}; if (options.filter_type) { filter.type = options.filter_type; } if (options.filter_namespace) { filter.namespace = options.filter_namespace; } if (options.filter_monobehaviour) { filter.isMonoBehaviour = true; } // Perform search let results = []; if (Object.keys(filter).length > 0) { results = await vectorStore.searchWithFilter(retrievalRequest.query, filter, topK); } else { results = await vectorStore.similaritySearch(retrievalRequest.query, topK); } // Format response const response = { documents: results.map(doc => ({ content: doc.pageContent, metadata: doc.metadata })) }; res.json(response); } catch (error) { console.error('Error in /retrieve:', error); const errorResponse = { error: { message: error instanceof Error ? error.message : 'Unknown error', type: 'server_error' } }; res.status(500).json(errorResponse); } }); // Tools endpoint app.get('/tools', (req, res) => { const toolsResponse = { tools: [ { name: 'search_code', description: 'Search for code in the IL2CPP dump', input_schema: { type: 'object', properties: { query: { type: 'string', description: 'The search query' }, filter_type: { type: 'string', description: 'Filter by entity type (class, method, enum, interface)' }, top_k: { type: 'integer', description: 'Number of results to return' } }, required: ['query'] } }, { name: 'find_monobehaviours', description: 'Find MonoBehaviour classes in the IL2CPP dump', input_schema: { type: 'object', properties: { query: { type: 'string', description: 'Optional search query to filter MonoBehaviours' }, top_k: { type: 'integer', description: 'Number of results to return' } }, required: [] } } ] }; res.json(toolsResponse); }); // Tool call endpoint app.post('/tools/:tool_name', async (req, res) => { try { if (!vectorStore) { const error = { error: { message: 'Vector store not initialized', type: 'server_error' } }; return res.status(500).json(error); } const toolName = req.params.tool_name; const toolCallRequest = req.body; let response; switch (toolName) { case 'search_code': response = await handleSearchCodeTool(toolCallRequest, vectorStore); break; case 'find_monobehaviours': response = await handleFindMonoBehavioursTool(toolCallRequest, vectorStore); break; default: const error = { error: { message: `Unknown tool: ${toolName}`, type: 'invalid_request_error', param: 'tool_name' } }; return res.status(400).json(error); } res.json(response); } catch (error) { console.error(`Error in /tools/${req.params.tool_name}:`, error); const errorResponse = { error: { message: error instanceof Error ? error.message : 'Unknown error', type: 'server_error' } }; res.status(500).json(errorResponse); } }); // Start the server app.listen(port, host, () => { console.log(`MCP server listening at http://${host}:${port}`); }); } /** * Handle the search_code tool call * @param request Tool call request * @param store Vector store instance * @returns Tool call response */ async function handleSearchCodeTool(request, store) { const query = request.arguments.query; const filterType = request.arguments.filter_type; const topK = request.arguments.top_k || 5; const filter = {}; if (filterType) { filter.type = filterType; } let results; if (Object.keys(filter).length > 0) { results = await store.searchWithFilter(query, filter, topK); } else { results = await store.similaritySearch(query, topK); } // Format the results const formattedResults = results.map(doc => ({ content: doc.pageContent, type: doc.metadata.type, name: doc.metadata.name, namespace: doc.metadata.namespace, fullName: doc.metadata.fullName })); return { content: JSON.stringify(formattedResults, null, 2), metadata: { result_count: results.length, query: query, filter_type: filterType } }; } /** * Handle the find_monobehaviours tool call * @param request Tool call request * @param store Vector store instance * @returns Tool call response */ async function handleFindMonoBehavioursTool(request, store) { const query = request.arguments.query || ''; const topK = request.arguments.top_k || 10; const filter = { type: 'class', isMonoBehaviour: true }; const results = await store.searchWithFilter(query, filter, topK); // Format the results const formattedResults = results.map(doc => ({ content: doc.pageContent, name: doc.metadata.name, namespace: doc.metadata.namespace, fullName: doc.metadata.fullName })); return { content: JSON.stringify(formattedResults, null, 2), metadata: { result_count: results.length, query: query || 'All MonoBehaviours' } }; } //# sourceMappingURL=server.js.map