@chrysb/alphaclaw 0.9.0-beta.4 → 0.9.0-beta.6
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/lib/server/routes/mcp.js +34 -42
- package/package.json +1 -1
package/lib/server/routes/mcp.js
CHANGED
|
@@ -26,34 +26,28 @@ const resolveGatewayWsUrl = ({ openclawDir, gatewayPort }) => {
|
|
|
26
26
|
return `${scheme}://127.0.0.1:${gatewayPort}`;
|
|
27
27
|
};
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
let activeSessionId = null;
|
|
30
30
|
let activeTransport = null;
|
|
31
|
-
const
|
|
31
|
+
const kSseKeepAliveMs = 15_000;
|
|
32
32
|
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
const closeActiveSession = () => {
|
|
34
|
+
if (!activeTransport) return;
|
|
35
|
+
const id = activeSessionId;
|
|
36
|
+
const t = activeTransport;
|
|
37
|
+
activeSessionId = null;
|
|
38
|
+
activeTransport = null;
|
|
38
39
|
t.close().catch(() => {});
|
|
40
|
+
if (id) console.log(`[mcp] Closed session: ${id}`);
|
|
39
41
|
};
|
|
40
42
|
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
setTimeout(() => {
|
|
50
|
-
for (const id of staleIds) {
|
|
51
|
-
if (sessions.has(id) && sessions.get(id) !== activeTransport) {
|
|
52
|
-
console.log(`[mcp] Cleaning up stale session: ${id}`);
|
|
53
|
-
closeSession(id);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}, kSessionGraceMs);
|
|
43
|
+
const adoptSession = (sessionId, transport) => {
|
|
44
|
+
if (activeTransport && activeTransport !== transport) {
|
|
45
|
+
const prevId = activeSessionId;
|
|
46
|
+
activeTransport.close().catch(() => {});
|
|
47
|
+
console.log(`[mcp] Replaced session ${prevId} → ${sessionId}`);
|
|
48
|
+
}
|
|
49
|
+
activeSessionId = sessionId;
|
|
50
|
+
activeTransport = transport;
|
|
57
51
|
};
|
|
58
52
|
|
|
59
53
|
const registerMcpRoutes = ({
|
|
@@ -102,7 +96,7 @@ const registerMcpRoutes = ({
|
|
|
102
96
|
});
|
|
103
97
|
|
|
104
98
|
app.post("/api/mcp/stop", requireAuth, async (_req, res) => {
|
|
105
|
-
|
|
99
|
+
closeActiveSession();
|
|
106
100
|
const result = stopMcpBridge();
|
|
107
101
|
res.json(result);
|
|
108
102
|
});
|
|
@@ -140,19 +134,24 @@ const registerMcpRoutes = ({
|
|
|
140
134
|
|
|
141
135
|
if (req.method === "GET") {
|
|
142
136
|
res.setHeader("X-Accel-Buffering", "no");
|
|
137
|
+
const keepAliveId = setInterval(() => {
|
|
138
|
+
if (res.headersSent && !res.writableEnded) {
|
|
139
|
+
res.write(": keepalive\n\n");
|
|
140
|
+
}
|
|
141
|
+
}, kSseKeepAliveMs);
|
|
142
|
+
res.on("close", () => clearInterval(keepAliveId));
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
const sessionId = req.headers["mcp-session-id"];
|
|
146
146
|
|
|
147
147
|
// ── Existing session ───────────────────────────────────────
|
|
148
148
|
if (sessionId) {
|
|
149
|
-
|
|
150
|
-
if (transport) {
|
|
149
|
+
if (sessionId === activeSessionId && activeTransport) {
|
|
151
150
|
console.log(
|
|
152
|
-
`[mcp] ${req.method} sessionId=${sessionId} →
|
|
151
|
+
`[mcp] ${req.method} sessionId=${sessionId} → active session`,
|
|
153
152
|
);
|
|
154
153
|
try {
|
|
155
|
-
await
|
|
154
|
+
await activeTransport.handleRequest(req, res, req.body);
|
|
156
155
|
} catch (err) {
|
|
157
156
|
console.error(
|
|
158
157
|
"[mcp] handleRequest error (existing session):",
|
|
@@ -164,7 +163,7 @@ const registerMcpRoutes = ({
|
|
|
164
163
|
}
|
|
165
164
|
} else {
|
|
166
165
|
console.log(
|
|
167
|
-
`[mcp] ${req.method} sessionId=${sessionId} → NOT FOUND (
|
|
166
|
+
`[mcp] ${req.method} sessionId=${sessionId} → NOT FOUND (active=${activeSessionId || "none"})`,
|
|
168
167
|
);
|
|
169
168
|
res.status(404).json({
|
|
170
169
|
jsonrpc: "2.0",
|
|
@@ -184,12 +183,8 @@ const registerMcpRoutes = ({
|
|
|
184
183
|
sessionIdGenerator: () => randomUUID(),
|
|
185
184
|
enableJsonResponse: true,
|
|
186
185
|
onsessioninitialized: (newSessionId) => {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
retireStaleSessions(newSessionId);
|
|
190
|
-
console.log(
|
|
191
|
-
`[mcp] Session registered: ${newSessionId} (sessions=${sessions.size})`,
|
|
192
|
-
);
|
|
186
|
+
adoptSession(newSessionId, transport);
|
|
187
|
+
console.log(`[mcp] Session adopted: ${newSessionId}`);
|
|
193
188
|
},
|
|
194
189
|
});
|
|
195
190
|
|
|
@@ -198,14 +193,11 @@ const registerMcpRoutes = ({
|
|
|
198
193
|
};
|
|
199
194
|
|
|
200
195
|
transport.onclose = () => {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
break;
|
|
205
|
-
}
|
|
196
|
+
if (activeTransport === transport) {
|
|
197
|
+
activeSessionId = null;
|
|
198
|
+
activeTransport = null;
|
|
206
199
|
}
|
|
207
|
-
|
|
208
|
-
console.log(`[mcp] Transport closed (sessions=${sessions.size})`);
|
|
200
|
+
console.log(`[mcp] Transport closed`);
|
|
209
201
|
};
|
|
210
202
|
|
|
211
203
|
transport.onerror = (err) => {
|