Add multi-account support and CORS/logging middleware
- Add garfield, sales, leads, founder accounts to IMAP and SMTP configs - Refactor fetcherpay config into shared helper functions - Add CORS middleware with wildcard origin - Add request logging middleware and MCP session lifecycle logs - Include package-lock.json and add @types/cors dependency Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
39
src/index.ts
39
src/index.ts
@@ -1,5 +1,6 @@
|
||||
import 'dotenv/config';
|
||||
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 { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
||||
@@ -11,8 +12,24 @@ import {
|
||||
import { tools, handleToolCall } from './tools.js';
|
||||
|
||||
const app = express();
|
||||
app.use(cors({
|
||||
origin: '*',
|
||||
methods: ['GET', 'POST', 'DELETE', 'OPTIONS'],
|
||||
allowedHeaders: ['Content-Type', 'mcp-session-id', 'Accept'],
|
||||
credentials: true
|
||||
}));
|
||||
app.use(express.json());
|
||||
|
||||
// Request logging middleware
|
||||
app.use((req, res, next) => {
|
||||
const timestamp = new Date().toISOString();
|
||||
console.log(`[${timestamp}] ${req.method} ${req.path} - ${req.headers['user-agent'] || 'no-ua'}`);
|
||||
if (req.body && Object.keys(req.body).length > 0) {
|
||||
console.log(` Body: ${JSON.stringify(req.body).substring(0, 500)}`);
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
function createMcpServer() {
|
||||
const server = new Server(
|
||||
{ name: 'hermes', version: '1.0.0' },
|
||||
@@ -33,11 +50,13 @@ const httpTransports = new Map<string, StreamableHTTPServerTransport>();
|
||||
|
||||
app.post('/mcp', async (req, res) => {
|
||||
const sessionId = req.headers['mcp-session-id'] as string | undefined;
|
||||
console.log(`[mcp] POST sessionId=${sessionId ?? 'none'}, isInit=${isInitializeRequest(req.body)}`);
|
||||
|
||||
let transport: StreamableHTTPServerTransport;
|
||||
|
||||
if (sessionId && httpTransports.has(sessionId)) {
|
||||
// Known active session — reuse it
|
||||
console.log(`[mcp] Reusing existing session ${sessionId}`);
|
||||
transport = httpTransports.get(sessionId)!;
|
||||
} else if (isInitializeRequest(req.body)) {
|
||||
// Initialize request: create a new session.
|
||||
@@ -46,15 +65,23 @@ app.post('/mcp', async (req, res) => {
|
||||
if (sessionId) {
|
||||
console.warn(`[mcp] Stale session ${sessionId} re-initializing — pod may have restarted`);
|
||||
}
|
||||
console.log(`[mcp] Creating new session`);
|
||||
transport = new StreamableHTTPServerTransport({
|
||||
sessionIdGenerator: () => crypto.randomUUID(),
|
||||
onsessioninitialized: (id) => { httpTransports.set(id, transport); },
|
||||
onsessioninitialized: (id) => {
|
||||
console.log(`[mcp] Session initialized: ${id}`);
|
||||
httpTransports.set(id, transport);
|
||||
},
|
||||
});
|
||||
transport.onclose = () => {
|
||||
if (transport.sessionId) httpTransports.delete(transport.sessionId);
|
||||
if (transport.sessionId) {
|
||||
console.log(`[mcp] Session closed: ${transport.sessionId}`);
|
||||
httpTransports.delete(transport.sessionId);
|
||||
}
|
||||
};
|
||||
const server = createMcpServer();
|
||||
await server.connect(transport);
|
||||
console.log(`[mcp] Server connected to transport`);
|
||||
} else {
|
||||
// Unknown session + non-initialize request: session expired (e.g. pod restarted).
|
||||
// Return 404 so MCP clients know to re-initialize rather than keep retrying.
|
||||
@@ -63,7 +90,13 @@ app.post('/mcp', async (req, res) => {
|
||||
return;
|
||||
}
|
||||
|
||||
await transport.handleRequest(req, res, req.body);
|
||||
try {
|
||||
await transport.handleRequest(req, res, req.body);
|
||||
console.log(`[mcp] Request handled successfully`);
|
||||
} catch (err) {
|
||||
console.error(`[mcp] Error handling request:`, err);
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/mcp', async (req, res) => {
|
||||
|
||||
Reference in New Issue
Block a user