@lifeaitools/clauth 1.5.32 → 1.5.34
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/cli/commands/serve.js +31 -14
- package/package.json +1 -1
package/cli/commands/serve.js
CHANGED
|
@@ -2978,8 +2978,9 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
|
|
|
2978
2978
|
// fall through to MCP handling
|
|
2979
2979
|
}
|
|
2980
2980
|
|
|
2981
|
-
// ── MCP Streamable HTTP transport
|
|
2981
|
+
// ── MCP Streamable HTTP transport ──
|
|
2982
2982
|
// POST /sse, /mcp, /gws, /clauth — JSON-RPC over HTTP
|
|
2983
|
+
// claude.ai requires text/event-stream SSE format (like regen-media/Express).
|
|
2983
2984
|
if (method === "POST" && (reqPath === "/sse" || isMcpPath)) {
|
|
2984
2985
|
let body;
|
|
2985
2986
|
try { body = await readBody(req); } catch {
|
|
@@ -2992,26 +2993,45 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
|
|
|
2992
2993
|
const logMsg = `[${new Date().toISOString()}] Streamable HTTP [${reqPath}]: ${rpcMethod} id=${id}\n`;
|
|
2993
2994
|
try { fs.appendFileSync(LOG_FILE, logMsg); } catch {}
|
|
2994
2995
|
|
|
2996
|
+
// Check if client accepts SSE — claude.ai sends Accept: application/json, text/event-stream
|
|
2997
|
+
const acceptsSSE = (req.headers.accept || "").includes("text/event-stream");
|
|
2998
|
+
|
|
2999
|
+
// Helper: respond in SSE or JSON format based on client preference
|
|
3000
|
+
// SSE response matches regen-media/Express exactly: no CORS, Content-Length, x-powered-by
|
|
3001
|
+
function mcpRespond(res, jsonRpcResponse) {
|
|
3002
|
+
if (acceptsSSE) {
|
|
3003
|
+
const ssePayload = `event: message\ndata: ${JSON.stringify(jsonRpcResponse)}\n\n`;
|
|
3004
|
+
const buf = Buffer.from(ssePayload, "utf8");
|
|
3005
|
+
res.writeHead(200, {
|
|
3006
|
+
"Content-Type": "text/event-stream",
|
|
3007
|
+
"Content-Length": buf.length,
|
|
3008
|
+
"Cache-Control": "no-cache",
|
|
3009
|
+
"vary": "Accept-Encoding",
|
|
3010
|
+
"x-powered-by": "Express",
|
|
3011
|
+
});
|
|
3012
|
+
return res.end(buf);
|
|
3013
|
+
}
|
|
3014
|
+
res.writeHead(200, { "Content-Type": "application/json", ...CORS });
|
|
3015
|
+
return res.end(JSON.stringify(jsonRpcResponse));
|
|
3016
|
+
}
|
|
3017
|
+
|
|
2995
3018
|
// Notifications — no response needed
|
|
2996
3019
|
if (rpcMethod === "notifications/initialized" || rpcMethod === "initialized") {
|
|
2997
|
-
res.writeHead(
|
|
3020
|
+
res.writeHead(202, CORS);
|
|
2998
3021
|
return res.end();
|
|
2999
3022
|
}
|
|
3000
3023
|
|
|
3001
3024
|
if (rpcMethod === "initialize") {
|
|
3002
|
-
// Always return 2025-03-26 — returning 2025-11-25 causes claude.ai to require OAuth
|
|
3003
3025
|
const result = {
|
|
3004
3026
|
protocolVersion: "2025-03-26",
|
|
3005
3027
|
serverInfo: { name: serverNameForPath(reqPath), version: VERSION },
|
|
3006
|
-
capabilities: { tools: {} }
|
|
3028
|
+
capabilities: { tools: { listChanged: true } }
|
|
3007
3029
|
};
|
|
3008
|
-
res
|
|
3009
|
-
return res.end(JSON.stringify({ jsonrpc: "2.0", id, result }));
|
|
3030
|
+
return mcpRespond(res, { jsonrpc: "2.0", id, result });
|
|
3010
3031
|
}
|
|
3011
3032
|
|
|
3012
3033
|
if (rpcMethod === "tools/list") {
|
|
3013
|
-
res
|
|
3014
|
-
return res.end(JSON.stringify({ jsonrpc: "2.0", id, result: { tools: toolsForPath(reqPath) } }));
|
|
3034
|
+
return mcpRespond(res, { jsonrpc: "2.0", id, result: { tools: toolsForPath(reqPath) } });
|
|
3015
3035
|
}
|
|
3016
3036
|
|
|
3017
3037
|
if (rpcMethod === "tools/call") {
|
|
@@ -3021,17 +3041,14 @@ function createServer(initPassword, whitelist, port, tunnelHostnameInit = null,
|
|
|
3021
3041
|
try {
|
|
3022
3042
|
const result = await handleMcpTool(vault, name, args || {});
|
|
3023
3043
|
password = vault.password;
|
|
3024
|
-
res
|
|
3025
|
-
return res.end(JSON.stringify({ jsonrpc: "2.0", id, result }));
|
|
3044
|
+
return mcpRespond(res, { jsonrpc: "2.0", id, result });
|
|
3026
3045
|
} catch (err) {
|
|
3027
|
-
res
|
|
3028
|
-
return res.end(JSON.stringify({ jsonrpc: "2.0", id, result: mcpError(`Internal error: ${err.message}`) }));
|
|
3046
|
+
return mcpRespond(res, { jsonrpc: "2.0", id, result: mcpError(`Internal error: ${err.message}`) });
|
|
3029
3047
|
}
|
|
3030
3048
|
}
|
|
3031
3049
|
|
|
3032
3050
|
// Unknown method
|
|
3033
|
-
res
|
|
3034
|
-
return res.end(JSON.stringify({ jsonrpc: "2.0", id, error: { code: -32601, message: `Unknown method: ${rpcMethod}` } }));
|
|
3051
|
+
return mcpRespond(res, { jsonrpc: "2.0", id, error: { code: -32601, message: `Unknown method: ${rpcMethod}` } });
|
|
3035
3052
|
}
|
|
3036
3053
|
|
|
3037
3054
|
// ── MCP SSE transport — /sse and namespaced paths ────
|