Skip to content

feat(mcp): integrate recommended MCPs, spawn-sub-agent composer, files-touched chips#2

Merged
github-actions[bot] merged 5 commits into
mainfrom
feat/mcp-integrations
Apr 23, 2026
Merged

feat(mcp): integrate recommended MCPs, spawn-sub-agent composer, files-touched chips#2
github-actions[bot] merged 5 commits into
mainfrom
feat/mcp-integrations

Conversation

@4Gaige
Copy link
Copy Markdown
Owner

@4Gaige 4Gaige commented Apr 23, 2026

Summary

Phase 6 delivers Dispatch's MCP integration layer. On boot we register two recommended MCP servers (unless the user dismisses them), expose Settings toggles to manage them, add a "Spawn sub-agent" button to the chat composer, and decorate sidebar session rows with a "files touched" chip row derived from session transcripts. Also hardens the upstream-sync workflow so it works on a freshly-forked repo.

Changes

New files

  • server/routes/mcp-bootstrap.js — ensureRecommendedMCPs self-executes on import, writes ~/.claude.json additively (never overwrites on parse errors), tracks user dismissals in ~/.claude/dispatch-recommended-mcps.json. HTTP endpoints:
    • GET /api/mcp-bootstrap/recommended — list with install/dismiss status
    • POST /api/mcp-bootstrap/recommended/:name/toggle — enable/disable, atomic write
    • POST /api/mcp-bootstrap/spawn-sub-agent — SSE stream of a claude -p ... subprocess; kills child on client abort
    • GET /api/mcp-bootstrap/session-files-touched/:projectName/:sessionId — derives top tool-use files from the Claude session JSONL; rejects .., slashes, null bytes and validates the resolved path stays inside ~/.claude/projects
  • src/components/chat/view/subcomponents/SpawnSubAgentButton.tsx — composer icon button + mobile-first modal with agent-type chips, prompt textarea, live output pane, copy-to-input hook
  • src/components/settings/view/tabs/RecommendedMCPsTab.tsx — toggleable tile list using Midnight ds-tile/ds-chip classes; 44×52 switch meets touch-target minimum
  • src/components/sidebar/view/subcomponents/SessionFilesTouchedChips.tsx — IntersectionObserver-deferred fetch, 60s in-memory cache, lavender chips beneath each session row

Touched files (wrapper-style)

  • server/index.js — one import + one app.use('/api/mcp-bootstrap', …) (the phase brief's "single require" pattern matched to the existing sibling-route style)
  • src/components/chat/view/subcomponents/ChatComposer.tsx — one import + <SpawnSubAgentButton /> inside the existing <PromptInputTools> cluster
  • src/components/sidebar/view/subcomponents/SidebarProjectSessions.tsx — wrap each existing <SidebarSessionItem> with the chip row (SidebarProjectItem is untouched per the golden rule)
  • Settings plumbing: types.ts, SettingsSidebar.tsx, SettingsMainTabs.tsx, Settings.tsx all get the new mcp tab; SettingsSidebar/SettingsMainTabs use t(key, { defaultValue }) so missing locale keys do not show mainTabs.mcp raw
  • src/i18n/locales/en/settings.json — adds "mcp": "MCP"
  • .github/workflows/sync-upstream.yml — adds a "create upstream-sync branch if missing" step so the workflow no longer fails on first dispatch

Verification

  • npm run build — passes (Vite + tsc-alias, no TS errors)
  • npm run typecheck — passes
  • npm run lint — 0 errors (warnings pre-existing in the codebase; no new rule violations)
  • Raw Tailwind color grep on the diff — no matches
  • gh workflow run sync-upstream.yml — run 24818956668 completes green
  • ~/.claude.json bootstrap verified by module-level side-effect + idempotency test (additive, respects dismissals)

Test plan

  • Open Settings → MCP tab; confirm both entries appear with installed/dismissed chips
  • Toggle codebase-memory-mcp off → confirm it disappears from ~/.claude.json; restart and confirm bootstrap doesn't re-add it
  • Toggle it back on → confirm it re-registers
  • Click ✨ in the composer → modal opens; submit with a short prompt → confirm output streams in
  • Close modal while running → confirm the claude subprocess is killed
  • Expand a project in the sidebar → confirm lavender "files touched" chips appear under sessions with tool-use history
  • Try curl /api/mcp-bootstrap/session-files-touched/..%2F..%2Fetc/passwd — expect 400
  • On mobile (375×812), confirm toggle switches and the Spawn modal are usable with touch targets ≥44px

🤖 Generated with Claude Code

4Gaige and others added 5 commits April 23, 2026 00:33
Registers codebase-memory-mcp and claude-code-mcp in ~/.claude.json on boot
unless the user has dismissed them. Companion state file tracks dismissals so
re-installs don't fight the toggle. Exposes HTTP endpoints for list/toggle,
sub-agent spawn (SSE), and session files-touched derivation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…files-touched chips

- SpawnSubAgentButton in chat composer opens a mobile-first modal with agent type chips
  and a prompt textarea; submit streams SSE output from /api/mcp-bootstrap/spawn-sub-agent.
- RecommendedMCPsTab in Settings lists the two Dispatch-recommended MCPs with toggles
  wired to /api/mcp-bootstrap/recommended; toggling writes ~/.claude.json and persists
  dismissals so the bootstrap does not fight the user.
- SessionFilesTouchedChips under each sidebar session lazily fetches derived "files
  touched" from session JSONL tool uses; uses IntersectionObserver to defer work until
  the row scrolls into view.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The aormsby sync action requires the target branch to already exist. Dispatch
the workflow on a fresh fork and it fails with "pathspec 'upstream-sync' did
not match any file(s)". Create the branch from main up front so the first
sync run (and any future re-creation) just works.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Reject '..', slashes, and null bytes in session-files-touched route params;
  defense-in-depth prefix-check on the resolved path so no response can read
  outside ~/.claude/projects.
- Bump recommended-MCPs toggle to 44x44 with a 52px-wide track so the mobile
  touch target meets the phase's minimum.
- If ~/.claude.json is unreadable/unparseable, ensureRecommendedMCPs and the
  toggle endpoint now abort instead of silently rewriting an empty config
  over the user's state. The toggle surfaces a 409 with the path so the user
  can fix their file manually.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…s corrupt

describeRecommendedMCPs now treats an unparseable config the same as a missing
one so the Settings page still renders (with items reported as not installed)
instead of blowing up with a 500. Matches the guard already in place on the
bootstrap and toggle paths.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@github-actions github-actions Bot merged commit 26af5f7 into main Apr 23, 2026
2 checks passed
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