@agentwares/agentguard 0.1.9 → 0.1.10
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/CHANGELOG.md +33 -0
- package/dist/audit-5LUDXZLG.js +18 -0
- package/dist/chunk-2QDPPTPY.js +179 -0
- package/dist/chunk-2QDPPTPY.js.map +1 -0
- package/dist/{chunk-SUXQTT3X.js → chunk-4WTFMFRY.js} +18 -16
- package/dist/chunk-4WTFMFRY.js.map +1 -0
- package/dist/{chunk-VQWQ5TOM.js → chunk-DEVXG3IB.js} +4 -4
- package/dist/chunk-DEVXG3IB.js.map +1 -0
- package/dist/chunk-F73VDY3W.js +202 -0
- package/dist/chunk-F73VDY3W.js.map +1 -0
- package/dist/{chunk-X4M7YWQA.js → chunk-IEJK7N3B.js} +32 -27
- package/dist/chunk-IEJK7N3B.js.map +1 -0
- package/dist/{chunk-ZSLWPKXI.js → chunk-IS3DAHZI.js} +562 -8
- package/dist/chunk-IS3DAHZI.js.map +1 -0
- package/dist/{chunk-KRKZGAJ3.js → chunk-JSELR4SG.js} +66 -55
- package/dist/chunk-JSELR4SG.js.map +1 -0
- package/dist/{chunk-TW5KJREH.js → chunk-OM5L7A32.js} +20 -11
- package/dist/chunk-OM5L7A32.js.map +1 -0
- package/dist/{chunk-HPYZ3JDX.js → chunk-SWZQMPDG.js} +3 -3
- package/dist/{chunk-HPYZ3JDX.js.map → chunk-SWZQMPDG.js.map} +1 -1
- package/dist/{chunk-D66U3PVB.js → chunk-TJXZBOHL.js} +6 -6
- package/dist/chunk-TJXZBOHL.js.map +1 -0
- package/dist/{chunk-BKXXTWIS.js → chunk-XOBFANL4.js} +5 -5
- package/dist/chunk-XOBFANL4.js.map +1 -0
- package/dist/chunk-XPNBYSIN.js +23 -0
- package/dist/chunk-XPNBYSIN.js.map +1 -0
- package/dist/{chunk-6S7LYVOC.js → chunk-YBVD6HTT.js} +27 -24
- package/dist/chunk-YBVD6HTT.js.map +1 -0
- package/dist/{chunk-6TUQD666.js → chunk-ZG4LGUJE.js} +100 -81
- package/dist/chunk-ZG4LGUJE.js.map +1 -0
- package/dist/cli.js +6 -4
- package/dist/fixtures/crm-server.js +2 -2
- package/dist/fixtures/demo-agent.js +1 -1
- package/dist/index.d.ts +5 -5
- package/dist/index.js +23 -21
- package/dist/index.js.map +1 -1
- package/dist/init-MKPQU2JG.js +17 -0
- package/dist/{proxy-3Z5YEZ4R.js → proxy-6GP63TLD.js} +21 -29
- package/dist/proxy-6GP63TLD.js.map +1 -0
- package/dist/tools-XS7PMTLT.js +15 -0
- package/llms.txt +8 -6
- package/package.json +10 -4
- package/server.json +9 -9
- package/dist/audit-2YCMHMCP.js +0 -17
- package/dist/chunk-3O6KWT3E.js +0 -345
- package/dist/chunk-3O6KWT3E.js.map +0 -1
- package/dist/chunk-6S7LYVOC.js.map +0 -1
- package/dist/chunk-6TUQD666.js.map +0 -1
- package/dist/chunk-BKXXTWIS.js.map +0 -1
- package/dist/chunk-D66U3PVB.js.map +0 -1
- package/dist/chunk-KRKZGAJ3.js.map +0 -1
- package/dist/chunk-SUXQTT3X.js.map +0 -1
- package/dist/chunk-TW5KJREH.js.map +0 -1
- package/dist/chunk-VQWQ5TOM.js.map +0 -1
- package/dist/chunk-X4M7YWQA.js.map +0 -1
- package/dist/chunk-ZSLWPKXI.js.map +0 -1
- package/dist/init-CWROGV5I.js +0 -15
- package/dist/proxy-3Z5YEZ4R.js.map +0 -1
- package/dist/tools-3LLDG3XQ.js +0 -15
- /package/dist/{audit-2YCMHMCP.js.map → audit-5LUDXZLG.js.map} +0 -0
- /package/dist/{init-CWROGV5I.js.map → init-MKPQU2JG.js.map} +0 -0
- /package/dist/{tools-3LLDG3XQ.js.map → tools-XS7PMTLT.js.map} +0 -0
|
@@ -5,11 +5,14 @@ import {
|
|
|
5
5
|
listToolManifest,
|
|
6
6
|
localhostHosts,
|
|
7
7
|
toolError
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-IS3DAHZI.js";
|
|
9
|
+
import {
|
|
10
|
+
RUN
|
|
11
|
+
} from "./chunk-XPNBYSIN.js";
|
|
9
12
|
import {
|
|
10
13
|
registrationPath,
|
|
11
14
|
version
|
|
12
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-4WTFMFRY.js";
|
|
13
16
|
|
|
14
17
|
// src/proxy/own-tools.ts
|
|
15
18
|
import {
|
|
@@ -18,11 +21,12 @@ import {
|
|
|
18
21
|
listRuns,
|
|
19
22
|
parseAuditJsonl,
|
|
20
23
|
renderReportMarkdown,
|
|
24
|
+
resolveToolName,
|
|
21
25
|
verifyChain
|
|
22
26
|
} from "@agentwares/agentguard-core";
|
|
23
27
|
import { existsSync, readFileSync } from "fs";
|
|
24
28
|
import { z } from "zod";
|
|
25
|
-
var INIT_COMMAND =
|
|
29
|
+
var INIT_COMMAND = `${RUN} init`;
|
|
26
30
|
var READ_ONLY = {
|
|
27
31
|
readOnlyHint: true,
|
|
28
32
|
destructiveHint: false,
|
|
@@ -47,7 +51,7 @@ function unreadable(path, error) {
|
|
|
47
51
|
return toolError({
|
|
48
52
|
code: "AUDIT_UNREADABLE",
|
|
49
53
|
cause: `the audit log at ${path} could not be read: ${error}`,
|
|
50
|
-
fix: "call
|
|
54
|
+
fix: "call okgate_verify_audit_log to see where it breaks; a hand-edited or truncated line has to be restored from a copy",
|
|
51
55
|
retryable: false
|
|
52
56
|
});
|
|
53
57
|
}
|
|
@@ -58,23 +62,21 @@ function numbers(caps) {
|
|
|
58
62
|
}
|
|
59
63
|
function nextStep(runtime) {
|
|
60
64
|
if (!runtime.configured)
|
|
61
|
-
return `
|
|
65
|
+
return `okgate is guarding nothing: no policy file at ${runtime.loaded.path}. Run \`${INIT_COMMAND}\` in the project directory: it writes okgate.yaml in dry-run mode and routes the project's MCP servers through okgate (backup kept, \`--undo\` restores). Then restart the MCP client.`;
|
|
62
66
|
if (runtime.policy.upstreams.length === 0)
|
|
63
|
-
return `${runtime.loaded.path} lists no upstream servers, so
|
|
64
|
-
return "
|
|
67
|
+
return `${runtime.loaded.path} lists no upstream servers, so okgate is guarding nothing. Add the MCP servers your agent uses under \`upstreams:\` in that file (it has commented examples), then restart the MCP client.`;
|
|
68
|
+
return "okgate is running; run your agent, then read okgate_get_report.";
|
|
65
69
|
}
|
|
66
70
|
var StatusOutput = z.object({
|
|
67
|
-
configured: z.boolean().describe(
|
|
68
|
-
"true when a policy file was found and loaded; false means agentguard guards nothing"
|
|
69
|
-
),
|
|
71
|
+
configured: z.boolean().describe("true when a policy file was found and loaded; false means okgate guards nothing"),
|
|
70
72
|
policy_path: z.string().describe("absolute path of the policy file read, or looked for"),
|
|
71
73
|
mode: z.enum(["dry-run", "enforce"]).describe("dry-run fakes writes and spends and records them; enforce lets allowed calls run"),
|
|
72
74
|
upstreams: z.array(
|
|
73
75
|
z.object({
|
|
74
76
|
name: z.string().describe("upstream name from the policy"),
|
|
75
|
-
connected: z.boolean().describe("whether
|
|
77
|
+
connected: z.boolean().describe("whether okgate is connected to it"),
|
|
76
78
|
tools: z.number().int().describe("tools it exposes"),
|
|
77
|
-
transport: z.enum(["stdio", "http"]).describe("how
|
|
79
|
+
transport: z.enum(["stdio", "http"]).describe("how okgate reaches it"),
|
|
78
80
|
error: z.string().optional().describe("why it is not connected")
|
|
79
81
|
})
|
|
80
82
|
).describe("the MCP servers this proxy fronts; empty means none are configured"),
|
|
@@ -100,7 +102,7 @@ var StatusOutput = z.object({
|
|
|
100
102
|
next_step: z.string().describe("the one thing to do next, with the command when there is one")
|
|
101
103
|
});
|
|
102
104
|
var ReportOutput = z.object({
|
|
103
|
-
configured: z.boolean().describe("false when no policy file was found (
|
|
105
|
+
configured: z.boolean().describe("false when no policy file was found (okgate guards nothing)"),
|
|
104
106
|
audit_log_path: z.string().describe("absolute path of the audit log the report was built from"),
|
|
105
107
|
run_id: z.string().nullable().describe("the run reported on; null when the log has no runs"),
|
|
106
108
|
runs_in_log: z.number().int().describe("how many runs the audit log holds"),
|
|
@@ -128,12 +130,12 @@ var ReportOutput = z.object({
|
|
|
128
130
|
tool: z.string().describe("the tool that was stopped"),
|
|
129
131
|
cause: z.string().describe("why")
|
|
130
132
|
})
|
|
131
|
-
).describe("every call
|
|
133
|
+
).describe("every call okgate stopped, in order"),
|
|
132
134
|
top_tools: z.array(z.object({ tool: z.string(), calls: z.number().int(), class: z.string() })).describe("the most-called tools with their class (read, write, spend)"),
|
|
133
|
-
markdown: z.string().describe("the same report `
|
|
135
|
+
markdown: z.string().describe("the same report `okgate report` prints, as Markdown")
|
|
134
136
|
});
|
|
135
137
|
var VerifyOutput = z.object({
|
|
136
|
-
configured: z.boolean().describe("false when no policy file was found (
|
|
138
|
+
configured: z.boolean().describe("false when no policy file was found (okgate guards nothing)"),
|
|
137
139
|
path: z.string().describe("absolute path of the audit log checked"),
|
|
138
140
|
exists: z.boolean().describe("false when no call has been recorded yet; an absent log verifies"),
|
|
139
141
|
ok: z.boolean().describe("true when every entry's hash and prev_hash recompute"),
|
|
@@ -146,12 +148,12 @@ var VerifyOutput = z.object({
|
|
|
146
148
|
});
|
|
147
149
|
function createOwnTools(runtime) {
|
|
148
150
|
const status = defineTool({
|
|
149
|
-
name: "
|
|
150
|
-
title: "
|
|
151
|
-
description: "Report what
|
|
151
|
+
name: "okgate_get_status",
|
|
152
|
+
title: "okgate status",
|
|
153
|
+
description: "Report what okgate is guarding right now: the policy file it loaded (or that none was found), dry-run or enforce mode, each upstream MCP server and whether it connected, a run's cap usage and remaining budget, the kill switch, and pending approvals. Call it first to learn whether okgate is set up; next_step says what to do when it is not. For what a run did, use okgate_get_report; to check the log was not edited, okgate_verify_audit_log. Reads local files only and changes nothing.",
|
|
152
154
|
input: z.strictObject({ run_id: runIdInput }),
|
|
153
155
|
output: StatusOutput,
|
|
154
|
-
annotations: { title: "
|
|
156
|
+
annotations: { title: "okgate status", ...READ_ONLY },
|
|
155
157
|
async handler({ run_id }) {
|
|
156
158
|
const { loaded, guard } = runtime;
|
|
157
159
|
const audit = readAudit(loaded.auditPath);
|
|
@@ -180,12 +182,12 @@ function createOwnTools(runtime) {
|
|
|
180
182
|
}
|
|
181
183
|
});
|
|
182
184
|
const report = defineTool({
|
|
183
|
-
name: "
|
|
184
|
-
title: "
|
|
185
|
-
description: "Summarize one run from
|
|
185
|
+
name: "okgate_get_report",
|
|
186
|
+
title: "okgate run report",
|
|
187
|
+
description: "Summarize one run from okgate's audit log: how many tool calls, what dry-run mode faked (records it would have created, updated or deleted, messages sent, dollars spent), what really ran upstream, and every call okgate halted with its code and cause. Defaults to the most recent run. Use it after an agent run, before switching a policy from dry-run to enforce; for live caps and the kill switch use okgate_get_status. Read-only: reads the audit file and does not record this call.",
|
|
186
188
|
input: z.strictObject({ run_id: runIdInput }),
|
|
187
189
|
output: ReportOutput,
|
|
188
|
-
annotations: { title: "
|
|
190
|
+
annotations: { title: "okgate run report", ...READ_ONLY },
|
|
189
191
|
handler({ run_id }) {
|
|
190
192
|
const { loaded } = runtime;
|
|
191
193
|
const audit = readAudit(loaded.auditPath);
|
|
@@ -201,7 +203,7 @@ function createOwnTools(runtime) {
|
|
|
201
203
|
}
|
|
202
204
|
const runId = run_id ?? latestRunId(audit.entries) ?? null;
|
|
203
205
|
const built = buildReport(audit.entries, { runId: runId ?? void 0 });
|
|
204
|
-
const markdown = runId ? renderReportMarkdown(built) : `#
|
|
206
|
+
const markdown = runId ? renderReportMarkdown(built) : `# okgate report
|
|
205
207
|
|
|
206
208
|
No runs recorded in ${loaded.auditPath} yet. ${nextStep(runtime)}`;
|
|
207
209
|
return {
|
|
@@ -232,12 +234,12 @@ No runs recorded in ${loaded.auditPath} yet. ${nextStep(runtime)}`;
|
|
|
232
234
|
}
|
|
233
235
|
});
|
|
234
236
|
const verify = defineTool({
|
|
235
|
-
name: "
|
|
236
|
-
title: "Verify
|
|
237
|
-
description: "Recompute the hash chain of
|
|
237
|
+
name: "okgate_verify_audit_log",
|
|
238
|
+
title: "Verify okgate audit log",
|
|
239
|
+
description: "Recompute the hash chain of okgate's audit log (JSONL, one entry per tool call) and say whether any entry was edited, removed from the middle or reordered, naming the first broken entry. Returns the entry count and head hash; record both elsewhere, because entries cut from the end of the file still verify. Use it before trusting okgate_get_report. Takes no arguments: it checks the log the loaded policy names. Read-only; a log that does not exist yet verifies as empty.",
|
|
238
240
|
input: z.strictObject({}),
|
|
239
241
|
output: VerifyOutput,
|
|
240
|
-
annotations: { title: "Verify
|
|
242
|
+
annotations: { title: "Verify okgate audit log", ...READ_ONLY },
|
|
241
243
|
async handler() {
|
|
242
244
|
const { loaded } = runtime;
|
|
243
245
|
const audit = readAudit(loaded.auditPath);
|
|
@@ -275,10 +277,20 @@ function ownToolsActive(runtime) {
|
|
|
275
277
|
function ownToolList(tools) {
|
|
276
278
|
return listToolManifest(tools);
|
|
277
279
|
}
|
|
278
|
-
async function callOwnTool(tools, name, args, requestId) {
|
|
279
|
-
const
|
|
280
|
+
async function callOwnTool(tools, name, args, requestId, now = /* @__PURE__ */ new Date()) {
|
|
281
|
+
const resolved = resolveToolName(name, (n) => tools.some((t) => t.name === n), now);
|
|
282
|
+
if (resolved.kind === "expired")
|
|
283
|
+
return {
|
|
284
|
+
isError: true,
|
|
285
|
+
content: [{ type: "text", text: JSON.stringify(resolved.error) }],
|
|
286
|
+
_meta: { httpStatus: 404 }
|
|
287
|
+
};
|
|
288
|
+
const tool = tools.find((t) => t.name === resolved.name);
|
|
280
289
|
if (!tool) return void 0;
|
|
281
|
-
|
|
290
|
+
const result = await tool.invoke(args, createToolContext({ requestId }));
|
|
291
|
+
if (resolved.kind === "renamed")
|
|
292
|
+
return { ...result, _meta: { ...result._meta, ...resolved.meta } };
|
|
293
|
+
return result;
|
|
282
294
|
}
|
|
283
295
|
|
|
284
296
|
// src/proxy/server.ts
|
|
@@ -315,23 +327,22 @@ function headersOf(extra) {
|
|
|
315
327
|
function runIdFor(extra, meta, fallback) {
|
|
316
328
|
const header = headerValue(extra, "x-run-id");
|
|
317
329
|
if (header && header.trim()) return header.trim().slice(0, 128);
|
|
318
|
-
const fromMeta = meta?.runId ?? meta?.["agentguard/runId"] ?? meta?.run_id;
|
|
330
|
+
const fromMeta = meta?.runId ?? meta?.["okgate/runId"] ?? meta?.["agentguard/runId"] ?? meta?.run_id;
|
|
319
331
|
if (typeof fromMeta === "string" && fromMeta.trim()) return fromMeta.trim().slice(0, 128);
|
|
320
332
|
if (extra.sessionId) return `sess_${extra.sessionId.slice(0, 12)}`;
|
|
321
333
|
return fallback;
|
|
322
334
|
}
|
|
323
335
|
function toCallToolResult(result, tool) {
|
|
324
|
-
const
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
run_id: result.entry.run_id
|
|
333
|
-
}
|
|
336
|
+
const verdict = {
|
|
337
|
+
class: result.decision.classification.class,
|
|
338
|
+
verb: result.decision.classification.verb,
|
|
339
|
+
mode: result.decision.mode,
|
|
340
|
+
outcome: result.outcome,
|
|
341
|
+
dryRun: result.faked,
|
|
342
|
+
seq: result.entry.seq,
|
|
343
|
+
run_id: result.entry.run_id
|
|
334
344
|
};
|
|
345
|
+
const meta = { okgate: verdict, agentguard: verdict };
|
|
335
346
|
const hasOutputSchema = Boolean(tool?.tool.outputSchema);
|
|
336
347
|
if (result.error) {
|
|
337
348
|
const upstream2 = result.value;
|
|
@@ -385,7 +396,7 @@ function annotateTool(t, mode) {
|
|
|
385
396
|
name: t.name,
|
|
386
397
|
_meta: {
|
|
387
398
|
...t.tool._meta ?? {},
|
|
388
|
-
|
|
399
|
+
okgate: {
|
|
389
400
|
upstream: t.upstream,
|
|
390
401
|
class: t.classification.class,
|
|
391
402
|
verb: t.classification.verb,
|
|
@@ -396,18 +407,18 @@ function annotateTool(t, mode) {
|
|
|
396
407
|
}
|
|
397
408
|
function killedError(state) {
|
|
398
409
|
return Object.assign(
|
|
399
|
-
new Error(`
|
|
410
|
+
new Error(`okgate kill switch is on (${state.source ?? "?"}: ${state.reason ?? ""})`),
|
|
400
411
|
{ code: -32e3 }
|
|
401
412
|
);
|
|
402
413
|
}
|
|
403
414
|
function serverInstructions(runtime) {
|
|
404
415
|
if (ownToolsActive(runtime))
|
|
405
|
-
return `
|
|
406
|
-
return `Tool calls pass through
|
|
416
|
+
return `okgate is an MCP policy proxy, and this one fronts no upstream MCP servers${runtime.configured ? "" : ` (no policy file at ${runtime.loaded.path})`}, so it serves only its own read-only tools: okgate_get_status (what it guards, caps, kill switch), okgate_get_report (what a run did or would have done) and okgate_verify_audit_log. To guard the user's MCP servers, run \`${INIT_COMMAND}\` in the project directory and restart the client.`;
|
|
417
|
+
return `Tool calls pass through okgate (${runtime.policy.mode} mode). Errors carry { code, cause, fix, retryable }; follow "fix". CAP_EXCEEDED, LOOP_DETECTED and KILLED are not retryable: stop and report to the user. APPROVAL_REQUIRED: relay the approval command to the user, then retry the identical call once.`;
|
|
407
418
|
}
|
|
408
419
|
function createDownstreamServer(runtime, opts = {}) {
|
|
409
420
|
const server = new McpServer(
|
|
410
|
-
{ name: "
|
|
421
|
+
{ name: "okgate", version: PROXY_VERSION, title: "okgate policy proxy" },
|
|
411
422
|
{
|
|
412
423
|
capabilities: {
|
|
413
424
|
tools: { listChanged: true },
|
|
@@ -444,8 +455,8 @@ function createDownstreamServer(runtime, opts = {}) {
|
|
|
444
455
|
agent: null,
|
|
445
456
|
error: {
|
|
446
457
|
code: "TOOL_DENIED",
|
|
447
|
-
cause: "the agent key in Authorization / X-Agentguard-Key is not in
|
|
448
|
-
fix: "use a key created with `
|
|
458
|
+
cause: "the agent key in Authorization / X-Agentguard-Key is not in okgate.yaml",
|
|
459
|
+
fix: "use a key created with `okgate key create <agent>`, or omit the key to use the global policy",
|
|
449
460
|
retryable: false
|
|
450
461
|
}
|
|
451
462
|
};
|
|
@@ -547,7 +558,7 @@ function createDownstreamServer(runtime, opts = {}) {
|
|
|
547
558
|
// src/proxy/http.ts
|
|
548
559
|
import { writeFileSync, unlinkSync, existsSync as existsSync2, mkdirSync } from "fs";
|
|
549
560
|
import { createServer } from "http";
|
|
550
|
-
import {
|
|
561
|
+
import { killSwitchFor } from "@agentwares/agentguard-core/node";
|
|
551
562
|
function json(res, status, body) {
|
|
552
563
|
res.writeHead(status, { "Content-Type": "application/json", "Cache-Control": "no-store" });
|
|
553
564
|
res.end(JSON.stringify(body));
|
|
@@ -575,7 +586,7 @@ async function startHttpProxy(opts) {
|
|
|
575
586
|
const host = opts.host ?? "127.0.0.1";
|
|
576
587
|
const path = opts.path ?? "/mcp";
|
|
577
588
|
const token = opts.token ?? crypto.randomUUID().replace(/-/g, "");
|
|
578
|
-
const kill =
|
|
589
|
+
const kill = killSwitchFor(runtime.loaded);
|
|
579
590
|
const holder = {};
|
|
580
591
|
const server = createServer((req, res) => {
|
|
581
592
|
void (async () => {
|
|
@@ -624,7 +635,7 @@ async function startHttpProxy(opts) {
|
|
|
624
635
|
const killed = await runtime.guard.killState();
|
|
625
636
|
return json(res, 200, {
|
|
626
637
|
ok: true,
|
|
627
|
-
name: "
|
|
638
|
+
name: "okgate",
|
|
628
639
|
version: PROXY_VERSION,
|
|
629
640
|
mode: runtime.policy.mode,
|
|
630
641
|
killed: killed.killed,
|
|
@@ -670,7 +681,7 @@ async function startHttpProxy(opts) {
|
|
|
670
681
|
return json(res, 404, {
|
|
671
682
|
code: "NOT_FOUND",
|
|
672
683
|
cause: `no approval ${id}`,
|
|
673
|
-
fix: "list pending approvals with `
|
|
684
|
+
fix: "list pending approvals with `okgate approvals`",
|
|
674
685
|
retryable: false
|
|
675
686
|
});
|
|
676
687
|
if (req.headers.accept?.includes("text/html")) {
|
|
@@ -766,4 +777,4 @@ export {
|
|
|
766
777
|
createDownstreamServer,
|
|
767
778
|
startHttpProxy
|
|
768
779
|
};
|
|
769
|
-
//# sourceMappingURL=chunk-
|
|
780
|
+
//# sourceMappingURL=chunk-JSELR4SG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/proxy/own-tools.ts","../src/proxy/server.ts","../src/proxy/http.ts"],"sourcesContent":["/**\n * okgate's own tools: what an MCP client sees when the proxy has no upstream servers. That is\n * the proxy started with no `okgate.yaml` at all (an \"Add to Cursor\" button, a registry\n * install, a Glama build) or with a policy that lists none.\n *\n * Three read-only answers: status, a run's report and a verify of the audit log. They call no\n * upstream, write no file, and are not recorded in the audit log they read. With upstreams\n * configured they are not listed, so an agent's tool surface behind the proxy is unchanged.\n */\nimport { createToolContext, defineTool, listToolManifest, toolError } from \"@agentwares/mcp-kit\";\nimport {\n buildReport,\n latestRunId,\n listRuns,\n parseAuditJsonl,\n renderReportMarkdown,\n resolveToolName,\n verifyChain,\n type AuditEntry,\n type Caps,\n} from \"@agentwares/agentguard-core\";\nimport type { CallToolResult, Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { z } from \"zod\";\nimport { RUN } from \"../install.js\";\nimport type { ProxyRuntime } from \"./runtime.js\";\n\nexport const INIT_COMMAND = `${RUN} init`;\n\nconst READ_ONLY = {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: false,\n} as const;\n\nconst runIdInput = z\n .string()\n .min(1)\n .max(128)\n .optional()\n .describe(\n \"Run to read, as it appears in the audit log (for example run_20261007093015_ab12, or the X-Run-Id an HTTP client sent). Omit it for the most recent run.\",\n );\n\nconst counters = z\n .record(z.string(), z.number())\n .describe(\n \"counter name (tool_calls, writes, deletes, emails, spend_usd or a custom one) → value\",\n );\n\n/** The audit file, read without creating it. A line that is not JSON is reported, not thrown. */\nfunction readAudit(path: string): { exists: boolean; entries: AuditEntry[]; error?: string } {\n if (!existsSync(path)) return { exists: false, entries: [] };\n try {\n return { exists: true, entries: parseAuditJsonl(readFileSync(path, \"utf8\")) };\n } catch (err) {\n return { exists: true, entries: [], error: err instanceof Error ? err.message : String(err) };\n }\n}\n\nfunction unreadable(path: string, error: string): Error {\n return toolError({\n code: \"AUDIT_UNREADABLE\",\n cause: `the audit log at ${path} could not be read: ${error}`,\n fix: \"call okgate_verify_audit_log to see where it breaks; a hand-edited or truncated line has to be restored from a copy\",\n retryable: false,\n });\n}\n\nfunction numbers(caps: Caps): Record<string, number> {\n const out: Record<string, number> = {};\n for (const [k, v] of Object.entries(caps)) if (typeof v === \"number\") out[k] = v;\n return out;\n}\n\nfunction nextStep(runtime: ProxyRuntime): string {\n if (!runtime.configured)\n return `okgate is guarding nothing: no policy file at ${runtime.loaded.path}. Run \\`${INIT_COMMAND}\\` in the project directory: it writes okgate.yaml in dry-run mode and routes the project's MCP servers through okgate (backup kept, \\`--undo\\` restores). Then restart the MCP client.`;\n if (runtime.policy.upstreams.length === 0)\n return `${runtime.loaded.path} lists no upstream servers, so okgate is guarding nothing. Add the MCP servers your agent uses under \\`upstreams:\\` in that file (it has commented examples), then restart the MCP client.`;\n return \"okgate is running; run your agent, then read okgate_get_report.\";\n}\n\nconst StatusOutput = z.object({\n configured: z\n .boolean()\n .describe(\"true when a policy file was found and loaded; false means okgate guards nothing\"),\n policy_path: z.string().describe(\"absolute path of the policy file read, or looked for\"),\n mode: z\n .enum([\"dry-run\", \"enforce\"])\n .describe(\"dry-run fakes writes and spends and records them; enforce lets allowed calls run\"),\n upstreams: z\n .array(\n z.object({\n name: z.string().describe(\"upstream name from the policy\"),\n connected: z.boolean().describe(\"whether okgate is connected to it\"),\n tools: z.number().int().describe(\"tools it exposes\"),\n transport: z.enum([\"stdio\", \"http\"]).describe(\"how okgate reaches it\"),\n error: z.string().optional().describe(\"why it is not connected\"),\n }),\n )\n .describe(\"the MCP servers this proxy fronts; empty means none are configured\"),\n run_id: z\n .string()\n .nullable()\n .describe(\n \"run the usage is for: the requested run_id, else the latest run in the log, else null\",\n ),\n caps: z\n .object({ per_run: counters, per_day: counters })\n .describe(\"limits from the policy; a counter that is absent has no cap\"),\n used: z\n .object({ per_run: counters, per_day: counters })\n .describe(\"what that run, and today, have used against the caps\"),\n remaining: z\n .record(\n z.string(),\n z.object({ per_run: z.number().optional(), per_day: z.number().optional() }),\n )\n .describe(\"budget left per capped counter, per run and per day\"),\n kill_switch: z\n .object({\n on: z.boolean().describe(\"true halts every tool call with KILLED\"),\n reason: z.string().optional().describe(\"why it was pulled\"),\n source: z.string().optional().describe(\"file, env or memory\"),\n })\n .describe(\"the kill switch state\"),\n pending_approvals: z.number().int().describe(\"destructive calls waiting for a human decision\"),\n audit_log: z\n .object({\n path: z.string().describe(\"absolute path of the hash-chained JSONL audit log\"),\n entries: z.number().int().describe(\"entries in it; 0 when it does not exist yet\"),\n })\n .describe(\"where every tool call is recorded\"),\n next_step: z.string().describe(\"the one thing to do next, with the command when there is one\"),\n});\n\nconst ReportOutput = z.object({\n configured: z.boolean().describe(\"false when no policy file was found (okgate guards nothing)\"),\n audit_log_path: z.string().describe(\"absolute path of the audit log the report was built from\"),\n run_id: z.string().nullable().describe(\"the run reported on; null when the log has no runs\"),\n runs_in_log: z.number().int().describe(\"how many runs the audit log holds\"),\n tool_calls: z.number().int().describe(\"tool calls in this run\"),\n would_have: z\n .object({\n creates: z.number().int(),\n updates: z.number().int(),\n deletes: z.number().int(),\n sends: z.number().int(),\n executes: z.number().int(),\n spends: z.number().int(),\n spend_usd: z.number(),\n })\n .describe(\"what dry-run mode faked: what the run would have done had the calls executed\"),\n did: z\n .object({\n writes: z.number().int(),\n deletes: z.number().int(),\n sends: z.number().int(),\n spend_usd: z.number(),\n })\n .describe(\"what actually executed upstream\"),\n halts: z\n .array(\n z.object({\n seq: z.number().int().describe(\"audit entry number\"),\n ts: z.string().describe(\"ISO time of the call\"),\n code: z.string().describe(\"CAP_EXCEEDED, LOOP_DETECTED, KILLED, APPROVAL_REQUIRED, …\"),\n tool: z.string().describe(\"the tool that was stopped\"),\n cause: z.string().describe(\"why\"),\n }),\n )\n .describe(\"every call okgate stopped, in order\"),\n top_tools: z\n .array(z.object({ tool: z.string(), calls: z.number().int(), class: z.string() }))\n .describe(\"the most-called tools with their class (read, write, spend)\"),\n markdown: z.string().describe(\"the same report `okgate report` prints, as Markdown\"),\n});\n\nconst VerifyOutput = z.object({\n configured: z.boolean().describe(\"false when no policy file was found (okgate guards nothing)\"),\n path: z.string().describe(\"absolute path of the audit log checked\"),\n exists: z.boolean().describe(\"false when no call has been recorded yet; an absent log verifies\"),\n ok: z.boolean().describe(\"true when every entry's hash and prev_hash recompute\"),\n entries: z.number().int().describe(\"entries checked\"),\n head_hash: z\n .string()\n .nullable()\n .describe(\n \"hash of the last entry; record it with the count to detect entries cut from the end\",\n ),\n broken_at: z.number().int().nullable().describe(\"seq of the first entry that does not verify\"),\n reason: z.string().nullable().describe(\"why verification failed\"),\n});\n\nexport function createOwnTools(runtime: ProxyRuntime) {\n const status = defineTool({\n name: \"okgate_get_status\",\n title: \"okgate status\",\n description:\n \"Report what okgate is guarding right now: the policy file it loaded (or that none was found), dry-run or enforce mode, each upstream MCP server and whether it connected, a run's cap usage and remaining budget, the kill switch, and pending approvals. Call it first to learn whether okgate is set up; next_step says what to do when it is not. For what a run did, use okgate_get_report; to check the log was not edited, okgate_verify_audit_log. Reads local files only and changes nothing.\",\n input: z.strictObject({ run_id: runIdInput }),\n output: StatusOutput,\n annotations: { title: \"okgate status\", ...READ_ONLY },\n async handler({ run_id }) {\n const { loaded, guard } = runtime;\n const audit = readAudit(loaded.auditPath);\n if (audit.error) throw unreadable(loaded.auditPath, audit.error);\n const runId = run_id ?? latestRunId(audit.entries) ?? null;\n const state = await guard.status(runId ?? \"(none yet)\");\n const pending = await guard.approvals.list(\"pending\");\n return {\n configured: runtime.configured,\n policy_path: loaded.path,\n mode: runtime.policy.mode,\n upstreams: runtime.upstreamStatus(),\n run_id: runId,\n caps: { per_run: numbers(state.caps.per_run), per_day: numbers(state.caps.per_day) },\n used: state.usage,\n remaining: state.remaining,\n kill_switch: {\n on: state.killed.killed,\n ...(state.killed.reason ? { reason: state.killed.reason } : {}),\n ...(state.killed.source ? { source: state.killed.source } : {}),\n },\n pending_approvals: pending.length,\n audit_log: { path: loaded.auditPath, entries: audit.entries.length },\n next_step: nextStep(runtime),\n };\n },\n });\n\n const report = defineTool({\n name: \"okgate_get_report\",\n title: \"okgate run report\",\n description:\n \"Summarize one run from okgate's audit log: how many tool calls, what dry-run mode faked (records it would have created, updated or deleted, messages sent, dollars spent), what really ran upstream, and every call okgate halted with its code and cause. Defaults to the most recent run. Use it after an agent run, before switching a policy from dry-run to enforce; for live caps and the kill switch use okgate_get_status. Read-only: reads the audit file and does not record this call.\",\n input: z.strictObject({ run_id: runIdInput }),\n output: ReportOutput,\n annotations: { title: \"okgate run report\", ...READ_ONLY },\n handler({ run_id }) {\n const { loaded } = runtime;\n const audit = readAudit(loaded.auditPath);\n if (audit.error) throw unreadable(loaded.auditPath, audit.error);\n const runs = listRuns(audit.entries);\n if (run_id && !runs.some((r) => r.runId === run_id)) {\n throw toolError({\n code: \"NOT_FOUND\",\n cause: `no run \"${run_id}\" in the audit log at ${loaded.auditPath}`,\n fix: `call again without run_id for the latest run${\n runs.length\n ? `; runs in the log: ${runs\n .slice(0, 5)\n .map((r) => r.runId)\n .join(\", \")}`\n : \"; the log has no runs yet\"\n }`,\n retryable: false,\n });\n }\n const runId = run_id ?? latestRunId(audit.entries) ?? null;\n const built = buildReport(audit.entries, { runId: runId ?? undefined });\n const markdown = runId\n ? renderReportMarkdown(built)\n : `# okgate report\\n\\nNo runs recorded in ${loaded.auditPath} yet. ${nextStep(runtime)}`;\n return {\n configured: runtime.configured,\n audit_log_path: loaded.auditPath,\n run_id: runId,\n runs_in_log: runs.length,\n tool_calls: runId ? audit.entries.filter((e) => e.run_id === runId).length : 0,\n would_have: {\n creates: built.wouldHave.creates,\n updates: built.wouldHave.updates,\n deletes: built.wouldHave.deletes,\n sends: built.wouldHave.sends,\n executes: built.wouldHave.executes,\n spends: built.wouldHave.spends,\n spend_usd: built.wouldHave.spendUsd,\n },\n did: {\n writes: built.did.writes,\n deletes: built.did.deletes,\n sends: built.did.sends,\n spend_usd: built.did.spendUsd,\n },\n halts: built.halts,\n top_tools: built.topTools,\n markdown,\n };\n },\n });\n\n const verify = defineTool({\n name: \"okgate_verify_audit_log\",\n title: \"Verify okgate audit log\",\n description:\n \"Recompute the hash chain of okgate's audit log (JSONL, one entry per tool call) and say whether any entry was edited, removed from the middle or reordered, naming the first broken entry. Returns the entry count and head hash; record both elsewhere, because entries cut from the end of the file still verify. Use it before trusting okgate_get_report. Takes no arguments: it checks the log the loaded policy names. Read-only; a log that does not exist yet verifies as empty.\",\n input: z.strictObject({}),\n output: VerifyOutput,\n annotations: { title: \"Verify okgate audit log\", ...READ_ONLY },\n async handler() {\n const { loaded } = runtime;\n const audit = readAudit(loaded.auditPath);\n if (audit.error) {\n return {\n configured: runtime.configured,\n path: loaded.auditPath,\n exists: true,\n ok: false,\n entries: 0,\n head_hash: null,\n broken_at: null,\n reason: audit.error,\n };\n }\n const result = await verifyChain(audit.entries);\n return {\n configured: runtime.configured,\n path: loaded.auditPath,\n exists: audit.exists,\n ok: result.ok,\n entries: result.entries,\n // an empty chain's head is the genesis hash, which is not an entry anyone can record\n head_hash: result.entries > 0 ? (result.head ?? null) : null,\n broken_at: result.brokenAt ?? null,\n reason: result.reason ?? null,\n };\n },\n });\n\n return [status, report, verify];\n}\n\nexport type OwnTool = ReturnType<typeof createOwnTools>[number];\n\n/** Own tools are served only when the proxy fronts no upstream at all. */\nexport function ownToolsActive(runtime: ProxyRuntime): boolean {\n return runtime.upstreamStatus().length === 0;\n}\n\n/** The MCP `tools/list` entries for the own tools. */\nexport function ownToolList(tools: readonly OwnTool[]): Tool[] {\n return listToolManifest(tools) as Tool[];\n}\n\n/**\n * Run an own tool. An `okgate_*` name (the product's name before the rename) runs its\n * `okgate_*` twin with a deprecation note in `_meta` until OLD_NAMES_UNTIL, then answers\n * TOOL_RENAMED. tools/list shows only the new names.\n */\nexport async function callOwnTool(\n tools: readonly OwnTool[],\n name: string,\n args: unknown,\n requestId?: string,\n now: Date = new Date(),\n): Promise<CallToolResult | undefined> {\n const resolved = resolveToolName(name, (n) => tools.some((t) => t.name === n), now);\n if (resolved.kind === \"expired\")\n return {\n isError: true,\n content: [{ type: \"text\", text: JSON.stringify(resolved.error) }],\n _meta: { httpStatus: 404 },\n };\n const tool = tools.find((t) => t.name === resolved.name);\n if (!tool) return undefined;\n const result = (await tool.invoke(args, createToolContext({ requestId }))) as CallToolResult;\n if (resolved.kind === \"renamed\")\n return { ...result, _meta: { ...result._meta, ...resolved.meta } };\n return result;\n}\n","/**\n * Downstream side of the proxy: the MCP server an agent connects to. One instance per session\n * (stdio: one; Streamable HTTP: one per `Mcp-Session-Id`). Every request is served from the\n * runtime; tool calls go through the policy engine.\n */\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { RequestHandlerExtra } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport {\n CallToolRequestSchema,\n CompleteRequestSchema,\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n ListResourceTemplatesRequestSchema,\n ListResourcesRequestSchema,\n ListToolsRequestSchema,\n ReadResourceRequestSchema,\n SetLevelRequestSchema,\n SubscribeRequestSchema,\n UnsubscribeRequestSchema,\n type CallToolResult,\n type ServerNotification,\n type ServerRequest,\n type Tool,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport {\n keyFromHeaders,\n resolveAgent,\n type AgentScope,\n type GuardErrorBody,\n type GuardResult,\n} from \"@agentwares/agentguard-core\";\nimport { version as cliVersion } from \"../version.js\";\nimport {\n INIT_COMMAND,\n callOwnTool,\n createOwnTools,\n ownToolList,\n ownToolsActive,\n} from \"./own-tools.js\";\nimport type { DownstreamSession, ExposedTool, ProxyRuntime } from \"./runtime.js\";\n\n/**\n * Reported to every MCP client in `serverInfo`. Derived from package.json rather than written\n * out, because a hand-maintained copy drifts: this said 0.1.0 while npm served 0.1.2, so a\n * client could not tell which build it was talking to.\n */\nexport const PROXY_VERSION = cliVersion();\n\ntype Extra = RequestHandlerExtra<ServerRequest, ServerNotification>;\n\nexport interface DownstreamOptions {\n /** run id for calls that carry neither `X-Run-Id` nor `_meta.runId` (default: runtime.defaultRunId) */\n defaultRunId?: string;\n}\n\nfunction headerValue(extra: Extra, name: string): string | undefined {\n const raw =\n extra.requestInfo?.headers?.[name] ?? extra.requestInfo?.headers?.[name.toLowerCase()];\n if (Array.isArray(raw)) return raw[0];\n return typeof raw === \"string\" ? raw : undefined;\n}\n\nfunction headersOf(extra: Extra): Record<string, string | undefined> {\n const out: Record<string, string | undefined> = {};\n for (const [k, v] of Object.entries(extra.requestInfo?.headers ?? {}))\n out[k.toLowerCase()] = Array.isArray(v) ? v[0] : v;\n return out;\n}\n\nexport function runIdFor(\n extra: Extra,\n meta: Record<string, unknown> | undefined,\n fallback: string,\n): string {\n const header = headerValue(extra, \"x-run-id\");\n if (header && header.trim()) return header.trim().slice(0, 128);\n const fromMeta =\n meta?.runId ?? meta?.[\"okgate/runId\"] ?? meta?.[\"agentguard/runId\"] ?? meta?.run_id;\n if (typeof fromMeta === \"string\" && fromMeta.trim()) return fromMeta.trim().slice(0, 128);\n if (extra.sessionId) return `sess_${extra.sessionId.slice(0, 12)}`;\n return fallback;\n}\n\n/** Shape the engine's verdict into what the MCP client receives. */\nexport function toCallToolResult(\n result: GuardResult,\n tool: ExposedTool | undefined,\n): CallToolResult {\n const verdict = {\n class: result.decision.classification.class,\n verb: result.decision.classification.verb,\n mode: result.decision.mode,\n outcome: result.outcome,\n dryRun: result.faked,\n seq: result.entry.seq,\n run_id: result.entry.run_id,\n };\n // `okgate` is the same object under the name before the rename, for 90 days\n const meta = { okgate: verdict, agentguard: verdict };\n const hasOutputSchema = Boolean(tool?.tool.outputSchema);\n if (result.error) {\n const upstream = result.value as CallToolResult | undefined;\n if (upstream && upstream.content) {\n return { ...upstream, isError: true, _meta: { ...(upstream._meta ?? {}), ...meta } };\n }\n const body: GuardErrorBody = result.error;\n return {\n isError: true,\n content: [{ type: \"text\", text: JSON.stringify(body) }],\n ...(hasOutputSchema ? {} : { structuredContent: body }),\n _meta: { ...meta, httpStatus: httpStatusFor(body.code) },\n };\n }\n if (result.faked) {\n const value = result.value;\n const isObject = value !== null && typeof value === \"object\" && !Array.isArray(value);\n return {\n content: [\n { type: \"text\", text: typeof value === \"string\" ? value : JSON.stringify(value, null, 2) },\n ],\n ...(isObject ? { structuredContent: value as Record<string, unknown> } : {}),\n _meta: meta,\n };\n }\n const upstream = result.value as CallToolResult;\n return { ...upstream, _meta: { ...(upstream._meta ?? {}), ...meta } };\n}\n\nfunction httpStatusFor(code: string): number {\n switch (code) {\n case \"KILLED\":\n case \"TOOL_DENIED\":\n case \"APPROVAL_DENIED\":\n return 403;\n case \"APPROVAL_REQUIRED\":\n return 202;\n case \"CAP_EXCEEDED\":\n case \"LOOP_DETECTED\":\n return 429;\n case \"UNKNOWN_TOOL\":\n return 404;\n case \"UPSTREAM_ERROR\":\n return 502;\n default:\n return 500;\n }\n}\n\nexport function annotateTool(t: ExposedTool, mode: string): Tool {\n return {\n ...t.tool,\n name: t.name,\n _meta: {\n ...(t.tool._meta ?? {}),\n okgate: {\n upstream: t.upstream,\n class: t.classification.class,\n verb: t.classification.verb,\n mode,\n },\n },\n };\n}\n\nfunction killedError(state: { reason?: string; source?: string }): Error {\n return Object.assign(\n new Error(`okgate kill switch is on (${state.source ?? \"?\"}: ${state.reason ?? \"\"})`),\n { code: -32000 },\n );\n}\n\n/** What the client is told about this server, which depends on whether it fronts anything. */\nexport function serverInstructions(runtime: ProxyRuntime): string {\n if (ownToolsActive(runtime))\n return `okgate is an MCP policy proxy, and this one fronts no upstream MCP servers${\n runtime.configured ? \"\" : ` (no policy file at ${runtime.loaded.path})`\n }, so it serves only its own read-only tools: okgate_get_status (what it guards, caps, kill switch), okgate_get_report (what a run did or would have done) and okgate_verify_audit_log. To guard the user's MCP servers, run \\`${INIT_COMMAND}\\` in the project directory and restart the client.`;\n return `Tool calls pass through okgate (${runtime.policy.mode} mode). Errors carry { code, cause, fix, retryable }; follow \"fix\". CAP_EXCEEDED, LOOP_DETECTED and KILLED are not retryable: stop and report to the user. APPROVAL_REQUIRED: relay the approval command to the user, then retry the identical call once.`;\n}\n\n/** Build the per-session MCP server. */\nexport function createDownstreamServer(\n runtime: ProxyRuntime,\n opts: DownstreamOptions = {},\n): McpServer {\n const server = new McpServer(\n { name: \"okgate\", version: PROXY_VERSION, title: \"okgate policy proxy\" },\n {\n capabilities: {\n tools: { listChanged: true },\n resources: { subscribe: true, listChanged: true },\n prompts: { listChanged: true },\n logging: {},\n completions: {},\n },\n instructions: serverInstructions(runtime),\n },\n );\n const ownTools = createOwnTools(runtime);\n const session: DownstreamSession = {\n id: crypto.randomUUID(),\n server,\n lastActive: Date.now(),\n inflight: new Map(),\n };\n runtime.attach(session);\n const previousOnClose = server.server.onclose;\n server.server.onclose = () => {\n previousOnClose?.();\n runtime.detach(session);\n };\n const touch = (): void => {\n session.lastActive = Date.now();\n };\n\n const agentFor = async (\n extra: Extra,\n ): Promise<{ agent: AgentScope | null | undefined; error?: GuardErrorBody }> => {\n const key = keyFromHeaders(headersOf(extra));\n if (!key) return { agent: undefined };\n const resolved = await resolveAgent(runtime.policy, { key });\n if (resolved.error) {\n return {\n agent: null,\n error: {\n code: \"TOOL_DENIED\",\n cause: \"the agent key in Authorization / X-Agentguard-Key is not in okgate.yaml\",\n fix: \"use a key created with `okgate key create <agent>`, or omit the key to use the global policy\",\n retryable: false,\n },\n };\n }\n return { agent: resolved.agent };\n };\n\n const low = server.server;\n low.setRequestHandler(ListToolsRequestSchema, async (_req, extra) => {\n touch();\n const { agent } = await agentFor(extra);\n const scope = agent === undefined ? runtime.agent : agent;\n if (ownToolsActive(runtime)) return { tools: ownToolList(ownTools) };\n return {\n tools: runtime\n .listTools(scope)\n .map((t) => annotateTool(t, scope?.mode ?? runtime.policy.mode)),\n };\n });\n\n low.setRequestHandler(CallToolRequestSchema, async (req, extra) => {\n touch();\n if (ownToolsActive(runtime)) {\n // Read-only answers about okgate itself: no upstream, no policy decision, no audit entry.\n const own = await callOwnTool(\n ownTools,\n req.params.name,\n req.params.arguments ?? {},\n String(extra.requestId),\n );\n if (own) return own;\n }\n const { agent, error } = await agentFor(extra);\n const runId = runIdFor(extra, req.params._meta, opts.defaultRunId ?? runtime.defaultRunId);\n if (error) {\n return {\n isError: true,\n content: [{ type: \"text\", text: JSON.stringify(error) }],\n structuredContent: error,\n _meta: { httpStatus: 401 },\n };\n }\n const progressToken = req.params._meta?.progressToken;\n const { result, tool } = await runtime.callTool(req.params.name, req.params.arguments ?? {}, {\n runId,\n agent,\n sessionId: extra.sessionId ?? session.id,\n session,\n requestId: extra.requestId,\n onprogress:\n progressToken === undefined\n ? undefined\n : (p) => {\n void extra.sendNotification({\n method: \"notifications/progress\",\n params: { progressToken, ...p },\n });\n },\n });\n return toCallToolResult(result, tool);\n });\n\n const guardRead = async (): Promise<void> => {\n const state = await runtime.guard.killState();\n if (state.killed) throw killedError(state);\n };\n\n low.setRequestHandler(ListResourcesRequestSchema, async () => {\n touch();\n return runtime.listResources();\n });\n low.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {\n touch();\n return runtime.listResourceTemplates();\n });\n low.setRequestHandler(ReadResourceRequestSchema, async (req) => {\n touch();\n await guardRead();\n return runtime.readResource(req.params.uri);\n });\n low.setRequestHandler(SubscribeRequestSchema, async (req) => {\n await runtime.subscribe(req.params.uri, true);\n return {};\n });\n low.setRequestHandler(UnsubscribeRequestSchema, async (req) => {\n await runtime.subscribe(req.params.uri, false);\n return {};\n });\n low.setRequestHandler(ListPromptsRequestSchema, async () => {\n touch();\n return runtime.listPrompts();\n });\n low.setRequestHandler(GetPromptRequestSchema, async (req) => {\n touch();\n await guardRead();\n return runtime.getPrompt(req.params.name, req.params.arguments);\n });\n low.setRequestHandler(CompleteRequestSchema, async (req) => {\n touch();\n return runtime.complete(req.params);\n });\n low.setRequestHandler(SetLevelRequestSchema, async (req) => {\n await runtime.setLevel(req.params.level);\n return {};\n });\n return server;\n}\n","/**\n * Streamable HTTP front door plus the local control endpoints: /health, /status, /kill,\n * /resume, /approve/:id, /deny/:id, /approvals. Control endpoints need the per-process token\n * (written to `<state>/http.json` so the CLI can find a running proxy).\n */\nimport { createHttpHandler, localhostHosts, type HttpHandler } from \"@agentwares/mcp-kit\";\nimport { writeFileSync, unlinkSync, existsSync, mkdirSync } from \"node:fs\";\nimport { createServer, type IncomingMessage, type ServerResponse } from \"node:http\";\nimport { killSwitchFor } from \"@agentwares/agentguard-core/node\";\nimport type { ProxyRuntime } from \"./runtime.js\";\nimport { createDownstreamServer, PROXY_VERSION } from \"./server.js\";\n\nexport interface HttpProxyOptions {\n runtime: ProxyRuntime;\n port?: number;\n host?: string;\n path?: string;\n token?: string;\n /** write `<stateDir>/http.json` for the CLI (default true) */\n registerFile?: boolean;\n}\n\nexport interface HttpProxy {\n url: string;\n port: number;\n token: string;\n close(): Promise<void>;\n}\n\nimport { registrationPath, type HttpRegistration } from \"../registration.js\";\n\nexport { registrationPath, type HttpRegistration };\n\nfunction json(res: ServerResponse, status: number, body: unknown): void {\n res.writeHead(status, { \"Content-Type\": \"application/json\", \"Cache-Control\": \"no-store\" });\n res.end(JSON.stringify(body));\n}\n\nfunction html(res: ServerResponse, status: number, body: string): void {\n res.writeHead(status, {\n \"Content-Type\": \"text/html; charset=utf-8\",\n \"Cache-Control\": \"no-store\",\n });\n res.end(\n `<!doctype html><meta name=\"viewport\" content=\"width=device-width\"><body style=\"font:16px system-ui;padding:2rem;max-width:40rem\">${body}</body>`,\n );\n}\n\nasync function readBody(req: IncomingMessage): Promise<Uint8Array<ArrayBuffer> | undefined> {\n if (req.method === \"GET\" || req.method === \"HEAD\") return undefined;\n const chunks: Buffer[] = [];\n for await (const chunk of req) chunks.push(chunk as Buffer);\n return new Uint8Array(Buffer.concat(chunks));\n}\n\nfunction isLoopback(host: string): boolean {\n return host === \"127.0.0.1\" || host === \"localhost\" || host === \"::1\" || host === \"[::1]\";\n}\n\nexport async function startHttpProxy(opts: HttpProxyOptions): Promise<HttpProxy> {\n const { runtime } = opts;\n const host = opts.host ?? \"127.0.0.1\";\n const path = opts.path ?? \"/mcp\";\n const token = opts.token ?? crypto.randomUUID().replace(/-/g, \"\");\n const kill = killSwitchFor(runtime.loaded);\n\n const holder: { mcp?: HttpHandler } = {};\n const server = createServer((req, res) => {\n void (async () => {\n const url = new URL(req.url ?? \"/\", `http://${req.headers.host ?? host}`);\n const authorized = (): boolean => {\n const q = url.searchParams.get(\"token\");\n const h = req.headers.authorization?.replace(/^Bearer\\s+/i, \"\");\n return q === token || h === token;\n };\n if (url.pathname === path && holder.mcp) {\n const headers = new Headers();\n for (const [k, v] of Object.entries(req.headers)) {\n if (Array.isArray(v)) for (const item of v) headers.append(k, item);\n else if (typeof v === \"string\") headers.set(k, v);\n }\n const controller = new AbortController();\n res.on(\"close\", () => {\n if (!res.writableFinished) controller.abort();\n });\n const response = await holder.mcp(\n new Request(url, {\n method: req.method ?? \"GET\",\n headers,\n body: await readBody(req),\n signal: controller.signal,\n }),\n );\n const out: Record<string, string> = {};\n response.headers.forEach((v, k) => {\n out[k] = v;\n });\n res.writeHead(response.status, out);\n if (!response.body) return res.end();\n const reader = response.body.getReader();\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n res.write(value);\n }\n } catch {\n // client went away\n }\n return res.end();\n }\n if (url.pathname === \"/health\") {\n const killed = await runtime.guard.killState();\n return json(res, 200, {\n ok: true,\n name: \"okgate\",\n version: PROXY_VERSION,\n mode: runtime.policy.mode,\n killed: killed.killed,\n upstreams: runtime.upstreamStatus(),\n tools: runtime.listTools().length,\n mcp: `${url.origin}${path}`,\n });\n }\n if (url.pathname === \"/status\") {\n if (!authorized()) return json(res, 401, unauthorized());\n const runId = url.searchParams.get(\"run\") ?? runtime.defaultRunId;\n return json(res, 200, { runId, ...(await runtime.guard.status(runId)) });\n }\n if (url.pathname === \"/kill\" && req.method === \"POST\") {\n if (!authorized()) return json(res, 401, unauthorized());\n const body = await readBody(req);\n let reason = \"killed via HTTP\";\n try {\n const parsed = JSON.parse(Buffer.from(body ?? []).toString(\"utf8\") || \"{}\") as {\n reason?: string;\n };\n if (parsed.reason) reason = String(parsed.reason).slice(0, 200);\n } catch {\n // no body\n }\n kill.kill(reason);\n await runtime.guard.halt(reason);\n return json(res, 200, { killed: true, reason });\n }\n if (url.pathname === \"/resume\" && req.method === \"POST\") {\n if (!authorized()) return json(res, 401, unauthorized());\n kill.resume();\n await runtime.guard.resume();\n return json(res, 200, { killed: false });\n }\n const decision = /^\\/(approve|deny)\\/([A-Za-z0-9_-]+)$/.exec(url.pathname);\n if (decision) {\n if (!authorized()) return json(res, 401, unauthorized());\n const [, action, id] = decision;\n const record = await runtime.guard.decide(\n id!,\n action === \"approve\" ? \"approved\" : \"denied\",\n \"http\",\n );\n if (!record)\n return json(res, 404, {\n code: \"NOT_FOUND\",\n cause: `no approval ${id}`,\n fix: \"list pending approvals with `okgate approvals`\",\n retryable: false,\n });\n if (req.headers.accept?.includes(\"text/html\")) {\n return html(\n res,\n 200,\n `<h1>${record.status === \"approved\" ? \"Approved\" : record.status === \"denied\" ? \"Denied\" : record.status}</h1><p><code>${record.tool}</code> — approval <code>${record.id}</code>.</p><p>The agent may now retry the call once.</p>`,\n );\n }\n return json(res, 200, record);\n }\n if (url.pathname === \"/approvals\") {\n if (!authorized()) return json(res, 401, unauthorized());\n return json(res, 200, {\n approvals: await runtime.guard.approvals.list(\n url.searchParams.get(\"all\") ? undefined : \"pending\",\n ),\n });\n }\n return json(res, 404, {\n code: \"NOT_FOUND\",\n cause: `no route for ${url.pathname}`,\n fix: `POST JSON-RPC to ${path}; GET /health`,\n retryable: false,\n });\n })().catch((err: unknown) => {\n if (!res.headersSent)\n json(res, 500, {\n code: \"INTERNAL\",\n cause: err instanceof Error ? err.message : String(err),\n fix: \"retry; if it persists, report the request\",\n retryable: false,\n });\n else res.end();\n });\n });\n\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(opts.port ?? 8788, host, () => resolve());\n });\n const address = server.address();\n const port = typeof address === \"object\" && address ? address.port : (opts.port ?? 8788);\n holder.mcp = createHttpHandler(() => createDownstreamServer(runtime), {\n sessions: true,\n jsonResponse: false,\n cors: true,\n allowedHosts: isLoopback(host) ? localhostHosts(port) : undefined,\n enableDnsRebindingProtection: isLoopback(host),\n });\n\n const baseUrl = `http://${host}:${port}`;\n const url = `${baseUrl}${path}`;\n const regFile = registrationPath(runtime.loaded.stateDir);\n if (opts.registerFile !== false) {\n mkdirSync(runtime.loaded.stateDir, { recursive: true });\n const reg: HttpRegistration = {\n url,\n baseUrl,\n token,\n pid: process.pid,\n startedAt: new Date().toISOString(),\n };\n writeFileSync(regFile, JSON.stringify(reg, null, 2));\n }\n return {\n url,\n port,\n token,\n close: () =>\n new Promise<void>((resolve, reject) => {\n if (opts.registerFile !== false && existsSync(regFile)) {\n try {\n unlinkSync(regFile);\n } catch {\n // fine\n }\n }\n server.closeAllConnections();\n server.close((err) => (err ? reject(err) : resolve()));\n }),\n };\n}\n\nfunction unauthorized(): Record<string, unknown> {\n return {\n code: \"UNAUTHORIZED\",\n cause: \"missing or wrong control token\",\n fix: \"pass ?token=<token> or Authorization: Bearer <token> from <state>/http.json\",\n retryable: false,\n };\n}\n"],"mappings":"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","names":["upstream","existsSync","url","existsSync"]}
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
backupFor
|
|
3
|
+
} from "./chunk-2QDPPTPY.js";
|
|
4
|
+
import {
|
|
5
|
+
npxArgs
|
|
6
|
+
} from "./chunk-XPNBYSIN.js";
|
|
7
|
+
|
|
1
8
|
// src/configs.ts
|
|
2
9
|
import { copyFileSync, existsSync, readFileSync, writeFileSync } from "fs";
|
|
3
10
|
import { homedir, platform } from "os";
|
|
@@ -94,17 +101,17 @@ function readServers(file) {
|
|
|
94
101
|
if (!servers || typeof servers !== "object") return {};
|
|
95
102
|
return servers;
|
|
96
103
|
}
|
|
97
|
-
var PROXY_SERVER_NAME = "
|
|
98
|
-
var
|
|
104
|
+
var PROXY_SERVER_NAME = "okgate";
|
|
105
|
+
var LEGACY_PROXY_SERVER_NAME = "agentguard";
|
|
99
106
|
function isProxyEntry(entry) {
|
|
100
|
-
return (entry.args ?? []).some((a) =>
|
|
107
|
+
return (entry.args ?? []).some((a) => /(^|\/)(okgate|agentguard)(@[^/]*)?(\.js)?$/.test(a)) && (entry.args ?? []).includes("proxy");
|
|
101
108
|
}
|
|
102
109
|
function serversToUpstreams(servers) {
|
|
103
110
|
const upstreams = [];
|
|
104
111
|
const skipped = [];
|
|
105
112
|
for (const [rawName, entry] of Object.entries(servers)) {
|
|
106
113
|
if (isProxyEntry(entry)) {
|
|
107
|
-
skipped.push({ name: rawName, reason: "already the
|
|
114
|
+
skipped.push({ name: rawName, reason: "already the okgate proxy" });
|
|
108
115
|
continue;
|
|
109
116
|
}
|
|
110
117
|
const name = rawName.replace(/[^a-zA-Z0-9_-]/g, "-").replace(/^[^a-zA-Z0-9]+/, "") || "upstream";
|
|
@@ -137,10 +144,11 @@ function serversToUpstreams(servers) {
|
|
|
137
144
|
return { upstreams, skipped };
|
|
138
145
|
}
|
|
139
146
|
function backupPath(file) {
|
|
140
|
-
|
|
147
|
+
const { existing, next } = backupFor(file.path);
|
|
148
|
+
return existing ?? next;
|
|
141
149
|
}
|
|
142
150
|
function proxyEntry(file, policyPath, opts = {}) {
|
|
143
|
-
const args = [
|
|
151
|
+
const args = [...npxArgs({ yes: true }), "proxy", "--config", policyPath];
|
|
144
152
|
if (opts.agent) args.push("--agent", opts.agent);
|
|
145
153
|
const entry = { command: "npx", args };
|
|
146
154
|
if (file.serversKey === "servers") entry.type = "stdio";
|
|
@@ -162,10 +170,11 @@ function restoreClientConfig(file) {
|
|
|
162
170
|
copyFileSync(backup, file.path);
|
|
163
171
|
return true;
|
|
164
172
|
}
|
|
165
|
-
function mergeServerIntoConfig(file, name, entry) {
|
|
173
|
+
function mergeServerIntoConfig(file, name, entry, replaces = []) {
|
|
166
174
|
const raw = JSON.parse(readFileSync(file.path, "utf8"));
|
|
167
|
-
const servers = raw[file.serversKey] ?? {};
|
|
168
|
-
const replaced = name in servers;
|
|
175
|
+
const servers = { ...raw[file.serversKey] ?? {} };
|
|
176
|
+
const replaced = name in servers || replaces.some((old) => old in servers);
|
|
177
|
+
for (const old of replaces) delete servers[old];
|
|
169
178
|
const backup = backupPath(file);
|
|
170
179
|
if (!existsSync(backup)) copyFileSync(file.path, backup);
|
|
171
180
|
raw[file.serversKey] = { ...servers, [name]: entry };
|
|
@@ -180,11 +189,11 @@ export {
|
|
|
180
189
|
describeConfigPath,
|
|
181
190
|
readServers,
|
|
182
191
|
PROXY_SERVER_NAME,
|
|
183
|
-
|
|
192
|
+
LEGACY_PROXY_SERVER_NAME,
|
|
184
193
|
serversToUpstreams,
|
|
185
194
|
proxyEntry,
|
|
186
195
|
rewriteClientConfig,
|
|
187
196
|
restoreClientConfig,
|
|
188
197
|
mergeServerIntoConfig
|
|
189
198
|
};
|
|
190
|
-
//# sourceMappingURL=chunk-
|
|
199
|
+
//# sourceMappingURL=chunk-OM5L7A32.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/configs.ts"],"sourcesContent":["/**\n * Find the agent's existing MCP config (Claude Code, Claude Desktop, Cursor, VS Code, Windsurf,\n * Gemini CLI, generic `mcp.json`), read its servers, and rewrite it so every server goes through\n * the proxy.\n */\nimport { copyFileSync, existsSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { homedir, platform } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport type { Upstream } from \"@agentwares/agentguard-core\";\nimport { backupFor } from \"./hooks/clients.js\";\nimport { PACKAGE, npxArgs } from \"./install.js\";\n\nexport type ClientKind =\n | \"claude-code-project\"\n | \"claude-code-user\"\n | \"claude-desktop\"\n | \"cursor-project\"\n | \"cursor-user\"\n | \"vscode\"\n | \"windsurf\"\n | \"gemini-project\"\n | \"gemini-user\"\n | \"generic\";\n\nexport interface ClientConfigFile {\n kind: ClientKind;\n label: string;\n path: string;\n /** `mcpServers` (most clients) or `servers` (VS Code) */\n serversKey: \"mcpServers\" | \"servers\";\n}\n\nexport interface ServerEntry {\n type?: string;\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n cwd?: string;\n url?: string;\n /** Gemini CLI's name for a Streamable HTTP endpoint (its `url` means SSE) */\n httpUrl?: string;\n headers?: Record<string, string>;\n [k: string]: unknown;\n}\n\nexport function candidateConfigs(\n cwd: string = process.cwd(),\n home: string = homedir(),\n env: NodeJS.ProcessEnv = process.env,\n): ClientConfigFile[] {\n const desktop =\n platform() === \"darwin\"\n ? join(home, \"Library\", \"Application Support\", \"Claude\", \"claude_desktop_config.json\")\n : platform() === \"win32\"\n ? join(\n env.APPDATA ?? join(home, \"AppData\", \"Roaming\"),\n \"Claude\",\n \"claude_desktop_config.json\",\n )\n : join(\n env.XDG_CONFIG_HOME ?? join(home, \".config\"),\n \"Claude\",\n \"claude_desktop_config.json\",\n );\n return [\n {\n kind: \"claude-code-project\",\n label: \"Claude Code (project .mcp.json)\",\n path: join(cwd, \".mcp.json\"),\n serversKey: \"mcpServers\",\n },\n {\n kind: \"cursor-project\",\n label: \"Cursor (project)\",\n path: join(cwd, \".cursor\", \"mcp.json\"),\n serversKey: \"mcpServers\",\n },\n {\n kind: \"vscode\",\n label: \"VS Code (project)\",\n path: join(cwd, \".vscode\", \"mcp.json\"),\n serversKey: \"servers\",\n },\n { kind: \"generic\", label: \"mcp.json\", path: join(cwd, \"mcp.json\"), serversKey: \"mcpServers\" },\n {\n kind: \"gemini-project\",\n label: \"Gemini CLI (project .gemini/settings.json)\",\n path: join(cwd, \".gemini\", \"settings.json\"),\n serversKey: \"mcpServers\",\n },\n { kind: \"claude-desktop\", label: \"Claude Desktop\", path: desktop, serversKey: \"mcpServers\" },\n {\n kind: \"cursor-user\",\n label: \"Cursor (user)\",\n path: join(home, \".cursor\", \"mcp.json\"),\n serversKey: \"mcpServers\",\n },\n {\n kind: \"windsurf\",\n label: \"Windsurf\",\n path: join(home, \".codeium\", \"windsurf\", \"mcp_config.json\"),\n serversKey: \"mcpServers\",\n },\n {\n kind: \"claude-code-user\",\n label: \"Claude Code (user ~/.claude.json)\",\n path: join(home, \".claude.json\"),\n serversKey: \"mcpServers\",\n },\n {\n kind: \"gemini-user\",\n label: \"Gemini CLI (user ~/.gemini/settings.json)\",\n path: join(home, \".gemini\", \"settings.json\"),\n serversKey: \"mcpServers\",\n },\n ];\n}\n\n/** Gemini CLI reads `httpUrl` for Streamable HTTP and `url` for SSE, unlike every other client. */\nexport function isGeminiConfig(file: ClientConfigFile): boolean {\n return (\n file.kind === \"gemini-project\" ||\n file.kind === \"gemini-user\" ||\n /[/\\\\]\\.gemini[/\\\\]settings\\.json$/.test(file.path)\n );\n}\n\n/** Configs that exist on disk, project-level first. */\nexport function detectClientConfigs(\n cwd?: string,\n home?: string,\n env?: NodeJS.ProcessEnv,\n): ClientConfigFile[] {\n return candidateConfigs(cwd, home, env).filter((c) => existsSync(c.path));\n}\n\n/** Describe an explicit path the user passed with `--client`. */\nexport function describeConfigPath(path: string): ClientConfigFile {\n const abs = resolve(path);\n const known = candidateConfigs().find((c) => c.path === abs);\n if (known) return known;\n let serversKey: \"mcpServers\" | \"servers\" = \"mcpServers\";\n try {\n const parsed = JSON.parse(readFileSync(abs, \"utf8\")) as Record<string, unknown>;\n if (parsed.servers && !parsed.mcpServers) serversKey = \"servers\";\n } catch {\n // unreadable: caller reports\n }\n return {\n kind: abs.includes(\".vscode\") ? \"vscode\" : \"generic\",\n label: abs,\n path: abs,\n serversKey,\n };\n}\n\nexport function readServers(file: ClientConfigFile): Record<string, ServerEntry> {\n const raw = JSON.parse(readFileSync(file.path, \"utf8\")) as Record<string, unknown>;\n const servers = raw[file.serversKey];\n if (!servers || typeof servers !== \"object\") return {};\n return servers as Record<string, ServerEntry>;\n}\n\nexport const PROXY_SERVER_NAME = \"okgate\";\n/** The key an okgate-era `init` or `connect` wrote; replaced, never duplicated. */\nexport const LEGACY_PROXY_SERVER_NAME = \"agentguard\";\n\n/** What `npx` is told to fetch. Must be the published package name (see install.ts). */\nexport const PROXY_PACKAGE = PACKAGE;\n\n/** The local proxy entry, as this CLI writes it now or as okgate wrote it. */\nexport function isProxyEntry(entry: ServerEntry): boolean {\n return (\n (entry.args ?? []).some((a) => /(^|\\/)(okgate|agentguard)(@[^/]*)?(\\.js)?$/.test(a)) &&\n (entry.args ?? []).includes(\"proxy\")\n );\n}\n\n/** Client servers → policy upstreams. Names are sanitized; secrets stay where they were (in the config). */\nexport function serversToUpstreams(servers: Record<string, ServerEntry>): {\n upstreams: Upstream[];\n skipped: { name: string; reason: string }[];\n} {\n const upstreams: Upstream[] = [];\n const skipped: { name: string; reason: string }[] = [];\n for (const [rawName, entry] of Object.entries(servers)) {\n if (isProxyEntry(entry)) {\n skipped.push({ name: rawName, reason: \"already the okgate proxy\" });\n continue;\n }\n const name =\n rawName.replace(/[^a-zA-Z0-9_-]/g, \"-\").replace(/^[^a-zA-Z0-9]+/, \"\") || \"upstream\";\n // `httpUrl` is Gemini CLI's Streamable HTTP field; okgate reaches upstreams that way.\n const url = typeof entry.httpUrl === \"string\" ? entry.httpUrl : entry.url;\n if (url) {\n upstreams.push({\n name,\n url,\n headers: entry.headers ?? {},\n args: [],\n env: {},\n prefix: false,\n timeout_ms: 60_000,\n });\n } else if (entry.command) {\n upstreams.push({\n name,\n command: entry.command,\n args: entry.args ?? [],\n env: entry.env ?? {},\n cwd: entry.cwd,\n headers: {},\n prefix: false,\n timeout_ms: 60_000,\n });\n } else {\n skipped.push({ name: rawName, reason: \"no `command` or `url`\" });\n }\n }\n return { upstreams, skipped };\n}\n\n/** The original's backup: an agentguard-era `.agentguard-backup` if there is one, else `.okgate-backup`. */\nexport function backupPath(file: ClientConfigFile): string {\n const { existing, next } = backupFor(file.path);\n return existing ?? next;\n}\n\n/** The entry that replaces every server: one proxy, all upstreams behind it. */\nexport function proxyEntry(\n file: ClientConfigFile,\n policyPath: string,\n opts: { agent?: string } = {},\n): ServerEntry {\n // The published name, scope and all. `npx -y okgate` 404s — that package does not\n // exist — so every config this wrote failed to start the proxy, and the line printed next\n // to it already said `npx @agentwares/agentguard proxy`. Worse than broken: the unscoped\n // name is unclaimed, so anyone who took it would have their code run by our onboarding.\n // install.ts says which package serves the okgate bin.\n const args = [...npxArgs({ yes: true }), \"proxy\", \"--config\", policyPath];\n if (opts.agent) args.push(\"--agent\", opts.agent);\n const entry: ServerEntry = { command: \"npx\", args };\n if (file.serversKey === \"servers\") entry.type = \"stdio\";\n return entry;\n}\n\n/** Back up the file (once) and replace its servers with the single proxy entry. */\nexport function rewriteClientConfig(\n file: ClientConfigFile,\n policyPath: string,\n opts: { agent?: string } = {},\n): { backup: string; replaced: string[] } {\n const raw = JSON.parse(readFileSync(file.path, \"utf8\")) as Record<string, unknown>;\n const servers = (raw[file.serversKey] as Record<string, ServerEntry> | undefined) ?? {};\n const replaced = Object.keys(servers).filter((n) => !isProxyEntry(servers[n]!));\n const backup = backupPath(file);\n if (!existsSync(backup)) copyFileSync(file.path, backup);\n raw[file.serversKey] = { [PROXY_SERVER_NAME]: proxyEntry(file, policyPath, opts) };\n writeFileSync(file.path, JSON.stringify(raw, null, 2) + \"\\n\");\n return { backup, replaced };\n}\n\n/** `okgate init --undo`: restore the backup. */\nexport function restoreClientConfig(file: ClientConfigFile): boolean {\n const backup = backupPath(file);\n if (!existsSync(backup)) return false;\n copyFileSync(backup, file.path);\n return true;\n}\n\n/**\n * Add (or replace) one named server in a client config, leaving every other server alone.\n *\n * `rewriteClientConfig` is the `init` path: it replaces the whole server list with the local\n * proxy. `connect` is the opposite shape — the hosted proxy is one more remote server sitting\n * alongside whatever the client already has — so it merges instead of replacing. Both back the\n * file up once before touching it, so `init --undo` still restores either.\n */\nexport function mergeServerIntoConfig(\n file: ClientConfigFile,\n name: string,\n entry: ServerEntry,\n /** older names of the same server, removed so it is not listed twice */\n replaces: readonly string[] = [],\n): { backup: string; replaced: boolean } {\n const raw = JSON.parse(readFileSync(file.path, \"utf8\")) as Record<string, unknown>;\n const servers = { ...((raw[file.serversKey] as Record<string, ServerEntry> | undefined) ?? {}) };\n const replaced = name in servers || replaces.some((old) => old in servers);\n for (const old of replaces) delete servers[old];\n const backup = backupPath(file);\n if (!existsSync(backup)) copyFileSync(file.path, backup);\n raw[file.serversKey] = { ...servers, [name]: entry };\n writeFileSync(file.path, JSON.stringify(raw, null, 2) + \"\\n\");\n return { backup, replaced };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
serveNodeHttp,
|
|
8
8
|
serveStdio,
|
|
9
9
|
toolError
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-IS3DAHZI.js";
|
|
11
11
|
|
|
12
12
|
// src/fixtures/crm-server.ts
|
|
13
13
|
import { z } from "zod";
|
|
@@ -171,7 +171,7 @@ function createCrmMcpServer(state = seedState()) {
|
|
|
171
171
|
return createMcpServer({
|
|
172
172
|
name: "fake-crm",
|
|
173
173
|
version: "0.1.0",
|
|
174
|
-
instructions: "A fake CRM for
|
|
174
|
+
instructions: "A fake CRM for okgate tests. Nothing here is real.",
|
|
175
175
|
tools: crmTools(state)
|
|
176
176
|
});
|
|
177
177
|
}
|
|
@@ -203,4 +203,4 @@ export {
|
|
|
203
203
|
crmTools,
|
|
204
204
|
createCrmMcpServer
|
|
205
205
|
};
|
|
206
|
-
//# sourceMappingURL=chunk-
|
|
206
|
+
//# sourceMappingURL=chunk-SWZQMPDG.js.map
|