Skip to content

feat(mothership): discover every workspace mcp server without tagging - #9263

Merged
waleedlatif1 merged 1 commit into
stagingfrom
feat/mcp-discovery-without-tagging
Oct 21, 2026
Merged

waleedlatif1 merged 1 commit into
stagingfrom
feat/mcp-discovery-without-tagging

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Agent and plan chats now discover every usable workspace MCP server, not just the ones a user /-tagged. This matches Claude Code, Codex, Cursor and OpenCode, where configured MCP servers are available and their tools load on demand. Built-in integrations already work this way here.
  • A tagged server now acts as a priority hint, not a gate. Its operations win ranking ties, and its own errors still surface. Execution never checked tags (traced through executeMcpToolUseCase, which authorizes per server), so the catalog lookup was the only gate.
  • Latency: untagged servers are discovered through McpService's cache-aside path (5-minute cache, list_changed invalidation, deduplicated in-flight requests, a cooldown for failed servers), and each is capped at 3s. A cold or slow server is skipped and logged without failing the query, and the background discovery warms the cache for the next one. Tagged servers and exact-toolId lookups stay live and complete, as before.
  • Unchanged scope: Search (assistant mode) stays MCP-free. Workflow-block requests (mcpExecution / mcpToolIds) stay limited to the block's selections and Force. Credential Group servers still need an explicit managed connection.
  • Permission groups: if MCP is disabled for the requester, a broad query returns built-in operations without MCP instead of failing. A request that targets an MCP server still fails with the permission error.

Stacked on #9260 (resilient per-server discovery). Merge that first; this PR then retargets staging.

Type of Change

  • New feature

Testing

  • New catalog.test.ts block "untagged workspace MCP servers":
    • agent and plan queries return an untagged server's operations from the cache path;
    • disabled, Credential Group and deleted servers are excluded;
    • a tagged server ranks ahead of an equally relevant untagged one;
    • a slow untagged server is skipped after 3s without failing the query;
    • an MCP-disabled permission group still lists built-ins, while a targeted request throws;
    • an untagged server's exact toolId resolves via complete discovery.
  • The 8 new tests fail on the previous code. The 5 touched vitest files pass (147 tests), and tsc --noEmit is clean. CI runs the rest.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel

vercel Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
docs Skipped Skipped Oct 21, 2026 1:17am UTC

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 10 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Turn on auto-fix | Re-trigger cubic

@greptile-apps

greptile-apps Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 5/5

[Medium impact] The PR appears safe to merge; no actionable issues were found.

Summary

Agent and plan chats can discover usable workspace MCP servers without tagging them.

  • Agent and Plan chats find workspace MCP tools without a tag.

No actionable issues were found. This review used code inspection; no tests were run.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Catalog request] --> B{Search mode?}
  B -->|Yes| C[Built-ins only]
  B -->|No| D{MCP allowed?}
  D -->|No, broad chat| C
  D -->|No, targeted or workflow| E[Permission error]
  D -->|Yes| F{Workflow selection?}
  F -->|Yes| G[Discover selected MCP tools]
  F -->|No| H[List usable workspace servers]
  H --> I[Tagged or targeted: complete discovery]
  H --> J[Untagged: cached discovery, three-second wait]
  G --> K[Filter and rank results]
  I --> K
  J --> K
Loading

Reviews (1) · Last reviewed commit: "feat(mothership): discover every workspa..." · Reviewed by Greptile

The integration catalog only inspected MCP servers the user had /-tagged in the
chat, so a configured server's tools were invisible to the agent until tagged.
Claude Code, Codex, Cursor and OpenCode treat every configured server as
available and discover tools lazily; built-in integrations here already did.

In agent and plan chats, the catalog's MCP candidates are now every enabled,
non-Credential-Group server the requester can list in the target workspace.
Search stays MCP-free, and workflow-block requests (mcpExecution or selected
operations) stay scoped to their explicit selections.

- Untagged servers are discovered best-effort: cache-aside through the existing
  McpService discovery cache (in-flight deduped, negative cache honored), and a
  server that does not answer within 3s is skipped and logged while its
  discovery keeps running to warm the cache for the next query.
- Tagged servers and an explicitly targeted server (service mcp:<id> or an exact
  tool id, which the worker re-resolves before executing) are still listed live
  and completely, and a targeted server still fails with its own error.
- Tagged servers rank first among equally relevant matches via a
  preferredServices tie-break in projectIntegrationCatalog.
- A permission group that disables MCP now drops MCP from broad requests and
  keeps built-in operations listed; targeted and workflow-block requests still
  fail with the permission error.

Tagging persistence is unchanged; comments that said untagged servers stay
unavailable now describe tags as a priority hint.
@waleedlatif1
waleedlatif1 force-pushed the feat/mcp-discovery-without-tagging branch from 2d6bc32 to a1bb62b Compare October 21, 2026 01:17
@waleedlatif1
waleedlatif1 changed the base branch from fix/mcp-discovery-resilience to staging October 21, 2026 01:17
@waleedlatif1
waleedlatif1 merged commit f2b5823 into staging Oct 21, 2026
53 of 54 checks passed
@waleedlatif1
waleedlatif1 deleted the feat/mcp-discovery-without-tagging branch October 21, 2026 01:56
waleedlatif1 added a commit that referenced this pull request Oct 21, 2026
… catalog resilient (#9266)

* fix(mothership): keep untagged mcp discovery side-effect free and the catalog resilient

Broad agent and plan catalog queries now discover every usable workspace MCP
server (#9263), but a server's status, failure count, cooldown and OAuth row
are shared by the workspace while its credentials resolve per requester. A
member without a personal {{VAR}} the server references made discovery fail,
which stamped the server failing and put it in a workspace-wide cooldown, so
another member's tagged or targeted discovery and call re-resolution failed
with McpServerCooldownError. For an OAuth server the requester never
connected, discovery inserted an empty OAuth row and marked the server
disconnected for everyone.

- Best-effort (untagged, broad) discovery is a McpService mode that only reads
  shared health state: on failure it writes no status, failure count,
  cooldown or cache eviction, and on success only warms the tool cache.
- Before reading the cache or connecting, it skips a server the requester
  cannot authenticate to: a referenced variable they have no value for
  (findMissingMcpConfigEnvVars, which records no secret usage), or an OAuth
  server with no authorized tokens (read, never created). Another member's
  cached tools are not served to them.
- Tagged and targeted discovery keep today's health bookkeeping.
- A failure listing the workspace's servers no longer fails the whole
  catalog: broad requests log it and keep built-ins and tagged servers;
  targeted MCP requests still fail with it.
- A query with no content terms after tokenization (stop words only, or a
  script the tokenizer does not split) returns the unranked listing, as an
  empty query does, instead of total 0. Exact-ID ranking is unchanged.
- A tagged server that is no longer usable is logged when dropped.

* fix(mothership): gate best-effort mcp discovery on side-effect-free credential reads

The best-effort gate read the OAuth row with loadOauthRow, which clears a
column it cannot decrypt, so a broad catalog query after a key rotation
erased the one grant every member shares. hasDecryptableOauthTokens reads
the tokens column and tries to decrypt it without writing anything.

findMissingMcpConfigEnvVars took a variable that failed to decrypt (which
the environment snapshot reports as '') as present, so best-effort discovery
connected with an empty credential instead of skipping. An empty effective
value now counts as missing.

* fix(mothership): keep the shared mcp oauth grant intact on best-effort refresh failures

Best-effort discovery could still run the SDK's OAuth recovery while listing
tools. A rejected refresh made it clear the tokens (and, for a rejected
client, the registration) and start a new authorization flow, which
disconnected the shared grant for every member. Its OAuth clients now use a
SimMcpOauthProvider with preserveGrant, which refuses to invalidate
credentials, register a client or start authorization before any write, so a
failed refresh skips the server. A successful refresh still persists. It
keeps the grant valid for everyone and must be saved where the server
rotates refresh tokens. These clients are pooled apart from tracked ones.

findMissingMcpConfigEnvVars counted every empty value as missing, but an
empty variable is valid. Only a key the snapshot names in decryptionFailures
whose effective value is empty now counts as missing.

This branch was previously deployed

1 inactive deployment
Preview — a1bb62bf Deployed Oct 21, 2026 by vercel[bot]
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