@shield-agent/kya 0.10.1 → 0.12.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/.mcp.json +1 -1
- package/README.md +3 -3
- package/amp/settings.example.json +1 -1
- package/claude/claude_desktop_config.example.json +1 -1
- package/cline/cline_mcp_settings.example.json +1 -1
- package/copilot/mcp-config.example.json +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +80 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/connect.d.ts +14 -2
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +84 -31
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/gate-serve.d.ts +23 -0
- package/dist/commands/gate-serve.d.ts.map +1 -0
- package/dist/commands/gate-serve.js +93 -0
- package/dist/commands/gate-serve.js.map +1 -0
- package/dist/commands/gate.d.ts +85 -0
- package/dist/commands/gate.d.ts.map +1 -0
- package/dist/commands/gate.js +268 -0
- package/dist/commands/gate.js.map +1 -0
- package/dist/commands/stop.d.ts +3 -0
- package/dist/commands/stop.d.ts.map +1 -1
- package/dist/commands/stop.js +34 -0
- package/dist/commands/stop.js.map +1 -1
- package/dist/gate/binary.d.ts +49 -0
- package/dist/gate/binary.d.ts.map +1 -0
- package/dist/gate/binary.js +129 -0
- package/dist/gate/binary.js.map +1 -0
- package/dist/gate/config-gen.d.ts +24 -0
- package/dist/gate/config-gen.d.ts.map +1 -0
- package/dist/gate/config-gen.js +146 -0
- package/dist/gate/config-gen.js.map +1 -0
- package/dist/gate/config.d.ts +39 -0
- package/dist/gate/config.d.ts.map +1 -0
- package/dist/gate/config.js +177 -0
- package/dist/gate/config.js.map +1 -0
- package/dist/gate/daemon.d.ts +38 -0
- package/dist/gate/daemon.d.ts.map +1 -0
- package/dist/gate/daemon.js +117 -0
- package/dist/gate/daemon.js.map +1 -0
- package/dist/gate/otlp-decode.d.ts +21 -0
- package/dist/gate/otlp-decode.d.ts.map +1 -0
- package/dist/gate/otlp-decode.js +268 -0
- package/dist/gate/otlp-decode.js.map +1 -0
- package/dist/gate/otlp-receiver.d.ts +35 -0
- package/dist/gate/otlp-receiver.d.ts.map +1 -0
- package/dist/gate/otlp-receiver.js +186 -0
- package/dist/gate/otlp-receiver.js.map +1 -0
- package/dist/mcp-servers.d.ts +34 -0
- package/dist/mcp-servers.d.ts.map +1 -0
- package/dist/mcp-servers.js +272 -0
- package/dist/mcp-servers.js.map +1 -0
- package/dist/offline-evaluate.d.ts.map +1 -1
- package/dist/offline-evaluate.js +19 -0
- package/dist/offline-evaluate.js.map +1 -1
- package/dist/receipt/dashboard.d.ts +2 -0
- package/dist/receipt/dashboard.d.ts.map +1 -1
- package/dist/receipt/dashboard.js +12 -0
- package/dist/receipt/dashboard.js.map +1 -1
- package/dist/receipt/render-receipt.d.ts +2 -0
- package/dist/receipt/render-receipt.d.ts.map +1 -1
- package/dist/receipt/render-receipt.js +24 -4
- package/dist/receipt/render-receipt.js.map +1 -1
- package/droid/README.md +1 -1
- package/droid/mcp.example.json +1 -1
- package/gemini/settings.example.json +1 -1
- package/grok/README.md +1 -1
- package/kilo/kilo.example.json +1 -1
- package/kimi/mcp.example.json +1 -1
- package/kiro/mcp.example.json +1 -1
- package/manifest.json +1 -1
- package/mastracode/mcp.example.json +1 -1
- package/mcp.json +1 -1
- package/openai/codex.config.example.toml +1 -1
- package/opencode/opencode.example.json +1 -1
- package/package.json +1 -1
- package/qwen/settings.example.json +1 -1
- package/server.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,EAClB,QAAQ,EACR,eAAe,GAEhB,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"stop.js","sourceRoot":"","sources":["../../src/commands/stop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** Pinned gateway build. Bump only together with the repack workflow input. */
|
|
2
|
+
export declare const GATE_VERSION = "1.5.0";
|
|
3
|
+
export declare function gateBinDir(env?: NodeJS.ProcessEnv): string;
|
|
4
|
+
export declare function gateBinaryPath(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): string;
|
|
5
|
+
export interface GatePlatform {
|
|
6
|
+
readonly os: "linux" | "darwin" | "windows";
|
|
7
|
+
readonly arch: "amd64" | "arm64";
|
|
8
|
+
}
|
|
9
|
+
export declare function resolveGatePlatform(platform?: NodeJS.Platform, arch?: string): GatePlatform;
|
|
10
|
+
export declare function gateArtifactName(version: string, p: GatePlatform): string;
|
|
11
|
+
export declare function gateArtifactUrl(version: string, p: GatePlatform): string;
|
|
12
|
+
export declare function sha256Hex(buf: Uint8Array): string;
|
|
13
|
+
/** First hex token of a `<sha256> <name>` checksum file. */
|
|
14
|
+
export declare function parseSha256File(text: string): string;
|
|
15
|
+
export interface GateBinaryStatus {
|
|
16
|
+
readonly path: string;
|
|
17
|
+
readonly present: boolean;
|
|
18
|
+
/** First line of `kya-gate --version`, when readable. */
|
|
19
|
+
readonly version?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function inspectGateBinary(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform): GateBinaryStatus;
|
|
22
|
+
export interface EnsureBinaryDeps {
|
|
23
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
24
|
+
readonly platform?: NodeJS.Platform;
|
|
25
|
+
readonly arch?: string;
|
|
26
|
+
/** Injectable for tests; defaults to global fetch. */
|
|
27
|
+
readonly fetchFn?: (url: string) => Promise<{
|
|
28
|
+
ok: boolean;
|
|
29
|
+
status: number;
|
|
30
|
+
arrayBuffer: () => Promise<ArrayBuffer>;
|
|
31
|
+
text: () => Promise<string>;
|
|
32
|
+
}>;
|
|
33
|
+
/** Injectable for tests; defaults to tar extraction via the system tar. */
|
|
34
|
+
readonly extract?: (tarGzPath: string, destDir: string) => void;
|
|
35
|
+
}
|
|
36
|
+
export interface EnsureBinaryResult {
|
|
37
|
+
readonly path: string;
|
|
38
|
+
readonly installed: boolean;
|
|
39
|
+
readonly version: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Install the pinned gateway binary when absent or stale (reported version ≠
|
|
43
|
+
* GATE_VERSION). Never silently downloads: this runs only from
|
|
44
|
+
* `kya gate setup`. A checksum mismatch aborts the install and leaves the
|
|
45
|
+
* previous binary untouched; the install itself is atomic (temp file +
|
|
46
|
+
* rename inside the bin dir).
|
|
47
|
+
*/
|
|
48
|
+
export declare function ensureGateBinary(deps?: EnsureBinaryDeps): Promise<EnsureBinaryResult>;
|
|
49
|
+
//# sourceMappingURL=binary.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binary.d.ts","sourceRoot":"","sources":["../../src/gate/binary.ts"],"names":[],"mappings":"AAeA,+EAA+E;AAC/E,eAAO,MAAM,YAAY,UAAU,CAAC;AAIpC,wBAAgB,UAAU,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAEvE;AAED,wBAAgB,cAAc,CAC5B,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,MAAM,CAER;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,EAAE,EAAE,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC;CAClC;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,GAAE,MAAM,CAAC,QAA2B,EAC5C,IAAI,GAAE,MAAqB,GAC1B,YAAY,CAWd;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAEzE;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,YAAY,GAAG,MAAM,CAExE;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,UAAU,GAAG,MAAM,CAEjD;AAED,6DAA6D;AAC7D,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIpD;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,yDAAyD;IACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,iBAAiB,CAC/B,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,gBAAgB,CAqBlB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IACpC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,sDAAsD;IACtD,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;QAAC,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;KAAE,CAAC,CAAC;IACnJ,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACjE;AAMD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,GAAE,gBAAqB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAuD/F"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local gateway binary management. `kya gate setup` is the ONLY place a
|
|
3
|
+
* binary is downloaded: it fetches the pinned repacked artifact from this
|
|
4
|
+
* repo's own `gate-v*` GitHub release, verifies the published sha256, and
|
|
5
|
+
* installs to `<global .kya>/bin/kya-gate`. Everything else (run/doctor)
|
|
6
|
+
* only ever uses the binary already on disk.
|
|
7
|
+
*/
|
|
8
|
+
import { createHash } from "node:crypto";
|
|
9
|
+
import { execFileSync } from "node:child_process";
|
|
10
|
+
import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
12
|
+
import { join } from "node:path";
|
|
13
|
+
import { globalConfigDir } from "../config.js";
|
|
14
|
+
import { KyaError } from "../errors.js";
|
|
15
|
+
/** Pinned gateway build. Bump only together with the repack workflow input. */
|
|
16
|
+
export const GATE_VERSION = "1.5.0";
|
|
17
|
+
const RELEASE_REPO = "The-Pixel-Boys/shield-kya";
|
|
18
|
+
export function gateBinDir(env = process.env) {
|
|
19
|
+
return join(globalConfigDir(env), "bin");
|
|
20
|
+
}
|
|
21
|
+
export function gateBinaryPath(env = process.env, platform = process.platform) {
|
|
22
|
+
return join(gateBinDir(env), platform === "win32" ? "kya-gate.exe" : "kya-gate");
|
|
23
|
+
}
|
|
24
|
+
export function resolveGatePlatform(platform = process.platform, arch = process.arch) {
|
|
25
|
+
const os = platform === "darwin" ? "darwin" : platform === "win32" ? "windows" : platform === "linux" ? "linux" : undefined;
|
|
26
|
+
const a = arch === "x64" ? "amd64" : arch === "arm64" ? "arm64" : undefined;
|
|
27
|
+
if (!os || !a) {
|
|
28
|
+
throw new KyaError(`no gateway build for ${platform}/${arch} — supported: linux, darwin, windows × amd64, arm64`, "GATE_UNSUPPORTED_PLATFORM");
|
|
29
|
+
}
|
|
30
|
+
return { os, arch: a };
|
|
31
|
+
}
|
|
32
|
+
export function gateArtifactName(version, p) {
|
|
33
|
+
return `kya-gate-${version}-${p.os}-${p.arch}.tar.gz`;
|
|
34
|
+
}
|
|
35
|
+
export function gateArtifactUrl(version, p) {
|
|
36
|
+
return `https://github.com/${RELEASE_REPO}/releases/download/gate-v${version}/${gateArtifactName(version, p)}`;
|
|
37
|
+
}
|
|
38
|
+
export function sha256Hex(buf) {
|
|
39
|
+
return createHash("sha256").update(buf).digest("hex");
|
|
40
|
+
}
|
|
41
|
+
/** First hex token of a `<sha256> <name>` checksum file. */
|
|
42
|
+
export function parseSha256File(text) {
|
|
43
|
+
const m = /^([0-9a-f]{64})/i.exec(text.trim());
|
|
44
|
+
if (!m)
|
|
45
|
+
throw new KyaError("checksum file is malformed", "GATE_CHECKSUM_MALFORMED");
|
|
46
|
+
return m[1].toLowerCase();
|
|
47
|
+
}
|
|
48
|
+
export function inspectGateBinary(env = process.env, platform = process.platform) {
|
|
49
|
+
const path = gateBinaryPath(env, platform);
|
|
50
|
+
if (!existsSync(path))
|
|
51
|
+
return { path, present: false };
|
|
52
|
+
let version;
|
|
53
|
+
try {
|
|
54
|
+
const out = execFileSync(path, ["--version"], {
|
|
55
|
+
encoding: "utf8",
|
|
56
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
57
|
+
timeout: 5_000,
|
|
58
|
+
}).trim();
|
|
59
|
+
// The binary prints a JSON build object; fall back to the first line.
|
|
60
|
+
try {
|
|
61
|
+
const parsed = JSON.parse(out);
|
|
62
|
+
version = typeof parsed.version === "string" ? parsed.version : undefined;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
version = out.split("\n")[0]?.trim();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
version = undefined;
|
|
70
|
+
}
|
|
71
|
+
return { path, present: true, version: version || undefined };
|
|
72
|
+
}
|
|
73
|
+
function defaultExtract(tarGzPath, destDir) {
|
|
74
|
+
execFileSync("tar", ["-xzf", tarGzPath, "-C", destDir], { stdio: ["ignore", "ignore", "pipe"] });
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Install the pinned gateway binary when absent or stale (reported version ≠
|
|
78
|
+
* GATE_VERSION). Never silently downloads: this runs only from
|
|
79
|
+
* `kya gate setup`. A checksum mismatch aborts the install and leaves the
|
|
80
|
+
* previous binary untouched; the install itself is atomic (temp file +
|
|
81
|
+
* rename inside the bin dir).
|
|
82
|
+
*/
|
|
83
|
+
export async function ensureGateBinary(deps = {}) {
|
|
84
|
+
const env = deps.env ?? process.env;
|
|
85
|
+
const platform = deps.platform ?? process.platform;
|
|
86
|
+
const p = resolveGatePlatform(platform, deps.arch ?? process.arch);
|
|
87
|
+
const path = gateBinaryPath(env, platform);
|
|
88
|
+
const existing = inspectGateBinary(env, platform);
|
|
89
|
+
if (existing.present && existing.version === GATE_VERSION) {
|
|
90
|
+
return { path, installed: false, version: GATE_VERSION };
|
|
91
|
+
}
|
|
92
|
+
const fetchFn = deps.fetchFn ??
|
|
93
|
+
((url) => fetch(url, { redirect: "follow", signal: AbortSignal.timeout(120_000) }));
|
|
94
|
+
const name = gateArtifactName(GATE_VERSION, p);
|
|
95
|
+
const base = gateArtifactUrl(GATE_VERSION, p);
|
|
96
|
+
const binDir = gateBinDir(env);
|
|
97
|
+
mkdirSync(binDir, { recursive: true });
|
|
98
|
+
const stage = mkdtempSync(join(tmpdir(), "kya-gate-"));
|
|
99
|
+
try {
|
|
100
|
+
const [tgzRes, sumRes] = [await fetchFn(base), await fetchFn(`${base}.sha256`)];
|
|
101
|
+
if (!tgzRes.ok || !sumRes.ok) {
|
|
102
|
+
throw new KyaError(`gateway artifact ${name} not available (HTTP ${!tgzRes.ok ? tgzRes.status : sumRes.status}) — run the repack workflow first or check the release tag gate-v${GATE_VERSION}`, "GATE_DOWNLOAD_FAILED");
|
|
103
|
+
}
|
|
104
|
+
const tgz = Buffer.from(await tgzRes.arrayBuffer());
|
|
105
|
+
const expected = parseSha256File(await sumRes.text());
|
|
106
|
+
const actual = sha256Hex(tgz);
|
|
107
|
+
if (actual !== expected) {
|
|
108
|
+
throw new KyaError(`gateway artifact checksum mismatch (expected ${expected}, got ${actual}) — refusing to install`, "GATE_CHECKSUM_MISMATCH");
|
|
109
|
+
}
|
|
110
|
+
const tgzPath = join(stage, name);
|
|
111
|
+
writeFileSync(tgzPath, tgz);
|
|
112
|
+
(deps.extract ?? defaultExtract)(tgzPath, stage);
|
|
113
|
+
const extracted = join(stage, platform === "win32" ? "kya-gate.exe" : "kya-gate");
|
|
114
|
+
if (!existsSync(extracted)) {
|
|
115
|
+
throw new KyaError(`gateway artifact ${name} did not contain a kya-gate binary — corrupt repack?`, "GATE_ARTIFACT_INVALID");
|
|
116
|
+
}
|
|
117
|
+
// Atomic install: stage beside the target, then rename over it.
|
|
118
|
+
const tmpTarget = join(binDir, `.kya-gate.${process.pid}.tmp`);
|
|
119
|
+
writeFileSync(tmpTarget, readFileSync(extracted));
|
|
120
|
+
if (platform !== "win32")
|
|
121
|
+
chmodSync(tmpTarget, 0o755);
|
|
122
|
+
renameSync(tmpTarget, path);
|
|
123
|
+
return { path, installed: true, version: GATE_VERSION };
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
rmSync(stage, { recursive: true, force: true });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=binary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"binary.js","sourceRoot":"","sources":["../../src/gate/binary.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { GatewayServer, GatewaysConfig } from "./config.js";
|
|
2
|
+
/** Destructive-name family denied on every target, registry or not. */
|
|
3
|
+
export declare const DESTRUCTIVE_PATTERN = "(?:^|_)(?:drop|truncate|purge|transfer)(?:_|$)";
|
|
4
|
+
/** Loopback-only L4 rule for the (wildcard-bound) MCP listener. */
|
|
5
|
+
export declare const LOOPBACK_RULE = "cidr(\"127.0.0.0/8\").containsIP(source.address) || source.address == \"::1\"";
|
|
6
|
+
/** Deny patterns for one server: destructive family + its ADMIN registry rules. */
|
|
7
|
+
export declare function denyPatternsFor(serverId: string): readonly string[];
|
|
8
|
+
/**
|
|
9
|
+
* Whether an unmatched tool on this server is allowed: the registry
|
|
10
|
+
* defaultTier — READ and WRITE both map to allow (WRITE is observed, not
|
|
11
|
+
* blocked); an ADMIN default would deny. Unknown servers allow (local
|
|
12
|
+
* observe gateway), subject to the destructive deny.
|
|
13
|
+
*/
|
|
14
|
+
export declare function unmatchedAllowed(serverId: string): boolean;
|
|
15
|
+
/** The OR-allow CEL rule for one server target. */
|
|
16
|
+
export declare function celAllowRule(server: GatewayServer): string;
|
|
17
|
+
/**
|
|
18
|
+
* Standalone gateway YAML: one listener multiplexing every server as an MCP
|
|
19
|
+
* target behind a loopback-only L4 allowlist, generated CEL authorization,
|
|
20
|
+
* OTLP/HTTP traces to the local receiver. `failureMode` (gateways.json,
|
|
21
|
+
* default failOpen) decides whether one broken target takes the gateway down.
|
|
22
|
+
*/
|
|
23
|
+
export declare function generateGatewayYaml(config: GatewaysConfig): string;
|
|
24
|
+
//# sourceMappingURL=config-gen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-gen.d.ts","sourceRoot":"","sources":["../../src/gate/config-gen.ts"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAEjE,uEAAuE;AACvE,eAAO,MAAM,mBAAmB,mDAAmD,CAAC;AAEpF,mEAAmE;AACnE,eAAO,MAAM,aAAa,kFACmD,CAAC;AAE9E,mFAAmF;AACnF,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAGnE;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAE1D;AAMD,mDAAmD;AACnD,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAS1D;AA0CD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CA0ClE"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate the gateway YAML from `.kya/gateways.json` + the MCP server
|
|
3
|
+
* registry tiers. The CEL authorization rules are always derived from the
|
|
4
|
+
* registry — never hand-written:
|
|
5
|
+
*
|
|
6
|
+
* - destructive names (drop|truncate|purge|transfer, word-boundary anchored
|
|
7
|
+
* so `dropdown_select` is untouched) are denied for every server, and
|
|
8
|
+
* this deny always wins (rules are OR-allow, so the deny is expressed as
|
|
9
|
+
* "allow … AND NOT matches(deny)");
|
|
10
|
+
* - the server's ADMIN-tier registry patterns join the deny set;
|
|
11
|
+
* - everything else on the target is allowed: READ → allow, WRITE → allow
|
|
12
|
+
* (observe mode — allowed calls are audited, not blocked), and unmatched
|
|
13
|
+
* tools follow the server's defaultTier, which for every registered
|
|
14
|
+
* server resolves to one of those two allows;
|
|
15
|
+
* - unknown servers get the destructive-name deny only.
|
|
16
|
+
*
|
|
17
|
+
* A tool whose name matches the deny set has no allow rule, so the gateway
|
|
18
|
+
* denies the call (and filters it from tools/list).
|
|
19
|
+
*
|
|
20
|
+
* Listener hardening: the binary binds UNSPECIFIED with no config knob, so
|
|
21
|
+
* exposure is cut at L4 — a frontend networkAuthorization allowlist permits
|
|
22
|
+
* only loopback sources (127.0.0.0/8, ::1) — and the stats/readiness/admin
|
|
23
|
+
* listeners are turned off entirely. Logging is pinned to warn so module
|
|
24
|
+
* noise (and upstream build strings) stays out of gate.log.
|
|
25
|
+
*/
|
|
26
|
+
import { mcpServerAdminPatterns, mcpServerDefaultTier, } from "../mcp-servers.js";
|
|
27
|
+
/** Destructive-name family denied on every target, registry or not. */
|
|
28
|
+
export const DESTRUCTIVE_PATTERN = "(?:^|_)(?:drop|truncate|purge|transfer)(?:_|$)";
|
|
29
|
+
/** Loopback-only L4 rule for the (wildcard-bound) MCP listener. */
|
|
30
|
+
export const LOOPBACK_RULE = 'cidr("127.0.0.0/8").containsIP(source.address) || source.address == "::1"';
|
|
31
|
+
/** Deny patterns for one server: destructive family + its ADMIN registry rules. */
|
|
32
|
+
export function denyPatternsFor(serverId) {
|
|
33
|
+
const admin = mcpServerAdminPatterns(serverId) ?? [];
|
|
34
|
+
return [...new Set([DESTRUCTIVE_PATTERN, ...admin])];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Whether an unmatched tool on this server is allowed: the registry
|
|
38
|
+
* defaultTier — READ and WRITE both map to allow (WRITE is observed, not
|
|
39
|
+
* blocked); an ADMIN default would deny. Unknown servers allow (local
|
|
40
|
+
* observe gateway), subject to the destructive deny.
|
|
41
|
+
*/
|
|
42
|
+
export function unmatchedAllowed(serverId) {
|
|
43
|
+
return mcpServerDefaultTier(serverId) !== "ADMIN";
|
|
44
|
+
}
|
|
45
|
+
function celString(s) {
|
|
46
|
+
return `'${s.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
47
|
+
}
|
|
48
|
+
/** The OR-allow CEL rule for one server target. */
|
|
49
|
+
export function celAllowRule(server) {
|
|
50
|
+
const target = `mcp.tool.target == ${celString(server.id)}`;
|
|
51
|
+
const deny = denyPatternsFor(server.id).join("|");
|
|
52
|
+
if (!unmatchedAllowed(server.id)) {
|
|
53
|
+
// ADMIN defaultTier: only explicitly non-denied, non-admin tools may run —
|
|
54
|
+
// allow nothing unmatched (no registered server has this today).
|
|
55
|
+
return `${target} && false`;
|
|
56
|
+
}
|
|
57
|
+
return `${target} && !mcp.tool.name.matches(${celString(deny)})`;
|
|
58
|
+
}
|
|
59
|
+
function q(s) {
|
|
60
|
+
return JSON.stringify(s);
|
|
61
|
+
}
|
|
62
|
+
function indent(lines, pad) {
|
|
63
|
+
return lines.map((l) => (l ? pad + l : l));
|
|
64
|
+
}
|
|
65
|
+
function targetYaml(server) {
|
|
66
|
+
const lines = [`- name: ${q(server.id)}`];
|
|
67
|
+
if (server.transport === "stdio") {
|
|
68
|
+
const [cmd, ...args] = server.cmd;
|
|
69
|
+
lines.push(" stdio:");
|
|
70
|
+
lines.push(` cmd: ${q(cmd)}`);
|
|
71
|
+
if (args.length > 0) {
|
|
72
|
+
lines.push(" args:");
|
|
73
|
+
lines.push(...args.map((a) => ` - ${q(a)}`));
|
|
74
|
+
}
|
|
75
|
+
if (server.env && Object.keys(server.env).length > 0) {
|
|
76
|
+
lines.push(" env:");
|
|
77
|
+
for (const [k, v] of Object.entries(server.env)) {
|
|
78
|
+
lines.push(` ${q(k)}: ${q(v)}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
lines.push(" mcp:");
|
|
84
|
+
lines.push(` host: ${q(server.url)}`);
|
|
85
|
+
if (server.headers && Object.keys(server.headers).length > 0) {
|
|
86
|
+
// Transport policy on the http target: static auth headers.
|
|
87
|
+
lines.push(" policies:");
|
|
88
|
+
lines.push(" requestHeaderModifier:");
|
|
89
|
+
lines.push(" set:");
|
|
90
|
+
for (const [k, v] of Object.entries(server.headers)) {
|
|
91
|
+
lines.push(` ${q(k)}: ${q(v)}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return lines;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Standalone gateway YAML: one listener multiplexing every server as an MCP
|
|
99
|
+
* target behind a loopback-only L4 allowlist, generated CEL authorization,
|
|
100
|
+
* OTLP/HTTP traces to the local receiver. `failureMode` (gateways.json,
|
|
101
|
+
* default failOpen) decides whether one broken target takes the gateway down.
|
|
102
|
+
*/
|
|
103
|
+
export function generateGatewayYaml(config) {
|
|
104
|
+
const lines = [
|
|
105
|
+
"# Generated by kya gate — regenerate with `kya gate run` (do not edit).",
|
|
106
|
+
"config:",
|
|
107
|
+
' statsAddr: "off"',
|
|
108
|
+
' readinessAddr: "off"',
|
|
109
|
+
' adminAddr: "off"',
|
|
110
|
+
" logging:",
|
|
111
|
+
' level: "warn"',
|
|
112
|
+
" tracing:",
|
|
113
|
+
` otlpEndpoint: ${q(`http://127.0.0.1:${config.otlpPort}`)}`,
|
|
114
|
+
` otlpProtocol: "http"`,
|
|
115
|
+
" randomSampling: true",
|
|
116
|
+
"frontendPolicies:",
|
|
117
|
+
" networkAuthorization:",
|
|
118
|
+
" rules:",
|
|
119
|
+
` - allow: ${q(LOOPBACK_RULE)}`,
|
|
120
|
+
"binds:",
|
|
121
|
+
` - port: ${config.port}`,
|
|
122
|
+
" listeners:",
|
|
123
|
+
" - routes:",
|
|
124
|
+
" - backends:",
|
|
125
|
+
" - mcp:",
|
|
126
|
+
` failureMode: ${q(config.failureMode)}`,
|
|
127
|
+
];
|
|
128
|
+
if (config.servers.length === 0) {
|
|
129
|
+
lines.push(" targets: []");
|
|
130
|
+
return `${lines.join("\n")}\n`;
|
|
131
|
+
}
|
|
132
|
+
lines.push(" targets:");
|
|
133
|
+
for (const server of config.servers) {
|
|
134
|
+
lines.push(...indent(targetYaml(server), " "));
|
|
135
|
+
}
|
|
136
|
+
// Backend-level policies: sibling of `mcp`, applies to the whole target set
|
|
137
|
+
// (per-target rules match on mcp.tool.target inside the CEL).
|
|
138
|
+
lines.push(" policies:");
|
|
139
|
+
lines.push(" mcpAuthorization:");
|
|
140
|
+
lines.push(" rules:");
|
|
141
|
+
for (const server of config.servers) {
|
|
142
|
+
lines.push(` - ${q(celAllowRule(server))}`);
|
|
143
|
+
}
|
|
144
|
+
return `${lines.join("\n")}\n`;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=config-gen.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-gen.js","sourceRoot":"","sources":["../../src/gate/config-gen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EACL,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAG3B,uEAAuE;AACvE,MAAM,CAAC,MAAM,mBAAmB,GAAG,gDAAgD,CAAC;AAEpF,mEAAmE;AACnE,MAAM,CAAC,MAAM,aAAa,GACxB,2EAA2E,CAAC;AAE9E,mFAAmF;AACnF,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,MAAM,KAAK,GAAG,sBAAsB,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;IACrD,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,mBAAmB,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,OAAO,oBAAoB,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC;AACpD,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC;AAC9D,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,YAAY,CAAC,MAAqB;IAChD,MAAM,MAAM,GAAG,sBAAsB,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;IAC5D,MAAM,IAAI,GAAG,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClD,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;QACjC,2EAA2E;QAC3E,iEAAiE;QACjE,OAAO,GAAG,MAAM,WAAW,CAAC;IAC9B,CAAC;IACD,OAAO,GAAG,MAAM,8BAA8B,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC;AACnE,CAAC;AAED,SAAS,CAAC,CAAC,CAAS;IAClB,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,MAAM,CAAC,KAAe,EAAE,GAAW;IAC1C,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,UAAU,CAAC,MAAqB;IACvC,MAAM,KAAK,GAAa,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACpD,IAAI,MAAM,CAAC,SAAS,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,MAAM,CAAC,GAAI,CAAC;QACnC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,GAAI,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACpD,CAAC;QACD,IAAI,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACrD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACvB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;gBAChD,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;IACH,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,GAAI,CAAC,EAAE,CAAC,CAAC;QAC1C,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7D,4DAA4D;YAC5D,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC1B,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;YACzC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACzB,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBACpD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAsB;IACxD,MAAM,KAAK,GAAa;QACtB,yEAAyE;QACzE,SAAS;QACT,oBAAoB;QACpB,wBAAwB;QACxB,oBAAoB;QACpB,YAAY;QACZ,mBAAmB;QACnB,YAAY;QACZ,qBAAqB,CAAC,CAAC,oBAAoB,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE;QAC/D,0BAA0B;QAC1B,0BAA0B;QAC1B,mBAAmB;QACnB,yBAAyB;QACzB,YAAY;QACZ,kBAAkB,CAAC,CAAC,aAAa,CAAC,EAAE;QACpC,QAAQ;QACR,aAAa,MAAM,CAAC,IAAI,EAAE;QAC1B,gBAAgB;QAChB,iBAAiB;QACjB,uBAAuB;QACvB,sBAAsB;QACtB,kCAAkC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE;KAC1D,CAAC;IACF,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAC5C,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IACjC,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IACzC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,sBAAsB,CAAC,CAAC,CAAC;IACpE,CAAC;IACD,4EAA4E;IAC5E,8DAA8D;IAC9D,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IACxC,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAC;IAClD,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IACzC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACpC,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface GatewayServer {
|
|
2
|
+
readonly id: string;
|
|
3
|
+
readonly transport: "stdio" | "http";
|
|
4
|
+
readonly cmd?: readonly string[];
|
|
5
|
+
readonly url?: string;
|
|
6
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
7
|
+
/** http only: request headers for the remote server (auth tokens go here). */
|
|
8
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
9
|
+
}
|
|
10
|
+
export type GateFailureMode = "failOpen" | "failClosed";
|
|
11
|
+
export interface GatewaysConfig {
|
|
12
|
+
/** Listener port on 127.0.0.1 (default 3930). */
|
|
13
|
+
readonly port: number;
|
|
14
|
+
/** Local OTLP/HTTP receiver port (default 3931). */
|
|
15
|
+
readonly otlpPort: number;
|
|
16
|
+
/**
|
|
17
|
+
* Gateway behavior when a target fails to initialize: failOpen serves the
|
|
18
|
+
* healthy targets (default, better local UX); failClosed takes the whole
|
|
19
|
+
* gateway down (strict — a silently missing server is impossible).
|
|
20
|
+
*/
|
|
21
|
+
readonly failureMode: GateFailureMode;
|
|
22
|
+
readonly servers: readonly GatewayServer[];
|
|
23
|
+
}
|
|
24
|
+
export declare const GATE_DEFAULT_PORT = 3930;
|
|
25
|
+
export declare const GATE_DEFAULT_OTLP_PORT = 3931;
|
|
26
|
+
export declare function gatewaysPath(env?: NodeJS.ProcessEnv): string;
|
|
27
|
+
/** Validate raw parsed JSON into a GatewaysConfig. Unknown top-level keys (recipes) are ignored. */
|
|
28
|
+
export declare function validateGateways(raw: unknown): GatewaysConfig;
|
|
29
|
+
export declare function readGateways(env?: NodeJS.ProcessEnv): GatewaysConfig;
|
|
30
|
+
/**
|
|
31
|
+
* Scaffold `.kya/gateways.json`: an empty active `servers` list plus the
|
|
32
|
+
* `recipes` catalog — move a recipe object into `servers` and fill its
|
|
33
|
+
* placeholders to enable it. Idempotent: an existing file is left alone.
|
|
34
|
+
*/
|
|
35
|
+
export declare function scaffoldGateways(env?: NodeJS.ProcessEnv): {
|
|
36
|
+
path: string;
|
|
37
|
+
created: boolean;
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/gate/config.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,OAAO,GAAG,MAAM,CAAC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAChD,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD;AAED,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,YAAY,CAAC;AAExD,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAC;IACtC,QAAQ,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,CAAC;CAC5C;AAED,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,sBAAsB,OAAO,CAAC;AAE3C,wBAAgB,YAAY,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAEzE;AAsFD,oGAAoG;AACpG,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAuB7D;AAED,wBAAgB,YAAY,CAC1B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,cAAc,CAYhB;AA6BD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAepC"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `.kya/gateways.json` — the upstream MCP servers the local kya gateway
|
|
3
|
+
* federates. Strict JSON (hand-editable, merge-safe); `kya gate init` seeds
|
|
4
|
+
* it with a `recipes` catalog of ready-to-move entries for the well-known
|
|
5
|
+
* servers from the MCP server registry.
|
|
6
|
+
*/
|
|
7
|
+
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { globalConfigDir } from "../config.js";
|
|
10
|
+
import { UsageError } from "../errors.js";
|
|
11
|
+
import { atomicWriteSync } from "../fs-atomic.js";
|
|
12
|
+
export const GATE_DEFAULT_PORT = 3930;
|
|
13
|
+
export const GATE_DEFAULT_OTLP_PORT = 3931;
|
|
14
|
+
export function gatewaysPath(env = process.env) {
|
|
15
|
+
return join(globalConfigDir(env), "gateways.json");
|
|
16
|
+
}
|
|
17
|
+
const TARGET_ID_RE = /^[a-z0-9][a-z0-9-]*$/;
|
|
18
|
+
function isPlainObject(v) {
|
|
19
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
20
|
+
}
|
|
21
|
+
function parsePort(raw, key, fallback) {
|
|
22
|
+
if (raw === undefined)
|
|
23
|
+
return fallback;
|
|
24
|
+
if (typeof raw !== "number" || !Number.isInteger(raw) || raw < 1 || raw > 65535) {
|
|
25
|
+
throw new UsageError(`gateways.json: "${key}" must be an integer port 1-65535`);
|
|
26
|
+
}
|
|
27
|
+
return raw;
|
|
28
|
+
}
|
|
29
|
+
function parseServer(raw, index) {
|
|
30
|
+
const where = `gateways.json: servers[${index}]`;
|
|
31
|
+
if (!isPlainObject(raw))
|
|
32
|
+
throw new UsageError(`${where} must be an object`);
|
|
33
|
+
const id = raw.id;
|
|
34
|
+
if (typeof id !== "string" || !TARGET_ID_RE.test(id)) {
|
|
35
|
+
throw new UsageError(`${where}.id must match ${TARGET_ID_RE} (the gateway rejects underscores in target names)`);
|
|
36
|
+
}
|
|
37
|
+
const transport = raw.transport;
|
|
38
|
+
if (transport !== "stdio" && transport !== "http") {
|
|
39
|
+
throw new UsageError(`${where}.transport must be "stdio" or "http"`);
|
|
40
|
+
}
|
|
41
|
+
let cmd;
|
|
42
|
+
if (raw.cmd !== undefined) {
|
|
43
|
+
if (!Array.isArray(raw.cmd) ||
|
|
44
|
+
raw.cmd.length === 0 ||
|
|
45
|
+
raw.cmd.some((c) => typeof c !== "string" || c.length === 0)) {
|
|
46
|
+
throw new UsageError(`${where}.cmd must be a non-empty array of strings`);
|
|
47
|
+
}
|
|
48
|
+
cmd = raw.cmd;
|
|
49
|
+
}
|
|
50
|
+
let url;
|
|
51
|
+
if (raw.url !== undefined) {
|
|
52
|
+
if (typeof raw.url !== "string" || !/^https?:\/\//.test(raw.url)) {
|
|
53
|
+
throw new UsageError(`${where}.url must be an http(s) URL`);
|
|
54
|
+
}
|
|
55
|
+
url = raw.url;
|
|
56
|
+
}
|
|
57
|
+
let env;
|
|
58
|
+
if (raw.env !== undefined) {
|
|
59
|
+
if (!isPlainObject(raw.env) || Object.values(raw.env).some((v) => typeof v !== "string")) {
|
|
60
|
+
throw new UsageError(`${where}.env must be an object of string values`);
|
|
61
|
+
}
|
|
62
|
+
env = raw.env;
|
|
63
|
+
}
|
|
64
|
+
let headers;
|
|
65
|
+
if (raw.headers !== undefined) {
|
|
66
|
+
if (!isPlainObject(raw.headers) || Object.values(raw.headers).some((v) => typeof v !== "string")) {
|
|
67
|
+
throw new UsageError(`${where}.headers must be an object of string values`);
|
|
68
|
+
}
|
|
69
|
+
headers = raw.headers;
|
|
70
|
+
}
|
|
71
|
+
if (transport === "stdio" && !cmd) {
|
|
72
|
+
throw new UsageError(`${where}: transport "stdio" requires "cmd"`);
|
|
73
|
+
}
|
|
74
|
+
if (transport === "http" && !url) {
|
|
75
|
+
throw new UsageError(`${where}: transport "http" requires "url"`);
|
|
76
|
+
}
|
|
77
|
+
if (transport === "http" && env) {
|
|
78
|
+
// The gateway's http targets have no env concept; auth travels as headers.
|
|
79
|
+
throw new UsageError(`${where}: transport "http" does not support "env" — use "headers" (e.g. {"authorization": "Bearer …"})`);
|
|
80
|
+
}
|
|
81
|
+
if (transport === "stdio" && headers) {
|
|
82
|
+
throw new UsageError(`${where}: "headers" only applies to transport "http"`);
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
id,
|
|
86
|
+
transport,
|
|
87
|
+
...(cmd ? { cmd } : {}),
|
|
88
|
+
...(url ? { url } : {}),
|
|
89
|
+
...(env ? { env } : {}),
|
|
90
|
+
...(headers ? { headers } : {}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** Validate raw parsed JSON into a GatewaysConfig. Unknown top-level keys (recipes) are ignored. */
|
|
94
|
+
export function validateGateways(raw) {
|
|
95
|
+
if (!isPlainObject(raw))
|
|
96
|
+
throw new UsageError("gateways.json must be a JSON object");
|
|
97
|
+
const port = parsePort(raw.port, "port", GATE_DEFAULT_PORT);
|
|
98
|
+
const otlpPort = parsePort(raw.otlpPort, "otlpPort", GATE_DEFAULT_OTLP_PORT);
|
|
99
|
+
let failureMode = "failOpen";
|
|
100
|
+
if (raw.failureMode !== undefined) {
|
|
101
|
+
if (raw.failureMode !== "failOpen" && raw.failureMode !== "failClosed") {
|
|
102
|
+
throw new UsageError('gateways.json: "failureMode" must be "failOpen" or "failClosed"');
|
|
103
|
+
}
|
|
104
|
+
failureMode = raw.failureMode;
|
|
105
|
+
}
|
|
106
|
+
if (raw.servers !== undefined && !Array.isArray(raw.servers)) {
|
|
107
|
+
throw new UsageError('gateways.json: "servers" must be an array');
|
|
108
|
+
}
|
|
109
|
+
const servers = (raw.servers ?? []).map(parseServer);
|
|
110
|
+
const seen = new Set();
|
|
111
|
+
for (const s of servers) {
|
|
112
|
+
if (seen.has(s.id)) {
|
|
113
|
+
throw new UsageError(`gateways.json: duplicate server id "${s.id}"`);
|
|
114
|
+
}
|
|
115
|
+
seen.add(s.id);
|
|
116
|
+
}
|
|
117
|
+
return { port, otlpPort, failureMode, servers };
|
|
118
|
+
}
|
|
119
|
+
export function readGateways(env = process.env) {
|
|
120
|
+
const path = gatewaysPath(env);
|
|
121
|
+
if (!existsSync(path)) {
|
|
122
|
+
return { port: GATE_DEFAULT_PORT, otlpPort: GATE_DEFAULT_OTLP_PORT, failureMode: "failOpen", servers: [] };
|
|
123
|
+
}
|
|
124
|
+
let raw;
|
|
125
|
+
try {
|
|
126
|
+
raw = JSON.parse(readFileSync(path, "utf8"));
|
|
127
|
+
}
|
|
128
|
+
catch {
|
|
129
|
+
throw new UsageError(`${path} is not valid JSON — fix it by hand, then re-run kya gate run`);
|
|
130
|
+
}
|
|
131
|
+
return validateGateways(raw);
|
|
132
|
+
}
|
|
133
|
+
const RECIPES = [
|
|
134
|
+
{ id: "playwright", transport: "stdio", cmd: ["npx", "-y", "@playwright/mcp@latest"], note: "Browser automation" },
|
|
135
|
+
{ id: "github", transport: "http", url: "https://api.githubcopilot.com/mcp/", headers: { authorization: "Bearer <github-pat>" }, note: "GitHub (remote; auth travels as a header — the gateway's http targets have no env)" },
|
|
136
|
+
{ id: "slack", transport: "stdio", cmd: ["npx", "-y", "@modelcontextprotocol/server-slack"], env: { SLACK_BOT_TOKEN: "<xoxb-…>", SLACK_TEAM_ID: "<T…>" }, note: "Slack workspace" },
|
|
137
|
+
{ id: "postgresql", transport: "stdio", cmd: ["npx", "-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"], note: "PostgreSQL (pass the connection string as the last arg)" },
|
|
138
|
+
{ id: "filesystem", transport: "stdio", cmd: ["npx", "-y", "@modelcontextprotocol/server-filesystem", "."], note: "Local filesystem (scope = last args)" },
|
|
139
|
+
{ id: "context7", transport: "http", url: "https://mcp.context7.com/mcp", note: "Library docs" },
|
|
140
|
+
{ id: "figma", transport: "http", url: "https://mcp.figma.com/mcp", note: "Figma Dev Mode (remote)" },
|
|
141
|
+
{ id: "browser-use", transport: "stdio", cmd: ["uvx", "browser-use", "--mcp"], note: "Browser Use agent" },
|
|
142
|
+
{ id: "chrome-devtools", transport: "stdio", cmd: ["npx", "-y", "chrome-devtools-mcp@latest"], note: "Chrome DevTools" },
|
|
143
|
+
{ id: "atlassian", transport: "http", url: "https://mcp.atlassian.com/v1/sse", note: "Jira/Confluence (remote, OAuth)" },
|
|
144
|
+
{ id: "notion", transport: "http", url: "https://mcp.notion.com/mcp", note: "Notion (remote)" },
|
|
145
|
+
{ id: "supabase", transport: "stdio", cmd: ["npx", "-y", "@supabase/mcp-server-supabase@latest"], env: { SUPABASE_ACCESS_TOKEN: "<sbp_…>" }, note: "Supabase projects" },
|
|
146
|
+
{ id: "firecrawl", transport: "stdio", cmd: ["npx", "-y", "firecrawl-mcp"], env: { FIRECRAWL_API_KEY: "<fc-…>" }, note: "Web scraping" },
|
|
147
|
+
{ id: "sequential-thinking", transport: "stdio", cmd: ["npx", "-y", "@modelcontextprotocol/server-sequential-thinking"], note: "Reasoning scratchpad" },
|
|
148
|
+
{ id: "n8n", transport: "stdio", cmd: ["npx", "-y", "n8n-mcp"], note: "n8n workflows" },
|
|
149
|
+
{ id: "linear", transport: "http", url: "https://mcp.linear.app/sse", note: "Linear (remote, OAuth)" },
|
|
150
|
+
{ id: "serena", transport: "stdio", cmd: ["uvx", "--from", "git+https://github.com/oraios/serena", "serena-mcp-server"], note: "Code navigation" },
|
|
151
|
+
{ id: "sentry", transport: "http", url: "https://mcp.sentry.dev/mcp", note: "Sentry (remote, OAuth)" },
|
|
152
|
+
{ id: "zapier", transport: "http", url: "https://mcp.zapier.com/api/mcp/mcp", note: "Zapier actions (use your own MCP URL)" },
|
|
153
|
+
{ id: "exa", transport: "http", url: "https://mcp.exa.ai/mcp", note: "Web search" },
|
|
154
|
+
];
|
|
155
|
+
/**
|
|
156
|
+
* Scaffold `.kya/gateways.json`: an empty active `servers` list plus the
|
|
157
|
+
* `recipes` catalog — move a recipe object into `servers` and fill its
|
|
158
|
+
* placeholders to enable it. Idempotent: an existing file is left alone.
|
|
159
|
+
*/
|
|
160
|
+
export function scaffoldGateways(env = process.env) {
|
|
161
|
+
const path = gatewaysPath(env);
|
|
162
|
+
if (existsSync(path))
|
|
163
|
+
return { path, created: false };
|
|
164
|
+
mkdirSync(globalConfigDir(env), { recursive: true });
|
|
165
|
+
const doc = {
|
|
166
|
+
port: GATE_DEFAULT_PORT,
|
|
167
|
+
// failOpen: one broken target never takes the gateway down (a missing
|
|
168
|
+
// server then fails silently — its tools just vanish). failClosed is the
|
|
169
|
+
// strict choice: any broken target stops the whole gateway.
|
|
170
|
+
failureMode: "failOpen",
|
|
171
|
+
servers: [],
|
|
172
|
+
recipes: RECIPES.map(({ note, ...entry }) => ({ note, ...entry })),
|
|
173
|
+
};
|
|
174
|
+
atomicWriteSync(path, `${JSON.stringify(doc, null, 2)}\n`);
|
|
175
|
+
return { path, created: true };
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=config.js.map
|