@memlink/cli 1.0.3 → 1.0.5

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/cli/index.js CHANGED
@@ -45902,24 +45902,46 @@ Memlink is a self-hosted MCP server that gives you persistent, organized memory
45902
45902
  ## Connection
45903
45903
 
45904
45904
  The MCP server runs at:
45905
+
45906
+ **Streamable HTTP** (modern clients):
45905
45907
  \`\`\`
45906
45908
  http://localhost:4444/mcp?id=YOUR_MEMORY_ID
45907
45909
  \`\`\`
45908
45910
 
45911
+ **SSE** (legacy clients like OpenCode):
45912
+ \`\`\`
45913
+ http://localhost:4444/sse?id=YOUR_MEMORY_ID
45914
+ \`\`\`
45915
+
45909
45916
  The memory ID is a 12-character alphanumeric string assigned when you create a memory via \`memlink init <name>\`.
45910
45917
 
45911
- ### MCP Config (for agent settings)
45918
+ ### Streamable HTTP config
45912
45919
 
45913
45920
  \`\`\`json
45914
45921
  {
45915
45922
  "mcpServers": {
45916
45923
  "memlink": {
45924
+ "type": "http",
45917
45925
  "url": "http://localhost:4444/mcp?id=YOUR_MEMORY_ID"
45918
45926
  }
45919
45927
  }
45920
45928
  }
45921
45929
  \`\`\`
45922
45930
 
45931
+ ### SSE config (OpenCode)
45932
+
45933
+ \`\`\`json
45934
+ {
45935
+ "mcpServers": {
45936
+ "memlink": {
45937
+ "type": "remote",
45938
+ "enabled": true,
45939
+ "url": "http://localhost:4444/sse?id=YOUR_MEMORY_ID"
45940
+ }
45941
+ }
45942
+ }
45943
+ \`\`\`
45944
+
45923
45945
  ## Session Workflow
45924
45946
 
45925
45947
  1. **Start of session** — Always call \`memory_read\` to load existing context
@@ -46002,7 +46024,7 @@ function nanoid(size = 21) {
46002
46024
  }
46003
46025
 
46004
46026
  // src/core/types.ts
46005
- var MEMLINK_VERSION = "1.0.3";
46027
+ var MEMLINK_VERSION = "1.0.5";
46006
46028
  var DEFAULT_PORT = 4444;
46007
46029
  var DEFAULT_HOST = "localhost";
46008
46030
  var CONFIG_DIR = ".memlink";
@@ -64883,6 +64905,134 @@ class StreamableHTTPServerTransport {
64883
64905
  }
64884
64906
  }
64885
64907
 
64908
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/server/sse.js
64909
+ import { randomUUID } from "node:crypto";
64910
+ import { TLSSocket } from "node:tls";
64911
+ var import_raw_body = __toESM(require_raw_body(), 1);
64912
+ var import_content_type = __toESM(require_content_type(), 1);
64913
+ import { URL as URL2 } from "node:url";
64914
+ var MAXIMUM_MESSAGE_SIZE = "4mb";
64915
+
64916
+ class SSEServerTransport {
64917
+ constructor(_endpoint, res, options) {
64918
+ this._endpoint = _endpoint;
64919
+ this.res = res;
64920
+ this._sessionId = randomUUID();
64921
+ this._options = options || { enableDnsRebindingProtection: false };
64922
+ }
64923
+ validateRequestHeaders(req) {
64924
+ if (!this._options.enableDnsRebindingProtection) {
64925
+ return;
64926
+ }
64927
+ if (this._options.allowedHosts && this._options.allowedHosts.length > 0) {
64928
+ const hostHeader = req.headers.host;
64929
+ if (!hostHeader || !this._options.allowedHosts.includes(hostHeader)) {
64930
+ return `Invalid Host header: ${hostHeader}`;
64931
+ }
64932
+ }
64933
+ if (this._options.allowedOrigins && this._options.allowedOrigins.length > 0) {
64934
+ const originHeader = req.headers.origin;
64935
+ if (originHeader && !this._options.allowedOrigins.includes(originHeader)) {
64936
+ return `Invalid Origin header: ${originHeader}`;
64937
+ }
64938
+ }
64939
+ return;
64940
+ }
64941
+ async start() {
64942
+ if (this._sseResponse) {
64943
+ throw new Error("SSEServerTransport already started! If using Server class, note that connect() calls start() automatically.");
64944
+ }
64945
+ this.res.writeHead(200, {
64946
+ "Content-Type": "text/event-stream",
64947
+ "Cache-Control": "no-cache, no-transform",
64948
+ Connection: "keep-alive"
64949
+ });
64950
+ const dummyBase = "http://localhost";
64951
+ const endpointUrl = new URL2(this._endpoint, dummyBase);
64952
+ endpointUrl.searchParams.set("sessionId", this._sessionId);
64953
+ const relativeUrlWithSession = endpointUrl.pathname + endpointUrl.search + endpointUrl.hash;
64954
+ this.res.write(`event: endpoint
64955
+ data: ${relativeUrlWithSession}
64956
+
64957
+ `);
64958
+ this._sseResponse = this.res;
64959
+ this.res.on("close", () => {
64960
+ this._sseResponse = undefined;
64961
+ this.onclose?.();
64962
+ });
64963
+ }
64964
+ async handlePostMessage(req, res, parsedBody) {
64965
+ if (!this._sseResponse) {
64966
+ const message = "SSE connection not established";
64967
+ res.writeHead(500).end(message);
64968
+ throw new Error(message);
64969
+ }
64970
+ const validationError = this.validateRequestHeaders(req);
64971
+ if (validationError) {
64972
+ res.writeHead(403).end(validationError);
64973
+ this.onerror?.(new Error(validationError));
64974
+ return;
64975
+ }
64976
+ const authInfo = req.auth;
64977
+ const host = req.headers.host;
64978
+ const protocol = req.socket instanceof TLSSocket ? "https" : "http";
64979
+ const fullUrl = host && req.url ? new URL2(req.url, `${protocol}://${host}`) : undefined;
64980
+ const requestInfo = {
64981
+ headers: req.headers,
64982
+ url: fullUrl
64983
+ };
64984
+ let body;
64985
+ try {
64986
+ const ct = import_content_type.default.parse(req.headers["content-type"] ?? "");
64987
+ if (ct.type !== "application/json") {
64988
+ throw new Error(`Unsupported content-type: ${ct.type}`);
64989
+ }
64990
+ body = parsedBody ?? await import_raw_body.default(req, {
64991
+ limit: MAXIMUM_MESSAGE_SIZE,
64992
+ encoding: ct.parameters.charset ?? "utf-8"
64993
+ });
64994
+ } catch (error2) {
64995
+ res.writeHead(400).end(String(error2));
64996
+ this.onerror?.(error2);
64997
+ return;
64998
+ }
64999
+ try {
65000
+ await this.handleMessage(typeof body === "string" ? JSON.parse(body) : body, { requestInfo, authInfo });
65001
+ } catch {
65002
+ res.writeHead(400).end(`Invalid message: ${body}`);
65003
+ return;
65004
+ }
65005
+ res.writeHead(202).end("Accepted");
65006
+ }
65007
+ async handleMessage(message, extra) {
65008
+ let parsedMessage;
65009
+ try {
65010
+ parsedMessage = JSONRPCMessageSchema.parse(message);
65011
+ } catch (error2) {
65012
+ this.onerror?.(error2);
65013
+ throw error2;
65014
+ }
65015
+ this.onmessage?.(parsedMessage, extra);
65016
+ }
65017
+ async close() {
65018
+ this._sseResponse?.end();
65019
+ this._sseResponse = undefined;
65020
+ this.onclose?.();
65021
+ }
65022
+ async send(message) {
65023
+ if (!this._sseResponse) {
65024
+ throw new Error("Not connected");
65025
+ }
65026
+ this._sseResponse.write(`event: message
65027
+ data: ${JSON.stringify(message)}
65028
+
65029
+ `);
65030
+ }
65031
+ get sessionId() {
65032
+ return this._sessionId;
65033
+ }
65034
+ }
65035
+
64886
65036
  // node_modules/zod/v4/classic/external.js
64887
65037
  var exports_external = {};
64888
65038
  __export(exports_external, {
@@ -79161,7 +79311,7 @@ function date7(params) {
79161
79311
  config2(en_default4());
79162
79312
  // src/server/index.ts
79163
79313
  var loggingEnabled = false;
79164
- function logRequest(req, memoryName, method, _params) {
79314
+ function logRequest(_req, memoryName, method, _params) {
79165
79315
  if (!loggingEnabled)
79166
79316
  return;
79167
79317
  const timestamp = new Date().toISOString();
@@ -79587,6 +79737,7 @@ Deleted: ${result.deleted}`
79587
79737
  });
79588
79738
  return server;
79589
79739
  }
79740
+ var sseSessions = new Map;
79590
79741
  function createApp() {
79591
79742
  const app = import_express.default();
79592
79743
  app.use(import_express.default.json({ limit: "10mb" }));
@@ -79624,6 +79775,50 @@ function createApp() {
79624
79775
  content: AGENT_SYSTEM_PROMPT(name)
79625
79776
  });
79626
79777
  });
79778
+ app.get("/sse", async (req, res) => {
79779
+ const memId = req.query.id || req.query.mem_id;
79780
+ if (!memId) {
79781
+ res.status(401).json({ error: "Missing memory ID. Use ?id=<memory_id>" });
79782
+ return;
79783
+ }
79784
+ const memoryInfo = getMemoryById(memId);
79785
+ if (!memoryInfo) {
79786
+ res.status(403).json({ error: "Invalid memory ID." });
79787
+ return;
79788
+ }
79789
+ const memoryId = memoryInfo.memoryId;
79790
+ const memoryName = memoryInfo.memoryName;
79791
+ updateUniversalMemoryLastSeen(memoryId);
79792
+ const mcpServer = buildMcpServer(memoryId, memoryName);
79793
+ const transport = new SSEServerTransport("/messages", res);
79794
+ sseSessions.set(transport.sessionId, { transport, memoryId, mcpServer });
79795
+ res.on("close", () => {
79796
+ sseSessions.delete(transport.sessionId);
79797
+ mcpServer.close();
79798
+ });
79799
+ try {
79800
+ await mcpServer.connect(transport);
79801
+ await transport.start();
79802
+ } catch {
79803
+ sseSessions.delete(transport.sessionId);
79804
+ mcpServer.close();
79805
+ }
79806
+ });
79807
+ app.post("/messages", async (req, res) => {
79808
+ const sessionId = req.query.sessionId;
79809
+ if (!sessionId || !sseSessions.has(sessionId)) {
79810
+ res.status(404).json({ error: "SSE session not found" });
79811
+ return;
79812
+ }
79813
+ const { transport } = sseSessions.get(sessionId);
79814
+ try {
79815
+ await transport.handlePostMessage(req, res, req.body);
79816
+ } catch (err2) {
79817
+ if (!res.headersSent) {
79818
+ res.status(500).json({ error: String(err2) });
79819
+ }
79820
+ }
79821
+ });
79627
79822
  app.all("/mcp", async (req, res) => {
79628
79823
  const memId = req.query.id || req.query.mem_id;
79629
79824
  if (!memId) {
@@ -79787,8 +79982,11 @@ function openUrl(url2) {
79787
79982
  function memoryTableRow(name, id, sizeKb) {
79788
79983
  return [colors.white(name), colors.dim(id), colors.dim(`${sizeKb} KB`)];
79789
79984
  }
79790
- function serverUrl(host, port) {
79791
- return `http://${host}:${port}/mcp`;
79985
+ function mcpUrl(host, port, memId) {
79986
+ return `http://${host}:${port}/mcp?id=${memId}`;
79987
+ }
79988
+ function sseUrl(host, port, memId) {
79989
+ return `http://${host}:${port}/sse?id=${memId}`;
79792
79990
  }
79793
79991
  var program2 = new Command;
79794
79992
  program2.name("memlink").description("Memlink — Universal memory for AI agents").version(MEMLINK_VERSION, "--version").addHelpText("before", logo());
@@ -79797,8 +79995,8 @@ program2.action(() => {
79797
79995
  const config3 = loadConfig();
79798
79996
  const host = envHost() || config3.serverHost || DEFAULT_HOST;
79799
79997
  const port = envPort() || config3.serverPort || DEFAULT_PORT;
79800
- const url2 = serverUrl(host, port);
79801
- console.log(info("Server", url2));
79998
+ const base = `http://${host}:${port}`;
79999
+ console.log(info("Server", base));
79802
80000
  let totalSize = 0;
79803
80001
  let totalEntries = 0;
79804
80002
  if (config3.universalMemories.length > 0) {
@@ -79839,7 +80037,8 @@ program2.command("serve").description("Start the Memlink MCP server").option("--
79839
80037
  const host = opts.host;
79840
80038
  if (config3.universalMemories.length > 0) {
79841
80039
  for (const mem of config3.universalMemories) {
79842
- console.log(info("URL", `http://${host}:${port}/mcp?id=${mem.memoryId}`));
80040
+ console.log(info("MCP", mcpUrl(host, port, mem.memoryId)));
80041
+ console.log(info("SSE", sseUrl(host, port, mem.memoryId)));
79843
80042
  }
79844
80043
  } else {
79845
80044
  console.log(info("no memories", "Create one with: Memlink init <name>"));
@@ -79856,12 +80055,14 @@ function initAction(name, opts) {
79856
80055
  const config3 = loadConfig();
79857
80056
  const host = envHost() || config3.serverHost || DEFAULT_HOST;
79858
80057
  const port = envPort() || config3.serverPort || DEFAULT_PORT;
79859
- const url2 = serverUrl(host, port) + `?id=${memory.memoryId}`;
80058
+ const mcp = mcpUrl(host, port, memory.memoryId);
80059
+ const sse = sseUrl(host, port, memory.memoryId);
79860
80060
  console.log(info("Name", memory.memoryName));
79861
80061
  console.log(info("ID", memory.memoryId));
79862
- console.log(info("URL", url2));
80062
+ console.log(info("MCP", mcp));
80063
+ console.log(info("SSE", sse));
79863
80064
  console.log();
79864
- const copied = copyToClipboard(url2);
80065
+ const copied = copyToClipboard(mcp);
79865
80066
  if (copied) {
79866
80067
  console.log(ok("URL copied to clipboard"));
79867
80068
  }
@@ -79912,7 +80113,8 @@ program2.command("connect <memoryId>").description("Get MCP connection details f
79912
80113
  }
79913
80114
  const host = envHost() || config3.serverHost || DEFAULT_HOST;
79914
80115
  const port = envPort() || config3.serverPort || DEFAULT_PORT;
79915
- const url2 = serverUrl(host, port) + `?id=${memory.memoryId}`;
80116
+ const mcp = mcpUrl(host, port, memory.memoryId);
80117
+ const sse = sseUrl(host, port, memory.memoryId);
79916
80118
  const small = logoSmall();
79917
80119
  if (small)
79918
80120
  console.log(`
@@ -79920,24 +80122,41 @@ program2.command("connect <memoryId>").description("Get MCP connection details f
79920
80122
  `);
79921
80123
  console.log(info("Name", memory.memoryName));
79922
80124
  console.log(info("ID", memory.memoryId));
79923
- console.log(info("URL", url2));
80125
+ console.log(info("MCP", mcp));
80126
+ console.log(info("SSE", sse));
79924
80127
  console.log();
79925
- const mcpConfig = {
80128
+ const httpConfig = {
79926
80129
  mcpServers: {
79927
80130
  memlink: {
79928
- url: url2
80131
+ type: "http",
80132
+ url: mcp
79929
80133
  }
79930
80134
  }
79931
80135
  };
79932
- console.log(subheading("MCP JSON:"));
79933
- const jsonStr = JSON.stringify(mcpConfig, null, 2);
80136
+ const sseConfig = {
80137
+ mcpServers: {
80138
+ memlink: {
80139
+ type: "remote",
80140
+ enabled: true,
80141
+ url: sse
80142
+ }
80143
+ }
80144
+ };
80145
+ console.log(subheading("Streamable HTTP (modern clients):"));
80146
+ console.log(colors.muted(" ```json"));
80147
+ console.log(colors.muted(JSON.stringify(httpConfig, null, 2).split(`
80148
+ `).map((l) => " " + l).join(`
80149
+ `)));
80150
+ console.log(colors.muted(" ```"));
80151
+ console.log();
80152
+ console.log(subheading("SSE (legacy clients like OpenCode):"));
79934
80153
  console.log(colors.muted(" ```json"));
79935
- console.log(colors.muted(jsonStr.split(`
80154
+ console.log(colors.muted(JSON.stringify(sseConfig, null, 2).split(`
79936
80155
  `).map((l) => " " + l).join(`
79937
80156
  `)));
79938
80157
  console.log(colors.muted(" ```"));
79939
80158
  console.log();
79940
- const copied = copyToClipboard(url2);
80159
+ const copied = copyToClipboard(mcp);
79941
80160
  if (copied) {
79942
80161
  console.log(ok("URL copied to clipboard"));
79943
80162
  }
@@ -56081,6 +56081,134 @@ class StreamableHTTPServerTransport {
56081
56081
  }
56082
56082
  }
56083
56083
 
56084
+ // node_modules/@modelcontextprotocol/sdk/dist/esm/server/sse.js
56085
+ import { randomUUID } from "node:crypto";
56086
+ import { TLSSocket } from "node:tls";
56087
+ var import_raw_body = __toESM(require_raw_body(), 1);
56088
+ var import_content_type = __toESM(require_content_type(), 1);
56089
+ import { URL as URL2 } from "node:url";
56090
+ var MAXIMUM_MESSAGE_SIZE = "4mb";
56091
+
56092
+ class SSEServerTransport {
56093
+ constructor(_endpoint, res, options) {
56094
+ this._endpoint = _endpoint;
56095
+ this.res = res;
56096
+ this._sessionId = randomUUID();
56097
+ this._options = options || { enableDnsRebindingProtection: false };
56098
+ }
56099
+ validateRequestHeaders(req) {
56100
+ if (!this._options.enableDnsRebindingProtection) {
56101
+ return;
56102
+ }
56103
+ if (this._options.allowedHosts && this._options.allowedHosts.length > 0) {
56104
+ const hostHeader = req.headers.host;
56105
+ if (!hostHeader || !this._options.allowedHosts.includes(hostHeader)) {
56106
+ return `Invalid Host header: ${hostHeader}`;
56107
+ }
56108
+ }
56109
+ if (this._options.allowedOrigins && this._options.allowedOrigins.length > 0) {
56110
+ const originHeader = req.headers.origin;
56111
+ if (originHeader && !this._options.allowedOrigins.includes(originHeader)) {
56112
+ return `Invalid Origin header: ${originHeader}`;
56113
+ }
56114
+ }
56115
+ return;
56116
+ }
56117
+ async start() {
56118
+ if (this._sseResponse) {
56119
+ throw new Error("SSEServerTransport already started! If using Server class, note that connect() calls start() automatically.");
56120
+ }
56121
+ this.res.writeHead(200, {
56122
+ "Content-Type": "text/event-stream",
56123
+ "Cache-Control": "no-cache, no-transform",
56124
+ Connection: "keep-alive"
56125
+ });
56126
+ const dummyBase = "http://localhost";
56127
+ const endpointUrl = new URL2(this._endpoint, dummyBase);
56128
+ endpointUrl.searchParams.set("sessionId", this._sessionId);
56129
+ const relativeUrlWithSession = endpointUrl.pathname + endpointUrl.search + endpointUrl.hash;
56130
+ this.res.write(`event: endpoint
56131
+ data: ${relativeUrlWithSession}
56132
+
56133
+ `);
56134
+ this._sseResponse = this.res;
56135
+ this.res.on("close", () => {
56136
+ this._sseResponse = undefined;
56137
+ this.onclose?.();
56138
+ });
56139
+ }
56140
+ async handlePostMessage(req, res, parsedBody) {
56141
+ if (!this._sseResponse) {
56142
+ const message = "SSE connection not established";
56143
+ res.writeHead(500).end(message);
56144
+ throw new Error(message);
56145
+ }
56146
+ const validationError = this.validateRequestHeaders(req);
56147
+ if (validationError) {
56148
+ res.writeHead(403).end(validationError);
56149
+ this.onerror?.(new Error(validationError));
56150
+ return;
56151
+ }
56152
+ const authInfo = req.auth;
56153
+ const host = req.headers.host;
56154
+ const protocol = req.socket instanceof TLSSocket ? "https" : "http";
56155
+ const fullUrl = host && req.url ? new URL2(req.url, `${protocol}://${host}`) : undefined;
56156
+ const requestInfo = {
56157
+ headers: req.headers,
56158
+ url: fullUrl
56159
+ };
56160
+ let body;
56161
+ try {
56162
+ const ct = import_content_type.default.parse(req.headers["content-type"] ?? "");
56163
+ if (ct.type !== "application/json") {
56164
+ throw new Error(`Unsupported content-type: ${ct.type}`);
56165
+ }
56166
+ body = parsedBody ?? await import_raw_body.default(req, {
56167
+ limit: MAXIMUM_MESSAGE_SIZE,
56168
+ encoding: ct.parameters.charset ?? "utf-8"
56169
+ });
56170
+ } catch (error2) {
56171
+ res.writeHead(400).end(String(error2));
56172
+ this.onerror?.(error2);
56173
+ return;
56174
+ }
56175
+ try {
56176
+ await this.handleMessage(typeof body === "string" ? JSON.parse(body) : body, { requestInfo, authInfo });
56177
+ } catch {
56178
+ res.writeHead(400).end(`Invalid message: ${body}`);
56179
+ return;
56180
+ }
56181
+ res.writeHead(202).end("Accepted");
56182
+ }
56183
+ async handleMessage(message, extra) {
56184
+ let parsedMessage;
56185
+ try {
56186
+ parsedMessage = JSONRPCMessageSchema.parse(message);
56187
+ } catch (error2) {
56188
+ this.onerror?.(error2);
56189
+ throw error2;
56190
+ }
56191
+ this.onmessage?.(parsedMessage, extra);
56192
+ }
56193
+ async close() {
56194
+ this._sseResponse?.end();
56195
+ this._sseResponse = undefined;
56196
+ this.onclose?.();
56197
+ }
56198
+ async send(message) {
56199
+ if (!this._sseResponse) {
56200
+ throw new Error("Not connected");
56201
+ }
56202
+ this._sseResponse.write(`event: message
56203
+ data: ${JSON.stringify(message)}
56204
+
56205
+ `);
56206
+ }
56207
+ get sessionId() {
56208
+ return this._sessionId;
56209
+ }
56210
+ }
56211
+
56084
56212
  // node_modules/zod/v4/classic/external.js
56085
56213
  var exports_external = {};
56086
56214
  __export(exports_external, {
@@ -70395,7 +70523,7 @@ function nanoid4(size = 21) {
70395
70523
  }
70396
70524
 
70397
70525
  // src/core/types.ts
70398
- var MEMLINK_VERSION = "1.0.3";
70526
+ var MEMLINK_VERSION = "1.0.5";
70399
70527
  var DEFAULT_PORT = 4444;
70400
70528
  var DEFAULT_HOST = "localhost";
70401
70529
  var CONFIG_DIR = ".memlink";
@@ -70813,7 +70941,7 @@ function bulkDeleteMemoriesByPattern(memoryId, pattern, useRegex = false) {
70813
70941
 
70814
70942
  // src/server/index.ts
70815
70943
  var loggingEnabled = false;
70816
- function logRequest(req, memoryName, method, _params) {
70944
+ function logRequest(_req, memoryName, method, _params) {
70817
70945
  if (!loggingEnabled)
70818
70946
  return;
70819
70947
  const timestamp = new Date().toISOString();
@@ -71239,6 +71367,7 @@ Deleted: ${result.deleted}`
71239
71367
  });
71240
71368
  return server;
71241
71369
  }
71370
+ var sseSessions = new Map;
71242
71371
  function createApp() {
71243
71372
  const app = import_express.default();
71244
71373
  app.use(import_express.default.json({ limit: "10mb" }));
@@ -71276,6 +71405,50 @@ function createApp() {
71276
71405
  content: AGENT_SYSTEM_PROMPT(name)
71277
71406
  });
71278
71407
  });
71408
+ app.get("/sse", async (req, res) => {
71409
+ const memId = req.query.id || req.query.mem_id;
71410
+ if (!memId) {
71411
+ res.status(401).json({ error: "Missing memory ID. Use ?id=<memory_id>" });
71412
+ return;
71413
+ }
71414
+ const memoryInfo = getMemoryById(memId);
71415
+ if (!memoryInfo) {
71416
+ res.status(403).json({ error: "Invalid memory ID." });
71417
+ return;
71418
+ }
71419
+ const memoryId = memoryInfo.memoryId;
71420
+ const memoryName = memoryInfo.memoryName;
71421
+ updateUniversalMemoryLastSeen(memoryId);
71422
+ const mcpServer = buildMcpServer(memoryId, memoryName);
71423
+ const transport = new SSEServerTransport("/messages", res);
71424
+ sseSessions.set(transport.sessionId, { transport, memoryId, mcpServer });
71425
+ res.on("close", () => {
71426
+ sseSessions.delete(transport.sessionId);
71427
+ mcpServer.close();
71428
+ });
71429
+ try {
71430
+ await mcpServer.connect(transport);
71431
+ await transport.start();
71432
+ } catch {
71433
+ sseSessions.delete(transport.sessionId);
71434
+ mcpServer.close();
71435
+ }
71436
+ });
71437
+ app.post("/messages", async (req, res) => {
71438
+ const sessionId = req.query.sessionId;
71439
+ if (!sessionId || !sseSessions.has(sessionId)) {
71440
+ res.status(404).json({ error: "SSE session not found" });
71441
+ return;
71442
+ }
71443
+ const { transport } = sseSessions.get(sessionId);
71444
+ try {
71445
+ await transport.handlePostMessage(req, res, req.body);
71446
+ } catch (err) {
71447
+ if (!res.headersSent) {
71448
+ res.status(500).json({ error: String(err) });
71449
+ }
71450
+ }
71451
+ });
71279
71452
  app.all("/mcp", async (req, res) => {
71280
71453
  const memId = req.query.id || req.query.mem_id;
71281
71454
  if (!memId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memlink/cli",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Memlink — Universal memory async and organized for AI agents. Self hosted, Fast, Organized.",
5
5
  "keywords": [
6
6
  "mcp",