kojee-mcp 0.2.2 → 0.4.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 +140 -7
- package/dist/chunk-36DMIXH7.js +51 -0
- package/dist/chunk-E7TE4QZD.js +33 -0
- package/dist/chunk-VZVGTHGF.js +142 -0
- package/dist/chunk-WHTH6WBP.js +72 -0
- package/dist/{chunk-QKAUM3TR.js → chunk-ZGVUM4AG.js} +409 -24
- package/dist/cli.js +190 -16
- package/dist/event-log-ETWR6PPY.js +112 -0
- package/dist/event-queue-5YVJFR3E.js +43 -0
- package/dist/hook-server-43QS7L7P.js +71 -0
- package/dist/index.d.ts +0 -13
- package/dist/index.js +2 -1
- package/dist/install-WV25CRU2.js +182 -0
- package/dist/paired-config-OAR3O3XY.js +10 -0
- package/dist/session-discovery-WSHLR4OV.js +26 -0
- package/dist/stop-hook-5XU3EQAE.js +76 -0
- package/dist/user-prompt-submit-hook-WSRIJVF4.js +54 -0
- package/package.json +9 -13
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cleanupDiscoveryByKey,
|
|
3
|
+
cleanupSessionDiscovery,
|
|
4
|
+
discoveryFileName,
|
|
5
|
+
discoveryPathForKey,
|
|
6
|
+
readSessionDiscovery,
|
|
7
|
+
readSessionDiscoveryByKey,
|
|
8
|
+
sessionDiscoveryDir,
|
|
9
|
+
sessionDiscoveryPath,
|
|
10
|
+
sweepStaleDiscovery,
|
|
11
|
+
writeDiscoveryByKey,
|
|
12
|
+
writeSessionDiscovery
|
|
13
|
+
} from "./chunk-VZVGTHGF.js";
|
|
14
|
+
export {
|
|
15
|
+
cleanupDiscoveryByKey,
|
|
16
|
+
cleanupSessionDiscovery,
|
|
17
|
+
discoveryFileName,
|
|
18
|
+
discoveryPathForKey,
|
|
19
|
+
readSessionDiscovery,
|
|
20
|
+
readSessionDiscoveryByKey,
|
|
21
|
+
sessionDiscoveryDir,
|
|
22
|
+
sessionDiscoveryPath,
|
|
23
|
+
sweepStaleDiscovery,
|
|
24
|
+
writeDiscoveryByKey,
|
|
25
|
+
writeSessionDiscovery
|
|
26
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readHookStdin
|
|
3
|
+
} from "./chunk-WHTH6WBP.js";
|
|
4
|
+
import {
|
|
5
|
+
deriveDiscoveryKey,
|
|
6
|
+
findClaudeAncestorPid
|
|
7
|
+
} from "./chunk-36DMIXH7.js";
|
|
8
|
+
import {
|
|
9
|
+
readSessionDiscoveryByKey
|
|
10
|
+
} from "./chunk-VZVGTHGF.js";
|
|
11
|
+
|
|
12
|
+
// src/hooks/stop-hook.ts
|
|
13
|
+
import { spawn } from "child_process";
|
|
14
|
+
import fs from "fs";
|
|
15
|
+
async function isMonitorRunning(logPath) {
|
|
16
|
+
return new Promise((resolve) => {
|
|
17
|
+
const child = spawn("pgrep", ["-f", `tail -n \\+1 -F ${logPath}`], { stdio: "ignore" });
|
|
18
|
+
child.on("exit", (code) => resolve(code === 0));
|
|
19
|
+
child.on("error", () => resolve(false));
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
var STOP_POLL_TIMEOUT_MS = Number.parseInt(
|
|
23
|
+
process.env["KOJEE_STOP_HOOK_TIMEOUT_MS"] ?? "30000",
|
|
24
|
+
10
|
|
25
|
+
);
|
|
26
|
+
async function runStopHook() {
|
|
27
|
+
await readHookStdin();
|
|
28
|
+
const ccPid = findClaudeAncestorPid();
|
|
29
|
+
const key = deriveDiscoveryKey(process.env["CLAUDE_PROJECT_DIR"], ccPid);
|
|
30
|
+
const discovery = readSessionDiscoveryByKey(key);
|
|
31
|
+
if (!discovery) {
|
|
32
|
+
process.stdout.write("{}");
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
const logPath = `/tmp/kojee-events-${key}.log`;
|
|
36
|
+
const monitorAlive = await isMonitorRunning(logPath);
|
|
37
|
+
const pollTimeoutMs = monitorAlive ? 0 : STOP_POLL_TIMEOUT_MS;
|
|
38
|
+
let body = null;
|
|
39
|
+
try {
|
|
40
|
+
const res = await fetch(
|
|
41
|
+
`http://127.0.0.1:${discovery.port}/poll?type=stop&timeout_ms=${pollTimeoutMs}`
|
|
42
|
+
);
|
|
43
|
+
if (res.ok) {
|
|
44
|
+
body = await res.json();
|
|
45
|
+
}
|
|
46
|
+
} catch {
|
|
47
|
+
}
|
|
48
|
+
if (body && body.count > 0) {
|
|
49
|
+
const reason = formatEvents(body.events);
|
|
50
|
+
process.stdout.write(JSON.stringify({ decision: "block", reason }));
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (!monitorAlive && fs.existsSync(logPath)) {
|
|
54
|
+
process.stdout.write(JSON.stringify({
|
|
55
|
+
decision: "block",
|
|
56
|
+
reason: `Before stopping, spawn the kojee Tandem event watcher: Monitor(command="tail -n +1 -F ${logPath}", persistent=true, description="kojee Tandem events"). This is needed so Tandem peer messages can wake you from idle. After spawning it once at the start of the session, you don't need to spawn it again.`
|
|
57
|
+
}));
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
process.stdout.write("{}");
|
|
61
|
+
}
|
|
62
|
+
function formatEvents(events) {
|
|
63
|
+
const header = `[${events.length} unread Tandem ${events.length === 1 ? "event" : "events"}]
|
|
64
|
+
|
|
65
|
+
`;
|
|
66
|
+
const bodies = events.map((evt) => {
|
|
67
|
+
const attrs = Object.entries(evt.meta).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
68
|
+
return `<channel source="kojee-mcp" ${attrs}>
|
|
69
|
+
${evt.content}
|
|
70
|
+
</channel>`;
|
|
71
|
+
});
|
|
72
|
+
return header + bodies.join("\n\n");
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
runStopHook
|
|
76
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {
|
|
2
|
+
readHookStdin
|
|
3
|
+
} from "./chunk-WHTH6WBP.js";
|
|
4
|
+
import {
|
|
5
|
+
deriveDiscoveryKey,
|
|
6
|
+
findClaudeAncestorPid
|
|
7
|
+
} from "./chunk-36DMIXH7.js";
|
|
8
|
+
import {
|
|
9
|
+
readSessionDiscoveryByKey
|
|
10
|
+
} from "./chunk-VZVGTHGF.js";
|
|
11
|
+
|
|
12
|
+
// src/hooks/user-prompt-submit-hook.ts
|
|
13
|
+
async function runUserPromptSubmitHook() {
|
|
14
|
+
await readHookStdin();
|
|
15
|
+
const ccPid = findClaudeAncestorPid();
|
|
16
|
+
const key = deriveDiscoveryKey(process.env["CLAUDE_PROJECT_DIR"], ccPid);
|
|
17
|
+
const discovery = readSessionDiscoveryByKey(key);
|
|
18
|
+
if (!discovery) {
|
|
19
|
+
process.stdout.write("{}");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
let body;
|
|
23
|
+
try {
|
|
24
|
+
const res = await fetch(`http://127.0.0.1:${discovery.port}/poll?type=user-prompt-submit&timeout_ms=0`);
|
|
25
|
+
if (!res.ok) {
|
|
26
|
+
process.stdout.write("{}");
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
body = await res.json();
|
|
30
|
+
} catch {
|
|
31
|
+
process.stdout.write("{}");
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (body.count === 0) {
|
|
35
|
+
process.stdout.write("{}");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
process.stdout.write(JSON.stringify({ additionalContext: formatEvents(body.events) }));
|
|
39
|
+
}
|
|
40
|
+
function formatEvents(events) {
|
|
41
|
+
const header = `[${events.length} unread Tandem ${events.length === 1 ? "event" : "events"}]
|
|
42
|
+
|
|
43
|
+
`;
|
|
44
|
+
const bodies = events.map((evt) => {
|
|
45
|
+
const attrs = Object.entries(evt.meta).map(([k, v]) => `${k}="${v}"`).join(" ");
|
|
46
|
+
return `<channel source="kojee-mcp" ${attrs}>
|
|
47
|
+
${evt.content}
|
|
48
|
+
</channel>`;
|
|
49
|
+
});
|
|
50
|
+
return header + bodies.join("\n\n");
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
runUserPromptSubmitHook
|
|
54
|
+
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kojee-mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Local MCP proxy for Kojee — handles DPoP auth, tool discovery, and governance transparently",
|
|
3
|
+
"version": "0.4.0",
|
|
5
4
|
"type": "module",
|
|
6
5
|
"main": "dist/index.js",
|
|
7
6
|
"bin": {
|
|
@@ -10,29 +9,26 @@
|
|
|
10
9
|
"scripts": {
|
|
11
10
|
"build": "tsup src/cli.ts src/index.ts --format esm --dts --clean",
|
|
12
11
|
"dev": "tsup src/cli.ts --format esm --watch",
|
|
13
|
-
"typecheck": "tsc --noEmit"
|
|
12
|
+
"typecheck": "tsc --noEmit",
|
|
13
|
+
"test": "vitest run",
|
|
14
|
+
"test:watch": "vitest",
|
|
15
|
+
"dev:stub": "tsx dev-tools/stub-broker.ts"
|
|
14
16
|
},
|
|
15
17
|
"files": [
|
|
16
18
|
"dist"
|
|
17
19
|
],
|
|
18
|
-
"keywords": [
|
|
19
|
-
"mcp",
|
|
20
|
-
"kojee",
|
|
21
|
-
"ai-governance",
|
|
22
|
-
"agent-tools",
|
|
23
|
-
"dpop"
|
|
24
|
-
],
|
|
25
|
-
"license": "MIT",
|
|
26
20
|
"dependencies": {
|
|
27
21
|
"@modelcontextprotocol/sdk": "latest",
|
|
28
22
|
"jose": "^5.0.0",
|
|
29
23
|
"commander": "^12.0.0",
|
|
30
|
-
"zod": "^3.22.0"
|
|
24
|
+
"zod": "^3.22.0",
|
|
25
|
+
"ulidx": "^2.3.0"
|
|
31
26
|
},
|
|
32
27
|
"devDependencies": {
|
|
33
28
|
"typescript": "^5.4.0",
|
|
34
29
|
"@types/node": "^20.0.0",
|
|
35
30
|
"tsup": "^8.0.0",
|
|
36
|
-
"vitest": "^1.0.0"
|
|
31
|
+
"vitest": "^1.0.0",
|
|
32
|
+
"tsx": "^4.7.0"
|
|
37
33
|
}
|
|
38
34
|
}
|