@adtl/gateway 0.3.0 → 0.3.2
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 +59 -1
- package/dist/audit.d.ts +4 -2
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js.map +1 -1
- package/dist/cli.js +80 -15
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +49 -44
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +10 -3
- package/dist/config.js.map +1 -1
- package/dist/gateway.d.ts +1 -1
- package/dist/gateway.js +1 -1
- package/dist/hooks/claudeCode.d.ts +43 -0
- package/dist/hooks/claudeCode.d.ts.map +1 -0
- package/dist/hooks/claudeCode.js +148 -0
- package/dist/hooks/claudeCode.js.map +1 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/preset.d.ts +16 -0
- package/dist/hooks/preset.d.ts.map +1 -0
- package/dist/hooks/preset.js +32 -0
- package/dist/hooks/preset.js.map +1 -0
- package/dist/hooks/run.d.ts +9 -0
- package/dist/hooks/run.d.ts.map +1 -0
- package/dist/hooks/run.js +44 -0
- package/dist/hooks/run.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/init/fromMcpJson.d.ts +41 -0
- package/dist/init/fromMcpJson.d.ts.map +1 -0
- package/dist/init/fromMcpJson.js +141 -0
- package/dist/init/fromMcpJson.js.map +1 -0
- package/dist/init/index.d.ts +2 -0
- package/dist/init/index.d.ts.map +1 -1
- package/dist/init/index.js +2 -0
- package/dist/init/index.js.map +1 -1
- package/dist/init/run.d.ts +13 -0
- package/dist/init/run.d.ts.map +1 -1
- package/dist/init/run.js +83 -11
- package/dist/init/run.js.map +1 -1
- package/dist/startup.d.ts +12 -1
- package/dist/startup.d.ts.map +1 -1
- package/dist/startup.js +27 -3
- package/dist/startup.js.map +1 -1
- package/package.json +4 -4
- package/src/audit.ts +4 -2
- package/src/cli.ts +70 -15
- package/src/config.ts +9 -3
- package/src/gateway.ts +1 -1
- package/src/hooks/claudeCode.ts +194 -0
- package/src/hooks/index.ts +3 -0
- package/src/hooks/preset.ts +47 -0
- package/src/hooks/run.ts +49 -0
- package/src/index.ts +1 -0
- package/src/init/fromMcpJson.ts +165 -0
- package/src/init/index.ts +2 -0
- package/src/init/run.ts +91 -12
- package/src/startup.ts +28 -4
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/gateway.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { type CallToolResult, type GetPromptResult, type Prompt, type ReadResour
|
|
|
4
4
|
import type { ApprovalBroker } from "./approvals.js";
|
|
5
5
|
import type { AuditSink } from "./audit.js";
|
|
6
6
|
import type { InterceptorInvoker } from "./invoker.js";
|
|
7
|
-
export declare const GATEWAY_VERSION = "0.3.
|
|
7
|
+
export declare const GATEWAY_VERSION = "0.3.2";
|
|
8
8
|
/** `_meta` key on gateway-generated error results describing why a call was stopped. */
|
|
9
9
|
export declare const GATEWAY_DECISION_KEY = "adtl/gateway";
|
|
10
10
|
export interface GatewayLogger {
|
package/dist/gateway.js
CHANGED
|
@@ -27,7 +27,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
27
27
|
import { UriTemplate } from "@modelcontextprotocol/sdk/shared/uriTemplate.js";
|
|
28
28
|
import { CallToolRequestSchema, ErrorCode, GetPromptRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ListToolsRequestSchema, McpError, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
29
29
|
import { TOOL_SEPARATOR } from "./config.js";
|
|
30
|
-
export const GATEWAY_VERSION = "0.3.
|
|
30
|
+
export const GATEWAY_VERSION = "0.3.2";
|
|
31
31
|
/** `_meta` key on gateway-generated error results describing why a call was stopped. */
|
|
32
32
|
export const GATEWAY_DECISION_KEY = "adtl/gateway";
|
|
33
33
|
const stderrLogger = {
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type AdtlConfig, type SessionStore } from "@adtl/labels";
|
|
2
|
+
import type { AuditSink } from "../audit.js";
|
|
3
|
+
export interface HookInput {
|
|
4
|
+
session_id?: string;
|
|
5
|
+
hook_event_name?: string;
|
|
6
|
+
tool_name?: string;
|
|
7
|
+
tool_input?: unknown;
|
|
8
|
+
tool_response?: unknown;
|
|
9
|
+
/** PostToolUseFailure: the error the tool returned. */
|
|
10
|
+
error?: unknown;
|
|
11
|
+
cwd?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface HookOptions {
|
|
14
|
+
config: AdtlConfig;
|
|
15
|
+
sessions: SessionStore;
|
|
16
|
+
/** Name of the gateway in Claude Code's MCP config; its tools are skipped. Default `adtl`. */
|
|
17
|
+
gatewayServer?: string;
|
|
18
|
+
/** `audit`: decide and log, but never deny or ask. */
|
|
19
|
+
mode?: "active" | "audit";
|
|
20
|
+
audit?: AuditSink;
|
|
21
|
+
/** Files the agent must not change: the ADTL config and the session directory. */
|
|
22
|
+
protect?: {
|
|
23
|
+
configPath?: string;
|
|
24
|
+
sessionsDir?: string;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/** What the hook process prints and exits with. */
|
|
28
|
+
export interface HookOutcome {
|
|
29
|
+
stdout?: Record<string, unknown>;
|
|
30
|
+
stderr?: string;
|
|
31
|
+
exitCode: number;
|
|
32
|
+
}
|
|
33
|
+
/** `config` with labels for Claude Code's built-in tools; rules under `servers.claude-code` win. */
|
|
34
|
+
export declare function withClaudeCodePreset(config: AdtlConfig): AdtlConfig;
|
|
35
|
+
/** Which ADTL server and tool a Claude Code tool name is, or undefined for the gateway's own tools. */
|
|
36
|
+
export declare function routeTool(toolName: string, gatewayServer?: string): {
|
|
37
|
+
server: string;
|
|
38
|
+
tool: string;
|
|
39
|
+
} | undefined;
|
|
40
|
+
export declare function handleHook(input: HookInput, opts: HookOptions): HookOutcome;
|
|
41
|
+
/** Fail closed: exit 2 stops a PreToolUse call and shows the reason to Claude. */
|
|
42
|
+
export declare function failure(event: string | undefined, why: string): HookOutcome;
|
|
43
|
+
//# sourceMappingURL=claudeCode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudeCode.d.ts","sourceRoot":"","sources":["../../src/hooks/claudeCode.ts"],"names":[],"mappings":"AAsBA,OAAO,EAKL,KAAK,UAAU,EAGf,KAAK,YAAY,EAClB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAc,SAAS,EAAE,MAAM,aAAa,CAAC;AAGzD,MAAM,WAAW,SAAS;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,uDAAuD;IACvD,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,YAAY,CAAC;IACvB,8FAA8F;IAC9F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,sDAAsD;IACtD,IAAI,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,kFAAkF;IAClF,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACzD;AAED,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,oGAAoG;AACpG,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CAanE;AAED,uGAAuG;AACvG,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,aAAa,SAAS,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAKhH;AAuCD,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,GAAG,WAAW,CA2D3E;AAED,kFAAkF;AAClF,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAG3E"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code hooks adapter: puts Claude Code's built-in tools (WebFetch, Read,
|
|
3
|
+
* Bash, …) and MCP servers that don't go through the gateway under the same
|
|
4
|
+
* labels and policy as gateway calls.
|
|
5
|
+
*
|
|
6
|
+
* PreToolUse runs the policy against the session label:
|
|
7
|
+
* block → deny, ask → Claude Code's permission prompt,
|
|
8
|
+
* allow → no answer, so Claude Code's own permissions apply
|
|
9
|
+
* PostToolUse labels the tool's output and adds it to the session label
|
|
10
|
+
* PostToolUseFailure same: a failed tool's error output still reaches the model
|
|
11
|
+
*
|
|
12
|
+
* Built-in tools are labeled as the server `claude-code` (see preset.ts); MCP
|
|
13
|
+
* tools `mcp__<server>__<tool>` as `<server>`. Tools of the gateway's own MCP
|
|
14
|
+
* server (`mcp__adtl__*` by default) are skipped: the gateway checks those.
|
|
15
|
+
*
|
|
16
|
+
* Hooks and gateway share one session label through a FileSessionStore keyed
|
|
17
|
+
* by Claude Code's session id, which the gateway reads from
|
|
18
|
+
* `CLAUDE_CODE_SESSION_ID`.
|
|
19
|
+
*
|
|
20
|
+
* Errors fail closed: a PreToolUse hook that can't decide denies the call.
|
|
21
|
+
*/
|
|
22
|
+
import { isAbsolute, relative, resolve, sep } from "node:path";
|
|
23
|
+
import { callHash, evaluatePolicy, labelResult, toolEgress, } from "@adtl/labels";
|
|
24
|
+
import { CLAUDE_CODE_PRESET, CLAUDE_CODE_SERVER } from "./preset.js";
|
|
25
|
+
const NOTHING = { exitCode: 0 };
|
|
26
|
+
/** `config` with labels for Claude Code's built-in tools; rules under `servers.claude-code` win. */
|
|
27
|
+
export function withClaudeCodePreset(config) {
|
|
28
|
+
const own = config.servers[CLAUDE_CODE_SERVER];
|
|
29
|
+
return {
|
|
30
|
+
...config,
|
|
31
|
+
servers: {
|
|
32
|
+
...config.servers,
|
|
33
|
+
[CLAUDE_CODE_SERVER]: {
|
|
34
|
+
acceptServerClaims: own?.acceptServerClaims ?? false,
|
|
35
|
+
...(own?.defaults ? { defaults: own.defaults } : {}),
|
|
36
|
+
tools: { ...CLAUDE_CODE_PRESET, ...own?.tools },
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/** Which ADTL server and tool a Claude Code tool name is, or undefined for the gateway's own tools. */
|
|
42
|
+
export function routeTool(toolName, gatewayServer = "adtl") {
|
|
43
|
+
const m = /^mcp__(.+?)__(.+)$/.exec(toolName);
|
|
44
|
+
if (!m)
|
|
45
|
+
return { server: CLAUDE_CODE_SERVER, tool: toolName };
|
|
46
|
+
if (m[1] === gatewayServer)
|
|
47
|
+
return undefined;
|
|
48
|
+
return { server: m[1], tool: m[2] };
|
|
49
|
+
}
|
|
50
|
+
function isRecord(v) {
|
|
51
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
52
|
+
}
|
|
53
|
+
function inside(path, dir) {
|
|
54
|
+
const r = relative(dir, path);
|
|
55
|
+
return r === "" || (!r.startsWith(`..${sep}`) && r !== ".." && !isAbsolute(r));
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A best-effort guard against the agent clearing its own taint by editing the
|
|
59
|
+
* config or deleting session files. Not a sandbox: Bash can always find a way.
|
|
60
|
+
*/
|
|
61
|
+
function protectedTarget(input, route, protect) {
|
|
62
|
+
if (!protect || route.server !== CLAUDE_CODE_SERVER)
|
|
63
|
+
return undefined;
|
|
64
|
+
const args = isRecord(input.tool_input) ? input.tool_input : {};
|
|
65
|
+
const cwd = input.cwd ?? process.cwd();
|
|
66
|
+
const path = typeof args.file_path === "string" ? args.file_path : typeof args.notebook_path === "string" ? args.notebook_path : undefined;
|
|
67
|
+
if (path !== undefined && ["Write", "Edit", "MultiEdit", "NotebookEdit"].includes(route.tool)) {
|
|
68
|
+
const abs = resolve(cwd, path);
|
|
69
|
+
if (protect.configPath && abs === resolve(protect.configPath)) {
|
|
70
|
+
return { decision: "block", reason: "The agent may not change the ADTL config; edit it yourself" };
|
|
71
|
+
}
|
|
72
|
+
if (protect.sessionsDir && inside(abs, resolve(protect.sessionsDir))) {
|
|
73
|
+
return { decision: "block", reason: "The agent may not change ADTL session labels" };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
const command = typeof args.command === "string" ? args.command : undefined;
|
|
77
|
+
if (command !== undefined && ["Bash", "Monitor"].includes(route.tool)) {
|
|
78
|
+
const marks = [".adtl/sessions", protect.sessionsDir].filter((m) => !!m);
|
|
79
|
+
if (marks.some((m) => command.includes(m))) {
|
|
80
|
+
return { decision: "ask", reason: "This command touches ADTL session labels" };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
export function handleHook(input, opts) {
|
|
86
|
+
const event = input.hook_event_name;
|
|
87
|
+
if (event !== "PreToolUse" && event !== "PostToolUse" && event !== "PostToolUseFailure")
|
|
88
|
+
return NOTHING;
|
|
89
|
+
if (typeof input.tool_name !== "string" || typeof input.session_id !== "string" || input.session_id === "") {
|
|
90
|
+
return failure(event, "hook input has no tool_name or session_id");
|
|
91
|
+
}
|
|
92
|
+
const route = routeTool(input.tool_name, opts.gatewayServer);
|
|
93
|
+
if (!route)
|
|
94
|
+
return NOTHING;
|
|
95
|
+
const config = withClaudeCodePreset(opts.config);
|
|
96
|
+
const ts = new Date().toISOString();
|
|
97
|
+
const base = { ts, sessionId: input.session_id, event: "tools/call", ...route, via: "claude-code-hook" };
|
|
98
|
+
if (event !== "PreToolUse") {
|
|
99
|
+
const label = labelResult({ ...route, result: input.tool_response ?? input.error ?? null }, config);
|
|
100
|
+
const sessionLabel = opts.sessions.observe(input.session_id, label);
|
|
101
|
+
opts.audit?.write({ ...base, outcome: "forwarded", label, sessionLabel, durationMs: 0 });
|
|
102
|
+
return NOTHING;
|
|
103
|
+
}
|
|
104
|
+
const hash = callHash(route.server, route.tool, input.tool_input ?? {});
|
|
105
|
+
const session = opts.sessions.get(input.session_id);
|
|
106
|
+
const guard = protectedTarget(input, route, opts.protect);
|
|
107
|
+
const policy = evaluatePolicy(config.policy, {
|
|
108
|
+
session,
|
|
109
|
+
...route,
|
|
110
|
+
egress: toolEgress(config, route.server, route.tool),
|
|
111
|
+
});
|
|
112
|
+
const d = guard && (guard.decision === "block" || policy.decision === "allow")
|
|
113
|
+
? { decision: guard.decision, reason: guard.reason, matched: ["adtl-self-protection"] }
|
|
114
|
+
: policy;
|
|
115
|
+
if (d.decision === "allow")
|
|
116
|
+
return NOTHING;
|
|
117
|
+
const audit = opts.mode === "audit";
|
|
118
|
+
const entry = {
|
|
119
|
+
...base,
|
|
120
|
+
outcome: audit ? "forwarded" : d.decision === "ask" ? "asked" : "blocked",
|
|
121
|
+
decision: d.decision,
|
|
122
|
+
...(audit ? { mode: "audit" } : {}),
|
|
123
|
+
reason: d.reason,
|
|
124
|
+
matched: d.matched,
|
|
125
|
+
callHash: hash,
|
|
126
|
+
sessionLabel: session,
|
|
127
|
+
durationMs: 0,
|
|
128
|
+
};
|
|
129
|
+
opts.audit?.write(entry);
|
|
130
|
+
if (audit)
|
|
131
|
+
return NOTHING;
|
|
132
|
+
return {
|
|
133
|
+
exitCode: 0,
|
|
134
|
+
stdout: {
|
|
135
|
+
hookSpecificOutput: {
|
|
136
|
+
hookEventName: "PreToolUse",
|
|
137
|
+
permissionDecision: d.decision === "ask" ? "ask" : "deny",
|
|
138
|
+
permissionDecisionReason: d.decision === "ask" ? `ADTL: ${d.reason}. Approve only if you expected this call.` : `ADTL blocked this call: ${d.reason}.`,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
/** Fail closed: exit 2 stops a PreToolUse call and shows the reason to Claude. */
|
|
144
|
+
export function failure(event, why) {
|
|
145
|
+
const stopped = event === "PreToolUse" ? " The call was stopped." : "";
|
|
146
|
+
return { exitCode: 2, stderr: `ADTL hook error: ${why}.${stopped}` };
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=claudeCode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudeCode.js","sourceRoot":"","sources":["../../src/hooks/claudeCode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EACL,QAAQ,EACR,cAAc,EACd,WAAW,EACX,UAAU,GAKX,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAgCrE,MAAM,OAAO,GAAgB,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;AAE7C,oGAAoG;AACpG,MAAM,UAAU,oBAAoB,CAAC,MAAkB;IACrD,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC/C,OAAO;QACL,GAAG,MAAM;QACT,OAAO,EAAE;YACP,GAAG,MAAM,CAAC,OAAO;YACjB,CAAC,kBAAkB,CAAC,EAAE;gBACpB,kBAAkB,EAAE,GAAG,EAAE,kBAAkB,IAAI,KAAK;gBACpD,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBACpD,KAAK,EAAE,EAAE,GAAG,kBAAkB,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE;aAChD;SACF;KACF,CAAC;AACJ,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,aAAa,GAAG,MAAM;IAChE,MAAM,CAAC,GAAG,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC9C,IAAI,CAAC,CAAC;QAAE,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IAC9D,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,aAAa;QAAE,OAAO,SAAS,CAAC;IAC7C,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,CAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAE,EAAE,CAAC;AACxC,CAAC;AAED,SAAS,QAAQ,CAAC,CAAU;IAC1B,OAAO,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,SAAS,MAAM,CAAC,IAAY,EAAE,GAAW;IACvC,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC9B,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AACjF,CAAC;AAED;;;GAGG;AACH,SAAS,eAAe,CAAC,KAAgB,EAAE,KAAuC,EAAE,OAA+B;IACjH,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,KAAK,kBAAkB;QAAE,OAAO,SAAS,CAAC;IACtE,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;IAChE,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACvC,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3I,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9F,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC/B,IAAI,OAAO,CAAC,UAAU,IAAI,GAAG,KAAK,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9D,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,4DAA4D,EAAE,CAAC;QACrG,CAAC;QACD,IAAI,OAAO,CAAC,WAAW,IAAI,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;YACrE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,8CAA8C,EAAE,CAAC;QACvF,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAAG,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5E,IAAI,OAAO,KAAK,SAAS,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACtE,MAAM,KAAK,GAAG,CAAC,gBAAgB,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACtF,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,0CAA0C,EAAE,CAAC;QACjF,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAgB,EAAE,IAAiB;IAC5D,MAAM,KAAK,GAAG,KAAK,CAAC,eAAe,CAAC;IACpC,IAAI,KAAK,KAAK,YAAY,IAAI,KAAK,KAAK,aAAa,IAAI,KAAK,KAAK,oBAAoB;QAAE,OAAO,OAAO,CAAC;IACxG,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,IAAI,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,KAAK,EAAE,EAAE,CAAC;QAC3G,OAAO,OAAO,CAAC,KAAK,EAAE,2CAA2C,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;IAC7D,IAAI,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC;IAC3B,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjD,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACpC,MAAM,IAAI,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,UAAU,EAAE,KAAK,EAAE,YAAqB,EAAE,GAAG,KAAK,EAAE,GAAG,EAAE,kBAA2B,EAAE,CAAC;IAE3H,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,GAAG,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,aAAa,IAAI,KAAK,CAAC,KAAK,IAAI,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;QACpG,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACpE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;QACzF,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAmB,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE;QAC3D,OAAO;QACP,GAAG,KAAK;QACR,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC;KACrD,CAAC,CAAC;IACH,MAAM,CAAC,GACL,KAAK,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,OAAO,IAAI,MAAM,CAAC,QAAQ,KAAK,OAAO,CAAC;QAClE,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,sBAAsB,CAAC,EAAE;QACvF,CAAC,CAAC,MAAM,CAAC;IACb,IAAI,CAAC,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,OAAO,CAAC;IAE3C,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,KAAK,OAAO,CAAC;IACpC,MAAM,KAAK,GAAe;QACxB,GAAG,IAAI;QACP,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;QACzE,QAAQ,EAAE,CAAC,CAAC,QAAQ;QACpB,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5C,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,OAAO;QACrB,UAAU,EAAE,CAAC;KACd,CAAC;IACF,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IACzB,IAAI,KAAK;QAAE,OAAO,OAAO,CAAC;IAE1B,OAAO;QACL,QAAQ,EAAE,CAAC;QACX,MAAM,EAAE;YACN,kBAAkB,EAAE;gBAClB,aAAa,EAAE,YAAY;gBAC3B,kBAAkB,EAAE,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM;gBACzD,wBAAwB,EACtB,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,2CAA2C,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,MAAM,GAAG;aAC/H;SACF;KACF,CAAC;AACJ,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,OAAO,CAAC,KAAyB,EAAE,GAAW;IAC5D,MAAM,OAAO,GAAG,KAAK,KAAK,YAAY,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,EAAE,oBAAoB,GAAG,IAAI,OAAO,EAAE,EAAE,CAAC;AACvE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Labels for Claude Code's built-in tools, used when `servers.claude-code`
|
|
3
|
+
* doesn't override them. Built-in tools are labeled as the server `claude-code`.
|
|
4
|
+
*
|
|
5
|
+
* - Local reads (Read, Grep, Glob) are trusted but private: your own files.
|
|
6
|
+
* Files written from untrusted content aren't tracked until the v0.4 ledger.
|
|
7
|
+
* - Web tools bring in untrusted content, and their URL or query can carry
|
|
8
|
+
* data out, so their egress is external.
|
|
9
|
+
* - Bash can do anything: its output has unknown integrity, and its egress is
|
|
10
|
+
* unknown.
|
|
11
|
+
* - Edits and bookkeeping tools return nothing worth labeling.
|
|
12
|
+
*/
|
|
13
|
+
import type { ToolRule } from "@adtl/labels";
|
|
14
|
+
export declare const CLAUDE_CODE_SERVER = "claude-code";
|
|
15
|
+
export declare const CLAUDE_CODE_PRESET: Record<string, ToolRule>;
|
|
16
|
+
//# sourceMappingURL=preset.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preset.d.ts","sourceRoot":"","sources":["../../src/hooks/preset.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAOhD,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAyBvD,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export const CLAUDE_CODE_SERVER = "claude-code";
|
|
2
|
+
const localRead = { integrity: "trusted", confidentiality: "private", egress: "none" };
|
|
3
|
+
const localWrite = { integrity: "trusted", confidentiality: "public", egress: "none" };
|
|
4
|
+
const web = { integrity: "untrusted", confidentiality: "public", egress: "external" };
|
|
5
|
+
const shell = { integrity: "unknown", confidentiality: "private", egress: "unknown" };
|
|
6
|
+
export const CLAUDE_CODE_PRESET = {
|
|
7
|
+
Read: localRead,
|
|
8
|
+
Grep: localRead,
|
|
9
|
+
Glob: localRead,
|
|
10
|
+
LS: localRead,
|
|
11
|
+
NotebookRead: localRead,
|
|
12
|
+
Write: localWrite,
|
|
13
|
+
Edit: localWrite,
|
|
14
|
+
MultiEdit: localWrite,
|
|
15
|
+
NotebookEdit: localWrite,
|
|
16
|
+
TodoWrite: localWrite,
|
|
17
|
+
AskUserQuestion: localWrite,
|
|
18
|
+
Skill: localWrite,
|
|
19
|
+
ToolSearch: localWrite,
|
|
20
|
+
EnterPlanMode: localWrite,
|
|
21
|
+
ExitPlanMode: localWrite,
|
|
22
|
+
WebFetch: web,
|
|
23
|
+
WebSearch: web,
|
|
24
|
+
Bash: shell,
|
|
25
|
+
BashOutput: shell,
|
|
26
|
+
KillShell: localWrite,
|
|
27
|
+
Monitor: shell,
|
|
28
|
+
// A sub-agent's own tool calls go through these hooks too; its answer mixes what it saw.
|
|
29
|
+
Agent: { integrity: "unknown", confidentiality: "private", egress: "none" },
|
|
30
|
+
Task: { integrity: "unknown", confidentiality: "private", egress: "none" },
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=preset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preset.js","sourceRoot":"","sources":["../../src/hooks/preset.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,MAAM,kBAAkB,GAAG,aAAa,CAAC;AAEhD,MAAM,SAAS,GAAa,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACjG,MAAM,UAAU,GAAa,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACjG,MAAM,GAAG,GAAa,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChG,MAAM,KAAK,GAAa,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;AAEhG,MAAM,CAAC,MAAM,kBAAkB,GAA6B;IAC1D,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;IACf,IAAI,EAAE,SAAS;IACf,EAAE,EAAE,SAAS;IACb,YAAY,EAAE,SAAS;IACvB,KAAK,EAAE,UAAU;IACjB,IAAI,EAAE,UAAU;IAChB,SAAS,EAAE,UAAU;IACrB,YAAY,EAAE,UAAU;IACxB,SAAS,EAAE,UAAU;IACrB,eAAe,EAAE,UAAU;IAC3B,KAAK,EAAE,UAAU;IACjB,UAAU,EAAE,UAAU;IACtB,aAAa,EAAE,UAAU;IACzB,YAAY,EAAE,UAAU;IACxB,QAAQ,EAAE,GAAG;IACb,SAAS,EAAE,GAAG;IACd,IAAI,EAAE,KAAK;IACX,UAAU,EAAE,KAAK;IACjB,SAAS,EAAE,UAAU;IACrB,OAAO,EAAE,KAAK;IACd,yFAAyF;IACzF,KAAK,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE;IAC3E,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE;CAC3E,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type HookOutcome } from "./claudeCode.js";
|
|
2
|
+
export interface RunHookOptions {
|
|
3
|
+
configPath: string;
|
|
4
|
+
stdin: string;
|
|
5
|
+
gatewayServer?: string;
|
|
6
|
+
env?: NodeJS.ProcessEnv;
|
|
7
|
+
}
|
|
8
|
+
export declare function runHook(opts: RunHookOptions): Promise<HookOutcome>;
|
|
9
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/hooks/run.ts"],"names":[],"mappings":"AAcA,OAAO,EAAuC,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAExF,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,wBAAsB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAyBxE"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `adtl-gateway hook --config adtl.yaml`: the command Claude Code runs for
|
|
3
|
+
* PreToolUse, PostToolUse and PostToolUseFailure. Reads the hook event from
|
|
4
|
+
* stdin and answers on stdout (JSON) or stderr (with exit code 2).
|
|
5
|
+
*
|
|
6
|
+
* The config needs no `gateway:` section; if there is one, its `audit` log and
|
|
7
|
+
* `mode` are used, so hook and gateway write to the same audit log.
|
|
8
|
+
*/
|
|
9
|
+
import { readFile } from "node:fs/promises";
|
|
10
|
+
import { dirname, resolve } from "node:path";
|
|
11
|
+
import { FileSessionStore, defaultSessionsDir } from "@adtl/labels";
|
|
12
|
+
import { parseConfigText } from "@adtl/interceptors";
|
|
13
|
+
import { parse as parseYaml } from "yaml";
|
|
14
|
+
import { JsonlAuditLog } from "../audit.js";
|
|
15
|
+
import { failure, handleHook } from "./claudeCode.js";
|
|
16
|
+
export async function runHook(opts) {
|
|
17
|
+
let input;
|
|
18
|
+
try {
|
|
19
|
+
input = JSON.parse(opts.stdin);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
// Without the event name we can't tell whether this is a PreToolUse call; refuse it to be safe.
|
|
23
|
+
return failure("PreToolUse", "hook input on stdin is not JSON");
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const path = resolve(input.cwd ?? process.cwd(), opts.configPath);
|
|
27
|
+
const text = await readFile(path, "utf8");
|
|
28
|
+
const config = parseConfigText(text, path);
|
|
29
|
+
const gw = (parseYaml(text) ?? {}).gateway ?? {};
|
|
30
|
+
const sessionsDir = defaultSessionsDir(opts.env ?? process.env);
|
|
31
|
+
return handleHook(input, {
|
|
32
|
+
config,
|
|
33
|
+
sessions: new FileSessionStore(sessionsDir),
|
|
34
|
+
...(opts.gatewayServer ? { gatewayServer: opts.gatewayServer } : {}),
|
|
35
|
+
mode: gw.mode === "audit" ? "audit" : "active",
|
|
36
|
+
...(typeof gw.audit === "string" ? { audit: new JsonlAuditLog(resolve(dirname(path), gw.audit)) } : {}),
|
|
37
|
+
protect: { configPath: path, sessionsDir },
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
return failure(input.hook_event_name, err.message);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/hooks/run.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,UAAU,EAAoC,MAAM,iBAAiB,CAAC;AASxF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAoB;IAChD,IAAI,KAAgB,CAAC;IACrB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAc,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,gGAAgG;QAChG,OAAO,OAAO,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAClE,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC3C,MAAM,EAAE,GAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,CAAuD,CAAC,OAAO,IAAI,EAAE,CAAC;QACxG,MAAM,WAAW,GAAG,kBAAkB,CAAC,IAAI,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC;QAChE,OAAO,UAAU,CAAC,KAAK,EAAE;YACvB,MAAM;YACN,QAAQ,EAAE,IAAI,gBAAgB,CAAC,WAAW,CAAC;YAC3C,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;YAC9C,GAAG,CAAC,OAAO,EAAE,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACvG,OAAO,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE;SAC3C,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,OAAO,CAAC,KAAK,CAAC,eAAe,EAAG,GAAa,CAAC,OAAO,CAAC,CAAC;IAChE,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,WAAW,CAAC;AAC1B,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type Document } from "yaml";
|
|
2
|
+
import type { Upstream } from "../config.js";
|
|
3
|
+
export declare const DEFAULT_GATEWAY_NAME = "adtl";
|
|
4
|
+
export interface McpImport {
|
|
5
|
+
/** Servers moved into gateway.upstreams: name in the client config → upstream id. */
|
|
6
|
+
imported: {
|
|
7
|
+
name: string;
|
|
8
|
+
id: string;
|
|
9
|
+
}[];
|
|
10
|
+
/** Servers already in adtl.yaml under the same id; left as they are. */
|
|
11
|
+
kept: {
|
|
12
|
+
name: string;
|
|
13
|
+
id: string;
|
|
14
|
+
}[];
|
|
15
|
+
/** Servers left in the client config, with why. */
|
|
16
|
+
skipped: {
|
|
17
|
+
name: string;
|
|
18
|
+
reason: string;
|
|
19
|
+
}[];
|
|
20
|
+
/** The client config as it should be once the gateway replaces the imported servers. */
|
|
21
|
+
text: string;
|
|
22
|
+
changed: boolean;
|
|
23
|
+
}
|
|
24
|
+
type Entry = Record<string, unknown>;
|
|
25
|
+
/** True if this client entry already runs adtl-gateway. */
|
|
26
|
+
export declare function isGatewayEntry(entry: Entry): boolean;
|
|
27
|
+
/** A valid upstream id (letters, digits, '-') for a client server name, unique among `taken`. */
|
|
28
|
+
export declare function upstreamId(name: string, taken: Set<string>): string;
|
|
29
|
+
/** The upstream for one client entry, or why it can't be one. */
|
|
30
|
+
export declare function toUpstream(entry: Entry, mcpDir: string, configDir: string): Upstream | {
|
|
31
|
+
skip: string;
|
|
32
|
+
};
|
|
33
|
+
/** What runs the gateway from the client config, with adtl.yaml given relative to the client config's directory. */
|
|
34
|
+
export declare function gatewayEntry(configPath: string, mcpDir: string): Entry;
|
|
35
|
+
/**
|
|
36
|
+
* Add the client's servers to `doc` (adtl.yaml) under gateway.upstreams, and
|
|
37
|
+
* return the client config rewritten to use the gateway.
|
|
38
|
+
*/
|
|
39
|
+
export declare function importMcpServers(mcpText: string, mcpPath: string, doc: Document, configPath: string, gatewayName?: string): McpImport;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=fromMcpJson.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fromMcpJson.d.ts","sourceRoot":"","sources":["../../src/init/fromMcpJson.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAS,KAAK,QAAQ,EAAE,MAAM,MAAM,CAAC;AAC5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAG7C,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAE3C,MAAM,WAAW,SAAS;IACxB,qFAAqF;IACrF,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACzC,wEAAwE;IACxE,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACrC,mDAAmD;IACnD,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5C,wFAAwF;IACxF,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,KAAK,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAerC,2DAA2D;AAC3D,wBAAgB,cAAc,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAGpD;AAED,iGAAiG;AACjG,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,MAAM,CAMnE;AAED,iEAAiE;AACjE,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAoBvG;AAED,oHAAoH;AACpH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CAEtE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,QAAQ,EACb,UAAU,EAAE,MAAM,EAClB,WAAW,SAAuB,GACjC,SAAS,CA8DX"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `adtl-gateway init --from .mcp.json`: import an MCP client's server list
|
|
3
|
+
* (Claude Code's .mcp.json, or any file with `mcpServers`, such as Claude
|
|
4
|
+
* Desktop's config) into `gateway.upstreams`, and point the client at the
|
|
5
|
+
* gateway instead.
|
|
6
|
+
*
|
|
7
|
+
* - stdio servers keep their command, args and env; HTTP servers their url
|
|
8
|
+
* and headers. `${VAR}` and `${VAR:-default}` work the same in adtl.yaml.
|
|
9
|
+
* - SSE servers are left in the client config: the gateway speaks Streamable HTTP only.
|
|
10
|
+
* - An entry that already runs the gateway is recognized and kept.
|
|
11
|
+
* - Upstreams already in adtl.yaml are never changed.
|
|
12
|
+
*
|
|
13
|
+
* The new client config has the imported servers replaced by one entry that
|
|
14
|
+
* runs the gateway; everything else in the file is kept.
|
|
15
|
+
*/
|
|
16
|
+
import { dirname, relative, resolve } from "node:path";
|
|
17
|
+
import { isMap } from "yaml";
|
|
18
|
+
import { GATEWAY_VERSION } from "../gateway.js";
|
|
19
|
+
export const DEFAULT_GATEWAY_NAME = "adtl";
|
|
20
|
+
function isRecord(v) {
|
|
21
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
22
|
+
}
|
|
23
|
+
function strings(v) {
|
|
24
|
+
return Array.isArray(v) && v.every((x) => typeof x === "string") ? v : undefined;
|
|
25
|
+
}
|
|
26
|
+
function stringRecord(v) {
|
|
27
|
+
if (!isRecord(v))
|
|
28
|
+
return undefined;
|
|
29
|
+
return Object.values(v).every((x) => typeof x === "string") ? v : undefined;
|
|
30
|
+
}
|
|
31
|
+
/** True if this client entry already runs adtl-gateway. */
|
|
32
|
+
export function isGatewayEntry(entry) {
|
|
33
|
+
const words = [entry.command, ...(strings(entry.args) ?? [])].filter((w) => typeof w === "string");
|
|
34
|
+
return words.some((w) => /(^|[/\\@])adtl-gateway$|@adtl\/gateway(@[^/\s]*)?$|packages[/\\]gateway[/\\]dist[/\\]cli\.js$/.test(w));
|
|
35
|
+
}
|
|
36
|
+
/** A valid upstream id (letters, digits, '-') for a client server name, unique among `taken`. */
|
|
37
|
+
export function upstreamId(name, taken) {
|
|
38
|
+
const base = name.replace(/[^A-Za-z0-9-]+/g, "-").replace(/^-+|-+$/g, "") || "server";
|
|
39
|
+
let id = base;
|
|
40
|
+
for (let n = 2; taken.has(id); n++)
|
|
41
|
+
id = `${base}-${n}`;
|
|
42
|
+
taken.add(id);
|
|
43
|
+
return id;
|
|
44
|
+
}
|
|
45
|
+
/** The upstream for one client entry, or why it can't be one. */
|
|
46
|
+
export function toUpstream(entry, mcpDir, configDir) {
|
|
47
|
+
const type = typeof entry.type === "string" ? entry.type : undefined;
|
|
48
|
+
if (type === "sse")
|
|
49
|
+
return { skip: "the gateway doesn't support SSE servers; it speaks Streamable HTTP" };
|
|
50
|
+
if (type === "http" || (type === undefined && typeof entry.url === "string")) {
|
|
51
|
+
if (typeof entry.url !== "string")
|
|
52
|
+
return { skip: "HTTP server without a url" };
|
|
53
|
+
const headers = stringRecord(entry.headers);
|
|
54
|
+
return { url: entry.url, headers: headers ?? {} };
|
|
55
|
+
}
|
|
56
|
+
if (type !== undefined && type !== "stdio")
|
|
57
|
+
return { skip: `unknown server type "${type}"` };
|
|
58
|
+
if (typeof entry.command !== "string" || entry.command === "")
|
|
59
|
+
return { skip: "no command or url" };
|
|
60
|
+
// Clients start stdio servers in the project directory; the gateway resolves cwd against adtl.yaml's.
|
|
61
|
+
const cwd = relative(configDir, mcpDir);
|
|
62
|
+
const args = strings(entry.args) ?? [];
|
|
63
|
+
const env = stringRecord(entry.env) ?? {};
|
|
64
|
+
return {
|
|
65
|
+
command: entry.command,
|
|
66
|
+
args,
|
|
67
|
+
env,
|
|
68
|
+
...(cwd !== "" ? { cwd } : {}),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/** What runs the gateway from the client config, with adtl.yaml given relative to the client config's directory. */
|
|
72
|
+
export function gatewayEntry(configPath, mcpDir) {
|
|
73
|
+
return { command: "npx", args: ["-y", `@adtl/gateway@${GATEWAY_VERSION}`, "--config", relative(mcpDir, configPath) || configPath] };
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Add the client's servers to `doc` (adtl.yaml) under gateway.upstreams, and
|
|
77
|
+
* return the client config rewritten to use the gateway.
|
|
78
|
+
*/
|
|
79
|
+
export function importMcpServers(mcpText, mcpPath, doc, configPath, gatewayName = DEFAULT_GATEWAY_NAME) {
|
|
80
|
+
let json;
|
|
81
|
+
try {
|
|
82
|
+
json = JSON.parse(mcpText);
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
throw new Error(`${mcpPath}: not valid JSON: ${err.message}`);
|
|
86
|
+
}
|
|
87
|
+
if (!isRecord(json) || !isRecord(json.mcpServers))
|
|
88
|
+
throw new Error(`${mcpPath}: no "mcpServers" object`);
|
|
89
|
+
const mcpDir = dirname(resolve(mcpPath));
|
|
90
|
+
const configDir = dirname(resolve(configPath));
|
|
91
|
+
const existing = doc.getIn(["gateway", "upstreams"]);
|
|
92
|
+
const taken = new Set(isMap(existing) ? existing.items.map((p) => String(p.key?.value ?? p.key)) : []);
|
|
93
|
+
const alreadyThere = new Set(taken);
|
|
94
|
+
const result = { imported: [], kept: [], skipped: [], text: mcpText, changed: false };
|
|
95
|
+
const servers = {};
|
|
96
|
+
let gatewayKey;
|
|
97
|
+
for (const [name, entry] of Object.entries(json.mcpServers)) {
|
|
98
|
+
if (!isRecord(entry)) {
|
|
99
|
+
result.skipped.push({ name, reason: "not an object" });
|
|
100
|
+
servers[name] = entry;
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (isGatewayEntry(entry)) {
|
|
104
|
+
gatewayKey ??= name;
|
|
105
|
+
servers[name] = entry;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const upstream = toUpstream(entry, mcpDir, configDir);
|
|
109
|
+
if ("skip" in upstream) {
|
|
110
|
+
result.skipped.push({ name, reason: upstream.skip });
|
|
111
|
+
servers[name] = entry;
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
const plain = name.replace(/[^A-Za-z0-9-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
115
|
+
if (alreadyThere.has(plain)) {
|
|
116
|
+
result.kept.push({ name, id: plain });
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const id = upstreamId(name, taken);
|
|
120
|
+
// Leave out empty fields; the gateway fills them in.
|
|
121
|
+
const written = Object.fromEntries(Object.entries(upstream).filter(([, v]) => !(Array.isArray(v) ? v.length === 0 : isRecord(v) && Object.keys(v).length === 0)));
|
|
122
|
+
doc.setIn(["gateway", "upstreams", id], doc.createNode(written));
|
|
123
|
+
result.imported.push({ name, id });
|
|
124
|
+
}
|
|
125
|
+
// Block style, so long paths and secrets references stay readable (a new config starts with `upstreams: {}`).
|
|
126
|
+
const upstreams = doc.getIn(["gateway", "upstreams"]);
|
|
127
|
+
if (isMap(upstreams) && result.imported.length)
|
|
128
|
+
upstreams.flow = false;
|
|
129
|
+
if (result.imported.length === 0 && result.kept.length === 0)
|
|
130
|
+
return result;
|
|
131
|
+
if (gatewayKey === undefined) {
|
|
132
|
+
let key = gatewayName;
|
|
133
|
+
for (let n = 2; key in servers; n++)
|
|
134
|
+
key = `${gatewayName}-${n}`;
|
|
135
|
+
servers[key] = gatewayEntry(resolve(configPath), mcpDir);
|
|
136
|
+
}
|
|
137
|
+
result.text = `${JSON.stringify({ ...json, mcpServers: servers }, null, 2)}\n`;
|
|
138
|
+
result.changed = result.text !== mcpText;
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=fromMcpJson.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fromMcpJson.js","sourceRoot":"","sources":["../../src/init/fromMcpJson.ts"],"names":[],"mappings":"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"}
|