Skip to content

feat: add MCP permission grants#40

Merged
gnanam1990 merged 1 commit into
mainfrom
feat/m4-mcp-permissions
Jun 3, 2026
Merged

feat: add MCP permission grants#40
gnanam1990 merged 1 commit into
mainfrom
feat/m4-mcp-permissions

Conversation

@gnanam1990

@gnanam1990 gnanam1990 commented Jun 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds the M4 MCP permissions backend so Zero can persist trusted MCP server/tool grants and manage them from the CLI.

What changed

  • Added ZeroMcpPermissionStore for durable per-server and per-tool MCP grants.
  • Enforced server identity matching so stale grants do not apply after a server transport changes.
  • Added autonomy ceilings (low, medium, high) for persistent approvals.
  • Added zero mcp permissions list, revoke, and clear CLI commands with JSON output support.
  • Wired MCP tool metadata into the agent loop so matching persistent grants can skip repeated ask-mode prompts.
  • Kept one-time session approval grants separate from persistent MCP grants.
  • Made MCP registry registration atomic when duplicate generated tool names are detected.
  • Preserved custom tool JSON schemas while preparing provider tool definitions.

Validation

  • npx --yes bun install --frozen-lockfile
  • npx --yes bun run typecheck
  • npx --yes bun test ./tests --timeout 15000 (253 pass, 0 fail)
  • npx --yes bun run build
  • npx --yes bun run smoke:build
  • ./zero --help
  • ./zero mcp --help
  • ./zero mcp permissions --help
  • ZERO_MCP_PERMISSIONS_PATH=/tmp/zero-mcp-permissions-pr-smoke.json ./zero mcp permissions list --json
  • git diff --check HEAD

Summary by CodeRabbit

  • New Features

    • Manage persistent MCP permission grants via new zero mcp permissions CLI commands: list permissions, revoke server or tool grants, and clear all approvals.
    • Control MCP tool execution through autonomy level settings (low, medium, high).
  • Bug Fixes

    • Fixed JSON schema object mutations during tool definition preparation.

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 76423934-06e1-4829-8815-6bc629565529

📥 Commits

Reviewing files that changed from the base of the PR and between cf84860 and 3ef496d.

📒 Files selected for processing (12)
  • src/agent/loop.ts
  • src/index.ts
  • src/tools/registry.ts
  • src/tools/types.ts
  • src/zero-mcp/index.ts
  • src/zero-mcp/permissions.ts
  • src/zero-mcp/tools.ts
  • src/zero-runtime/context.ts
  • src/zero-runtime/types.ts
  • tests/agent-loop.test.ts
  • tests/zero-mcp-client.test.ts
  • tests/zero-mcp-permissions.test.ts

📝 Walkthrough

Walkthrough

This PR introduces persistent MCP tool permission management. New file-based storage (ZeroMcpPermissionStore) durably tracks approved tools and servers per autonomy level. Tools gain identity metadata to associate with stored grants. The agent loop's permission check now queries this store before asking for interactive approval, allowing previously-approved tools to execute silently. CLI commands manage the grant database. Type contracts are updated to propagate autonomy through the runtime.

Changes

MCP Persistent Permission Management

Layer / File(s) Summary
Permission store and persistence layer
src/zero-mcp/permissions.ts, src/zero-mcp/index.ts
Defines ZeroMcpPermissionGrant model and implements ZeroMcpPermissionStore with file-based atomic persistence, concurrent-write serialization, autonomy ordering, and tool-over-server precedence for approval decisions.
Tool metadata and registry support
src/tools/types.ts, src/tools/registry.ts, src/zero-mcp/tools.ts, tests/zero-mcp-client.test.ts
Tools now carry zeroMcp identity metadata, registry supports tool unregistration, and duplicate tool name validation is added to prevent overwrites across server boundaries.
Agent permission checking and schema mutation fix
src/agent/loop.ts
Extends AgentOptions with autonomy and mcpPermissionStore; tool execution now checks persistent approval via store before falling back to interactive approval; schema mutation eliminated via destructuring; internal helpers added for MCP-aware grant key computation and persistent approval lookup.
Agent loop tests
tests/agent-loop.test.ts
Tests verify schema immutability when preparing provider tool definitions and that persistently-approved tools execute without invoking onToolApproval.
CLI permission management commands
src/index.ts
Adds zero mcp permissions command group with list, revoke (tool or server scope), and clear (requires --confirm) subcommands, supporting JSON output and error handling.
Permission store and CLI tests
tests/zero-mcp-permissions.test.ts
Comprehensive test suite validating permission store persistence, autonomy ceiling enforcement, cascading server revocation, deterministic listing, invalid input rejection, and full CLI workflows.
Runtime context autonomy propagation
src/zero-runtime/types.ts, src/zero-runtime/context.ts
ZeroRunContext now includes resolved autonomy value in agentOptions for use in permission decision logic throughout execution.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Gitlawb/zero#37: The main PR's new MCP persistent-approval permission logic in src/agent/loop.ts is directly tied to the MCP client backend's tool.zeroMcp metadata (added in src/zero-mcp/tools.ts) by reusing it to compute the tool grant key and bypass onToolApproval when persistently approved.

Suggested reviewers

  • Vasanthdev2004
  • anandh8x

Poem

🐰 A rabbit's permission dance,
With stores that hold each grant,
No more asks for tools we trust—
Persistent approvals, a must!
Autonomy levels keep it fair,
Safe MCP tools everywhere. 🔐

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add MCP permission grants' directly describes the main change: adding a new permission grant system for MCP. It is clear, specific, and aligns with the primary objective of persisting and managing MCP permission grants.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/m4-mcp-permissions

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

github-actions Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Zero automated PR review

Verdict: No blockers found

Blockers

  • None found.

Validation

  • [pass] Diff hygiene: git diff --check
  • [pass] Typecheck: bun run typecheck
  • [pass] Tests: bun run test
  • [pass] Build: bun run build
  • [pass] Smoke build: bun run smoke:build

Scope

Head: 3ef496d00d17
Changed files (12): src/agent/loop.ts, src/index.ts, src/tools/registry.ts, src/tools/types.ts, src/zero-mcp/index.ts, src/zero-mcp/permissions.ts, src/zero-mcp/tools.ts, src/zero-runtime/context.ts, src/zero-runtime/types.ts, tests/agent-loop.test.ts, tests/zero-mcp-client.test.ts, tests/zero-mcp-permissions.test.ts

This deterministic review checks validation status and basic diff hygiene. A human reviewer still owns product judgment and design quality.

@anandh8x anandh8x left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review: MCP permission grants

No blockers. Well-designed persistent permission store with identity enforcement and autonomy ceilings.

What's good

  • Dual grant model — Server-level grants (blanket approval for all tools on a server) and tool-level grants (specific tool). Both identity-bound.
  • Identity enforcementisGrantAllowed checks serverIdentity. If server transport changes (new command/URL), identity changes and old grants don't apply. No stale permission leaks.
  • Autonomy ceilinglow < medium < high hierarchy via AUTONOMY_ORDER. A medium grant allows low and medium requests, denies high. Clean ordinal comparison.
  • Atomic writes — Temp file + rename pattern with PID/timestamp/random suffix. Write lock via promise chain serializes concurrent operations.
  • JSON schema mutation fixdelete jsonSchema.$schema → destructuring without $schema. Custom MCP tool schemas are no longer mutated. Tested.
  • Registry registration atomicity — Two-pass: first collects names and checks duplicates, second registers. No partial registration state on duplicate errors.
  • unregister on ToolRegistry — Tests clean up after themselves. Prevents global registry pollution.
  • Session vs persistent grantscreateToolGrantKey creates mcp:{server}:{identity}:{tool} keys for MCP tools, orthogonal to session-level {permission}:{sideEffect} keys. Checked in order: persistent first, then session, then prompt.
  • CLI commandslist, revoke <server> [tool], clear --confirm with --json output. clear requires explicit --confirm to prevent accidental nuke.
  • validateToolName — Basic non-empty check. Acceptable since tool names come from MCP sanitization.
  • Test coverage — 361 new lines: grant/check/revoke with identity mismatch and autonomy ceiling enforcement, server grant covers unnamed tools, server revocation cascades, list ordering, clear with/without confirm, CLI integration, agent loop integration with persisted grants bypassing prompts.

Observations (non-blocking)

  • readState parse errors — Re-throws with file path context but doesn't use { cause: err }. Original SyntaxError line/col info is lost.
  • validateToolName — No character validation (contrast with validateZeroMcpServerName regex). Acceptable since tool names are already sanitized by createZeroMcpToolName.
  • clear --confirm truthy checkif (!options.confirm). Commander boolean flags are true or undefined, so this is correct.

@Vasanthdev2004

Copy link
Copy Markdown
Collaborator

Blockers
None found.

Non-Blocking

  • Persistent grants are backend/CLI-management only in this PR: list/revoke/clear are wired, while creating persistent grants still depends on code paths/future UI, so the feature is safe but not fully user-facing yet.

Looks Good

  • Clean MCP permission model: grants are bound to server identity, per-tool grants and server-wide grants are separated, autonomy ceilings fail closed, and server revocation cascades tool grants.
  • Agent execution keeps MCP prompts gated unless a matching persistent grant exists, still routes all prompt/deny tools through ToolRegistry.run, and serializes approval prompts so multi-tool turns cannot overwrite the TUI resolver.
  • MCP registry registration now refuses duplicate generated tool names before mutating the registry, and provider tool schema preparation avoids mutating custom MCP schemas.
  • PR branch validation passed: typecheck, full tests 253 pass / 0 fail, build, smoke build, MCP permissions CLI help/list smoke, and git diff --check HEAD.
  • Latest-main test merge also passed: clean merge onto origin/main, typecheck, full tests 253 pass / 0 fail, build, and smoke build.

Verdict: Approve — permission persistence foundation is identity-safe, test-backed, and still passes on current main.

@Vasanthdev2004 Vasanthdev2004 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blockers
None found.

Non-Blocking

  • Persistent grants are backend/CLI-management only in this PR: list/revoke/clear are wired, while creating persistent grants still depends on code paths/future UI, so the feature is safe but not fully user-facing yet.

Looks Good

  • Clean MCP permission model: grants are bound to server identity, per-tool grants and server-wide grants are separated, autonomy ceilings fail closed, and server revocation cascades tool grants.
  • Agent execution keeps MCP prompts gated unless a matching persistent grant exists, still routes all prompt/deny tools through ToolRegistry.run, and serializes approval prompts so multi-tool turns cannot overwrite the TUI resolver.
  • MCP registry registration now refuses duplicate generated tool names before mutating the registry, and provider tool schema preparation avoids mutating custom MCP schemas.
  • PR branch validation passed: typecheck, full tests 253 pass / 0 fail, build, smoke build, MCP permissions CLI help/list smoke, and git diff --check HEAD.
  • Latest-main test merge also passed: clean merge onto origin/main, typecheck, full tests 253 pass / 0 fail, build, and smoke build.

Verdict: Approve — permission persistence foundation is identity-safe, test-backed, and still passes on current main.

@gnanam1990
gnanam1990 merged commit 6af3c8c into main Jun 3, 2026
6 checks passed
This was referenced Jun 4, 2026
@Vasanthdev2004
Vasanthdev2004 deleted the feat/m4-mcp-permissions branch June 28, 2026 08:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants