il2cpp-dump-analyzer-mcp
Version:
Agentic RAG system for analyzing IL2CPP dump.cs files from Unity games
291 lines • 10.3 kB
JavaScript
;
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