UNPKG

auto-prompt-mcp-server

Version:

MCP server that automatically adds prompts to file submissions when no user prompt is provided

361 lines (360 loc) 18.6 kB
#!/usr/bin/env node "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype); return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AutoPromptServer = void 0; var index_js_1 = require("@modelcontextprotocol/sdk/server/index.js"); var stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js"); var types_js_1 = require("@modelcontextprotocol/sdk/types.js"); var AutoPromptServer = /** @class */ (function () { function AutoPromptServer() { this.IMAGE_EXTENSIONS = new Set([ 'jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp' ]); this.CODE_EXTENSIONS = new Set([ 'js', 'ts', 'jsx', 'tsx', 'py', 'java', 'cpp', 'c', 'cs', 'php', 'rb', 'go', 'rs', 'swift', 'kt', 'scala', 'html', 'css', 'scss', 'sass', 'vue', 'svelte' ]); this.DATA_EXTENSIONS = new Set([ 'csv', 'json', 'xml', 'xlsx', 'xls', 'sql' ]); this.server = new index_js_1.Server({ name: 'auto-prompt-server', version: '1.0.0', capabilities: { tools: {}, }, }); // Default configuration - can be overridden via environment variables this.config = { defaultPrompt: process.env.AUTO_PROMPT_DEFAULT || 'Please analyze this file and provide insights.', filePrompt: process.env.AUTO_PROMPT_FILE || 'What can you tell me about this file?', imagePrompt: process.env.AUTO_PROMPT_IMAGE || 'Describe this image and its contents.', codePrompt: process.env.AUTO_PROMPT_CODE || 'Review this code and explain what it does.', dataPrompt: process.env.AUTO_PROMPT_DATA || 'Analyze this data and summarize key findings.', }; this.setupHandlers(); } AutoPromptServer.prototype.validateProcessFileSubmissionArgs = function (args) { if (typeof args !== 'object' || args === null) { throw new Error('Invalid arguments: expected object'); } var obj = args; if (!Array.isArray(obj.files)) { throw new Error('Invalid arguments: files must be an array'); } // Validate each file in the array for (var _i = 0, _a = obj.files; _i < _a.length; _i++) { var file = _a[_i]; if (typeof file !== 'object' || file === null) { throw new Error('Invalid file: each file must be an object'); } var fileObj = file; if (typeof fileObj.name !== 'string' || typeof fileObj.content !== 'string') { throw new Error('Invalid file: name and content must be strings'); } } return { files: obj.files, userPrompt: typeof obj.userPrompt === 'string' ? obj.userPrompt : undefined, promptType: typeof obj.promptType === 'string' ? obj.promptType : undefined, }; }; AutoPromptServer.prototype.validateConfigurePromptsArgs = function (args) { if (typeof args !== 'object' || args === null) { throw new Error('Invalid arguments: expected object'); } return args; }; AutoPromptServer.prototype.setupHandlers = function () { var _this = this; this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, ({ tools: [ { name: 'process_file_submission', description: 'Processes file submissions and adds appropriate prompts when none are provided', inputSchema: { type: 'object', properties: { files: { type: 'array', items: { type: 'object', properties: { name: { type: 'string' }, content: { type: 'string' }, mimeType: { type: 'string' }, size: { type: 'number' } }, required: ['name', 'content'] } }, userPrompt: { type: 'string', description: 'Optional user prompt - if provided, no auto-prompt will be added' }, promptType: { type: 'string', enum: ['default', 'file', 'image', 'code', 'data'], description: 'Type of auto-prompt to use if no user prompt provided' } }, required: ['files'] } }, { name: 'configure_prompts', description: 'Configure the default prompts used for different file types', inputSchema: { type: 'object', properties: { defaultPrompt: { type: 'string' }, filePrompt: { type: 'string' }, imagePrompt: { type: 'string' }, codePrompt: { type: 'string' }, dataPrompt: { type: 'string' } } } }, { name: 'get_configuration', description: 'Get current prompt configuration', inputSchema: { type: 'object', properties: {} } } ], })]; }); }); }); this.server.setRequestHandler(types_js_1.CallToolRequestSchema, function (request) { return __awaiter(_this, void 0, void 0, function () { var _a, name, args, _b, error_1, errorMessage; return __generator(this, function (_c) { switch (_c.label) { case 0: _a = request.params, name = _a.name, args = _a.arguments; _c.label = 1; case 1: _c.trys.push([1, 10, , 11]); _b = name; switch (_b) { case 'process_file_submission': return [3 /*break*/, 2]; case 'configure_prompts': return [3 /*break*/, 4]; case 'get_configuration': return [3 /*break*/, 6]; } return [3 /*break*/, 8]; case 2: return [4 /*yield*/, this.processFileSubmission(this.validateProcessFileSubmissionArgs(args))]; case 3: return [2 /*return*/, _c.sent()]; case 4: return [4 /*yield*/, this.configurePrompts(this.validateConfigurePromptsArgs(args))]; case 5: return [2 /*return*/, _c.sent()]; case 6: return [4 /*yield*/, this.getConfiguration()]; case 7: return [2 /*return*/, _c.sent()]; case 8: throw new Error("Unknown tool: ".concat(name)); case 9: return [3 /*break*/, 11]; case 10: error_1 = _c.sent(); errorMessage = error_1 instanceof Error ? error_1.message : 'Unknown error occurred'; return [2 /*return*/, { content: [ { type: 'text', text: "Error: ".concat(errorMessage), }, ], isError: true, }]; case 11: return [2 /*return*/]; } }); }); }); }; AutoPromptServer.prototype.processFileSubmission = function (args) { return __awaiter(this, void 0, void 0, function () { var files, userPrompt, _a, promptType, autoPrompt, filesList; return __generator(this, function (_b) { files = args.files, userPrompt = args.userPrompt, _a = args.promptType, promptType = _a === void 0 ? 'default' : _a; if (!files || !Array.isArray(files) || files.length === 0) { throw new Error('No files provided'); } // If user provided a prompt, don't add auto-prompt if (userPrompt && userPrompt.trim()) { return [2 /*return*/, { content: [ { type: 'text', text: "User prompt detected: \"".concat(userPrompt, "\"\nNo auto-prompt added. Processing ").concat(files.length, " file(s) with user's prompt."), }, ], }]; } autoPrompt = this.selectAutoPrompt(files, promptType); filesList = files.map(function (file) { return "- ".concat(file.name, " (").concat(file.mimeType || 'unknown type', ")"); }).join('\n'); return [2 /*return*/, { content: [ { type: 'text', text: "No user prompt detected. Auto-prompt added: \"".concat(autoPrompt, "\"\n\nFiles submitted:\n").concat(filesList, "\n\nProcessing with auto-prompt..."), }, ], }]; }); }); }; AutoPromptServer.prototype.selectAutoPrompt = function (files, promptType) { // If specific prompt type requested, use it if (promptType !== 'default') { var promptKey = "".concat(promptType, "Prompt"); return this.config[promptKey] || this.config.defaultPrompt; } // Auto-detect based on file types var fileExtensions = files.map(function (file) { var ext = file.name.toLowerCase().split('.').pop(); return ext || ''; }); var mimeTypes = files.map(function (file) { return file.mimeType || ''; }).filter(Boolean); // Check for images if (this.hasImageFiles(mimeTypes, fileExtensions)) { return this.config.imagePrompt; } // Check for code files if (this.hasCodeFiles(fileExtensions)) { return this.config.codePrompt; } // Check for data files if (this.hasDataFiles(fileExtensions, mimeTypes)) { return this.config.dataPrompt; } // Default for other file types return this.config.filePrompt; }; AutoPromptServer.prototype.hasImageFiles = function (mimeTypes, extensions) { var _this = this; return mimeTypes.some(function (type) { return type.startsWith('image/'); }) || extensions.some(function (ext) { return _this.IMAGE_EXTENSIONS.has(ext); }); }; AutoPromptServer.prototype.hasCodeFiles = function (extensions) { var _this = this; return extensions.some(function (ext) { return _this.CODE_EXTENSIONS.has(ext); }); }; AutoPromptServer.prototype.hasDataFiles = function (extensions, mimeTypes) { var _this = this; return extensions.some(function (ext) { return _this.DATA_EXTENSIONS.has(ext); }) || mimeTypes.some(function (type) { return type.includes('spreadsheet') || type.includes('json') || type.includes('xml'); }); }; AutoPromptServer.prototype.configurePrompts = function (args) { return __awaiter(this, void 0, void 0, function () { var validKeys, updates, _i, _a, _b, key, value, configKey; return __generator(this, function (_c) { validKeys = ['defaultPrompt', 'filePrompt', 'imagePrompt', 'codePrompt', 'dataPrompt']; updates = []; for (_i = 0, _a = Object.entries(args); _i < _a.length; _i++) { _b = _a[_i], key = _b[0], value = _b[1]; if (validKeys.includes(key) && typeof value === 'string' && value.trim()) { configKey = key; this.config[configKey] = value.trim(); updates.push("".concat(key, ": \"").concat(value.trim(), "\"")); } } if (updates.length === 0) { throw new Error('No valid prompt configurations provided'); } return [2 /*return*/, { content: [ { type: 'text', text: "Prompt configuration updated:\n".concat(updates.join('\n')), }, ], }]; }); }); }; AutoPromptServer.prototype.getConfiguration = function () { return __awaiter(this, void 0, void 0, function () { var configText; return __generator(this, function (_a) { configText = Object.entries(this.config) .map(function (_a) { var key = _a[0], value = _a[1]; return "".concat(key, ": \"").concat(value, "\""); }) .join('\n'); return [2 /*return*/, { content: [ { type: 'text', text: "Current prompt configuration:\n".concat(configText), }, ], }]; }); }); }; AutoPromptServer.prototype.run = function () { return __awaiter(this, void 0, void 0, function () { var transport; return __generator(this, function (_a) { switch (_a.label) { case 0: transport = new stdio_js_1.StdioServerTransport(); return [4 /*yield*/, this.server.connect(transport)]; case 1: _a.sent(); console.error('Auto-Prompt MCP server running on stdio'); return [2 /*return*/]; } }); }); }; return AutoPromptServer; }()); exports.AutoPromptServer = AutoPromptServer; // Run the server var isMainModule = process.argv[1] && process.argv[1].endsWith('server.js'); if (isMainModule) { var server = new AutoPromptServer(); server.run().catch(console.error); } exports.default = AutoPromptServer;