context-optimizer-mcp-server
Version:
Context optimization tools MCP server for AI coding assistants - compatible with GitHub Copilot, Cursor AI, and other MCP-supporting assistants
124 lines (121 loc) • 5.55 kB
JavaScript
/**
* File Analysis Tool - Extract specific information from files without reading entire contents into chat
*
* Ports the FileAnalysisTool from VS Code extension to MCP with Node.js file system
*/
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.AskAboutFileTool = void 0;
const fs = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
const base_1 = require("./base");
const pathValidator_1 = require("../security/pathValidator");
const factory_1 = require("../providers/factory");
const manager_1 = require("../config/manager");
class AskAboutFileTool extends base_1.BaseMCPTool {
name = 'askAboutFile';
description = 'Extract specific information from files without reading their entire contents into chat context. Works with text files, code files, images, PDFs, and more.';
inputSchema = {
type: 'object',
properties: {
filePath: {
type: 'string',
description: 'Full absolute path to the file to analyze (e.g., "C:\\Users\\username\\project\\src\\file.ts", "/home/user/project/docs/README.md")'
},
question: {
type: 'string',
description: 'Specific question about the file content (e.g., "Does this file export a validateEmail function?", "What is the main purpose described in this spec?", "Extract all import statements")'
}
},
required: ['filePath', 'question']
};
async execute(args) {
try {
this.logOperation('File analysis started', { filePath: args.filePath, question: args.question });
// Validate required fields
const fieldError = this.validateRequiredFields(args, ['filePath', 'question']);
if (fieldError) {
return this.createErrorResponse(fieldError);
}
// Validate file path security
const pathValidation = await pathValidator_1.PathValidator.validateFilePath(args.filePath);
if (!pathValidation.valid) {
return this.createErrorResponse(pathValidation.error);
}
// Read file content
const fileContent = await fs.readFile(pathValidation.resolvedPath, 'utf8');
// Process with LLM
const config = manager_1.ConfigurationManager.getConfig();
const provider = factory_1.LLMProviderFactory.createProvider(config.llm.provider);
const apiKey = this.getApiKey(config.llm.provider, config.llm);
const prompt = this.createFileAnalysisPrompt(fileContent, args.question, args.filePath);
const response = await provider.processRequest(prompt, config.llm.model, apiKey);
if (!response.success) {
return this.createErrorResponse(`LLM processing failed: ${response.error}`);
}
this.logOperation('File analysis completed successfully');
return this.createSuccessResponse(response.content);
}
catch (error) {
this.logOperation('File analysis failed', { error });
return this.createErrorResponse(`File analysis failed: ${error instanceof Error ? error.message : String(error)}`);
}
}
createFileAnalysisPrompt(fileContent, question, filePath) {
const fileExtension = path.extname(filePath);
return `You are analyzing a file for a user question. Be concise and focused in your response.
File: ${filePath} (${fileExtension})
Question: ${question}
Instructions:
- Answer only what is specifically asked
- Be brief and to the point
- Use markdown formatting for code snippets
- Don't explain things that weren't asked for
- If the question can be answered with yes/no, start with that
File Content:
${fileContent}`;
}
getApiKey(provider, llmConfig) {
const keyField = `${provider}Key`;
const key = llmConfig[keyField];
if (!key) {
throw new Error(`API key not configured for provider: ${provider}`);
}
return key;
}
}
exports.AskAboutFileTool = AskAboutFileTool;
//# sourceMappingURL=askAboutFile.js.map
;