@adtl/gateway 0.1.1 → 0.3.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 +57 -5
- 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 +12 -2
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js +1 -1
- package/dist/audit.js.map +1 -1
- package/dist/cli.js +46 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +346 -4
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +63 -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 +33 -3
- package/dist/gateway.d.ts.map +1 -1
- package/dist/gateway.js +263 -23
- package/dist/gateway.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/init/index.d.ts +4 -0
- package/dist/init/index.d.ts.map +1 -0
- package/dist/init/index.js +4 -0
- package/dist/init/index.js.map +1 -0
- package/dist/init/presets.d.ts +30 -0
- package/dist/init/presets.d.ts.map +1 -0
- package/dist/init/presets.js +34 -0
- package/dist/init/presets.js.map +1 -0
- package/dist/init/run.d.ts +18 -0
- package/dist/init/run.d.ts.map +1 -0
- package/dist/init/run.js +60 -0
- package/dist/init/run.js.map +1 -0
- package/dist/init/suggest.d.ts +50 -0
- package/dist/init/suggest.d.ts.map +1 -0
- package/dist/init/suggest.js +82 -0
- package/dist/init/suggest.js.map +1 -0
- package/dist/invoker.d.ts.map +1 -1
- package/dist/invoker.js +4 -2
- 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 +6 -1
- package/dist/startup.d.ts.map +1 -1
- package/dist/startup.js +37 -5
- package/dist/startup.js.map +1 -1
- package/package.json +4 -3
- package/src/approvals.ts +219 -0
- package/src/audit.ts +8 -3
- package/src/cli.ts +41 -1
- package/src/config.ts +65 -2
- package/src/email.ts +79 -0
- package/src/gateway.ts +324 -22
- package/src/index.ts +4 -0
- package/src/init/index.ts +3 -0
- package/src/init/presets.ts +64 -0
- package/src/init/run.ts +79 -0
- package/src/init/suggest.ts +127 -0
- package/src/invoker.ts +3 -2
- package/src/ntfy.ts +154 -0
- package/src/startup.ts +35 -4
package/dist/config.d.ts
CHANGED
|
@@ -12,9 +12,16 @@
|
|
|
12
12
|
* docs:
|
|
13
13
|
* url: https://example.com/mcp
|
|
14
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
|
|
15
22
|
*
|
|
16
|
-
* `${VAR}` in command, args, env, cwd, url
|
|
17
|
-
* 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.
|
|
18
25
|
*/
|
|
19
26
|
import { z } from "zod";
|
|
20
27
|
export declare const StdioUpstreamSchema: z.ZodObject<{
|
|
@@ -71,6 +78,184 @@ export declare const UpstreamSchema: z.ZodUnion<[z.ZodObject<{
|
|
|
71
78
|
export type StdioUpstream = z.infer<typeof StdioUpstreamSchema>;
|
|
72
79
|
export type HttpUpstream = z.infer<typeof HttpUpstreamSchema>;
|
|
73
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>;
|
|
74
259
|
export declare const GatewayConfigSchema: z.ZodObject<{
|
|
75
260
|
upstreams: z.ZodEffects<z.ZodEffects<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodObject<{
|
|
76
261
|
command: z.ZodString;
|
|
@@ -153,6 +338,119 @@ export declare const GatewayConfigSchema: z.ZodObject<{
|
|
|
153
338
|
* logs what would have been stopped: for trying a policy out safely.
|
|
154
339
|
*/
|
|
155
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
|
+
}>>;
|
|
156
454
|
/** Timeout for each interceptor invocation, in milliseconds. */
|
|
157
455
|
interceptorTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
158
456
|
}, "strict", z.ZodTypeAny, {
|
|
@@ -167,13 +465,34 @@ export declare const GatewayConfigSchema: z.ZodObject<{
|
|
|
167
465
|
}>;
|
|
168
466
|
mode: "audit" | "active";
|
|
169
467
|
interceptorTimeoutMs: number;
|
|
170
|
-
audit?: string | undefined;
|
|
171
468
|
interceptors?: {
|
|
172
469
|
command: string;
|
|
173
470
|
args: string[];
|
|
174
471
|
env: Record<string, string>;
|
|
175
472
|
cwd?: string | undefined;
|
|
176
473
|
} | undefined;
|
|
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;
|
|
177
496
|
}, {
|
|
178
497
|
upstreams: Record<string, {
|
|
179
498
|
command: string;
|
|
@@ -184,14 +503,35 @@ export declare const GatewayConfigSchema: z.ZodObject<{
|
|
|
184
503
|
url: string;
|
|
185
504
|
headers?: Record<string, string> | undefined;
|
|
186
505
|
}>;
|
|
187
|
-
audit?: string | undefined;
|
|
188
506
|
interceptors?: {
|
|
189
507
|
command: string;
|
|
190
508
|
args?: string[] | undefined;
|
|
191
509
|
env?: Record<string, string> | undefined;
|
|
192
510
|
cwd?: string | undefined;
|
|
193
511
|
} | undefined;
|
|
512
|
+
audit?: string | undefined;
|
|
194
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;
|
|
195
535
|
interceptorTimeoutMs?: number | undefined;
|
|
196
536
|
}>;
|
|
197
537
|
export type GatewayConfig = z.infer<typeof GatewayConfigSchema>;
|
|
@@ -203,5 +543,7 @@ export declare class EnvExpansionError extends Error {
|
|
|
203
543
|
/** Replace `${VAR}` with values from `env`. `$${VAR}` keeps a literal `${VAR}`. */
|
|
204
544
|
export declare function expandEnv(value: string, env: NodeJS.ProcessEnv, where: string): string;
|
|
205
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;
|
|
206
548
|
export declare function isHttpUpstream(u: Upstream): u is HttpUpstream;
|
|
207
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
|
@@ -12,11 +12,19 @@
|
|
|
12
12
|
* docs:
|
|
13
13
|
* url: https://example.com/mcp
|
|
14
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
|
|
15
22
|
*
|
|
16
|
-
* `${VAR}` in command, args, env, cwd, url
|
|
17
|
-
* 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.
|
|
18
25
|
*/
|
|
19
26
|
import { z } from "zod";
|
|
27
|
+
import { EMAIL_EVENTS } from "./email.js";
|
|
20
28
|
const UPSTREAM_ID = /^[A-Za-z0-9-]+$/;
|
|
21
29
|
export const StdioUpstreamSchema = z
|
|
22
30
|
.object({
|
|
@@ -33,6 +41,44 @@ export const HttpUpstreamSchema = z
|
|
|
33
41
|
})
|
|
34
42
|
.strict();
|
|
35
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();
|
|
36
82
|
export const GatewayConfigSchema = z
|
|
37
83
|
.object({
|
|
38
84
|
upstreams: z
|
|
@@ -50,6 +96,8 @@ export const GatewayConfigSchema = z
|
|
|
50
96
|
* logs what would have been stopped: for trying a policy out safely.
|
|
51
97
|
*/
|
|
52
98
|
mode: z.enum(["active", "audit"]).default("active"),
|
|
99
|
+
/** Human approvals for "ask" decisions. Without an answering channel, "ask" blocks. */
|
|
100
|
+
approvals: ApprovalsConfigSchema.optional(),
|
|
53
101
|
/** Timeout for each interceptor invocation, in milliseconds. */
|
|
54
102
|
interceptorTimeoutMs: z.number().int().positive().default(5000),
|
|
55
103
|
})
|
|
@@ -90,6 +138,19 @@ export function expandUpstream(id, u, env) {
|
|
|
90
138
|
...(u.cwd !== undefined ? { cwd: expandEnv(u.cwd, env, `${where}.cwd`) } : {}),
|
|
91
139
|
};
|
|
92
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
|
+
}
|
|
93
154
|
export function isHttpUpstream(u) {
|
|
94
155
|
return "url" in u;
|
|
95
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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"}
|