feat(mcp): integrate recommended MCPs, spawn-sub-agent composer, files-touched chips#2
Merged
Merged
Conversation
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>
18 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.jsonadditively (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 statusPOST /api/mcp-bootstrap/recommended/:name/toggle— enable/disable, atomic writePOST /api/mcp-bootstrap/spawn-sub-agent— SSE stream of aclaude -p ...subprocess; kills child on client abortGET /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/projectssrc/components/chat/view/subcomponents/SpawnSubAgentButton.tsx— composer icon button + mobile-first modal with agent-type chips, prompt textarea, live output pane, copy-to-input hooksrc/components/settings/view/tabs/RecommendedMCPsTab.tsx— toggleable tile list using Midnightds-tile/ds-chipclasses; 44×52 switch meets touch-target minimumsrc/components/sidebar/view/subcomponents/SessionFilesTouchedChips.tsx— IntersectionObserver-deferred fetch, 60s in-memory cache, lavender chips beneath each session rowTouched files (wrapper-style)
server/index.js— one import + oneapp.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>clustersrc/components/sidebar/view/subcomponents/SidebarProjectSessions.tsx— wrap each existing<SidebarSessionItem>with the chip row (SidebarProjectItem is untouched per the golden rule)types.ts,SettingsSidebar.tsx,SettingsMainTabs.tsx,Settings.tsxall get the newmcptab;SettingsSidebar/SettingsMainTabsuset(key, { defaultValue })so missing locale keys do not showmainTabs.mcprawsrc/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 dispatchVerification
npm run build— passes (Vite + tsc-alias, no TS errors)npm run typecheck— passesnpm run lint— 0 errors (warnings pre-existing in the codebase; no new rule violations)gh workflow run sync-upstream.yml— run 24818956668 completes green~/.claude.jsonbootstrap verified by module-level side-effect + idempotency test (additive, respects dismissals)Test plan
~/.claude.json; restart and confirm bootstrap doesn't re-add itclaudesubprocess is killedcurl /api/mcp-bootstrap/session-files-touched/..%2F..%2Fetc/passwd— expect 400🤖 Generated with Claude Code