Skip to content

feat: initial remote MCP source management UI#2608

Merged
bflad merged 10 commits into
mainfrom
bflad-age-1719-initial-remote-mcp-source-management-ui-kbWW
May 8, 2026
Merged

feat: initial remote MCP source management UI#2608
bflad merged 10 commits into
mainfrom
bflad-age-1719-initial-remote-mcp-source-management-ui-kbWW

Conversation

@bflad
Copy link
Copy Markdown
Member

@bflad bflad commented May 5, 2026

Summary

Implements AGE-1719 — the day-0 dashboard UI for the new Remote MCP source type, gated behind the gram-remote-mcp PostHog flag. Lets users register an external MCP server by URL and manage it with full CRUD without touching the catalog or deployment surface.

What's in this PR

Backend:

  • Extends mcpServers.list with optional remote_mcp_server_id and toolset_id filters so the detail page's MCP Servers tab can scope to a single backend. The two filters are mutually exclusive (the mcp_servers schema's mcp_servers_backend_exclusivity_check already guarantees exactly one backend per row, so a query that pinned both would always be empty).
  • Adds a remoteMcp.verifyURL RPC that probes a candidate URL with an MCP initialize request and reports a verification outcome.
  • Adds an optional human-readable name and a URL-derived slug to remote_mcp_servers; slug is computed server-side on every write from the URL host+path and the last four characters of the id, and getServer accepts mutually-exclusive id or slug parameters.

Dashboard — gated behind gram-remote-mcp:

  • Add Source dropdown gains a Custom remote server entry (lucide Network, violet swatch). Existing Third party server entry renamed to Registry server to disambiguate from the new flow.
  • New create form at /sources/add-remote-mcp with a URL field, an optional Display Name field, a Verify MCP Connectivity button (calls remoteMcp.verifyURL), and absolute-http(s) + non-empty-host validation that mirrors the server's url.Parse checks.
  • New detail page at /sources/remotemcp/:slug (with id fallback) modeled on ExternalMCPDetails.tsx. Three hash-routed tabs: Overview (Source Information table + Source Activity panel mirroring the OpenAPI source layout — Activity renders a structural empty state pending telemetry wiring tracked in AGE-2213 and AGE-2214), MCP Servers (cards for mcp_servers rows whose backend points at this remote MCP server), Settings (Display Name + URL edit with Verify MCP Connectivity button, plus Danger Zone delete).
  • Source listing card and table row gain a remotemcp variant on NamedAsset with a Remote MCP badge; the display label prefers the server name and falls back to the URL with the protocol stripped. Card click routes into the new detail page.
  • Existing RemoveSourceDialogContent and ViewAssetDialogContent narrow their asset prop to exclude remotemcp since those flows only handle deployment-bound sources.
  • Form and Settings validation errors surface as inline alert boxes.

Orchestration

The backend doesn't expose a single transactional RPC for the compound create/delete operations the issue describes, so the create and delete flows live in pages/sources/remote-mcp/hooks.ts:

  • useCreateRemoteMcpSource — calls remoteMcp.createServer, then mcpServers.create with the new id and visibility: "disabled". On partial failure (mcp_server create fails) it attempts to roll back the remoteMcp row; if rollback also fails, surfaces the orphaned id so the user can clean up manually.
  • useDeleteRemoteMcpSource — soft-deletes each linked mcp_servers row first (which cascades to mcp_endpoints server-side), then deletes the remoteMcp row. The confirmation dialog enumerates linked servers and their endpoints up front so the user understands the full fan-out before confirming.

Both hooks invalidate remoteMcp.listServers, mcpServers.list, and mcpEndpoints.list with refetchType: "all" on success so the index, detail, and dialog caches stay coherent across navigation.

Follow-ups

  • Full MCP server, custom domain, and MCP endpoint management beyond the auto-provision-on-create scaffolding is tracked in AGE-2118.
  • Source Activity telemetry wiring for Remote MCP Server sources — ClickHouse telemetry_logs schema change (AGE-2213) and the dashboard wiring on top (AGE-2214).

@bflad bflad requested review from a team as code owners May 5, 2026 18:48
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 5, 2026

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

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

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 5, 2026

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

Project Deployment Actions Updated (UTC)
gram-docs-redirect Ready Ready Preview, Comment May 8, 2026 1:40pm

Request Review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 5, 2026

🦋 Changeset detected

Latest commit: 86a161d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
dashboard Minor
server Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added the preview Spawn a preview environment label May 5, 2026
@speakeasybot
Copy link
Copy Markdown
Collaborator

speakeasybot commented May 5, 2026

🚀 Preview Environment (PR #2608)

Preview URL: https://pr-2608.dev.getgram.ai

Component Status Details Updated (UTC)
✅ Database Ready Existing database reused 2026-05-08 13:45:17.
✅ Images Available Container images ready 2026-05-08 13:45:00.

Gram Preview Bot

@bflad bflad force-pushed the bflad-age-1719-initial-remote-mcp-source-management-ui-kbWW branch from fa9540c to 0d7e4e2 Compare May 5, 2026 18:54
@bflad bflad force-pushed the bflad-age-1719-initial-remote-mcp-source-management-ui-kbWW branch from 0d7e4e2 to 3a3e584 Compare May 6, 2026 13:48
Copy link
Copy Markdown
Member

@simplesagar simplesagar left a comment

Choose a reason for hiding this comment

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

Nice work! Some feedback on the UX primarily on the state post adding a server by url, screenshot below

  1. I think we need a display name that's easier for customers to reference rather than just the long id eg: https://pr-2608.dev.getgram.ai/speakeasy-team/projects/default/sources/remotemcp/019dfd85-a73e-76f0-8cc9-41c579064bcf
  2. If we can we should materialise the remote tools into a list on this page as a new tab. See tabs for other source types as inspiration
  3. on the settings tab it let me update to a url that was invalid whereas in the initial setup step it does not
  4. in the initial setup step there's a nice warning below the entry box indicating validity of the URL. We should highlight/color that text to make it stand out as a warning.

Other ideas

  • you could probably lift and shift the source overview tab (table and activity overview) we have for other source types
  • We show a filtered view of deployments for other sources. We could probably do something similar here.
Image

@bflad
Copy link
Copy Markdown
Member Author

bflad commented May 6, 2026

Thanks, @simplesagar!

I think we need a display name that's easier for customers to reference rather than just the long id

I agree, I do think we need some form of (display) name. I'm not sure about using it as slug as that'll have URL path character requirements then. Either which way (whether just name or name + slug) can get that added into the backend real quick. Using the URL everywhere leaves much to be desired.

If we can we should materialise the remote tools into a list on this page as a new tab. See tabs for other source types as inspiration

Is there a particular reason? A few of us are thinking we should only do this when working with policies and we should only do this during management of those. Getting the list requires authentication and we don't want to store this sort of data if avoidable (one of the problems with the existing implementation).

on the settings tab it let me update to a url that was invalid whereas in the initial setup step it does not

Will get that sorted, good catch.

in the initial setup step there's a nice warning below the entry box indicating validity of the URL. We should highlight/color that text to make it stand out as a warning.

Will also get this sorted, thank you.

you could probably lift and shift the source overview tab (table and activity overview) we have for other source types

Will reach out to you about this.

We show a filtered view of deployments for other sources. We could probably do something similar here.

We need to handle this differently for Registry MCP / Remote MCP. They're intentionally not using the toolset deployment model. Let me have a think about this, we might be able to augment the deployments page with audit logging for these sources or something so it shows similar information.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

bflad added 6 commits May 8, 2026 08:11
https://linear.app/speakeasy/issue/AGE-1719/initial-remote-mcp-source-management-ui

Both filters are optional and mutually exclusive — the schema's
mcp_servers_backend_exclusivity_check guarantees exactly one backend
per row, so a query that pinned both would always be empty. Index
migration tracked separately in AGE-2121.
https://linear.app/speakeasy/issue/AGE-1719/initial-remote-mcp-source-management-ui

Adds a flag-gated (gram-remote-mcp) Add Source entry, create form,
and detail page with Overview / MCP Servers / Settings tabs for the
new Remote MCP source type. The create and delete flows orchestrate
sequential remoteMcp + mcpServers RPC calls with rollback so the
linked records stay in sync. Also renames the existing Third party
server entry to Registry server to disambiguate.
Strip the http(s):// prefix when rendering a remote MCP server URL in
the page header, breadcrumbs, source card, and source table row. The
Settings input and Overview URL field keep the canonical value.
Orphaned by the source index empty-state refactor that switched the
condition to allSources.length === 0.
@bflad bflad force-pushed the bflad-age-1719-initial-remote-mcp-source-management-ui-kbWW branch from 6d8edf0 to 6a39405 Compare May 8, 2026 12:14
@blacksmith-sh

This comment has been minimized.

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

bflad added 4 commits May 8, 2026 09:39
…utton

https://linear.app/speakeasy/issue/AGE-1719/initial-remote-mcp-source-management-ui

Adds a new remoteMcp.verifyURL management API method that probes a
candidate remote MCP server URL with an MCP initialize request and
reports a verification outcome. Wires it into the Add Source create
form and the source Settings tab so users get a reachability signal
before they save. Treats reachable-but-401/403 responses as verified —
auth verification is intentionally out of scope.
https://linear.app/speakeasy/issue/AGE-1719/initial-remote-mcp-source-management-ui

Adds an optional human-readable name and a URL-derived slug to remote
MCP server records. createServer and updateServer accept an optional
name; slug is computed server-side on every write from the URL
host+path and the last four characters of the server ID. getServer
takes mutually-exclusive id and slug parameters; either resolves the
row.

Dashboard adds a name input on both the create form and the Settings
tab, prefers the name (falling back to the protocol-stripped URL) in
breadcrumbs, hero, source cards, and source table rows, and routes
/sources/remotemcp by slug (falling back to id).

Other changes:
- verifyURL returns "MCP response not found" for 404 responses.
- The Settings tab URL update navigates to the new slug to avoid
  bouncing the user back to the Sources index after save.
… MCP source overview

https://linear.app/speakeasy/issue/AGE-1719/initial-remote-mcp-source-management-ui

Mirrors the OpenAPI source overview's two-column layout: a Source
Information table on the left (Name, URL, Transport Type, Source ID,
Created, Updated, Linked MCP servers) and a Source Activity panel on
the right. Activity renders the structural panel with the same "no
data yet" empty state as OpenAPI — telemetry wiring is deferred since
the proxy's remote_mcp_server.id metrics aren't reachable from the
dashboard's ClickHouse-backed observability RPC yet.

Lifts OverviewRow into a shared SourceInfoTable / SourceInfoRow
component used by both overview tabs.
https://linear.app/speakeasy/issue/AGE-1719/initial-remote-mcp-source-management-ui

CreateServer now requires an explicit id (the impl pre-generates one
so it can compute the slug from the id's last four chars), but the
test fixtures still passed uuid.Nil by omission, causing primary-key
collisions whenever a test seeded more than one remote_mcp_server in
the same DB.

Adds a remotemcptest.SeedServer helper that generates a UUIDv7 when
none is supplied, and migrates the five call sites across mcpservers,
mcpendpoints, and xmcp to use it.
@bflad bflad force-pushed the bflad-age-1719-initial-remote-mcp-source-management-ui-kbWW branch from 26c8b29 to 86a161d Compare May 8, 2026 13:40
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 new potential issue.

View 11 additional findings in Devin Review.

Open in Devin Review

Comment thread server/internal/remotemcp/verifyurl.go
@simplesagar
Copy link
Copy Markdown
Member

Thanks for addressing the feedback Brian!

Is there a particular reason? A few of us are thinking we should only do this when working with policies and we should only do this during management of those. Getting the list requires authentication and we don't want to store this sort of data if avoidable (one of the problems with the existing implementation).

Primary reason is that it when a user adds in a source its an unusual experience not to be able to see what tools you are bringing into the system. There is also a matter of inconsistency between http, function, external and remote sources. I'm not opposed to asking the user to auth just in time during the process of adding a remote mcp. I think that ensures they are the right person to add in the source too.

@bflad
Copy link
Copy Markdown
Member Author

bflad commented May 8, 2026

We chatted about the tools listing vs security configuration awkwardness out of band. We'll create a way to handle that (either via wizard and/or some handling on these pages) such that you can go through the security configuration and persist it, rather than it potentially being temporary just to get the tools list. We just want to ensure there's one way to do that rather than introducing multiple UI journeys to manage.

@bflad bflad added this pull request to the merge queue May 8, 2026
Merged via the queue into main with commit 5136b45 May 8, 2026
38 checks passed
@bflad bflad deleted the bflad-age-1719-initial-remote-mcp-source-management-ui-kbWW branch May 8, 2026 15:19
@github-actions github-actions Bot locked and limited conversation to collaborators May 8, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

preview Spawn a preview environment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants