@praxis.guard/auditor-cli 0.0.62 → 0.0.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -0
- package/dist/adapters/claude-code/adapter.d.ts +3 -1
- package/dist/adapters/claude-code/adapter.d.ts.map +1 -1
- package/dist/adapters/claude-code/adapter.js +68 -0
- package/dist/adapters/claude-code/adapter.js.map +1 -1
- package/dist/adapters/claude-desktop.d.ts +2 -1
- package/dist/adapters/claude-desktop.d.ts.map +1 -1
- package/dist/adapters/claude-desktop.js +24 -0
- package/dist/adapters/claude-desktop.js.map +1 -1
- package/dist/adapters/codex.d.ts +3 -1
- package/dist/adapters/codex.d.ts.map +1 -1
- package/dist/adapters/codex.js +7 -1
- package/dist/adapters/codex.js.map +1 -1
- package/dist/adapters/copilot-cli/adapter.d.ts +3 -1
- package/dist/adapters/copilot-cli/adapter.d.ts.map +1 -1
- package/dist/adapters/copilot-cli/adapter.js +57 -1
- package/dist/adapters/copilot-cli/adapter.js.map +1 -1
- package/dist/adapters/copilot-cli/config.d.ts +6 -0
- package/dist/adapters/copilot-cli/config.d.ts.map +1 -1
- package/dist/adapters/copilot-cli/config.js +23 -0
- package/dist/adapters/copilot-cli/config.js.map +1 -1
- package/dist/adapters/cursor.d.ts +4 -1
- package/dist/adapters/cursor.d.ts.map +1 -1
- package/dist/adapters/cursor.js +15 -1
- package/dist/adapters/cursor.js.map +1 -1
- package/dist/adapters/remove-helpers.d.ts +23 -0
- package/dist/adapters/remove-helpers.d.ts.map +1 -0
- package/dist/adapters/remove-helpers.js +40 -0
- package/dist/adapters/remove-helpers.js.map +1 -0
- package/dist/adapters/select-targets.d.ts +10 -0
- package/dist/adapters/select-targets.d.ts.map +1 -1
- package/dist/adapters/select-targets.js +23 -1
- package/dist/adapters/select-targets.js.map +1 -1
- package/dist/adapters/types.d.ts +29 -0
- package/dist/adapters/types.d.ts.map +1 -1
- package/dist/adapters/vscode.d.ts +2 -1
- package/dist/adapters/vscode.d.ts.map +1 -1
- package/dist/adapters/vscode.js +38 -6
- package/dist/adapters/vscode.js.map +1 -1
- package/dist/approval/mcp-flow-create.d.ts +3 -0
- package/dist/approval/mcp-flow-create.d.ts.map +1 -0
- package/dist/approval/mcp-flow-create.js +76 -0
- package/dist/approval/mcp-flow-create.js.map +1 -0
- package/dist/approval/mcp-flow-existing.d.ts +14 -0
- package/dist/approval/mcp-flow-existing.d.ts.map +1 -0
- package/dist/approval/mcp-flow-existing.js +43 -0
- package/dist/approval/mcp-flow-existing.js.map +1 -0
- package/dist/approval/mcp-flow-outcome.d.ts +5 -0
- package/dist/approval/mcp-flow-outcome.d.ts.map +1 -0
- package/dist/approval/mcp-flow-outcome.js +19 -0
- package/dist/approval/mcp-flow-outcome.js.map +1 -0
- package/dist/approval/mcp-flow-pending.d.ts +7 -0
- package/dist/approval/mcp-flow-pending.d.ts.map +1 -0
- package/dist/approval/mcp-flow-pending.js +25 -0
- package/dist/approval/mcp-flow-pending.js.map +1 -0
- package/dist/approval/mcp-flow-redeem.d.ts +13 -0
- package/dist/approval/mcp-flow-redeem.d.ts.map +1 -0
- package/dist/approval/mcp-flow-redeem.js +20 -0
- package/dist/approval/mcp-flow-redeem.js.map +1 -0
- package/dist/approval/mcp-flow.d.ts +6 -28
- package/dist/approval/mcp-flow.d.ts.map +1 -1
- package/dist/approval/mcp-flow.js +21 -129
- package/dist/approval/mcp-flow.js.map +1 -1
- package/dist/approval/mcp-flow.types.d.ts +42 -0
- package/dist/approval/mcp-flow.types.d.ts.map +1 -0
- package/dist/approval/mcp-flow.types.js +2 -0
- package/dist/approval/mcp-flow.types.js.map +1 -0
- package/dist/cli/cursor-config/environment-config.d.ts +8 -0
- package/dist/cli/cursor-config/environment-config.d.ts.map +1 -1
- package/dist/cli/cursor-config/environment-config.js +45 -1
- package/dist/cli/cursor-config/environment-config.js.map +1 -1
- package/dist/cli/cursor-config/hooks-config.d.ts +13 -0
- package/dist/cli/cursor-config/hooks-config.d.ts.map +1 -1
- package/dist/cli/cursor-config/hooks-config.js +64 -0
- package/dist/cli/cursor-config/hooks-config.js.map +1 -1
- package/dist/cli/cursor-config/index.d.ts +3 -3
- package/dist/cli/cursor-config/index.d.ts.map +1 -1
- package/dist/cli/cursor-config/index.js +3 -3
- package/dist/cli/cursor-config/index.js.map +1 -1
- package/dist/cli/cursor-config/json-io.d.ts +2 -0
- package/dist/cli/cursor-config/json-io.d.ts.map +1 -1
- package/dist/cli/cursor-config/json-io.js +5 -1
- package/dist/cli/cursor-config/json-io.js.map +1 -1
- package/dist/cli/cursor-config/mcp-config.d.ts +5 -0
- package/dist/cli/cursor-config/mcp-config.d.ts.map +1 -1
- package/dist/cli/cursor-config/mcp-config.js +37 -0
- package/dist/cli/cursor-config/mcp-config.js.map +1 -1
- package/dist/cli/cursor-config.d.ts +1 -1
- package/dist/cli/cursor-config.d.ts.map +1 -1
- package/dist/cli/cursor-config.js +1 -1
- package/dist/cli/cursor-config.js.map +1 -1
- package/dist/cli/dispatch-uninstall.d.ts +6 -0
- package/dist/cli/dispatch-uninstall.d.ts.map +1 -0
- package/dist/cli/dispatch-uninstall.js +10 -0
- package/dist/cli/dispatch-uninstall.js.map +1 -0
- package/dist/cli/doctor-adapter-lines.d.ts +4 -0
- package/dist/cli/doctor-adapter-lines.d.ts.map +1 -0
- package/dist/cli/doctor-adapter-lines.js +47 -0
- package/dist/cli/doctor-adapter-lines.js.map +1 -0
- package/dist/cli/doctor-notifications.d.ts +5 -0
- package/dist/cli/doctor-notifications.d.ts.map +1 -0
- package/dist/cli/doctor-notifications.js +10 -0
- package/dist/cli/doctor-notifications.js.map +1 -0
- package/dist/cli/doctor-remote.d.ts +3 -0
- package/dist/cli/doctor-remote.d.ts.map +1 -0
- package/dist/cli/doctor-remote.js +48 -0
- package/dist/cli/doctor-remote.js.map +1 -0
- package/dist/cli/doctor.d.ts +1 -22
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +46 -142
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +3 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +12 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/setup-gateway.d.ts +13 -0
- package/dist/cli/setup-gateway.d.ts.map +1 -1
- package/dist/cli/setup-gateway.js +24 -0
- package/dist/cli/setup-gateway.js.map +1 -1
- package/dist/cli/uninstall-all.d.ts +24 -0
- package/dist/cli/uninstall-all.d.ts.map +1 -0
- package/dist/cli/uninstall-all.js +249 -0
- package/dist/cli/uninstall-all.js.map +1 -0
- package/dist/codex/config-hooks.d.ts +7 -0
- package/dist/codex/config-hooks.d.ts.map +1 -1
- package/dist/codex/config-hooks.js +28 -0
- package/dist/codex/config-hooks.js.map +1 -1
- package/dist/codex/config-io.d.ts +1 -0
- package/dist/codex/config-io.d.ts.map +1 -1
- package/dist/codex/config-io.js +4 -1
- package/dist/codex/config-io.js.map +1 -1
- package/dist/codex/config-toml.d.ts +7 -0
- package/dist/codex/config-toml.d.ts.map +1 -1
- package/dist/codex/config-toml.js +50 -0
- package/dist/codex/config-toml.js.map +1 -1
- package/dist/codex/config.d.ts +2 -0
- package/dist/codex/config.d.ts.map +1 -1
- package/dist/codex/config.js +52 -3
- package/dist/codex/config.js.map +1 -1
- package/dist/mcp/evaluate-guard-approval.d.ts +47 -0
- package/dist/mcp/evaluate-guard-approval.d.ts.map +1 -0
- package/dist/mcp/evaluate-guard-approval.js +80 -0
- package/dist/mcp/evaluate-guard-approval.js.map +1 -0
- package/dist/mcp/evaluate-guard-policy.d.ts +3 -0
- package/dist/mcp/evaluate-guard-policy.d.ts.map +1 -0
- package/dist/mcp/evaluate-guard-policy.js +6 -0
- package/dist/mcp/evaluate-guard-policy.js.map +1 -0
- package/dist/mcp/evaluate-guard-proposal.d.ts +16 -0
- package/dist/mcp/evaluate-guard-proposal.d.ts.map +1 -0
- package/dist/mcp/evaluate-guard-proposal.js +57 -0
- package/dist/mcp/evaluate-guard-proposal.js.map +1 -0
- package/dist/mcp/evaluate-guard-run.d.ts +23 -0
- package/dist/mcp/evaluate-guard-run.d.ts.map +1 -0
- package/dist/mcp/evaluate-guard-run.js +75 -0
- package/dist/mcp/evaluate-guard-run.js.map +1 -0
- package/dist/mcp/evaluate-guard-telemetry.d.ts +22 -0
- package/dist/mcp/evaluate-guard-telemetry.d.ts.map +1 -0
- package/dist/mcp/evaluate-guard-telemetry.js +38 -0
- package/dist/mcp/evaluate-guard-telemetry.js.map +1 -0
- package/dist/mcp/evaluate-guard-tier.d.ts +18 -0
- package/dist/mcp/evaluate-guard-tier.d.ts.map +1 -0
- package/dist/mcp/evaluate-guard-tier.js +42 -0
- package/dist/mcp/evaluate-guard-tier.js.map +1 -0
- package/dist/mcp/evaluate-guard.d.ts +2 -5
- package/dist/mcp/evaluate-guard.d.ts.map +1 -1
- package/dist/mcp/evaluate-guard.js +18 -195
- package/dist/mcp/evaluate-guard.js.map +1 -1
- package/dist/mcp/gateway-call-handler.d.ts +9 -0
- package/dist/mcp/gateway-call-handler.d.ts.map +1 -0
- package/dist/mcp/gateway-call-handler.js +61 -0
- package/dist/mcp/gateway-call-handler.js.map +1 -0
- package/dist/mcp/gateway-call-results.d.ts +5 -0
- package/dist/mcp/gateway-call-results.d.ts.map +1 -0
- package/dist/mcp/gateway-call-results.js +14 -0
- package/dist/mcp/gateway-call-results.js.map +1 -0
- package/dist/mcp/gateway-connection-lib.d.ts +54 -0
- package/dist/mcp/gateway-connection-lib.d.ts.map +1 -0
- package/dist/mcp/gateway-connection-lib.js +39 -0
- package/dist/mcp/gateway-connection-lib.js.map +1 -0
- package/dist/mcp/gateway-connection.d.ts +16 -0
- package/dist/mcp/gateway-connection.d.ts.map +1 -0
- package/dist/mcp/gateway-connection.js +54 -0
- package/dist/mcp/gateway-connection.js.map +1 -0
- package/dist/mcp/gateway-log.d.ts +5 -0
- package/dist/mcp/gateway-log.d.ts.map +1 -0
- package/dist/mcp/gateway-log.js +9 -0
- package/dist/mcp/gateway-log.js.map +1 -0
- package/dist/mcp/gateway.d.ts +2 -20
- package/dist/mcp/gateway.d.ts.map +1 -1
- package/dist/mcp/gateway.js +18 -186
- package/dist/mcp/gateway.js.map +1 -1
- package/dist/policies.v1.json +6 -0
- package/native/darwin-amd64/praxis-guard-daemon +0 -0
- package/native/darwin-amd64/praxis-guard-hook +0 -0
- package/native/darwin-arm64/praxis-guard-daemon +0 -0
- package/native/darwin-arm64/praxis-guard-hook +0 -0
- package/native/linux-amd64/praxis-guard-daemon +0 -0
- package/native/linux-amd64/praxis-guard-hook +0 -0
- package/native/linux-arm64/praxis-guard-daemon +0 -0
- package/native/linux-arm64/praxis-guard-hook +0 -0
- package/package.json +1 -1
package/dist/mcp/gateway.d.ts
CHANGED
|
@@ -1,24 +1,6 @@
|
|
|
1
1
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
|
-
import { type
|
|
3
|
-
|
|
4
|
-
* One downstream MCP server, abstracted so tests can inject fakes without
|
|
5
|
-
* spawning real subprocesses. The real implementation is `connectStdioServer`.
|
|
6
|
-
*/
|
|
7
|
-
export interface GatewayConnection {
|
|
8
|
-
readonly id: string;
|
|
9
|
-
/** Tools advertised by this downstream server (fetched at connect). */
|
|
10
|
-
tools: Tool[];
|
|
11
|
-
callTool(tool: string, args: Record<string, unknown>): Promise<CallToolResult>;
|
|
12
|
-
/** Re-establish the underlying transport after a failure. Returns false if it cannot. */
|
|
13
|
-
reconnect(): Promise<boolean>;
|
|
14
|
-
/**
|
|
15
|
-
* Register a callback fired AFTER this connection refreshes its tool slice in
|
|
16
|
-
* response to a downstream `tools/list_changed` (or a reconnect-driven refresh).
|
|
17
|
-
* `createGatewayServer` uses it to re-emit the gateway's own `list_changed`
|
|
18
|
-
* upstream. Optional so in-process test fakes need not implement it.
|
|
19
|
-
*/
|
|
20
|
-
onToolsChanged?(listener: () => void): void;
|
|
21
|
-
}
|
|
2
|
+
import { type GatewayConnection } from "./gateway-connection.js";
|
|
3
|
+
export type { GatewayConnection } from "./gateway-connection.js";
|
|
22
4
|
/**
|
|
23
5
|
* Build the low-level MCP `Server` that fronts the given downstream connections.
|
|
24
6
|
* Exported for tests (inject fake connections); `runMcpGateway` wires the real ones.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/mcp/gateway.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/mcp/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAmBnE,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,yBAAyB,CAAC;AAGjC,YAAY,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,iBAAiB,EAAE,GAAG,MAAM,CAmC5E;AAED;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8B9E"}
|
package/dist/mcp/gateway.js
CHANGED
|
@@ -1,116 +1,14 @@
|
|
|
1
|
-
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
2
|
-
import { StdioClientTransport, getDefaultEnvironment, } from "@modelcontextprotocol/sdk/client/stdio.js";
|
|
3
1
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
-
import { CallToolRequestSchema, ListToolsRequestSchema,
|
|
3
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
6
4
|
import { mkdirSync } from "node:fs";
|
|
7
5
|
import path from "node:path";
|
|
8
6
|
import { AUDITOR_CLI_VERSION } from "../runtime/version.js";
|
|
9
7
|
import { GUARD_DIR } from "../bridge/guard-storage-root.js";
|
|
10
|
-
import { exposedToolName, loadGatewayConfig,
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
function logErr(line) {
|
|
15
|
-
process.stderr.write(`[auditor-gateway] ${line}\n`);
|
|
16
|
-
}
|
|
17
|
-
function withTimeout(p, ms, label) {
|
|
18
|
-
return new Promise((resolve, reject) => {
|
|
19
|
-
const t = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
20
|
-
p.then((v) => {
|
|
21
|
-
clearTimeout(t);
|
|
22
|
-
resolve(v);
|
|
23
|
-
}, (e) => {
|
|
24
|
-
clearTimeout(t);
|
|
25
|
-
reject(e);
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Register the downstream `tools/list_changed` handler on `client` (the CURRENT
|
|
31
|
-
* one; call again after a reconnect with the fresh client). On notification:
|
|
32
|
-
* re-list (bounded), swap the connection's slice, then fire `getListener` so the
|
|
33
|
-
* gateway re-emits list_changed upstream. A failed refresh keeps the prior slice
|
|
34
|
-
* (no crash); the next call's reconnect path heals the connection.
|
|
35
|
-
*/
|
|
36
|
-
function attachListChangedHandler(client, conn, getListener) {
|
|
37
|
-
client.setNotificationHandler(ToolListChangedNotificationSchema, async () => {
|
|
38
|
-
try {
|
|
39
|
-
const re = await withTimeout(client.listTools(), CONNECT_TIMEOUT_MS, `listTools ${conn.id}`);
|
|
40
|
-
conn.tools = re.tools;
|
|
41
|
-
getListener()?.();
|
|
42
|
-
}
|
|
43
|
-
catch (e) {
|
|
44
|
-
logErr(`tools/list_changed refresh for "${conn.id}" failed: ${truncErr(e)}`);
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
/** Real stdio-backed connection to a downstream MCP server. */
|
|
49
|
-
async function connectStdioServer(server) {
|
|
50
|
-
const spawn = () => new StdioClientTransport({
|
|
51
|
-
command: server.command,
|
|
52
|
-
args: server.args,
|
|
53
|
-
env: server.env ? { ...getDefaultEnvironment(), ...server.env } : undefined,
|
|
54
|
-
});
|
|
55
|
-
let client = new Client({ name: `praxis-gateway-client-${server.id}`, version: AUDITOR_CLI_VERSION });
|
|
56
|
-
// Set when createGatewayServer wires this connection (re-emits list_changed upstream).
|
|
57
|
-
let toolsChangedListener = null;
|
|
58
|
-
const getListener = () => toolsChangedListener;
|
|
59
|
-
await withTimeout(client.connect(spawn()), CONNECT_TIMEOUT_MS, `connect ${server.id}`);
|
|
60
|
-
const listed = await withTimeout(client.listTools(), CONNECT_TIMEOUT_MS, `listTools ${server.id}`);
|
|
61
|
-
const conn = {
|
|
62
|
-
id: server.id,
|
|
63
|
-
tools: listed.tools,
|
|
64
|
-
onToolsChanged(listener) {
|
|
65
|
-
toolsChangedListener = listener;
|
|
66
|
-
},
|
|
67
|
-
async callTool(tool, args) {
|
|
68
|
-
return (await client.callTool({ name: tool, arguments: args }));
|
|
69
|
-
},
|
|
70
|
-
async reconnect() {
|
|
71
|
-
try {
|
|
72
|
-
// Close the old client first so the dead subprocess + pipes are reaped;
|
|
73
|
-
// otherwise a flapping downstream leaks one child process per failure.
|
|
74
|
-
await client.close().catch(() => { });
|
|
75
|
-
client = new Client({
|
|
76
|
-
name: `praxis-gateway-client-${server.id}`,
|
|
77
|
-
version: AUDITOR_CLI_VERSION,
|
|
78
|
-
});
|
|
79
|
-
await withTimeout(client.connect(spawn()), CONNECT_TIMEOUT_MS, `reconnect ${server.id}`);
|
|
80
|
-
const re = await withTimeout(client.listTools(), CONNECT_TIMEOUT_MS, `listTools ${server.id}`);
|
|
81
|
-
conn.tools = re.tools;
|
|
82
|
-
// Fresh client needs its own handler; the tool set may have changed across
|
|
83
|
-
// the gap, so propagate the refreshed slice upstream.
|
|
84
|
-
attachListChangedHandler(client, conn, getListener);
|
|
85
|
-
toolsChangedListener?.();
|
|
86
|
-
return true;
|
|
87
|
-
}
|
|
88
|
-
catch (e) {
|
|
89
|
-
logErr(`reconnect to "${server.id}" failed: ${String(e)}`);
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
},
|
|
93
|
-
};
|
|
94
|
-
attachListChangedHandler(client, conn, getListener);
|
|
95
|
-
return conn;
|
|
96
|
-
}
|
|
97
|
-
function textResult(text, isError) {
|
|
98
|
-
return { content: [{ type: "text", text }], isError };
|
|
99
|
-
}
|
|
100
|
-
/** Bound downstream-supplied error text so a hostile downstream can't flood or spoof the result. */
|
|
101
|
-
function truncErr(e) {
|
|
102
|
-
return String(e).slice(0, 300);
|
|
103
|
-
}
|
|
104
|
-
function blockedResult(serverId, tool, d) {
|
|
105
|
-
const reason = d.reasons[0] ?? "policy";
|
|
106
|
-
if (d.inlineApproval) {
|
|
107
|
-
return textResult(`Praxis guard requires human approval for ${serverId}__${tool} (tier=${d.tier}). ` +
|
|
108
|
-
`Approve at ${d.inlineApproval.open_url} then retry this exact tool call. ` +
|
|
109
|
-
`(request ${d.inlineApproval.request_id})`, true);
|
|
110
|
-
}
|
|
111
|
-
return textResult(`Praxis guard blocked ${serverId}__${tool} (tier=${d.tier}): ${reason}. ` +
|
|
112
|
-
(d.tier === "DESTRUCTIVE" ? "Destructive actions cannot be auto-approved." : ""), true);
|
|
113
|
-
}
|
|
8
|
+
import { exposedToolName, loadGatewayConfig, resolveGatewayStorageRoot, } from "./gateway-config.js";
|
|
9
|
+
import { handleGatewayCallTool } from "./gateway-call-handler.js";
|
|
10
|
+
import { connectStdioServer, } from "./gateway-connection.js";
|
|
11
|
+
import { logGatewayErr, truncGatewayErr } from "./gateway-log.js";
|
|
114
12
|
/**
|
|
115
13
|
* Build the low-level MCP `Server` that fronts the given downstream connections.
|
|
116
14
|
* Exported for tests (inject fake connections); `runMcpGateway` wires the real ones.
|
|
@@ -120,10 +18,7 @@ function blockedResult(serverId, tool, d) {
|
|
|
120
18
|
export function createGatewayServer(connections) {
|
|
121
19
|
const byId = new Map(connections.map((c) => [c.id, c]));
|
|
122
20
|
const ids = connections.map((c) => c.id);
|
|
123
|
-
const server = new Server({ name: "praxis-guard-gateway", version: AUDITOR_CLI_VERSION },
|
|
124
|
-
// listChanged: true tells the host (Desktop) to listen for tools/list_changed
|
|
125
|
-
// so downstream tools that appear after login (auth-gated) become visible.
|
|
126
|
-
{ capabilities: { tools: { listChanged: true } } });
|
|
21
|
+
const server = new Server({ name: "praxis-guard-gateway", version: AUDITOR_CLI_VERSION }, { capabilities: { tools: { listChanged: true } } });
|
|
127
22
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
128
23
|
const tools = [];
|
|
129
24
|
for (const conn of connections) {
|
|
@@ -133,75 +28,17 @@ export function createGatewayServer(connections) {
|
|
|
133
28
|
}
|
|
134
29
|
return { tools };
|
|
135
30
|
});
|
|
136
|
-
// When any downstream refreshes its tool slice, re-emit the gateway's own
|
|
137
|
-
// list_changed upstream so the host re-fetches the combined namespaced set.
|
|
138
31
|
for (const conn of connections) {
|
|
139
32
|
conn.onToolsChanged?.(() => {
|
|
140
|
-
server.sendToolListChanged().catch((e) =>
|
|
33
|
+
server.sendToolListChanged().catch((e) => logGatewayErr(`sendToolListChanged failed: ${truncGatewayErr(e)}`));
|
|
141
34
|
});
|
|
142
35
|
}
|
|
143
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
const args = (request.params.arguments ?? {});
|
|
150
|
-
const parsed = parseExposedToolName(exposed, ids);
|
|
151
|
-
if (!parsed) {
|
|
152
|
-
return textResult(`Praxis gateway: unknown tool "${exposed}".`, true);
|
|
153
|
-
}
|
|
154
|
-
const conn = byId.get(parsed.serverId);
|
|
155
|
-
if (!conn) {
|
|
156
|
-
return textResult(`Praxis gateway: downstream "${parsed.serverId}" is not connected.`, true);
|
|
157
|
-
}
|
|
158
|
-
// Only proxy tools the downstream actually advertised. Without this, any
|
|
159
|
-
// `knownServer__anything` would be forwarded (and classified skipped->allow),
|
|
160
|
-
// proxying tools the downstream never listed. The gateway owns this check, not
|
|
161
|
-
// the downstream (found in QA: ISSUE-001).
|
|
162
|
-
if (!conn.tools.some((t) => t.name === parsed.tool)) {
|
|
163
|
-
return textResult(`Praxis gateway: "${parsed.serverId}" does not expose a tool named "${parsed.tool}".`, true);
|
|
164
|
-
}
|
|
165
|
-
const decision = await evaluateGatewayCall({
|
|
166
|
-
serverId: parsed.serverId,
|
|
167
|
-
tool: parsed.tool,
|
|
168
|
-
toolInput: args,
|
|
169
|
-
});
|
|
170
|
-
if (decision.decision === "block") {
|
|
171
|
-
return blockedResult(parsed.serverId, parsed.tool, decision);
|
|
172
|
-
}
|
|
173
|
-
// allow -> forward, returning the downstream result VERBATIM (decision D5).
|
|
174
|
-
try {
|
|
175
|
-
return await conn.callTool(parsed.tool, args);
|
|
176
|
-
}
|
|
177
|
-
catch (e) {
|
|
178
|
-
logErr(`downstream "${parsed.serverId}" call failed: ${truncErr(e)}; reconnecting`);
|
|
179
|
-
const ok = await conn.reconnect();
|
|
180
|
-
// Retry ONLY idempotent (READ) calls. A redeemed MUTATE/DESTRUCTIVE must not
|
|
181
|
-
// be auto-replayed: if the first attempt reached the downstream and mutated
|
|
182
|
-
// state before the transport died, a blind retry double-applies it. Reconnect
|
|
183
|
-
// still heals the connection for the next call.
|
|
184
|
-
if (ok && decision.tier === "READ") {
|
|
185
|
-
try {
|
|
186
|
-
return await conn.callTool(parsed.tool, args);
|
|
187
|
-
}
|
|
188
|
-
catch (e2) {
|
|
189
|
-
return textResult(`Praxis gateway: downstream "${parsed.serverId}" error after reconnect: ${truncErr(e2)}`, true);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
return textResult(`Praxis gateway: downstream "${parsed.serverId}" call failed` +
|
|
193
|
-
(ok ? " (reconnected; not retried to avoid double-execution)" : " and is unavailable") +
|
|
194
|
-
`: ${truncErr(e)}`, true);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
catch (e) {
|
|
198
|
-
logErr(`gating error for "${request.params?.name}": ${truncErr(e)}`);
|
|
199
|
-
// Blast-radius escape hatch: the gateway fronts every Desktop connector, so a
|
|
200
|
-
// fail-closed bug blocks all tools. Name the recovery path in the result.
|
|
201
|
-
return textResult("Praxis gateway: guard evaluation failed; blocking this call (fail-closed). " +
|
|
202
|
-
"To restore direct tools: run `auditor setup gateway --revert --apply`, then relaunch Claude Desktop.", true);
|
|
203
|
-
}
|
|
204
|
-
});
|
|
36
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => handleGatewayCallTool({
|
|
37
|
+
exposed: request.params.name,
|
|
38
|
+
args: (request.params.arguments ?? {}),
|
|
39
|
+
ids,
|
|
40
|
+
byId,
|
|
41
|
+
}));
|
|
205
42
|
return server;
|
|
206
43
|
}
|
|
207
44
|
/**
|
|
@@ -211,33 +48,28 @@ export function createGatewayServer(connections) {
|
|
|
211
48
|
* stdio. Blocks until disconnect.
|
|
212
49
|
*/
|
|
213
50
|
export async function runMcpGateway(explicitConfigPath) {
|
|
214
|
-
// Create the dedicated gateway guard storage marker BEFORE any evaluation so
|
|
215
|
-
// resolveGuardStorageRoot resolves ticket/approval/audit state to the gateway's
|
|
216
|
-
// own root (not $HOME). Without this marker the walk-up would land on $HOME and
|
|
217
|
-
// re-share the namespace with hook hosts (decision D9). Best-effort: a failure
|
|
218
|
-
// here must not stop the gateway from serving.
|
|
219
51
|
try {
|
|
220
52
|
mkdirSync(path.join(resolveGatewayStorageRoot(), GUARD_DIR), { recursive: true });
|
|
221
53
|
}
|
|
222
54
|
catch (e) {
|
|
223
|
-
|
|
55
|
+
logGatewayErr(`could not create gateway storage root: ${truncGatewayErr(e)}`);
|
|
224
56
|
}
|
|
225
57
|
const { servers, errors } = await loadGatewayConfig(explicitConfigPath);
|
|
226
58
|
for (const e of errors)
|
|
227
|
-
|
|
59
|
+
logGatewayErr(e);
|
|
228
60
|
const settled = await Promise.allSettled(servers.map((s) => connectStdioServer(s)));
|
|
229
61
|
const connections = [];
|
|
230
62
|
settled.forEach((r, i) => {
|
|
231
63
|
if (r.status === "fulfilled") {
|
|
232
64
|
connections.push(r.value);
|
|
233
|
-
|
|
65
|
+
logGatewayErr(`connected "${servers[i].id}" (${r.value.tools.length} tools)`);
|
|
234
66
|
}
|
|
235
67
|
else {
|
|
236
|
-
|
|
68
|
+
logGatewayErr(`skipping "${servers[i].id}": ${String(r.reason)}`);
|
|
237
69
|
}
|
|
238
70
|
});
|
|
239
71
|
if (connections.length === 0) {
|
|
240
|
-
|
|
72
|
+
logGatewayErr("no downstream servers connected; gateway will expose no tools. " +
|
|
241
73
|
"To restore direct connectors: run `auditor setup gateway --revert --apply`, then relaunch Claude Desktop.");
|
|
242
74
|
}
|
|
243
75
|
const server = createGatewayServer(connections);
|
package/dist/mcp/gateway.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["../../src/mcp/gateway.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,
|
|
1
|
+
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["../../src/mcp/gateway.ts"],"names":[],"mappings":"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"}
|
package/dist/policies.v1.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|