@adtl/gateway 0.1.0 → 0.2.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 +48 -4
- package/dist/approvals.d.ts +97 -0
- package/dist/approvals.d.ts.map +1 -0
- package/dist/approvals.js +151 -0
- package/dist/approvals.js.map +1 -0
- package/dist/audit.d.ts +10 -0
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js.map +1 -1
- package/dist/cli.js +8 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +352 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +69 -2
- package/dist/config.js.map +1 -1
- package/dist/email.d.ts +35 -0
- package/dist/email.d.ts.map +1 -0
- package/dist/email.js +63 -0
- package/dist/email.js.map +1 -0
- package/dist/gateway.d.ts +12 -2
- package/dist/gateway.d.ts.map +1 -1
- package/dist/gateway.js +91 -11
- package/dist/gateway.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/invoker.d.ts +10 -1
- package/dist/invoker.d.ts.map +1 -1
- package/dist/invoker.js +15 -6
- package/dist/invoker.js.map +1 -1
- package/dist/ntfy.d.ts +44 -0
- package/dist/ntfy.d.ts.map +1 -0
- package/dist/ntfy.js +133 -0
- package/dist/ntfy.js.map +1 -0
- package/dist/startup.d.ts +3 -0
- package/dist/startup.d.ts.map +1 -1
- package/dist/startup.js +39 -4
- package/dist/startup.js.map +1 -1
- package/package.json +4 -3
- package/src/approvals.ts +219 -0
- package/src/audit.ts +5 -0
- package/src/cli.ts +15 -4
- package/src/config.ts +71 -2
- package/src/email.ts +79 -0
- package/src/gateway.ts +103 -11
- package/src/index.ts +3 -0
- package/src/invoker.ts +17 -5
- package/src/ntfy.ts +154 -0
- package/src/startup.ts +36 -3
package/dist/config.d.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* gateway:
|
|
5
5
|
* audit: ./adtl-audit.jsonl # optional JSONL audit log
|
|
6
|
+
* mode: audit # optional: log what would be stopped, stop nothing
|
|
6
7
|
* upstreams:
|
|
7
8
|
* github: # id must match `servers.github` in the label config
|
|
8
9
|
* command: npx
|
|
@@ -11,9 +12,16 @@
|
|
|
11
12
|
* docs:
|
|
12
13
|
* url: https://example.com/mcp
|
|
13
14
|
* headers: { Authorization: "Bearer ${DOCS_TOKEN}" }
|
|
15
|
+
* approvals: # optional: make "ask" really ask
|
|
16
|
+
* timeoutSeconds: 50
|
|
17
|
+
* ntfy: { topic: "${ADTL_NTFY_TOPIC}" }
|
|
18
|
+
* email:
|
|
19
|
+
* smtp: { host: smtp.example.com, port: 465, user: "${SMTP_USER}", pass: "${SMTP_PASS}" }
|
|
20
|
+
* from: adtl@example.com
|
|
21
|
+
* to: you@example.com
|
|
14
22
|
*
|
|
15
|
-
* `${VAR}` in command, args, env, cwd, url
|
|
16
|
-
* gateway's environment. A missing variable is a config error.
|
|
23
|
+
* `${VAR}` in command, args, env, cwd, url, headers and approval settings is
|
|
24
|
+
* replaced from the gateway's environment. A missing variable is a config error.
|
|
17
25
|
*/
|
|
18
26
|
import { z } from "zod";
|
|
19
27
|
export declare const StdioUpstreamSchema: z.ZodObject<{
|
|
@@ -70,6 +78,184 @@ export declare const UpstreamSchema: z.ZodUnion<[z.ZodObject<{
|
|
|
70
78
|
export type StdioUpstream = z.infer<typeof StdioUpstreamSchema>;
|
|
71
79
|
export type HttpUpstream = z.infer<typeof HttpUpstreamSchema>;
|
|
72
80
|
export type Upstream = z.infer<typeof UpstreamSchema>;
|
|
81
|
+
export declare const NtfyConfigSchema: z.ZodObject<{
|
|
82
|
+
server: z.ZodDefault<z.ZodString>;
|
|
83
|
+
/** Topic approval requests are sent to. Anyone who can read it can approve: keep it secret. */
|
|
84
|
+
topic: z.ZodString;
|
|
85
|
+
/** Topic answers are posted to. Default: `<topic>-reply`. */
|
|
86
|
+
replyTopic: z.ZodOptional<z.ZodString>;
|
|
87
|
+
token: z.ZodOptional<z.ZodString>;
|
|
88
|
+
}, "strict", z.ZodTypeAny, {
|
|
89
|
+
server: string;
|
|
90
|
+
topic: string;
|
|
91
|
+
replyTopic?: string | undefined;
|
|
92
|
+
token?: string | undefined;
|
|
93
|
+
}, {
|
|
94
|
+
topic: string;
|
|
95
|
+
server?: string | undefined;
|
|
96
|
+
replyTopic?: string | undefined;
|
|
97
|
+
token?: string | undefined;
|
|
98
|
+
}>;
|
|
99
|
+
export declare const EmailConfigSchema: z.ZodObject<{
|
|
100
|
+
smtp: z.ZodObject<{
|
|
101
|
+
host: z.ZodString;
|
|
102
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
103
|
+
/** TLS from the start. Default: true on port 465, otherwise STARTTLS. */
|
|
104
|
+
secure: z.ZodOptional<z.ZodBoolean>;
|
|
105
|
+
user: z.ZodOptional<z.ZodString>;
|
|
106
|
+
pass: z.ZodOptional<z.ZodString>;
|
|
107
|
+
}, "strict", z.ZodTypeAny, {
|
|
108
|
+
host: string;
|
|
109
|
+
port: number;
|
|
110
|
+
secure?: boolean | undefined;
|
|
111
|
+
user?: string | undefined;
|
|
112
|
+
pass?: string | undefined;
|
|
113
|
+
}, {
|
|
114
|
+
host: string;
|
|
115
|
+
port?: number | undefined;
|
|
116
|
+
secure?: boolean | undefined;
|
|
117
|
+
user?: string | undefined;
|
|
118
|
+
pass?: string | undefined;
|
|
119
|
+
}>;
|
|
120
|
+
from: z.ZodString;
|
|
121
|
+
to: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "atleastone">]>;
|
|
122
|
+
on: z.ZodDefault<z.ZodArray<z.ZodEnum<["pending", "blocked", "approved", "denied", "timeout", "undeliverable"]>, "atleastone">>;
|
|
123
|
+
}, "strict", z.ZodTypeAny, {
|
|
124
|
+
smtp: {
|
|
125
|
+
host: string;
|
|
126
|
+
port: number;
|
|
127
|
+
secure?: boolean | undefined;
|
|
128
|
+
user?: string | undefined;
|
|
129
|
+
pass?: string | undefined;
|
|
130
|
+
};
|
|
131
|
+
from: string;
|
|
132
|
+
to: string | [string, ...string[]];
|
|
133
|
+
on: ["pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable", ...("pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable")[]];
|
|
134
|
+
}, {
|
|
135
|
+
smtp: {
|
|
136
|
+
host: string;
|
|
137
|
+
port?: number | undefined;
|
|
138
|
+
secure?: boolean | undefined;
|
|
139
|
+
user?: string | undefined;
|
|
140
|
+
pass?: string | undefined;
|
|
141
|
+
};
|
|
142
|
+
from: string;
|
|
143
|
+
to: string | [string, ...string[]];
|
|
144
|
+
on?: ["pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable", ...("pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable")[]] | undefined;
|
|
145
|
+
}>;
|
|
146
|
+
export declare const ApprovalsConfigSchema: z.ZodObject<{
|
|
147
|
+
/**
|
|
148
|
+
* How long a call waits for an answer; no answer means deny. Many MCP
|
|
149
|
+
* clients give up on a request after 60 seconds, hence the default.
|
|
150
|
+
*/
|
|
151
|
+
timeoutSeconds: z.ZodDefault<z.ZodNumber>;
|
|
152
|
+
ntfy: z.ZodOptional<z.ZodObject<{
|
|
153
|
+
server: z.ZodDefault<z.ZodString>;
|
|
154
|
+
/** Topic approval requests are sent to. Anyone who can read it can approve: keep it secret. */
|
|
155
|
+
topic: z.ZodString;
|
|
156
|
+
/** Topic answers are posted to. Default: `<topic>-reply`. */
|
|
157
|
+
replyTopic: z.ZodOptional<z.ZodString>;
|
|
158
|
+
token: z.ZodOptional<z.ZodString>;
|
|
159
|
+
}, "strict", z.ZodTypeAny, {
|
|
160
|
+
server: string;
|
|
161
|
+
topic: string;
|
|
162
|
+
replyTopic?: string | undefined;
|
|
163
|
+
token?: string | undefined;
|
|
164
|
+
}, {
|
|
165
|
+
topic: string;
|
|
166
|
+
server?: string | undefined;
|
|
167
|
+
replyTopic?: string | undefined;
|
|
168
|
+
token?: string | undefined;
|
|
169
|
+
}>>;
|
|
170
|
+
email: z.ZodOptional<z.ZodObject<{
|
|
171
|
+
smtp: z.ZodObject<{
|
|
172
|
+
host: z.ZodString;
|
|
173
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
174
|
+
/** TLS from the start. Default: true on port 465, otherwise STARTTLS. */
|
|
175
|
+
secure: z.ZodOptional<z.ZodBoolean>;
|
|
176
|
+
user: z.ZodOptional<z.ZodString>;
|
|
177
|
+
pass: z.ZodOptional<z.ZodString>;
|
|
178
|
+
}, "strict", z.ZodTypeAny, {
|
|
179
|
+
host: string;
|
|
180
|
+
port: number;
|
|
181
|
+
secure?: boolean | undefined;
|
|
182
|
+
user?: string | undefined;
|
|
183
|
+
pass?: string | undefined;
|
|
184
|
+
}, {
|
|
185
|
+
host: string;
|
|
186
|
+
port?: number | undefined;
|
|
187
|
+
secure?: boolean | undefined;
|
|
188
|
+
user?: string | undefined;
|
|
189
|
+
pass?: string | undefined;
|
|
190
|
+
}>;
|
|
191
|
+
from: z.ZodString;
|
|
192
|
+
to: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "atleastone">]>;
|
|
193
|
+
on: z.ZodDefault<z.ZodArray<z.ZodEnum<["pending", "blocked", "approved", "denied", "timeout", "undeliverable"]>, "atleastone">>;
|
|
194
|
+
}, "strict", z.ZodTypeAny, {
|
|
195
|
+
smtp: {
|
|
196
|
+
host: string;
|
|
197
|
+
port: number;
|
|
198
|
+
secure?: boolean | undefined;
|
|
199
|
+
user?: string | undefined;
|
|
200
|
+
pass?: string | undefined;
|
|
201
|
+
};
|
|
202
|
+
from: string;
|
|
203
|
+
to: string | [string, ...string[]];
|
|
204
|
+
on: ["pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable", ...("pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable")[]];
|
|
205
|
+
}, {
|
|
206
|
+
smtp: {
|
|
207
|
+
host: string;
|
|
208
|
+
port?: number | undefined;
|
|
209
|
+
secure?: boolean | undefined;
|
|
210
|
+
user?: string | undefined;
|
|
211
|
+
pass?: string | undefined;
|
|
212
|
+
};
|
|
213
|
+
from: string;
|
|
214
|
+
to: string | [string, ...string[]];
|
|
215
|
+
on?: ["pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable", ...("pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable")[]] | undefined;
|
|
216
|
+
}>>;
|
|
217
|
+
}, "strict", z.ZodTypeAny, {
|
|
218
|
+
timeoutSeconds: number;
|
|
219
|
+
ntfy?: {
|
|
220
|
+
server: string;
|
|
221
|
+
topic: string;
|
|
222
|
+
replyTopic?: string | undefined;
|
|
223
|
+
token?: string | undefined;
|
|
224
|
+
} | undefined;
|
|
225
|
+
email?: {
|
|
226
|
+
smtp: {
|
|
227
|
+
host: string;
|
|
228
|
+
port: number;
|
|
229
|
+
secure?: boolean | undefined;
|
|
230
|
+
user?: string | undefined;
|
|
231
|
+
pass?: string | undefined;
|
|
232
|
+
};
|
|
233
|
+
from: string;
|
|
234
|
+
to: string | [string, ...string[]];
|
|
235
|
+
on: ["pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable", ...("pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable")[]];
|
|
236
|
+
} | undefined;
|
|
237
|
+
}, {
|
|
238
|
+
ntfy?: {
|
|
239
|
+
topic: string;
|
|
240
|
+
server?: string | undefined;
|
|
241
|
+
replyTopic?: string | undefined;
|
|
242
|
+
token?: string | undefined;
|
|
243
|
+
} | undefined;
|
|
244
|
+
email?: {
|
|
245
|
+
smtp: {
|
|
246
|
+
host: string;
|
|
247
|
+
port?: number | undefined;
|
|
248
|
+
secure?: boolean | undefined;
|
|
249
|
+
user?: string | undefined;
|
|
250
|
+
pass?: string | undefined;
|
|
251
|
+
};
|
|
252
|
+
from: string;
|
|
253
|
+
to: string | [string, ...string[]];
|
|
254
|
+
on?: ["pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable", ...("pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable")[]] | undefined;
|
|
255
|
+
} | undefined;
|
|
256
|
+
timeoutSeconds?: number | undefined;
|
|
257
|
+
}>;
|
|
258
|
+
export type ApprovalsConfig = z.infer<typeof ApprovalsConfigSchema>;
|
|
73
259
|
export declare const GatewayConfigSchema: z.ZodObject<{
|
|
74
260
|
upstreams: z.ZodEffects<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodObject<{
|
|
75
261
|
command: z.ZodString;
|
|
@@ -147,6 +333,124 @@ export declare const GatewayConfigSchema: z.ZodObject<{
|
|
|
147
333
|
}>>;
|
|
148
334
|
/** Path of a JSONL audit log. Relative paths are resolved against the config file's directory. */
|
|
149
335
|
audit: z.ZodOptional<z.ZodString>;
|
|
336
|
+
/**
|
|
337
|
+
* `active` (default) enforces the policy. `audit` stops and changes nothing, and
|
|
338
|
+
* logs what would have been stopped: for trying a policy out safely.
|
|
339
|
+
*/
|
|
340
|
+
mode: z.ZodDefault<z.ZodEnum<["active", "audit"]>>;
|
|
341
|
+
/** Human approvals for "ask" decisions. Without an answering channel, "ask" blocks. */
|
|
342
|
+
approvals: z.ZodOptional<z.ZodObject<{
|
|
343
|
+
/**
|
|
344
|
+
* How long a call waits for an answer; no answer means deny. Many MCP
|
|
345
|
+
* clients give up on a request after 60 seconds, hence the default.
|
|
346
|
+
*/
|
|
347
|
+
timeoutSeconds: z.ZodDefault<z.ZodNumber>;
|
|
348
|
+
ntfy: z.ZodOptional<z.ZodObject<{
|
|
349
|
+
server: z.ZodDefault<z.ZodString>;
|
|
350
|
+
/** Topic approval requests are sent to. Anyone who can read it can approve: keep it secret. */
|
|
351
|
+
topic: z.ZodString;
|
|
352
|
+
/** Topic answers are posted to. Default: `<topic>-reply`. */
|
|
353
|
+
replyTopic: z.ZodOptional<z.ZodString>;
|
|
354
|
+
token: z.ZodOptional<z.ZodString>;
|
|
355
|
+
}, "strict", z.ZodTypeAny, {
|
|
356
|
+
server: string;
|
|
357
|
+
topic: string;
|
|
358
|
+
replyTopic?: string | undefined;
|
|
359
|
+
token?: string | undefined;
|
|
360
|
+
}, {
|
|
361
|
+
topic: string;
|
|
362
|
+
server?: string | undefined;
|
|
363
|
+
replyTopic?: string | undefined;
|
|
364
|
+
token?: string | undefined;
|
|
365
|
+
}>>;
|
|
366
|
+
email: z.ZodOptional<z.ZodObject<{
|
|
367
|
+
smtp: z.ZodObject<{
|
|
368
|
+
host: z.ZodString;
|
|
369
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
370
|
+
/** TLS from the start. Default: true on port 465, otherwise STARTTLS. */
|
|
371
|
+
secure: z.ZodOptional<z.ZodBoolean>;
|
|
372
|
+
user: z.ZodOptional<z.ZodString>;
|
|
373
|
+
pass: z.ZodOptional<z.ZodString>;
|
|
374
|
+
}, "strict", z.ZodTypeAny, {
|
|
375
|
+
host: string;
|
|
376
|
+
port: number;
|
|
377
|
+
secure?: boolean | undefined;
|
|
378
|
+
user?: string | undefined;
|
|
379
|
+
pass?: string | undefined;
|
|
380
|
+
}, {
|
|
381
|
+
host: string;
|
|
382
|
+
port?: number | undefined;
|
|
383
|
+
secure?: boolean | undefined;
|
|
384
|
+
user?: string | undefined;
|
|
385
|
+
pass?: string | undefined;
|
|
386
|
+
}>;
|
|
387
|
+
from: z.ZodString;
|
|
388
|
+
to: z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "atleastone">]>;
|
|
389
|
+
on: z.ZodDefault<z.ZodArray<z.ZodEnum<["pending", "blocked", "approved", "denied", "timeout", "undeliverable"]>, "atleastone">>;
|
|
390
|
+
}, "strict", z.ZodTypeAny, {
|
|
391
|
+
smtp: {
|
|
392
|
+
host: string;
|
|
393
|
+
port: number;
|
|
394
|
+
secure?: boolean | undefined;
|
|
395
|
+
user?: string | undefined;
|
|
396
|
+
pass?: string | undefined;
|
|
397
|
+
};
|
|
398
|
+
from: string;
|
|
399
|
+
to: string | [string, ...string[]];
|
|
400
|
+
on: ["pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable", ...("pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable")[]];
|
|
401
|
+
}, {
|
|
402
|
+
smtp: {
|
|
403
|
+
host: string;
|
|
404
|
+
port?: number | undefined;
|
|
405
|
+
secure?: boolean | undefined;
|
|
406
|
+
user?: string | undefined;
|
|
407
|
+
pass?: string | undefined;
|
|
408
|
+
};
|
|
409
|
+
from: string;
|
|
410
|
+
to: string | [string, ...string[]];
|
|
411
|
+
on?: ["pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable", ...("pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable")[]] | undefined;
|
|
412
|
+
}>>;
|
|
413
|
+
}, "strict", z.ZodTypeAny, {
|
|
414
|
+
timeoutSeconds: number;
|
|
415
|
+
ntfy?: {
|
|
416
|
+
server: string;
|
|
417
|
+
topic: string;
|
|
418
|
+
replyTopic?: string | undefined;
|
|
419
|
+
token?: string | undefined;
|
|
420
|
+
} | undefined;
|
|
421
|
+
email?: {
|
|
422
|
+
smtp: {
|
|
423
|
+
host: string;
|
|
424
|
+
port: number;
|
|
425
|
+
secure?: boolean | undefined;
|
|
426
|
+
user?: string | undefined;
|
|
427
|
+
pass?: string | undefined;
|
|
428
|
+
};
|
|
429
|
+
from: string;
|
|
430
|
+
to: string | [string, ...string[]];
|
|
431
|
+
on: ["pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable", ...("pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable")[]];
|
|
432
|
+
} | undefined;
|
|
433
|
+
}, {
|
|
434
|
+
ntfy?: {
|
|
435
|
+
topic: string;
|
|
436
|
+
server?: string | undefined;
|
|
437
|
+
replyTopic?: string | undefined;
|
|
438
|
+
token?: string | undefined;
|
|
439
|
+
} | undefined;
|
|
440
|
+
email?: {
|
|
441
|
+
smtp: {
|
|
442
|
+
host: string;
|
|
443
|
+
port?: number | undefined;
|
|
444
|
+
secure?: boolean | undefined;
|
|
445
|
+
user?: string | undefined;
|
|
446
|
+
pass?: string | undefined;
|
|
447
|
+
};
|
|
448
|
+
from: string;
|
|
449
|
+
to: string | [string, ...string[]];
|
|
450
|
+
on?: ["pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable", ...("pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable")[]] | undefined;
|
|
451
|
+
} | undefined;
|
|
452
|
+
timeoutSeconds?: number | undefined;
|
|
453
|
+
}>>;
|
|
150
454
|
/** Timeout for each interceptor invocation, in milliseconds. */
|
|
151
455
|
interceptorTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
152
456
|
}, "strict", z.ZodTypeAny, {
|
|
@@ -159,6 +463,7 @@ export declare const GatewayConfigSchema: z.ZodObject<{
|
|
|
159
463
|
url: string;
|
|
160
464
|
headers: Record<string, string>;
|
|
161
465
|
}>;
|
|
466
|
+
mode: "audit" | "active";
|
|
162
467
|
interceptorTimeoutMs: number;
|
|
163
468
|
interceptors?: {
|
|
164
469
|
command: string;
|
|
@@ -167,6 +472,27 @@ export declare const GatewayConfigSchema: z.ZodObject<{
|
|
|
167
472
|
cwd?: string | undefined;
|
|
168
473
|
} | undefined;
|
|
169
474
|
audit?: string | undefined;
|
|
475
|
+
approvals?: {
|
|
476
|
+
timeoutSeconds: number;
|
|
477
|
+
ntfy?: {
|
|
478
|
+
server: string;
|
|
479
|
+
topic: string;
|
|
480
|
+
replyTopic?: string | undefined;
|
|
481
|
+
token?: string | undefined;
|
|
482
|
+
} | undefined;
|
|
483
|
+
email?: {
|
|
484
|
+
smtp: {
|
|
485
|
+
host: string;
|
|
486
|
+
port: number;
|
|
487
|
+
secure?: boolean | undefined;
|
|
488
|
+
user?: string | undefined;
|
|
489
|
+
pass?: string | undefined;
|
|
490
|
+
};
|
|
491
|
+
from: string;
|
|
492
|
+
to: string | [string, ...string[]];
|
|
493
|
+
on: ["pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable", ...("pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable")[]];
|
|
494
|
+
} | undefined;
|
|
495
|
+
} | undefined;
|
|
170
496
|
}, {
|
|
171
497
|
upstreams: Record<string, {
|
|
172
498
|
command: string;
|
|
@@ -184,6 +510,28 @@ export declare const GatewayConfigSchema: z.ZodObject<{
|
|
|
184
510
|
cwd?: string | undefined;
|
|
185
511
|
} | undefined;
|
|
186
512
|
audit?: string | undefined;
|
|
513
|
+
mode?: "audit" | "active" | undefined;
|
|
514
|
+
approvals?: {
|
|
515
|
+
ntfy?: {
|
|
516
|
+
topic: string;
|
|
517
|
+
server?: string | undefined;
|
|
518
|
+
replyTopic?: string | undefined;
|
|
519
|
+
token?: string | undefined;
|
|
520
|
+
} | undefined;
|
|
521
|
+
email?: {
|
|
522
|
+
smtp: {
|
|
523
|
+
host: string;
|
|
524
|
+
port?: number | undefined;
|
|
525
|
+
secure?: boolean | undefined;
|
|
526
|
+
user?: string | undefined;
|
|
527
|
+
pass?: string | undefined;
|
|
528
|
+
};
|
|
529
|
+
from: string;
|
|
530
|
+
to: string | [string, ...string[]];
|
|
531
|
+
on?: ["pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable", ...("pending" | "blocked" | "approved" | "denied" | "timeout" | "undeliverable")[]] | undefined;
|
|
532
|
+
} | undefined;
|
|
533
|
+
timeoutSeconds?: number | undefined;
|
|
534
|
+
} | undefined;
|
|
187
535
|
interceptorTimeoutMs?: number | undefined;
|
|
188
536
|
}>;
|
|
189
537
|
export type GatewayConfig = z.infer<typeof GatewayConfigSchema>;
|
|
@@ -195,5 +543,7 @@ export declare class EnvExpansionError extends Error {
|
|
|
195
543
|
/** Replace `${VAR}` with values from `env`. `$${VAR}` keeps a literal `${VAR}`. */
|
|
196
544
|
export declare function expandEnv(value: string, env: NodeJS.ProcessEnv, where: string): string;
|
|
197
545
|
export declare function expandUpstream<T extends Upstream>(id: string, u: T, env: NodeJS.ProcessEnv): T;
|
|
546
|
+
/** Expand `${VAR}` in every string of the approvals section. */
|
|
547
|
+
export declare function expandApprovals(a: ApprovalsConfig, env: NodeJS.ProcessEnv): ApprovalsConfig;
|
|
198
548
|
export declare function isHttpUpstream(u: Upstream): u is HttpUpstream;
|
|
199
549
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;EAOrB,CAAC;AAEZ,eAAO,MAAM,kBAAkB;;;;;;;;;EAKpB,CAAC;AAEZ,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;IAAqD,CAAC;AACjF,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC9D,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAEtD,eAAO,MAAM,gBAAgB;;IAGzB,+FAA+F;;IAE/F,6DAA6D;;;;;;;;;;;;;EAItD,CAAC;AAEZ,eAAO,MAAM,iBAAiB;;;;QAMtB,yEAAyE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAUtE,CAAC;AAEZ,eAAO,MAAM,qBAAqB;IAE9B;;;OAGG;;;;QA/BH,+FAA+F;;QAE/F,6DAA6D;;;;;;;;;;;;;;;;;;YAYzD,yEAAyE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsBtE,CAAC;AACZ,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAQ5B,8GAA8G;;;;;;;;;;;;;;;;;IAE9G,kGAAkG;;IAElG;;;OAGG;;IAEH,uFAAuF;;QA5BvF;;;WAGG;;;;YA/BH,+FAA+F;;YAE/F,6DAA6D;;;;;;;;;;;;;;;;;;gBAYzD,yEAAyE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA4C7E,gEAAgE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAGzD,CAAC;AACZ,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAEhE,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC,qBAAa,iBAAkB,SAAQ,KAAK;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM;gBAAhB,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAIrD;AAED,mFAAmF;AACnF,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAOtF;AAMD,wBAAgB,cAAc,CAAC,CAAC,SAAS,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,CAAC,CAY9F;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAAC,CAAC,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,CAAC,UAAU,GAAG,eAAe,CAQ3F;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,QAAQ,GAAG,CAAC,IAAI,YAAY,CAE7D"}
|
package/dist/config.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* gateway:
|
|
5
5
|
* audit: ./adtl-audit.jsonl # optional JSONL audit log
|
|
6
|
+
* mode: audit # optional: log what would be stopped, stop nothing
|
|
6
7
|
* upstreams:
|
|
7
8
|
* github: # id must match `servers.github` in the label config
|
|
8
9
|
* command: npx
|
|
@@ -11,11 +12,19 @@
|
|
|
11
12
|
* docs:
|
|
12
13
|
* url: https://example.com/mcp
|
|
13
14
|
* headers: { Authorization: "Bearer ${DOCS_TOKEN}" }
|
|
15
|
+
* approvals: # optional: make "ask" really ask
|
|
16
|
+
* timeoutSeconds: 50
|
|
17
|
+
* ntfy: { topic: "${ADTL_NTFY_TOPIC}" }
|
|
18
|
+
* email:
|
|
19
|
+
* smtp: { host: smtp.example.com, port: 465, user: "${SMTP_USER}", pass: "${SMTP_PASS}" }
|
|
20
|
+
* from: adtl@example.com
|
|
21
|
+
* to: you@example.com
|
|
14
22
|
*
|
|
15
|
-
* `${VAR}` in command, args, env, cwd, url
|
|
16
|
-
* gateway's environment. A missing variable is a config error.
|
|
23
|
+
* `${VAR}` in command, args, env, cwd, url, headers and approval settings is
|
|
24
|
+
* replaced from the gateway's environment. A missing variable is a config error.
|
|
17
25
|
*/
|
|
18
26
|
import { z } from "zod";
|
|
27
|
+
import { EMAIL_EVENTS } from "./email.js";
|
|
19
28
|
const UPSTREAM_ID = /^[A-Za-z0-9-]+$/;
|
|
20
29
|
export const StdioUpstreamSchema = z
|
|
21
30
|
.object({
|
|
@@ -32,6 +41,44 @@ export const HttpUpstreamSchema = z
|
|
|
32
41
|
})
|
|
33
42
|
.strict();
|
|
34
43
|
export const UpstreamSchema = z.union([StdioUpstreamSchema, HttpUpstreamSchema]);
|
|
44
|
+
export const NtfyConfigSchema = z
|
|
45
|
+
.object({
|
|
46
|
+
server: z.string().min(1).default("https://ntfy.sh"),
|
|
47
|
+
/** Topic approval requests are sent to. Anyone who can read it can approve: keep it secret. */
|
|
48
|
+
topic: z.string().min(1),
|
|
49
|
+
/** Topic answers are posted to. Default: `<topic>-reply`. */
|
|
50
|
+
replyTopic: z.string().min(1).optional(),
|
|
51
|
+
token: z.string().min(1).optional(),
|
|
52
|
+
})
|
|
53
|
+
.strict();
|
|
54
|
+
export const EmailConfigSchema = z
|
|
55
|
+
.object({
|
|
56
|
+
smtp: z
|
|
57
|
+
.object({
|
|
58
|
+
host: z.string().min(1),
|
|
59
|
+
port: z.number().int().positive().default(587),
|
|
60
|
+
/** TLS from the start. Default: true on port 465, otherwise STARTTLS. */
|
|
61
|
+
secure: z.boolean().optional(),
|
|
62
|
+
user: z.string().min(1).optional(),
|
|
63
|
+
pass: z.string().optional(),
|
|
64
|
+
})
|
|
65
|
+
.strict(),
|
|
66
|
+
from: z.string().min(1),
|
|
67
|
+
to: z.union([z.string().min(1), z.array(z.string().min(1)).nonempty()]),
|
|
68
|
+
on: z.array(z.enum(EMAIL_EVENTS)).nonempty().default(["pending", "blocked"]),
|
|
69
|
+
})
|
|
70
|
+
.strict();
|
|
71
|
+
export const ApprovalsConfigSchema = z
|
|
72
|
+
.object({
|
|
73
|
+
/**
|
|
74
|
+
* How long a call waits for an answer; no answer means deny. Many MCP
|
|
75
|
+
* clients give up on a request after 60 seconds, hence the default.
|
|
76
|
+
*/
|
|
77
|
+
timeoutSeconds: z.number().int().positive().max(3600).default(50),
|
|
78
|
+
ntfy: NtfyConfigSchema.optional(),
|
|
79
|
+
email: EmailConfigSchema.optional(),
|
|
80
|
+
})
|
|
81
|
+
.strict();
|
|
35
82
|
export const GatewayConfigSchema = z
|
|
36
83
|
.object({
|
|
37
84
|
upstreams: z
|
|
@@ -44,6 +91,13 @@ export const GatewayConfigSchema = z
|
|
|
44
91
|
interceptors: StdioUpstreamSchema.optional(),
|
|
45
92
|
/** Path of a JSONL audit log. Relative paths are resolved against the config file's directory. */
|
|
46
93
|
audit: z.string().min(1).optional(),
|
|
94
|
+
/**
|
|
95
|
+
* `active` (default) enforces the policy. `audit` stops and changes nothing, and
|
|
96
|
+
* logs what would have been stopped: for trying a policy out safely.
|
|
97
|
+
*/
|
|
98
|
+
mode: z.enum(["active", "audit"]).default("active"),
|
|
99
|
+
/** Human approvals for "ask" decisions. Without an answering channel, "ask" blocks. */
|
|
100
|
+
approvals: ApprovalsConfigSchema.optional(),
|
|
47
101
|
/** Timeout for each interceptor invocation, in milliseconds. */
|
|
48
102
|
interceptorTimeoutMs: z.number().int().positive().default(5000),
|
|
49
103
|
})
|
|
@@ -84,6 +138,19 @@ export function expandUpstream(id, u, env) {
|
|
|
84
138
|
...(u.cwd !== undefined ? { cwd: expandEnv(u.cwd, env, `${where}.cwd`) } : {}),
|
|
85
139
|
};
|
|
86
140
|
}
|
|
141
|
+
/** Expand `${VAR}` in every string of the approvals section. */
|
|
142
|
+
export function expandApprovals(a, env) {
|
|
143
|
+
const walk = (v, where) => {
|
|
144
|
+
if (typeof v === "string")
|
|
145
|
+
return expandEnv(v, env, where);
|
|
146
|
+
if (Array.isArray(v))
|
|
147
|
+
return v.map((x, i) => walk(x, `${where}[${i}]`));
|
|
148
|
+
if (v && typeof v === "object")
|
|
149
|
+
return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, walk(x, `${where}.${k}`)]));
|
|
150
|
+
return v;
|
|
151
|
+
};
|
|
152
|
+
return walk(a, "gateway.approvals");
|
|
153
|
+
}
|
|
87
154
|
export function isHttpUpstream(u) {
|
|
88
155
|
return "url" in u;
|
|
89
156
|
}
|
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/email.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ApprovalEvent, Notifier } from "./approvals.js";
|
|
2
|
+
export declare const EMAIL_EVENTS: readonly ["pending", "blocked", "approved", "denied", "timeout", "undeliverable"];
|
|
3
|
+
export type EmailEvent = (typeof EMAIL_EVENTS)[number];
|
|
4
|
+
export interface MailSender {
|
|
5
|
+
sendMail(mail: {
|
|
6
|
+
from: string;
|
|
7
|
+
to: string[];
|
|
8
|
+
subject: string;
|
|
9
|
+
text: string;
|
|
10
|
+
}): Promise<unknown>;
|
|
11
|
+
}
|
|
12
|
+
export interface EmailOptions {
|
|
13
|
+
from: string;
|
|
14
|
+
to: string[];
|
|
15
|
+
/** Which events send an email. */
|
|
16
|
+
on: EmailEvent[];
|
|
17
|
+
/** SMTP settings, used unless `sender` is given. */
|
|
18
|
+
smtp?: {
|
|
19
|
+
host: string;
|
|
20
|
+
port: number;
|
|
21
|
+
secure?: boolean;
|
|
22
|
+
user?: string;
|
|
23
|
+
pass?: string;
|
|
24
|
+
};
|
|
25
|
+
sender?: MailSender;
|
|
26
|
+
}
|
|
27
|
+
export declare class EmailNotifier implements Notifier {
|
|
28
|
+
private readonly opts;
|
|
29
|
+
readonly name = "email";
|
|
30
|
+
private readonly sender;
|
|
31
|
+
constructor(opts: EmailOptions);
|
|
32
|
+
notify(event: ApprovalEvent): Promise<void>;
|
|
33
|
+
private compose;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=email.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../src/email.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE9D,eAAO,MAAM,YAAY,mFAAoF,CAAC;AAC9G,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAEvD,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACjG;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,EAAE,CAAC;IACb,kCAAkC;IAClC,EAAE,EAAE,UAAU,EAAE,CAAC;IACjB,oDAAoD;IACpD,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtF,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,qBAAa,aAAc,YAAW,QAAQ;IAIhC,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,QAAQ,CAAC,IAAI,WAAW;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;gBAEP,IAAI,EAAE,YAAY;IAgBzC,MAAM,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjD,OAAO,CAAC,OAAO;CAwBhB"}
|
package/dist/email.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Email notices over SMTP. Notify only, on purpose: emails never contain
|
|
3
|
+
* approve links, because mail security scanners open links automatically and
|
|
4
|
+
* would approve calls by themselves. Approving happens on the push channel.
|
|
5
|
+
*
|
|
6
|
+
* Emails name the tool, server and reason, never arguments or results.
|
|
7
|
+
*/
|
|
8
|
+
import nodemailer from "nodemailer";
|
|
9
|
+
export const EMAIL_EVENTS = ["pending", "blocked", "approved", "denied", "timeout", "undeliverable"];
|
|
10
|
+
export class EmailNotifier {
|
|
11
|
+
opts;
|
|
12
|
+
name = "email";
|
|
13
|
+
sender;
|
|
14
|
+
constructor(opts) {
|
|
15
|
+
this.opts = opts;
|
|
16
|
+
if (opts.sender) {
|
|
17
|
+
this.sender = opts.sender;
|
|
18
|
+
}
|
|
19
|
+
else if (opts.smtp) {
|
|
20
|
+
const { host, port, secure, user, pass } = opts.smtp;
|
|
21
|
+
this.sender = nodemailer.createTransport({
|
|
22
|
+
host,
|
|
23
|
+
port,
|
|
24
|
+
secure: secure ?? port === 465,
|
|
25
|
+
...(user !== undefined ? { auth: { user, pass } } : {}),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
throw new Error("EmailNotifier needs smtp settings or a sender");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
async notify(event) {
|
|
33
|
+
const kind = event.kind === "resolved" ? event.result.outcome : event.kind;
|
|
34
|
+
if (!this.opts.on.includes(kind))
|
|
35
|
+
return;
|
|
36
|
+
const { subject, text } = this.compose(event);
|
|
37
|
+
await this.sender.sendMail({ from: this.opts.from, to: this.opts.to, subject, text });
|
|
38
|
+
}
|
|
39
|
+
compose(event) {
|
|
40
|
+
const footer = "\n\n-- \nSent by ADTL (adtl-gateway). This email never contains approve links; approve on your push channel.";
|
|
41
|
+
if (event.kind === "blocked") {
|
|
42
|
+
return {
|
|
43
|
+
subject: `ADTL blocked ${event.server}.${event.tool}`,
|
|
44
|
+
text: `ADTL blocked a call to ${event.server}.${event.tool}.\n\nReason: ${event.reason}\nRule: ${event.matched.join(", ") || "default"}\nSession: ${event.sessionId}${footer}`,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const r = event.request;
|
|
48
|
+
const subject = `${r.server}.${r.tool}`;
|
|
49
|
+
if (event.kind === "pending") {
|
|
50
|
+
return {
|
|
51
|
+
subject: `ADTL: approval needed for ${subject}`,
|
|
52
|
+
text: `An agent wants to call ${subject} and ADTL needs your approval.\n\nReason: ${r.reason}\nRule: ${r.matched.join(", ") || "default"}\n` +
|
|
53
|
+
`Session: ${r.sessionId}\nExpires: ${r.expiresAt.toISOString()} (no answer means deny)${footer}`,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const res = event.result;
|
|
57
|
+
return {
|
|
58
|
+
subject: `ADTL: ${subject} ${res.outcome}`,
|
|
59
|
+
text: `The approval request for ${subject} was ${res.outcome}${res.channel ? ` via ${res.channel}` : ""} after ${Math.round(res.waitedMs / 1000)}s.\n\nReason it was asked: ${r.reason}\nSession: ${r.sessionId}${footer}`,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=email.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email.js","sourceRoot":"","sources":["../src/email.ts"],"names":[],"mappings":"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"}
|