@adtl/gateway 0.2.0 → 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 +21 -2
- package/dist/audit.d.ts +5 -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/gateway.d.ts +22 -2
- package/dist/gateway.d.ts.map +1 -1
- package/dist/gateway.js +189 -14
- package/dist/gateway.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/init/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/startup.d.ts +3 -1
- package/dist/startup.d.ts.map +1 -1
- package/dist/startup.js +3 -3
- package/dist/startup.js.map +1 -1
- package/package.json +3 -3
- package/src/audit.ts +6 -3
- package/src/cli.ts +41 -1
- package/src/gateway.ts +238 -13
- package/src/index.ts +1 -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/startup.ts +3 -3
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presets for well-known MCP servers, used by `adtl-gateway init`.
|
|
3
|
+
*
|
|
4
|
+
* A preset says what a server's reads and writes mean, and the server's own
|
|
5
|
+
* `readOnlyHint` decides which tools are reads. That keeps a preset correct as
|
|
6
|
+
* the server adds tools (the GitHub server has about 90 and adds more).
|
|
7
|
+
*
|
|
8
|
+
* Presets are only a starting point: `init` writes one explicit line per tool
|
|
9
|
+
* into adtl.yaml, and the gateway owner reviews and edits them.
|
|
10
|
+
*/
|
|
11
|
+
import type { ToolRule } from "@adtl/labels";
|
|
12
|
+
export interface Preset {
|
|
13
|
+
id: string;
|
|
14
|
+
/** `serverInfo.name` values the server reports at initialize. */
|
|
15
|
+
serverNames: string[];
|
|
16
|
+
/** Server defaults: resources, prompts, and tools added after `init` ran. */
|
|
17
|
+
defaults: ToolRule;
|
|
18
|
+
/** Tools with `readOnlyHint: true`. */
|
|
19
|
+
read: ToolRule;
|
|
20
|
+
/** All other tools. Fields left out fall back to `defaults`. */
|
|
21
|
+
write: ToolRule;
|
|
22
|
+
/** Exact per-tool overrides. */
|
|
23
|
+
tools?: Record<string, ToolRule>;
|
|
24
|
+
/** One line written above the server in adtl.yaml. */
|
|
25
|
+
note: string;
|
|
26
|
+
}
|
|
27
|
+
export declare const PRESETS: Preset[];
|
|
28
|
+
/** The preset for an upstream: by the name the server reports, then by the upstream id. */
|
|
29
|
+
export declare function choosePreset(upstreamId: string, serverName: string | undefined, presets?: Preset[]): Preset | undefined;
|
|
30
|
+
//# sourceMappingURL=presets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../src/init/presets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,iEAAiE;IACjE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,6EAA6E;IAC7E,QAAQ,EAAE,QAAQ,CAAC;IACnB,uCAAuC;IACvC,IAAI,EAAE,QAAQ,CAAC;IACf,gEAAgE;IAChE,KAAK,EAAE,QAAQ,CAAC;IAChB,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACjC,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,OAAO,EAAE,MAAM,EA2B3B,CAAC;AAEF,2FAA2F;AAC3F,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,WAAU,GAAG,MAAM,GAAG,SAAS,CAKtH"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const PRESETS = [
|
|
2
|
+
{
|
|
3
|
+
id: "github",
|
|
4
|
+
serverNames: ["github-mcp-server"],
|
|
5
|
+
// Issues, PRs, comments and code can be written by anyone who can open an issue.
|
|
6
|
+
defaults: { integrity: "untrusted", confidentiality: "private", egress: "public" },
|
|
7
|
+
read: { integrity: "untrusted", confidentiality: "private", egress: "internal" },
|
|
8
|
+
write: { egress: "public" },
|
|
9
|
+
note: "preset github: content is untrusted (anyone can write issues), private repos make it private; writes are public",
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
id: "filesystem",
|
|
13
|
+
serverNames: ["secure-filesystem-server"],
|
|
14
|
+
defaults: { integrity: "trusted", confidentiality: "private", egress: "internal" },
|
|
15
|
+
read: { integrity: "trusted", confidentiality: "private", egress: "none" },
|
|
16
|
+
write: { egress: "internal" },
|
|
17
|
+
note: "preset filesystem: files are trusted; set integrity: untrusted if these folders hold downloads or cloned repos",
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: "fetch",
|
|
21
|
+
serverNames: ["mcp-fetch"],
|
|
22
|
+
// The URL itself can carry data out, so even a read is external egress.
|
|
23
|
+
defaults: { integrity: "untrusted", confidentiality: "public", egress: "external" },
|
|
24
|
+
read: { integrity: "untrusted", confidentiality: "public", egress: "external" },
|
|
25
|
+
write: { integrity: "untrusted", confidentiality: "public", egress: "external" },
|
|
26
|
+
note: "preset fetch: web pages are untrusted; a fetched URL can carry data out, so fetch is external egress",
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
/** The preset for an upstream: by the name the server reports, then by the upstream id. */
|
|
30
|
+
export function choosePreset(upstreamId, serverName, presets = PRESETS) {
|
|
31
|
+
return ((serverName !== undefined ? presets.find((p) => p.serverNames.includes(serverName)) : undefined) ??
|
|
32
|
+
presets.find((p) => p.id === upstreamId));
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=presets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presets.js","sourceRoot":"","sources":["../../src/init/presets.ts"],"names":[],"mappings":"AA4BA,MAAM,CAAC,MAAM,OAAO,GAAa;IAC/B;QACE,EAAE,EAAE,QAAQ;QACZ,WAAW,EAAE,CAAC,mBAAmB,CAAC;QAClC,iFAAiF;QACjF,QAAQ,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE;QAClF,IAAI,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE;QAChF,KAAK,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;QAC3B,IAAI,EAAE,iHAAiH;KACxH;IACD;QACE,EAAE,EAAE,YAAY;QAChB,WAAW,EAAE,CAAC,0BAA0B,CAAC;QACzC,QAAQ,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE;QAClF,IAAI,EAAE,EAAE,SAAS,EAAE,SAAS,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE;QAC1E,KAAK,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;QAC7B,IAAI,EAAE,gHAAgH;KACvH;IACD;QACE,EAAE,EAAE,OAAO;QACX,WAAW,EAAE,CAAC,WAAW,CAAC;QAC1B,wEAAwE;QACxE,QAAQ,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE;QACnF,IAAI,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE;QAC/E,KAAK,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE;QAChF,IAAI,EAAE,sGAAsG;KAC7G;CACF,CAAC;AAEF,2FAA2F;AAC3F,MAAM,UAAU,YAAY,CAAC,UAAkB,EAAE,UAA8B,EAAE,OAAO,GAAG,OAAO;IAChG,OAAO,CACL,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAChG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,CACzC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type MergeReport } from "./suggest.js";
|
|
2
|
+
export interface InitOptions {
|
|
3
|
+
path: string;
|
|
4
|
+
write?: boolean;
|
|
5
|
+
env?: NodeJS.ProcessEnv;
|
|
6
|
+
}
|
|
7
|
+
export interface InitResult {
|
|
8
|
+
/** The updated adtl.yaml. */
|
|
9
|
+
text: string;
|
|
10
|
+
reports: MergeReport[];
|
|
11
|
+
/** Upstreams that could not be scanned; left untouched in the file. */
|
|
12
|
+
failed: {
|
|
13
|
+
id: string;
|
|
14
|
+
error: string;
|
|
15
|
+
}[];
|
|
16
|
+
}
|
|
17
|
+
export declare function runInit(opts: InitOptions): Promise<InitResult>;
|
|
18
|
+
//# sourceMappingURL=run.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/init/run.ts"],"names":[],"mappings":"AAeA,OAAO,EAA8B,KAAK,WAAW,EAAmB,MAAM,cAAc,CAAC;AAE7F,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,6BAA6B;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,uEAAuE;IACvE,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CACzC;AAwBD,wBAAsB,OAAO,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAyBpE"}
|
package/dist/init/run.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `adtl-gateway init`: connect to every upstream in adtl.yaml, list its
|
|
3
|
+
* tools, and draft a labeling rule for each tool not configured yet.
|
|
4
|
+
*
|
|
5
|
+
* Without `write`, the updated file is only returned (the CLI prints it).
|
|
6
|
+
* With `write`, the original is kept as `<file>.bak` and the file is updated
|
|
7
|
+
* in place. Existing entries and comments are never changed.
|
|
8
|
+
*/
|
|
9
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
10
|
+
import { dirname } from "node:path";
|
|
11
|
+
import { parseDocument } from "yaml";
|
|
12
|
+
import { expandUpstream } from "../config.js";
|
|
13
|
+
import { connectUpstream, loadGatewayConfig } from "../startup.js";
|
|
14
|
+
import { mergeIntoDocument, suggest } from "./suggest.js";
|
|
15
|
+
async function listAllTools(client) {
|
|
16
|
+
const tools = [];
|
|
17
|
+
let cursor;
|
|
18
|
+
do {
|
|
19
|
+
const page = await client.listTools(cursor ? { cursor } : {});
|
|
20
|
+
tools.push(...page.tools);
|
|
21
|
+
cursor = page.nextCursor;
|
|
22
|
+
} while (cursor);
|
|
23
|
+
return tools;
|
|
24
|
+
}
|
|
25
|
+
async function scan(id, connect) {
|
|
26
|
+
const client = await connect();
|
|
27
|
+
try {
|
|
28
|
+
const name = client.getServerVersion()?.name;
|
|
29
|
+
const tools = await listAllTools(client);
|
|
30
|
+
return { id, ...(name ? { serverName: name } : {}), tools: tools.map((t) => ({ name: t.name, annotations: t.annotations })) };
|
|
31
|
+
}
|
|
32
|
+
finally {
|
|
33
|
+
await client.close().catch(() => undefined);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export async function runInit(opts) {
|
|
37
|
+
const env = opts.env ?? process.env;
|
|
38
|
+
const loaded = await loadGatewayConfig(opts.path);
|
|
39
|
+
const baseDir = dirname(loaded.path);
|
|
40
|
+
const original = await readFile(loaded.path, "utf8");
|
|
41
|
+
const ids = Object.keys(loaded.gateway.upstreams);
|
|
42
|
+
const settled = await Promise.allSettled(ids.map((id) => scan(id, () => connectUpstream(id, expandUpstream(id, loaded.gateway.upstreams[id], env), baseDir))));
|
|
43
|
+
const scans = [];
|
|
44
|
+
const failed = [];
|
|
45
|
+
settled.forEach((s, i) => {
|
|
46
|
+
if (s.status === "fulfilled")
|
|
47
|
+
scans.push(s.value);
|
|
48
|
+
else
|
|
49
|
+
failed.push({ id: ids[i], error: s.reason.message });
|
|
50
|
+
});
|
|
51
|
+
const doc = parseDocument(original);
|
|
52
|
+
const reports = mergeIntoDocument(doc, scans.map((s) => suggest(s)));
|
|
53
|
+
const text = doc.toString();
|
|
54
|
+
if (opts.write && text !== original) {
|
|
55
|
+
await writeFile(`${loaded.path}.bak`, original, "utf8");
|
|
56
|
+
await writeFile(loaded.path, text, "utf8");
|
|
57
|
+
}
|
|
58
|
+
return { text, reports, failed };
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=run.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/init/run.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Draft ADTL rules for an upstream's tools, and merge them into adtl.yaml.
|
|
3
|
+
*
|
|
4
|
+
* Without a preset, rules come from the MCP tool annotations. Those are the
|
|
5
|
+
* server's own claims, so they only decide egress; integrity is always
|
|
6
|
+
* untrusted and confidentiality private until the owner says otherwise.
|
|
7
|
+
* Missing hints take the MCP spec defaults (readOnlyHint false, openWorldHint true).
|
|
8
|
+
*
|
|
9
|
+
* Merging never changes an entry that is already in the file: the owner's
|
|
10
|
+
* choices win, and `init` can be re-run to pick up new tools.
|
|
11
|
+
*/
|
|
12
|
+
import type { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
13
|
+
import type { ToolRule } from "@adtl/labels";
|
|
14
|
+
import { type Document } from "yaml";
|
|
15
|
+
import { type Preset } from "./presets.js";
|
|
16
|
+
export interface ServerScan {
|
|
17
|
+
/** Upstream id in gateway.upstreams. */
|
|
18
|
+
id: string;
|
|
19
|
+
/** `serverInfo.name` the server reported. */
|
|
20
|
+
serverName?: string;
|
|
21
|
+
tools: Pick<Tool, "name" | "annotations">[];
|
|
22
|
+
}
|
|
23
|
+
export interface ToolSuggestion {
|
|
24
|
+
name: string;
|
|
25
|
+
rule: ToolRule;
|
|
26
|
+
/** Short reason, written as a comment next to the rule. */
|
|
27
|
+
why: string;
|
|
28
|
+
}
|
|
29
|
+
export interface ServerSuggestion {
|
|
30
|
+
id: string;
|
|
31
|
+
preset?: Preset;
|
|
32
|
+
defaults: ToolRule;
|
|
33
|
+
tools: ToolSuggestion[];
|
|
34
|
+
}
|
|
35
|
+
/** A rule from the tool's MCP annotations alone. */
|
|
36
|
+
export declare function ruleFromHints(annotations: Tool["annotations"]): Omit<ToolSuggestion, "name">;
|
|
37
|
+
export declare function suggest(scan: ServerScan, presets?: Preset[]): ServerSuggestion;
|
|
38
|
+
export interface MergeReport {
|
|
39
|
+
id: string;
|
|
40
|
+
preset?: string;
|
|
41
|
+
added: string[];
|
|
42
|
+
/** Tools already configured; left as they were. */
|
|
43
|
+
kept: string[];
|
|
44
|
+
/** Configured tools the server no longer offers. Left in place, reported only. */
|
|
45
|
+
stale: string[];
|
|
46
|
+
addedDefaults: boolean;
|
|
47
|
+
}
|
|
48
|
+
/** Add the suggestions to the document's `servers:` section, keeping every existing entry. */
|
|
49
|
+
export declare function mergeIntoDocument(doc: Document, suggestions: ServerSuggestion[]): MergeReport[];
|
|
50
|
+
//# sourceMappingURL=suggest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest.d.ts","sourceRoot":"","sources":["../../src/init/suggest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAmB,KAAK,QAAQ,EAAgB,MAAM,MAAM,CAAC;AACpE,OAAO,EAAyB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC;AAElE,MAAM,WAAW,UAAU;IACzB,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAAC,EAAE,CAAC;CAC7C;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,2DAA2D;IAC3D,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAID,oDAAoD;AACpD,wBAAgB,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAM5F;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,WAAU,GAAG,gBAAgB,CAU7E;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,mDAAmD;IACnD,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,kFAAkF;IAClF,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,aAAa,EAAE,OAAO,CAAC;CACxB;AAYD,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,GAAG,WAAW,EAAE,CA2C/F"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { isMap, isScalar } from "yaml";
|
|
2
|
+
import { choosePreset, PRESETS } from "./presets.js";
|
|
3
|
+
const UNKNOWN_DEFAULTS = { integrity: "untrusted", confidentiality: "private" };
|
|
4
|
+
/** A rule from the tool's MCP annotations alone. */
|
|
5
|
+
export function ruleFromHints(annotations) {
|
|
6
|
+
const readOnly = annotations?.readOnlyHint === true;
|
|
7
|
+
const openWorld = annotations?.openWorldHint !== false;
|
|
8
|
+
const egress = readOnly ? (openWorld ? "external" : "none") : openWorld ? "public" : "internal";
|
|
9
|
+
const why = `hints: ${readOnly ? "read-only" : "writes"}, ${openWorld ? "open world" : "closed world"} (review)`;
|
|
10
|
+
return { rule: { integrity: "untrusted", confidentiality: "private", egress }, why };
|
|
11
|
+
}
|
|
12
|
+
export function suggest(scan, presets = PRESETS) {
|
|
13
|
+
const preset = choosePreset(scan.id, scan.serverName, presets);
|
|
14
|
+
const tools = scan.tools.map(({ name, annotations }) => {
|
|
15
|
+
if (!preset)
|
|
16
|
+
return { name, ...ruleFromHints(annotations) };
|
|
17
|
+
const override = preset.tools?.[name];
|
|
18
|
+
if (override)
|
|
19
|
+
return { name, rule: override, why: `preset ${preset.id}` };
|
|
20
|
+
const read = annotations?.readOnlyHint === true;
|
|
21
|
+
return { name, rule: read ? preset.read : preset.write, why: `preset ${preset.id}: ${read ? "read" : "write"}` };
|
|
22
|
+
});
|
|
23
|
+
return { id: scan.id, ...(preset ? { preset } : {}), defaults: preset?.defaults ?? UNKNOWN_DEFAULTS, tools };
|
|
24
|
+
}
|
|
25
|
+
function mapAt(doc, parent, key, commentBefore) {
|
|
26
|
+
const existing = parent.get(key, true);
|
|
27
|
+
if (isMap(existing))
|
|
28
|
+
return existing;
|
|
29
|
+
const map = doc.createNode({});
|
|
30
|
+
const k = doc.createNode(key);
|
|
31
|
+
if (commentBefore && isScalar(k))
|
|
32
|
+
k.commentBefore = ` ${commentBefore}`;
|
|
33
|
+
parent.add(doc.createPair(k, map));
|
|
34
|
+
return map;
|
|
35
|
+
}
|
|
36
|
+
/** Add the suggestions to the document's `servers:` section, keeping every existing entry. */
|
|
37
|
+
export function mergeIntoDocument(doc, suggestions) {
|
|
38
|
+
let servers = doc.get("servers", true);
|
|
39
|
+
if (!isMap(servers)) {
|
|
40
|
+
servers = doc.createNode({});
|
|
41
|
+
// Put servers: first, ahead of policy: and gateway:.
|
|
42
|
+
const root = doc.contents;
|
|
43
|
+
if (isMap(root))
|
|
44
|
+
root.items.unshift(doc.createPair("servers", servers));
|
|
45
|
+
else
|
|
46
|
+
doc.contents = doc.createNode({ servers });
|
|
47
|
+
}
|
|
48
|
+
const serversMap = servers;
|
|
49
|
+
return suggestions.map((s) => {
|
|
50
|
+
const report = { id: s.id, added: [], kept: [], stale: [], addedDefaults: false };
|
|
51
|
+
if (s.preset)
|
|
52
|
+
report.preset = s.preset.id;
|
|
53
|
+
const isNew = !serversMap.has(s.id);
|
|
54
|
+
const server = mapAt(doc, serversMap, s.id, isNew ? (s.preset?.note ?? "from MCP tool hints: review every line") : undefined);
|
|
55
|
+
if (!server.has("defaults")) {
|
|
56
|
+
const d = doc.createNode(s.defaults, { flow: true });
|
|
57
|
+
d.comment = " resources, prompts, and tools not listed below";
|
|
58
|
+
server.items.unshift(doc.createPair("defaults", d));
|
|
59
|
+
report.addedDefaults = true;
|
|
60
|
+
}
|
|
61
|
+
const tools = mapAt(doc, server, "tools");
|
|
62
|
+
tools.flow = false;
|
|
63
|
+
const offered = new Set(s.tools.map((t) => t.name));
|
|
64
|
+
for (const t of s.tools) {
|
|
65
|
+
if (tools.has(t.name)) {
|
|
66
|
+
report.kept.push(t.name);
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
const v = doc.createNode(t.rule, { flow: true });
|
|
70
|
+
v.comment = ` ${t.why}`;
|
|
71
|
+
tools.set(t.name, v);
|
|
72
|
+
report.added.push(t.name);
|
|
73
|
+
}
|
|
74
|
+
for (const item of tools.items) {
|
|
75
|
+
const name = isScalar(item.key) ? String(item.key.value) : String(item.key);
|
|
76
|
+
if (!offered.has(name))
|
|
77
|
+
report.stale.push(name);
|
|
78
|
+
}
|
|
79
|
+
return report;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=suggest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suggest.js","sourceRoot":"","sources":["../../src/init/suggest.ts"],"names":[],"mappings":"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"}
|
package/dist/startup.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
1
2
|
import type { AdtlConfig } from "@adtl/labels";
|
|
2
3
|
import { ApprovalBroker } from "./approvals.js";
|
|
3
|
-
import { type GatewayConfig } from "./config.js";
|
|
4
|
+
import { type GatewayConfig, type Upstream } from "./config.js";
|
|
4
5
|
import { AdtlGateway, type GatewayLogger } from "./gateway.js";
|
|
5
6
|
export declare class GatewayConfigError extends Error {
|
|
6
7
|
constructor(message: string);
|
|
@@ -13,6 +14,7 @@ export interface LoadedConfig {
|
|
|
13
14
|
export declare function loadGatewayConfig(path: string): Promise<LoadedConfig>;
|
|
14
15
|
/** Path of the bundled adtl-interceptors CLI. */
|
|
15
16
|
export declare function bundledInterceptorsCli(): string;
|
|
17
|
+
export declare function connectUpstream(id: string, u: Upstream, baseDir: string): Promise<Client>;
|
|
16
18
|
/** Build the approval broker from `gateway.approvals`, or undefined if not configured. */
|
|
17
19
|
export declare function createApprovals(cfg: GatewayConfig, env: NodeJS.ProcessEnv, log: GatewayLogger): ApprovalBroker | undefined;
|
|
18
20
|
export interface StartedGateway {
|
package/dist/startup.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"startup.d.ts","sourceRoot":"","sources":["../src/startup.ts"],"names":[],"mappings":"
|
|
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"}
|
package/dist/startup.js
CHANGED
|
@@ -71,7 +71,7 @@ function stdioTransport(u, baseDir) {
|
|
|
71
71
|
stderr: "inherit",
|
|
72
72
|
});
|
|
73
73
|
}
|
|
74
|
-
async function
|
|
74
|
+
export async function connectUpstream(id, u, baseDir) {
|
|
75
75
|
const client = new Client({ name: `adtl-gateway→${id}`, version: GATEWAY_VERSION });
|
|
76
76
|
const transport = isHttpUpstream(u)
|
|
77
77
|
? new StreamableHTTPClientTransport(new URL(u.url), { requestInit: { headers: u.headers } })
|
|
@@ -112,7 +112,7 @@ export async function startGateway(loaded, opts = {}) {
|
|
|
112
112
|
const icfg = loaded.gateway.interceptors
|
|
113
113
|
? expandUpstream("interceptors", loaded.gateway.interceptors, env)
|
|
114
114
|
: { command: process.execPath, args: [bundledInterceptorsCli(), "--config", loaded.path], env: {} };
|
|
115
|
-
const interceptors = await
|
|
115
|
+
const interceptors = await connectUpstream("interceptors", icfg, baseDir);
|
|
116
116
|
clients.push(interceptors);
|
|
117
117
|
if (!interceptors.getServerCapabilities()?.extensions?.[INTERCEPTORS_EXTENSION]) {
|
|
118
118
|
throw new GatewayConfigError(`The interceptor server does not declare the ${INTERCEPTORS_EXTENSION} extension`);
|
|
@@ -132,7 +132,7 @@ export async function startGateway(loaded, opts = {}) {
|
|
|
132
132
|
// 2. Upstream servers. One failing upstream does not stop the others.
|
|
133
133
|
const upstreams = new Map();
|
|
134
134
|
const ids = Object.keys(loaded.gateway.upstreams);
|
|
135
|
-
const settled = await Promise.allSettled(ids.map((id) =>
|
|
135
|
+
const settled = await Promise.allSettled(ids.map((id) => connectUpstream(id, expandUpstream(id, loaded.gateway.upstreams[id], env), baseDir)));
|
|
136
136
|
settled.forEach((s, i) => {
|
|
137
137
|
const id = ids[i];
|
|
138
138
|
if (s.status === "fulfilled") {
|
package/dist/startup.js.map
CHANGED
|
@@ -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
|
+
"version": "0.3.0",
|
|
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.
|
|
50
|
-
"@adtl/labels": "0.
|
|
49
|
+
"@adtl/interceptors": "0.3.0",
|
|
50
|
+
"@adtl/labels": "0.3.0",
|
|
51
51
|
"@modelcontextprotocol/sdk": "1.31.0",
|
|
52
52
|
"nodemailer": "10.0.12",
|
|
53
53
|
"yaml": "2.9.1",
|
package/src/audit.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Append-only JSONL audit log. One line per tool call.
|
|
2
|
+
* Append-only JSONL audit log. One line per tool call, resource read or prompt get.
|
|
3
3
|
*
|
|
4
4
|
* Arguments and results are never written; the call is identified by its
|
|
5
5
|
* hash, so the log can be shared without leaking the data it describes.
|
|
@@ -10,9 +10,12 @@ import { dirname } from "node:path";
|
|
|
10
10
|
export interface AuditEntry {
|
|
11
11
|
ts: string;
|
|
12
12
|
sessionId: string;
|
|
13
|
-
event: "tools/call";
|
|
13
|
+
event: "tools/call" | "resources/read" | "prompts/get";
|
|
14
14
|
server: string;
|
|
15
|
-
tool
|
|
15
|
+
/** Exactly one of tool, resource or prompt is set, matching `event`. */
|
|
16
|
+
tool?: string;
|
|
17
|
+
resource?: string;
|
|
18
|
+
prompt?: string;
|
|
16
19
|
/** Final outcome of the call. */
|
|
17
20
|
outcome: "forwarded" | "blocked" | "upstream_error";
|
|
18
21
|
/** The policy's decision. In audit mode a call can be forwarded with decision "ask" or "block". */
|
package/src/cli.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* servers through ADTL's interceptors.
|
|
5
5
|
*
|
|
6
6
|
* adtl-gateway --config adtl.yaml [--audit]
|
|
7
|
+
* adtl-gateway init --config adtl.yaml [--write]
|
|
7
8
|
*
|
|
8
9
|
* Point your MCP client (e.g. Claude Code's .mcp.json) at this command.
|
|
9
10
|
* Logs go to stderr; stdout carries MCP JSON-RPC only.
|
|
@@ -11,9 +12,11 @@
|
|
|
11
12
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
12
13
|
import { EnvExpansionError } from "./config.js";
|
|
13
14
|
import { GATEWAY_VERSION } from "./gateway.js";
|
|
15
|
+
import { runInit, type InitResult } from "./init/run.js";
|
|
14
16
|
import { GatewayConfigError, loadGatewayConfig, startGateway } from "./startup.js";
|
|
15
17
|
|
|
16
18
|
const USAGE = `Usage: adtl-gateway --config <adtl.yaml> [--audit]
|
|
19
|
+
adtl-gateway init --config <adtl.yaml> [--write]
|
|
17
20
|
|
|
18
21
|
Runs an MCP server over stdio that forwards tool calls to the upstream
|
|
19
22
|
servers in the config, checking and labeling each call with ADTL.
|
|
@@ -23,9 +26,18 @@ Options:
|
|
|
23
26
|
--audit Log what would be stopped, but stop nothing
|
|
24
27
|
(same as gateway.mode: audit).
|
|
25
28
|
-v, --version Print the version and exit.
|
|
29
|
+
|
|
30
|
+
init:
|
|
31
|
+
Connects to every upstream, lists its tools, and drafts a labeling rule
|
|
32
|
+
for each tool the config doesn't cover yet (presets for GitHub,
|
|
33
|
+
filesystem and fetch; MCP tool hints otherwise). Existing entries are
|
|
34
|
+
never changed. Prints the updated config; review it before using it.
|
|
35
|
+
--write Update the config file in place (original kept as .bak).
|
|
26
36
|
-h, --help Show this help.`;
|
|
27
37
|
|
|
28
38
|
interface Args {
|
|
39
|
+
init?: boolean;
|
|
40
|
+
write?: boolean;
|
|
29
41
|
config?: string;
|
|
30
42
|
audit?: boolean;
|
|
31
43
|
help?: boolean;
|
|
@@ -36,11 +48,13 @@ function parseArgs(argv: string[]): Args {
|
|
|
36
48
|
const out: Args = {};
|
|
37
49
|
for (let i = 0; i < argv.length; i++) {
|
|
38
50
|
const a = argv[i];
|
|
39
|
-
if (
|
|
51
|
+
if (i === 0 && a === "init") out.init = true;
|
|
52
|
+
else if (a === "-h" || a === "--help") out.help = true;
|
|
40
53
|
else if (a === "-v" || a === "--version") out.version = true;
|
|
41
54
|
else if (a === "-c" || a === "--config") out.config = argv[++i];
|
|
42
55
|
else if (a?.startsWith("--config=")) out.config = a.slice("--config=".length);
|
|
43
56
|
else if (a === "--audit") out.audit = true;
|
|
57
|
+
else if (a === "--write" && out.init) out.write = true;
|
|
44
58
|
else throw new GatewayConfigError(`Unknown argument: ${a}\n\n${USAGE}`);
|
|
45
59
|
}
|
|
46
60
|
return out;
|
|
@@ -52,6 +66,7 @@ async function main(): Promise<void> {
|
|
|
52
66
|
if (args.help) return void console.log(USAGE);
|
|
53
67
|
if (args.version) return void console.log(GATEWAY_VERSION);
|
|
54
68
|
if (!args.config) throw new GatewayConfigError(`Missing --config\n\n${USAGE}`);
|
|
69
|
+
if (args.init) return init(args.config, args.write === true);
|
|
55
70
|
|
|
56
71
|
const loaded = await loadGatewayConfig(args.config);
|
|
57
72
|
if (args.audit) loaded.gateway.mode = "audit";
|
|
@@ -77,6 +92,31 @@ async function main(): Promise<void> {
|
|
|
77
92
|
console.error(`[adtl-gateway] ${GATEWAY_VERSION} ready (session ${started.gateway.sessionId})`);
|
|
78
93
|
}
|
|
79
94
|
|
|
95
|
+
function summarize(r: InitResult, path: string, write: boolean): string {
|
|
96
|
+
const lines = r.reports.map((s) => {
|
|
97
|
+
const parts = [`${s.added.length} tools added`];
|
|
98
|
+
if (s.kept.length) parts.push(`${s.kept.length} kept`);
|
|
99
|
+
if (s.addedDefaults) parts.push("defaults added");
|
|
100
|
+
if (s.stale.length) parts.push(`no longer offered: ${s.stale.join(", ")}`);
|
|
101
|
+
return ` ${s.id} (${s.preset ? `preset ${s.preset}` : "from tool hints, review"}): ${parts.join("; ")}`;
|
|
102
|
+
});
|
|
103
|
+
for (const f of r.failed) lines.push(` ${f.id}: could not connect, skipped (${f.error})`);
|
|
104
|
+
const changed = r.reports.some((s) => s.added.length || s.addedDefaults);
|
|
105
|
+
const tail = !changed
|
|
106
|
+
? "Nothing to add."
|
|
107
|
+
: write
|
|
108
|
+
? `Updated ${path} (original saved as ${path}.bak). Review every line marked "review".`
|
|
109
|
+
: "Nothing written. Review the config above, then re-run with --write.";
|
|
110
|
+
return `${lines.join("\n")}\n${tail}`;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async function init(path: string, write: boolean): Promise<void> {
|
|
114
|
+
const result = await runInit({ path, write });
|
|
115
|
+
if (!write) process.stdout.write(result.text);
|
|
116
|
+
console.error(`[adtl-gateway] init\n${summarize(result, path, write)}`);
|
|
117
|
+
if (result.failed.length && !result.reports.length) process.exitCode = 1;
|
|
118
|
+
}
|
|
119
|
+
|
|
80
120
|
main().catch((err: unknown) => {
|
|
81
121
|
const known = err instanceof GatewayConfigError || err instanceof EnvExpansionError;
|
|
82
122
|
console.error(known ? `[adtl-gateway] ${(err as Error).message}` : err);
|