@mysten-incubation/memwal-mcp 0.0.13 → 0.0.14-dev.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.
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Streamable HTTP transport for the stdio bridge.
3
+ *
4
+ * The legacy transport splits a call in two: POST to `/api/mcp/messages`, then
5
+ * wait for the reply to arrive on a separate `/api/mcp/sse` stream. Everything
6
+ * expensive in `bridge.ts` follows from that split — the `inFlight` map, the
7
+ * `sent` flag, the 404-means-never-ran reset, the idle watchdog, and the
8
+ * replay-on-reconnect path — because a POST can succeed while its reply is
9
+ * lost, and the bridge cannot tell that from a call still running.
10
+ *
11
+ * Streamable HTTP (MCP 2025-06) collapses that: one endpoint, and the reply
12
+ * comes back on the same request. The relayer has served it since
13
+ * `mcp_proxy.rs:751` ("Single endpoint that supersedes the SSE+POST split");
14
+ * only the bridge was still on the old transport.
15
+ *
16
+ * This module wraps the MCP SDK's own client transport rather than hand-rolling
17
+ * the protocol: session-id round-tripping, the optional SSE upgrade on a POST
18
+ * response, and resumption tokens are all spec details that are easy to get
19
+ * subtly wrong and that the SDK already implements.
20
+ */
21
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
22
+ import { log } from "./logger.js";
23
+ /**
24
+ * Resolve the transport from `MEMWAL_MCP_TRANSPORT`.
25
+ *
26
+ * Defaults to `sse`, the transport every released bridge has used. Streamable
27
+ * HTTP is opt-in until it has production mileage: this runs on users' machines
28
+ * against their real memories, so the new path proves itself before it becomes
29
+ * the one that runs by default.
30
+ *
31
+ * An unrecognised value falls back rather than throwing — a typo in a user's
32
+ * MCP config must not stop their memory from working.
33
+ */
34
+ export function resolveTransport(raw) {
35
+ const value = raw?.trim().toLowerCase();
36
+ if (!value)
37
+ return "sse";
38
+ if (value === "http" || value === "streamable" || value === "streamable-http") {
39
+ return "http";
40
+ }
41
+ if (value === "sse")
42
+ return "sse";
43
+ log.warn("bridge.transport_unrecognized", { value, using: "sse" });
44
+ return "sse";
45
+ }
46
+ /**
47
+ * The Streamable HTTP endpoint for a relayer base URL.
48
+ *
49
+ * `/api/mcp` — the same base the SSE transport hangs `/api/mcp/sse` and
50
+ * `/api/mcp/messages` off, minus the split.
51
+ */
52
+ export function streamableUrl(relayerUrl) {
53
+ return `${relayerUrl.replace(/\/+$/, "")}/api/mcp`;
54
+ }
55
+ /** HTTP status carried on the SDK's transport error, when it has one. */
56
+ function statusOf(err) {
57
+ const code = err?.code;
58
+ return typeof code === "number" ? code : 0;
59
+ }
60
+ export async function openStreamableSession(relayerUrl, creds, extraHeaders = {}) {
61
+ const url = streamableUrl(relayerUrl);
62
+ // Queue + waiter rather than an event emitter, so a message that arrives
63
+ // before `runBridge` pulls from the iterator is buffered instead of
64
+ // dropped. The SSE path does the same thing for the same reason.
65
+ const queue = [];
66
+ let wake = null;
67
+ let closed = false;
68
+ const push = (msg) => {
69
+ queue.push(msg);
70
+ const resume = wake;
71
+ wake = null;
72
+ resume?.();
73
+ };
74
+ const finish = () => {
75
+ closed = true;
76
+ const resume = wake;
77
+ wake = null;
78
+ resume?.();
79
+ };
80
+ const transport = new StreamableHTTPClientTransport(new URL(url), {
81
+ requestInit: {
82
+ headers: {
83
+ authorization: `Bearer ${creds.delegatePrivateKey}`,
84
+ "x-memwal-account-id": creds.accountId,
85
+ ...extraHeaders,
86
+ },
87
+ },
88
+ });
89
+ transport.onmessage = push;
90
+ transport.onclose = finish;
91
+ transport.onerror = (err) => {
92
+ log.warn("bridge.streamable_error", { err: String(err) });
93
+ // Not `finish()` — the SDK transport reconnects its own stream, and
94
+ // tearing the session down on a transient read error is what the SSE
95
+ // watchdog did wrong.
96
+ };
97
+ await transport.start();
98
+ const iter = {
99
+ async next() {
100
+ while (queue.length === 0) {
101
+ if (closed)
102
+ return { value: undefined, done: true };
103
+ await new Promise((resolve) => (wake = resolve));
104
+ }
105
+ return { value: queue.shift(), done: false };
106
+ },
107
+ };
108
+ return {
109
+ postUrl: url,
110
+ async send(msg) {
111
+ try {
112
+ await transport.send(msg);
113
+ return 200;
114
+ }
115
+ catch (err) {
116
+ const status = statusOf(err);
117
+ log.warn("bridge.streamable_send_failed", {
118
+ status,
119
+ err: String(err),
120
+ });
121
+ // Surface the status rather than throwing: `postIfCurrent`
122
+ // routes on it, and a 404 specifically means the message was
123
+ // discarded rather than run.
124
+ return status;
125
+ }
126
+ },
127
+ iter,
128
+ abort: () => {
129
+ void transport.close().catch(() => {
130
+ /* already gone */
131
+ });
132
+ finish();
133
+ },
134
+ };
135
+ }
136
+ //# sourceMappingURL=streamable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"streamable.js","sourceRoot":"","sources":["../src/streamable.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mysten-incubation/memwal-mcp",
3
- "version": "0.0.13",
3
+ "version": "0.0.14-dev.1",
4
4
  "description": "Walrus Memory MCP client — single-binary stdio MCP server that bridges Cursor / Claude Desktop / Antigravity / Claude Code to the Walrus Memory relayer. Handles browser-based wallet login on first run.",
5
5
  "type": "module",
6
6
  "engines": {