Repository navigation
server@2.27.0
Minor Changes
- 16a18d2: Device agents polling with an agent API key now receive
mcp_servers: the Speakeasy-hosted MCP servers in the plugins assigned to the agent, which the device writes into each tool's configuration with its own credential under aspeakeasy-<slug>name that stays stable across polls. Servers in plugins offered as available, unproxied vendor servers and gateway members are left out. Each entry also names the token endpoint, assertion audience and, where needed, resource a headless device exchanges its workload identity at to reach the server; entries no workload grant reaches carry none. The list is always present and empty for people, and changes to it change the poll's ETag. - 2bf3947: MCP servers that share a sign-in can each use their own upstream OAuth client. Each server, and each gateway member, signs in through the client configured for it instead of a provider shared by every server on the sign-in. The consent screen offers each server only its own clients. Connections made before a server was configured are asked to reconnect, never handed another server's client.
- 4c5156a: A headless device can authenticate to the device-agent API as a workload instead of with an agent API key. It exchanges an identity assertion, from a platform issuer the organization trusts or from its Speakeasy device issuer, at its organization's
/oauth/workload/device-agent/{organization_id}/tokenfor a 15-minute bearer token. Plugin polling (agent.getPlugins) and hook ingestion (Claude Code, Cursor, Codex,hooks.ingest, and OpenTelemetry logs and metrics) accept that token inAuthorization: Bearer. The workload stays the authenticated actor and acts for the agent assigned to it, under that agent's live permissions, so withdrawing the assignment or suspending the agent refuses the token on its next use. Every hooks request names its project inGram-Projectand is accepted only when the agent holdsorg:hooks_ingestfor that project; a request that names no project is refused. - e6c4584: Report whether each directory role mapping's source still exists, and list where each member's directory-mapped roles come from. Mappings now carry a
source_statusofactiveormissing(a deleted group, or an attribute value no live directory user has). Members now include their directory groups by stable ID, whether they have a live directory profile, and one entry per mapping that currently grants them a role, so a role reached through two groups shows both. - 9b19ed9: Store directory users' first and last names from Directory Sync events, and add a session-only
listDirectoryPeopleread that returns every live directory profile with its groups and whether it belongs to a member, has an account but is not a member, has not signed in, or shares an ambiguous email. - 1cf1228: Raise directory changes that need an admin decision and add
listDirectoryReviewItemsandresolveDirectoryReviewItemto decide them. Once review starts for an organization (on the first hourly reconciliation), a directory group first seen after that with no role, a new value of an attribute key that already has mappings, and a mapped group or attribute value that has gone from the directory are each raised as a review item, at most once per occurrence. Directory events raise and settle items in the same transaction as the change; the hourly sweep catches the rest and never writes mappings. Approving a new source maps it to the chosen roles, creating new roles as bulk setup does; approving a missing source removes its mappings. Dismissing leaves a new source unmapped or keeps a missing source's mappings, and an attribute key can be opted out of new-value decisions. Mapping a source directly settles its pending items. Every decision is recorded in the audit log. - 98de4bb: Tell organization admins about directory changes waiting for a decision. Admins get one email when new directory review items have been quiet for 15 minutes, then a weekly reminder while any stay pending, up to four reminders; the email has counts and a link to the SSO page, never group names or attribute values. Every item that opens or resolves now publishes a
directory_review.opened_v1ordirectory_review.resolved_v1webhook event in the same transaction, carrying IDs, the kind, its state and the pending count. Admins can turn the emails off per organization withgetDirectoryReviewSettingsandupdateDirectoryReviewSettings, which are audit logged; webhooks are unaffected. Platform MCP gainslist_directory_review_itemsandresolve_directory_review_item, which run the dashboard's own review checks and require explicit confirmation. - 8b6af9e: Add
previewDirectoryRoleSetupandapplyDirectoryRoleSetupfor setting up directory role mappings in bulk. The preview proposes a role for every directory group and attribute value: an existing role with the same name, or a new one named after the source. Attribute keys with too many values to offer are listed by name and value count. Apply creates the new roles and replaces each listed source's roles in one transaction, and changes nothing if a source or its roles changed since the preview. New roles get no grants unless a grant set is given. WorkOS role sync is reported as requested, not done, and creating roles sets up no plugin distribution. - 06bec6e: Platform MCP tools that add, check and connect an MCP server now use the organization's default project when no project is named, and their result names the project they used. An organization with no default project gets a clear error that asks for a project.
- 30b88fd: Org Gateway now requires an administrator to opt in instead of becoming available automatically. Review organization-wide MCP access by role before enabling, inspect each person’s effective assignments, remove server-specific role grants or block role access, and open client-specific connection instructions from the Organization Gateway card on the MCP Servers page. The assignments explorer is also available in Roles & Permissions.
- 3516760: Add the Platform MCP
redeploy_deploymenttool for previewing and confirming a whole-project deployment retry or rollback. Redeployment preserves the existing authorization and audit workflow, checks the active snapshot before cloning and again atomically before activation, and uses idempotency receipts so retries reuse the same deployment. Processing is dispatched without blocking the MCP call. Results report observed processing status rather than assuming a cloned deployment is ready. - f039d7a: Speakeasy remembers per-server approvals for identified users connecting through a shared authorization server. Unchanged access can reuse the saved tool selection and session length; new servers, changed tool inventories, and missing upstream permissions require consent. Withdrawing consent forgets every approval for that person and client under the issuer without revoking existing sessions.
- b772e91: Show connected tunnel agents, target network checks, and MCP request history in the dashboard. Agents report aggregate HTTP progress when a gateway with diagnostics enabled polls them without collecting payloads or making MCP calls. Existing agents continue forwarding traffic.
- a49d1b6: Headless boxes with no platform identity, such as a one-off VPS, can now enroll as workloads. An administrator who owns an agent, or holds agent:authorize on it, creates a single-use join token with
workloadIdentities.createDeviceJoinToken; the agent's policy must grantorg:device_agent_sync, and nothing else is required to enroll. The box registers its public key withworkloadIdentities.registerDeviceand is admitted and assigned that agent. Its signed assertions are then exchanged for workload sessions like any other workload's, and are verified against the key registered for that device alone. Neither the join token nor the admission names a hooks project: a workload names its project on every hooks request, and the agent'sorg:hooks_ingestgrant for that project decides whether it is accepted.
Patch Changes
-
3c60eac: When the code exchange at the end of an MCP connection login fails, the error now names why instead of only "upstream token exchange failed": the identity provider's standard OAuth error code (for example
invalid_grantorinvalid_client), including when the provider reports it under HTTP 200; the HTTP status of a failed response; or a fixed reason when the provider could not be reached, the MCP tunnel is not connected or could not reach the provider, or the client assertion could not be signed. The provider's own error description and vendor-specific codes are kept to server logs. A provider outage now answers 502 or 503 instead of 401. Federated sign-in now treatstemporarily_unavailableandserver_errorfrom the provider as an outage, andinvalid_clientorunauthorized_clientreported under HTTP 200 as a configuration problem. -
f95f7df: An MCP OAuth request whose
client_idis the MCP server's own URL is now refused with401 invalid_clientand a hint to check the MCP client's OAuth Client ID setting, instead of failing with a retryable503after trying to fetch that URL as a client metadata document. -
e251399: Retires the experimental
/x/mcpMCP surface. Every/x/mcp/*route, including its OAuth endpoints,.well-knownmetadata and the/x/mcp/idp_callbackand/x/mcp/remote_login_callbackcallbacks, now returns 404; MCP servers are served at/mcp/{slug}. Dashboard-minted user-session tokens for an MCP server without an endpoint now name/mcp/{slug}as their issuer. Tokens already minted with an/x/mcpissuer are accepted on/mcpexactly as before. Login flows still in progress on/x/mcpat deploy, and shared-authorization-server sessions bound to an/x/mcpresource, must re-authorize on/mcp. -
a335d3c: Hosted MCP plugin entries, install page metadata, and assistant attachments are now always written under the toolset's canonical MCP server, and the
hosted-mcp-server-key-writesrollout flag is removed. That includes a canonical server that is disabled, and toolsets with MCP off or no MCP slug that have one. Theplugin:server_addaudit event for a hosted toolset names the MCP server. Adding a toolset that has no MCP server to a plugin, saving its install page metadata, or attaching it to an assistant now fails with "toolset has no hosted MCP server", and the Default plugin attach skips it. The Plugins page disables such toolsets in the server picker. Turning MCP on for a toolset now delivers its MCP server to matching role plugins, as enabling any other MCP server does; a removal recorded under either key still keeps it out. Readers still accept rows under either key. A toolset no longer reads install page metadata or headers stored under a server that holds its id but is not its canonical MCP server. -
2d42382: Hosted MCP plugin entries, install page metadata, and assistant attachments are now read only under the toolset's canonical MCP server. Rows still stored under the retired toolset key are no longer read, except that a plugin entry removed under the toolset key still keeps role delivery from re-adding the server. A plugin entry left under the toolset key is listed with backend
unresolvedinstead of being dropped. -
6933ae5: Add a
-cleanup-orphansmode to the hosted MCP wrappers backfill that removes toolset-keyed dependents whose toolset or project is deleted, journaled and audited like the dependent move. -
45e50cf: Add a
-rekey-removal-recordsmode to the hosted MCP wrappers migration tool. It moves soft-deleted toolset-keyed plugin server rows onto the canonical server key, so plugin removals keep blocking role delivery once the toolset key is dropped. -
eba9f9f: The Playground MCP URL and the
issclaim of dashboard-minted user-session tokens no longer name a custom domain that is not verified and activated. Those addresses fall back to the server's platform endpoint, or to/mcp/{slug}when it has none. A toolset whose MCP server's only endpoints sit on such a domain still mints against that server's issuer; only theissURL changes. The legacy toolset Playground URL applies the same check to the toolset's own custom domain. -
a8f0010: An MCP server's User Identity settings now say when its OAuth client also signs in other MCP servers, since changing or rotating that client changes their sign-in too.
-
2a1b1dc: MCP route bases are now a typed value with two served surfaces,
/mcpand the organization gateway's/mcp/gateway. A login state cached with any other route base, such as the retired/x/mcp, now fails closed on resume instead of building URLs on an unserved surface. -
ba8e729: A configured MCP server header can no longer read the caller's
Authorizationrequest header as its source. That header may carry the caller's Speakeasy credential, and must not be sent to an upstream MCP server under another name. Creating or updating such a header is refused, and the dashboard flags it while editing. At request time, an optional one is not sent and a required one fails the request. To pass a caller-supplied upstream credential through, read it from a separate request header; it can still be sent upstream asAuthorization. -
01394c3: Add a
-delete-leftover-removal-recordsmode to the hosted MCP wrappers migration tool. It hard-deletes soft-deleted plugin removal records that are still keyed only by toolset when their toolset or project is deleted, or when the plugin already has a server-keyed removal record for the toolset's canonical server, and leaves any record that may still keep a live wrapper server of the toolset out, so the toolset column can be dropped. It runs as a dry run by default, journals every deleted row, and ships a restore script. It also adds a-delete-orphan-wrapper-serversmode, run first, that deletes live non-canonical servers left behind by deleted toolsets through the app's server delete, with the same audit rows and publication requests, a journal and a restore script, so their toolsets' removal records can then be deleted too. Every run of the tool, dry runs included, now needs an explicit-project <id>or-all-projects. -
11fb65f: Authorization challenges are now recorded when the client disconnects before the request finishes, and an MCP tool listing stops checking per-tool access once the client has gone.
-
bd1d30e: Deleting an MCP server or gateway now removes it from the scope of every risk policy that also targets other servers, so those policies can still be saved. A policy left with no target is deleted, as before.
-
e446682: Anthropic inference hook verdicts now check only the latest exchange of a conversation, so long conversations no longer time out and a denial applies only to the turn that introduced the content.
-
e2ab479: The typed auth client backfill now also records static credential and pass-through clients from a source's credential headers, copies credential headers onto upstream OAuth clients, and records EMA clients from ready identity chaining bindings. It keeps copies and scopes in sync, retires what the configuration no longer yields, runs each phase independently under a per-organization lock, and reports per-kind counts and why anything is unresolved.
-
03b4725: Record a typed auth client for every upstream OAuth client an MCP server uses, as a separate step of the admin upstream OAuth migration, retire backfilled records whose association or client is gone, and mark servers that offer one as needing upstream authentication where that is still undecided. Nothing reads these records yet.
-
732e74d: Resolve issuer-gated direct remote and tunneled servers through typed auth clients behind the
auth-client-resolverflag, withauth-client-resolver-shadowcomparing the two paths without changing requests. Choices not yet mapped onto auth clients, and cases the old path still handles differently, keep being served the old way. With the flags off nothing changes. -
0ea1722: When the auth client resolver is enforced, a personal connection or service account resolves through its OAuth registration without requiring a link to the server's sign-in, so one consent serves every server the registration reaches: a project registration's servers in its project, and an organization or global registration's servers across the organization the consent was made in, never another organization.
With the flags off, lookups are unchanged. A re-consent through another organization's sign-in now replaces the stored grant with a new one recorded in that organization, rather than updating the old grant in place. Workloads, agents and other automated callers in the first organization then need the user to reconnect there, instead of silently using a token consented in the other organization.
-
479789c: Connecting to a service whose authorization server has no sign-in page now says the service doesn't support signing in from Speakeasy, instead of failing with an unexpected error. The demo seed's Enterprise Managed Authorization example servers are now disabled, so consent pages and gateways no longer ask people to connect them.
-
1f98a3b: The stable device agent installer links move from
/v1/install/to/rpc/install/(device-agent-macos.pkganddevice-agent-windows.msi). Production never routed/v1/installto the server, so those links returned the dashboard's HTML, and the Windows setup step saved that page asspeakeasy-agent.msi. The Windows step now uses the new link. -
9bd70da: Limit a directory group or attribute value to 20 roles. Saving more roles on one source, directly, through bulk role setup or by approving a directory review item, now fails with a clear error instead of being saved.
-
8da7eb9: Stop directory-mapped roles and profile attributes from contributing when their attributed directory is deleted, without removing organisation memberships or affecting another directory.
-
52c9adb: Serve the hooks@0.3.37 binary to hook installations. Previously pinned releases stay available so installations that have not regenerated their bootstrap script can still install.
-
2d77545: Answer legacy Claude Code hook requests (
/rpc/hooks.claude) within 5 seconds. When a policy check takes longer, the endpoint now responds from the organization's hooks fail-open setting instead of letting older curl-based hook scripts time out and block with "HTTP 000". Fail-open organizations get a pass-through response; fail-closed organizations, and organizations whose setting cannot be read, get a block that says the security check did not finish in time. The event is still recorded, and the slow check finishes in the background. -
75bb8cd: Listing MCP servers no longer returns servers backed by a deleted toolset, and the hosted server summary now includes the toolset's description. Opening such a server by id or slug still works, so it can be found and deleted. MCP server reads now report
has_endpoint: whether any endpoint routes to the server, including one on a custom domain that is not live yet. -
43a942f: Add
search_chatsandread_chatto Platform MCP to search messages by text, owner or participant and read surrounding context, withchat:readaccess and audit logging. -
41cdca1: Every Platform MCP tool now states
readOnlyHint,destructiveHint, andopenWorldHintexplicitly for every audience, set from what the tool really does, and keeps the same hints whether or not its feature is switched on. A tool is marked open world only when it reaches a host outside Speakeasy, such as a registry, the user's own MCP server, an OAuth provider, or GitHub. Clients such as ChatGPT's app review refuse a tool that leaves a hint implicit. -
b772e91: Tool Logs now marks a failed tool call on a remote or tunneled MCP server as failed. A tool result with
isErrorset is recorded with status 500 when the server answered with HTTP 2xx, as a JSON-RPC error already was. A call that gets no tool result at all, because the server could not be reached, answered with an error status or an unreadable body, or ended its stream early, now writes a failed row instead of none, carrying the server's error status or 502 when there was none. -
7a21235: Opening the dashboard on the legacy host no longer resets the organization you picked on your organization's own host. A move between hosts keeps the session you already have there, unless you just switched organization before the move.