tarot-mcp-server
Version:
Model Context Protocol server for Rider-Waite tarot card readings
127 lines (126 loc) • 4.24 kB
JavaScript
import express from 'express';
import cors from 'cors';
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
/**
* HTTP Server for Tarot MCP with SSE (Server-Sent Events) support
*/
export class TarotHttpServer {
app;
server;
tarotServer;
port;
constructor(tarotServer, port = 3000) {
this.port = port;
this.app = express();
this.tarotServer = tarotServer;
// Create MCP server instance
this.server = new Server({
name: "tarot-mcp-server",
version: "1.0.0",
}, {
capabilities: {
tools: {},
},
});
this.setupMiddleware();
this.setupMCPHandlers();
this.setupRoutes();
}
/**
* Setup Express middleware
*/
setupMiddleware() {
this.app.use(cors());
this.app.use(express.json());
}
/**
* Setup MCP request handlers
*/
setupMCPHandlers() {
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: this.tarotServer.getAvailableTools(),
};
});
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
const result = await this.tarotServer.executeTool(name, args || {});
return {
content: [
{
type: "text",
text: result,
},
],
};
}
catch (error) {
return {
isError: true,
content: [
{
type: "text",
text: `Error executing tool ${name}: ${error instanceof Error ? error.message : String(error)}`,
},
],
};
}
});
}
/**
* Setup HTTP routes
*/
setupRoutes() {
this.app.get('/health', (req, res) => {
res.json({ status: 'ok' });
});
// SSE endpoint
this.app.get('/sse', async (req, res) => {
const transport = new SSEServerTransport('/sse', res);
await this.server.connect(transport);
});
// Example of a direct API endpoint
this.app.post('/api/reading', async (req, res) => {
try {
const { spreadType, question, sessionId } = req.body;
const result = await this.tarotServer.executeTool('perform_reading', { spreadType, question, sessionId });
res.json({ result });
}
catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
}
});
// Custom spread creation endpoint
this.app.post('/api/custom-spread', async (req, res) => {
try {
const { spreadName, description, positions, question, sessionId } = req.body;
const result = await this.tarotServer.executeTool('create_custom_spread', {
spreadName,
description,
positions,
question,
sessionId
});
res.json({ result });
}
catch (error) {
res.status(500).json({ error: error instanceof Error ? error.message : String(error) });
}
});
}
/**
* Start the HTTP server
*/
async start() {
return new Promise((resolve) => {
this.app.listen(this.port, () => {
console.log(`Tarot MCP Server running on http://localhost:${this.port}`);
console.log(`SSE endpoint available at http://localhost:${this.port}/sse`);
resolve();
});
});
}
}