Skip to content

fix(devframe): enforce MCP state exposure policy - #336

Merged
antfu merged 2 commits into
mainfrom
fix/mcp-state-policy
Sep 3, 2026
Merged

fix(devframe): enforce MCP state exposure policy#336
antfu merged 2 commits into
mainfrom
fix/mcp-state-policy

Conversation

@antfubot

@antfubot antfubot commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Why

MCP resource listing honored exposeSharedState, but direct devframe://state/<key> reads did not. A caller that knew a filtered key could bypass the exposure policy and read shared state that discovery had hidden. This closes that gap so one predicate governs listing, the built-in read tool, and direct resource reads.

Implements plans/003-enforce-mcp-state-policy.md.

What

  • registerResourceHandlers now resolves the shared-state predicate once via sharedStateFilter and applies it to both resources/list and resources/read. A direct read of a key that the policy denies (disabled exposure or a filter that excludes it) is rejected with the existing DF0048 diagnostic — before any storage access — so a denied key is indistinguishable from a missing one.
  • Generalized the bootPair test helper to accept an exposeSharedState policy, and added regression tests proving direct-URI reads can no longer bypass the policy: exposure false omits state resources and rejects direct reads, a predicate lists/reads allowed keys and rejects a known denied key, and the state-read tool and resource path agree for the same policy.

Verification

  • pnpm exec vitest run packages/devframe/src/adapters/mcp/__tests__/mcp-server.test.ts — 16 passed
  • pnpm --filter devframe typecheck — pass
  • pnpm lint — pass
  • Full packages/devframe suite — 590 passed

Note: repo-wide pnpm build/pnpm knip fail on pre-existing, unrelated environment issues (a stray write-only artifact in plugins/git/assets-pkg/dist, and starter/ needing built dist), untouched by this change.

This PR was created with the help of an agent.

@coldtea-pr-lens

coldtea-pr-lens Bot commented Sep 3, 2026

Copy link
Copy Markdown

◈ PR Lens

🟢 +0 new · 🟠 ~1 changed · 🔴 -0 removed · 0 flows · 2 files · commit d08b3fa


Architecture

Architecture diagram for devframes/devframe at d08b3fa

1 component touched across 1 lane.

Open full size


Data flow

No data-flow sequence changed in this PR.


Drill down
Devframe Core Engine — 1 component
🟡 CHANGED MCP Server Adapter

Registers MCP resource and tool handlers, enforcing shared-state exposure policies on direct resource reads.


View

  • Architecture lens
  • Data flow lens
  • Expand every detail
  • Show unchanged neighbours

Tip

The diagrams follow your GitHub theme, so dark mode gets the dark render and light mode the light one, and the moving dots show this pull request's data in motion.

🪧 More tips
  • Run PR Lens on your own machine: npx skills add coldteadotai/pr-lens installs the agent skill. Then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."
  • Draw a diff before it is even a pull request: npx @coldtea/pr-lens-cli analyze --base origin/main reads the diff with your own model key, and npx @coldtea/pr-lens-cli render .pr-lens/graph.json draws the same lenses on your machine.
  • The boxes under View are live. Tick Architecture lens or Data flow lens to choose which diagrams appear, or Expand every detail to open every drill-down at once. The comment redraws in place a few seconds later.
  • Show unchanged neighbours lists the components this change did not touch alongside the ones it did, so the drill-down shows what the changed code sits next to.
  • GitHub will not let you zoom an image in a comment. The link under each diagram opens it full size on a page of its own, where you can.
  • The CLI's render picks up .github/pr-lens.yml automatically and applies your corrections (renames, exclusions, lane pins) at draw time.
  • Would you rather run it from CI on a key of your own? Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and a model key in your repository secrets, say GEMINI_API_KEY. The Action asks Gemini by default, or OpenAI and any endpoint speaking /chat/completions through its provider input.
  • PR Lens is free for open source. A star on the repository is what keeps it going.
  • Push a new commit and the whole comment re-renders for the new head. An older run never overwrites a newer one, so a slow render cannot put a stale diagram back.

◈ Rendered by PR Lens · crafted with ❤️ by the Coldtea team · Something drawn wrong?

@vercel

vercel Bot commented Sep 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
devframe Skipped Skipped Sep 3, 2026 2:11am UTC

@antfu
antfu merged commit 51827b7 into main Sep 3, 2026
14 checks passed
@antfu
antfu deleted the fix/mcp-state-policy branch September 3, 2026 02:17
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.

2 participants