Overview
Release 1.0.11 consolidates 57 PRs focused on the MCP Python SDK 2.x migration, tool preview, SSO linking and group-mapping controls, catalog and OAuth registration fixes, CORS and schema-validation hardening, and live black-box E2E coverage:
- Protocol & Transport - Moved to
mcp>=2.0.0withmcp-types, added modern protocol negotiation to legacy(MCP_CLIENT_CONNECT_MODE,MCP_INBOUND_PROTOCOL_MODE,GATEWAY_MODERN_LISTENERS_ENABLED, all legacy by default), and paginated every upstreamlist_*call. - Security & Auth - CORS origin reflection now requires an explicit allowlist, schema validation refuses remote
$refs, SSO cross-provider linking is fail-closed behindSSO_ALLOW_PROVIDER_LINKING, SSO and SIEM output is XSS-hardened, and tool lookup caches are isolated per tenant scope. - API & Platform - Added the tool preview endpoint, per-caller OAuth token status, a team search filter, passwordless SSO-only users, and MCP-compliant tool execution errors.
- Operations - Removed the stdio wrapper in favour of FastMCP, migrated the output length guard to the Rust-backed CPEX package, fixed OCP PGO Helm deployment on fresh clusters, and refreshed Python, Node.js, and Rust dependencies.
- Testing - Consolidated the live MCP E2E suites and added virtual server, user, token, team, and gateway lifecycle coverage against a running gateway.
Added
API & Platform
- Tool preview endpoint (#6443) - Added
POST /tools/preview/{name}(and its/v1mount), a dry-run counterpart to tool invocation that validates arguments against the tool'sinput_schema, resolves local vs. federated targeting, and reports which plugin pre-invoke hooks would run, without ever dispatching the tool. Gated behindMCPGATEWAY_TOOL_PREVIEW_ENABLED(off by default) and thetools.previewRBAC permission. Only plugins taggedpreview_safeactually run during a preview; every other hook that would run live is reported as a warning instead. - Per-caller OAuth token status (#6620) -
/oauth/statusreports the calling user's own token state instead of a shared gateway-level state. - Team search filter (#6652) -
GET /v1/teams/accepts asearch_queryfilter. APP_DOMAIN-derived server URL (#6656) -ServerReadexposes aurlbuilt fromAPP_DOMAIN, so clients behind ingress proxies receive a reachable address.
Security & Auth
- Passwordless SSO-only users (#6603) - Users provisioned through SSO exist without a local password instead of carrying an unusable placeholder credential.
SSO_ALLOW_PROVIDER_LINKING(#6616) - Explicit, fail-closed setting (defaultfalse) that gates cross-provider sign-in for an already-linked email.
Catalog & Plugins
- OAuth discovery metadata in the bundled catalog (#6613) - Seeded discovery metadata into
mcp-catalog.yml, so OAuth-protected catalog entries register without manual endpoint entry. - Rust-backed output length guard (#6846) - Migrated the output length guard plugin to the Rust-backed CPEX package.
Breaking Changes
- Configurable header sanitization limit (#6654) - Added
MAX_HEADER_VALUE_LENGTHwith a 4096 default. Existing deployments without this setting retain current behavior. Python integrations importing the removedMAX_HEADER_VALUE_LENGTHmodule constants must usesettings.max_header_value_length. Invalid pre-existingMAX_HEADER_VALUE_LENGTHenvironment values now fail startup. For large OAuth tokens, raiseMAX_HEADER_VALUE_LENGTH,MAX_HEADER_FIELD_SIZE_BYTES, andMAX_HEADER_TOTAL_SIZE_BYTEStogether. - stdio wrapper removed in favour of FastMCP -
mcpgateway/wrapper.py(python -m mcpgateway.wrapper) and the Rustcrates/wrapper/binary are removed. Clients that already speak Streamable HTTP need no bridge — point them at/servers/<server_id>/mcp/directly. For stdio clients such as Claude Desktop, use FastMCP's bridge (uvx fastmcp-remote); seedocs/docs/using/clients/for per-client configuration. (#6201) invoke_toolnow enforces input-schema validation (#6443) - Live tool invocation (tools/call) now validatesargumentsagainst the tool'sinput_schemabefore dispatch, raisingToolInvocationErroron a mismatch, via the same_validate_tool_input_argumentscheckPOST /tools/preview/{name}uses (#5629). Previouslyinvoke_toolnever checkedargumentsagainstinput_schemaat all, so a tool whose callers relied on that gap will now reject calls it previously accepted. To find affected callers before enabling, preview the same arguments againstPOST /tools/preview/{name}: avalidated: falseresponse with aninvalid_argumentswarning is exactly what live invocation will now reject. Remediate by correcting the caller's arguments or by relaxing the tool's publishedinput_schemato match what it actually accepts.- Tool execution failures return MCP-compliant errors (#6181) - A failed tool execution returns a protocol-conformant error result instead of the previous ad-hoc shape. Clients that parsed the old payload must read the MCP error fields.
- MCP Python SDK 2.x (#6868) - The gateway now requires
mcp>=2.0.0,mcp-types>=2.0.0, andcpex>=0.1.4, the first CPEX release built formcp2.x. Python consumers that import the gateway next tomcp1.x must upgrade. Protocol behaviour is unchanged by default:MCP_CLIENT_CONNECT_MODEandMCP_INBOUND_PROTOCOL_MODEboth default tolegacy, andGATEWAY_MODERN_LISTENERS_ENABLEDdefaults tofalse. Set them toautoandtrueto negotiate the 2026-07-28 revision.
Fixed
Security & Auth
- CORS origin reflection requires an explicit allowlist in every environment - In
developmentandstaging, an emptyALLOWED_ORIGINSmadeSecurityHeadersMiddlewarereflect any requestOriginand sendAccess-Control-Allow-Credentials: true. A malicious site could then read credentialed responses cross-origin. The middleware now reflects only origins listed inALLOWED_ORIGINS. Deployments that set an emptyALLOWED_ORIGINSin non-production and rely on cross-origin access must list each origin explicitly. (#6941) - Catalog registration ownership and visibility - Catalog registrations now default to private, attribute ownership to the authenticated caller, enforce token/team scope, and preserve ownership during gateway transfer and user deletion (#6036).
- OAuth token scope resolution fails closed for indeterminate state - Admin users with missing or malformed
token_teamsstate and no cached JWT payload now fail closed to public-only scope ([]/403) instead of receiving unrestricted admin bypass (None). This prevents indeterminate scope from being silently promoted to unrestricted access (#5980). (#6004) - Schema validation no longer resolves remote
$refs (#6443) - Tool input/output schemas are tool-controlled data, andjsonschema's default registry resolves remote$refURIs by fetching them over the network, which is reachable from tool preview and from every live invocation with an output schema. Non-local references are now refused outright, and validators are built against a registry that never retrieves, so an unresolvable reference fails validation closed instead of issuing a request. - SSO cross-provider relink misconfiguration and admin carryover (#6616) - Cross-provider sign-in for an already-linked email is now gated behind an explicit, fail-closed
SSO_ALLOW_PROVIDER_LINKINGsetting (defaultfalse) instead of an always-on, misleadingly-logged auto-link (#6431). When linking is enabled, relinking re-vets admin status against the new provider and demotes regardless of how admin was originally granted (api, manual, orsso), closing a privilege-carryover path where a manually-granted admin could relink to a provider that never vets for admin and silently keep*permissions. The refuse-path log message wording changed from "account-linking required" to "login refused"; update any log-based alerting that matched the old string. - Stored XSS on SSO and SIEM surfaces (#6615) - Hardened SSO and SIEM rendering against stored cross-site scripting (#5856).
- Dict-shaped SSO groups and roles claims (#6427) - SSO normalization flattens
groupsandrolesclaims delivered as objects instead of dropping them. - IBM Verify group mapping (#6610) - Implemented
IBM_VERIFY_GROUP_MAPPING, so IBM Verify groups map onto teams. - Forced password change with a custom admin password (#6717) - Bootstrap skips the forced password-change flag when
PLATFORM_ADMIN_PASSWORDis explicitly configured. - Tenant isolation for the tool lookup cache (#6968) - Tool lookups are cached per tenant scope, so one tenant's entry can no longer satisfy another tenant's lookup.
- Outbound spec fetching (#6933) - Spec retrieval uses the shared HTTP client with a bounded cache, DNS pinning against rebinding, and single-flight deduplication of concurrent fetches.
Gateway, Catalog & Tools
- Upstream list pagination (#6809) - Tool, prompt, resource, and resource-template discovery follows
nextCursoruntil the server stops returning one, with repeated-cursor protection, instead of importing only the first page. - Large REST response truncation (#6200) - REST tool responses, including non-JSON bodies and JSON parse errors, are bounded by
REST_RESPONSE_TEXT_MAX_LENGTHon every path rather than only on the JSON error path. - Empty resource content versus fetch failure (#6705) - An upstream fetch failure is no longer reported as an empty resource body.
- Catalog OAuth credential persistence on registration (#6588) - OAuth credentials submitted with a catalog server registration now persist onto the created gateway's
oauth_configin the same call, and "OAuth2.1 & API Key" catalog entries registered with no API key skip the doomed connection test instead of failing registration (#5967).requires_oauth_configno longer clears just becauseoauth_configis set - it now means "disabled OAuth gateway", so a previously-authorized OAuth gateway that was manually disabled (credential rotation, maintenance) now shows the "OAuth Config Required" card instead of "Already Registered". Display-only; no data or access is lost. - Catalog discovery with empty MCP capabilities (#6758) - Servers that advertise no capabilities are still discovered instead of being skipped.
auth_typespelling drift inmcp-catalog.yml(#6795) - Normalised inconsistentauth_typevalues in the bundled catalog.- Health-check failure reason (#6368) - Gateway health checks persist the failure reason, so the cause survives past the check.
- Async gateway audit sessions (#6455) - Gateway audit logging uses its own session, matching the separate-session audit pattern.
- Empty
structuredContentdicts (#6182) - An empty dict instructuredContentis preserved instead of being coerced away. - CPEX deny-path control telemetry (#6806) - Deny-path control telemetry is persisted instead of dropped.
Admin UI & Catalog Assets
- Object types in
anyOf/oneOfschemas (#6421) - The schema-driven form renders object branches ofanyOfandoneOfinstead of failing. - Catalog icon weight (#6852) - Normalized icon visual weight and stripped pale badge surrounds.
Build, CI & Dependencies
- OCP PGO on fresh clusters (#6196) - Fixed Helm OCP PGO deployment failures on clusters with no prior install.
package-lock.jsonmutation during local dev (#6782) -make devandmake serveno longer rewritepackage-lock.json.- Rust dependency advisories (#6831) - Upgraded
rustlsto 0.23.45 andchacha20to 0.10.2. - OCI image version label - The image
versionlabel reports 1.0.11 and is tracked by bumpversion, so it no longer drifts from the package version.
Documentation
- IBM Cloud Code Engine deployment guide (#6290) - Added the missing env secret to the deployment steps.
- ADR-025 and altk references (#6788) - Corrected package and image references.
- Agent prose and clean code standards (#6803) - Adopted the ASD-STE100 prose rules and clean code standards for agent-authored content.
- API-to-product vocabulary mapping (#6770) - Documented how API
gatewayandservermap to the product terms "MCP server" and "virtual server". - Release documentation (#6764) - Updated the release process documentation.
- MkDocs math rendering - Updated the
pymdownx.arithmatexformat functions for pymdownx 12.x.
Testing
- Consolidated live MCP E2E suites (#6786) - Merged the overlapping live MCP suites into one.
- Lifecycle coverage in the live E2E suite - Added virtual server (#6792), user (#6833), token (#6838), team (#6844), and gateway registration with tool sync (#6848) coverage.
- Cross-replica consistency (#6804) - Verified E2E behaviour across replicas.
- RBAC deny tests (#6874) - Fixed deny-path tests that swallowed
AssertionErrorand therefore always passed. - Playwright suite repair (#6572) - Fixed broken Playwright tests.
- Vault A2A tool test argument (#6967) - Corrected the tool argument name in the vault A2A-wrapped MCP tool test.
- External IdP integration tests (#6797) - Allowed real DNS passthrough, so external IdP integration tests resolve providers.
ephemeral_gatewayfixture collision -TestGatewayLifecycleno longer fails with a 409 when the fixture gateway is already registered.
Chores
| PR | Description |
|---|---|
| #6718 | align the publisher schema with the dataplane API |
| #6763 | update the Mend configuration |
| #6791 | pin cpex to 0.1.3
|
| #6801 | align CI coverage thresholds to 90% to match the Makefile |
| #6512 | run legacy-to-legacy conformance with verified baselines |
| #6851 | preserve colors in conformance output |
Release preparation bumped every version reference to 1.0.11 and refreshed Python, Node.js, and Rust dependencies.