@remnic/core 9.66.7 → 9.66.8
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/access-admin-ops-surface.d.ts +1 -1
- package/dist/access-admin-ops-surface.js +35 -35
- package/dist/access-authorization-probe.d.ts +1 -1
- package/dist/access-authorization-probe.js +36 -36
- package/dist/access-boundary.d.ts +1 -1
- package/dist/access-boundary.js +35 -35
- package/dist/access-cli.js +85 -84
- package/dist/access-cli.js.map +1 -1
- package/dist/access-extraction-force-flush.d.ts +1 -1
- package/dist/access-extraction-force-flush.js +35 -35
- package/dist/access-http-lcm-compaction.d.ts +1 -1
- package/dist/access-http-lifecycle-flush.d.ts +1 -1
- package/dist/access-http-offline-stream.d.ts +1 -1
- package/dist/access-http-query.js +37 -37
- package/dist/access-http.d.ts +2 -2
- package/dist/access-http.js +50 -49
- package/dist/access-identity-continuity-surface.js +35 -35
- package/dist/access-lcm-surface.d.ts +1 -1
- package/dist/access-lcm-surface.js +35 -35
- package/dist/access-mcp-sse.d.ts +20 -0
- package/dist/access-mcp-sse.js +8 -0
- package/dist/access-mcp-sse.js.map +1 -0
- package/dist/access-mcp.d.ts +1 -1
- package/dist/access-mcp.js +42 -42
- package/dist/access-namespace-preflight.js +35 -35
- package/dist/access-observe-write-surface.d.ts +1 -1
- package/dist/access-observe-write-surface.js +35 -35
- package/dist/access-offline-manifest.js +5 -5
- package/dist/access-operations-batch.js +36 -36
- package/dist/access-operations.d.ts +6 -6
- package/dist/access-operations.js +40 -40
- package/dist/access-recall-concurrency.d.ts +1 -1
- package/dist/access-recall-concurrency.js +35 -35
- package/dist/access-recall-response.d.ts +1 -1
- package/dist/access-recall-response.js +35 -35
- package/dist/access-recall-surface.d.ts +1 -1
- package/dist/access-recall-surface.js +35 -35
- package/dist/access-schema.d.ts +89 -89
- package/dist/access-service-helpers.d.ts +1 -1
- package/dist/access-service.d.ts +1 -1
- package/dist/access-service.js +35 -35
- package/dist/access-surface-catalog.d.ts +1 -1
- package/dist/access-surface-catalog.js +37 -37
- package/dist/active-recall.js +1 -1
- package/dist/briefing.js +12 -12
- package/dist/buffer.js +3 -3
- package/dist/causal-consolidation.js +13 -13
- package/dist/{chunk-BWZVFWMX.js → chunk-2MYBDWUY.js} +2 -2
- package/dist/{chunk-TNXNECAN.js → chunk-2OXIPF3A.js} +4 -4
- package/dist/{chunk-ZKE227GO.js → chunk-2V4YPDIX.js} +2 -2
- package/dist/{chunk-XJE6NHLT.js → chunk-2YDU4VR7.js} +46 -46
- package/dist/{chunk-POSD62F5.js → chunk-5IYJWCLC.js} +2 -2
- package/dist/{chunk-2W4MTU4P.js → chunk-5S6TQ36T.js} +31 -25
- package/dist/chunk-5S6TQ36T.js.map +1 -0
- package/dist/{chunk-CWPTYKCF.js → chunk-5UP5R37C.js} +3 -3
- package/dist/{chunk-D35XLYQ7.js → chunk-6BYJQ3L2.js} +4 -4
- package/dist/{chunk-CEK6AHIG.js → chunk-6ULLVM2V.js} +7 -7
- package/dist/{chunk-ABPLUXVY.js → chunk-6ZRLH4VS.js} +3 -3
- package/dist/{chunk-VVWOEKOZ.js → chunk-7X63THIR.js} +40 -40
- package/dist/{chunk-IN6D6BJG.js → chunk-AVYNKPFS.js} +14 -14
- package/dist/{chunk-YV4ST46A.js → chunk-AZLSFKGU.js} +4 -4
- package/dist/{chunk-MSXUEYH6.js → chunk-BDGWA5GK.js} +2 -2
- package/dist/{chunk-NMFPYAJ6.js → chunk-EKUABFXQ.js} +7 -7
- package/dist/{chunk-2C34EKRJ.js → chunk-FI6FT6YX.js} +2 -2
- package/dist/{chunk-OMGQAXUK.js → chunk-FNK4KIYR.js} +2 -2
- package/dist/{chunk-MGVOBLUK.js → chunk-FY62KW6Q.js} +2 -2
- package/dist/{chunk-XZBXINXZ.js → chunk-GIC6BASP.js} +4 -4
- package/dist/{chunk-PPAKBRI7.js → chunk-I2TIUGLC.js} +2 -2
- package/dist/{chunk-GNWLTCKC.js → chunk-IE7N2YK6.js} +2 -2
- package/dist/{chunk-Y3QQZOZ4.js → chunk-K7NUAY36.js} +15 -15
- package/dist/{chunk-7O24F2VS.js → chunk-KH2LZMD5.js} +2 -2
- package/dist/{chunk-QD55QEEY.js → chunk-KKGWB2LG.js} +5 -5
- package/dist/{chunk-FHY6HIAY.js → chunk-KMPEBHH5.js} +2 -2
- package/dist/{chunk-52DBRDP5.js → chunk-LWI43S46.js} +1 -1
- package/dist/{chunk-V6LJENGW.js → chunk-MBXTGOFR.js} +2 -2
- package/dist/{chunk-MAWHEUAA.js → chunk-MFIFCXS3.js} +2 -2
- package/dist/{chunk-KSZKQTZS.js → chunk-MWLBRFLY.js} +2 -2
- package/dist/{chunk-RACZB5HT.js → chunk-N37X5RU7.js} +4 -4
- package/dist/{chunk-6LMRUFBH.js → chunk-NEDBOZ7G.js} +2 -2
- package/dist/{chunk-BEUB5ABO.js → chunk-NEWY74GS.js} +2 -2
- package/dist/{chunk-AG46P24C.js → chunk-NNBZS3DY.js} +4 -4
- package/dist/{chunk-HQI2OQB5.js → chunk-O2RJZR6J.js} +5 -5
- package/dist/{chunk-6FUMA6AA.js → chunk-OERZXNSK.js} +2 -2
- package/dist/{chunk-KDYU3KZT.js → chunk-OMA2B7GY.js} +5 -5
- package/dist/{chunk-726CXBJO.js → chunk-QK375NXZ.js} +2 -2
- package/dist/{chunk-6TMIW4HE.js → chunk-RI4CMRTZ.js} +2 -2
- package/dist/{chunk-O7ERGZDA.js → chunk-RJ57OOCD.js} +2 -2
- package/dist/{chunk-SFJPCNBI.js → chunk-RPHCLGQ7.js} +2 -2
- package/dist/{chunk-42GDJAU7.js → chunk-S63O62DN.js} +2 -2
- package/dist/chunk-SRT6SHVZ.js +34 -0
- package/dist/chunk-SRT6SHVZ.js.map +1 -0
- package/dist/{chunk-2SW3N5HX.js → chunk-SVATDJNY.js} +2 -2
- package/dist/{chunk-4NKIGSJM.js → chunk-UJICQ77Y.js} +4 -4
- package/dist/{chunk-4COPICMD.js → chunk-ULTK4NZY.js} +6 -6
- package/dist/{chunk-DB2MKBQ7.js → chunk-UMSTKKMV.js} +2 -2
- package/dist/{chunk-Z3YEGSR4.js → chunk-UMZUKOJU.js} +4 -4
- package/dist/{chunk-PORKQEAW.js → chunk-UOQZOV2J.js} +99 -99
- package/dist/{chunk-PMNN247H.js → chunk-VYIPVLRX.js} +2 -2
- package/dist/{chunk-J2GY4UCR.js → chunk-X32ALJQB.js} +2 -2
- package/dist/{chunk-OCYRMVPT.js → chunk-XDUQR5R7.js} +2 -2
- package/dist/{chunk-QVEKPVCG.js → chunk-XORZMKVF.js} +3 -3
- package/dist/{chunk-THZ5UEQZ.js → chunk-XSPVSEAN.js} +3 -3
- package/dist/{chunk-FKBRP3J2.js → chunk-XUKS57W7.js} +2 -2
- package/dist/{chunk-ZW4SVXEY.js → chunk-XVCYV7WQ.js} +6 -6
- package/dist/{chunk-67U6UK5Q.js → chunk-YSYHSZWD.js} +2 -2
- package/dist/{cli-BOuEb4Ia.d.ts → cli-CsfFMe6n.d.ts} +1 -1
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +65 -64
- package/dist/coding/export-okf-codegraph.js +12 -12
- package/dist/compounding/engine.js +12 -12
- package/dist/config.js +1 -1
- package/dist/connectors/codex-materialize-runner.js +12 -12
- package/dist/connectors/index.js +13 -13
- package/dist/convergence-refresh.js +16 -16
- package/dist/corpus-watermark.js +15 -15
- package/dist/entity-retrieval.js +12 -12
- package/dist/explicit-capture.js +1 -1
- package/dist/external-wiki-access.d.ts +1 -1
- package/dist/external-wiki-access.js +36 -36
- package/dist/external-wiki-mcp-tools.d.ts +1 -1
- package/dist/extraction.js +25 -25
- package/dist/harmonic-retrieval.js +1 -1
- package/dist/index.d.ts +680 -680
- package/dist/index.js +135 -134
- package/dist/lcm/engine.js +2 -2
- package/dist/lcm/index.js +4 -4
- package/dist/location/index.js +45 -45
- package/dist/maintenance/memory-governance.js +13 -13
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +13 -13
- package/dist/maintenance/rebuild-memory-projection.js +15 -15
- package/dist/mcp-memory-inspector-app.d.ts +1 -1
- package/dist/memory-subject-cli.d.ts +1 -1
- package/dist/memory-subject.d.ts +1 -1
- package/dist/namespaces/migrate.js +13 -13
- package/dist/namespaces/search.js +6 -6
- package/dist/namespaces/storage.js +12 -12
- package/dist/offline-sync-impression-drain.js +4 -4
- package/dist/operator-doctor-corpus.js +16 -16
- package/dist/operator-toolkit.js +24 -24
- package/dist/orchestration/maintenance.js +26 -26
- package/dist/orchestrator.js +110 -109
- package/dist/{public-http-CmQRjQCD.d.ts → public-http-Cwvl4QZr.d.ts} +1 -1
- package/dist/resume-bundles.js +1 -1
- package/dist/schemas.d.ts +176 -176
- package/dist/search/factory.js +5 -5
- package/dist/search/index.js +5 -5
- package/dist/search/lancedb-backend.js +2 -2
- package/dist/search/meilisearch-backend.js +2 -2
- package/dist/search/orama-backend.js +2 -2
- package/dist/semantic-consolidation.js +13 -13
- package/dist/semantic-rule-promotion.js +12 -12
- package/dist/semantic-rule-verifier.js +12 -12
- package/dist/shared-context/manager.d.ts +6 -6
- package/dist/source-agent-qualifier.js +23 -23
- package/dist/storage.js +11 -11
- package/dist/support-passport/index.d.ts +4 -4
- package/dist/support-passport/index.js +38 -38
- package/dist/transfer/export-okf.js +13 -13
- package/dist/transfer/types.d.ts +78 -78
- package/dist/verified-recall.js +12 -12
- package/dist/who-knows-cli.d.ts +1 -1
- package/dist/who-knows-cli.js +13 -13
- package/dist/who-knows.d.ts +1 -1
- package/dist/who-knows.js +12 -12
- package/package.json +2 -2
- package/src/access-http.test.ts +41 -17
- package/src/access-http.ts +10 -10
- package/src/access-mcp-sse.ts +50 -0
- package/dist/chunk-2W4MTU4P.js.map +0 -1
- package/dist/{access-service-Dz6I9AZ-.d.ts → access-service-C2tV2-uL.d.ts} +64 -64
- /package/dist/{chunk-BWZVFWMX.js.map → chunk-2MYBDWUY.js.map} +0 -0
- /package/dist/{chunk-TNXNECAN.js.map → chunk-2OXIPF3A.js.map} +0 -0
- /package/dist/{chunk-ZKE227GO.js.map → chunk-2V4YPDIX.js.map} +0 -0
- /package/dist/{chunk-XJE6NHLT.js.map → chunk-2YDU4VR7.js.map} +0 -0
- /package/dist/{chunk-POSD62F5.js.map → chunk-5IYJWCLC.js.map} +0 -0
- /package/dist/{chunk-CWPTYKCF.js.map → chunk-5UP5R37C.js.map} +0 -0
- /package/dist/{chunk-D35XLYQ7.js.map → chunk-6BYJQ3L2.js.map} +0 -0
- /package/dist/{chunk-CEK6AHIG.js.map → chunk-6ULLVM2V.js.map} +0 -0
- /package/dist/{chunk-ABPLUXVY.js.map → chunk-6ZRLH4VS.js.map} +0 -0
- /package/dist/{chunk-VVWOEKOZ.js.map → chunk-7X63THIR.js.map} +0 -0
- /package/dist/{chunk-IN6D6BJG.js.map → chunk-AVYNKPFS.js.map} +0 -0
- /package/dist/{chunk-YV4ST46A.js.map → chunk-AZLSFKGU.js.map} +0 -0
- /package/dist/{chunk-MSXUEYH6.js.map → chunk-BDGWA5GK.js.map} +0 -0
- /package/dist/{chunk-NMFPYAJ6.js.map → chunk-EKUABFXQ.js.map} +0 -0
- /package/dist/{chunk-2C34EKRJ.js.map → chunk-FI6FT6YX.js.map} +0 -0
- /package/dist/{chunk-OMGQAXUK.js.map → chunk-FNK4KIYR.js.map} +0 -0
- /package/dist/{chunk-MGVOBLUK.js.map → chunk-FY62KW6Q.js.map} +0 -0
- /package/dist/{chunk-XZBXINXZ.js.map → chunk-GIC6BASP.js.map} +0 -0
- /package/dist/{chunk-PPAKBRI7.js.map → chunk-I2TIUGLC.js.map} +0 -0
- /package/dist/{chunk-GNWLTCKC.js.map → chunk-IE7N2YK6.js.map} +0 -0
- /package/dist/{chunk-Y3QQZOZ4.js.map → chunk-K7NUAY36.js.map} +0 -0
- /package/dist/{chunk-7O24F2VS.js.map → chunk-KH2LZMD5.js.map} +0 -0
- /package/dist/{chunk-QD55QEEY.js.map → chunk-KKGWB2LG.js.map} +0 -0
- /package/dist/{chunk-FHY6HIAY.js.map → chunk-KMPEBHH5.js.map} +0 -0
- /package/dist/{chunk-52DBRDP5.js.map → chunk-LWI43S46.js.map} +0 -0
- /package/dist/{chunk-V6LJENGW.js.map → chunk-MBXTGOFR.js.map} +0 -0
- /package/dist/{chunk-MAWHEUAA.js.map → chunk-MFIFCXS3.js.map} +0 -0
- /package/dist/{chunk-KSZKQTZS.js.map → chunk-MWLBRFLY.js.map} +0 -0
- /package/dist/{chunk-RACZB5HT.js.map → chunk-N37X5RU7.js.map} +0 -0
- /package/dist/{chunk-6LMRUFBH.js.map → chunk-NEDBOZ7G.js.map} +0 -0
- /package/dist/{chunk-BEUB5ABO.js.map → chunk-NEWY74GS.js.map} +0 -0
- /package/dist/{chunk-AG46P24C.js.map → chunk-NNBZS3DY.js.map} +0 -0
- /package/dist/{chunk-HQI2OQB5.js.map → chunk-O2RJZR6J.js.map} +0 -0
- /package/dist/{chunk-6FUMA6AA.js.map → chunk-OERZXNSK.js.map} +0 -0
- /package/dist/{chunk-KDYU3KZT.js.map → chunk-OMA2B7GY.js.map} +0 -0
- /package/dist/{chunk-726CXBJO.js.map → chunk-QK375NXZ.js.map} +0 -0
- /package/dist/{chunk-6TMIW4HE.js.map → chunk-RI4CMRTZ.js.map} +0 -0
- /package/dist/{chunk-O7ERGZDA.js.map → chunk-RJ57OOCD.js.map} +0 -0
- /package/dist/{chunk-SFJPCNBI.js.map → chunk-RPHCLGQ7.js.map} +0 -0
- /package/dist/{chunk-42GDJAU7.js.map → chunk-S63O62DN.js.map} +0 -0
- /package/dist/{chunk-2SW3N5HX.js.map → chunk-SVATDJNY.js.map} +0 -0
- /package/dist/{chunk-4NKIGSJM.js.map → chunk-UJICQ77Y.js.map} +0 -0
- /package/dist/{chunk-4COPICMD.js.map → chunk-ULTK4NZY.js.map} +0 -0
- /package/dist/{chunk-DB2MKBQ7.js.map → chunk-UMSTKKMV.js.map} +0 -0
- /package/dist/{chunk-Z3YEGSR4.js.map → chunk-UMZUKOJU.js.map} +0 -0
- /package/dist/{chunk-PORKQEAW.js.map → chunk-UOQZOV2J.js.map} +0 -0
- /package/dist/{chunk-PMNN247H.js.map → chunk-VYIPVLRX.js.map} +0 -0
- /package/dist/{chunk-J2GY4UCR.js.map → chunk-X32ALJQB.js.map} +0 -0
- /package/dist/{chunk-OCYRMVPT.js.map → chunk-XDUQR5R7.js.map} +0 -0
- /package/dist/{chunk-QVEKPVCG.js.map → chunk-XORZMKVF.js.map} +0 -0
- /package/dist/{chunk-THZ5UEQZ.js.map → chunk-XSPVSEAN.js.map} +0 -0
- /package/dist/{chunk-FKBRP3J2.js.map → chunk-XUKS57W7.js.map} +0 -0
- /package/dist/{chunk-ZW4SVXEY.js.map → chunk-XVCYV7WQ.js.map} +0 -0
- /package/dist/{chunk-67U6UK5Q.js.map → chunk-YSYHSZWD.js.map} +0 -0
package/src/access-http.test.ts
CHANGED
|
@@ -2354,7 +2354,7 @@ test("HTTP 401 www-authenticate is the bare Bearer challenge when resourceMetada
|
|
|
2354
2354
|
}
|
|
2355
2355
|
});
|
|
2356
2356
|
|
|
2357
|
-
test("HTTP /mcp
|
|
2357
|
+
test("HTTP /mcp serves GET SSE, DELETE 204, and 405 without SSE Accept (issue #2718)", async () => {
|
|
2358
2358
|
const service = {} as EngramAccessService;
|
|
2359
2359
|
const server = new EngramAccessHttpServer({
|
|
2360
2360
|
service,
|
|
@@ -2364,23 +2364,47 @@ test("HTTP /mcp returns 405 with Allow: POST for GET and DELETE (authorized requ
|
|
|
2364
2364
|
});
|
|
2365
2365
|
const status = await server.start();
|
|
2366
2366
|
try {
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
)
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2367
|
+
// Authorized GET with SSE Accept → 200 text/event-stream whose first
|
|
2368
|
+
// bytes are comment-only heartbeats (never JSON-RPC). Read one bounded
|
|
2369
|
+
// chunk, then cancel so the open stream cannot hang the test.
|
|
2370
|
+
const controller = new AbortController();
|
|
2371
|
+
const sse = await fetch(`http://127.0.0.1:${status.port}/mcp`, {
|
|
2372
|
+
headers: { authorization: "Bearer test-token", accept: "text/event-stream" },
|
|
2373
|
+
signal: controller.signal,
|
|
2374
|
+
});
|
|
2375
|
+
assert.equal(sse.status, 200, "GET /mcp with SSE Accept must be 200");
|
|
2376
|
+
assert.match(
|
|
2377
|
+
sse.headers.get("content-type") ?? "",
|
|
2378
|
+
/^text\/event-stream/,
|
|
2379
|
+
"GET /mcp SSE stream must advertise text/event-stream",
|
|
2380
|
+
);
|
|
2381
|
+
const reader = sse.body!.getReader();
|
|
2382
|
+
const { value: firstChunk } = await reader.read();
|
|
2383
|
+
const firstBytes = Buffer.from(firstChunk ?? []).toString("utf8");
|
|
2384
|
+
assert.ok(
|
|
2385
|
+
!firstBytes.includes("jsonrpc"),
|
|
2386
|
+
`GET /mcp stream must carry no JSON-RPC payload: ${JSON.stringify(firstBytes)}`,
|
|
2387
|
+
);
|
|
2388
|
+
controller.abort();
|
|
2389
|
+
|
|
2390
|
+
// Authorized GET without the SSE Accept → 405 + full method set.
|
|
2391
|
+
const rejected = await fetch(`http://127.0.0.1:${status.port}/mcp`, {
|
|
2392
|
+
headers: { authorization: "Bearer test-token" },
|
|
2393
|
+
});
|
|
2394
|
+
assert.equal(rejected.status, 405);
|
|
2395
|
+
assert.equal(rejected.headers.get("allow"), "GET, POST, DELETE");
|
|
2396
|
+
|
|
2397
|
+
// Authorized DELETE → 204 with empty body.
|
|
2398
|
+
const deleted = await fetch(`http://127.0.0.1:${status.port}/mcp`, {
|
|
2399
|
+
method: "DELETE",
|
|
2400
|
+
headers: { authorization: "Bearer test-token" },
|
|
2401
|
+
});
|
|
2402
|
+
assert.equal(deleted.status, 204);
|
|
2403
|
+
assert.equal(await deleted.text(), "");
|
|
2404
|
+
|
|
2405
|
+
// Unauthenticated GET /mcp still gets 401 first (auth gate beats method handling).
|
|
2382
2406
|
const unauth = await fetch(`http://127.0.0.1:${status.port}/mcp`, {
|
|
2383
|
-
|
|
2407
|
+
headers: { accept: "text/event-stream" },
|
|
2384
2408
|
});
|
|
2385
2409
|
assert.equal(unauth.status, 401);
|
|
2386
2410
|
} finally {
|
package/src/access-http.ts
CHANGED
|
@@ -27,6 +27,7 @@ import { nonEmptyQueryParam, optionalNamespaceKindQueryParam, optionalQueryStrin
|
|
|
27
27
|
import { CorrectionContractError } from "./correction/correction-contract.js";
|
|
28
28
|
import { respondWearablesErrorGlue } from "./wearables/http-glue.js"; import { respondMeetingsList, respondMeetingsGet, respondMeetingsBuild } from "./meetings/http-glue.js"; import { respondLocationStatus, respondLocationCheck, respondLocationSync, respondLocationBackfill, respondLocationDay } from "./location/http-glue.js"; import { respondStandup } from "./standup/http-glue.js";
|
|
29
29
|
import { EngramMcpServer, MCP_SUPPORTED_PROTOCOL_VERSIONS } from "./access-mcp.js";
|
|
30
|
+
import { handleMcpGetSse } from "./access-mcp-sse.js";
|
|
30
31
|
import { validateRequest, type SchemaName, type SchemaTypeFor } from "./access-schema.js";
|
|
31
32
|
import {
|
|
32
33
|
OFFLINE_SYNC_APPLY_MAX_BODY_BYTES,
|
|
@@ -884,17 +885,16 @@ export class EngramAccessHttpServer extends ReviewDeckAccessHttpBase {
|
|
|
884
885
|
correlationId: string,
|
|
885
886
|
abortSignal: AbortSignal,
|
|
886
887
|
): Promise<void> {
|
|
887
|
-
// Method-conformance for the streamable-HTTP MCP endpoint:
|
|
888
|
-
//
|
|
889
|
-
//
|
|
890
|
-
// to the
|
|
891
|
-
if (pathname === "/mcp" &&
|
|
888
|
+
// Method-conformance for the streamable-HTTP MCP endpoint (issue #2718):
|
|
889
|
+
// DELETE → 204, GET upgrades to the comment-only SSE stream in
|
|
890
|
+
// access-mcp-sse.ts when the client accepts text/event-stream, else 405
|
|
891
|
+
// with the full method set. POST continues to the handler below.
|
|
892
|
+
if (pathname === "/mcp" && req.method === "DELETE") { res.writeHead(204); res.end(); return; }
|
|
893
|
+
if (pathname === "/mcp" && req.method === "GET") {
|
|
894
|
+
if ((req.headers.accept ?? "").includes("text/event-stream"))
|
|
895
|
+
return handleMcpGetSse(req, res, this.sseCleanupFns);
|
|
892
896
|
const body = JSON.stringify({ error: "method_not_allowed", code: "method_not_allowed" });
|
|
893
|
-
res.writeHead(405, {
|
|
894
|
-
"content-type": "application/json; charset=utf-8",
|
|
895
|
-
allow: "POST",
|
|
896
|
-
"x-request-id": correlationId,
|
|
897
|
-
});
|
|
897
|
+
res.writeHead(405, { "content-type": "application/json; charset=utf-8", allow: "GET, POST, DELETE", "x-request-id": correlationId });
|
|
898
898
|
res.end(body);
|
|
899
899
|
return;
|
|
900
900
|
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from "node:http";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GET /mcp SSE half of the MCP streamable-HTTP transport (issue #2718).
|
|
5
|
+
*
|
|
6
|
+
* Clients such as the Grok Build TUI open a GET stream after `initialize`;
|
|
7
|
+
* that stream is reserved for server-initiated messages and this server has
|
|
8
|
+
* none to push, so it carries only SSE comment heartbeats — never a
|
|
9
|
+
* JSON-RPC payload. Header/heartbeat/cleanup shape mirrors
|
|
10
|
+
* `handleGraphEventsSSE` in access-http.ts (25 s heartbeat, cleanup
|
|
11
|
+
* registered in the server's `sseCleanupFns` set so `stop()` releases the
|
|
12
|
+
* interval even if the client never disconnects), but it subscribes to no
|
|
13
|
+
* event bus, resolves no namespace, and ignores `Last-Event-ID`.
|
|
14
|
+
*
|
|
15
|
+
* Lives in a sibling module rather than access-http.ts so the handler does
|
|
16
|
+
* not push that file past its fileSizeGrandfather ceiling (issue #1995).
|
|
17
|
+
*/
|
|
18
|
+
export function handleMcpGetSse(
|
|
19
|
+
req: IncomingMessage,
|
|
20
|
+
res: ServerResponse,
|
|
21
|
+
sseCleanupFns: Set<() => void>,
|
|
22
|
+
): void {
|
|
23
|
+
res.writeHead(200, {
|
|
24
|
+
"content-type": "text/event-stream; charset=utf-8",
|
|
25
|
+
"cache-control": "no-cache, no-store, must-revalidate",
|
|
26
|
+
"connection": "keep-alive",
|
|
27
|
+
"x-accel-buffering": "no",
|
|
28
|
+
"transfer-encoding": "chunked",
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Comment-only frames: `: ping\n\n` is a valid SSE comment that carries no
|
|
32
|
+
// data and cannot be mistaken for a JSON-RPC message. One is written
|
|
33
|
+
// immediately so clients and proxies see the stream is live without
|
|
34
|
+
// waiting for the first 25 s tick.
|
|
35
|
+
const heartbeat = (): void => {
|
|
36
|
+
try { res.write(": ping\n\n"); } catch { /* client gone; cleanup fires via "close" */ }
|
|
37
|
+
};
|
|
38
|
+
heartbeat();
|
|
39
|
+
const heartbeatInterval = setInterval(heartbeat, 25_000);
|
|
40
|
+
|
|
41
|
+
const cleanup = (): void => {
|
|
42
|
+
clearInterval(heartbeatInterval);
|
|
43
|
+
sseCleanupFns.delete(cleanup);
|
|
44
|
+
try { res.end(); } catch { /* ignore */ }
|
|
45
|
+
};
|
|
46
|
+
sseCleanupFns.add(cleanup);
|
|
47
|
+
|
|
48
|
+
req.once("close", cleanup);
|
|
49
|
+
req.once("error", cleanup);
|
|
50
|
+
}
|