@ariadnejs/mcp
Version:
Model Context Protocol server for Ariadne - Expose code intelligence capabilities to AI agents
223 lines • 9.32 kB
JavaScript
;
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 });
exports.startServer = startServer;
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
const core_1 = require("@ariadnejs/core");
const path = __importStar(require("path"));
const fs = __importStar(require("fs/promises"));
const get_symbol_context_1 = require("./tools/get_symbol_context");
const version_1 = require("./version");
async function startServer(options = {}) {
// Support PROJECT_PATH environment variable as per task 53
const projectPath = options.projectPath || process.env.PROJECT_PATH || process.cwd();
// Create the MCP server
const server = new index_js_1.Server({
name: "ariadne-mcp",
version: version_1.VERSION
}, {
capabilities: {
tools: {}
}
});
// Initialize Ariadne project
const project = new core_1.Project();
// Register tools handler
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "get_symbol_context",
description: "Get comprehensive information about any code symbol by name (function, class, variable, etc.)",
inputSchema: {
type: "object",
properties: {
symbol: {
type: "string",
description: "Name of the symbol to look up"
},
searchScope: {
type: "string",
enum: ["file", "project", "dependencies"],
description: "Scope to search within (default: project)"
},
includeTests: {
type: "boolean",
description: "Whether to include test file references (default: false)"
}
},
required: ["symbol"]
}
}
]
};
});
// Handle tool calls
server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case "get_symbol_context": {
const validatedArgs = get_symbol_context_1.getSymbolContextSchema.parse(args);
// Load all files in the project if needed
// TODO: Implement smart file loading based on search scope
// For now, load all files in the project
await loadProjectFiles(project, projectPath);
const result = await (0, get_symbol_context_1.getSymbolContext)(project, validatedArgs);
return {
content: [
{
type: "text",
text: JSON.stringify(result, null, 2)
}
]
};
}
default:
throw new Error(`Unknown tool: ${name}`);
}
}
catch (error) {
return {
content: [
{
type: "text",
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}
],
isError: true
};
}
});
// Helper function to load a file if not already in the project
async function loadFileIfNeeded(project, filePath) {
try {
const sourceCode = await fs.readFile(filePath, "utf-8");
project.add_or_update_file(filePath, sourceCode);
}
catch (error) {
throw new Error(`Failed to read file ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
}
}
// Helper function to load all project files (Task 53)
async function loadProjectFiles(project, projectPath) {
const loadedFiles = new Set();
let gitignorePatterns = [];
// Try to read .gitignore
try {
const gitignorePath = path.join(projectPath, '.gitignore');
const gitignoreContent = await fs.readFile(gitignorePath, 'utf-8');
gitignorePatterns = gitignoreContent
.split('\n')
.map(line => line.trim())
.filter(line => line && !line.startsWith('#'));
}
catch {
// .gitignore not found or unreadable, continue without it
}
function shouldIgnore(filePath) {
const relativePath = path.relative(projectPath, filePath);
// Always ignore common directories
const commonIgnores = [
'node_modules', '.git', 'dist', 'build', '.next', 'coverage',
'.nyc_output', '.cache', 'tmp', 'temp', '.DS_Store'
];
for (const ignore of commonIgnores) {
if (relativePath.includes(ignore))
return true;
}
// Check gitignore patterns (simple implementation)
for (const pattern of gitignorePatterns) {
if (pattern.endsWith('*')) {
const prefix = pattern.slice(0, -1);
if (relativePath.startsWith(prefix))
return true;
}
else if (relativePath === pattern || relativePath.includes('/' + pattern)) {
return true;
}
}
return false;
}
async function loadDirectory(dirPath) {
if (shouldIgnore(dirPath))
return;
let entries;
try {
entries = await fs.readdir(dirPath, { withFileTypes: true });
}
catch (error) {
console.warn(`Cannot read directory ${dirPath}: ${error}`);
return;
}
for (const entry of entries) {
const fullPath = path.join(dirPath, entry.name);
if (shouldIgnore(fullPath))
continue;
if (entry.isDirectory()) {
await loadDirectory(fullPath);
}
else if (entry.isFile()) {
// Load supported source files
if (/\.(ts|tsx|js|jsx|py|rs|go|java|cpp|c|hpp|h)$/.test(entry.name) && !entry.name.endsWith('.d.ts')) {
if (!loadedFiles.has(fullPath)) {
try {
await loadFileIfNeeded(project, fullPath);
loadedFiles.add(fullPath);
}
catch (error) {
console.warn(`Skipping file ${fullPath}: ${error}`);
}
}
}
}
}
}
console.log(`Loading project files from: ${projectPath}`);
const startTime = Date.now();
await loadDirectory(projectPath);
const duration = Date.now() - startTime;
console.log(`Loaded ${loadedFiles.size} files in ${duration}ms`);
}
// Connect transport based on options
if (options.transport === "stdio" || !options.transport) {
const transport = new stdio_js_1.StdioServerTransport();
await server.connect(transport);
}
return server;
}
//# sourceMappingURL=start_server.js.map