@mmnto/mcp 1.96.0 → 1.98.0
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/README.md +1 -1
- package/dist/description.test.d.ts +2 -0
- package/dist/description.test.d.ts.map +1 -0
- package/dist/description.test.js +16 -0
- package/dist/description.test.js.map +1 -0
- package/dist/search-log.d.ts +55 -1
- package/dist/search-log.d.ts.map +1 -1
- package/dist/search-log.js +54 -2
- package/dist/search-log.js.map +1 -1
- package/dist/search-log.test.d.ts +2 -0
- package/dist/search-log.test.d.ts.map +1 -0
- package/dist/search-log.test.js +89 -0
- package/dist/search-log.test.js.map +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @mmnto/mcp
|
|
2
2
|
|
|
3
|
-
MCP (Model Context Protocol) server for [Totem](https://github.com/mmnto-ai/totem)
|
|
3
|
+
MCP (Model Context Protocol) server for [Totem](https://github.com/mmnto-ai/totem) — a local-first, file-anchored substrate that makes AI-agent work queryable, enforceable, and derivable in your codebase. A stdio-based server that exposes a Totem project's knowledge index to MCP-compatible agents. Installs the `totem-mcp` binary.
|
|
4
4
|
|
|
5
5
|
## Setup
|
|
6
6
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"description.test.d.ts","sourceRoot":"","sources":["../src/description.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
// Family parity with the CLI's single-sourced self-description (mmnto-ai/totem#2336 D1,
|
|
4
|
+
// pattern from mmnto-ai/totem#2349): every published @mmnto package carries the ruled
|
|
5
|
+
// descriptive core and never regresses to the retired category label.
|
|
6
|
+
describe('package self-description parity (mmnto-ai/totem#2336 D1 family alignment)', () => {
|
|
7
|
+
it('package.json description carries the ruled descriptive core', () => {
|
|
8
|
+
const pkgUrl = new URL('../package.json', import.meta.url);
|
|
9
|
+
const pkg = JSON.parse(readFileSync(pkgUrl, 'utf-8'));
|
|
10
|
+
expect(pkg.name).toBe('@mmnto/mcp');
|
|
11
|
+
expect(pkg.description).toContain('a local-first, file-anchored substrate that makes AI-agent work queryable, enforceable, and derivable in your codebase');
|
|
12
|
+
// Guards against a regression to the retired category.
|
|
13
|
+
expect(pkg.description).not.toContain('persistent memory and context layer');
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=description.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"description.test.js","sourceRoot":"","sources":["../src/description.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAE9C,wFAAwF;AACxF,sFAAsF;AACtF,sEAAsE;AACtE,QAAQ,CAAC,2EAA2E,EAAE,GAAG,EAAE;IACzF,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;QACrE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAGnD,CAAC;QACF,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,SAAS,CAC/B,wHAAwH,CACzH,CAAC;QACF,uDAAuD;QACvD,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,qCAAqC,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/search-log.d.ts
CHANGED
|
@@ -7,7 +7,54 @@ export interface SearchLogEntry {
|
|
|
7
7
|
durationMs: number;
|
|
8
8
|
topScore: number | null;
|
|
9
9
|
error?: string;
|
|
10
|
+
/**
|
|
11
|
+
* A.3.a schema extension (ADR-029 flight-readiness note; ruled in on
|
|
12
|
+
* mmnto-ai/totem#2362). Env-derived at log time; the ~420 pre-extension
|
|
13
|
+
* entries stay permanently unattributed (no retro-inference — Tenet 20).
|
|
14
|
+
*
|
|
15
|
+
* Agent runtime attribution per ADR-078 § Decision item 2, STRICTLY
|
|
16
|
+
* orthogonal to any emitter/subsystem identifier. Derived from
|
|
17
|
+
* `TOTEM_SELF_AGENT` — the one env-carried agent identity in this cohort
|
|
18
|
+
* (packages/core/src/orchestration-resolver.ts § resolveSelfAgents,
|
|
19
|
+
* highest-precedence layer). `null` (stamped explicitly, never guessed —
|
|
20
|
+
* Tenet 4) when the env var is absent, so the reader can partition legacy +
|
|
21
|
+
* hookless events into an explicit "unattributed" bucket rather than a
|
|
22
|
+
* fabricated seat. The ADR-029 compliance reader renders this field as
|
|
23
|
+
* attribution COVERAGE (per-seat entry counts); per-seat compliance rates
|
|
24
|
+
* wait on a commit-side identity primitive, because commits carry no seat
|
|
25
|
+
* identity to join against (ruled on mmnto-ai/totem#2362).
|
|
26
|
+
*/
|
|
27
|
+
agent_source?: string | null;
|
|
28
|
+
/** A.3.a: explicit session id passed through from `TOTEM_SESSION_ID` if present, else null (never guessed). Reserved forward primitive for the ADR-078 commit-side session join; deliberately inert in the current repo-wide windowing. */
|
|
29
|
+
session_id?: string | null;
|
|
30
|
+
/** A.3.a: trace-correlation id passed through from `TOTEM_CORRELATION_ID` if present, else null (never guessed). Reserved for the A.3.c end-to-end correlation pass; carried now so the trio lands in one producer touch. */
|
|
31
|
+
correlation_id?: string | null;
|
|
10
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* The A.3.a attribution trio stamped onto every `SearchLogEntry` at log time.
|
|
35
|
+
* Every field is `string | null` — a present value or an explicit `null`
|
|
36
|
+
* (Tenet 4: absence is stamped, never guessed).
|
|
37
|
+
*/
|
|
38
|
+
export interface SearchLogAttribution {
|
|
39
|
+
agent_source: string | null;
|
|
40
|
+
session_id: string | null;
|
|
41
|
+
correlation_id: string | null;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Derive the A.3.a attribution trio from the environment (default
|
|
45
|
+
* `process.env`). Pure — no I/O, no side effects — so the producer stamp is
|
|
46
|
+
* testable without touching the filesystem.
|
|
47
|
+
*
|
|
48
|
+
* - `agent_source`: from `TOTEM_SELF_AGENT`, reusing the same read + comma
|
|
49
|
+
* parsing precedent as `resolveSelfAgents` (orchestration-resolver.ts). The
|
|
50
|
+
* MCP server is spawned under a single seat, so the first non-empty
|
|
51
|
+
* comma-separated entry is that seat; a bare value passes through unchanged.
|
|
52
|
+
* - `session_id` / `correlation_id`: straight pass-through from
|
|
53
|
+
* `TOTEM_SESSION_ID` / `TOTEM_CORRELATION_ID`.
|
|
54
|
+
*
|
|
55
|
+
* Any field whose env var is absent or blank is stamped `null`.
|
|
56
|
+
*/
|
|
57
|
+
export declare function deriveSearchLogAttribution(env?: NodeJS.ProcessEnv): SearchLogAttribution;
|
|
11
58
|
export interface SearchStats {
|
|
12
59
|
totalCalls: number;
|
|
13
60
|
avgDuration: number;
|
|
@@ -21,12 +68,19 @@ export declare function setLogDir(totemDir: string): void;
|
|
|
21
68
|
/**
|
|
22
69
|
* Record a search call.
|
|
23
70
|
*
|
|
71
|
+
* - Stamps the A.3.a attribution trio (`agent_source` / `session_id` /
|
|
72
|
+
* `correlation_id`) from the environment at log time — one producer touch
|
|
73
|
+
* shared by every call site. A caller-supplied value (none today) wins over
|
|
74
|
+
* the env derivation.
|
|
24
75
|
* - Always appends to the in-memory array.
|
|
25
76
|
* - Best-effort appends a single JSON line to `{totemDir}/.search-log.jsonl`.
|
|
26
77
|
* File writes are fire-and-forget — failures are silently swallowed because
|
|
27
78
|
* writing to stdout/stderr would corrupt the MCP stdio transport.
|
|
79
|
+
*
|
|
80
|
+
* Returns the stamped entry so the attribution stamp is observable in tests
|
|
81
|
+
* without touching the filesystem.
|
|
28
82
|
*/
|
|
29
|
-
export declare function logSearch(entry: SearchLogEntry):
|
|
83
|
+
export declare function logSearch(entry: SearchLogEntry): SearchLogEntry;
|
|
30
84
|
/**
|
|
31
85
|
* Compute aggregate stats from the in-memory search log.
|
|
32
86
|
*/
|
package/dist/search-log.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-log.d.ts","sourceRoot":"","sources":["../src/search-log.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"search-log.d.ts","sourceRoot":"","sources":["../src/search-log.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;;;;OAgBG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,2OAA2O;IAC3O,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,6NAA6N;IAC7N,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAaD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,oBAAoB,CAgBtB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAQD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAEhD;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAsB/D;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAc5C"}
|
package/dist/search-log.js
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
import * as fs from 'node:fs';
|
|
2
2
|
import * as path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Read one env var, trim it, and normalize empty/whitespace-only to `null`.
|
|
5
|
+
* `null` is the explicit "not present" stamp (Tenet 4) — never a guessed value.
|
|
6
|
+
*/
|
|
7
|
+
function envOrNull(env, key) {
|
|
8
|
+
const raw = env[key];
|
|
9
|
+
if (typeof raw !== 'string')
|
|
10
|
+
return null;
|
|
11
|
+
const trimmed = raw.trim();
|
|
12
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Derive the A.3.a attribution trio from the environment (default
|
|
16
|
+
* `process.env`). Pure — no I/O, no side effects — so the producer stamp is
|
|
17
|
+
* testable without touching the filesystem.
|
|
18
|
+
*
|
|
19
|
+
* - `agent_source`: from `TOTEM_SELF_AGENT`, reusing the same read + comma
|
|
20
|
+
* parsing precedent as `resolveSelfAgents` (orchestration-resolver.ts). The
|
|
21
|
+
* MCP server is spawned under a single seat, so the first non-empty
|
|
22
|
+
* comma-separated entry is that seat; a bare value passes through unchanged.
|
|
23
|
+
* - `session_id` / `correlation_id`: straight pass-through from
|
|
24
|
+
* `TOTEM_SESSION_ID` / `TOTEM_CORRELATION_ID`.
|
|
25
|
+
*
|
|
26
|
+
* Any field whose env var is absent or blank is stamped `null`.
|
|
27
|
+
*/
|
|
28
|
+
export function deriveSearchLogAttribution(env = process.env) {
|
|
29
|
+
const selfAgentRaw = envOrNull(env, 'TOTEM_SELF_AGENT');
|
|
30
|
+
const agent_source = selfAgentRaw !== null
|
|
31
|
+
? // Same comma-split as resolveSelfAgents; take the first non-empty seat.
|
|
32
|
+
(selfAgentRaw
|
|
33
|
+
.split(',')
|
|
34
|
+
.map((s) => s.trim())
|
|
35
|
+
.find((s) => s.length > 0) ?? null)
|
|
36
|
+
: null;
|
|
37
|
+
return {
|
|
38
|
+
agent_source,
|
|
39
|
+
session_id: envOrNull(env, 'TOTEM_SESSION_ID'),
|
|
40
|
+
correlation_id: envOrNull(env, 'TOTEM_CORRELATION_ID'),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
3
43
|
/** In-memory log of search calls for the current server session. */
|
|
4
44
|
const entries = [];
|
|
5
45
|
/** Resolved path to the JSONL log file, set on first logSearch call. */
|
|
@@ -14,17 +54,28 @@ export function setLogDir(totemDir) {
|
|
|
14
54
|
/**
|
|
15
55
|
* Record a search call.
|
|
16
56
|
*
|
|
57
|
+
* - Stamps the A.3.a attribution trio (`agent_source` / `session_id` /
|
|
58
|
+
* `correlation_id`) from the environment at log time — one producer touch
|
|
59
|
+
* shared by every call site. A caller-supplied value (none today) wins over
|
|
60
|
+
* the env derivation.
|
|
17
61
|
* - Always appends to the in-memory array.
|
|
18
62
|
* - Best-effort appends a single JSON line to `{totemDir}/.search-log.jsonl`.
|
|
19
63
|
* File writes are fire-and-forget — failures are silently swallowed because
|
|
20
64
|
* writing to stdout/stderr would corrupt the MCP stdio transport.
|
|
65
|
+
*
|
|
66
|
+
* Returns the stamped entry so the attribution stamp is observable in tests
|
|
67
|
+
* without touching the filesystem.
|
|
21
68
|
*/
|
|
22
69
|
export function logSearch(entry) {
|
|
23
|
-
|
|
70
|
+
// Env stamp LAST: the attribution trio is governance telemetry, so the
|
|
71
|
+
// environment-derived values are authoritative — a caller-supplied (or
|
|
72
|
+
// spread-truthy `undefined`) trio field must never displace the stamp.
|
|
73
|
+
const stamped = { ...entry, ...deriveSearchLogAttribution() };
|
|
74
|
+
entries.push(stamped);
|
|
24
75
|
// Best-effort, non-blocking file append
|
|
25
76
|
if (logFilePath) {
|
|
26
77
|
try {
|
|
27
|
-
const line = JSON.stringify(
|
|
78
|
+
const line = JSON.stringify(stamped) + '\n';
|
|
28
79
|
// fs.promises.appendFile returns a promise — we intentionally do NOT await it.
|
|
29
80
|
// The .catch() swallows any write error silently (no stdout/stderr writes).
|
|
30
81
|
fs.promises.appendFile(logFilePath, line, 'utf-8').catch(() => {
|
|
@@ -35,6 +86,7 @@ export function logSearch(entry) {
|
|
|
35
86
|
// Intentionally empty — synchronous errors from JSON.stringify etc.
|
|
36
87
|
}
|
|
37
88
|
}
|
|
89
|
+
return stamped;
|
|
38
90
|
}
|
|
39
91
|
/**
|
|
40
92
|
* Compute aggregate stats from the in-memory search log.
|
package/dist/search-log.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search-log.js","sourceRoot":"","sources":["../src/search-log.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"search-log.js","sourceRoot":"","sources":["../src/search-log.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-log.test.d.ts","sourceRoot":"","sources":["../src/search-log.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
2
|
+
import { deriveSearchLogAttribution, logSearch } from './search-log.js';
|
|
3
|
+
// ─── deriveSearchLogAttribution (pure — env in, trio out) ───
|
|
4
|
+
describe('deriveSearchLogAttribution', () => {
|
|
5
|
+
it('stamps all three fields from the environment when present', () => {
|
|
6
|
+
const attribution = deriveSearchLogAttribution({
|
|
7
|
+
TOTEM_SELF_AGENT: 'totem-claude',
|
|
8
|
+
TOTEM_SESSION_ID: 'sess-123',
|
|
9
|
+
TOTEM_CORRELATION_ID: 'corr-abc',
|
|
10
|
+
});
|
|
11
|
+
expect(attribution).toEqual({
|
|
12
|
+
agent_source: 'totem-claude',
|
|
13
|
+
session_id: 'sess-123',
|
|
14
|
+
correlation_id: 'corr-abc',
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
it('stamps null for every field when the env is absent (Tenet 4 — never guess)', () => {
|
|
18
|
+
expect(deriveSearchLogAttribution({})).toEqual({
|
|
19
|
+
agent_source: null,
|
|
20
|
+
session_id: null,
|
|
21
|
+
correlation_id: null,
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
it('stamps null per-field independently (partial env)', () => {
|
|
25
|
+
const attribution = deriveSearchLogAttribution({ TOTEM_SESSION_ID: 'only-session' });
|
|
26
|
+
expect(attribution.agent_source).toBeNull();
|
|
27
|
+
expect(attribution.session_id).toBe('only-session');
|
|
28
|
+
expect(attribution.correlation_id).toBeNull();
|
|
29
|
+
});
|
|
30
|
+
it('treats whitespace-only env values as absent → null', () => {
|
|
31
|
+
const attribution = deriveSearchLogAttribution({
|
|
32
|
+
TOTEM_SELF_AGENT: ' ',
|
|
33
|
+
TOTEM_SESSION_ID: '\t',
|
|
34
|
+
TOTEM_CORRELATION_ID: '',
|
|
35
|
+
});
|
|
36
|
+
expect(attribution).toEqual({
|
|
37
|
+
agent_source: null,
|
|
38
|
+
session_id: null,
|
|
39
|
+
correlation_id: null,
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
it('takes the first non-empty seat from a comma-separated TOTEM_SELF_AGENT', () => {
|
|
43
|
+
// Mirrors resolveSelfAgents' comma parsing — the MCP server runs under a
|
|
44
|
+
// single seat, so the first entry is that seat.
|
|
45
|
+
expect(deriveSearchLogAttribution({ TOTEM_SELF_AGENT: ' , totem-gemini , extra' }).agent_source).toBe('totem-gemini');
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
// ─── logSearch stamping (no setLogDir → in-memory only, no fs) ───
|
|
49
|
+
describe('logSearch attribution stamp', () => {
|
|
50
|
+
const ENV_KEYS = ['TOTEM_SELF_AGENT', 'TOTEM_SESSION_ID', 'TOTEM_CORRELATION_ID'];
|
|
51
|
+
const saved = {};
|
|
52
|
+
const baseEntry = {
|
|
53
|
+
timestamp: '2026-07-15T00:00:00.000Z',
|
|
54
|
+
query: 'q',
|
|
55
|
+
resultCount: 0,
|
|
56
|
+
durationMs: 1,
|
|
57
|
+
topScore: null,
|
|
58
|
+
};
|
|
59
|
+
beforeEach(() => {
|
|
60
|
+
for (const k of ENV_KEYS) {
|
|
61
|
+
saved[k] = process.env[k];
|
|
62
|
+
delete process.env[k];
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
afterEach(() => {
|
|
66
|
+
for (const k of ENV_KEYS) {
|
|
67
|
+
if (saved[k] === undefined)
|
|
68
|
+
delete process.env[k];
|
|
69
|
+
else
|
|
70
|
+
process.env[k] = saved[k];
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
it('stamps the trio from process.env onto the returned entry', () => {
|
|
74
|
+
process.env.TOTEM_SELF_AGENT = 'totem-claude';
|
|
75
|
+
process.env.TOTEM_SESSION_ID = 'sess-9';
|
|
76
|
+
process.env.TOTEM_CORRELATION_ID = 'corr-9';
|
|
77
|
+
const stamped = logSearch({ ...baseEntry });
|
|
78
|
+
expect(stamped.agent_source).toBe('totem-claude');
|
|
79
|
+
expect(stamped.session_id).toBe('sess-9');
|
|
80
|
+
expect(stamped.correlation_id).toBe('corr-9');
|
|
81
|
+
});
|
|
82
|
+
it('stamps explicit null on every field when the env is absent', () => {
|
|
83
|
+
const stamped = logSearch({ ...baseEntry });
|
|
84
|
+
expect(stamped.agent_source).toBeNull();
|
|
85
|
+
expect(stamped.session_id).toBeNull();
|
|
86
|
+
expect(stamped.correlation_id).toBeNull();
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
//# sourceMappingURL=search-log.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-log.test.js","sourceRoot":"","sources":["../src/search-log.test.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mmnto/mcp",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "MCP server for Totem — AI
|
|
3
|
+
"version": "1.98.0",
|
|
4
|
+
"description": "MCP server for Totem — a local-first, file-anchored substrate that makes AI-agent work queryable, enforceable, and derivable in your codebase",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": ">=24"
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"dotenv": "^16.4.0",
|
|
23
23
|
"jiti": "^2.4.0",
|
|
24
24
|
"zod": "^3.24.0",
|
|
25
|
-
"@mmnto/totem": "1.
|
|
25
|
+
"@mmnto/totem": "1.98.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^22.0.0",
|