57c21c3ee9df70230b9bb0429794400a1aedef81
- Author
- TheEdgeOfRage <git@theedgeofrage.com>
- Committer
- TheEdgeOfRage <git@theedgeofrage.com>
- Date
Message
Diff
This diff is truncated to protect this page.
1diff --git a/README.md b/README.md
2index 73ba64a10206f89813a2989d34401da7eecc4b6f..0d0ccd58a4625252fb2337e05e638be97674dfa3 100644
3--- a/README.md
4+++ b/README.md
5@@ -60,7 +60,7 @@ The extension handles Pi's `tool_call` event and evaluates each tool call before
6
7 **Stage 3 — LLM** sends the tool input to the configured model with a security-focused prompt. Successful responses are cached; errors and unparseable responses become `ask` decisions and are not cached.
8
9diff --git a/src/deterministic.ts b/src/deterministic.ts
10index f6b16f240b141cde47f3c9416f3ed23e21f8d7a6..701f72dbe5cb954d79f8b646f6abd9900f2ed826 100644
11--- a/src/deterministic.ts
12+++ b/src/deterministic.ts
13@@ -90,7 +90,13 @@ export function checkDeterministic(
14 category: "web_read",
15 }
16 default:
17- if (toolType.startsWith("mcp__")) return undefined
18+ if (toolType === "mcp" || toolType.startsWith("mcp__")) {
19+ return {
20+ decision: "allow",
21+ reason: "MCP tools bypass policy evaluation",
22+ category: "mcp",
23+ }
24+ }
25 return undefined
26 }
27 }
28diff --git a/src/rules.ts b/src/rules.ts
29index f614ddadd4da95afb9523e89885ce39862bca39f..0c23929956b747279cb5e80c903ec071d360d81e 100644
30--- a/src/rules.ts
31+++ b/src/rules.ts
32@@ -1,5 +1,5 @@
33 // Bump to invalidate all cached decisions when rules change.
34-export const POLICY_VERSION = 23;
35+export const POLICY_VERSION = 24;
36
37 // Trailing stderr redirections that are safe to strip before pattern matching.
38 // `2>&1` and `2>/dev/null` have no security implication but would otherwise
39diff --git a/test/deterministic.test.ts b/test/deterministic.test.ts
40index dcb3cdcfcf6143727cea32bf3b0dbc1cae85655a..1be5a57d5abdcf2614b170a63b60811a7994c5d4 100644
41--- a/test/deterministic.test.ts
42+++ b/test/deterministic.test.ts
43@@ -210,8 +210,13 @@ test("websearch always allowed", () => {
44 expect(d!.decision).toBe("allow")
45 })
46
47+test.each(["mcp", "mcp__linear__list"])("MCP tool %s is always allowed", (toolType) => {
48+ const decision = checkDeterministic(toolType, { foo: 1 })
49+ expect(decision).toMatchObject({ decision: "allow", category: "mcp" })
50+})
51+
52 test("unknown tool type returns undefined", () => {
53- expect(checkDeterministic("mcp__linear__list", { foo: 1 })).toBeUndefined()
54+ expect(checkDeterministic("unknown", { foo: 1 })).toBeUndefined()
55 })
56
57 describe("rtk prefix is transparent", () => {
58diff --git a/test/extension.test.ts b/test/extension.test.ts
59index e84da230cbb4822950af4a1a48183ccd7f76a579..1120cfda462d6a8323488545435faccf3fd1ed90 100644
60--- a/test/extension.test.ts
61+++ b/test/extension.test.ts
62@@ -55,6 +55,14 @@ describe("Pi policy extension", () => {
63 .resolves.toBeUndefined()
64 })
65
66+ test("allows MCP tool calls without policy approval", async () => {
67+ const { toolCall } = loadExtension()
68+ await expect(toolCall(
69+ { toolName: "mcp", input: { action: "auth-start", server: "grafana_prod" } },
70+ context(false),
71+ )).resolves.toBeUndefined()
72+ })
73+
74 test("runs check actions through deterministic rules", async () => {
75 writeFileSync(process.env.PI_POLICY_ENGINE_CONFIG!, JSON.stringify({
76 permission: { bash: { "*": "check" } },