memorix 1.8.2 → 1.8.4
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/CHANGELOG.md +35 -0
- package/dist/cli/index.js +277 -39
- package/dist/index.js +268 -25
- package/dist/memcode-runtime/CHANGELOG.md +35 -0
- package/dist/sdk.js +25 -16
- package/docs/1.8.0-RELEASE-CANDIDATE-SPEC.md +5 -2
- package/docs/API_REFERENCE.md +9 -8
- package/docs/DEVELOPMENT.md +3 -2
- package/docs/README.md +12 -9
- package/package.json +2 -1
- package/plugins/antigravity/memorix/plugin.json +1 -1
- package/plugins/claude/memorix/.claude-plugin/plugin.json +1 -1
- package/plugins/codebuddy/memorix/.codebuddy-plugin/plugin.json +1 -1
- package/plugins/codex/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/copilot/memorix/plugin.json +1 -1
- package/plugins/gemini/memorix/gemini-extension.json +1 -1
- package/plugins/hermes/memorix/plugin.yaml +1 -1
- package/plugins/omp/memorix/package.json +1 -1
- package/plugins/openclaw/memorix/.codex-plugin/plugin.json +1 -1
- package/plugins/pi/memorix/package.json +1 -1
- package/server.json +2 -2
- package/src/cli/commands/serve-http.ts +2 -7
- package/src/cli/commands/serve.ts +26 -7
- package/src/server/mcp-compat.ts +18 -37
- package/src/server/mcp-discovery.ts +60 -0
- package/src/server/stdio-startup-gate.ts +263 -0
- package/src/server.ts +2 -5
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,41 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.8.4] - 2026-08-27
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- **Stateless HTTP MCP requests (#255)** -- clients such as Claude Code that
|
|
11
|
+
send the current protocol header on every request can list and call tools
|
|
12
|
+
without echoing a custom project handle. Durable handles are still created
|
|
13
|
+
on `initialize` and remain available when a client opts into them.
|
|
14
|
+
- **MCP protocol self-description (#257)** -- discovery and HTTP response
|
|
15
|
+
headers now advertise the legacy revisions implemented by the pinned SDK,
|
|
16
|
+
instead of claiming complete support for the newer 2026 revision.
|
|
17
|
+
- **MCP stdio smoke contract** -- the release smoke script now checks the
|
|
18
|
+
truthful advertised revision set after the compatibility fix.
|
|
19
|
+
|
|
20
|
+
### MCP Compatibility
|
|
21
|
+
- The 1.8.4 line supports legacy stateful MCP, versionless stdio tool calls,
|
|
22
|
+
pre-initialize discovery, and the narrow stateless HTTP compatibility path.
|
|
23
|
+
It does not claim full 2026 result metadata, Tasks, subscriptions, or list
|
|
24
|
+
caching support.
|
|
25
|
+
|
|
26
|
+
## [1.8.3] - 2026-08-25
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
- **Stdio MCP startup gate** -- `memorix serve` now reads and bounds
|
|
30
|
+
newline-delimited JSON-RPC input before project initialization completes.
|
|
31
|
+
Early `server/discover` requests receive the complete discovery result, while
|
|
32
|
+
initialize, notifications, responses, and versionless tool requests replay
|
|
33
|
+
through the pinned SDK transport in input order without duplicate handling.
|
|
34
|
+
|
|
35
|
+
### MCP Compatibility
|
|
36
|
+
- **Stable cold-start discovery** -- real stdio CLI startup now supports
|
|
37
|
+
pre-initialize discovery within the startup window and preserves legacy
|
|
38
|
+
initialize plus versionless `tools/list`/`tools/call` behavior. Tasks,
|
|
39
|
+
subscriptions, list-response caching, and modern non-discovery result
|
|
40
|
+
metadata remain unsupported or partial.
|
|
41
|
+
|
|
7
42
|
## [1.8.2] - 2026-08-25
|
|
8
43
|
|
|
9
44
|
### Fixed
|
package/dist/cli/index.js
CHANGED
|
@@ -3232,7 +3232,7 @@ ${import_picocolors.default.gray(m3)} ${s4}
|
|
|
3232
3232
|
|
|
3233
3233
|
// src/cli/version.ts
|
|
3234
3234
|
function getCliVersion() {
|
|
3235
|
-
return true ? "1.8.
|
|
3235
|
+
return true ? "1.8.4" : pkg.version;
|
|
3236
3236
|
}
|
|
3237
3237
|
var init_version = __esm({
|
|
3238
3238
|
"src/cli/version.ts"() {
|
|
@@ -205764,6 +205764,257 @@ var init_tool_profile = __esm({
|
|
|
205764
205764
|
}
|
|
205765
205765
|
});
|
|
205766
205766
|
|
|
205767
|
+
// src/server/mcp-discovery.ts
|
|
205768
|
+
function getMcpServerInfo() {
|
|
205769
|
+
return {
|
|
205770
|
+
name: "memorix",
|
|
205771
|
+
version: true ? "1.8.4" : "1.0.1"
|
|
205772
|
+
};
|
|
205773
|
+
}
|
|
205774
|
+
function createMcpDiscoverResult(capabilities, serverInfo) {
|
|
205775
|
+
return {
|
|
205776
|
+
resultType: "complete",
|
|
205777
|
+
supportedVersions: [
|
|
205778
|
+
MCP_LEGACY_PROTOCOL_VERSION,
|
|
205779
|
+
MCP_OLDEST_LEGACY_PROTOCOL_VERSION
|
|
205780
|
+
],
|
|
205781
|
+
capabilities,
|
|
205782
|
+
_meta: {
|
|
205783
|
+
[MCP_SERVER_INFO_META_KEY]: { ...serverInfo }
|
|
205784
|
+
},
|
|
205785
|
+
// v1 has no response-cache negotiation. A zero private TTL prevents clients
|
|
205786
|
+
// from inventing a shared cache for an implementation that cannot invalidate it.
|
|
205787
|
+
ttlMs: 0,
|
|
205788
|
+
cacheScope: "private"
|
|
205789
|
+
};
|
|
205790
|
+
}
|
|
205791
|
+
function createMcpStartupDiscoverResult(serverInfo) {
|
|
205792
|
+
return createMcpDiscoverResult({ tools: { listChanged: true } }, serverInfo);
|
|
205793
|
+
}
|
|
205794
|
+
var MCP_LEGACY_PROTOCOL_VERSION, MCP_OLDEST_LEGACY_PROTOCOL_VERSION, MCP_SERVER_DISCOVER_METHOD, MCP_SERVER_INFO_META_KEY;
|
|
205795
|
+
var init_mcp_discovery = __esm({
|
|
205796
|
+
"src/server/mcp-discovery.ts"() {
|
|
205797
|
+
"use strict";
|
|
205798
|
+
init_esm_shims();
|
|
205799
|
+
MCP_LEGACY_PROTOCOL_VERSION = "2025-11-25";
|
|
205800
|
+
MCP_OLDEST_LEGACY_PROTOCOL_VERSION = "2024-11-05";
|
|
205801
|
+
MCP_SERVER_DISCOVER_METHOD = "server/discover";
|
|
205802
|
+
MCP_SERVER_INFO_META_KEY = "io.modelcontextprotocol/serverInfo";
|
|
205803
|
+
}
|
|
205804
|
+
});
|
|
205805
|
+
|
|
205806
|
+
// src/server/stdio-startup-gate.ts
|
|
205807
|
+
import { PassThrough as PassThrough3 } from "stream";
|
|
205808
|
+
var STDIO_STARTUP_GATE_MAX_BUFFER_SIZE, StdioStartupGate;
|
|
205809
|
+
var init_stdio_startup_gate = __esm({
|
|
205810
|
+
"src/server/stdio-startup-gate.ts"() {
|
|
205811
|
+
"use strict";
|
|
205812
|
+
init_esm_shims();
|
|
205813
|
+
init_mcp_discovery();
|
|
205814
|
+
STDIO_STARTUP_GATE_MAX_BUFFER_SIZE = 10 * 1024 * 1024;
|
|
205815
|
+
StdioStartupGate = class {
|
|
205816
|
+
input = new PassThrough3();
|
|
205817
|
+
stdin;
|
|
205818
|
+
stdout;
|
|
205819
|
+
serverInfo;
|
|
205820
|
+
maxBufferSize;
|
|
205821
|
+
onError;
|
|
205822
|
+
onEnd;
|
|
205823
|
+
queuedMessages = [];
|
|
205824
|
+
pendingInput = "";
|
|
205825
|
+
queuedBytes = 0;
|
|
205826
|
+
started = false;
|
|
205827
|
+
ready = false;
|
|
205828
|
+
stopped = false;
|
|
205829
|
+
stdinEnded = false;
|
|
205830
|
+
endNotified = false;
|
|
205831
|
+
onData = (chunk) => {
|
|
205832
|
+
if (this.stopped) return;
|
|
205833
|
+
if (this.ready) {
|
|
205834
|
+
if (Buffer.byteLength(chunk, "utf8") > this.maxBufferSize) {
|
|
205835
|
+
this.fail(new Error(`stdio input chunk exceeded ${this.maxBufferSize} bytes`));
|
|
205836
|
+
return;
|
|
205837
|
+
}
|
|
205838
|
+
this.input.write(chunk);
|
|
205839
|
+
return;
|
|
205840
|
+
}
|
|
205841
|
+
const text2 = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
205842
|
+
if (this.queuedBytes + Buffer.byteLength(this.pendingInput, "utf8") + Buffer.byteLength(text2, "utf8") > this.maxBufferSize) {
|
|
205843
|
+
this.fail(new Error(`stdio startup input exceeded ${this.maxBufferSize} bytes before a complete JSON-RPC line`));
|
|
205844
|
+
return;
|
|
205845
|
+
}
|
|
205846
|
+
this.pendingInput += text2;
|
|
205847
|
+
let newline = this.pendingInput.indexOf("\n");
|
|
205848
|
+
while (newline >= 0 && !this.stopped) {
|
|
205849
|
+
const line = this.pendingInput.slice(0, newline + 1);
|
|
205850
|
+
this.pendingInput = this.pendingInput.slice(newline + 1);
|
|
205851
|
+
this.handleLine(line);
|
|
205852
|
+
newline = this.pendingInput.indexOf("\n");
|
|
205853
|
+
}
|
|
205854
|
+
if (!this.stopped && Buffer.byteLength(this.pendingInput, "utf8") > this.maxBufferSize) {
|
|
205855
|
+
this.fail(new Error(`stdio startup input exceeded ${this.maxBufferSize} bytes`));
|
|
205856
|
+
}
|
|
205857
|
+
};
|
|
205858
|
+
onStdinError = (error40) => {
|
|
205859
|
+
this.fail(error40);
|
|
205860
|
+
};
|
|
205861
|
+
onStdinEnd = () => {
|
|
205862
|
+
this.stdinEnded = true;
|
|
205863
|
+
if (this.ready) this.finishInput();
|
|
205864
|
+
};
|
|
205865
|
+
constructor(options) {
|
|
205866
|
+
this.stdin = options.stdin;
|
|
205867
|
+
this.stdout = options.stdout;
|
|
205868
|
+
this.serverInfo = { ...options.serverInfo };
|
|
205869
|
+
this.maxBufferSize = options.maxBufferSize ?? STDIO_STARTUP_GATE_MAX_BUFFER_SIZE;
|
|
205870
|
+
this.onError = options.onError;
|
|
205871
|
+
this.onEnd = options.onEnd;
|
|
205872
|
+
}
|
|
205873
|
+
start() {
|
|
205874
|
+
if (this.started || this.stopped) return;
|
|
205875
|
+
this.started = true;
|
|
205876
|
+
this.stdin.on("data", this.onData);
|
|
205877
|
+
this.stdin.on("error", this.onStdinError);
|
|
205878
|
+
this.stdin.on("end", this.onStdinEnd);
|
|
205879
|
+
}
|
|
205880
|
+
/** Release queued messages only after StdioServerTransport has installed its listener. */
|
|
205881
|
+
markReady() {
|
|
205882
|
+
if (this.stopped || this.ready) return;
|
|
205883
|
+
this.ready = true;
|
|
205884
|
+
for (const message of this.queuedMessages) this.input.write(message);
|
|
205885
|
+
this.queuedMessages.length = 0;
|
|
205886
|
+
this.queuedBytes = 0;
|
|
205887
|
+
if (this.pendingInput) {
|
|
205888
|
+
this.input.write(this.pendingInput);
|
|
205889
|
+
this.pendingInput = "";
|
|
205890
|
+
}
|
|
205891
|
+
if (this.stdinEnded) this.finishInput();
|
|
205892
|
+
}
|
|
205893
|
+
stop() {
|
|
205894
|
+
if (this.stopped) return;
|
|
205895
|
+
this.stopped = true;
|
|
205896
|
+
this.stdin.off("data", this.onData);
|
|
205897
|
+
this.stdin.off("error", this.onStdinError);
|
|
205898
|
+
this.stdin.off("end", this.onStdinEnd);
|
|
205899
|
+
this.queuedMessages.length = 0;
|
|
205900
|
+
this.pendingInput = "";
|
|
205901
|
+
this.queuedBytes = 0;
|
|
205902
|
+
if (!this.input.destroyed) this.input.end();
|
|
205903
|
+
}
|
|
205904
|
+
handleLine(line) {
|
|
205905
|
+
const parsed = this.parseLine(line);
|
|
205906
|
+
if (!parsed) return;
|
|
205907
|
+
if ("error" in parsed) {
|
|
205908
|
+
this.writeJsonRpcError(null, parsed.error.code, parsed.error.message);
|
|
205909
|
+
return;
|
|
205910
|
+
}
|
|
205911
|
+
if (!this.ready && this.isDiscoveryRequest(parsed.message)) {
|
|
205912
|
+
const response = {
|
|
205913
|
+
jsonrpc: "2.0",
|
|
205914
|
+
id: parsed.message.id,
|
|
205915
|
+
result: createMcpStartupDiscoverResult(this.serverInfo)
|
|
205916
|
+
};
|
|
205917
|
+
try {
|
|
205918
|
+
this.stdout.write(`${JSON.stringify(response)}
|
|
205919
|
+
`);
|
|
205920
|
+
} catch (error40) {
|
|
205921
|
+
this.fail(error40 instanceof Error ? error40 : new Error(String(error40)));
|
|
205922
|
+
}
|
|
205923
|
+
return;
|
|
205924
|
+
}
|
|
205925
|
+
if (this.ready) {
|
|
205926
|
+
this.input.write(line);
|
|
205927
|
+
return;
|
|
205928
|
+
}
|
|
205929
|
+
const bytes = Buffer.byteLength(line, "utf8");
|
|
205930
|
+
if (this.queuedBytes + bytes > this.maxBufferSize) {
|
|
205931
|
+
this.fail(new Error(`stdio startup queue exceeded ${this.maxBufferSize} bytes`));
|
|
205932
|
+
return;
|
|
205933
|
+
}
|
|
205934
|
+
this.queuedMessages.push(line);
|
|
205935
|
+
this.queuedBytes += bytes;
|
|
205936
|
+
}
|
|
205937
|
+
parseLine(line) {
|
|
205938
|
+
const trimmed = line.endsWith("\n") ? line.slice(0, -1).replace(/\r$/, "") : line;
|
|
205939
|
+
if (!trimmed.trim()) return null;
|
|
205940
|
+
let value;
|
|
205941
|
+
try {
|
|
205942
|
+
value = JSON.parse(trimmed);
|
|
205943
|
+
} catch {
|
|
205944
|
+
return { error: { code: -32700, message: "Parse error" } };
|
|
205945
|
+
}
|
|
205946
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
205947
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
205948
|
+
}
|
|
205949
|
+
const message = value;
|
|
205950
|
+
if (message.jsonrpc !== "2.0") {
|
|
205951
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
205952
|
+
}
|
|
205953
|
+
const hasId = Object.prototype.hasOwnProperty.call(message, "id");
|
|
205954
|
+
const hasMethod = typeof message.method === "string";
|
|
205955
|
+
const hasResult = Object.prototype.hasOwnProperty.call(message, "result");
|
|
205956
|
+
const hasError = Object.prototype.hasOwnProperty.call(message, "error");
|
|
205957
|
+
if (hasMethod && (hasResult || hasError)) {
|
|
205958
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
205959
|
+
}
|
|
205960
|
+
if (!hasMethod && !hasResult && !hasError) {
|
|
205961
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
205962
|
+
}
|
|
205963
|
+
if (hasId && !this.isValidRequestId(message.id)) {
|
|
205964
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
205965
|
+
}
|
|
205966
|
+
if (!hasMethod && !hasId) {
|
|
205967
|
+
return { error: { code: -32600, message: "Invalid Request" } };
|
|
205968
|
+
}
|
|
205969
|
+
return { message };
|
|
205970
|
+
}
|
|
205971
|
+
isDiscoveryRequest(message) {
|
|
205972
|
+
if (message.method !== MCP_SERVER_DISCOVER_METHOD) return false;
|
|
205973
|
+
if (!Object.prototype.hasOwnProperty.call(message, "id")) return false;
|
|
205974
|
+
const params = message.params;
|
|
205975
|
+
return params === void 0 || typeof params === "object" && params !== null && !Array.isArray(params);
|
|
205976
|
+
}
|
|
205977
|
+
isValidRequestId(id) {
|
|
205978
|
+
return id === null || typeof id === "string" || typeof id === "number" && Number.isFinite(id);
|
|
205979
|
+
}
|
|
205980
|
+
writeJsonRpcError(id, code, message) {
|
|
205981
|
+
try {
|
|
205982
|
+
this.stdout.write(`${JSON.stringify({
|
|
205983
|
+
jsonrpc: "2.0",
|
|
205984
|
+
id,
|
|
205985
|
+
error: { code, message }
|
|
205986
|
+
})}
|
|
205987
|
+
`);
|
|
205988
|
+
} catch (error40) {
|
|
205989
|
+
this.fail(error40 instanceof Error ? error40 : new Error(String(error40)));
|
|
205990
|
+
}
|
|
205991
|
+
}
|
|
205992
|
+
finishInput() {
|
|
205993
|
+
if (!this.ready || this.input.destroyed || this.input.writableEnded) return;
|
|
205994
|
+
this.input.end();
|
|
205995
|
+
this.input.once("end", () => this.notifyEnd());
|
|
205996
|
+
}
|
|
205997
|
+
notifyEnd() {
|
|
205998
|
+
if (this.endNotified) return;
|
|
205999
|
+
this.endNotified = true;
|
|
206000
|
+
this.onEnd?.();
|
|
206001
|
+
}
|
|
206002
|
+
fail(error40) {
|
|
206003
|
+
if (this.stopped) return;
|
|
206004
|
+
this.stopped = true;
|
|
206005
|
+
this.stdin.off("data", this.onData);
|
|
206006
|
+
this.stdin.off("error", this.onStdinError);
|
|
206007
|
+
this.stdin.off("end", this.onStdinEnd);
|
|
206008
|
+
this.queuedMessages.length = 0;
|
|
206009
|
+
this.pendingInput = "";
|
|
206010
|
+
this.queuedBytes = 0;
|
|
206011
|
+
if (!this.input.destroyed) this.input.destroy();
|
|
206012
|
+
this.onError?.(error40);
|
|
206013
|
+
}
|
|
206014
|
+
};
|
|
206015
|
+
}
|
|
206016
|
+
});
|
|
206017
|
+
|
|
205767
206018
|
// src/cli/mcp-root-path.ts
|
|
205768
206019
|
import path37 from "path";
|
|
205769
206020
|
function mcpFileUriToPath(uri, platform2 = process.platform) {
|
|
@@ -219212,40 +219463,22 @@ var init_request_context = __esm({
|
|
|
219212
219463
|
// src/server/mcp-compat.ts
|
|
219213
219464
|
function buildMcpDiscoverResult(server, serverInfo) {
|
|
219214
219465
|
const getCapabilities = server.server.getCapabilities.bind(server.server);
|
|
219215
|
-
return
|
|
219216
|
-
resultType: "complete",
|
|
219217
|
-
supportedVersions: [
|
|
219218
|
-
MCP_MODERN_PROTOCOL_VERSION,
|
|
219219
|
-
MCP_LEGACY_PROTOCOL_VERSION,
|
|
219220
|
-
MCP_OLDEST_LEGACY_PROTOCOL_VERSION
|
|
219221
|
-
],
|
|
219222
|
-
capabilities: getCapabilities(),
|
|
219223
|
-
_meta: {
|
|
219224
|
-
[MCP_SERVER_INFO_META_KEY]: { ...serverInfo }
|
|
219225
|
-
},
|
|
219226
|
-
// v1 has no response-cache negotiation. A zero private TTL is the
|
|
219227
|
-
// conservative result and prevents clients from inventing a shared cache.
|
|
219228
|
-
ttlMs: 0,
|
|
219229
|
-
cacheScope: "private"
|
|
219230
|
-
};
|
|
219466
|
+
return createMcpDiscoverResult(getCapabilities(), serverInfo);
|
|
219231
219467
|
}
|
|
219232
219468
|
function registerMcpDiscovery(server, serverInfo) {
|
|
219233
219469
|
if (registeredServers.has(server)) return;
|
|
219234
219470
|
server.server.setRequestHandler(ServerDiscoverRequestSchema, async () => buildMcpDiscoverResult(server, serverInfo));
|
|
219235
219471
|
registeredServers.add(server);
|
|
219236
219472
|
}
|
|
219237
|
-
var
|
|
219473
|
+
var ServerDiscoverRequestSchema, registeredServers;
|
|
219238
219474
|
var init_mcp_compat = __esm({
|
|
219239
219475
|
"src/server/mcp-compat.ts"() {
|
|
219240
219476
|
"use strict";
|
|
219241
219477
|
init_esm_shims();
|
|
219242
219478
|
init_types8();
|
|
219243
219479
|
init_v4();
|
|
219244
|
-
|
|
219245
|
-
|
|
219246
|
-
MCP_OLDEST_LEGACY_PROTOCOL_VERSION = "2024-11-05";
|
|
219247
|
-
MCP_SERVER_DISCOVER_METHOD = "server/discover";
|
|
219248
|
-
MCP_SERVER_INFO_META_KEY = "io.modelcontextprotocol/serverInfo";
|
|
219480
|
+
init_mcp_discovery();
|
|
219481
|
+
init_mcp_discovery();
|
|
219249
219482
|
ServerDiscoverRequestSchema = RequestSchema.extend({
|
|
219250
219483
|
method: external_exports.literal(MCP_SERVER_DISCOVER_METHOD),
|
|
219251
219484
|
params: external_exports.looseObject({}).optional()
|
|
@@ -261633,10 +261866,7 @@ The path should point to a directory containing a .git folder.`
|
|
|
261633
261866
|
isError: true
|
|
261634
261867
|
};
|
|
261635
261868
|
};
|
|
261636
|
-
const serverInfo =
|
|
261637
|
-
name: "memorix",
|
|
261638
|
-
version: true ? "1.8.2" : "1.0.1"
|
|
261639
|
-
};
|
|
261869
|
+
const serverInfo = getMcpServerInfo();
|
|
261640
261870
|
const server = existingServer ?? new McpServer(serverInfo);
|
|
261641
261871
|
registerMcpDiscovery(server, serverInfo);
|
|
261642
261872
|
const originalRegisterTool = server.registerTool.bind(server);
|
|
@@ -266372,6 +266602,8 @@ var init_serve = __esm({
|
|
|
266372
266602
|
init_esm_shims();
|
|
266373
266603
|
init_dist2();
|
|
266374
266604
|
init_tool_profile();
|
|
266605
|
+
init_mcp_discovery();
|
|
266606
|
+
init_stdio_startup_gate();
|
|
266375
266607
|
init_mcp_root_path();
|
|
266376
266608
|
serve_default = defineCommand({
|
|
266377
266609
|
meta: {
|
|
@@ -266396,15 +266628,25 @@ var init_serve = __esm({
|
|
|
266396
266628
|
}
|
|
266397
266629
|
},
|
|
266398
266630
|
run: async ({ args }) => {
|
|
266631
|
+
const startupGate = new StdioStartupGate({
|
|
266632
|
+
stdin: process.stdin,
|
|
266633
|
+
stdout: process.stdout,
|
|
266634
|
+
serverInfo: getMcpServerInfo(),
|
|
266635
|
+
onError: (error40) => {
|
|
266636
|
+
console.error(`[memorix] stdio startup gate error: ${error40.message}`);
|
|
266637
|
+
process.exit(1);
|
|
266638
|
+
},
|
|
266639
|
+
onEnd: () => {
|
|
266640
|
+
console.error("[memorix] stdin closed \u2014 exiting");
|
|
266641
|
+
process.exitCode = 0;
|
|
266642
|
+
}
|
|
266643
|
+
});
|
|
266644
|
+
startupGate.start();
|
|
266399
266645
|
const { StdioServerTransport: StdioServerTransport2 } = await Promise.resolve().then(() => (init_stdio2(), stdio_exports));
|
|
266400
266646
|
const { createMemorixServer: createMemorixServer2 } = await Promise.resolve().then(() => (init_server4(), server_exports2));
|
|
266401
266647
|
const { detectProject: detectProject2, findGitInSubdirs: findGitInSubdirs2, isSystemDirectory: isSystemDirectory2 } = await Promise.resolve().then(() => (init_detector(), detector_exports));
|
|
266402
266648
|
const { homedir: homedir36 } = await import("os");
|
|
266403
266649
|
const { resolveServeProject: resolveServeProject2 } = await Promise.resolve().then(() => (init_serve_shared(), serve_shared_exports));
|
|
266404
|
-
process.stdin.on("end", () => {
|
|
266405
|
-
console.error("[memorix] stdin closed \u2014 exiting");
|
|
266406
|
-
process.exit(0);
|
|
266407
|
-
});
|
|
266408
266650
|
let safeCwd;
|
|
266409
266651
|
try {
|
|
266410
266652
|
safeCwd = process.cwd();
|
|
@@ -266439,8 +266681,9 @@ var init_serve = __esm({
|
|
|
266439
266681
|
const toolProfile = resolveToolProfile({ explicit: args.mode, envValue: process.env.MEMORIX_MODE, fallback: "micro" });
|
|
266440
266682
|
const serverOptions = detected ? { toolProfile, deferProjectRuntimeInit: true } : { allowUntrackedFallback: allowUntracked, deferProjectInitUntilBound: !allowUntracked, deferProjectRuntimeInit: true, toolProfile };
|
|
266441
266683
|
const { server, projectId, deferredInit, switchProject } = await createMemorixServer2(projectRoot, void 0, void 0, serverOptions);
|
|
266442
|
-
const transport = new StdioServerTransport2();
|
|
266684
|
+
const transport = new StdioServerTransport2(startupGate.input, process.stdout);
|
|
266443
266685
|
await server.connect(transport);
|
|
266686
|
+
startupGate.markReady();
|
|
266444
266687
|
console.error(`[memorix] MCP Server running on stdio (project: ${projectId})`);
|
|
266445
266688
|
console.error(`[memorix] Project root: ${detected?.rootPath ?? projectRoot}`);
|
|
266446
266689
|
const tryRootsSwitch = async () => {
|
|
@@ -269036,7 +269279,7 @@ var init_serve_http = __esm({
|
|
|
269036
269279
|
res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
|
|
269037
269280
|
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, Mcp-Session-Id, Mcp-Project-Handle, Mcp-Project-Root, Mcp-Stateless, Last-Event-Id");
|
|
269038
269281
|
res.setHeader("Access-Control-Expose-Headers", "Mcp-Session-Id, Mcp-Project-Handle, Mcp-Protocol-Version, Mcp-Method, Mcp-Name");
|
|
269039
|
-
res.setHeader("Mcp-Protocol-Version",
|
|
269282
|
+
res.setHeader("Mcp-Protocol-Version", MCP_SDK_COMPAT_PROTOCOL_VERSION);
|
|
269040
269283
|
res.setHeader("Mcp-Method", req.method || "UNKNOWN");
|
|
269041
269284
|
res.setHeader("Mcp-Name", MCP_SERVER_NAME);
|
|
269042
269285
|
}
|
|
@@ -269050,11 +269293,6 @@ var init_serve_http = __esm({
|
|
|
269050
269293
|
}
|
|
269051
269294
|
const requestedRoot = typeof req.headers["mcp-project-root"] === "string" ? req.headers["mcp-project-root"] : void 0;
|
|
269052
269295
|
const root = persisted?.projectRoot ?? requestedRoot ?? projectRoot;
|
|
269053
|
-
if (!persisted && !isInitializeRequest2(body) && !isServerDiscoverRequest(body)) {
|
|
269054
|
-
res.writeHead(400, { "Content-Type": "application/json" });
|
|
269055
|
-
res.end(JSON.stringify({ jsonrpc: "2.0", error: { code: -32e3, message: "Stateless MCP requests require Mcp-Project-Handle; initialize first." }, id: null }));
|
|
269056
|
-
return;
|
|
269057
|
-
}
|
|
269058
269296
|
const { createMemorixServer: createMemorixServer3 } = await Promise.resolve().then(() => (init_server4(), server_exports2));
|
|
269059
269297
|
const { createProjectBindingController: createProjectBindingController3 } = await Promise.resolve().then(() => (init_request_context(), request_context_exports));
|
|
269060
269298
|
const binding = createProjectBindingController3(root);
|
|
@@ -269081,7 +269319,7 @@ var init_serve_http = __esm({
|
|
|
269081
269319
|
try {
|
|
269082
269320
|
await server.connect(transport);
|
|
269083
269321
|
let effectiveHandle = persisted;
|
|
269084
|
-
if (!effectiveHandle && projectId !== "__unresolved__") {
|
|
269322
|
+
if (!effectiveHandle && projectId !== "__unresolved__" && isInitializeRequest2(body)) {
|
|
269085
269323
|
effectiveHandle = statelessBindingStore.create({
|
|
269086
269324
|
projectId,
|
|
269087
269325
|
projectRoot: root,
|