Skip to content

Feat/mcp server tool toggles#330

Open
plusplusoneplusplus wants to merge 6 commits into
mainfrom
feat/mcp-server-tool-toggles
Open

Feat/mcp server tool toggles#330
plusplusoneplusplus wants to merge 6 commits into
mainfrom
feat/mcp-server-tool-toggles

Conversation

@plusplusoneplusplus

Copy link
Copy Markdown
Owner

No description provided.

plusplusoneplusplus and others added 6 commits June 14, 2026 18:02
Introduce nativeSessionChatAdapter mapping NativeCliSessionDetail into the
minimal task/metadataProcess shapes that ChatHeader and
ConversationMetadataPopover consume, so the CLI Sessions detail view can be
rebuilt to match the chat activity UI (AC-01/03/04 foundation).

- toNativeSessionHeaderTask: provider badge task (no CoC run status)
- toNativeSessionMetadataProcess: provider + derived model for the popover
- buildNativeSessionMetadataExtraRows: repo/branch/cwd/host/created/updated/summary
- deriveNativeSessionModel + formatNativeSessionTimestamp helpers

Pure, fully unit-tested; no UI wiring yet, so existing panel behavior and
tests are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… ChatHeader

Adds an optional `extraRows` prop to `ConversationMetadataPopover` (appended
after the standard compact rows) and a matching `metadataExtraRows`
pass-through on `ChatHeader` (forwarded to both the inline popover and the
overflow-menu metadata render).

This is the AC-04 plumbing for the native CLI Sessions chat-parity rewrite:
read-only surfaces can surface fields with no built-in slot — repository,
branch, cwd, host, created/updated, stored summary — without forking the
popover. CoC chat behavior is unchanged when the prop is omitted.

Tests: extra-row rendering, single-grid-cell layout, extra-rows-only render
when the process yields no rows, the no-rows/no-extra-rows null case, and the
ChatHeader inline + overflow forwarding (plus the omitted-default no-op).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…eader + ConversationArea + disabled composer)

Rewrite SessionDetailView to compose chat's own ChatHeader +
ConversationArea (variant="inline") + ConversationMiniMap + a blocked
FollowUpInputArea over read-only native-session adapters, mirroring the
WorkItemExecutionSession reuse pattern instead of the SSE/taskId-coupled
ChatDetail. Replaces the custom card layout so the transcript reads
identically to a CoC chat activity.

- AC-01/02: ConversationArea+MiniMap fed by toClientConversationTurns,
  provider threaded for avatar/badge color, scroll-to-bottom wired.
- AC-03: ChatHeader via toNativeSessionHeaderTask/nativeSessionTitle;
  read-only + external badges injected through the viewToggle slot;
  Resume/Fork/Scratchpad/Loops/live-tokens/rename omitted.
- AC-04: repo/branch/cwd/host/created/updated/summary surfaced through
  the header metadata popover via metadataExtraRows; standalone card gone.
- AC-05: FollowUpInputArea rendered inputDisabled with a read-only note;
  send/stream/resume handlers are inert stubs.
- AC-06: select-to-copy + attach-context kept; pin/archive/delete omitted
  (no CoC processId to mutate).

Tests: panel suite stubs the four chat sub-components and asserts the
prop wiring (title/provider/turns, summary in extraRows, disabled
composer, attach-context on + pin/archive/delete off); the real-bubble
suite keeps ConversationArea+bubble real and now also renders the real
disabled composer, proving AC-05 mounts without crashing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add listMcpTools to mcp-connection-tester (full initialize +
notifications/initialized + tools/list handshake over stdio and
Streamable HTTP), and a mcp-tools-discovery module that resolves a
workspace's enabled servers from the effective config and probes them
concurrently with per-server timeouts and error isolation.

Expose GET /api/workspaces/:id/mcp-config/tools returning
{ servers: { [name]: { status, tools, error? } } }.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Live-discover each enabled MCP server's tools and let users toggle them
individually, persisting through the existing per-repo `enabledMcpTools`
allow-list.

AC-02 (Tools tab UI):
- Client SDK `workspaces.discoverMcpTools()` + contract types.
- McpServersPanel eagerly fetches discovery on mount; populates the
  per-row tool count (was `—`) with `n` / `enabled/total` / `…` / `!`.
- Real InspectorToolsPane: name + description + collapsible input schema
  + per-tool toggle, a filter box, Enable-all/Disable-all, and
  loading/empty/error/disabled states.

AC-03 (persist via enabledMcpTools allow-list):
- Pure allow-list write logic in `mcpToolsAllowList.ts`: no entry = all on;
  first toggle-off materializes the complement of discovered tools;
  new/undiscovered tools default OFF once an entry exists.
- Toggles persist via the existing `PUT /mcp-config` (sends the current
  `enabledMcpServers` alongside so the server list is not clobbered).
- `GET /mcp-config` now returns `enabledMcpTools` so toggles survive reload.

Tests: allow-list unit tests, Tools-tab component tests (discovery, counts,
search, schema expand, toggle/bulk persistence), and a server-side
PUT→GET round-trip. tsc clean; full coc suite (5020 tests) green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… path (AC-04)

Resolve `mcpServers` for the dashboard chat (`chat-base-executor.execute`)
and session follow-up (`follow-up-executor.executeFollowUp`) paths, applying
the per-repo server-level (`enabledMcpServers`) and per-tool
(`enabledMcpTools`) allow-lists. The resolved map is sent with
`loadDefaultMcpConfig: false` so disabled tools/servers never reach the agent.

Chosen approach: mcpServers resolution (the recommended route) over
`excludedTools`. The allow-list stores ENABLED tool names, which maps directly
onto `MCPServerConfig.tools` (a per-server whitelist) — no runtime tool
discovery is required. The excludedTools route would need the disabled
complement, i.e. the full discovered tool set at runtime, which the executor
does not have.

Accepted side effect: chat now also honors the server-level
`enabledMcpServers` allow-list. In the common no-toggle case the resolved map
is identical to the SDK's default global+workspace load (request-runner uses
the same `loadEffectiveMcpConfig`), so behavior is preserved; it only narrows
the set when a server or tool is actually disabled.

New shared helper `mcp-tool-enforcement.ts`:
- `applyMcpAllowList` (pure) — server-level + tool-level allow-list semantics
- `resolveChatMcpServers` — effective-config resolution + allow-list
- `resolveChatMcpServersForWorkspace` — workspace + per-repo prefs lookup;
  never throws (falls back to default load so a chat turn is never blocked)

Workflow (`workflows-write-handler.ts`) and CLI (`ai-invoker.ts`) paths are
untouched. Tests: 16 unit tests for the helper plus execute()/follow-up
integration tests asserting the disabled tool is absent from send options and
`loadDefaultMcpConfig: false`. Full coc suite green (29470 passed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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