chore: retire the legacy toolset MCP address

DA
18h ago
+1234-5475

AIM-670

Summary

  • Deletes hostedmcp/legacyalias and every call to it. Hosted MCP servers are reached only through their mcp_endpoints rows. A slug that only toolsets.mcp_slug held now returns not found on every surface:
    • /mcp/<slug> POST. GET (SSE) and DELETE answer 405, as for any unknown slug, and nothing is proxied.
    • both .well-known metadata routes
    • the per-endpoint OAuth handlers (register, authorize, token), and the shared authorization server's resource lookup
    • the install page and metadata export
    • cached challenges that name only a toolset (no mcp_server_id)
  • Rejects the old toolset-URN audience. A bearer must carry the server's resource, issuer or issuer-servers audience. Tool selections stored as toolset:<id> keep binding the toolset's server, so existing sessions keep serving, refreshing and redeeming codes.
  • Removes the migration counters mcp.toolset_slug_fallback and mcp.legacy_audience_accepted, their attribution log lines, and their gram.mcp.entry_point / gram.mcp.fallback.* attribute conventions.
  • Endpoints are the only address everywhere else too:
    • Plugin generation drops a hosted server that has no usable endpoint, where it used to emit the toolset-slug URL. Adding a toolset to a plugin needs an endpoint.
    • The slug availability check covers only endpoints. Endpoint writes no longer move a toolset alias.
    • Toolset views take mcp_slug / custom_domain_id from the canonical server's endpoint. The API fields are unchanged.
    • The same goes for telemetry matchers, assistant attachments, admin health, attach impact, mint, external MCP migration candidates and the OpenAPI impact report.
    • The Platform MCP connection settings and plugin views do this too. The connection-settings tool output drops legacy_platform_slug, which reported the custom-domain alias the platform host still served.
    • mcpServers keeps legacy_platform_slug, now deprecated and always absent.
  • mcpEndpoints.checkSlugAvailability: mcp_server_id is deprecated and ignored, so it can no longer fail the call (Goa, OpenAPI, SDK). The dashboard stops sending it.
  • Dashboard: the server address settings drop the row for the older Speakeasy address, which the API no longer reports.
  • No schema change. sqlc_retired_columns.sql and the toolset columns stay; AIM-671 drops them. The legacyalias sqlc package entry is gone.

Motivation

Since hosted servers own their endpoints (#8021), the alias was only a fallback for slugs no endpoint holds. #8132 fenced every remaining read of it into one package so it could be removed in one step. This PR removes it, so AIM-671 can drop the columns.

Customer impact: an address that exists only as a toolset's old mcp_slug stops serving. Old toolset-audience tokens are refused, so those clients sign in again. Making the address an endpoint on the server keeps it working.

Rollout

  • During the deploy, an old pod can answer 409 to an endpoint write whose new slug equals a stale toolset alias, since old pods still count aliases as taken. Retrying on a new pod succeeds.
  • A rollback revives every stale alias. Endpoint renames made while this PR was live did not move the aliases, so a revived alias can point at a slug the server no longer uses.

Merge gate

Do not merge until all hold:

  • AIM-821 (explicit endpoints for every address a legacy alias still serves) is applied on dev and prod, so no stored URL depends on the alias and no alias slug becomes claimable.
  • Datadog monitor 337099195 (legacy slug fallback, excluding install-page crawlers) reads OK after the backfill. It evaluates a 2-day window.
  • 2026-11-07 or later: 720h after the legacy toolset audience was last accepted, so no access token carrying it can still be valid. Endpoint routes already re-mint with the issuer audience.

๐Ÿค– Generated with Claude Code


Summary by cubic

Retires the legacy toolset /mcp/<slug> address and every fallback that resolved through toolsets.mcp_slug. Hosted MCP servers are now reached only through their mcp_endpoints rows, so a slug only a toolset still holds returns not found on every surface: the /mcp/<slug> routes, both .well-known metadata routes, the per-endpoint OAuth handlers, the shared authorization server resource lookup, the install page, and cached challenges without a server ID.

Also rejects the legacy toolset-URN bearer audience. Access tokens must name the server; clients holding toolset-audience tokens sign in again. Tool selections already stored as toolset:<id> keep binding, so existing sessions keep serving, refreshing, and redeeming codes. legacy_platform_slug is now deprecated and always absent, checkSlugAvailability ignores mcp_server_id, and the dashboard drops the older Speakeasy address. The migration counters and their attribution conventions are gone, and plugin generation drops hosted servers with no usable endpoint.

Migration

  • To keep an address working, add it as an endpoint on the server.
  • During deploy, an endpoint write whose new slug matches a stale alias can 409 from an old pod; retry on a new pod.
  • Do not merge until AIM-821 is applied on dev and prod, Datadog monitor 337099195 reads OK, and 2026-11-07 has passed (720h after the legacy audience was last accepted).

๐Ÿš€ Preview Environment (PR #8248)

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

ComponentStatusDetailsUpdated (UTC)
โœ… DatabaseReadyExisting database reused2026-10-30 23:43:05.
โœ… ImagesAvailableContainer images ready2026-10-30 23:45:02.

Gram Preview Bot