v1.0.11 - Release 2026-09-28 - MCP Python SDK 2.x, Tool Preview, SSO Controls, and Live E2E Coverage
LatestOverview
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.