chore: retire the legacy toolset MCP address
AIM-670
Summary
- Deletes
hostedmcp/legacyaliasand every call to it. Hosted MCP servers are reached only through theirmcp_endpointsrows. A slug that onlytoolsets.mcp_slugheld 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-knownmetadata 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_fallbackandmcp.legacy_audience_accepted, their attribution log lines, and theirgram.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_idfrom 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. mcpServerskeepslegacy_platform_slug, now deprecated and always absent.
mcpEndpoints.checkSlugAvailability:mcp_server_idis 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.sqland the toolset columns stay; AIM-671 drops them. Thelegacyaliassqlc 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
| Component | Status | Details | Updated (UTC) |
|---|---|---|---|
| โ Database | Ready | Existing database reused | 2026-10-30 23:43:05. |
| โ Images | Available | Container images ready | 2026-10-30 23:45:02. |
Gram Preview Bot