emotions-mcp-server
Version:
MCP Server for accessing PostgreSQL emotions database
384 lines (383 loc) • 15.7 kB
JavaScript
"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;