UNPKG

emotions-mcp-server

Version:

MCP Server for accessing PostgreSQL emotions database

384 lines (383 loc) 15.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EmotionsMcpServer = void 0; const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js"); const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js"); const database_1 = require("./database"); const zod_1 = require("zod"); class EmotionsMcpServer { constructor(connectionString) { this.transport = null; this.db = new database_1.EmotionsDbService(connectionString); this.server = new mcp_js_1.McpServer({ name: 'EmotionsMcpServer', version: '1.0.0', }); this.registerMethods(); } registerMethods() { // Method to check if the emotions table exists this.server.registerTool('tableExists', { description: 'Check if the emotions table exists for a given user context', inputSchema: {} }, async () => { try { const exists = await this.db.tableExists(); return { content: [{ type: 'text', text: JSON.stringify({ exists }) }] }; } catch (error) { if (error.message) { return { content: [{ type: 'text', text: `Error: ${error.message}` }], status: 'error' }; } return { content: [{ type: 'text', text: `Error: ${JSON.stringify(error)}` }], status: 'error' }; } }); // Method to create the emotions table this.server.registerTool('createTable', { description: 'Create the emotions table in the database', inputSchema: {} }, async () => { try { await this.db.createTable(); return { content: [{ type: 'text', text: 'Table created successfully' }] }; } catch (error) { if (error.message) { return { content: [{ type: 'text', text: `Error: ${error.message}` }], status: 'error' }; } return { content: [{ type: 'text', text: `Error: ${JSON.stringify(error)}` }], status: 'error' }; } }); // Method to insert a new emotion this.server.registerTool('insertEmotion', { description: 'Insert a new emotion record into the database', inputSchema: { userContext: zod_1.z.string().describe('User context for the emotion'), emotion: zod_1.z.object({ emotion: zod_1.z.string(), datum: zod_1.z.string().pipe(zod_1.z.coerce.date()), alter: zod_1.z.number().optional(), quellenart: zod_1.z.enum(['Eigene Emotion', 'Übernommene Emotion', 'Geerbte Emotion']), quelle: zod_1.z.string().optional(), koerperteil: zod_1.z.string().optional(), auswirkungen: zod_1.z.string().optional(), bemerkungen: zod_1.z.string().optional() }).describe('Emotion data') } }, async ({ userContext, emotion }) => { try { if (!userContext) { return { content: [{ type: 'text', text: 'User context is required' }], status: 'error' }; } if (!emotion) { return { content: [{ type: 'text', text: 'Emotion data is required' }], status: 'error' }; } const result = await this.db.insertEmotion(userContext, emotion); return { content: [{ type: 'text', text: JSON.stringify(result) }] }; } catch (error) { if (error.message) { return { content: [{ type: 'text', text: `Error: ${error.message}` }], status: 'error' }; } return { content: [{ type: 'text', text: `Error: ${JSON.stringify(error)}` }], status: 'error' }; } }); // Method to update an emotion this.server.registerTool('updateEmotion', { description: 'Update an existing emotion by ID', inputSchema: { userContext: zod_1.z.string().describe('User context for the emotion'), emotionNumber: zod_1.z.number().describe('Number of the emotion to update'), emotion: zod_1.z.object({ emotion: zod_1.z.string(), datum: zod_1.z.string().pipe(zod_1.z.coerce.date()), alter: zod_1.z.number().optional(), quellenart: zod_1.z.enum(['Eigene Emotion', 'Übernommene Emotion', 'Geerbte Emotion']), quelle: zod_1.z.string().optional(), koerperteil: zod_1.z.string().optional(), auswirkungen: zod_1.z.string().optional(), bemerkungen: zod_1.z.string().optional() }).describe('Updated emotion data') } }, async ({ userContext, emotionNumber, emotion }) => { try { if (!userContext) { return { content: [{ type: 'text', text: 'User context is required' }], status: 'error' }; } if (!emotionNumber) { return { content: [{ type: 'text', text: 'Emotion ID is required' }], status: 'error' }; } if (!emotion) { return { content: [{ type: 'text', text: 'Updated emotion data is required' }], status: 'error' }; } const updatedEmotion = await this.db.updateEmotion(userContext, emotionNumber, emotion); if (updatedEmotion) { return { content: [{ type: 'text', text: JSON.stringify(updatedEmotion) }] }; } else { return { content: [{ type: 'text', text: 'Emotion not found or update failed' }], status: 'error' }; } } catch (error) { if (error.message) { return { content: [{ type: 'text', text: `Error: ${error.message}` }], status: 'error' }; } return { content: [{ type: 'text', text: `Error: ${JSON.stringify(error)}` }], status: 'error' }; } }); // Method to delete an emotion this.server.registerTool('deleteEmotion', { description: 'Delete an emotion by ID', inputSchema: { userContext: zod_1.z.string().describe('User context for the emotion'), emotionNumber: zod_1.z.number().describe('Number of the emotion to delete') } }, async ({ userContext, emotionNumber }) => { try { if (!userContext) { return { content: [{ type: 'text', text: 'User context is required' }], status: 'error' }; } if (!emotionNumber) { return { content: [{ type: 'text', text: 'Emotion Number is required' }], status: 'error' }; } const result = await this.db.deleteEmotion(userContext, emotionNumber); if (result) { return { content: [{ type: 'text', text: 'Emotion deleted successfully' }] }; } else { return { content: [{ type: 'text', text: 'Emotion not found' }], status: 'error' }; } } catch (error) { if (error.message) { return { content: [{ type: 'text', text: `Error: ${error.message}` }], status: 'error' }; } return { content: [{ type: 'text', text: `Error: ${JSON.stringify(error)}` }], status: 'error' }; } }); // Method to get emotions with filters this.server.registerTool('getEmotions', { description: 'Get emotions based on filters', inputSchema: { userContext: zod_1.z.string().describe('User context for the emotions'), filter: zod_1.z.object({ nummer: zod_1.z.number().optional(), emotion: zod_1.z.string().optional(), datumVon: zod_1.z.string().pipe(zod_1.z.coerce.date()).optional(), datumBis: zod_1.z.string().pipe(zod_1.z.coerce.date()).optional(), alterVon: zod_1.z.number().optional(), alterBis: zod_1.z.number().optional(), quellenart: zod_1.z.enum(['Eigene Emotion', 'Übernommene Emotion', 'Geerbte Emotion']).optional(), quelle: zod_1.z.string().optional(), koerperteil: zod_1.z.string().optional(), auswirkungen: zod_1.z.string().optional(), bemerkungen: zod_1.z.string().optional() }).optional().describe('Filter criteria') } }, async ({ userContext, filter = {} }) => { try { if (!userContext) { return { content: [{ type: 'text', text: 'User context is required' }], status: 'error' }; } const emotions = await this.db.getEmotions(userContext, filter); return { content: [{ type: 'text', text: JSON.stringify(emotions) }] }; } catch (error) { if (error.message) { return { content: [{ type: 'text', text: `Error: ${error.message}` }], status: 'error' }; } return { content: [{ type: 'text', text: `Error: ${JSON.stringify(error)}` }], status: 'error' }; } }); // Method to get a specific emotion by ID this.server.registerTool('getEmotionByNumber', { description: 'Get a specific emotion by Number', inputSchema: { userContext: zod_1.z.string().describe('User context for the emotion'), emotionNumber: zod_1.z.number().describe('Number of the emotion to retrieve') } }, async ({ userContext, emotionNumber }) => { try { if (!userContext) { return { content: [{ type: 'text', text: 'User context is required' }], status: 'error' }; } if (!emotionNumber) { return { content: [{ type: 'text', text: 'Emotion Number is required' }], status: 'error' }; } const emotion = await this.db.getEmotionByNumber(userContext, emotionNumber); if (emotion) { return { content: [{ type: 'text', text: JSON.stringify(emotion) }] }; } else { return { content: [{ type: 'text', text: 'Emotion not found' }], status: 'error' }; } } catch (error) { if (error.message) { return { content: [{ type: 'text', text: `Error: ${error.message}` }], status: 'error' }; } return { content: [{ type: 'text', text: `Error: ${JSON.stringify(error)}` }], status: 'error' }; } }); // Method to get recent emotions this.server.registerTool('getRecentEmotions', { description: 'Get the most recent emotions for a user', inputSchema: { userContext: zod_1.z.string().describe('User context for the emotions'), limit: zod_1.z.number().min(1).default(10).describe('Maximum number of emotions to retrieve') } }, async ({ userContext, limit = 10 }) => { try { if (!userContext) { return { content: [{ type: 'text', text: 'User context is required' }], status: 'error' }; } const emotions = await this.db.getRecentEmotions(userContext, limit); return { content: [{ type: 'text', text: JSON.stringify(emotions) }] }; } catch (error) { if (error.message) { return { content: [{ type: 'text', text: `Error: ${error.message}` }], status: 'error' }; } return { content: [{ type: 'text', text: `Error: ${JSON.stringify(error)}` }], status: 'error' }; } }); } sendLoggingMessage(message) { // Logging is not supported in the MCP SDK //this.server.server.sendLoggingMessage({ // level: "info", // data: message, //}); } async start() { try { this.transport = new stdio_js_1.StdioServerTransport(); await this.server.connect(this.transport); this.sendLoggingMessage('MCP Server started'); } catch (error) { console.error('Failed to start MCP Server:', error); throw error; } } async stop() { try { this.sendLoggingMessage('Stopping MCP Server'); if (this.transport) { await this.server.close(); } await this.db.closeConnection(); } catch (error) { console.error('Error stopping MCP Server:', error); throw error; } } } exports.EmotionsMcpServer = EmotionsMcpServer;