current-time-timezone-server
Version:
MCP服务器,提供NTP校准的当前时间和时区相关功能,支持stdio和HTTP/SSE,可配置host和protocol,支持.env文件,返回指定时区的本地时间
113 lines • 4.15 kB
JavaScript
import express from "express";
import { randomUUID } from "node:crypto";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
import dotenv from "dotenv";
import { registerTimeTool } from "./utils/toolRegistration.js";
// Load environment variables
dotenv.config();
const app = express();
app.use(express.json());
const transports = {};
const sseTransports = {};
const createMcpServer = () => new McpServer({
name: "current-time-timezone-server",
version: "1.1.6"
});
const setupServer = (server) => {
registerTimeTool(server);
};
app.post('/mcp', async (req, res) => {
const sessionId = req.headers['mcp-session-id'];
let transport;
if (sessionId && transports[sessionId]) {
transport = transports[sessionId];
}
else if (!sessionId && isInitializeRequest(req.body)) {
const host = process.env.HOST || 'localhost';
const port = parseInt(process.env.PORT || '3000', 10);
const protocol = process.env.PROTOCOL || 'http';
transport = new StreamableHTTPServerTransport({
sessionIdGenerator: () => randomUUID(),
onsessioninitialized: (sessionId) => {
transports[sessionId] = transport;
},
});
transport.onclose = () => {
if (transport.sessionId) {
delete transports[transport.sessionId];
}
};
const server = createMcpServer();
setupServer(server);
await server.connect(transport);
}
else {
res.status(400).json({
jsonrpc: '2.0',
error: {
code: -32000,
message: 'Bad Request: No valid session ID provided',
},
id: null,
});
return;
}
await transport.handleRequest(req, res, req.body);
});
const handleSessionRequest = async (req, res) => {
const sessionId = req.headers['mcp-session-id'];
if (!sessionId || !transports[sessionId]) {
res.status(400).send('Invalid or missing session ID');
return;
}
const transport = transports[sessionId];
await transport.handleRequest(req, res, req.body);
};
// SSE endpoint - for traditional clients
app.get('/sse', async (req, res) => {
try {
const transport = new SSEServerTransport('/messages', res);
sseTransports[transport.sessionId] = transport;
res.on("close", () => {
delete sseTransports[transport.sessionId];
});
const server = createMcpServer();
setupServer(server);
await server.connect(transport);
}
catch (error) {
console.error('SSE connection error:', error);
res.status(500).send('SSE connection failed');
}
});
// Message endpoint - for SSE transport message handling
app.post('/messages', async (req, res) => {
try {
const sessionId = req.query.sessionId;
const transport = sseTransports[sessionId];
if (!transport) {
res.status(400).send('Corresponding SSE session not found');
return;
}
await transport.handlePostMessage(req, res, req.body);
}
catch (error) {
console.error('Message processing error:', error);
res.status(500).send('Message processing failed');
}
});
app.get('/mcp', handleSessionRequest);
app.delete('/mcp', handleSessionRequest);
const host = process.env.HOST || 'localhost';
const port = parseInt(process.env.PORT || '3000', 10);
const protocol = process.env.PROTOCOL || 'http';
app.listen(port, host, () => {
console.log(`MCP server running on ${protocol}://${host}:${port}`);
console.log(`Streamable HTTP endpoint: ${protocol}://${host}:${port}/mcp`);
console.log(`SSE endpoint: ${protocol}://${host}:${port}/sse`);
console.log(`SSE message endpoint: ${protocol}://${host}:${port}/messages`);
});
//# sourceMappingURL=server.js.map