@adtl/gateway 0.3.0 → 0.3.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/dist/startup.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
- import type { AdtlConfig } from "@adtl/labels";
2
+ import { type AdtlConfig } from "@adtl/labels";
3
3
  import { ApprovalBroker } from "./approvals.js";
4
4
  import { type GatewayConfig, type Upstream } from "./config.js";
5
5
  import { AdtlGateway, type GatewayLogger } from "./gateway.js";
@@ -17,6 +17,15 @@ export declare function bundledInterceptorsCli(): string;
17
17
  export declare function connectUpstream(id: string, u: Upstream, baseDir: string): Promise<Client>;
18
18
  /** Build the approval broker from `gateway.approvals`, or undefined if not configured. */
19
19
  export declare function createApprovals(cfg: GatewayConfig, env: NodeJS.ProcessEnv, log: GatewayLogger): ApprovalBroker | undefined;
20
+ /**
21
+ * Under Claude Code, which passes `CLAUDE_CODE_SESSION_ID` to stdio MCP
22
+ * servers, the gateway uses that id and keeps session labels in files, so the
23
+ * Claude Code hooks (`adtl-gateway hook`) add to the same session label.
24
+ */
25
+ export declare function sharedSession(env: NodeJS.ProcessEnv): {
26
+ sessionId: string;
27
+ dir: string;
28
+ } | undefined;
20
29
  export interface StartedGateway {
21
30
  gateway: AdtlGateway;
22
31
  close(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"startup.d.ts","sourceRoot":"","sources":["../src/startup.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAInE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAiB,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EAKL,KAAK,aAAa,EAElB,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,WAAW,EAAmB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAIhF,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA2B3E;AAED,iDAAiD;AACjD,wBAAgB,sBAAsB,IAAI,MAAM,CAI/C;AAaD,wBAAsB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO/F;AAED,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,cAAc,GAAG,SAAS,CAiB1H;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,aAAa,CAAA;CAAO,GAC7D,OAAO,CAAC,cAAc,CAAC,CAgEzB"}
1
+ {"version":3,"file":"startup.d.ts","sourceRoot":"","sources":["../src/startup.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAInE,OAAO,EAAsB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAGnE,OAAO,EAAE,cAAc,EAAiB,MAAM,gBAAgB,CAAC;AAE/D,OAAO,EAKL,KAAK,aAAa,EAElB,KAAK,QAAQ,EACd,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,WAAW,EAAmB,KAAK,aAAa,EAAE,MAAM,cAAc,CAAC;AAIhF,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA2B3E;AAED,iDAAiD;AACjD,wBAAgB,sBAAsB,IAAI,MAAM,CAI/C;AAaD,wBAAsB,eAAe,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAO/F;AAED,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,GAAG,EAAE,aAAa,GAAG,cAAc,GAAG,SAAS,CAiB1H;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAGpG;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,WAAW,CAAC;IACrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,YAAY,EACpB,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,MAAM,CAAC,EAAE,aAAa,CAAA;CAAO,GAC7D,OAAO,CAAC,cAAc,CAAC,CAwEzB"}
package/dist/startup.js CHANGED
@@ -9,6 +9,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
9
9
  import { StdioClientTransport, getDefaultEnvironment } from "@modelcontextprotocol/sdk/client/stdio.js";
10
10
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
11
11
  import { INTERCEPTORS_EXTENSION, LABEL_INTERCEPTOR, POLICY_INTERCEPTOR, parseConfigText } from "@adtl/interceptors";
12
+ import { defaultSessionsDir } from "@adtl/labels";
12
13
  import { parse as parseYaml } from "yaml";
13
14
  import { ZodError } from "zod";
14
15
  import { ApprovalBroker } from "./approvals.js";
@@ -101,6 +102,15 @@ export function createApprovals(cfg, env, log) {
101
102
  log.info(`approvals: ${notifiers.map((n) => n.name).join(", ")} (timeout ${a.timeoutSeconds}s)`);
102
103
  return new ApprovalBroker({ notifiers, timeoutMs: a.timeoutSeconds * 1000, log });
103
104
  }
105
+ /**
106
+ * Under Claude Code, which passes `CLAUDE_CODE_SESSION_ID` to stdio MCP
107
+ * servers, the gateway uses that id and keeps session labels in files, so the
108
+ * Claude Code hooks (`adtl-gateway hook`) add to the same session label.
109
+ */
110
+ export function sharedSession(env) {
111
+ const sessionId = env.CLAUDE_CODE_SESSION_ID?.trim();
112
+ return sessionId ? { sessionId, dir: defaultSessionsDir(env) } : undefined;
113
+ }
104
114
  export async function startGateway(loaded, opts = {}) {
105
115
  const env = opts.env ?? process.env;
106
116
  const baseDir = dirname(loaded.path);
@@ -109,9 +119,15 @@ export async function startGateway(loaded, opts = {}) {
109
119
  const closeAll = () => Promise.allSettled(clients.map((c) => c.close())).then(() => undefined);
110
120
  try {
111
121
  // 1. Interceptor server (out of process, per the Interceptors WG).
112
- const icfg = loaded.gateway.interceptors
113
- ? expandUpstream("interceptors", loaded.gateway.interceptors, env)
114
- : { command: process.execPath, args: [bundledInterceptorsCli(), "--config", loaded.path], env: {} };
122
+ const shared = sharedSession(env);
123
+ const custom = loaded.gateway.interceptors && expandUpstream("interceptors", loaded.gateway.interceptors, env);
124
+ const icfg = custom
125
+ ? { ...custom, env: { ...custom.env, ...(shared ? { ADTL_SESSIONS_DIR: shared.dir } : {}) } }
126
+ : {
127
+ command: process.execPath,
128
+ args: [bundledInterceptorsCli(), "--config", loaded.path, ...(shared ? ["--sessions-dir", shared.dir] : [])],
129
+ env: {},
130
+ };
115
131
  const interceptors = await connectUpstream("interceptors", icfg, baseDir);
116
132
  clients.push(interceptors);
117
133
  if (!interceptors.getServerCapabilities()?.extensions?.[INTERCEPTORS_EXTENSION]) {
@@ -127,6 +143,8 @@ export async function startGateway(loaded, opts = {}) {
127
143
  const audit = loaded.gateway.mode === "audit";
128
144
  const invoker = new InterceptorInvoker(bound, loaded.gateway.interceptorTimeoutMs, audit ? "audit" : undefined);
129
145
  log.info(`interceptors: ${names.join(", ")}`);
146
+ if (shared)
147
+ log.info(`sharing session labels with Claude Code hooks (${shared.dir})`);
130
148
  if (audit)
131
149
  log.warn("audit mode: calls are logged but never stopped or changed");
132
150
  // 2. Upstream servers. One failing upstream does not stop the others.
@@ -152,6 +170,7 @@ export async function startGateway(loaded, opts = {}) {
152
170
  const auditLog = loaded.gateway.audit ? new JsonlAuditLog(resolve(baseDir, loaded.gateway.audit)) : undefined;
153
171
  const approvals = createApprovals(loaded.gateway, env, log);
154
172
  const gateway = new AdtlGateway({
173
+ ...(shared ? { sessionId: shared.sessionId } : {}),
155
174
  upstreams,
156
175
  invoker,
157
176
  ...(auditLog ? { audit: auditLog } : {}),
@@ -1 +1 @@
1
- {"version":3,"file":"startup.js","sourceRoot":"","sources":["../src/startup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"startup.js","sourceRoot":"","sources":["../src/startup.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adtl/gateway",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Experimental: MCP gateway that labels every tool result and blocks risky tool calls using ADTL trust labels",
5
5
  "keywords": [
6
6
  "mcp",
@@ -46,8 +46,8 @@
46
46
  "url": "https://github.com/probita-ai/adtl/issues"
47
47
  },
48
48
  "dependencies": {
49
- "@adtl/interceptors": "0.3.0",
50
- "@adtl/labels": "0.3.0",
49
+ "@adtl/interceptors": "0.3.1",
50
+ "@adtl/labels": "0.3.1",
51
51
  "@modelcontextprotocol/sdk": "1.31.0",
52
52
  "nodemailer": "10.0.12",
53
53
  "yaml": "2.9.1",
package/src/audit.ts CHANGED
@@ -16,8 +16,10 @@ export interface AuditEntry {
16
16
  tool?: string;
17
17
  resource?: string;
18
18
  prompt?: string;
19
- /** Final outcome of the call. */
20
- outcome: "forwarded" | "blocked" | "upstream_error";
19
+ /** Final outcome of the call. "asked": handed to Claude Code's permission prompt by the hook. */
20
+ outcome: "forwarded" | "blocked" | "asked" | "upstream_error";
21
+ /** Present when the entry was written by the Claude Code hook rather than the gateway. */
22
+ via?: "claude-code-hook";
21
23
  /** The policy's decision. In audit mode a call can be forwarded with decision "ask" or "block". */
22
24
  decision?: string;
23
25
  /** Present when the gateway ran in audit mode: nothing was stopped or changed. */
package/src/cli.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  *
6
6
  * adtl-gateway --config adtl.yaml [--audit]
7
7
  * adtl-gateway init --config adtl.yaml [--write]
8
+ * adtl-gateway hook --config adtl.yaml [--gateway-server adtl]
8
9
  *
9
10
  * Point your MCP client (e.g. Claude Code's .mcp.json) at this command.
10
11
  * Logs go to stderr; stdout carries MCP JSON-RPC only.
@@ -12,11 +13,13 @@
12
13
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
13
14
  import { EnvExpansionError } from "./config.js";
14
15
  import { GATEWAY_VERSION } from "./gateway.js";
16
+ import { runHook } from "./hooks/run.js";
15
17
  import { runInit, type InitResult } from "./init/run.js";
16
18
  import { GatewayConfigError, loadGatewayConfig, startGateway } from "./startup.js";
17
19
 
18
20
  const USAGE = `Usage: adtl-gateway --config <adtl.yaml> [--audit]
19
21
  adtl-gateway init --config <adtl.yaml> [--write]
22
+ adtl-gateway hook --config <adtl.yaml> [--gateway-server <name>]
20
23
 
21
24
  Runs an MCP server over stdio that forwards tool calls to the upstream
22
25
  servers in the config, checking and labeling each call with ADTL.
@@ -33,10 +36,23 @@ init:
33
36
  filesystem and fetch; MCP tool hints otherwise). Existing entries are
34
37
  never changed. Prints the updated config; review it before using it.
35
38
  --write Update the config file in place (original kept as .bak).
39
+
40
+ hook:
41
+ The Claude Code hook for PreToolUse, PostToolUse and PostToolUseFailure.
42
+ Labels built-in tools (WebFetch, Read, Bash, ...) and MCP servers outside
43
+ the gateway, and runs the same policy on them, sharing the session label
44
+ with the gateway. Reads the hook event from stdin.
45
+ --gateway-server <name>
46
+ The gateway's name in Claude Code's MCP config; its
47
+ tools are checked by the gateway and skipped here.
48
+ Default: adtl.
49
+
36
50
  -h, --help Show this help.`;
37
51
 
38
52
  interface Args {
39
53
  init?: boolean;
54
+ hook?: boolean;
55
+ gatewayServer?: string;
40
56
  write?: boolean;
41
57
  config?: string;
42
58
  audit?: boolean;
@@ -49,6 +65,8 @@ function parseArgs(argv: string[]): Args {
49
65
  for (let i = 0; i < argv.length; i++) {
50
66
  const a = argv[i];
51
67
  if (i === 0 && a === "init") out.init = true;
68
+ else if (i === 0 && a === "hook") out.hook = true;
69
+ else if (a === "--gateway-server" && out.hook) out.gatewayServer = argv[++i];
52
70
  else if (a === "-h" || a === "--help") out.help = true;
53
71
  else if (a === "-v" || a === "--version") out.version = true;
54
72
  else if (a === "-c" || a === "--config") out.config = argv[++i];
@@ -67,6 +85,7 @@ async function main(): Promise<void> {
67
85
  if (args.version) return void console.log(GATEWAY_VERSION);
68
86
  if (!args.config) throw new GatewayConfigError(`Missing --config\n\n${USAGE}`);
69
87
  if (args.init) return init(args.config, args.write === true);
88
+ if (args.hook) return hook(args.config, args.gatewayServer);
70
89
 
71
90
  const loaded = await loadGatewayConfig(args.config);
72
91
  if (args.audit) loaded.gateway.mode = "audit";
@@ -110,6 +129,19 @@ function summarize(r: InitResult, path: string, write: boolean): string {
110
129
  return `${lines.join("\n")}\n${tail}`;
111
130
  }
112
131
 
132
+ async function readStdin(): Promise<string> {
133
+ const chunks: Buffer[] = [];
134
+ for await (const c of process.stdin) chunks.push(c as Buffer);
135
+ return Buffer.concat(chunks).toString("utf8");
136
+ }
137
+
138
+ async function hook(config: string, gatewayServer?: string): Promise<void> {
139
+ const out = await runHook({ configPath: config, stdin: await readStdin(), ...(gatewayServer ? { gatewayServer } : {}) });
140
+ if (out.stdout) process.stdout.write(`${JSON.stringify(out.stdout)}\n`);
141
+ if (out.stderr) process.stderr.write(`${out.stderr}\n`);
142
+ process.exitCode = out.exitCode;
143
+ }
144
+
113
145
  async function init(path: string, write: boolean): Promise<void> {
114
146
  const result = await runInit({ path, write });
115
147
  if (!write) process.stdout.write(result.text);
@@ -120,5 +152,6 @@ async function init(path: string, write: boolean): Promise<void> {
120
152
  main().catch((err: unknown) => {
121
153
  const known = err instanceof GatewayConfigError || err instanceof EnvExpansionError;
122
154
  console.error(known ? `[adtl-gateway] ${(err as Error).message}` : err);
123
- process.exit(1);
155
+ // For Claude Code hooks only exit code 2 stops the call; any other code lets it run.
156
+ process.exit(process.argv[2] === "hook" ? 2 : 1);
124
157
  });
package/src/gateway.ts CHANGED
@@ -51,7 +51,7 @@ import type { AuditEntry, AuditSink } from "./audit.js";
51
51
  import { TOOL_SEPARATOR } from "./config.js";
52
52
  import type { Blocked, ChainOutcome, InterceptorInvoker } from "./invoker.js";
53
53
 
54
- export const GATEWAY_VERSION = "0.3.0";
54
+ export const GATEWAY_VERSION = "0.3.1";
55
55
 
56
56
  /** `_meta` key on gateway-generated error results describing why a call was stopped. */
57
57
  export const GATEWAY_DECISION_KEY = "adtl/gateway";
@@ -0,0 +1,194 @@
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 {
24
+ callHash,
25
+ evaluatePolicy,
26
+ labelResult,
27
+ toolEgress,
28
+ type AdtlConfig,
29
+ type Decision,
30
+ type PolicyDecision,
31
+ type SessionStore,
32
+ } from "@adtl/labels";
33
+ import type { AuditEntry, AuditSink } from "../audit.js";
34
+ import { CLAUDE_CODE_PRESET, CLAUDE_CODE_SERVER } from "./preset.js";
35
+
36
+ export interface HookInput {
37
+ session_id?: string;
38
+ hook_event_name?: string;
39
+ tool_name?: string;
40
+ tool_input?: unknown;
41
+ tool_response?: unknown;
42
+ /** PostToolUseFailure: the error the tool returned. */
43
+ error?: unknown;
44
+ cwd?: string;
45
+ }
46
+
47
+ export interface HookOptions {
48
+ config: AdtlConfig;
49
+ sessions: SessionStore;
50
+ /** Name of the gateway in Claude Code's MCP config; its tools are skipped. Default `adtl`. */
51
+ gatewayServer?: string;
52
+ /** `audit`: decide and log, but never deny or ask. */
53
+ mode?: "active" | "audit";
54
+ audit?: AuditSink;
55
+ /** Files the agent must not change: the ADTL config and the session directory. */
56
+ protect?: { configPath?: string; sessionsDir?: string };
57
+ }
58
+
59
+ /** What the hook process prints and exits with. */
60
+ export interface HookOutcome {
61
+ stdout?: Record<string, unknown>;
62
+ stderr?: string;
63
+ exitCode: number;
64
+ }
65
+
66
+ const NOTHING: HookOutcome = { exitCode: 0 };
67
+
68
+ /** `config` with labels for Claude Code's built-in tools; rules under `servers.claude-code` win. */
69
+ export function withClaudeCodePreset(config: AdtlConfig): AdtlConfig {
70
+ const own = config.servers[CLAUDE_CODE_SERVER];
71
+ return {
72
+ ...config,
73
+ servers: {
74
+ ...config.servers,
75
+ [CLAUDE_CODE_SERVER]: {
76
+ acceptServerClaims: own?.acceptServerClaims ?? false,
77
+ ...(own?.defaults ? { defaults: own.defaults } : {}),
78
+ tools: { ...CLAUDE_CODE_PRESET, ...own?.tools },
79
+ },
80
+ },
81
+ };
82
+ }
83
+
84
+ /** Which ADTL server and tool a Claude Code tool name is, or undefined for the gateway's own tools. */
85
+ export function routeTool(toolName: string, gatewayServer = "adtl"): { server: string; tool: string } | undefined {
86
+ const m = /^mcp__(.+?)__(.+)$/.exec(toolName);
87
+ if (!m) return { server: CLAUDE_CODE_SERVER, tool: toolName };
88
+ if (m[1] === gatewayServer) return undefined;
89
+ return { server: m[1]!, tool: m[2]! };
90
+ }
91
+
92
+ function isRecord(v: unknown): v is Record<string, unknown> {
93
+ return typeof v === "object" && v !== null && !Array.isArray(v);
94
+ }
95
+
96
+ function inside(path: string, dir: string): boolean {
97
+ const r = relative(dir, path);
98
+ return r === "" || (!r.startsWith(`..${sep}`) && r !== ".." && !isAbsolute(r));
99
+ }
100
+
101
+ /**
102
+ * A best-effort guard against the agent clearing its own taint by editing the
103
+ * config or deleting session files. Not a sandbox: Bash can always find a way.
104
+ */
105
+ function protectedTarget(input: HookInput, route: { server: string; tool: string }, protect: HookOptions["protect"]): { decision: Decision; reason: string } | undefined {
106
+ if (!protect || route.server !== CLAUDE_CODE_SERVER) return undefined;
107
+ const args = isRecord(input.tool_input) ? input.tool_input : {};
108
+ const cwd = input.cwd ?? process.cwd();
109
+ const path = typeof args.file_path === "string" ? args.file_path : typeof args.notebook_path === "string" ? args.notebook_path : undefined;
110
+ if (path !== undefined && ["Write", "Edit", "MultiEdit", "NotebookEdit"].includes(route.tool)) {
111
+ const abs = resolve(cwd, path);
112
+ if (protect.configPath && abs === resolve(protect.configPath)) {
113
+ return { decision: "block", reason: "The agent may not change the ADTL config; edit it yourself" };
114
+ }
115
+ if (protect.sessionsDir && inside(abs, resolve(protect.sessionsDir))) {
116
+ return { decision: "block", reason: "The agent may not change ADTL session labels" };
117
+ }
118
+ }
119
+ const command = typeof args.command === "string" ? args.command : undefined;
120
+ if (command !== undefined && ["Bash", "Monitor"].includes(route.tool)) {
121
+ const marks = [".adtl/sessions", protect.sessionsDir].filter((m): m is string => !!m);
122
+ if (marks.some((m) => command.includes(m))) {
123
+ return { decision: "ask", reason: "This command touches ADTL session labels" };
124
+ }
125
+ }
126
+ return undefined;
127
+ }
128
+
129
+ export function handleHook(input: HookInput, opts: HookOptions): HookOutcome {
130
+ const event = input.hook_event_name;
131
+ if (event !== "PreToolUse" && event !== "PostToolUse" && event !== "PostToolUseFailure") return NOTHING;
132
+ if (typeof input.tool_name !== "string" || typeof input.session_id !== "string" || input.session_id === "") {
133
+ return failure(event, "hook input has no tool_name or session_id");
134
+ }
135
+ const route = routeTool(input.tool_name, opts.gatewayServer);
136
+ if (!route) return NOTHING;
137
+ const config = withClaudeCodePreset(opts.config);
138
+ const ts = new Date().toISOString();
139
+ const base = { ts, sessionId: input.session_id, event: "tools/call" as const, ...route, via: "claude-code-hook" as const };
140
+
141
+ if (event !== "PreToolUse") {
142
+ const label = labelResult({ ...route, result: input.tool_response ?? input.error ?? null }, config);
143
+ const sessionLabel = opts.sessions.observe(input.session_id, label);
144
+ opts.audit?.write({ ...base, outcome: "forwarded", label, sessionLabel, durationMs: 0 });
145
+ return NOTHING;
146
+ }
147
+
148
+ const hash = callHash(route.server, route.tool, input.tool_input ?? {});
149
+ const session = opts.sessions.get(input.session_id);
150
+ const guard = protectedTarget(input, route, opts.protect);
151
+ const policy: PolicyDecision = evaluatePolicy(config.policy, {
152
+ session,
153
+ ...route,
154
+ egress: toolEgress(config, route.server, route.tool),
155
+ });
156
+ const d: PolicyDecision =
157
+ guard && (guard.decision === "block" || policy.decision === "allow")
158
+ ? { decision: guard.decision, reason: guard.reason, matched: ["adtl-self-protection"] }
159
+ : policy;
160
+ if (d.decision === "allow") return NOTHING;
161
+
162
+ const audit = opts.mode === "audit";
163
+ const entry: AuditEntry = {
164
+ ...base,
165
+ outcome: audit ? "forwarded" : d.decision === "ask" ? "asked" : "blocked",
166
+ decision: d.decision,
167
+ ...(audit ? { mode: "audit" as const } : {}),
168
+ reason: d.reason,
169
+ matched: d.matched,
170
+ callHash: hash,
171
+ sessionLabel: session,
172
+ durationMs: 0,
173
+ };
174
+ opts.audit?.write(entry);
175
+ if (audit) return NOTHING;
176
+
177
+ return {
178
+ exitCode: 0,
179
+ stdout: {
180
+ hookSpecificOutput: {
181
+ hookEventName: "PreToolUse",
182
+ permissionDecision: d.decision === "ask" ? "ask" : "deny",
183
+ permissionDecisionReason:
184
+ d.decision === "ask" ? `ADTL: ${d.reason}. Approve only if you expected this call.` : `ADTL blocked this call: ${d.reason}.`,
185
+ },
186
+ },
187
+ };
188
+ }
189
+
190
+ /** Fail closed: exit 2 stops a PreToolUse call and shows the reason to Claude. */
191
+ export function failure(event: string | undefined, why: string): HookOutcome {
192
+ const stopped = event === "PreToolUse" ? " The call was stopped." : "";
193
+ return { exitCode: 2, stderr: `ADTL hook error: ${why}.${stopped}` };
194
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./claudeCode.js";
2
+ export * from "./preset.js";
3
+ export * from "./run.js";
@@ -0,0 +1,47 @@
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
+
15
+ export const CLAUDE_CODE_SERVER = "claude-code";
16
+
17
+ const localRead: ToolRule = { integrity: "trusted", confidentiality: "private", egress: "none" };
18
+ const localWrite: ToolRule = { integrity: "trusted", confidentiality: "public", egress: "none" };
19
+ const web: ToolRule = { integrity: "untrusted", confidentiality: "public", egress: "external" };
20
+ const shell: ToolRule = { integrity: "unknown", confidentiality: "private", egress: "unknown" };
21
+
22
+ export const CLAUDE_CODE_PRESET: Record<string, ToolRule> = {
23
+ Read: localRead,
24
+ Grep: localRead,
25
+ Glob: localRead,
26
+ LS: localRead,
27
+ NotebookRead: localRead,
28
+ Write: localWrite,
29
+ Edit: localWrite,
30
+ MultiEdit: localWrite,
31
+ NotebookEdit: localWrite,
32
+ TodoWrite: localWrite,
33
+ AskUserQuestion: localWrite,
34
+ Skill: localWrite,
35
+ ToolSearch: localWrite,
36
+ EnterPlanMode: localWrite,
37
+ ExitPlanMode: localWrite,
38
+ WebFetch: web,
39
+ WebSearch: web,
40
+ Bash: shell,
41
+ BashOutput: shell,
42
+ KillShell: localWrite,
43
+ Monitor: shell,
44
+ // A sub-agent's own tool calls go through these hooks too; its answer mixes what it saw.
45
+ Agent: { integrity: "unknown", confidentiality: "private", egress: "none" },
46
+ Task: { integrity: "unknown", confidentiality: "private", egress: "none" },
47
+ };
@@ -0,0 +1,49 @@
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, type HookInput, type HookOutcome } from "./claudeCode.js";
16
+
17
+ export interface RunHookOptions {
18
+ configPath: string;
19
+ stdin: string;
20
+ gatewayServer?: string;
21
+ env?: NodeJS.ProcessEnv;
22
+ }
23
+
24
+ export async function runHook(opts: RunHookOptions): Promise<HookOutcome> {
25
+ let input: HookInput;
26
+ try {
27
+ input = JSON.parse(opts.stdin) as HookInput;
28
+ } catch {
29
+ // Without the event name we can't tell whether this is a PreToolUse call; refuse it to be safe.
30
+ return failure("PreToolUse", "hook input on stdin is not JSON");
31
+ }
32
+ try {
33
+ const path = resolve(input.cwd ?? process.cwd(), opts.configPath);
34
+ const text = await readFile(path, "utf8");
35
+ const config = parseConfigText(text, path);
36
+ const gw = ((parseYaml(text) ?? {}) as { gateway?: { audit?: unknown; mode?: unknown } }).gateway ?? {};
37
+ const sessionsDir = defaultSessionsDir(opts.env ?? process.env);
38
+ return handleHook(input, {
39
+ config,
40
+ sessions: new FileSessionStore(sessionsDir),
41
+ ...(opts.gatewayServer ? { gatewayServer: opts.gatewayServer } : {}),
42
+ mode: gw.mode === "audit" ? "audit" : "active",
43
+ ...(typeof gw.audit === "string" ? { audit: new JsonlAuditLog(resolve(dirname(path), gw.audit)) } : {}),
44
+ protect: { configPath: path, sessionsDir },
45
+ });
46
+ } catch (err) {
47
+ return failure(input.hook_event_name, (err as Error).message);
48
+ }
49
+ }
package/src/index.ts CHANGED
@@ -7,3 +7,4 @@ export * from "./email.js";
7
7
  export * from "./gateway.js";
8
8
  export * from "./startup.js";
9
9
  export * from "./init/index.js";
10
+ export * from "./hooks/index.js";
package/src/startup.ts CHANGED
@@ -9,7 +9,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
9
9
  import { StdioClientTransport, getDefaultEnvironment } from "@modelcontextprotocol/sdk/client/stdio.js";
10
10
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
11
11
  import { INTERCEPTORS_EXTENSION, LABEL_INTERCEPTOR, POLICY_INTERCEPTOR, parseConfigText } from "@adtl/interceptors";
12
- import type { AdtlConfig } from "@adtl/labels";
12
+ import { defaultSessionsDir, type AdtlConfig } from "@adtl/labels";
13
13
  import { parse as parseYaml } from "yaml";
14
14
  import { ZodError } from "zod";
15
15
  import { ApprovalBroker, type Notifier } from "./approvals.js";
@@ -117,6 +117,16 @@ export function createApprovals(cfg: GatewayConfig, env: NodeJS.ProcessEnv, log:
117
117
  return new ApprovalBroker({ notifiers, timeoutMs: a.timeoutSeconds * 1000, log });
118
118
  }
119
119
 
120
+ /**
121
+ * Under Claude Code, which passes `CLAUDE_CODE_SESSION_ID` to stdio MCP
122
+ * servers, the gateway uses that id and keeps session labels in files, so the
123
+ * Claude Code hooks (`adtl-gateway hook`) add to the same session label.
124
+ */
125
+ export function sharedSession(env: NodeJS.ProcessEnv): { sessionId: string; dir: string } | undefined {
126
+ const sessionId = env.CLAUDE_CODE_SESSION_ID?.trim();
127
+ return sessionId ? { sessionId, dir: defaultSessionsDir(env) } : undefined;
128
+ }
129
+
120
130
  export interface StartedGateway {
121
131
  gateway: AdtlGateway;
122
132
  close(): Promise<void>;
@@ -134,9 +144,15 @@ export async function startGateway(
134
144
 
135
145
  try {
136
146
  // 1. Interceptor server (out of process, per the Interceptors WG).
137
- const icfg: StdioUpstream = loaded.gateway.interceptors
138
- ? expandUpstream("interceptors", loaded.gateway.interceptors, env)
139
- : { command: process.execPath, args: [bundledInterceptorsCli(), "--config", loaded.path], env: {} };
147
+ const shared = sharedSession(env);
148
+ const custom = loaded.gateway.interceptors && expandUpstream("interceptors", loaded.gateway.interceptors, env);
149
+ const icfg: StdioUpstream = custom
150
+ ? { ...custom, env: { ...custom.env, ...(shared ? { ADTL_SESSIONS_DIR: shared.dir } : {}) } }
151
+ : {
152
+ command: process.execPath,
153
+ args: [bundledInterceptorsCli(), "--config", loaded.path, ...(shared ? ["--sessions-dir", shared.dir] : [])],
154
+ env: {},
155
+ };
140
156
  const interceptors = await connectUpstream("interceptors", icfg, baseDir);
141
157
  clients.push(interceptors);
142
158
  if (!interceptors.getServerCapabilities()?.extensions?.[INTERCEPTORS_EXTENSION]) {
@@ -152,6 +168,7 @@ export async function startGateway(
152
168
  const audit = loaded.gateway.mode === "audit";
153
169
  const invoker = new InterceptorInvoker(bound, loaded.gateway.interceptorTimeoutMs, audit ? "audit" : undefined);
154
170
  log.info(`interceptors: ${names.join(", ")}`);
171
+ if (shared) log.info(`sharing session labels with Claude Code hooks (${shared.dir})`);
155
172
  if (audit) log.warn("audit mode: calls are logged but never stopped or changed");
156
173
 
157
174
  // 2. Upstream servers. One failing upstream does not stop the others.
@@ -178,6 +195,7 @@ export async function startGateway(
178
195
  const auditLog = loaded.gateway.audit ? new JsonlAuditLog(resolve(baseDir, loaded.gateway.audit)) : undefined;
179
196
  const approvals = createApprovals(loaded.gateway, env, log);
180
197
  const gateway = new AdtlGateway({
198
+ ...(shared ? { sessionId: shared.sessionId } : {}),
181
199
  upstreams,
182
200
  invoker,
183
201
  ...(auditLog ? { audit: auditLog } : {}),