[POC - Do not review / Merge] Compass mcp integration#8084
Open
mcasimir wants to merge 28 commits into
Open
Conversation
Embeds a Streamable HTTP MCP server inside Compass so tools like Claude Desktop and Cursor can run read-only MongoDB queries against Compass-managed connections. What's included: - New `@mongodb-js/compass-mcp-server` package wrapping `mongodb-mcp-server` with Bearer token auth, Origin validation (DNS-rebinding protection), and loopback-only binding (127.0.0.1:27097) - Per-MCP-session `CompassConnectionManager` that resolves connection IDs from Compass storage and runs a per-connection consent flow before connecting - `list-connections` custom tool so AI clients can discover available connections - Per-connection consent stored as `mcpAccess` on `ConnectionInfo` (persisted via existing `ConnectionStorage`) - `enableMcpServer` user preference (toggle) and `mcpServerToken` internal preference (32-byte random, OS-encrypted via safeStorage) - Main-process setup: token generation, IPC consent dialog, start/stop on preference change, graceful shutdown on exit - "AI Tools" settings tab with server status badge, URL, masked token, and Claude Desktop config snippet with one-click copy - Renderer-side `McpConsentDialog` with "Remember my choice" checkbox - Security regression test suite (401/403/loopback enforcement)
- Generate bearer token at setupMcpServer() startup rather than lazily
on first server start, so it appears in Settings → AI Tools immediately
- Register ipcMain.respondTo('mcp:get-status') handler for synchronous
status queries from the renderer
- Query status on mount in mcp-server-settings to show correct badge
when the settings panel opens after the server has already started
Move all MCP server lifecycle logic (token generation, start/stop, IPC handlers, preference listener) out of application.ts and into CompassMcpServerManager in the compass-mcp-server package. The call site in application.ts now mirrors setupCompassAuthService(): a 5-line method that calls CompassMcpServerManager.init() and registers an exit handler via onExit().
…ayout - Move MCP server settings into the Artificial Intelligence tab instead of a separate AI Tools tab; remove the mcp SettingsTabId - Read mcpServerToken via usePreferences() hook so it is visible even when the server has not yet started (was unset in the Redux settings sandbox which only loads UserConfigurablePreferences) - Show URL, token and snippet unconditionally; only the server status badge is gated on enableMcpServer being true
- Initialize status as null so no fake Stopped badge appears before
the IpcRenderer.call('mcp:get-status') round-trip completes
- Add vertical tab layout for Claude Desktop, Cursor, VS Code, Windsurf
— each tab shows the correct snippet format for that client plus
the config file path to paste it into
- VS Code uses "servers" key (not "mcpServers") per its MCP spec
- Remove enableMcpServer from usePreferences (status display no longer
gated on the preference value)
- Replace AllTools spread with an explicit allowlist of read-only MongoDB data-plane tools: list-databases, list-collections, schema, indexes, storage-size, find, count, aggregate, db-stats, explain - Remove all Atlas control-plane tools (clusters, projects, orgs, alerts, db users, etc.), Atlas Local deployment management tools, knowledge/assistant tools, and the export/logs tools - Add CompassConnectTool that accepts a connectionId argument and a description that points at list-connections, so external AI clients cannot supply a raw MongoDB connection string. The upstream connect tool is no longer registered.
Adds an Install / Update / Installed-checkmark button to each client tab in Settings → AI. Clicking it writes (or updates) the mongodb-compass entry in that client's user-level MCP config file — claude_desktop_config.json, cursor/mcp.json, Code/User/mcp.json, windsurf/mcp_config.json — using jsonc-parser to preserve any existing entries, comments, and trailing commas the user already has in those files. This mirrors the behavior of `npx mongodb-mcp-server@latest setup`, but driven from the existing Settings UI rather than a CLI wizard, since we already know the bridge command (we generate it from process.execPath) and the client (the active tab). Modules: - auto-setup.ts: install/update/uninstall/detect with jsonc-parser - client-paths.ts: single source of truth for per-client config paths and the mcpServers vs servers JSON key - new IPC handlers in CompassMcpServerManager: mcp:install-in-client, mcp:uninstall-from-client, mcp:detect-in-client - mcp-server-settings.tsx: detection-driven button with three states (Install / Update / Installed ✓), with a per-tag nonce + per-client result tag to avoid races when switching tabs quickly
…o mode
In dev mode webpack-dev-server's HMR client logs '[HMR] Waiting for
update signal from WDS...' to stdout, corrupting the MCP JSON-RPC
stream and producing "Unexpected token 'H'" errors in Claude Desktop.
Install a stdout filter as the very first statement in the entry: any
write whose first byte isn't `{` (JSON object) or `\n` (trailing
newline from a previous chunk) is redirected to stderr. The MCP bridge
only ever emits newline-delimited JSON objects on stdout, so this is
a safe filter; HMR / WDS / webpack diagnostic noise still shows up in
stderr for debugging but no longer breaks the protocol.
Large JSON-RPC responses from socket.pipe(process.stdout) — like
tools/list with all the schemas, ~13KB — arrive at the bridge as
multiple ~8KB chunks. The previous filter only looked at the leading
byte of each chunk: the first chunk passed (starts with '{'), but
continuation chunks (starting mid-string) were misclassified as noise
and redirected to stderr. The receiving MCP client got a JSON message
truncated at position 8192 and failed with "Expected ',' or '}' after
property value in JSON at position 8192".
Track whether we're at a message boundary across writes. When at a
boundary, gate the chunk on its first byte ('{' = MCP, anything else =
HMR/WDS noise to stderr). When mid-message, forward verbatim and only
flip back to boundary state when we see a trailing '\n'. This makes
the filter correct for any chunking the kernel/Node hand us.
Adds a new MCP tool that, instead of returning data, asks the running Compass GUI to open a collection in a workspace tab so the user can browse it interactively. Useful for "let me show you" responses where the AI hands off to the GUI rather than dumping documents back as text. Wiring: - New CompassOpenCollectionTool registered in COMPASS_TOOLS, accepts connectionId + database + collection. - New CompassToolContext shared by all Compass tools, with an openCollection(connectionId, namespace) callback alongside the existing getAllConnections. - Manager's openCollection implementation broadcasts mcp:open-collection to the focused window via hadron-ipc.broadcastFocused. - New McpNavigationListener renderer component (mounted inside the WorkspacesProvider scope) listens for that IPC and calls useOpenWorkspace().openCollectionWorkspace. The tool never returns any data — it's pure navigation intent. If the connection isn't active, Compass handles the connect prompt itself. Renamed ListConnectionsContext -> CompassToolContext to reflect that it's now the shared per-session context for all Compass tools.
When an AI client calls compass-open-collection, the OS-focused window is the AI client (Claude Desktop / Cursor / ...) — not Compass — so `ipcMain.broadcastFocused` silently dropped the message. Use `ipcMain.broadcast` instead so every Compass renderer receives the event regardless of focus. Also adds a one-line console.log in the renderer listener so we can verify IPC delivery in DevTools while iterating on this feature.
Two changes that together fix "tabs disappear" when the AI calls
compass-open-collection:
1. Pass { newTab: true } to openCollectionWorkspace. With the default
(newTab=false) the workspaces reducer REPLACES the currently active
tab — when the user is on, say, the Welcome screen, that tab gets
swapped out for the collection tab, which gave the impression that
"every tab disappeared". With newTab:true the collection tab is
inserted next to the active one, never destroying existing state.
2. Subscribe to the IPC channel exactly once on mount by parking
openCollectionWorkspace on a ref. The hook returns a fresh function
each render; the previous code re-attached the listener on every
render which was harmless but noisy.
Also wraps the dispatch in try/catch so any failure surfaces in
DevTools instead of silently breaking the render.
When the AI calls compass-open-collection for a connection that is saved in Compass but not currently active, openCollectionWorkspace opens a tab whose backing data service does not exist — the tab strip loses focus and nothing visibly renders, even though the new tab is in state. The renderer listener now mirrors the sidebar's behavior for a click on a saved (disconnected) connection: look up the ConnectionState, and if status !== 'connected' dispatch the standard `connect(info)` action (triggering the same auth / elicitation modals the user would see clicking the connection themselves). We await that dispatch and only then open the workspace tab so the Collection view has a working data service to render against.
The tool now hands a richer intent to Compass:
subtab Documents | Aggregations | Schema | Indexes | Validation
filter, projection, sort, limit -> pre-fills the documents query bar
pipeline -> pre-fills the aggregation builder; auto-implies the
Aggregations subtab when not set explicitly
These map to openCollectionWorkspace's `initialSubtab`,
`initialQuery`, `initialPipeline` options so the user lands directly
in the right view with the AI's draft loaded. Tool description nudges
the model to use this for HAND-OFF (iterating, exploring, optimizing)
— not for showing query results, which still go inline.
Two cross-cutting UX bits:
- Subtle attention nudge when a tab opens: app.dock.bounce on macOS,
BrowserWindow.flashFrame on Linux/Windows. Doesn't steal focus from
the AI client but makes the hand-off visible.
- newTab:false in the renderer listener, matching the sidebar's
"click a collection" semantics. Compass's canReplaceTab() protects
tabs holding unsaved work, so we de-dupe onto an existing tab when
one matches and otherwise replace the (likely-idle) active tab.
Two related discoverability changes.
1. Move MCP server settings to a dedicated 'MCP Server' tab in Settings.
The Artificial Intelligence tab had become cramped — toggle + four
client setup tabs + install buttons + config snippets stacked below
the GenAI toggles. Restore 'mcp' as a SettingsTabId, register the
tab in the settings modal next to AI, and remove the embedded
<McpServerSettings /> from gen-ai-settings.tsx. The AI tab returns
to just the GenAI controls.
2. Welcome tab announcement card.
Add a sibling card to the existing Atlas help block on the desktop
welcome tab that announces the MCP integration and deep-links into
Settings -> MCP Server in one click. Emits
globalAppRegistry.emit('open-compass-settings', 'mcp') — the same
mechanism welcome-modal-store already uses to deep-link Privacy.
The card is hidden once enableMcpServer is true so existing users
don't see a permanent nag; renders for first-time users in either
the "no connections yet" or "has saved connections" welcome states.
Three new tests cover: presence when MCP is off, hidden when on, and
the open-compass-settings emit on button click. 21/21 welcome tests
pass.
…l-access)
ConnectionInfo.mcpAccess becomes a discriminated union with three
modes (denied / ask / allowed) and a preset when allowed:
type McpAccess =
| { mode: 'denied' }
| { mode: 'ask' }
| { mode: 'allowed'; preset: McpPreset };
type McpPreset = 'metadata-only' | 'read-only' | 'full-access';
Legacy 'allowed'/'denied' string values are read transparently via
normalizeMcpAccess() — 'allowed' maps to read-only (today's behavior),
'denied' to denied, anything else (or undefined) to ask.
Per-preset tool allowlist lives in compass-mcp-server/src/presets.ts:
- metadata-only: list/schema/indexes/storage-size/db-stats/explain
- read-only: above + find / count / aggregate
- full-access: above + writes (insert/update/delete + DDL)
Enforcement
-----------
CompassConnectionManager.connect() resolves the connection's preset
(persisting the user's consent-dialog choice if 'ask') and stores it
as `activePreset`. The per-session tool context wraps it in a
checkAccess(toolName) helper that throws McpAccessDeniedError when
the tool isn't in the preset's allowlist.
Our own tools call checkAccess at the top of execute(). Upstream
mongodb-mcp-server tools are wrapped via withAccessCheck() — a small
HOC that subclasses each ToolBase to inject the gate before execute()
fires. Lives in build-tool-context.ts alongside buildToolContext().
Consent dialog
--------------
mcp-consent-dialog renders three preset radios with explanatory
descriptions. Default is read-only (matches today's allow behavior).
Full-access reveals an inline warning and requires a second confirm
checkbox before Allow is enabled. The 'remember' checkbox persists
the full McpAccess struct (mode + preset).
Connection form AI access tab is intentionally deferred to a
follow-up — the consent dialog covers the v1 surface area; the tab
requires plumbing mcpAccess through the connection-form's update
mechanism (which today only handles ConnectionOptions fields).
Tests
-----
New presets.spec.ts: preset allowlist invariants (metadata-only ⊂
read-only ⊂ full-access, always-on tools, unknown tools rejected) +
normalizeMcpAccess legacy-shape migration. 25/25 mcp-server tests
pass including all 7 existing security regressions.
…d access; welcome card stays visible
Three smaller v2 items shipped together:
1.5 Fail-safe normalizeMcpAccess
When the on-disk mcpAccess shape is {mode: 'allowed'} with an unknown
or missing preset, treat it as {mode: 'ask'} rather than silently
downgrading to read-only. Corrupted records, downgrade from a future
schema, or tampering all fail toward re-prompting the user rather
than toward an implicit allow. Legacy known strings ('allowed' /
'denied') keep their deterministic migration path.
2 Welcome card stays visible when MCP is on
The discovery card on the Welcome tab no longer disappears once
enableMcpServer becomes true. Instead, the body copy and CTA label
adapt to a 'manage MCP setup' variant pointing at Settings -> MCP
Server. This is the right entry point for users coming back to
install MCP in another AI client or refresh a snippet after switching
between dev / packaged Compass.
3 Full-access really means full
- Register the upstream write/DDL tools (InsertMany, UpdateMany,
DeleteMany, CreateIndex, DropIndex, CreateCollection,
DropCollection, RenameCollection, DropDatabase) wrapped in
withAccessCheck so they are denied by the gate for non-full-access
presets and run normally for full-access.
- Flip userConfig.readOnly: false in both transports so upstream
doesn't strip $out / $merge inside the aggregate tool.
- Add aggregateStageGate to enforce the equivalent restriction at our
own layer for read-only / metadata-only — pipelines containing
$out / $merge are rejected with McpAccessDeniedError unless the
active preset is full-access.
32/32 mcp-server tests pass (6 new aggregate-stage gate tests +
updated fail-safe tests). 21/21 welcome tests pass.
Adds an "AI access" tab inside the Connection form for editing ConnectionInfo.mcpAccess — the per-connection MCP policy that previously could only be set via the consent dialog at first use. Surface ------- - Access mode radio: Deny / Ask each session / Allow - When Allow is selected, a preset radio: Metadata only / Read-only data / Full access. Full-access requires a confirmation checkbox before propagating to form state (mirrors the consent dialog). - A tool-list preview below the preset radio renders presetTools(p), so users see exactly which MCP tools the AI will be able to use. Opt-in flag — does not affect other products -------------------------------------------- Following the showCSFLE precedent, the tab is gated on a new ConnectionFormSettings.showAiAccess flag, defaulting to false. The desktop Compass useConnectionFormPreferences sets it to true only when HADRON_DISTRIBUTION !== 'compass-web', so compass-web (and any other host that embeds connection-form without running an MCP server) sees zero UI change. ConnectionInfo.mcpAccess is still read-through/write-through unconditionally so the data is never lost even when the tab is hidden. Form plumbing ------------- - ConnectFormState gains `mcpAccess: McpAccess`, initialized via normalizeMcpAccess(initialConnectionInfo.mcpAccess). - New `UpdateMcpAccessAction` action + reducer case (an early-return branch in handleConnectionFormFieldUpdate that touches nothing else). - isDirty flips when mcpAccess changes, so Save activates. - getConnectionInfoToSave copies state.mcpAccess back into the resulting ConnectionInfo. Same precedent as `personalizationOptions` -> `favorite`. Adds @mongodb-js/compass-mcp-server as a dep of connection-form so the tab can pull presetTools / presetLabel directly from the same source of truth the runtime gate uses — guarantees the displayed tool list always matches what the AI will actually be able to call. 455/455 existing connection-form tests pass; no test changes required.
…ngs context
The previous commit added showAiAccess to ConnectionFormSettings and
opted in from useConnectionFormPreferences, but the
ConnectionFormWithSettings wrapper explicitly destructures every
known setting prop and rebuilds the context value — I forgot to
include showAiAccess in that list. Result: the prop reached
ConnectionFormModal but got dropped before the context provider, so
useConnectionFormSetting('showAiAccess') always fell back to its
default `false` and the tab never rendered.
Add showAiAccess to both the destructure and the memoized context
value (matches the pattern for all other settings).
The first version of the AI access tab used a custom containerStyles
flexbox + gap, a redundant <Subtitle> heading (the tab name already
says "AI access"), and hand-rolled description divs under each radio
with negative margins. Result: inconsistent padding compared to the
other Advanced Options tabs and uneven vertical rhythm.
Switch to the same primitives the other tabs and the create-collection
form use:
- Drop the <Subtitle> ("AI access for this connection") — tab name
alone is sufficient, matches General / Authentication / TLS pattern.
- Wrap each section in <FormFieldContainer> instead of custom flex
containers. Consistent spacing across tabs.
- Use <Radio size="small" description="...">label</Radio> — same
pattern as compass-data-modeling's export-diagram-modal. The Radio
component renders the description in the right place at the right
size; no manual divs or margin overrides.
- Tools list label uses <Label htmlFor> + a sibling div, matching how
other field groups in the form expose a textual block.
…access tab
The version we use of @leafygreen-ui/radio-group does not auto-derive
each <Radio>'s checked state from the parent <RadioGroup value="...">
prop alone — every working Radio usage elsewhere in the repo (e.g.
compass-data-modeling/export-diagram-modal.tsx) sets both `checked`
and `onClick` directly on each Radio. Without that, all three of our
mode radios rendered unselected and the preset section never appeared
because the click never propagated through RadioGroup's onChange.
Mirror that pattern: each Radio gets `checked={mode === opt.value}`
and `onClick={() => onModeChange(opt.value)}` (same for the preset
radios). RadioGroup still carries the `value` prop for accessibility.
The ConnectionSchema Zod validator in compass-main-connection-storage
still constrained mcpAccess to the legacy `'allowed' | 'denied'`
string enum. Saving a connection from the new AI access tab — which
writes `{ mode, preset }` — failed with:
Expected 'allowed' | 'denied', received object
path: connectionInfo.mcpAccess
Widen the schema to a union that accepts:
- the two legacy strings (so existing connection records still load)
- `{ mode: 'denied' }`
- `{ mode: 'ask' }`
- `{ mode: 'allowed', preset: 'metadata-only' | 'read-only' | 'full-access' }`
Both forms are normalized at read time via normalizeMcpAccess, so the
runtime gate and the AI access tab always see the discriminated union.
Rewrites the welcome card copy after pressure-testing the previous
draft. Three issues addressed:
1. The on-state title ("Connect AI tools to MongoDB Compass") was the
same as the off-state — telling a user who already enabled MCP to
"connect AI tools" reads as a bug. Now reads "MCP server is running".
2. The on-state body used "exposing your saved connections", which
overstates the model (connections in `ask`/`denied` aren't exposed)
and reads alarmist. Replaced with a neutral description of the
actual posture: server listening on localhost; per-connection
policies (deny/ask/allow with preset) gate every access.
3. The on-state body told users to manage per-connection access in
Settings → MCP Server — wrong location. Per-connection access
lives on each connection's AI access tab. Split the two surfaces
in the copy so users know where each control is.
Off-state body also dropped the "read-only" promise since v2 added
the full-access preset; replaced with "per-connection access you
control" which is accurate at any preset level.
Button label: "MANAGE MCP SETUP" -> "MANAGE INSTALLED CLIENTS"
since the deep-link target is specifically the client setup tab.
Test updated to assert the new on-state title + button label.
The client tab strip + Install button + snippet + config-path link were previously hidden when enableMcpServer was off. That was wrong: - The bridge command (process.execPath --mcp-stdio) doesn't depend on the server being running; the snippet is correct either way. - Users often want to wire up AI clients first and toggle the server on later, or vice versa. - Hiding the only UI for managing client installations behind the toggle made the Settings tab feel half-empty when MCP is off, with no actionable next step beyond flipping the toggle. Drop the enableMcpServer gate around the install section. The toggle itself stays at the top (now the toggle is the ONLY thing affected by enableMcpServer in this view; the bridge/snippet/install UI is always visible).
…guidance
Observed AI behavior: Cursor asked 'what is the longest citybike trip
in compass-data-sets', the AI called list-databases on our MCP without
first calling connect, got upstream mongodb-mcp-server's standard
not-connected message ('please use connect or update the MCP server
config to include a connection string'), and gave up — falling back
to a web search.
The upstream message is correct for the standalone mongodb-mcp-server
but wrong for ours: our connect tool takes a connectionId from
list-connections, never a connection string. The AI dutifully looked
for a connection string in the user's message, found none, and
concluded it couldn't help.
Override the session-level connectionErrorHandler in both transports
(CompassHttpRunner + CompassSocketServer) with a Compass-specific
handler that returns:
No active MongoDB connection. To work with a database in MongoDB
Compass:
1. Call `list-connections` to get the ids of the user's saved
Compass connections.
2. Call `connect` with `connectionId` set to the id of the
connection you want to use.
Do NOT ask the user for a connection string and do NOT pass a
connection string to `connect` — this server only accepts Compass
connection ids.
Also expanded the connect tool's own description to spell out the
same two-step workflow + 'never connection strings' rule. That way
the AI has the right mental model from the tool catalog alone,
before it ever hits the error path.
32/32 mcp-server tests still green.
…ific workflow
Upstream mongodb-mcp-server hardcodes the MCP `initialize` response's
`instructions` field via TransportRunnerBase.getInstructions() and
returns a generic one-liner ("This is the MongoDB MCP server."). AI
clients (Claude Desktop, Cursor) inject this string into the model's
system prompt at session start, so getting it right means the AI has
the right mental model BEFORE it tries any tool.
Override the static at module load with a Compass-specific text that
explicitly covers:
- Required workflow: list-connections, then connect(connectionId),
then read/metadata tools. No connection strings, ever.
- Per-connection access presets and what to tell the user when a tool
gets denied.
- Cost-aware exploration: prefer collection-storage-size over count
for "how big" questions; call schema/indexes before designing
aggregations; use explain to verify plans before heavy queries.
- compass-open-collection as the "show me the data" handoff to UI.
Implementation: createServer in upstream calls
TransportRunnerBase.getInstructions directly (not virtually), so
subclassing doesn't help — but the static is a plain function
property that's reassignable. Install once at compass-mcp-server
package entry (idempotent).
Pairs with the connectionErrorHandler override from the previous
commit: the AI now hears the same workflow guidance at session start
(via instructions) AND on any "not connected" tool-call failure (via
the error handler) AND in the connect tool's description (via the
catalog). Three reinforcing channels mean the AI shouldn't dead-end
on "I need a connection string and you didn't give me one".
32/32 mcp-server tests still green.
…AI integration Adds first-class description and MCP prompt name fields to saved queries and aggregation pipelines, surfaces saved queries to AI agents via dedicated MCP tools and slash-command prompts, and shows the loaded favorite's identity as an editable chip in the collection header breadcrumb row. Highlights: - query-bar: SaveDraftAsFavoriteModal (low-level Modal + plain Button) + SaveQueryMenu (save / save-as / update-in-place); loaded-favorite bridge broadcasts the loaded-favorite identity on localAppRegistry so external surfaces can subscribe without a circular dep - collection-header: editable Chip rendered next to Breadcrumbs reflects the current loaded favorite + dirty state; click name to rename in place - compass-aggregations + compass-saved-aggregations-queries: pipeline name, description and MCP prompt name fields plumbed through the saving / editing modals - my-queries-storage: shared MCP prompt name validator + schema additions on both query and pipeline storage - compass-mcp-server: list-saved-queries / save-saved-query tools, saved-query prompts (slash commands), Compass-specific initialize + not-connected instructions
Contributor
There was a problem hiding this comment.
Pull request overview
This PR introduces a proof-of-concept MCP (Model Context Protocol) integration into Compass, enabling external AI clients to connect to user-saved Compass connections, use a per-connection access policy, and expose described saved queries/aggregations as discoverable MCP prompts.
Changes:
- Adds a new
@mongodb-js/compass-mcp-serverpackage (socket server + stdio bridge + tool/preset enforcement + client auto-setup). - Extends saved query / saved pipeline storage + UI to support AI-facing descriptions and optional MCP prompt names.
- Adds per-connection MCP access policy plumbing (schema/types, connection form “AI access” tab, consent dialog, and navigation tool support).
Reviewed changes
Copilot reviewed 112 out of 115 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/my-queries-storage/src/query-storage-schema.ts | Adds persisted metadata for AI (description/authoredBy) + MCP prompt name validation on saved queries |
| packages/my-queries-storage/src/provider.ts | Re-exports MCP prompt-name helpers/types for renderer consumption |
| packages/my-queries-storage/src/pipeline-storage-schema.ts | Adds description/authoredBy/mcpPromptName to saved pipeline schema with shared validation |
| packages/my-queries-storage/src/mcp-prompt-name.ts | Introduces shared MCP prompt-name validation/suggestion helpers |
| packages/my-queries-storage/src/mcp-prompt-name.spec.ts | Adds unit tests for prompt-name validation/suggestion helpers |
| packages/my-queries-storage/src/index.ts | Exposes MCP prompt-name helpers from the package entrypoint |
| packages/connection-storage/src/compass-main-connection-storage.ts | Allows legacy + new mcpAccess shapes in persisted connections |
| packages/connection-info/src/index.ts | Exports MCP access types + normalization helper |
| packages/connection-info/src/connection-info.ts | Defines McpAccess/McpPreset and implements normalizeMcpAccess |
| packages/connection-form/src/utils/validation.ts | Adds aiAccess tab id to validation tab union |
| packages/connection-form/src/hooks/use-connect-form.ts | Adds mcpAccess state/actions and dirty tracking for the AI access tab |
| packages/connection-form/src/hooks/use-connect-form-settings.tsx | Adds showAiAccess setting with default off |
| packages/connection-form/src/components/connection-form.tsx | Plumbs mcpAccess through save payload and advanced options |
| packages/connection-form/src/components/advanced-options-tabs/advanced-options-tabs.tsx | Adds conditional “AI access” tab and shared props wiring |
| packages/connection-form/src/components/advanced-connection-options.tsx | Forwards mcpAccess into the advanced options tabs component |
| packages/connection-form/package.json | Adds dependency needed by the AI access tab for preset labeling/tool preview |
| packages/compass/src/main/main-app.ts | Extracts main bootstrap logic into a standalone module for conditional loading |
| packages/compass/src/main/index.ts | Adds dispatcher to start either GUI or MCP stdio bridge mode |
| packages/compass/src/main/application.ts | Initializes MCP server manager in the main process lifecycle |
| packages/compass/src/app/components/workspace.tsx | Mounts MCP navigation listener in the workspace tree |
| packages/compass/src/app/components/mcp-navigation-listener.tsx | Adds renderer-side IPC listener to open collections on MCP tool requests |
| packages/compass/src/app/components/mcp-consent-dialog.tsx | Adds renderer consent modal for per-connection MCP access grants |
| packages/compass/src/app/application.tsx | Mounts consent dialog at app root so it can respond to IPC events |
| packages/compass/package.json | Adds dependency on @mongodb-js/compass-mcp-server |
| packages/compass-welcome/src/components/mcp-welcome-section.tsx | Adds Welcome-tab discoverability CTA into MCP settings |
| packages/compass-welcome/src/components/desktop-welcome-tab.tsx | Renders MCP welcome card in both empty/non-empty connection states |
| packages/compass-welcome/src/components/desktop-welcome-tab.spec.tsx | Adds tests for MCP welcome section rendering and deep-link emission |
| packages/compass-settings/src/stores/settings.ts | Adds mcp settings tab id |
| packages/compass-settings/src/components/modal.tsx | Registers new “MCP Server” settings panel |
| packages/compass-settings/package.json | Adds dependency on @mongodb-js/compass-mcp-server |
| packages/compass-saved-aggregations-queries/src/stores/edit-item.ts | Extends edit flow to persist description + MCP prompt name |
| packages/compass-saved-aggregations-queries/src/components/saved-item-card.tsx | Renames “Rename” action label to “Edit” to match expanded modal |
| packages/compass-saved-aggregations-queries/src/components/edit-item-modal.tsx | Adds description + prompt name fields with validation + uniqueness check |
| packages/compass-query-bar/src/stores/query-bar-store.ts | Adds loaded-favorite pub/sub bridge + rename callback exposure |
| packages/compass-query-bar/src/stores/query-bar-store.spec.ts | Updates activation helper stubs for new cleanup API usage |
| packages/compass-query-bar/src/loaded-favorite-bridge.ts | Defines cross-package event + sticky keys contract for loaded favorites |
| packages/compass-query-bar/src/components/save-query-menu.tsx | Adds save menu supporting “Save” vs “Save as” based on loaded favorite |
| packages/compass-query-bar/src/components/save-draft-as-favorite-modal.spec.tsx | Adds coverage for modal behavior and new metadata fields |
| packages/compass-query-bar/src/components/query-history/recent-list.tsx | Removes inline “favorite recent” UI in favor of dedicated save flow |
| packages/compass-query-bar/src/components/query-history/recent-list.spec.tsx | Updates tests for recent list props after UI removal |
| packages/compass-query-bar/src/components/query-history/index.tsx | Removes now-unused “save favorite” callback wiring in query history |
| packages/compass-query-bar/src/components/query-history/index.spec.tsx | Removes obsolete test for inline favorite-from-recent flow |
| packages/compass-query-bar/src/components/query-history/favorite-list.tsx | Applies favorites while preserving favorite identity (for update-in-place) |
| packages/compass-preferences-model/src/preferences-schema.tsx | Adds enableMcpServer user pref and mcpStdio CLI flag |
| packages/compass-mcp-server/tsconfig.json | Adds TypeScript config for the new MCP server package |
| packages/compass-mcp-server/tsconfig-build.json | Adds build tsconfig for dist output |
| packages/compass-mcp-server/src/test/presets.spec.ts | Adds tests for preset allowlists, normalization, and aggregate gating |
| packages/compass-mcp-server/src/test/instructions.spec.ts | Adds tests for MCP instruction monkey-patch behavior/content |
| packages/compass-mcp-server/src/test/connection-error-handler.spec.ts | Adds tests ensuring Compass-specific connection error guidance |
| packages/compass-mcp-server/src/test/compass-socket-server.spec.ts | Adds integration smoke test for socket server + initialize handshake |
| packages/compass-mcp-server/src/test/auto-setup.spec.ts | Adds tests for writing/patching AI client config files (JSONC-safe) |
| packages/compass-mcp-server/src/stdio-bridge.ts | Implements stdio-to-socket bridge with fallback MCP server when GUI absent |
| packages/compass-mcp-server/src/socket-path.ts | Defines cross-platform socket/named-pipe path resolution |
| packages/compass-mcp-server/src/presets.ts | Defines MCP access presets and per-preset tool allowlists |
| packages/compass-mcp-server/src/mcp-saved-query-storage.ts | Defines catalog interface/types for described saved queries/aggregations |
| packages/compass-mcp-server/src/list-saved-queries-tool.ts | Adds MCP tool to list described saved queries/aggregations |
| packages/compass-mcp-server/src/list-connections-tool.ts | Adds MCP tool to list Compass saved connections |
| packages/compass-mcp-server/src/ipc-channels.ts | Centralizes renderer/main IPC channel names for MCP flows |
| packages/compass-mcp-server/src/instructions.ts | Adds Compass-specific MCP instructions string + upstream patch install |
| packages/compass-mcp-server/src/index.ts | Exposes the public surface for consumers (Compass + connection-form) |
| packages/compass-mcp-server/src/connection-error-handler.ts | Replaces upstream guidance to forbid connection strings and require ids |
| packages/compass-mcp-server/src/compass-tools.ts | Registers Compass MCP tool set and wraps upstream tools with access checks |
| packages/compass-mcp-server/src/compass-tool-context.ts | Defines shared tool context + access-denied error |
| packages/compass-mcp-server/src/compass-socket-server.ts | Implements per-session MCP servers over local sockets + prompt registry |
| packages/compass-mcp-server/src/compass-open-collection-tool.ts | Adds MCP tool to navigate the Compass UI without returning data |
| packages/compass-mcp-server/src/compass-connection-manager.ts | Implements connection-id-based connect + consent + preset tracking |
| packages/compass-mcp-server/src/compass-connect-tool.ts | Replaces upstream connect tool to accept Compass connection ids |
| packages/compass-mcp-server/src/client-paths.ts | Defines per-client config path resolution for auto-setup |
| packages/compass-mcp-server/src/build-tool-context.ts | Builds tool context and wraps tools with preset enforcement and stage gate |
| packages/compass-mcp-server/src/auto-setup.ts | Installs/uninstalls/detects Compass MCP entry in AI client config (JSONC) |
| packages/compass-mcp-server/scripts/dev-stdio-bridge.js | Dev-only wrapper to filter HMR stdout noise from the MCP wire |
| packages/compass-mcp-server/package.json | Declares new internal package and its deps/scripts |
| packages/compass-mcp-server/.mocharc.js | Adds mocha config hook for the new package |
| packages/compass-mcp-server/.eslintrc.js | Adds ESLint config for the new package |
| packages/compass-mcp-server/.eslintignore | Ignores build/artifacts for linting |
| packages/compass-mcp-server/.depcheckrc | Configures depcheck ignore patterns |
| packages/compass-connections/src/hooks/use-connection-form-preferences.tsx | Enables AI access tab only for desktop distribution builds |
| packages/compass-components/src/index.ts | Re-exports ModalFooter from LeafyGreen surface |
| packages/compass-collection/src/components/collection-header/use-loaded-favorite.ts | Adds hook subscribing to query-bar loaded-favorite bridge |
| packages/compass-collection/src/components/collection-header/use-loaded-favorite.spec.tsx | Tests loaded-favorite hook sticky + event update behavior |
| packages/compass-collection/src/components/collection-header/loaded-favorite-breadcrumb-chip.tsx | Adds breadcrumb-adjacent chip with inline rename + dirty indicator |
| packages/compass-collection/src/components/collection-header/loaded-favorite-breadcrumb-chip.spec.tsx | Tests chip rendering and rename UX behaviors |
| packages/compass-collection/src/components/collection-header/collection-header.tsx | Renders loaded-favorite chip next to breadcrumbs |
| packages/compass-collection/src/components/collection-header/collection-header.spec.tsx | Adds integration-level assertions that bridge emission reaches header UI |
| packages/compass-aggregations/src/modules/saving-pipeline.ts | Extends save-pipeline modal state/actions to include description + prompt name |
| packages/compass-aggregations/src/modules/saving-pipeline.spec.ts | Updates tests for new modal fields being forwarded/trimmed |
| packages/compass-aggregations/src/modules/saved-pipeline.ts | Persists description + prompt name on saved pipelines |
| packages/compass-aggregations/src/modules/mcp-prompt-name.ts | Adds top-level reducer slice for pipeline MCP prompt name |
| packages/compass-aggregations/src/modules/index.ts | Wires new description + mcpPromptName reducers into root reducer |
| packages/compass-aggregations/src/modules/description.ts | Adds top-level reducer slice for pipeline description |
| packages/compass-aggregations/src/components/saving-pipeline-modal/saving-pipeline-modal.tsx | Adds description + prompt name inputs with validation to save modal |
| packages/compass-aggregations/src/components/pipeline/pipeline.tsx | Plumbs new modal props/actions through pipeline component |
| packages/compass-aggregations/src/components/pipeline-toolbar/pipeline-settings/pipeline-name.tsx | Replaces toolbar name display with a favorite-style identity chip |
| packages/compass-aggregations/src/components/pipeline-toolbar/pipeline-settings/pipeline-name.spec.tsx | Updates tests to match new chip-based UI and dirty indicator |
| packages/compass-aggregations/src/components/pipeline-toolbar/pipeline-settings/pipeline-menus.tsx | Ensures “Save As” preserves description/prompt name when cloning |
| packages/compass-aggregations/src/components/aggregations/aggregations.tsx | Wires new saving-pipeline actions into connected aggregations component |
| .gitignore | Ignores .tmp directory |
Comment on lines
+185
to
+188
| } catch (err: any) { | ||
| // eslint-disable-next-line no-console | ||
| console.error('Failed to perform operation', err?.messsage ?? err); | ||
| exitCode = 1; |
Comment on lines
+73
to
+77
| function runFallbackServer(): void { | ||
| const MESSAGE = | ||
| 'MongoDB Compass is not running, so no connections are available. Start ' + | ||
| 'Compass and enable the MCP server in Settings → Artificial Intelligence, ' + | ||
| 'then ask me again.'; |
Comment on lines
+93
to
+98
| // @ts-expect-error typescript is correctly highlighting that this esm import | ||
| // is missing a path, but we're passing this through bundler, so that's kinda | ||
| // expected. In theory we should switch tsconfing to moduleResolution: bundler | ||
| // to fix this, on practice switching to anything that prefers esm over cjs | ||
| // causes a lot of code to stop compiling because types are not being resolved | ||
| // correctly, so we're just ignoring this error for now |
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.
Poc: install the mcp server from Compass, share connections and expose saved queries as prompts (I made sure new 3rd party deps are ok).