Skip to content

fix(mcp): show all editors and treat selection as desired state#1144

Open
runeb wants to merge 1 commit into
mainfrom
aigro-4989
Open

fix(mcp): show all editors and treat selection as desired state#1144
runeb wants to merge 1 commit into
mainfrom
aigro-4989

Conversation

@runeb
Copy link
Copy Markdown
Member

@runeb runeb commented May 29, 2026

Now sanity mcp configure (and the sanity init step) lists every detected editor, pre-checked by its current state. The selection is the desired final state: selecting an editor writes/updates its config, deselecting a configured one removes its Sanity entry.

Tested: targeted unit tests for prompt labels, setup orchestration (add/remove/no-op + per-editor error handling), and the new removeMCPConfig.

image

Closes AIGRO-4989


Note

Medium Risk
The CLI reads and rewrites local editor MCP config files (including bearer tokens) and can delete Sanity entries; behavior is well covered by tests but mis-edits could affect developer tooling setup.

Overview
sanity mcp configure (and the init MCP step) now treats the checkbox list as the desired end state: every detected editor is shown, pre-checked only if it is already configured, and the prompt always runs when editors exist (including when everything already looks valid).

Selecting an editor writes or updates its Sanity MCP entry; deselecting one that was configured removes only the Sanity server from that editor’s JSONC/TOML config via new removeMCPConfig, leaving other MCP servers and JSONC comments intact. writeMCPConfig skips disk writes when the existing Sanity block already matches (canonical compare) and returns whether a write happened, so setupMCP can distinguish newly configured vs already configured editors.

Orchestration now applies adds and removals per editor with continued processing on partial failures, surfaces removedEditors in CLI output and telemetry, and adjusts labels (e.g. OAuth-only editors as “(configured)” rather than “missing credentials”).

Reviewed by Cursor Bugbot for commit ce008ce. Bugbot is set up for automated code reviews on this repo. Configure here.

@claude
Copy link
Copy Markdown

claude Bot commented May 29, 2026

Claude finished @runeb's task in 3m 23s —— View job


Review

A few small things to consider; nothing blocking.

Test coverage gaps

  • packages/@sanity/cli/src/commands/mcp/__tests__/configure.test.ts exercises selection but never the new deselection → file rewrite flow end-to-end. The orchestration in setupMCP.test.ts mocks removeMCPConfig, and removeMCPConfig.test.ts covers file manipulation in isolation — so the prompt → write-without-Sanity-entry chain isn't hit by any single test. One integration test where mockCheckbox.mockResolvedValue([]) against a configured editor and mockWriteFile is asserted to receive content without "Sanity" would close that gap. (Fix this →)

Test fixtures

  • setupMCP.test.ts repeatedly passes authStatus: 'unknown' (e.g. lines 53–54, 69, 84). AuthStatus is 'unauthorized' | 'valid' — the field should be omitted for unconfigured editors to match what detectAvailableEditors actually returns. Doesn't fail today only because mocks are untyped.
  • init.create-new-project.test.ts lines 349–355 / 401–407 mock setupMCP with alreadyConfiguredEditors: [...] AND skipped: true. With the new orchestration these can't coexist: when an editor is already configured and the user keeps it selected, setupMCP returns skipped: false and pushes into alreadyConfiguredEditors (see setupMCP.ts:130–141). Fixtures should update to skipped: false so they reflect reality.

Behavior

  • removeMCPConfig.ts TOML branch (lines 24–31): when Sanity was the only server in the map, you write back config[configKey] = {}. No test covers this — worth adding to confirm smol-toml emits something sensible (or delete the key entirely if it's the last one).

Changeset — looks fine. Patch bump matches a UX-only fix; summary is one user-facing sentence in developer voice. Could split the semicolon clause for readability but not required.


  • Read changed files
  • Review test coverage
  • Validate changeset content
  • Post review

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 29, 2026

📦 Bundle Stats — @sanity/cli

Compared against main (7d2118d4)

@sanity/cli

Metric Value vs main (7d2118d)
Internal (raw) 2.1 KB -
Internal (gzip) 799 B -
Bundled (raw) 10.97 MB -
Bundled (gzip) 2.06 MB -
Import time 841ms -7ms, -0.9%

bin:sanity

Metric Value vs main (7d2118d)
Internal (raw) 1023 B -
Internal (gzip) 486 B -
Bundled (raw) 9.87 MB -
Bundled (gzip) 1.77 MB -
Import time 1.98s +2ms, +0.1%

🗺️ View treemap · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

📦 Bundle Stats — @sanity/cli-core

Compared against main (7d2118d4)

Metric Value vs main (7d2118d)
Internal (raw) 96.3 KB -
Internal (gzip) 22.7 KB -
Bundled (raw) 21.64 MB -
Bundled (gzip) 3.43 MB -
Import time 808ms +1ms, +0.2%

🗺️ View treemap · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

📦 Bundle Stats — create-sanity

Compared against main (7d2118d4)

Metric Value vs main (7d2118d)
Internal (raw) 908 B -
Internal (gzip) 483 B -
Bundled (raw) 931 B -
Bundled (gzip) 491 B -
Import time ❌ ChildProcess denied: node -
Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

@runeb runeb marked this pull request as ready for review May 29, 2026 15:41
@runeb runeb requested a review from a team as a code owner May 29, 2026 15:41
@github-actions
Copy link
Copy Markdown
Contributor

Coverage Delta

File Statements
packages/@sanity/cli/src/actions/init/initAction.ts 97.1% (±0%)
packages/@sanity/cli/src/actions/mcp/promptForMCPSetup.ts 92.8% (- 7.2%)
packages/@sanity/cli/src/actions/mcp/removeMCPConfig.ts 92.8% (new)
packages/@sanity/cli/src/actions/mcp/setupMCP.ts 100.0% (±0%)
packages/@sanity/cli/src/actions/mcp/writeMCPConfig.ts 97.0% (- 3.0%)
packages/@sanity/cli/src/commands/mcp/configure.ts 90.0% (±0%)
packages/@sanity/cli/src/telemetry/init.telemetry.ts 100.0% (±0%)
packages/@sanity/cli/src/telemetry/mcp.telemetry.ts 100.0% (±0%)

Comparing 8 changed files against main @ 7d2118d4509f4d0a7406b1e262d17f4b531d1d07

Overall Coverage

Metric Coverage
Statements 84.3% (+ 0.0%)
Branches 74.5% (+ 0.2%)
Functions 84.2% (+ 0.0%)
Lines 84.8% (+ 0.0%)

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ce008ce. Configure here.

const validEditor = editors.find((e) => e.authStatus === 'valid' && e.existingToken)
if (validEditor?.existingToken) {
mcpDebug('Reusing valid token from %s', validEditor.name)
token = validEditor.existingToken
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Token creation failure silently skips pending editor removals

Medium Severity

When createMCPToken() fails, the early return at line 117 skips processing editorsToRemove, reporting removedEditors: []. Removal is a purely local file operation that doesn't need a token, so deselected editors could still have their Sanity entries removed. This silently drops the user's explicit intent to remove a configuration. The scenario is reachable when the only configured editor is oauthOnly (e.g. Cursor) — it has no existingToken, so no reusable token is found, and token creation is attempted for a newly-selected non-oauthOnly editor.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ce008ce. Configure here.

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.

1 participant