ctxjev-mcp 0.4.0 → 0.6.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 +24 -4
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/schemas.js +6 -2
- package/dist/schemas.js.map +1 -1
- package/dist/server.js +15 -0
- package/dist/server.js.map +1 -1
- package/dist/tools.d.ts +9 -1
- package/dist/tools.js +30 -9
- package/dist/tools.js.map +1 -1
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -27,19 +27,39 @@ config shape differs.
|
|
|
27
27
|
|
|
28
28
|
## Setup
|
|
29
29
|
|
|
30
|
+
Every example below pins the version (`ctxjev-mcp@0.6.0`, the latest on npm), so your host runs the
|
|
31
|
+
release you chose rather than whatever npm has at the time; change the pin to upgrade.
|
|
32
|
+
|
|
30
33
|
Get a key at [console.typesafe.ai/settings/keys](https://console.typesafe.ai/settings/keys) (no
|
|
31
|
-
waitlist) first.
|
|
34
|
+
waitlist) first. Without one the server still starts and lists its two tools, but every call
|
|
35
|
+
returns an error saying `TYPESAFE_API_KEY` isn't set.
|
|
32
36
|
|
|
33
37
|
**Claude Code:**
|
|
34
38
|
|
|
35
39
|
```bash
|
|
36
|
-
claude mcp add ctxjev --env TYPESAFE_API_KEY=... -- npx ctxjev-mcp
|
|
40
|
+
claude mcp add ctxjev --env TYPESAFE_API_KEY=... -- npx ctxjev-mcp@0.6.0
|
|
37
41
|
```
|
|
38
42
|
|
|
43
|
+
The ctxjev repo also carries a project-level `.mcp.json`, which runs the server from
|
|
44
|
+
`packages/mcp-server/dist/` and so needs `pnpm install && pnpm build` in the clone first. That scope
|
|
45
|
+
also needs an approval step
|
|
46
|
+
that didn't surface in the UI when tested (Claude Code v2.1.278): `claude mcp list` silently omits
|
|
47
|
+
the server. `claude mcp add` at local scope, as above, works immediately. If both exist, `claude
|
|
48
|
+
mcp list` warns that the server is defined in two scopes; that concerns OAuth token storage, which
|
|
49
|
+
a local stdio server doesn't use, so it's safe to ignore (or `claude mcp remove ctxjev -s project`).
|
|
50
|
+
|
|
39
51
|
**Codex CLI** (verified against `codex-cli` v0.155.1):
|
|
40
52
|
|
|
41
53
|
```bash
|
|
42
|
-
codex mcp add ctxjev --env TYPESAFE_API_KEY=... -- npx ctxjev-mcp
|
|
54
|
+
codex mcp add ctxjev --env TYPESAFE_API_KEY=... -- npx ctxjev-mcp@0.6.0
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Or through the [Agent Plugins](https://agent-plugins.org) bundle in the ctxjev repo
|
|
58
|
+
(`.agents/plugins/marketplace.json`), which registers the same `npx ctxjev-mcp@0.6.0` command:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
codex plugin marketplace add x96x64/ctxjev
|
|
62
|
+
codex plugin add ctxjev@ctxjev-plugins
|
|
43
63
|
```
|
|
44
64
|
|
|
45
65
|
**GitHub Copilot** (VS Code, agent mode) uses `.vscode/mcp.json` (note the top-level key is
|
|
@@ -51,7 +71,7 @@ codex mcp add ctxjev --env TYPESAFE_API_KEY=... -- npx ctxjev-mcp
|
|
|
51
71
|
"ctxjev": {
|
|
52
72
|
"type": "stdio",
|
|
53
73
|
"command": "npx",
|
|
54
|
-
"args": ["ctxjev-mcp"],
|
|
74
|
+
"args": ["ctxjev-mcp@0.6.0"],
|
|
55
75
|
"env": { "TYPESAFE_API_KEY": "..." }
|
|
56
76
|
}
|
|
57
77
|
}
|
package/dist/index.js
CHANGED
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
3
|
import { createServer } from './server.js';
|
|
4
4
|
async function main() {
|
|
5
|
+
// Start either way: exiting here showed up in the host only as "connection closed". Without a
|
|
6
|
+
// key, the tools are still listed, and each call returns an error saying what's missing.
|
|
5
7
|
if (!process.env.TYPESAFE_API_KEY) {
|
|
6
|
-
console.error('ctxjev-mcp: TYPESAFE_API_KEY is not set — get one at console.typesafe.ai/settings/keys');
|
|
7
|
-
process.exit(1);
|
|
8
|
+
console.error('ctxjev-mcp: TYPESAFE_API_KEY is not set, so every tool call will return an error until it is — get one at console.typesafe.ai/settings/keys');
|
|
8
9
|
}
|
|
9
10
|
const server = createServer();
|
|
10
11
|
await server.connect(new StdioServerTransport());
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,KAAK,UAAU,IAAI;IACjB,8FAA8F;IAC9F,yFAAyF;IACzF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,6IAA6I,CAAC,CAAA;IAC9J,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,EAAE,CAAA;IAC7B,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAA;AAClD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;IAC/D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
|
package/dist/schemas.js
CHANGED
|
@@ -8,10 +8,14 @@ const MAX_CONTENT_LENGTH = 4000;
|
|
|
8
8
|
// goal gets embedded into state.goal on every chunked Jev request (jevClient.ts) — an oversized
|
|
9
9
|
// goal is billed once per chunk, not once per call, and deserves the same cap as content.
|
|
10
10
|
const MAX_GOAL_LENGTH = 2000;
|
|
11
|
+
// Ids and tool names are labels, not content: a Claude Code tool_use id or record uuid is under 60
|
|
12
|
+
// characters, and MCP tool names under 64. Generous caps, so every string the server accepts is bounded.
|
|
13
|
+
const MAX_ID_LENGTH = 256;
|
|
14
|
+
const MAX_TOOL_NAME_LENGTH = 256;
|
|
11
15
|
export const entrySchema = z.object({
|
|
12
|
-
id: z.string().min(1),
|
|
16
|
+
id: z.string().min(1).max(MAX_ID_LENGTH),
|
|
13
17
|
role: z.enum(['user', 'assistant', 'tool']),
|
|
14
|
-
toolName: z.string().optional(),
|
|
18
|
+
toolName: z.string().max(MAX_TOOL_NAME_LENGTH).optional(),
|
|
15
19
|
content: z.string().max(MAX_CONTENT_LENGTH),
|
|
16
20
|
// .finite() — bare z.number() only rejects NaN, not Infinity/-Infinity. core's computeRecency
|
|
17
21
|
// takes min/max across the whole batch, so one infinite timestamp turns every entry's recency
|
package/dist/schemas.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAEnE,+FAA+F;AAC/F,0FAA0F;AAC1F,8CAA8C;AAC9C,MAAM,WAAW,GAAG,GAAG,CAAA;AACvB,MAAM,kBAAkB,GAAG,IAAI,CAAA;AAC/B,gGAAgG;AAChG,0FAA0F;AAC1F,MAAM,eAAe,GAAG,IAAI,CAAA;
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAA;AAEnE,+FAA+F;AAC/F,0FAA0F;AAC1F,8CAA8C;AAC9C,MAAM,WAAW,GAAG,GAAG,CAAA;AACvB,MAAM,kBAAkB,GAAG,IAAI,CAAA;AAC/B,gGAAgG;AAChG,0FAA0F;AAC1F,MAAM,eAAe,GAAG,IAAI,CAAA;AAC5B,mGAAmG;AACnG,yGAAyG;AACzG,MAAM,aAAa,GAAG,GAAG,CAAA;AACzB,MAAM,oBAAoB,GAAG,GAAG,CAAA;AAEhC,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;IAC3C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,QAAQ,EAAE;IACzD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,kBAAkB,CAAC;IAC3C,8FAA8F;IAC9F,8FAA8F;IAC9F,qEAAqE;IACrE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE;IAC9B,YAAY,EAAE,CAAC;SACZ,MAAM,EAAE;SACR,GAAG,EAAE;SACL,WAAW,EAAE;SACb,QAAQ,EAAE;SACV,QAAQ,CAAC,wHAAwH,CAAC;CACtI,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,iEAAiE,CAAC;IACxH,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,qCAAqC,CAAC;IAC9F,aAAa,EAAE,CAAC;SACb,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,EAAE;SACV,QAAQ,CAAC,sGAAsG,cAAc,CAAC,aAAa,GAAG,CAAC;CACnJ,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,GAAG,mBAAmB;IACtB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qEAAqE,cAAc,CAAC,SAAS,GAAG,CAAC;IACzJ,cAAc,EAAE,CAAC;SACd,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,EAAE;SACV,QAAQ,CAAC,kGAAkG,cAAc,CAAC,cAAc,GAAG,CAAC;CAChJ,CAAA;AAED;;;6DAG6D;AAC7D,MAAM,UAAU,sBAAsB,CAAC,SAAiB,EAAE,cAAsB;IAC9E,IAAI,CAAC,qBAAqB,CAAC,SAAS,EAAE,cAAc,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,cAAc,SAAS,8CAA8C,cAAc,GAAG,CAAC,CAAA;IACzG,CAAC;AACH,CAAC"}
|
package/dist/server.js
CHANGED
|
@@ -8,12 +8,25 @@ import { pruneHistoryTool, scoreRelevanceTool } from './tools.js';
|
|
|
8
8
|
// reported to MCP clients can't silently go stale after the next release the way a literal
|
|
9
9
|
// string would (ctxjev-cli's --version had exactly this bug — see CHANGELOG 0.1.2).
|
|
10
10
|
const VERSION = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '../package.json'), 'utf8')).version;
|
|
11
|
+
const MISSING_KEY = {
|
|
12
|
+
isError: true,
|
|
13
|
+
content: [
|
|
14
|
+
{
|
|
15
|
+
type: 'text',
|
|
16
|
+
text: 'TYPESAFE_API_KEY is not set in the environment this MCP server runs in. Both tools score with Jev and need it: get one at console.typesafe.ai/settings/keys and add it to the server\'s env in your MCP host\'s config.',
|
|
17
|
+
},
|
|
18
|
+
],
|
|
19
|
+
};
|
|
20
|
+
// Checked per call, not at startup, so a server started without a key still connects and lists its tools.
|
|
21
|
+
const hasKey = () => Boolean(process.env.TYPESAFE_API_KEY);
|
|
11
22
|
export function createServer() {
|
|
12
23
|
const server = new McpServer({ name: 'ctxjev', version: VERSION });
|
|
13
24
|
server.registerTool('score_relevance', {
|
|
14
25
|
description: "Score a batch of AI agent history entries for relevance to a goal, using Jev. Doesn't decide what to do about it — see prune_history for that.",
|
|
15
26
|
inputSchema: scoreRelevanceInput,
|
|
16
27
|
}, async (args) => {
|
|
28
|
+
if (!hasKey())
|
|
29
|
+
return MISSING_KEY;
|
|
17
30
|
const result = await scoreRelevanceTool(args);
|
|
18
31
|
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
19
32
|
});
|
|
@@ -21,6 +34,8 @@ export function createServer() {
|
|
|
21
34
|
description: 'Score a batch of AI agent history entries against a goal and decide what to keep, drop, or summarize.',
|
|
22
35
|
inputSchema: pruneHistoryInput,
|
|
23
36
|
}, async (args) => {
|
|
37
|
+
if (!hasKey())
|
|
38
|
+
return MISSING_KEY;
|
|
24
39
|
const result = await pruneHistoryTool(args);
|
|
25
40
|
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
26
41
|
});
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AACrE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAEjE,6FAA6F;AAC7F,2FAA2F;AAC3F,oFAAoF;AACpF,MAAM,OAAO,GAAW,IAAI,CAAC,KAAK,CAChC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,CACvF,CAAC,OAAO,CAAA;AAET,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;IAElE,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,WAAW,EACT,gJAAgJ;QAClJ,WAAW,EAAE,mBAAmB;KACjC,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAA;QAC7C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;IAC/E,CAAC,CACF,CAAA;IAED,MAAM,CAAC,YAAY,CACjB,eAAe,EACf;QACE,WAAW,EAAE,uGAAuG;QACpH,WAAW,EAAE,iBAAiB;KAC/B,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAA;QAC3C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;IAC/E,CAAC,CACF,CAAA;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACnE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAA;AACrE,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAEjE,6FAA6F;AAC7F,2FAA2F;AAC3F,oFAAoF;AACpF,MAAM,OAAO,GAAW,IAAI,CAAC,KAAK,CAChC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,CACvF,CAAC,OAAO,CAAA;AAET,MAAM,WAAW,GAAG;IAClB,OAAO,EAAE,IAAI;IACb,OAAO,EAAE;QACP;YACE,IAAI,EAAE,MAAe;YACrB,IAAI,EAAE,yNAAyN;SAChO;KACF;CACF,CAAA;AAED,0GAA0G;AAC1G,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAA;AAE1D,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAA;IAElE,MAAM,CAAC,YAAY,CACjB,iBAAiB,EACjB;QACE,WAAW,EACT,gJAAgJ;QAClJ,WAAW,EAAE,mBAAmB;KACjC,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,WAAW,CAAA;QACjC,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAA;QAC7C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;IAC/E,CAAC,CACF,CAAA;IAED,MAAM,CAAC,YAAY,CACjB,eAAe,EACf;QACE,WAAW,EAAE,uGAAuG;QACpH,WAAW,EAAE,iBAAiB;KAC/B,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,CAAC,MAAM,EAAE;YAAE,OAAO,WAAW,CAAA;QACjC,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAA;QAC3C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAA;IAC/E,CAAC,CACF,CAAA;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/dist/tools.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
import { type Entry } from 'ctxjev-core';
|
|
1
|
+
import { type Entry, type ScoreCache } from 'ctxjev-core';
|
|
2
|
+
/**
|
|
3
|
+
* Plain functions wrapping ctxjev-core, kept independent of the MCP framework so they're
|
|
4
|
+
* testable without spinning up a server. src/server.ts adapts these into MCP tool handlers.
|
|
5
|
+
*/
|
|
6
|
+
export declare const SCORE_CACHE_LIMIT = 5000;
|
|
7
|
+
export declare function createBoundedScoreCache(limit?: number): ScoreCache & {
|
|
8
|
+
readonly size: number;
|
|
9
|
+
};
|
|
2
10
|
export type ScoreRelevanceArgs = {
|
|
3
11
|
goal: string;
|
|
4
12
|
entries: Entry[];
|
package/dist/tools.js
CHANGED
|
@@ -4,17 +4,38 @@ import { validatePolicyOrdering } from './schemas.js';
|
|
|
4
4
|
* Plain functions wrapping ctxjev-core, kept independent of the MCP framework so they're
|
|
5
5
|
* testable without spinning up a server. src/server.ts adapts these into MCP tool handlers.
|
|
6
6
|
*/
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const scoreCache = (() => {
|
|
7
|
+
// Shared across calls, so re-scoring overlapping history doesn't re-pay Jev for it. Bounded,
|
|
8
|
+
// since a server can run for as long as its host does: the least recently used key goes first.
|
|
9
|
+
export const SCORE_CACHE_LIMIT = 5_000;
|
|
10
|
+
export function createBoundedScoreCache(limit = SCORE_CACHE_LIMIT) {
|
|
12
11
|
const store = new Map();
|
|
13
|
-
return {
|
|
14
|
-
|
|
12
|
+
return {
|
|
13
|
+
get(key) {
|
|
14
|
+
const value = store.get(key);
|
|
15
|
+
if (value !== undefined) {
|
|
16
|
+
store.delete(key);
|
|
17
|
+
store.set(key, value);
|
|
18
|
+
}
|
|
19
|
+
return value;
|
|
20
|
+
},
|
|
21
|
+
set(key, value) {
|
|
22
|
+
store.delete(key);
|
|
23
|
+
store.set(key, value);
|
|
24
|
+
if (store.size > limit)
|
|
25
|
+
store.delete(store.keys().next().value);
|
|
26
|
+
},
|
|
27
|
+
get size() {
|
|
28
|
+
return store.size;
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
const scoreCache = createBoundedScoreCache();
|
|
15
33
|
export async function scoreRelevanceTool({ goal, entries, recencyWeight }) {
|
|
16
34
|
const { usage, onUsage } = createUsageAccumulator();
|
|
17
|
-
|
|
35
|
+
// core's own default scorer is 'recency' as of 0.6.0 (see prune.ts), since the holdout eval tied
|
|
36
|
+
// Jev on task success. This tool's whole purpose is exposing Jev scoring, so it keeps asking for
|
|
37
|
+
// it explicitly rather than silently inheriting that default.
|
|
38
|
+
const scored = await scoreEntries(entries, goal, recencyWeight ?? DEFAULT_POLICY.recencyWeight, { onUsage, cache: scoreCache, scorer: 'jev' });
|
|
18
39
|
return { scored, usage };
|
|
19
40
|
}
|
|
20
41
|
export async function pruneHistoryTool({ goal, entries, recencyWeight, dropBelow, summarizeBelow }) {
|
|
@@ -25,7 +46,7 @@ export async function pruneHistoryTool({ goal, entries, recencyWeight, dropBelow
|
|
|
25
46
|
};
|
|
26
47
|
validatePolicyOrdering(policy.dropBelow, policy.summarizeBelow);
|
|
27
48
|
const { usage, onUsage } = createUsageAccumulator();
|
|
28
|
-
const decisions = await pruneContext(entries, goal, policy, { onUsage, cache: scoreCache });
|
|
49
|
+
const decisions = await pruneContext(entries, goal, policy, { onUsage, cache: scoreCache, scorer: 'jev' });
|
|
29
50
|
const savings = summarizeSavings(entries, decisions);
|
|
30
51
|
return { decisions, savings, usage };
|
|
31
52
|
}
|
package/dist/tools.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAmD,MAAM,aAAa,CAAA;AACnK,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAErD;;;GAGG;AAEH,
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAmD,MAAM,aAAa,CAAA;AACnK,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAA;AAErD;;;GAGG;AAEH,6FAA6F;AAC7F,+FAA+F;AAC/F,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,CAAA;AAEtC,MAAM,UAAU,uBAAuB,CAAC,KAAK,GAAG,iBAAiB;IAC/D,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAA;IACvC,OAAO;QACL,GAAG,CAAC,GAAG;YACL,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YAC5B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;gBACjB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YACvB,CAAC;YACD,OAAO,KAAK,CAAA;QACd,CAAC;QACD,GAAG,CAAC,GAAG,EAAE,KAAK;YACZ,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YACjB,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YACrB,IAAI,KAAK,CAAC,IAAI,GAAG,KAAK;gBAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAM,CAAC,CAAA;QAClE,CAAC;QACD,IAAI,IAAI;YACN,OAAO,KAAK,CAAC,IAAI,CAAA;QACnB,CAAC;KACF,CAAA;AACH,CAAC;AAED,MAAM,UAAU,GAAG,uBAAuB,EAAE,CAAA;AAQ5C,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAsB;IAC3F,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,sBAAsB,EAAE,CAAA;IACnD,iGAAiG;IACjG,iGAAiG;IACjG,8DAA8D;IAC9D,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,aAAa,IAAI,cAAc,CAAC,aAAa,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;IAC9I,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA;AAC1B,CAAC;AAOD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,cAAc,EAAoB;IAClH,MAAM,MAAM,GAAkB;QAC5B,SAAS,EAAE,SAAS,IAAI,cAAc,CAAC,SAAS;QAChD,cAAc,EAAE,cAAc,IAAI,cAAc,CAAC,cAAc;QAC/D,aAAa,EAAE,aAAa,IAAI,cAAc,CAAC,aAAa;KAC7D,CAAA;IACD,sBAAsB,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,cAAc,CAAC,CAAA;IAE/D,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,sBAAsB,EAAE,CAAA;IACnD,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;IAC1G,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAA;IACpD,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,CAAA;AACtC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ctxjev-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "MCP server exposing ctxjev's Jev-based context scoring/pruning as tools for any MCP-capable agent host.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -40,15 +40,16 @@
|
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
42
42
|
"zod": "^4.6.5",
|
|
43
|
-
"ctxjev-core": "0.
|
|
43
|
+
"ctxjev-core": "0.6.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "^22",
|
|
47
|
-
"typescript": "^
|
|
48
|
-
"vitest": "^
|
|
47
|
+
"typescript": "^6.0.3",
|
|
48
|
+
"vitest": "^4.1.11"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "tsc -b",
|
|
52
|
-
"test": "vitest run"
|
|
52
|
+
"test": "vitest run",
|
|
53
|
+
"typecheck": "tsc -p tsconfig.test.json"
|
|
53
54
|
}
|
|
54
55
|
}
|