ctxjev-mcp 0.7.0 → 0.7.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.
- package/README.md +17 -11
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/schemas.d.ts +12 -0
- package/dist/schemas.js +7 -0
- package/dist/schemas.js.map +1 -1
- package/dist/server.js +8 -7
- package/dist/server.js.map +1 -1
- package/dist/tools.d.ts +5 -2
- package/dist/tools.js +6 -6
- package/dist/tools.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
# ctxjev-mcp
|
|
4
4
|
|
|
5
|
-
**
|
|
5
|
+
**Context scoring (Jev, or offline) as MCP tools for Claude Code, Codex, and any other MCP host.**
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/ctxjev-mcp)
|
|
8
8
|
[](LICENSE)
|
|
@@ -27,17 +27,20 @@ config shape differs.
|
|
|
27
27
|
|
|
28
28
|
## Setup
|
|
29
29
|
|
|
30
|
-
Every example below pins the version (`ctxjev-mcp@0.7.
|
|
30
|
+
Every example below pins the version (`ctxjev-mcp@0.7.1`, the latest on npm), so your host runs the
|
|
31
31
|
release you chose rather than whatever npm has at the time; change the pin to upgrade.
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
waitlist)
|
|
35
|
-
|
|
33
|
+
Both tools score with Jev by default (`scorer: "jev"`), which needs a key from
|
|
34
|
+
[console.typesafe.ai/settings/keys](https://console.typesafe.ai/settings/keys) (no waitlist). Without
|
|
35
|
+
one the server still starts and lists its two tools; a call with `scorer: "local"` (keyword overlap
|
|
36
|
+
with the goal) or `scorer: "recency"` (newest first, the same as plain truncation) works offline and
|
|
37
|
+
sends nothing, and a call that uses Jev returns an error saying `TYPESAFE_API_KEY` isn't set. For
|
|
38
|
+
offline use only, leave `--env TYPESAFE_API_KEY=...` (or the `env` block) out of the examples below.
|
|
36
39
|
|
|
37
40
|
**Claude Code:**
|
|
38
41
|
|
|
39
42
|
```bash
|
|
40
|
-
claude mcp add ctxjev --env TYPESAFE_API_KEY=... -- npx ctxjev-mcp@0.7.
|
|
43
|
+
claude mcp add ctxjev --env TYPESAFE_API_KEY=... -- npx ctxjev-mcp@0.7.1
|
|
41
44
|
```
|
|
42
45
|
|
|
43
46
|
The ctxjev repo also carries a project-level `.mcp.json`, which runs the server from
|
|
@@ -51,11 +54,11 @@ a local stdio server doesn't use, so it's safe to ignore (or `claude mcp remove
|
|
|
51
54
|
**Codex CLI** (verified against `codex-cli` v0.155.1):
|
|
52
55
|
|
|
53
56
|
```bash
|
|
54
|
-
codex mcp add ctxjev --env TYPESAFE_API_KEY=... -- npx ctxjev-mcp@0.7.
|
|
57
|
+
codex mcp add ctxjev --env TYPESAFE_API_KEY=... -- npx ctxjev-mcp@0.7.1
|
|
55
58
|
```
|
|
56
59
|
|
|
57
60
|
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.7.
|
|
61
|
+
(`.agents/plugins/marketplace.json`), which registers the same `npx ctxjev-mcp@0.7.1` command:
|
|
59
62
|
|
|
60
63
|
```bash
|
|
61
64
|
codex plugin marketplace add x96x64/ctxjev
|
|
@@ -71,7 +74,7 @@ codex plugin add ctxjev@ctxjev-plugins
|
|
|
71
74
|
"ctxjev": {
|
|
72
75
|
"type": "stdio",
|
|
73
76
|
"command": "npx",
|
|
74
|
-
"args": ["ctxjev-mcp@0.7.
|
|
77
|
+
"args": ["ctxjev-mcp@0.7.1"],
|
|
75
78
|
"env": { "TYPESAFE_API_KEY": "..." }
|
|
76
79
|
}
|
|
77
80
|
}
|
|
@@ -80,14 +83,17 @@ codex plugin add ctxjev@ctxjev-plugins
|
|
|
80
83
|
|
|
81
84
|
## Tools
|
|
82
85
|
|
|
83
|
-
- **`score_relevance`** takes `{ goal, entries, recencyWeight? }` and returns a
|
|
86
|
+
- **`score_relevance`** takes `{ goal, entries, scorer?, recencyWeight? }` and returns a
|
|
84
87
|
relevance/recency/combined score per entry plus Jev token usage, with no decision made.
|
|
88
|
+
`scorer` is `"jev"` (the default, as before 0.7.1; needs `TYPESAFE_API_KEY`), `"local"`, or
|
|
89
|
+
`"recency"`; the last two run offline and report zero usage.
|
|
85
90
|
- **`prune_history`** takes the same input plus `{ dropBelow?, summarizeBelow? }` and returns a
|
|
86
91
|
decision (`keep`/`drop`/`summarize`) per entry, a savings report, and Jev token usage.
|
|
87
92
|
|
|
88
93
|
`entries` is `{ id, role: 'user'|'assistant'|'tool', toolName?, content, timestamp }[]`.
|
|
89
94
|
|
|
90
|
-
|
|
95
|
+
With `scorer: "jev"`, entry content and the goal are sent to TypeSafe AI's Jev API (with `"local"`
|
|
96
|
+
or `"recency"`, nothing is sent anywhere). Common secret formats (API keys,
|
|
91
97
|
tokens, private-key blocks, `NAME=value` credentials) are masked to `[REDACTED]` first, on a
|
|
92
98
|
best-effort basis.
|
|
93
99
|
|
package/dist/index.js
CHANGED
|
@@ -3,9 +3,10 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
3
3
|
import { createServer } from './server.js';
|
|
4
4
|
async function main() {
|
|
5
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
|
|
6
|
+
// key, the tools are still listed, scorer 'local' and 'recency' work, and a call that uses Jev
|
|
7
|
+
// returns an error saying what's missing.
|
|
7
8
|
if (!process.env.TYPESAFE_API_KEY) {
|
|
8
|
-
console.error('ctxjev-mcp: TYPESAFE_API_KEY is not set, so
|
|
9
|
+
console.error('ctxjev-mcp: TYPESAFE_API_KEY is not set, so only scorer "local" and "recency" work; a call that uses Jev (the default) returns an error until it is — get one at console.typesafe.ai/settings/keys');
|
|
9
10
|
}
|
|
10
11
|
const server = createServer();
|
|
11
12
|
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,8FAA8F;IAC9F,
|
|
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,+FAA+F;IAC/F,0CAA0C;IAC1C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,oMAAoM,CAAC,CAAA;IACrN,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.d.ts
CHANGED
|
@@ -11,7 +11,14 @@ export declare const entrySchema: z.ZodObject<{
|
|
|
11
11
|
timestamp: z.ZodNumber;
|
|
12
12
|
sourceTokens: z.ZodOptional<z.ZodNumber>;
|
|
13
13
|
}, z.core.$strip>;
|
|
14
|
+
export declare const SCORERS: readonly ["jev", "local", "recency"];
|
|
15
|
+
export type McpScorer = (typeof SCORERS)[number];
|
|
14
16
|
export declare const scoreRelevanceInput: {
|
|
17
|
+
scorer: z.ZodDefault<z.ZodEnum<{
|
|
18
|
+
jev: "jev";
|
|
19
|
+
local: "local";
|
|
20
|
+
recency: "recency";
|
|
21
|
+
}>>;
|
|
15
22
|
goal: z.ZodString;
|
|
16
23
|
entries: z.ZodArray<z.ZodObject<{
|
|
17
24
|
id: z.ZodString;
|
|
@@ -30,6 +37,11 @@ export declare const scoreRelevanceInput: {
|
|
|
30
37
|
export declare const pruneHistoryInput: {
|
|
31
38
|
dropBelow: z.ZodOptional<z.ZodNumber>;
|
|
32
39
|
summarizeBelow: z.ZodOptional<z.ZodNumber>;
|
|
40
|
+
scorer: z.ZodDefault<z.ZodEnum<{
|
|
41
|
+
jev: "jev";
|
|
42
|
+
local: "local";
|
|
43
|
+
recency: "recency";
|
|
44
|
+
}>>;
|
|
33
45
|
goal: z.ZodString;
|
|
34
46
|
entries: z.ZodArray<z.ZodObject<{
|
|
35
47
|
id: z.ZodString;
|
package/dist/schemas.js
CHANGED
|
@@ -28,7 +28,14 @@ export const entrySchema = z.object({
|
|
|
28
28
|
.optional()
|
|
29
29
|
.describe('Tokens in the full payload `content` was excerpted from, so the savings report counts what removing it actually saves.'),
|
|
30
30
|
});
|
|
31
|
+
// 'jev' stays the default so a call that doesn't name a scorer behaves as in 0.7.0; 'local'
|
|
32
|
+
// (keyword overlap) and 'recency' (plain truncation) run offline, with no key and nothing sent.
|
|
33
|
+
export const SCORERS = ['jev', 'local', 'recency'];
|
|
31
34
|
export const scoreRelevanceInput = {
|
|
35
|
+
scorer: z
|
|
36
|
+
.enum(SCORERS)
|
|
37
|
+
.default('jev')
|
|
38
|
+
.describe("How to score: 'jev' (TypeSafe AI's Jev; needs TYPESAFE_API_KEY in the server's env, and sends masked excerpts), 'local' (keyword overlap with the goal, offline), or 'recency' (newest first, the same as plain truncation, offline)."),
|
|
32
39
|
goal: z.string().min(1).max(MAX_GOAL_LENGTH).describe('The current task/goal to judge each entry\'s relevance against.'),
|
|
33
40
|
entries: z.array(entrySchema).max(MAX_ENTRIES).describe('The agent history entries to score.'),
|
|
34
41
|
recencyWeight: z
|
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;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,yEAAyE,cAAc,CAAC,SAAS,GAAG,CAAC;IAC7J,cAAc,EAAE,CAAC;SACd,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,CAAC,CAAC;SACN,QAAQ,EAAE;SACV,QAAQ,CAAC,kHAAkH,cAAc,CAAC,cAAc,GAAG,CAAC;CAChK,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"}
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -13,28 +13,29 @@ const MISSING_KEY = {
|
|
|
13
13
|
content: [
|
|
14
14
|
{
|
|
15
15
|
type: 'text',
|
|
16
|
-
text: 'TYPESAFE_API_KEY is not set in the environment this MCP server runs in.
|
|
16
|
+
text: 'TYPESAFE_API_KEY is not set in the environment this MCP server runs in. scorer "jev" (the default) needs it: get one at console.typesafe.ai/settings/keys and add it to the server\'s env in your MCP host\'s config, or pass scorer "local" (keyword overlap) or "recency" (plain truncation), which run offline.',
|
|
17
17
|
},
|
|
18
18
|
],
|
|
19
19
|
};
|
|
20
|
-
// Checked per call, not at startup, so a server started without a key still connects and lists its
|
|
21
|
-
|
|
20
|
+
// Checked per call, not at startup, so a server started without a key still connects and lists its
|
|
21
|
+
// tools; and only for scorer 'jev', since 'local' and 'recency' need no key.
|
|
22
|
+
const needsMissingKey = (scorer) => scorer === 'jev' && !process.env.TYPESAFE_API_KEY;
|
|
22
23
|
export function createServer() {
|
|
23
24
|
const server = new McpServer({ name: 'ctxjev', version: VERSION });
|
|
24
25
|
server.registerTool('score_relevance', {
|
|
25
|
-
description: "Score a batch of AI agent history entries for relevance to a goal,
|
|
26
|
+
description: "Score a batch of AI agent history entries for relevance to a goal: with Jev by default (needs TYPESAFE_API_KEY), or offline with scorer 'local' or 'recency'. Doesn't decide what to do about it — see prune_history for that.",
|
|
26
27
|
inputSchema: scoreRelevanceInput,
|
|
27
28
|
}, async (args) => {
|
|
28
|
-
if (
|
|
29
|
+
if (needsMissingKey(args.scorer))
|
|
29
30
|
return MISSING_KEY;
|
|
30
31
|
const result = await scoreRelevanceTool(args);
|
|
31
32
|
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
32
33
|
});
|
|
33
34
|
server.registerTool('prune_history', {
|
|
34
|
-
description:
|
|
35
|
+
description: "Score a batch of AI agent history entries against a goal and decide what to keep, drop, or summarize: with Jev by default (needs TYPESAFE_API_KEY), or offline with scorer 'local' or 'recency'.",
|
|
35
36
|
inputSchema: pruneHistoryInput,
|
|
36
37
|
}, async (args) => {
|
|
37
|
-
if (
|
|
38
|
+
if (needsMissingKey(args.scorer))
|
|
38
39
|
return MISSING_KEY;
|
|
39
40
|
const result = await pruneHistoryTool(args);
|
|
40
41
|
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
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,WAAW,GAAG;IAClB,OAAO,EAAE,IAAI;IACb,OAAO,EAAE;QACP;YACE,IAAI,EAAE,MAAe;YACrB,IAAI,EAAE,
|
|
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,oTAAoT;SAC3T;KACF;CACF,CAAA;AAED,mGAAmG;AACnG,6EAA6E;AAC7E,MAAM,eAAe,GAAG,CAAC,MAAc,EAAE,EAAE,CAAC,MAAM,KAAK,KAAK,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAA;AAE7F,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,gOAAgO;QAClO,WAAW,EAAE,mBAAmB;KACjC,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,OAAO,WAAW,CAAA;QACpD,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,kMAAkM;QAC/M,WAAW,EAAE,iBAAiB;KAC/B,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,IAAI,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;YAAE,OAAO,WAAW,CAAA;QACpD,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,5 @@
|
|
|
1
1
|
import { type Entry, type JevClient, type ScoreCache } from 'ctxjev-core';
|
|
2
|
+
import { type McpScorer } from './schemas.js';
|
|
2
3
|
/**
|
|
3
4
|
* Plain functions wrapping ctxjev-core, kept independent of the MCP framework so they're
|
|
4
5
|
* testable without spinning up a server. src/server.ts adapts these into MCP tool handlers.
|
|
@@ -13,11 +14,13 @@ export type ToolDeps = {
|
|
|
13
14
|
cache?: ScoreCache;
|
|
14
15
|
};
|
|
15
16
|
export type ScoreRelevanceArgs = {
|
|
17
|
+
/** Defaults to 'jev', as in 0.7.0; 'local' and 'recency' run offline. */
|
|
18
|
+
scorer?: McpScorer;
|
|
16
19
|
goal: string;
|
|
17
20
|
entries: Entry[];
|
|
18
21
|
recencyWeight?: number;
|
|
19
22
|
};
|
|
20
|
-
export declare function scoreRelevanceTool({ goal, entries, recencyWeight }: ScoreRelevanceArgs, { jevClient, cache }?: ToolDeps): Promise<{
|
|
23
|
+
export declare function scoreRelevanceTool({ scorer, goal, entries, recencyWeight }: ScoreRelevanceArgs, { jevClient, cache }?: ToolDeps): Promise<{
|
|
21
24
|
scored: import("ctxjev-core").ScoredEntry[];
|
|
22
25
|
usage: import("ctxjev-core").JevUsage;
|
|
23
26
|
}>;
|
|
@@ -25,7 +28,7 @@ export type PruneHistoryArgs = ScoreRelevanceArgs & {
|
|
|
25
28
|
dropBelow?: number;
|
|
26
29
|
summarizeBelow?: number;
|
|
27
30
|
};
|
|
28
|
-
export declare function pruneHistoryTool({ goal, entries, recencyWeight, dropBelow, summarizeBelow }: PruneHistoryArgs, { jevClient, cache }?: ToolDeps): Promise<{
|
|
31
|
+
export declare function pruneHistoryTool({ scorer, goal, entries, recencyWeight, dropBelow, summarizeBelow }: PruneHistoryArgs, { jevClient, cache }?: ToolDeps): Promise<{
|
|
29
32
|
decisions: import("ctxjev-core").PruneDecision[];
|
|
30
33
|
savings: import("ctxjev-core").SavingsReport;
|
|
31
34
|
usage: import("ctxjev-core").JevUsage;
|
package/dist/tools.js
CHANGED
|
@@ -30,15 +30,15 @@ export function createBoundedScoreCache(limit = SCORE_CACHE_LIMIT) {
|
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
const scoreCache = createBoundedScoreCache();
|
|
33
|
-
export async function scoreRelevanceTool({ goal, entries, recencyWeight }, { jevClient, cache = scoreCache } = {}) {
|
|
33
|
+
export async function scoreRelevanceTool({ scorer = 'jev', goal, entries, recencyWeight }, { jevClient, cache = scoreCache } = {}) {
|
|
34
34
|
const { usage, onUsage } = createUsageAccumulator();
|
|
35
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.
|
|
37
|
-
//
|
|
38
|
-
const scored = await scoreEntries(entries, goal, recencyWeight ?? DEFAULT_POLICY.recencyWeight, { onUsage, cache, jevClient, scorer
|
|
36
|
+
// Jev on task success. These tools default to 'jev', as they did before `scorer` existed, so a
|
|
37
|
+
// host's existing calls keep their meaning; 'local' and 'recency' are offline.
|
|
38
|
+
const scored = await scoreEntries(entries, goal, recencyWeight ?? DEFAULT_POLICY.recencyWeight, { onUsage, cache, jevClient, scorer });
|
|
39
39
|
return { scored, usage };
|
|
40
40
|
}
|
|
41
|
-
export async function pruneHistoryTool({ goal, entries, recencyWeight, dropBelow, summarizeBelow }, { jevClient, cache = scoreCache } = {}) {
|
|
41
|
+
export async function pruneHistoryTool({ scorer = 'jev', goal, entries, recencyWeight, dropBelow, summarizeBelow }, { jevClient, cache = scoreCache } = {}) {
|
|
42
42
|
const policy = {
|
|
43
43
|
dropBelow: dropBelow ?? DEFAULT_POLICY.dropBelow,
|
|
44
44
|
summarizeBelow: summarizeBelow ?? DEFAULT_POLICY.summarizeBelow,
|
|
@@ -46,7 +46,7 @@ export async function pruneHistoryTool({ goal, entries, recencyWeight, dropBelow
|
|
|
46
46
|
};
|
|
47
47
|
validatePolicyOrdering(policy.dropBelow, policy.summarizeBelow);
|
|
48
48
|
const { usage, onUsage } = createUsageAccumulator();
|
|
49
|
-
const decisions = await pruneContext(entries, goal, policy, { onUsage, cache, jevClient, scorer
|
|
49
|
+
const decisions = await pruneContext(entries, goal, policy, { onUsage, cache, jevClient, scorer });
|
|
50
50
|
const savings = summarizeSavings(entries, decisions);
|
|
51
51
|
return { decisions, savings, usage };
|
|
52
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,EAAmE,MAAM,aAAa,CAAA;AACnL,OAAO,EAAE,sBAAsB,
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ctxjev-mcp",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
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,7 +40,7 @@
|
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
42
42
|
"zod": "^4.6.5",
|
|
43
|
-
"ctxjev-core": "0.7.
|
|
43
|
+
"ctxjev-core": "0.7.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "^22",
|