Skip to content

Release/1.1.0 - #7264

Merged
Lang-Akshay merged 39 commits into
mainfrom
release/1.1.0
Oct 20, 2026
Merged

Lang-Akshay merged 39 commits into
mainfrom
release/1.1.0

Conversation

@prakhar-singh1928

@prakhar-singh1928 prakhar-singh1928 commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

[1.1.0] - 2026-10-19 - Modern MCP Protocol, Federated Completions, and Catalog Pagination

Overview

Release 1.1.0 delivers modern MCP protocol negotiation on by default, federated completions, MCP catalog pagination, MCP Origin/Host transport security enforcement, federated gateway tool-name collision detection, and configuration import ownership enforcement. It also removes deprecated anyio monkey-patch settings and the in-tree mcp-servers/ directory. This release consolidates 69 PRs across:

  • Protocol & Transport - MCP_CLIENT_CONNECT_MODE and MCP_INBOUND_PROTOCOL_MODE now default to auto, inbound MCP era negotiation is complete, completion/complete is forwarded to the owning upstream, downstream MCP catalog lists are paginated, and federated resource names carry the gateway name as a prefix.
  • Security & Auth - Added private_key_jwt token endpoint client authentication, MCP Origin/Host enforcement, configuration import ownership enforcement, call-time URL scheme allowlisting, DCR outbound request pinning, and external IdP token fallback on all auth paths.
  • API & Platform - Added named A2A response models, the invitee invitations API, passwordless SSO user provisioning, per-user MCP server rate limiting, and success and error counts in the metrics timeseries.
  • Operations - Added make container-bump-image-versions, moved CSS linting from Stylelint to Biome, migrated Tailwind CSS to v4, removed the anyio monkey-patch settings, the Rust MCP config surface, and the in-tree mcp-servers/ directory.
  • Testing - Eliminated pytest warnings and redundant tests, restored OAuth gateway membership coverage, verified resource template federation, and fixed the live-gateway E2E suite.

Added

Protocol & Transport

  • Modern MCP protocol negotiation is on by default (#7061) - MCP_CLIENT_CONNECT_MODE and MCP_INBOUND_PROTOCOL_MODE now default to auto instead of legacy. Outbound upstream connections probe server/discover and negotiate the 2026-07-28 revision, with transparent fallback to the legacy initialize handshake. Inbound clients may send mcp-protocol-version: 2026-07-28 instead of receiving a 400. Set either variable to legacy to restore the previous behaviour.

  • Inbound MCP era negotiation (#7156) - Completed inbound MCP era negotiation.

  • Federated completions (#6629, #6760) - Forward completion/complete to the owning upstream with request metadata. Both legacy and modern MCP connections remain supported through existing negotiation settings; forwarding has no modern-only gate.

  • Streamable HTTP serverInfo stamping (#6566, #7145) - The streamable HTTP server is configured with the app name and version for serverInfo.

  • Federated resource names prefixed with gateway names (#6780) - Federated resource names carry the owning gateway's name as a prefix.

  • structuredContent accepts any JSON value for 2026-era callers (#7244) - Tool results on the 2026-07-28 wire now accept any JSON value (string, number, array, null, or object) as structuredContent. The 2025 wire is unchanged: non-object values are stripped and the text copy in content is used instead.

  • Federated gateway tool-name collisions (#6534) - Gateway registration, refresh, OAuth discovery, reactivation, rename, and visibility updates now reject detected tool-name collisions in public, team, and private visibility scopes. Gateway automation must handle the endpoint's conflict response when a previously accepted colliding registration is rejected. Existing duplicate rows require administrator review before affected invocation names are usable. Operators can identify duplicates with:

    SELECT name, COUNT(*) AS duplicate_count FROM tools WHERE visibility = 'public' GROUP BY name HAVING COUNT(*) > 1 ORDER BY name;
    SELECT team_id, name, COUNT(*) AS duplicate_count FROM tools WHERE visibility = 'team' GROUP BY team_id, name HAVING COUNT(*) > 1 ORDER BY team_id, name;
    SELECT owner_email, name, COUNT(*) AS duplicate_count FROM tools WHERE visibility = 'private' GROUP BY owner_email, name HAVING COUNT(*) > 1 ORDER BY owner_email, name;

API & Platform

  • Named response models for A2A routes (#6820, #6699) - Added named response models for POST /v1/a2a/{agent_name}/invoke, POST /v1/a2a/invoke, and POST /v1/a2a/{agent_name}/jsonrpc. The OpenAPI schema now exposes typed components while preserving the routes' passthrough behavior.
  • Invitee invitations API (#6960) - Added an API for invitee invitations.
  • Per-user MCP server rate limiting (#7191) - Adopted per-user rate limiting for MCP servers.
  • Metrics timeseries counts (#7138) - The observability metrics timeseries returns success and error counts.

Security & Auth

  • private_key_jwt token endpoint client authentication (#6991) - OAuth token requests can authenticate with RFC 7523 private_key_jwt.
  • Passwordless SSO user provisioning (#6692, #7180, #7219) - Added a passwordless SSO user provisioning service and its API. feat: add feature-gated SSO user provisioning API #7180 gated the API behind a feature flag. feat: remove the SSO user provisioning API flag #7219 removes that flag.
  • JWT lifecycle clarification after database reset - Local JWTs remain cryptographically valid when database storage is lost but the signing key remains unchanged. Database cleanup is not credential rotation. Destructive resets must rotate JWT_SECRET_KEY when old-token invalidation is required. Persistent database storage and short-lived local tokens remain recommended for production deployments.

Operations & Tooling

  • Container image version bumper (#5811) - Added make container-bump-image-versions to bump container image version pins.
  • CSS linting moves from Stylelint to Biome (#7162) - make lint-web and the lint-web CI job now lint mcpgateway/static/*.css with Biome, configured in biome.json. The CI matrix entry is renamed from stylelint to biome-css. Stylelint and its configs leave the dev dependencies, which removes the braces advisory (GHSA-vfj7-8cjw-p6xm) from npm audit.
  • make testing-up web UI URL (#6415) - The startup summary now shows a ContextForge Web UI row whose port comes from the resolved Compose configuration. The printed URL now matches the port Compose publishes when WEB_UI_PORT is set only in .env. Resolution failure stops the target instead of printing a fallback URL.
  • Pinned-resource load test (#6984) - Added a pinned-resource performance benchmark stack and run history to the load test suite.
  • mcp-servers/ directory removed (#7078) - The unsupported sample/test MCP servers, the Go/Python scaffolding templates, and the mcp-url-to-markdown-tests workflow leave the repository. The six Python servers now live in IBM/contextforge-examples under mcp-servers/python/; the scaffolding templates are deleted without migration. The performance compose generator and benchmark docs now use the published ghcr.io/ibm/cfex-mcp-fast-time-server and ghcr.io/ibm/cfex-mcp-benchmark-server images. The /v1/mcp-servers REST API is unchanged: it remains the product-language alias for the gateways API.

Breaking Changes

  • Downstream MCP catalog pagination (#6990, #7171) — Python MCP lists now return at most MCP_LIST_PAGE_SIZE=100 items by default. Clients that ignore nextCursor receive only the first page. Database order changes from created_at DESC to id ASC. Server-scoped lists exclude other users' private rows for unrestricted administrators; administrators retain their own private rows. Multi-page direct-proxy lists now require Redis. Share AUTH_ENCRYPTION_SECRET across workers and keep traversals on one version during deployment. Restart traversals after reconnect, rotation, or rollback. Rust tools lists remain complete until the bridge forwards client cursors. This change delivers part of [BUG]: Add downstream pagination for MCP list methods #6990. See pagination configuration.
  • Completion authorization (#6760) - POST /protocol/completion/complete now requires tools.read RBAC permission. Previously, authentication alone passed this endpoint's authorization check. Before upgrading from 1.0.11, grant tools.read to completion callers' roles and include it in replacement tokens with explicit permission scopes. Denied callers receive HTTP 403 before upstream access. See completion permission migration.
  • Experimental anyio cancellation monkey-patch removed (#5427) - Removed the opt-in ANYIO_CANCEL_DELIVERY_PATCH_ENABLED and ANYIO_CANCEL_DELIVERY_MAX_ITERATIONS workaround from mcpgateway/transports/sse_transport.py, together with the SSE_TASK_GROUP_CLEANUP_TIMEOUT setting. The gateway now requires anyio>=4.15.0, which fixes the _deliver_cancellation CPU spin loop upstream (anyio issues #695 and #1111). Unknown environment keys are ignored, so existing deployments start without changes. Remove the retired variables from your configuration to keep it accurate. The matching Helm values and docker-compose entries are also removed. Dangling MCP_SESSION_POOL_CLEANUP_TIMEOUT references, which no code path ever read, are removed from docker-compose, the Helm chart, and .env.example. SSE connection protection and cleanup timeouts remain the containment strategy; see docs/docs/operations/cpu-spin-loop-mitigation.md.
  • Rust MCP config surface removed (#7255, #6177) - Removed the Rust MCP configuration surface (closes Remove Rust runtime config surface (experimental_rust_mcp_* settings, entrypoint, .env.example) #5819) and the Python Rust-runtime proxy integration (closes Remove Python Rust-runtime proxy integration (proxies, runtime_state, runtime-admin router) #5818), together with the remaining Rust MCP references in the Makefile, docs, and comments.
  • x-mcp-header annotation validation on tool registration (#6773) - POST /tools (create) and PUT /tools/{id} (update) now validate x-mcp-header annotations in input_schema against the MCP 2026-07-28 constraints. Payloads with invalid annotations are rejected with HTTP 422. Previously these passed validation silently. Update any tool registration payload that uses non-conforming x-mcp-header values before upgrading.

Security

  • Configuration import ownership enforcement (#7243) - POST /v1/import with conflict_strategy=update no longer overwrites tools, resources, prompts, or gateways that the importer does not own. Bulk registration now runs check_resource_ownership() before it modifies an existing row and reports Permission denied for rows the caller does not own. Bulk update without a caller identity changes nothing. The import call to update_gateway() now passes the importer identity. The admin.import routes use global_only=True, so a team-scoped role no longer satisfies them. The Admin UI import now passes the authenticated email as imported_by. Deployments that grant admin.import through a team-scoped role must move that grant to a global role.
  • MCP Origin/Host enforcement (#6875) - Implements MCP 2025-11-25 §transport-security: a present-but-unlisted Origin header on /mcp is now rejected with HTTP 403. Set MCP_ALLOWED_ORIGINS to a comma-separated list of allowed origins to enable enforcement (default: empty, backward-compatible). An optional companion setting MCP_ALLOWED_HOSTS enforces exact host:port matching on the Host header. Enforcement runs at the public /mcp mount via MCPOriginHostGate, covering the Python ingress path.
  • A2A plugin header trust (#7157) - A2A pre-invoke plugins can supply credentials and custom headers without the agent caller-header allowlist. Plugin output now overrides configured agent authentication, and an empty Authorization value suppresses all fallback authorization. The gateway retains inbound caller filtering, sanitizes plugin input, resolves output case-insensitively, and strips X-Vault-Tokens before egress.
  • Outbound request validation in the DCR path (#6961) - Dynamic client registration validates and pins outbound requests.
  • Rate limit tier matching for /v1 paths (#6879) - Rate limit tier matching normalizes /v1 paths.
  • URL scheme allowlist at call time (#6881) - The gateway enforces the URL scheme allowlist at call time and scans the database on startup.
  • JSON Schema pattern evaluation (#6957) - The gateway bounds JSON Schema pattern evaluation in a worker process.
  • Outbound HTTP connection handling (#6965) - Hardened outbound HTTP connection handling. Outbound URL validation runs even when SSRF_PROTECTION_ENABLED=false. Dangerous-protocol, control-character, embedded-credential, and XSS checks apply unconditionally. A deployment that relied on the old side effect to reach a non-HTTP(S) URL will see it rejected. Pooled upstream MCP sessions no longer follow HTTP redirects. An upstream that answers /sse with a 307 redirect to /sse/ fails instead of following it; register the redirected URL directly. Connection setup fails closed when a caller-supplied HTTP client's TLS context cannot be read. Some outbound requests connect to a single validated address; a dual-stack upstream whose first-sorted address is unreachable can fail. Requests to a validated address use a dedicated connection pool. Behavior is unchanged when an environment proxy (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY) applies to the target.
  • Candidate credential handshakes (#6877) - Candidate credential handshakes are isolated.
  • Virtual-server scoped tool invocation (#6672) - Hardened virtual-server scoped tool invocation.
  • Token scoping for plugin-binding and completion routes (#6709) - Token scoping maps plugin-binding routes. Token scoping maps the completion route to tools.read.
  • Input validation and output escaping tightening (#7076) - Tightened input validation and output escaping across gateway paths. ADR-056 CSP hardening applies.
  • Result body HTML escaping (#7239) - escapeHtml is applied to the tool result body before rendering, preventing stored XSS in result output.
  • DCR outbound request pinning (#7081) - Dynamic client registration pins outbound requests to the validated endpoint address.

Fixed

Auth & OAuth

  • Email claim for generic OIDC providers (#6484) - SSO resolves an email claim for generic OIDC providers.
  • External-IdP verification in get_current_user() (#6424, #7049) - External-IdP verification is wired into get_current_user(), and all auth paths fall back to external IdP tokens.
  • private_key_jwt follow-ups (#7190) - Restored private_key_jwt follow-ups dropped from feat(oauth): add private_key_jwt token endpoint client authentication #6991.
  • OAuth token handling (#7240) - Improved OAuth token handling.
  • OAuth gateway catalog on empty fetch (#6049) - The gateway preserves its catalog when an OAuth fetch returns empty.

Gateway, Catalog & Tools

  • Frontend email routes (#6953) - Invitation and password emails include the React /app mount prefix. UI_BASE_URL accepts a deployment base or a full frontend root ending in /app. Full roots produce a startup warning and have only the final mount segment removed during normalization. For a deployment prefix /contextforge/app, set the full root https://ui.example.com/contextforge/app/app to preserve both segments in emailed links. The invitation frontend route remains tracked by [BUG]: Invitation emails link to /accept-invitation #6776.
  • Modern MCP clients no longer see the deprecated logging capability (#6630, #6631, #7030) - server/discover responses for 2026-07-28 clients now omit capabilities.logging. MCP 2026-07-28 deprecates that capability (SEP-2577), and ContextForge sends no request-scoped log messages. Clients on 2025-11-25 and older still receive the capability and can call logging/setLevel. Use OpenTelemetry and structured logging for gateway observability. Modern clients reach the gateway only when MCP_INBOUND_PROTOCOL_MODE=auto; docker-compose.yml now passes that variable to the gateway, with a legacy default.
  • Session-affinity worker ID (#6688) - The gateway computes the session-affinity worker ID from the live PID after fork.
  • Refresh throttle anchor (#7130) - The refresh throttle anchors to cycle_started_at, so the gateway no longer skips refreshes.
  • Gateway URL rejection messages (#7096) - Gateway URL rejections name the cause. Fixed CA signing status.
  • Oversize _meta (#7259) - The gateway rejects oversize _meta with -32602 and keeps the upstream resource error.
  • psutil.cpu_freq() on macOS (#7087) - Guarded psutil.cpu_freq() against SystemError.
  • Tool error translation (#7169) - Upstream JSON-RPC error codes are preserved in tool results. The error code is reported under _meta["io.contextforge/errorCode"] and the result retains the isError shape. Previously the code was lost and the SDK made up a transport-level code. Clients that rely on a specific error code from the gateway's own fallback will see the upstream code instead.
  • Prompt error translation (#7204) - Prompt calls that fail with missing required arguments return -32602 (INVALID_PARAMS). Upstream JSON-RPC errors are relayed with their original code and sanitized data. Previously the shape and code varied across failure paths.
  • Error response format standardization (#7079) - JSON-RPC error response bodies are now formatted consistently across all gateway paths using a shared ErrorFormatter. Clients that parsed the raw detail or message field of error responses may need to update their parsers.

Observability & A2A

  • W3C trace context in A2A invocations (#7093) - A2A invocations propagate W3C trace context.
  • Tenantless background spans (#7155) - OpenTelemetry suppresses tenantless background spans.

Admin UI

  • Admin UI edit modals (#7271) - Table rows stay in the innerHTML guard. Edit modals use delegated handlers.

Build, CI & Dependencies

  • OS package refresh before Docker security scans (#7186) - CI refreshes OS packages before Docker security scans.
  • Checkov skip placement - Moved the checkov skip off the nginx FROM line.

Changed

  • Duplicate Gateway.last_seen annotation removed (#6682) - Removed the duplicate model annotation.

Documentation

  • Container image version bumping (#7137) - Replaced the manual UBI tag steps with make container-bump-image-versions.
  • Deprecation lifecycle (#6996) - Adopted the MCP-style deprecation lifecycle and recorded the deprecation backlog.

Testing

  • Pytest warnings and redundant tests (#6895) - Eliminated pytest warnings, dead test code, and redundant auth tests.
  • Resource template federation (#6962) - Verified resource template federation through the gateway.
  • OAuth gateway membership (#7210) - Restored OAuth gateway membership regression coverage.
  • Pre-provisioned SSO (#7183) - Validated pre-provisioned SSO authentication and documented onboarding.
  • Live-gateway E2E suite - Fixed suite ordering, error shapes, and cleanup.

Chores

PR Description
#7132 routine dependencies update - 2026-10-05
#7135 migrate Tailwind CSS v3 to v4 and fix npm CVEs
#6769 validate the Code Engine registry secret and clarify env logging
#7213 rate limit middleware updates
#7250 replace mcp-server-filesystem examples with mcp-server-fetch
#7257 routine dependency update
#7267 docker-compose.yml dual-era test configuration
#7199 follow-up to #6877
#7201 follow-up to #7157; ADR-057
#7200 follow-up to #6996

Release preparation bumped every version reference to 1.1.0, refreshed npm dependencies (12 packages updated, 0 vulnerabilities), bumped the NODEJS_IMAGE pin to 10.2-1792386062, updated uv.lock and Cargo.lock, normalised .bumpversion.cfg indentation, and removed Rust MCP leftovers from the Makefile, docs, and comments.

@prakhar-singh1928 prakhar-singh1928 changed the title chore: bump version to 1.1.0 Release/1.1.0 Oct 19, 2026
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
prakhar-singh1928 and others added 4 commits October 19, 2026 15:20
Run async e2e tests on a worker thread. The session-scoped sync
Playwright fixture leaves an event loop running on the main thread,
and pytest-asyncio then fails with "Runner.run() cannot be called
from a running event loop".

Accept both error shapes where the stateful-session /rpc path and the
SDK handler differ: unknown tool, unknown prompt, ReDoS rejection,
array structuredContent for legacy callers, and template read URIs.

Delete the private tenant gateways with the tenant context that
created them. The admin context got 404, so the gateways leaked and
blocked the fast_time registration on the next stack start.

Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Signed-off-by: Brian Hussey <brian.hussey@ie.ibm.com>
Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>

@msureshkumar88 msureshkumar88 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of release/1.1.0 (head f39cb8a)

The version bump is consistent at 1.1.0 across .bumpversion.cfg, pyproject.toml, Cargo.toml, Cargo.lock, uv.lock, the Helm chart, Containerfile and SECURITY.md. The 1.0.11 to 1.1.0 upgrade works: one Alembic head, upgrade, downgrade and re-upgrade pass, and the app starts on the upgraded database. The unit suite, ruff, interrogate, secrets scan and Rust checks pass. The release date fix in f39cb8a is correct.

The release changes consumer contracts that the CHANGELOG does not describe. Those gaps block the merge. Each finding below uses the format severity | path:line | problem | fix.

Blocking

blocking | CHANGELOG.md [1.1.0] Breaking Changes | The Rust MCP runtime integration is removed (#6177, #7255) with no entry. Removed: GET/PATCH /admin/runtime/mcp-mode and /admin/runtime/a2a-mode, the /_internal/mcp/transport mount, the Admin UI "MCP Runtime" cards, EXPERIMENTAL_RUST_MCP_*, MCP_RUST_*, RUST_MCP_MODE, RUST_MCP_BUILD, RUST_MCP_LOG, RUST_MCP_SESSION_AUTH_REUSE, ENABLE_RUST_MCP_RMCP_BUILD, and the compose build args ENABLE_RUST and ENABLE_RUST_MCP_RMCP. | Add a Breaking Changes entry that lists the removed endpoints and variables. State the migration: use the Python transport.

blocking | CHANGELOG.md [1.1.0] Breaking Changes | Federated resource names now get the gateway slug prefix (#6780). Migration c7e91a2b4d60 adds resources.original_name and resources.custom_name_slug and rewrites resources.name for every gateway-owned row. Names change on upgrade, on refresh and on gateway rename. An upgrade test turned "Report Final" into my-upstream-gw-report-final. The CHANGELOG has no entry. | Add a Breaking Changes entry. Cover the name change, the two new columns, the migration, the downgrade behavior (restores upstream names, discards manual base overrides), the new custom_name update field, and that URIs do not change.

blocking | CHANGELOG.md [1.1.0] | EXPOSE_ERROR_DETAILS is now deprecated and ignored, and error responses are always sanitized (#7079). The CHANGELOG has no entry. | Document the ignored variable and the new error body shape. Verify the body shape against the diff first.

blocking | mcpgateway/middleware/token_scoping.py (_PERMISSION_PATTERNS), CHANGELOG.md:21 | /protocol/completion/complete has no entry in _PERMISSION_PATTERNS. A direct call to _check_permission_restrictions('/protocol/completion/complete', 'POST', ['tools.read']) returns False. Default-deny then rejects a scoped token that includes tools.read. The CHANGELOG migration note tells operators to issue exactly such a token. Evidence missing: I did not exercise the full middleware stack. | Add ("POST", r"^/protocol/completion/complete", Permissions.TOOLS_READ), or correct the migration note. Add a test with a token scoped to tools.read only. Add a deny-path test for a token without it.

blocking | PR description | The description is the empty template. It has no summary, no linked issues and no breaking-change list. | Fill in the template. List the breaking changes and the verification commands with real results.

Functionally impacting

functionally-impacting | CHANGELOG.md:5-7 | The Deprecation Notice says the Rust MCP and A2A sidecars and ValidationMiddleware "will sunset on 2026-07-07". That date is past, and the Rust MCP integration is now removed. | Rewrite the notice to match the current state. Check whether the A2A runtime and ValidationMiddleware are removed before you write it.

functionally-impacting | CHANGELOG.md:52 | The Origin/Host entry says enforcement covers "all ingress modes (Python, rust-internal, rust-public)" and that the /_internal/mcp/transport bridge is exempt. The Rust ingresses and that bridge no longer exist. | Reword the entry to the public /mcp mount only. Remove the bridge sentence. Fix the matching comments in streamablehttp_transport.py.

functionally-impacting | CHANGELOG.md:19 | The pagination entry says "Rust tools lists remain complete until the bridge forwards client cursors". The Rust bridge is removed. | Delete the sentence.

functionally-impacting | CHANGELOG.md:60 | The logging-capability entry says docker-compose passes MCP_INBOUND_PROTOCOL_MODE "with a legacy default". docker-compose.yml:171 defaults to auto, as do config.py and .env.example. | Change legacy to auto.

functionally-impacting | CHANGELOG.md:46 | The entry says the mcp-servers/ directory is removed. mcp-servers/python/completion_test_server/ is still tracked, and docker-compose uses it. | Reword to "removed except completion_test_server", or remove the leftover.

functionally-impacting | CHANGELOG.md [1.1.0] Added and Security | These merged changes have no entry. Check each against the code before you write it:

  • Regex sandbox for JSON Schema pattern (#6957): REGEX_TIMEOUT_SECONDS, REGEX_WORKERS, REGEX_MAX_SUBJECT_BYTES, fails closed.
  • URL scheme enforcement (#6881): STRICT_SCHEME_ENFORCEMENT and a startup scan.
  • Security fixes: the two "Merge commit from fork" commits (6424230, 69aa591), DCR outbound validation (#6961), handshake credential isolation (#6877), outbound HTTP hardening (#6965, #7076), HTML escaping (#7239), plugin-binding token scoping (#6709), /v1 rate-limit tier path (#6879), scoped /rpc authorization (#6672).
  • Team invitations API (#6960, #6991) and OAuth private_key_jwt (#7190 and follow-ups), plus the #7240 token handling change.
  • SSO and external IdP bearer verification (#6692, #6424, #7049), SSO_API_TOKEN_AUTH_ENABLED. State the net result of #7180 and #7219.
  • MCP wire changes: tool and prompt error translation (#7204, #7169), oversized _meta rejected with -32602 (#7259), structuredContent any JSON for 2026-07-28 callers (#7244), ttlMs and cacheScope (#7181), x-mcp-header validation (#6773), serverInfo stamping (#7156), inbound era negotiation (#7145).
  • Per-user-per-server MCP rate limiting (#7191, #7213), OTel tenantless span suppression with OTEL_SYSTEM_TRACES_ENABLED (#7155), metrics timeseries counts (#7138).
  • Gateway registration failure causes and HTTP statuses (#6724, fixed by #7096).
    | Add one entry per item, or group related items. Confirm the security wording with the security owners.

Suggestions

suggestion | docs/docs/architecture/roadmap.md | The roadmap has no 1.1.0 entry. Section 1.4 of release-management.md asks for the milestone to close with the release date. | Mark the shipped themes and close milestone #24 on release day.

suggestion | Makefile:28-31, testing-up-rust* targets | The RUST_MCP_* variables and the testing-up-rust* targets stay, but the entrypoint no longer reads them. | Remove the dead targets, or document that they are no-ops.

Please update the CHANGELOG, the token scoping entry and the PR description. I will review again after the push.

The completion endpoint requires tools.read, but _PERMISSION_PATTERNS
had no entry for POST /protocol/completion/complete. Default-deny then
rejected tokens scoped to tools.read. Add the pattern and allow and
deny tests.

Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>
Remove the testing-up-rust and testing-rebuild-rust targets and the
RUST_MCP_MODE and RUST_MCP_LOG variables. The entrypoint no longer reads
them. Drop the Rust sections from the testing, compose, and performance
docs. Remove stale Rust ingress text from the Origin/Host comments and
.env.example. Note shipped pagination and completions in the roadmap.

Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>

@madhu-mohan-jaishankar madhu-mohan-jaishankar left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@msureshkumar88 msureshkumar88 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review of release/1.1.0 (head 42a06c9), CHANGELOG excluded

This pass covers the release branch except CHANGELOG.md, which #7278 tracks.

The release preparation is in good shape:

  • The version is 1.1.0 in all seven .bumpversion.cfg targets, uv.lock, Cargo.lock, the Helm values.yaml image tags, and the cedar and opa plugin pins. The two remaining 1.0.11 references (docs/docs/manage/api-usage.md:9, docs/tables/deprecations-removed.yaml:4) are historical and correct.
  • Alembic has one head, c7e91a2b4d60. The branch contains every commit on main.
  • CI: 72 checks pass, 6 skip (publish and sign jobs), none fail.
  • The earlier non-CHANGELOG findings are fixed. ae56d1f6e adds the completion route to _PERMISSION_PATTERNS with allow-path and deny-path tests. The PR description is filled in. The Origin/Host comments are reworded. The testing-up-rust* targets and RUST_MCP_* Makefile variables are gone. The roadmap records the 1.1.0 themes.
  • The #7271 Admin UI fix is correct. toggleUseDefaultMaxMembers receives (checked, event) from the change delegator, and the checkbox is inside the <form>. I sent five mXSS payloads through the new table-context wrapper in security.js (tbody break-out, svg/math namespace confusion, form nesting). No event-handler attribute survived.
  • Local runs pass: tests/unit/js/innerhtml-guard.test.js (7/7), tests/unit/mcpgateway/middleware/test_token_scoping.py, tests/unit/mcpgateway/test_version.py.

One wire-behavior bug blocks the release. Each finding uses severity | path:line | problem | fix.

Blocking

blocking | mcpgateway/transports/streamablehttp_transport.py:5279 (also :5085), mcpgateway/main.py:11562 | With USE_STATEFUL_SESSIONS=true and MCPGATEWAY_SESSION_AFFINITY_ENABLED=true, the transport dispatches a session's POST in-process to /_internal/mcp/rpc. That route sets _trusted_internal_mcp_dispatch, so tools/call skips _object_only_structured_content(). The transport then sends response.content to the client unchanged. A 2025-era client receives a non-object structuredContent, and the SDK rejects the CallToolResult ("valid dictionary"). This contradicts #7244, which keeps the 2025 wire unchanged. docker-compose.yml:398 and :406 enable both settings, so the compose deployment reaches this path. | Strip a non-object structuredContent before the transport sends the response to a legacy session. Alternatively, skip the strip in main.py only when the originating caller is modern. Restore the strict e2e assertion in the same change.

Functionally impacting

functionally-impacting | tests/live_gateway/e2e/test_e2e.py:1048 | The legacy structuredContent test now catches the client validation error and returns early, so it passes on the bug above. | Remove the except branch after the fix. Assert that the legacy client receives an object-only result with the value in a text block.

functionally-impacting | tests/live_gateway/e2e/test_e2e.py:824, :914, :5067 | The suite now accepts two wire behaviors that depend on the session path. Unknown tool: an isError result or JSON-RPC -32601. Unknown prompt: -32602 "Unknown prompt:" or -32002 "Prompt not found:". Bounded regex rejection: an isError result or -32603. One client gets different errors when stateful affinity is on. | Align the /rpc path with the SDK path, or document the difference as a known 1.1.0 limitation and track it in an issue.

functionally-impacting | docs/tables/deprecations-pending.yaml:13-23 | The "Rust MCP runtime sidecar" row says "Code remains: RUST_MCP_MODE, … and the transport proxies". #6177 and #7255 remove that integration. | Move the row to docs/tables/deprecations-removed.yaml with Removed: "1.1.0 (<release date>)".

Suggestions

suggestion | docs/docs/architecture/rust-mcp-runtime.md:24-68, :417; docs/docs/architecture/.pages:7 | The page is still in the docs navigation. It presents RUST_MCP_MODE as the operator control and lists the deleted testing-rebuild-rust* targets. | Remove the page from the navigation, or add a "removed in 1.1.0" notice at the top.

suggestion | crates/mcp_runtime/README.md, DEVELOPING.md, RELEASE-CHECKLIST.md, STATUS.md | These files reference the deleted testing-up-rust* and testing-rebuild-rust* targets. | Remove the references, or point them to the crate's standalone cargo workflow.

Minor

minor | AGENTS.md:530, tests/live_gateway/mcp/test_completion_federation.py:22, tests/live_gateway/e2e/test_e2e.py:144 | These lines still set RUST_MCP_MODE= or RUST_MCP_MODE=off. No code reads that variable. | Remove the variable from these lines.

minor | milestone v1.1.0 (#24) | The milestone is open with zero open issues. | Close it on release day, per release-management.md section 1.4.

Fix the blocking finding, or add a documented waiver to this PR. I will review again after the push.

@Lang-Akshay

Copy link
Copy Markdown
Collaborator

For the mention blocking issue @msureshkumar88
I am aware of this issue and it is tracked here - 7131

@madhu-mohan-jaishankar

madhu-mohan-jaishankar commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

@msureshkumar88 on functionally impacting 2, tool error shape and prompt error shape will differ and its expected. prompts don't have isError at all whereas for tools, isError is needed for plugins and for clients to get the uniform error shapes in both eras.

Signed-off-by: Vishu Bhatnagar <vishu.bhatnagar@ibm.com>
Signed-off-by: Vishu Bhatnagar <vishu.bhatnagar@ibm.com>
Signed-off-by: Vishu Bhatnagar <vishu.bhatnagar@ibm.com>
Signed-off-by: Vishu Bhatnagar <vishu.bhatnagar@ibm.com>
Signed-off-by: Vishu Bhatnagar <vishu.bhatnagar@ibm.com>
Signed-off-by: Vishu Bhatnagar <vishu.bhatnagar@ibm.com>
Signed-off-by: Vishu Bhatnagar <vishu.bhatnagar@ibm.com>

@msureshkumar88 msureshkumar88 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up review of release/1.1.0 (head 42a06c9)

Thank you for the replies. No commits have landed since the last review, so the findings below are still open at 42a06c9e9. The fixes confirmed in the last pass stay confirmed: the completion route in _PERMISSION_PATTERNS with tests, the PR description, the Origin/Host comments, the Makefile Rust targets and the roadmap entry.

Replies

#7131 as tracking for the blocking finding. #7131 does not cover this bug. It tracks upstream calls without Mcp-Session-Id that open a new transport per call, which is a connection-pooling topic. It does not mention structuredContent, /_internal/mcp/rpc, _trusted_internal_mcp_dispatch or #7244. Its last edit is 2026-10-05. The blocking finding needs a fix, or a waiver that links an issue for this exact bug.

Tool and prompt error shapes. I agree that prompts and tools have different error shapes. Prompts have no isError, and tools need it for plugins. The finding is different: one call gets a different error depending on the session path. An unknown tool returns an isError result on the SDK path and JSON-RPC -32601 on the stateful /rpc path. An unknown prompt returns -32602 "Unknown prompt:" on one path and -32002 "Prompt not found:" on the other. A bounded regex rejection returns an isError result on one path and -32603 on the other. The finding stays open.

Each finding uses severity | path:line | problem | fix.

Blocking

blocking | mcpgateway/transports/streamablehttp_transport.py:5279 (also :5085), mcpgateway/main.py:11561, :11776 | main.py skips _object_only_structured_content() for a trusted internal dispatch. The comment says the originating worker keeps the value. The transport does not strip it: it sends response.content from post_rpc_in_process() to the client unchanged. A 2025-era client on a stateful affinity session receives a non-object structuredContent and rejects the CallToolResult. docker-compose.yml:398 and :406 enable this path. | Apply _object_only_structured_content() to the JSON-RPC result in the transport before send(), at both dispatch sites. Confirm that only 2025-era sessions reach this path. Alternatively, remove the _trusted_internal_mcp_dispatch guard in main.py; the Rust runtime was the other internal caller and is removed. For a waiver instead, open an issue for this bug and list it in the PR description as a known 1.1.0 limitation.

blocking | CHANGELOG.md [1.1.0] Breaking Changes, "Rust MCP config surface removed" | The entry does not list what operators lose. | List the removed endpoints (GET/PATCH /admin/runtime/mcp-mode, /admin/runtime/a2a-mode, the /_internal/mcp/transport mount), the removed variables (EXPERIMENTAL_RUST_MCP_*, MCP_RUST_*, RUST_MCP_MODE, RUST_MCP_BUILD, RUST_MCP_LOG, RUST_MCP_SESSION_AUTH_REUSE, ENABLE_RUST_MCP_RMCP_BUILD) and the compose build args ENABLE_RUST and ENABLE_RUST_MCP_RMCP. State the migration: use the Python transport.

blocking | CHANGELOG.md [1.1.0] | #6780 is listed under Added only. Migration c7e91a2b4d60 rewrites resources.name for every gateway-owned row and adds original_name and custom_name_slug. | Add a Breaking Changes entry. Cover the name change on upgrade, refresh and gateway rename, the two columns, the downgrade behavior, the custom_name update field, and that URIs do not change.

blocking | CHANGELOG.md [1.1.0] | #7079 has no entry. EXPOSE_ERROR_DETAILS is deprecated and ignored, and error responses are always sanitized. | Add an entry for the ignored variable and the new error body shape.

Functionally impacting

functionally-impacting | tests/live_gateway/e2e/test_e2e.py:1046-1053 | The legacy structuredContent test catches the client validation error and returns early. It passes on the blocking bug. | Remove the except branch with the fix. Assert structured_content is None and that the text block carries [1, 2, 3].

functionally-impacting | tests/live_gateway/e2e/test_e2e.py:824, :914, :5067 | The error shape for one call depends on the session path (see Replies). | Align the /rpc path with the SDK path. Alternatively, document the difference as a known 1.1.0 limitation and track it in an issue.

functionally-impacting | docs/tables/deprecations-pending.yaml:13-23 | The "Rust MCP runtime sidecar" row is still pending. #6177 and #7255 remove that integration. | Move the row to docs/tables/deprecations-removed.yaml with Removed: "1.1.0 (2026-10-19)".

functionally-impacting | CHANGELOG.md:7 | The Deprecation Notice says the Rust sidecars and ValidationMiddleware "will sunset on 2026-07-07". The date is past and the Rust MCP integration is removed. | Rewrite the notice to the current state.

functionally-impacting | CHANGELOG.md:64 | "Rust tools lists remain complete until the bridge forwards client cursors." The bridge is removed. | Delete the sentence.

functionally-impacting | CHANGELOG.md:100 | The entry says docker-compose passes MCP_INBOUND_PROTOCOL_MODE "with a legacy default". The default is auto. | Change legacy to auto.

functionally-impacting | CHANGELOG.md [1.1.0], mcp-servers/ entry | The entry says the directory is removed. mcp-servers/python/completion_test_server/ is still tracked and used by docker-compose. | Reword to "removed except completion_test_server".

functionally-impacting | CHANGELOG.md [1.1.0] | These items have no entry: the two "Merge commit from fork" security fixes (6424230, 69aa591); REGEX_TIMEOUT_SECONDS, REGEX_WORKERS, REGEX_MAX_SUBJECT_BYTES (#6957); STRICT_SCHEME_ENFORCEMENT (#6881); SSO_API_TOKEN_AUTH_ENABLED; OTEL_SYSTEM_TRACES_ENABLED (#7155); ttlMs and cacheScope (#7181). | Add the variables to the existing entries, or add new entries. Confirm the security wording with the security owners.

Suggestions

suggestion | docs/docs/architecture/.pages:7, docs/docs/architecture/rust-mcp-runtime.md | The page is still in the navigation with a "sunsets on 2026-07-07" banner. | Remove it from the navigation, or add a "removed in 1.1.0" notice.

suggestion | crates/mcp_runtime/README.md, DEVELOPING.md, RELEASE-CHECKLIST.md, STATUS.md | 25 references to the deleted testing-up-rust* and testing-rebuild-rust* targets remain. | Remove them, or point to the standalone cargo workflow.

Minor

minor | AGENTS.md:530, tests/live_gateway/e2e/test_e2e.py:144, tests/live_gateway/mcp/test_completion_federation.py:22 | These lines still set RUST_MCP_MODE. No code reads it. | Remove the variable.

Fix the blocking findings, or document a waiver in the PR description with a linked issue for each. I will review again after the push.

@madhu-mohan-jaishankar

Copy link
Copy Markdown
Collaborator

Thanks @msureshkumar88 for review. Regarding /rpc paths, we don't want to change anything as there is no usage. Please file an issue and we can pick it up later if needed by @jonpspri. This is not a blocking issue for this release.

chore: update web UI to v0.2.4 and document startup
msureshkumar88
msureshkumar88 previously approved these changes Oct 20, 2026

@msureshkumar88 msureshkumar88 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval of release/1.1.0 (head 67aeb44)

The maintainer reviewed the open findings and waives all of them for 1.1.0. I approve on that basis.

The release preparation is sound. The version is 1.1.0 in every bump target. Alembic has one head. CI passes. The completion route in _PERMISSION_PATTERNS has allow-path and deny-path tests. The #7271 Admin UI fix holds against the mXSS payloads I sent. The new commits since 42a06c9e9 change only web UI docs, the web UI image pin and the CHANGELOG web UI entry.

Waived for 1.1.0

/rpc path (no usage; follow-up issue to be filed):

  • Legacy structuredContent on the stateful affinity /rpc path (streamablehttp_transport.py:5279, :5085; main.py:11561, :11776)
  • The early return in the legacy structuredContent e2e test (test_e2e.py:1046-1053)
  • Session-path-dependent error shapes (test_e2e.py:824, :914, :5067)

CHANGELOG [1.1.0]:

  • The Rust removal entry (#7255, #6177) does not list the removed endpoints, variables and compose build args
  • No Breaking Changes entry for the #6780 resource name rewrite (migration c7e91a2b4d60)
  • No entry for #7079 (EXPOSE_ERROR_DETAILS ignored)
  • CHANGELOG.md:7: the 2026-07-07 sunset notice
  • "Rust tools lists remain complete until the bridge forwards client cursors"
  • "with a legacy default"; the default is auto
  • The mcp-servers/ entry does not mention completion_test_server
  • No entries for the fork security merges (6424230, 69aa591), REGEX_* (#6957), STRICT_SCHEME_ENFORCEMENT (#6881), SSO_API_TOKEN_AUTH_ENABLED, OTEL_SYSTEM_TRACES_ENABLED (#7155), ttlMs and cacheScope (#7181)

Rust deprecation records and cleanup:

  • The Rust sidecar row in docs/tables/deprecations-pending.yaml:13-23
  • docs/docs/architecture/rust-mcp-runtime.md in the navigation
  • testing-up-rust* and testing-rebuild-rust* references in crates/mcp_runtime/*.md
  • RUST_MCP_MODE in AGENTS.md:530, test_e2e.py:144, test_completion_federation.py:22

Close milestone #24 on release day. Correct the CHANGELOG items in a follow-up so the published release notes match the code.

Signed-off-by: prakhar-singh1928 <prakhar.singh1928@ibm.com>

@Lang-Akshay Lang-Akshay left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM ✅

@Lang-Akshay
Lang-Akshay added this pull request to the merge queue Oct 20, 2026
@Lang-Akshay
Lang-Akshay removed this pull request from the merge queue due to a manual request Oct 20, 2026

@brian-hussey brian-hussey left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good from my point of view.

@Lang-Akshay
Lang-Akshay added this pull request to the merge queue Oct 20, 2026
Merged via the queue into main with commit cd7e925 Oct 20, 2026
76 checks passed
@Lang-Akshay
Lang-Akshay deleted the release/1.1.0 branch October 20, 2026 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

6 participants