mirror of
https://github.com/upstash/context7.git
synced 2025-12-06 03:48:45 +00:00
added sse http support
This commit is contained in:
parent
2628a868c2
commit
c2f695d377
98
src/index.ts
98
src/index.ts
@ -6,6 +6,10 @@ import { z } from "zod";
|
|||||||
import { searchLibraries, fetchLibraryDocumentation } from "./lib/api.js";
|
import { searchLibraries, fetchLibraryDocumentation } from "./lib/api.js";
|
||||||
import { formatSearchResults } from "./lib/utils.js";
|
import { formatSearchResults } from "./lib/utils.js";
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
|
import { createServer } from "http";
|
||||||
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
||||||
|
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
||||||
|
import { parse } from "url";
|
||||||
|
|
||||||
// Load environment variables from .env file if present
|
// Load environment variables from .env file if present
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
@ -23,11 +27,15 @@ if (process.env.DEFAULT_MINIMUM_TOKENS) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create server instance
|
// Store SSE transports by session ID
|
||||||
|
const sseTransports: Record<string, SSEServerTransport> = {};
|
||||||
|
|
||||||
|
// Function to create a new server instance with all tools registered
|
||||||
|
function createServerInstance() {
|
||||||
const server = new McpServer({
|
const server = new McpServer({
|
||||||
name: "Context7",
|
name: "Context7",
|
||||||
description: "Retrieves up-to-date documentation and code examples for any library.",
|
description: "Retrieves up-to-date documentation and code examples for any library.",
|
||||||
version: "1.0.6",
|
version: "1.0.7",
|
||||||
capabilities: {
|
capabilities: {
|
||||||
resources: {},
|
resources: {},
|
||||||
tools: {},
|
tools: {},
|
||||||
@ -162,11 +170,97 @@ server.tool(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
|
const transportType = process.env.MCP_TRANSPORT || "stdio";
|
||||||
|
|
||||||
|
if (transportType === "http" || transportType === "sse") {
|
||||||
|
const port = process.env.PORT ? parseInt(process.env.PORT, 10) : 3000;
|
||||||
|
const httpServer = createServer(async (req, res) => {
|
||||||
|
const url = parse(req.url || "").pathname;
|
||||||
|
|
||||||
|
// Set CORS headers for all responses
|
||||||
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||||
|
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,OPTIONS,DELETE');
|
||||||
|
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, MCP-Session-Id, mcp-session-id');
|
||||||
|
|
||||||
|
// Handle preflight OPTIONS requests
|
||||||
|
if (req.method === 'OPTIONS') {
|
||||||
|
res.writeHead(200);
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Create new server instance for each request
|
||||||
|
const requestServer = createServerInstance();
|
||||||
|
|
||||||
|
if (url === "/mcp") {
|
||||||
|
const transport = new StreamableHTTPServerTransport({
|
||||||
|
sessionIdGenerator: undefined
|
||||||
|
});
|
||||||
|
await requestServer.connect(transport);
|
||||||
|
await transport.handleRequest(req, res);
|
||||||
|
} else if (url === "/sse" && req.method === "GET") {
|
||||||
|
// Create new SSE transport for GET request
|
||||||
|
const sseTransport = new SSEServerTransport("/messages", res);
|
||||||
|
// Store the transport by session ID
|
||||||
|
sseTransports[sseTransport.sessionId] = sseTransport;
|
||||||
|
// Clean up transport when connection closes
|
||||||
|
res.on("close", () => {
|
||||||
|
delete sseTransports[sseTransport.sessionId];
|
||||||
|
});
|
||||||
|
await requestServer.connect(sseTransport);
|
||||||
|
} else if (url === "/messages" && req.method === "POST") {
|
||||||
|
// Get session ID from query parameters
|
||||||
|
const parsedUrl = parse(req.url || "", true);
|
||||||
|
const sessionId = parsedUrl.query.sessionId as string;
|
||||||
|
|
||||||
|
if (!sessionId) {
|
||||||
|
res.writeHead(400);
|
||||||
|
res.end("Missing sessionId parameter");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get existing transport for this session
|
||||||
|
const sseTransport = sseTransports[sessionId];
|
||||||
|
if (!sseTransport) {
|
||||||
|
res.writeHead(400);
|
||||||
|
res.end(`No transport found for sessionId: ${sessionId}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle the POST message with the existing transport
|
||||||
|
await sseTransport.handlePostMessage(req, res);
|
||||||
|
} else if (url === "/ping") {
|
||||||
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||||
|
res.end('pong');
|
||||||
|
} else {
|
||||||
|
res.writeHead(404);
|
||||||
|
res.end("Not found");
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error handling request:", error);
|
||||||
|
if (!res.headersSent) {
|
||||||
|
res.writeHead(500);
|
||||||
|
res.end("Internal Server Error");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
httpServer.listen(port, () => {
|
||||||
|
console.error(`Context7 Documentation MCP Server running on ${transportType.toUpperCase()} at http://localhost:${port}/mcp and legacy SSE at /sse`);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Stdio transport - this is already stateless by nature
|
||||||
|
const server = createServerInstance();
|
||||||
const transport = new StdioServerTransport();
|
const transport = new StdioServerTransport();
|
||||||
await server.connect(transport);
|
await server.connect(transport);
|
||||||
console.error("Context7 Documentation MCP Server running on stdio");
|
console.error("Context7 Documentation MCP Server running on stdio");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
main().catch((error) => {
|
main().catch((error) => {
|
||||||
console.error("Fatal error in main():", error);
|
console.error("Fatal error in main():", error);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user