beeai-framework 0.1.13 → 0.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agents/experimental/remote → adapters/acp/agents}/agent.cjs +9 -6
- package/dist/adapters/acp/agents/agent.cjs.map +1 -0
- package/dist/{agents/experimental/remote → adapters/acp/agents}/agent.d.cts +11 -30
- package/dist/{agents/experimental/remote → adapters/acp/agents}/agent.d.ts +11 -30
- package/dist/{agents/experimental/remote → adapters/acp/agents}/agent.js +9 -6
- package/dist/adapters/acp/agents/agent.js.map +1 -0
- package/dist/adapters/acp/agents/events.cjs +4 -0
- package/dist/adapters/acp/agents/events.cjs.map +1 -0
- package/dist/adapters/acp/agents/events.d.cts +34 -0
- package/dist/adapters/acp/agents/events.d.ts +34 -0
- package/dist/adapters/acp/agents/events.js +3 -0
- package/dist/adapters/acp/agents/events.js.map +1 -0
- package/dist/adapters/acp/agents/types.cjs +4 -0
- package/dist/adapters/acp/agents/types.cjs.map +1 -0
- package/dist/adapters/acp/agents/types.d.cts +38 -0
- package/dist/adapters/acp/agents/types.d.ts +38 -0
- package/dist/adapters/acp/agents/types.js +3 -0
- package/dist/adapters/acp/agents/types.js.map +1 -0
- package/dist/adapters/amazon-bedrock/backend/client.cjs +3 -1
- package/dist/adapters/amazon-bedrock/backend/client.cjs.map +1 -1
- package/dist/adapters/amazon-bedrock/backend/client.js +3 -1
- package/dist/adapters/amazon-bedrock/backend/client.js.map +1 -1
- package/dist/adapters/anthropic/backend/client.cjs +3 -1
- package/dist/adapters/anthropic/backend/client.cjs.map +1 -1
- package/dist/adapters/anthropic/backend/client.js +3 -1
- package/dist/adapters/anthropic/backend/client.js.map +1 -1
- package/dist/adapters/azure-openai/backend/client.cjs +3 -1
- package/dist/adapters/azure-openai/backend/client.cjs.map +1 -1
- package/dist/adapters/azure-openai/backend/client.js +3 -1
- package/dist/adapters/azure-openai/backend/client.js.map +1 -1
- package/dist/adapters/beeai_platform/agents/agent.cjs +61 -0
- package/dist/adapters/beeai_platform/agents/agent.cjs.map +1 -0
- package/dist/adapters/beeai_platform/agents/agent.d.cts +49 -0
- package/dist/adapters/beeai_platform/agents/agent.d.ts +49 -0
- package/dist/adapters/beeai_platform/agents/agent.js +59 -0
- package/dist/adapters/beeai_platform/agents/agent.js.map +1 -0
- package/dist/adapters/beeai_platform/agents/events.cjs +4 -0
- package/dist/adapters/beeai_platform/agents/events.cjs.map +1 -0
- package/dist/adapters/beeai_platform/agents/events.d.cts +34 -0
- package/dist/adapters/beeai_platform/agents/events.d.ts +34 -0
- package/dist/adapters/beeai_platform/agents/events.js +3 -0
- package/dist/adapters/beeai_platform/agents/events.js.map +1 -0
- package/dist/adapters/beeai_platform/agents/types.cjs +4 -0
- package/dist/adapters/beeai_platform/agents/types.cjs.map +1 -0
- package/dist/adapters/beeai_platform/agents/types.d.cts +38 -0
- package/dist/adapters/beeai_platform/agents/types.d.ts +38 -0
- package/dist/adapters/beeai_platform/agents/types.js +3 -0
- package/dist/adapters/beeai_platform/agents/types.js.map +1 -0
- package/dist/adapters/google-vertex/backend/client.cjs +3 -1
- package/dist/adapters/google-vertex/backend/client.cjs.map +1 -1
- package/dist/adapters/google-vertex/backend/client.js +3 -1
- package/dist/adapters/google-vertex/backend/client.js.map +1 -1
- package/dist/adapters/groq/backend/client.cjs +3 -1
- package/dist/adapters/groq/backend/client.cjs.map +1 -1
- package/dist/adapters/groq/backend/client.js +3 -1
- package/dist/adapters/groq/backend/client.js.map +1 -1
- package/dist/adapters/mcp/serve/http_server.cjs +163 -0
- package/dist/adapters/mcp/serve/http_server.cjs.map +1 -0
- package/dist/adapters/mcp/serve/http_server.d.cts +21 -0
- package/dist/adapters/mcp/serve/http_server.d.ts +21 -0
- package/dist/adapters/mcp/serve/http_server.js +157 -0
- package/dist/adapters/mcp/serve/http_server.js.map +1 -0
- package/dist/adapters/mcp/serve/in_memory_store.cjs +69 -0
- package/dist/adapters/mcp/serve/in_memory_store.cjs.map +1 -0
- package/dist/adapters/mcp/serve/in_memory_store.d.cts +49 -0
- package/dist/adapters/mcp/serve/in_memory_store.d.ts +49 -0
- package/dist/adapters/mcp/serve/in_memory_store.js +67 -0
- package/dist/adapters/mcp/serve/in_memory_store.js.map +1 -0
- package/dist/adapters/mcp/serve/server.cjs +109 -0
- package/dist/adapters/mcp/serve/server.cjs.map +1 -0
- package/dist/adapters/mcp/serve/server.d.cts +70 -0
- package/dist/adapters/mcp/serve/server.d.ts +70 -0
- package/dist/adapters/mcp/serve/server.js +106 -0
- package/dist/adapters/mcp/serve/server.js.map +1 -0
- package/dist/adapters/ollama/backend/client.cjs +3 -1
- package/dist/adapters/ollama/backend/client.cjs.map +1 -1
- package/dist/adapters/ollama/backend/client.js +3 -1
- package/dist/adapters/ollama/backend/client.js.map +1 -1
- package/dist/adapters/openai/backend/client.cjs +3 -1
- package/dist/adapters/openai/backend/client.cjs.map +1 -1
- package/dist/adapters/openai/backend/client.js +3 -1
- package/dist/adapters/openai/backend/client.js.map +1 -1
- package/dist/adapters/vercel/backend/chat.cjs +7 -3
- package/dist/adapters/vercel/backend/chat.cjs.map +1 -1
- package/dist/adapters/vercel/backend/chat.js +8 -4
- package/dist/adapters/vercel/backend/chat.js.map +1 -1
- package/dist/adapters/vercel/backend/utils.cjs +82 -0
- package/dist/adapters/vercel/backend/utils.cjs.map +1 -0
- package/dist/adapters/vercel/backend/utils.d.cts +30 -0
- package/dist/adapters/vercel/backend/utils.d.ts +30 -0
- package/dist/adapters/vercel/backend/utils.js +78 -0
- package/dist/adapters/vercel/backend/utils.js.map +1 -0
- package/dist/{agent-Cmnvjx_k.d.cts → agent-Ca5UE2P1.d.cts} +1 -1
- package/dist/{agent-B55OuVCj.d.ts → agent-CgsoqVL5.d.ts} +1 -1
- package/dist/agents/react/agent.d.cts +1 -1
- package/dist/agents/react/agent.d.ts +1 -1
- package/dist/agents/react/prompts.d.cts +1 -1
- package/dist/agents/react/prompts.d.ts +1 -1
- package/dist/agents/react/runners/base.d.cts +1 -1
- package/dist/agents/react/runners/base.d.ts +1 -1
- package/dist/agents/react/runners/deep-think/prompts.d.cts +1 -1
- package/dist/agents/react/runners/deep-think/prompts.d.ts +1 -1
- package/dist/agents/react/runners/deep-think/runner.d.cts +2 -2
- package/dist/agents/react/runners/deep-think/runner.d.ts +2 -2
- package/dist/agents/react/runners/default/runner.d.cts +2 -2
- package/dist/agents/react/runners/default/runner.d.ts +2 -2
- package/dist/agents/react/runners/granite/prompts.d.cts +1 -1
- package/dist/agents/react/runners/granite/prompts.d.ts +1 -1
- package/dist/agents/react/runners/granite/runner.d.cts +2 -2
- package/dist/agents/react/runners/granite/runner.d.ts +2 -2
- package/dist/memory/slidingMemory.d.cts +1 -1
- package/dist/memory/slidingMemory.d.ts +1 -1
- package/dist/serve/server.cjs +52 -0
- package/dist/serve/server.cjs.map +1 -0
- package/dist/serve/server.d.cts +31 -0
- package/dist/serve/server.d.ts +31 -0
- package/dist/serve/server.js +50 -0
- package/dist/serve/server.js.map +1 -0
- package/dist/tools/database/qdrant.cjs +174 -0
- package/dist/tools/database/qdrant.cjs.map +1 -0
- package/dist/tools/database/qdrant.d.cts +86 -0
- package/dist/tools/database/qdrant.d.ts +86 -0
- package/dist/tools/database/qdrant.js +171 -0
- package/dist/tools/database/qdrant.js.map +1 -0
- package/dist/version.cjs +1 -1
- package/dist/version.js +1 -1
- package/package.json +17 -6
- package/dist/agents/experimental/remote/agent.cjs.map +0 -1
- package/dist/agents/experimental/remote/agent.js.map +0 -1
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var express = require('express');
|
|
4
|
+
var sse_js = require('@modelcontextprotocol/sdk/server/sse.js');
|
|
5
|
+
var streamableHttp_js = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
|
|
6
|
+
var types_js = require('@modelcontextprotocol/sdk/types.js');
|
|
7
|
+
var in_memory_store_cjs = require('./in_memory_store.cjs');
|
|
8
|
+
var node_crypto = require('node:crypto');
|
|
9
|
+
var logger_cjs = require('../../../logger/logger.cjs');
|
|
10
|
+
|
|
11
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
|
|
13
|
+
var express__default = /*#__PURE__*/_interopDefault(express);
|
|
14
|
+
|
|
15
|
+
var __defProp = Object.defineProperty;
|
|
16
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
17
|
+
const logger = logger_cjs.Logger.root.child({
|
|
18
|
+
name: "MCP HTTP server"
|
|
19
|
+
});
|
|
20
|
+
function runServer(server, hostname = "127.0.0.1", port = 3e3) {
|
|
21
|
+
const app = express__default.default();
|
|
22
|
+
app.use(express__default.default.json());
|
|
23
|
+
const transports = {};
|
|
24
|
+
app.all("/mcp", async (req, res) => {
|
|
25
|
+
logger.debug(`Received ${req.method} request to /mcp`);
|
|
26
|
+
try {
|
|
27
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
28
|
+
let transport;
|
|
29
|
+
if (sessionId && transports[sessionId]) {
|
|
30
|
+
const existingTransport = transports[sessionId];
|
|
31
|
+
if (existingTransport instanceof streamableHttp_js.StreamableHTTPServerTransport) {
|
|
32
|
+
transport = existingTransport;
|
|
33
|
+
} else {
|
|
34
|
+
res.status(400).json({
|
|
35
|
+
jsonrpc: "2.0",
|
|
36
|
+
error: {
|
|
37
|
+
code: -32e3,
|
|
38
|
+
message: "Bad Request: Session exists but uses a different transport protocol"
|
|
39
|
+
},
|
|
40
|
+
id: null
|
|
41
|
+
});
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
} else if (!sessionId && req.method === "POST" && types_js.isInitializeRequest(req.body)) {
|
|
45
|
+
const eventStore = new in_memory_store_cjs.InMemoryEventStore();
|
|
46
|
+
transport = new streamableHttp_js.StreamableHTTPServerTransport({
|
|
47
|
+
sessionIdGenerator: /* @__PURE__ */ __name(() => node_crypto.randomUUID(), "sessionIdGenerator"),
|
|
48
|
+
eventStore,
|
|
49
|
+
// Enable resumability
|
|
50
|
+
onsessioninitialized: /* @__PURE__ */ __name((sessionId2) => {
|
|
51
|
+
logger.debug(`StreamableHTTP session initialized with ID: ${sessionId2}`);
|
|
52
|
+
transports[sessionId2] = transport;
|
|
53
|
+
}, "onsessioninitialized")
|
|
54
|
+
});
|
|
55
|
+
transport.onclose = () => {
|
|
56
|
+
const sid = transport.sessionId;
|
|
57
|
+
if (sid && transports[sid]) {
|
|
58
|
+
logger.debug(`Transport closed for session ${sid}, removing from transports map`);
|
|
59
|
+
delete transports[sid];
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
await server.connect(transport);
|
|
63
|
+
} else {
|
|
64
|
+
res.status(400).json({
|
|
65
|
+
jsonrpc: "2.0",
|
|
66
|
+
error: {
|
|
67
|
+
code: -32e3,
|
|
68
|
+
message: "Bad Request: No valid session ID provided"
|
|
69
|
+
},
|
|
70
|
+
id: null
|
|
71
|
+
});
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
await transport.handleRequest(req, res, req.body);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
logger.error("Error handling MCP request:", error);
|
|
77
|
+
if (!res.headersSent) {
|
|
78
|
+
res.status(500).json({
|
|
79
|
+
jsonrpc: "2.0",
|
|
80
|
+
error: {
|
|
81
|
+
code: -32603,
|
|
82
|
+
message: "Internal server error"
|
|
83
|
+
},
|
|
84
|
+
id: null
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
app.get("/sse", async (req, res) => {
|
|
90
|
+
logger.info("Received GET request to /sse (deprecated SSE transport)");
|
|
91
|
+
const transport = new sse_js.SSEServerTransport("/messages", res);
|
|
92
|
+
transports[transport.sessionId] = transport;
|
|
93
|
+
res.on("close", () => {
|
|
94
|
+
delete transports[transport.sessionId];
|
|
95
|
+
});
|
|
96
|
+
await server.connect(transport);
|
|
97
|
+
});
|
|
98
|
+
app.post("/messages", async (req, res) => {
|
|
99
|
+
const sessionId = req.query.sessionId;
|
|
100
|
+
let transport;
|
|
101
|
+
const existingTransport = transports[sessionId];
|
|
102
|
+
if (existingTransport instanceof sse_js.SSEServerTransport) {
|
|
103
|
+
transport = existingTransport;
|
|
104
|
+
} else {
|
|
105
|
+
res.status(400).json({
|
|
106
|
+
jsonrpc: "2.0",
|
|
107
|
+
error: {
|
|
108
|
+
code: -32e3,
|
|
109
|
+
message: "Bad Request: Session exists but uses a different transport protocol"
|
|
110
|
+
},
|
|
111
|
+
id: null
|
|
112
|
+
});
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (transport) {
|
|
116
|
+
await transport.handlePostMessage(req, res, req.body);
|
|
117
|
+
} else {
|
|
118
|
+
res.status(400).send("No transport found for sessionId");
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
app.listen(port, hostname, () => {
|
|
122
|
+
logger.info(`Backwards compatible MCP server listening on port ${hostname}:${port}`);
|
|
123
|
+
logger.debug(`
|
|
124
|
+
==============================================
|
|
125
|
+
SUPPORTED TRANSPORT OPTIONS:
|
|
126
|
+
|
|
127
|
+
1. Streamable Http(Protocol version: 2025-03-26)
|
|
128
|
+
Endpoint: /mcp
|
|
129
|
+
Methods: GET, POST, DELETE
|
|
130
|
+
Usage:
|
|
131
|
+
- Initialize with POST to /mcp
|
|
132
|
+
- Establish SSE stream with GET to /mcp
|
|
133
|
+
- Send requests with POST to /mcp
|
|
134
|
+
- Terminate session with DELETE to /mcp
|
|
135
|
+
|
|
136
|
+
2. Http + SSE (Protocol version: 2024-11-05)
|
|
137
|
+
Endpoints: /sse (GET) and /messages (POST)
|
|
138
|
+
Usage:
|
|
139
|
+
- Establish SSE stream with GET to /sse
|
|
140
|
+
- Send requests with POST to /messages?sessionId=<id>
|
|
141
|
+
==============================================
|
|
142
|
+
`);
|
|
143
|
+
});
|
|
144
|
+
process.on("SIGINT", async () => {
|
|
145
|
+
logger.info("Shutting down server...");
|
|
146
|
+
for (const sessionId in transports) {
|
|
147
|
+
try {
|
|
148
|
+
logger.debug(`Closing transport for session ${sessionId}`);
|
|
149
|
+
await transports[sessionId].close();
|
|
150
|
+
delete transports[sessionId];
|
|
151
|
+
} catch (error) {
|
|
152
|
+
logger.error(`Error closing transport for session ${sessionId}:`, error);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
logger.debug("Server shutdown complete");
|
|
156
|
+
process.exit(0);
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
__name(runServer, "runServer");
|
|
160
|
+
|
|
161
|
+
exports.runServer = runServer;
|
|
162
|
+
//# sourceMappingURL=http_server.cjs.map
|
|
163
|
+
//# sourceMappingURL=http_server.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["http_server.ts"],"names":["logger","Logger","root","child","name","runServer","server","hostname","port","app","express","use","json","transports","all","req","res","debug","method","sessionId","headers","transport","existingTransport","StreamableHTTPServerTransport","status","jsonrpc","error","code","message","id","isInitializeRequest","body","eventStore","InMemoryEventStore","sessionIdGenerator","randomUUID","onsessioninitialized","onclose","sid","connect","handleRequest","headersSent","get","info","SSEServerTransport","on","post","query","handlePostMessage","send","listen","process","close","exit"],"mappings":"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","file":"http_server.cjs","sourcesContent":["/**\n * Copyright 2025 © BeeAI a Series of LF Projects, LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Taken from: https://github.com/modelcontextprotocol/typescript-sdk/blob/main/src/examples/server/sseAndStreamableHttpCompatibleServer.ts\n\nimport express, { Request, Response } from \"express\";\nimport { SSEServerTransport } from \"@modelcontextprotocol/sdk/server/sse.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { isInitializeRequest } from \"@modelcontextprotocol/sdk/types.js\";\nimport { InMemoryEventStore } from \"./in_memory_store.js\";\nimport { randomUUID } from \"node:crypto\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { Logger } from \"@/logger/logger.js\";\n\nconst logger = Logger.root.child({\n name: \"MCP HTTP server\",\n});\n\nexport function runServer(server: McpServer, hostname = \"127.0.0.1\", port = 3000) {\n // Create Express application\n const app = express();\n app.use(express.json());\n\n // Store transports by session ID\n const transports: Record<string, StreamableHTTPServerTransport | SSEServerTransport> = {};\n\n //=============================================================================\n // STREAMABLE HTTP TRANSPORT (PROTOCOL VERSION 2025-03-26)\n //=============================================================================\n\n // Handle all MCP Streamable HTTP requests (GET, POST, DELETE) on a single endpoint\n app.all(\"/mcp\", async (req: Request, res: Response) => {\n logger.debug(`Received ${req.method} request to /mcp`);\n\n try {\n // Check for existing session ID\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n let transport: StreamableHTTPServerTransport;\n\n if (sessionId && transports[sessionId]) {\n // Check if the transport is of the correct type\n const existingTransport = transports[sessionId];\n if (existingTransport instanceof StreamableHTTPServerTransport) {\n // Reuse existing transport\n transport = existingTransport;\n } else {\n // Transport exists but is not a StreamableHTTPServerTransport (could be SSEServerTransport)\n res.status(400).json({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: Session exists but uses a different transport protocol\",\n },\n id: null,\n });\n return;\n }\n } else if (!sessionId && req.method === \"POST\" && isInitializeRequest(req.body)) {\n const eventStore = new InMemoryEventStore();\n transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n eventStore, // Enable resumability\n onsessioninitialized: (sessionId) => {\n // Store the transport by session ID when session is initialized\n logger.debug(`StreamableHTTP session initialized with ID: ${sessionId}`);\n transports[sessionId] = transport;\n },\n });\n\n // Set up onclose handler to clean up transport when closed\n transport.onclose = () => {\n const sid = transport.sessionId;\n if (sid && transports[sid]) {\n logger.debug(`Transport closed for session ${sid}, removing from transports map`);\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete transports[sid];\n }\n };\n\n // Connect the transport to the MCP server\n await server.connect(transport);\n } else {\n // Invalid request - no session ID or not initialization request\n res.status(400).json({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: No valid session ID provided\",\n },\n id: null,\n });\n return;\n }\n\n // Handle the request with the transport\n await transport.handleRequest(req, res, req.body);\n } catch (error) {\n logger.error(\"Error handling MCP request:\", error);\n if (!res.headersSent) {\n res.status(500).json({\n jsonrpc: \"2.0\",\n error: {\n code: -32603,\n message: \"Internal server error\",\n },\n id: null,\n });\n }\n }\n });\n\n //=============================================================================\n // DEPRECATED HTTP+SSE TRANSPORT (PROTOCOL VERSION 2024-11-05)\n //=============================================================================\n\n app.get(\"/sse\", async (req: Request, res: Response) => {\n logger.info(\"Received GET request to /sse (deprecated SSE transport)\");\n const transport = new SSEServerTransport(\"/messages\", res);\n transports[transport.sessionId] = transport;\n res.on(\"close\", () => {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete transports[transport.sessionId];\n });\n await server.connect(transport);\n });\n\n app.post(\"/messages\", async (req: Request, res: Response) => {\n const sessionId = req.query.sessionId as string;\n let transport: SSEServerTransport;\n const existingTransport = transports[sessionId];\n if (existingTransport instanceof SSEServerTransport) {\n // Reuse existing transport\n transport = existingTransport;\n } else {\n // Transport exists but is not a SSEServerTransport (could be StreamableHTTPServerTransport)\n res.status(400).json({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: Session exists but uses a different transport protocol\",\n },\n id: null,\n });\n return;\n }\n if (transport) {\n await transport.handlePostMessage(req, res, req.body);\n } else {\n res.status(400).send(\"No transport found for sessionId\");\n }\n });\n\n // Start the server\n app.listen(port, hostname, () => {\n logger.info(`Backwards compatible MCP server listening on port ${hostname}:${port}`);\n logger.debug(`\n ==============================================\n SUPPORTED TRANSPORT OPTIONS:\n\n 1. Streamable Http(Protocol version: 2025-03-26)\n Endpoint: /mcp\n Methods: GET, POST, DELETE\n Usage: \n - Initialize with POST to /mcp\n - Establish SSE stream with GET to /mcp\n - Send requests with POST to /mcp\n - Terminate session with DELETE to /mcp\n\n 2. Http + SSE (Protocol version: 2024-11-05)\n Endpoints: /sse (GET) and /messages (POST)\n Usage:\n - Establish SSE stream with GET to /sse\n - Send requests with POST to /messages?sessionId=<id>\n ==============================================\n `);\n });\n\n // Handle server shutdown\n process.on(\"SIGINT\", async () => {\n logger.info(\"Shutting down server...\");\n\n // Close all active transports to properly clean up resources\n for (const sessionId in transports) {\n try {\n logger.debug(`Closing transport for session ${sessionId}`);\n await transports[sessionId].close();\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete transports[sessionId];\n } catch (error) {\n logger.error(`Error closing transport for session ${sessionId}:`, error);\n }\n }\n logger.debug(\"Server shutdown complete\");\n process.exit(0);\n });\n}\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Copyright 2025 © BeeAI a Series of LF Projects, LLC
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
declare function runServer(server: McpServer, hostname?: string, port?: number): void;
|
|
20
|
+
|
|
21
|
+
export { runServer };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Copyright 2025 © BeeAI a Series of LF Projects, LLC
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
declare function runServer(server: McpServer, hostname?: string, port?: number): void;
|
|
20
|
+
|
|
21
|
+
export { runServer };
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
3
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
4
|
+
import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import { InMemoryEventStore } from './in_memory_store.js';
|
|
6
|
+
import { randomUUID } from 'node:crypto';
|
|
7
|
+
import { Logger } from '../../../logger/logger.js';
|
|
8
|
+
|
|
9
|
+
var __defProp = Object.defineProperty;
|
|
10
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
11
|
+
const logger = Logger.root.child({
|
|
12
|
+
name: "MCP HTTP server"
|
|
13
|
+
});
|
|
14
|
+
function runServer(server, hostname = "127.0.0.1", port = 3e3) {
|
|
15
|
+
const app = express();
|
|
16
|
+
app.use(express.json());
|
|
17
|
+
const transports = {};
|
|
18
|
+
app.all("/mcp", async (req, res) => {
|
|
19
|
+
logger.debug(`Received ${req.method} request to /mcp`);
|
|
20
|
+
try {
|
|
21
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
22
|
+
let transport;
|
|
23
|
+
if (sessionId && transports[sessionId]) {
|
|
24
|
+
const existingTransport = transports[sessionId];
|
|
25
|
+
if (existingTransport instanceof StreamableHTTPServerTransport) {
|
|
26
|
+
transport = existingTransport;
|
|
27
|
+
} else {
|
|
28
|
+
res.status(400).json({
|
|
29
|
+
jsonrpc: "2.0",
|
|
30
|
+
error: {
|
|
31
|
+
code: -32e3,
|
|
32
|
+
message: "Bad Request: Session exists but uses a different transport protocol"
|
|
33
|
+
},
|
|
34
|
+
id: null
|
|
35
|
+
});
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
} else if (!sessionId && req.method === "POST" && isInitializeRequest(req.body)) {
|
|
39
|
+
const eventStore = new InMemoryEventStore();
|
|
40
|
+
transport = new StreamableHTTPServerTransport({
|
|
41
|
+
sessionIdGenerator: /* @__PURE__ */ __name(() => randomUUID(), "sessionIdGenerator"),
|
|
42
|
+
eventStore,
|
|
43
|
+
// Enable resumability
|
|
44
|
+
onsessioninitialized: /* @__PURE__ */ __name((sessionId2) => {
|
|
45
|
+
logger.debug(`StreamableHTTP session initialized with ID: ${sessionId2}`);
|
|
46
|
+
transports[sessionId2] = transport;
|
|
47
|
+
}, "onsessioninitialized")
|
|
48
|
+
});
|
|
49
|
+
transport.onclose = () => {
|
|
50
|
+
const sid = transport.sessionId;
|
|
51
|
+
if (sid && transports[sid]) {
|
|
52
|
+
logger.debug(`Transport closed for session ${sid}, removing from transports map`);
|
|
53
|
+
delete transports[sid];
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
await server.connect(transport);
|
|
57
|
+
} else {
|
|
58
|
+
res.status(400).json({
|
|
59
|
+
jsonrpc: "2.0",
|
|
60
|
+
error: {
|
|
61
|
+
code: -32e3,
|
|
62
|
+
message: "Bad Request: No valid session ID provided"
|
|
63
|
+
},
|
|
64
|
+
id: null
|
|
65
|
+
});
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
await transport.handleRequest(req, res, req.body);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
logger.error("Error handling MCP request:", error);
|
|
71
|
+
if (!res.headersSent) {
|
|
72
|
+
res.status(500).json({
|
|
73
|
+
jsonrpc: "2.0",
|
|
74
|
+
error: {
|
|
75
|
+
code: -32603,
|
|
76
|
+
message: "Internal server error"
|
|
77
|
+
},
|
|
78
|
+
id: null
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
app.get("/sse", async (req, res) => {
|
|
84
|
+
logger.info("Received GET request to /sse (deprecated SSE transport)");
|
|
85
|
+
const transport = new SSEServerTransport("/messages", res);
|
|
86
|
+
transports[transport.sessionId] = transport;
|
|
87
|
+
res.on("close", () => {
|
|
88
|
+
delete transports[transport.sessionId];
|
|
89
|
+
});
|
|
90
|
+
await server.connect(transport);
|
|
91
|
+
});
|
|
92
|
+
app.post("/messages", async (req, res) => {
|
|
93
|
+
const sessionId = req.query.sessionId;
|
|
94
|
+
let transport;
|
|
95
|
+
const existingTransport = transports[sessionId];
|
|
96
|
+
if (existingTransport instanceof SSEServerTransport) {
|
|
97
|
+
transport = existingTransport;
|
|
98
|
+
} else {
|
|
99
|
+
res.status(400).json({
|
|
100
|
+
jsonrpc: "2.0",
|
|
101
|
+
error: {
|
|
102
|
+
code: -32e3,
|
|
103
|
+
message: "Bad Request: Session exists but uses a different transport protocol"
|
|
104
|
+
},
|
|
105
|
+
id: null
|
|
106
|
+
});
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (transport) {
|
|
110
|
+
await transport.handlePostMessage(req, res, req.body);
|
|
111
|
+
} else {
|
|
112
|
+
res.status(400).send("No transport found for sessionId");
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
app.listen(port, hostname, () => {
|
|
116
|
+
logger.info(`Backwards compatible MCP server listening on port ${hostname}:${port}`);
|
|
117
|
+
logger.debug(`
|
|
118
|
+
==============================================
|
|
119
|
+
SUPPORTED TRANSPORT OPTIONS:
|
|
120
|
+
|
|
121
|
+
1. Streamable Http(Protocol version: 2025-03-26)
|
|
122
|
+
Endpoint: /mcp
|
|
123
|
+
Methods: GET, POST, DELETE
|
|
124
|
+
Usage:
|
|
125
|
+
- Initialize with POST to /mcp
|
|
126
|
+
- Establish SSE stream with GET to /mcp
|
|
127
|
+
- Send requests with POST to /mcp
|
|
128
|
+
- Terminate session with DELETE to /mcp
|
|
129
|
+
|
|
130
|
+
2. Http + SSE (Protocol version: 2024-11-05)
|
|
131
|
+
Endpoints: /sse (GET) and /messages (POST)
|
|
132
|
+
Usage:
|
|
133
|
+
- Establish SSE stream with GET to /sse
|
|
134
|
+
- Send requests with POST to /messages?sessionId=<id>
|
|
135
|
+
==============================================
|
|
136
|
+
`);
|
|
137
|
+
});
|
|
138
|
+
process.on("SIGINT", async () => {
|
|
139
|
+
logger.info("Shutting down server...");
|
|
140
|
+
for (const sessionId in transports) {
|
|
141
|
+
try {
|
|
142
|
+
logger.debug(`Closing transport for session ${sessionId}`);
|
|
143
|
+
await transports[sessionId].close();
|
|
144
|
+
delete transports[sessionId];
|
|
145
|
+
} catch (error) {
|
|
146
|
+
logger.error(`Error closing transport for session ${sessionId}:`, error);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
logger.debug("Server shutdown complete");
|
|
150
|
+
process.exit(0);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
__name(runServer, "runServer");
|
|
154
|
+
|
|
155
|
+
export { runServer };
|
|
156
|
+
//# sourceMappingURL=http_server.js.map
|
|
157
|
+
//# sourceMappingURL=http_server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["http_server.ts"],"names":["logger","Logger","root","child","name","runServer","server","hostname","port","app","express","use","json","transports","all","req","res","debug","method","sessionId","headers","transport","existingTransport","StreamableHTTPServerTransport","status","jsonrpc","error","code","message","id","isInitializeRequest","body","eventStore","InMemoryEventStore","sessionIdGenerator","randomUUID","onsessioninitialized","onclose","sid","connect","handleRequest","headersSent","get","info","SSEServerTransport","on","post","query","handlePostMessage","send","listen","process","close","exit"],"mappings":"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","file":"http_server.js","sourcesContent":["/**\n * Copyright 2025 © BeeAI a Series of LF Projects, LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Taken from: https://github.com/modelcontextprotocol/typescript-sdk/blob/main/src/examples/server/sseAndStreamableHttpCompatibleServer.ts\n\nimport express, { Request, Response } from \"express\";\nimport { SSEServerTransport } from \"@modelcontextprotocol/sdk/server/sse.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { isInitializeRequest } from \"@modelcontextprotocol/sdk/types.js\";\nimport { InMemoryEventStore } from \"./in_memory_store.js\";\nimport { randomUUID } from \"node:crypto\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { Logger } from \"@/logger/logger.js\";\n\nconst logger = Logger.root.child({\n name: \"MCP HTTP server\",\n});\n\nexport function runServer(server: McpServer, hostname = \"127.0.0.1\", port = 3000) {\n // Create Express application\n const app = express();\n app.use(express.json());\n\n // Store transports by session ID\n const transports: Record<string, StreamableHTTPServerTransport | SSEServerTransport> = {};\n\n //=============================================================================\n // STREAMABLE HTTP TRANSPORT (PROTOCOL VERSION 2025-03-26)\n //=============================================================================\n\n // Handle all MCP Streamable HTTP requests (GET, POST, DELETE) on a single endpoint\n app.all(\"/mcp\", async (req: Request, res: Response) => {\n logger.debug(`Received ${req.method} request to /mcp`);\n\n try {\n // Check for existing session ID\n const sessionId = req.headers[\"mcp-session-id\"] as string | undefined;\n let transport: StreamableHTTPServerTransport;\n\n if (sessionId && transports[sessionId]) {\n // Check if the transport is of the correct type\n const existingTransport = transports[sessionId];\n if (existingTransport instanceof StreamableHTTPServerTransport) {\n // Reuse existing transport\n transport = existingTransport;\n } else {\n // Transport exists but is not a StreamableHTTPServerTransport (could be SSEServerTransport)\n res.status(400).json({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: Session exists but uses a different transport protocol\",\n },\n id: null,\n });\n return;\n }\n } else if (!sessionId && req.method === \"POST\" && isInitializeRequest(req.body)) {\n const eventStore = new InMemoryEventStore();\n transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomUUID(),\n eventStore, // Enable resumability\n onsessioninitialized: (sessionId) => {\n // Store the transport by session ID when session is initialized\n logger.debug(`StreamableHTTP session initialized with ID: ${sessionId}`);\n transports[sessionId] = transport;\n },\n });\n\n // Set up onclose handler to clean up transport when closed\n transport.onclose = () => {\n const sid = transport.sessionId;\n if (sid && transports[sid]) {\n logger.debug(`Transport closed for session ${sid}, removing from transports map`);\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete transports[sid];\n }\n };\n\n // Connect the transport to the MCP server\n await server.connect(transport);\n } else {\n // Invalid request - no session ID or not initialization request\n res.status(400).json({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: No valid session ID provided\",\n },\n id: null,\n });\n return;\n }\n\n // Handle the request with the transport\n await transport.handleRequest(req, res, req.body);\n } catch (error) {\n logger.error(\"Error handling MCP request:\", error);\n if (!res.headersSent) {\n res.status(500).json({\n jsonrpc: \"2.0\",\n error: {\n code: -32603,\n message: \"Internal server error\",\n },\n id: null,\n });\n }\n }\n });\n\n //=============================================================================\n // DEPRECATED HTTP+SSE TRANSPORT (PROTOCOL VERSION 2024-11-05)\n //=============================================================================\n\n app.get(\"/sse\", async (req: Request, res: Response) => {\n logger.info(\"Received GET request to /sse (deprecated SSE transport)\");\n const transport = new SSEServerTransport(\"/messages\", res);\n transports[transport.sessionId] = transport;\n res.on(\"close\", () => {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete transports[transport.sessionId];\n });\n await server.connect(transport);\n });\n\n app.post(\"/messages\", async (req: Request, res: Response) => {\n const sessionId = req.query.sessionId as string;\n let transport: SSEServerTransport;\n const existingTransport = transports[sessionId];\n if (existingTransport instanceof SSEServerTransport) {\n // Reuse existing transport\n transport = existingTransport;\n } else {\n // Transport exists but is not a SSEServerTransport (could be StreamableHTTPServerTransport)\n res.status(400).json({\n jsonrpc: \"2.0\",\n error: {\n code: -32000,\n message: \"Bad Request: Session exists but uses a different transport protocol\",\n },\n id: null,\n });\n return;\n }\n if (transport) {\n await transport.handlePostMessage(req, res, req.body);\n } else {\n res.status(400).send(\"No transport found for sessionId\");\n }\n });\n\n // Start the server\n app.listen(port, hostname, () => {\n logger.info(`Backwards compatible MCP server listening on port ${hostname}:${port}`);\n logger.debug(`\n ==============================================\n SUPPORTED TRANSPORT OPTIONS:\n\n 1. Streamable Http(Protocol version: 2025-03-26)\n Endpoint: /mcp\n Methods: GET, POST, DELETE\n Usage: \n - Initialize with POST to /mcp\n - Establish SSE stream with GET to /mcp\n - Send requests with POST to /mcp\n - Terminate session with DELETE to /mcp\n\n 2. Http + SSE (Protocol version: 2024-11-05)\n Endpoints: /sse (GET) and /messages (POST)\n Usage:\n - Establish SSE stream with GET to /sse\n - Send requests with POST to /messages?sessionId=<id>\n ==============================================\n `);\n });\n\n // Handle server shutdown\n process.on(\"SIGINT\", async () => {\n logger.info(\"Shutting down server...\");\n\n // Close all active transports to properly clean up resources\n for (const sessionId in transports) {\n try {\n logger.debug(`Closing transport for session ${sessionId}`);\n await transports[sessionId].close();\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete transports[sessionId];\n } catch (error) {\n logger.error(`Error closing transport for session ${sessionId}:`, error);\n }\n }\n logger.debug(\"Server shutdown complete\");\n process.exit(0);\n });\n}\n"]}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
5
|
+
class InMemoryEventStore {
|
|
6
|
+
static {
|
|
7
|
+
__name(this, "InMemoryEventStore");
|
|
8
|
+
}
|
|
9
|
+
events = /* @__PURE__ */ new Map();
|
|
10
|
+
/**
|
|
11
|
+
* Generates a unique event ID for a given stream ID
|
|
12
|
+
*/
|
|
13
|
+
generateEventId(streamId) {
|
|
14
|
+
return `${streamId}_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Extracts the stream ID from an event ID
|
|
18
|
+
*/
|
|
19
|
+
getStreamIdFromEventId(eventId) {
|
|
20
|
+
const parts = eventId.split("_");
|
|
21
|
+
return parts.length > 0 ? parts[0] : "";
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Stores an event with a generated event ID
|
|
25
|
+
* Implements EventStore.storeEvent
|
|
26
|
+
*/
|
|
27
|
+
async storeEvent(streamId, message) {
|
|
28
|
+
const eventId = this.generateEventId(streamId);
|
|
29
|
+
this.events.set(eventId, {
|
|
30
|
+
streamId,
|
|
31
|
+
message
|
|
32
|
+
});
|
|
33
|
+
return eventId;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Replays events that occurred after a specific event ID
|
|
37
|
+
* Implements EventStore.replayEventsAfter
|
|
38
|
+
*/
|
|
39
|
+
async replayEventsAfter(lastEventId, { send }) {
|
|
40
|
+
if (!lastEventId || !this.events.has(lastEventId)) {
|
|
41
|
+
return "";
|
|
42
|
+
}
|
|
43
|
+
const streamId = this.getStreamIdFromEventId(lastEventId);
|
|
44
|
+
if (!streamId) {
|
|
45
|
+
return "";
|
|
46
|
+
}
|
|
47
|
+
let foundLastEvent = false;
|
|
48
|
+
const sortedEvents = [
|
|
49
|
+
...this.events.entries()
|
|
50
|
+
].sort((a, b) => a[0].localeCompare(b[0]));
|
|
51
|
+
for (const [eventId, { streamId: eventStreamId, message }] of sortedEvents) {
|
|
52
|
+
if (eventStreamId !== streamId) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (eventId === lastEventId) {
|
|
56
|
+
foundLastEvent = true;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (foundLastEvent) {
|
|
60
|
+
await send(eventId, message);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return streamId;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
exports.InMemoryEventStore = InMemoryEventStore;
|
|
68
|
+
//# sourceMappingURL=in_memory_store.cjs.map
|
|
69
|
+
//# sourceMappingURL=in_memory_store.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["in_memory_store.ts"],"names":["InMemoryEventStore","events","Map","generateEventId","streamId","Date","now","Math","random","toString","substring","getStreamIdFromEventId","eventId","parts","split","length","storeEvent","message","set","replayEventsAfter","lastEventId","send","has","foundLastEvent","sortedEvents","entries","sort","a","b","localeCompare","eventStreamId"],"mappings":";;;;AA0BO,MAAMA,kBAAAA,CAAAA;EA1Bb;;;AA2BUC,EAAAA,MAAAA,uBAAaC,GAAAA,EAAAA;;;;AAKbC,EAAAA,eAAAA,CAAgBC,QAA0B,EAAA;AAChD,IAAA,OAAO,GAAGA,QAAAA,CAAAA,CAAAA,EAAYC,IAAKC,CAAAA,GAAAA,EAAG,CAAMC,CAAAA,EAAAA,IAAAA,CAAKC,MAAM,EAAA,CAAGC,SAAS,EAAA,CAAA,CAAIC,SAAU,CAAA,CAAA,EAAG,EAAA,CAAA,CAAA,CAAA;AAC9E;;;;AAKQC,EAAAA,sBAAAA,CAAuBC,OAAyB,EAAA;AACtD,IAAMC,MAAAA,KAAAA,GAAQD,OAAQE,CAAAA,KAAAA,CAAM,GAAA,CAAA;AAC5B,IAAA,OAAOD,KAAME,CAAAA,MAAAA,GAAS,CAAIF,GAAAA,KAAAA,CAAM,CAAA,CAAK,GAAA,EAAA;AACvC;;;;;EAMA,MAAMG,UAAAA,CAAWZ,UAAkBa,OAA0C,EAAA;AAC3E,IAAML,MAAAA,OAAAA,GAAU,IAAKT,CAAAA,eAAAA,CAAgBC,QAAAA,CAAAA;AACrC,IAAKH,IAAAA,CAAAA,MAAAA,CAAOiB,IAAIN,OAAS,EAAA;AAAER,MAAAA,QAAAA;AAAUa,MAAAA;KAAQ,CAAA;AAC7C,IAAOL,OAAAA,OAAAA;AACT;;;;;AAMA,EAAA,MAAMO,iBACJC,CAAAA,WAAAA,EACA,EAAEC,IAAAA,EACe,EAAA;AACjB,IAAA,IAAI,CAACD,WAAe,IAAA,CAAC,KAAKnB,MAAOqB,CAAAA,GAAAA,CAAIF,WAAAA,CAAc,EAAA;AACjD,MAAO,OAAA,EAAA;AACT;AAGA,IAAMhB,MAAAA,QAAAA,GAAW,IAAKO,CAAAA,sBAAAA,CAAuBS,WAAAA,CAAAA;AAC7C,IAAA,IAAI,CAAChB,QAAU,EAAA;AACb,MAAO,OAAA,EAAA;AACT;AAEA,IAAA,IAAImB,cAAiB,GAAA,KAAA;AAGrB,IAAA,MAAMC,YAAe,GAAA;AAAI,MAAA,GAAA,IAAA,CAAKvB,OAAOwB,OAAO;MAAIC,IAAK,CAAA,CAACC,CAAGC,EAAAA,CAAAA,KAAMD,CAAE,CAAA,CAAA,EAAGE,aAAcD,CAAAA,CAAAA,CAAE,CAAA,CAAE,CAAA,CAAA;AAEtF,IAAW,KAAA,MAAA,CAAChB,SAAS,EAAER,QAAAA,EAAU0B,eAAeb,OAAO,EAAE,KAAKO,YAAc,EAAA;AAE1E,MAAA,IAAIM,kBAAkB1B,QAAU,EAAA;AAC9B,QAAA;AACF;AAGA,MAAA,IAAIQ,YAAYQ,WAAa,EAAA;AAC3BG,QAAiB,cAAA,GAAA,IAAA;AACjB,QAAA;AACF;AAEA,MAAA,IAAIA,cAAgB,EAAA;AAClB,QAAMF,MAAAA,IAAAA,CAAKT,SAASK,OAAAA,CAAAA;AACtB;AACF;AACA,IAAOb,OAAAA,QAAAA;AACT;AACF","file":"in_memory_store.cjs","sourcesContent":["/**\n * Copyright 2025 © BeeAI a Series of LF Projects, LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n// Taken from: https://github.com/modelcontextprotocol/typescript-sdk/blob/main/src/examples/shared/inMemoryEventStore.ts\n\nimport { EventStore } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\n\n/**\n * Simple in-memory implementation of the EventStore interface for resumability\n * This is primarily intended for examples and testing, not for production use\n * where a persistent storage solution would be more appropriate.\n */\nexport class InMemoryEventStore implements EventStore {\n private events = new Map<string, { streamId: string; message: JSONRPCMessage }>();\n\n /**\n * Generates a unique event ID for a given stream ID\n */\n private generateEventId(streamId: string): string {\n return `${streamId}_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;\n }\n\n /**\n * Extracts the stream ID from an event ID\n */\n private getStreamIdFromEventId(eventId: string): string {\n const parts = eventId.split(\"_\");\n return parts.length > 0 ? parts[0] : \"\";\n }\n\n /**\n * Stores an event with a generated event ID\n * Implements EventStore.storeEvent\n */\n async storeEvent(streamId: string, message: JSONRPCMessage): Promise<string> {\n const eventId = this.generateEventId(streamId);\n this.events.set(eventId, { streamId, message });\n return eventId;\n }\n\n /**\n * Replays events that occurred after a specific event ID\n * Implements EventStore.replayEventsAfter\n */\n async replayEventsAfter(\n lastEventId: string,\n { send }: { send: (eventId: string, message: JSONRPCMessage) => Promise<void> },\n ): Promise<string> {\n if (!lastEventId || !this.events.has(lastEventId)) {\n return \"\";\n }\n\n // Extract the stream ID from the event ID\n const streamId = this.getStreamIdFromEventId(lastEventId);\n if (!streamId) {\n return \"\";\n }\n\n let foundLastEvent = false;\n\n // Sort events by eventId for chronological ordering\n const sortedEvents = [...this.events.entries()].sort((a, b) => a[0].localeCompare(b[0]));\n\n for (const [eventId, { streamId: eventStreamId, message }] of sortedEvents) {\n // Only include events from the same stream\n if (eventStreamId !== streamId) {\n continue;\n }\n\n // Start sending events after we find the lastEventId\n if (eventId === lastEventId) {\n foundLastEvent = true;\n continue;\n }\n\n if (foundLastEvent) {\n await send(eventId, message);\n }\n }\n return streamId;\n }\n}\n"]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { EventStore } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
2
|
+
import { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Copyright 2025 © BeeAI a Series of LF Projects, LLC
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Simple in-memory implementation of the EventStore interface for resumability
|
|
22
|
+
* This is primarily intended for examples and testing, not for production use
|
|
23
|
+
* where a persistent storage solution would be more appropriate.
|
|
24
|
+
*/
|
|
25
|
+
declare class InMemoryEventStore implements EventStore {
|
|
26
|
+
private events;
|
|
27
|
+
/**
|
|
28
|
+
* Generates a unique event ID for a given stream ID
|
|
29
|
+
*/
|
|
30
|
+
private generateEventId;
|
|
31
|
+
/**
|
|
32
|
+
* Extracts the stream ID from an event ID
|
|
33
|
+
*/
|
|
34
|
+
private getStreamIdFromEventId;
|
|
35
|
+
/**
|
|
36
|
+
* Stores an event with a generated event ID
|
|
37
|
+
* Implements EventStore.storeEvent
|
|
38
|
+
*/
|
|
39
|
+
storeEvent(streamId: string, message: JSONRPCMessage): Promise<string>;
|
|
40
|
+
/**
|
|
41
|
+
* Replays events that occurred after a specific event ID
|
|
42
|
+
* Implements EventStore.replayEventsAfter
|
|
43
|
+
*/
|
|
44
|
+
replayEventsAfter(lastEventId: string, { send }: {
|
|
45
|
+
send: (eventId: string, message: JSONRPCMessage) => Promise<void>;
|
|
46
|
+
}): Promise<string>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { InMemoryEventStore };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { EventStore } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
2
|
+
import { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Copyright 2025 © BeeAI a Series of LF Projects, LLC
|
|
6
|
+
*
|
|
7
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
8
|
+
* you may not use this file except in compliance with the License.
|
|
9
|
+
* You may obtain a copy of the License at
|
|
10
|
+
*
|
|
11
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
12
|
+
*
|
|
13
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
14
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
15
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
16
|
+
* See the License for the specific language governing permissions and
|
|
17
|
+
* limitations under the License.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Simple in-memory implementation of the EventStore interface for resumability
|
|
22
|
+
* This is primarily intended for examples and testing, not for production use
|
|
23
|
+
* where a persistent storage solution would be more appropriate.
|
|
24
|
+
*/
|
|
25
|
+
declare class InMemoryEventStore implements EventStore {
|
|
26
|
+
private events;
|
|
27
|
+
/**
|
|
28
|
+
* Generates a unique event ID for a given stream ID
|
|
29
|
+
*/
|
|
30
|
+
private generateEventId;
|
|
31
|
+
/**
|
|
32
|
+
* Extracts the stream ID from an event ID
|
|
33
|
+
*/
|
|
34
|
+
private getStreamIdFromEventId;
|
|
35
|
+
/**
|
|
36
|
+
* Stores an event with a generated event ID
|
|
37
|
+
* Implements EventStore.storeEvent
|
|
38
|
+
*/
|
|
39
|
+
storeEvent(streamId: string, message: JSONRPCMessage): Promise<string>;
|
|
40
|
+
/**
|
|
41
|
+
* Replays events that occurred after a specific event ID
|
|
42
|
+
* Implements EventStore.replayEventsAfter
|
|
43
|
+
*/
|
|
44
|
+
replayEventsAfter(lastEventId: string, { send }: {
|
|
45
|
+
send: (eventId: string, message: JSONRPCMessage) => Promise<void>;
|
|
46
|
+
}): Promise<string>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export { InMemoryEventStore };
|