@holin-work/holin-cli 1.2.0 → 1.2.1

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.
Files changed (2) hide show
  1. package/bin/holin-cli.js +42 -8
  2. package/package.json +1 -1
package/bin/holin-cli.js CHANGED
@@ -235,15 +235,49 @@ function createProxyServer() {
235
235
  headers: forwardHeaders,
236
236
  };
237
237
 
238
+ // Parse request body to determine MCP method
239
+ let mcpMethod = "";
240
+ try {
241
+ const parsed = JSON.parse(rawBody);
242
+ mcpMethod = parsed.method || "";
243
+ } catch { /* not JSON */ }
244
+
245
+ // Non-streaming methods should return JSON, not SSE
246
+ // Accio expects JSON for initialize and tools/list
247
+ const shouldConvertToJson = mcpMethod === "initialize" || mcpMethod === "tools/list";
248
+
238
249
  const proxyReq = https.request(options, (proxyRes) => {
239
- log(`[proxy] ← ${proxyRes.statusCode} content-type=${proxyRes.headers["content-type"]}`);
240
- // Forward response headers (strip content-length for chunked SSE)
241
- const headers = { ...proxyRes.headers };
242
- delete headers["content-length"];
243
- delete headers["transfer-encoding"];
244
-
245
- res.writeHead(proxyRes.statusCode || 502, headers);
246
- proxyRes.pipe(res);
250
+ log(`[proxy] ← ${proxyRes.statusCode} content-type=${proxyRes.headers["content-type"]} method=${mcpMethod}`);
251
+
252
+ if (shouldConvertToJson && proxyRes.headers["content-type"]?.includes("text/event-stream")) {
253
+ // Collect SSE response and convert to JSON
254
+ const sseChunks = [];
255
+ proxyRes.on("data", (c) => sseChunks.push(c));
256
+ proxyRes.on("end", () => {
257
+ const sseText = Buffer.concat(sseChunks).toString("utf8");
258
+ let jsonBody = sseText;
259
+ // Parse SSE: extract the last "data:" line
260
+ for (const line of sseText.split("\n")) {
261
+ const trimmed = line.trim();
262
+ if (trimmed.startsWith("data:")) {
263
+ jsonBody = trimmed.slice(5).trim();
264
+ }
265
+ }
266
+ const headers = { ...proxyRes.headers };
267
+ headers["content-type"] = "application/json";
268
+ headers["content-length"] = Buffer.byteLength(jsonBody);
269
+ delete headers["transfer-encoding"];
270
+ res.writeHead(proxyRes.statusCode || 502, headers);
271
+ res.end(jsonBody);
272
+ });
273
+ } else {
274
+ // Stream SSE directly for tools/call and other methods
275
+ const headers = { ...proxyRes.headers };
276
+ delete headers["content-length"];
277
+ delete headers["transfer-encoding"];
278
+ res.writeHead(proxyRes.statusCode || 502, headers);
279
+ proxyRes.pipe(res);
280
+ }
247
281
  });
248
282
 
249
283
  proxyReq.on("error", (err) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holin-work/holin-cli",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Holin CLI — Accio plugin authorization tool for ICBU batch listing",
5
5
  "type": "module",
6
6
  "bin": {