Commit Graph

22 Commits

Author SHA1 Message Date
Teknium ceaf622c6d fix(mcp): same-named MCP servers with different credentials connect per profile; owner /reload-mcp keeps adopters' tools
Under gateway.multiplex_profiles every connection ledger in tools/mcp_tool.py
(_servers, _server_scope_keys/_server_tool_scopes, connecting/error/cooldown
maps, the circuit breaker, lazy schema-cache configs, trust metadata) was keyed
by the bare server NAME. The common per-tenant layout — each profile names its
server `github`/`notion` with its own token — gave only the first profile a
connection: the second profile's register_mcp_servers saw the name as "already
connected", refused to adopt it (different credentials, 4ddbcbd35e), and left
the profile silently tool-less with a healthy-looking `configured` status
(#106005 Bug 1/2, #91654). Siblings of the same bug: profile A's failing `x`
put profile B's healthy `x` into A's 10-minute connect cooldown and A's open
circuit breaker short-circuited B's calls; toolsets._resolve_toolset_memo was
not scope-keyed, so B resolved A's `mcp-<server>` tool names.

Keys are now the connection key from the new tools/mcp_tool_scope.py: the bare
name outside a multiplexer (single-profile processes are unchanged) and
(owner_scope, name) under one. Call-time lookups (_resolve_server_key) prefer
the calling scope's own connection, then a shared connection it adopted, so
identical-route profiles still share one subprocess. _select_new_servers,
the cooldown/breaker/trust maps, lazy registration and get_mcp_status all read
and write through the composite key; teardown resolves a task's key by
identity (the MCP loop has no profile context). The toolset memo key includes
registry.current_scope_key().

An owner's scoped /reload-mcp tore down its connection and, with it, every
adopting profile's tool overlay; nothing re-ran the adopters' discovery until
they reloaded. shutdown_mcp_servers(scope=) now records the orphaned adopters
and register_mcp_servers re-registers them under their own home + secret scope
once the owner's rediscovery pass completes.

Docs: multi-profile-gateways.md states the per-profile connection rule.

Fixes #106005
Fixes #91654
Co-authored-by: Bergmann89 <info@bergmann89.de>
Co-authored-by: Izzy-Gottz <srulynj@gmail.com>
2026-09-11 15:27:23 -07:00
kshitijk4poor 4ddbcbd35e fix(mcp): a profile only adopts a shared connection whose credentials match its own config
_same_server_route compared config_fingerprint alone, which by design excludes
env/headers/auth (so the schema cache survives a token rotation). Profile B with the
same URL but different headers/env therefore adopted profile A's live connection and
called tools as A. _connection_identity = route fingerprint + env + headers + auth mode,
used by both the adopt and the stale-removal checks.

Also collapses the three writers of _server_tool_scopes to two: the adoption loop
re-implemented in mcp_tool_discovery._select_new_servers is dropped —
register_connected_into_current_scope (which runs first in register_mcp_servers) is
the single adopter, and _register_candidates records scope for freshly registered tools.
2026-09-09 12:20:21 +05:30
joaomarcos d02edc2cbc fix(gateway): register shared MCP tools per profile 2026-09-09 12:20:21 +05:30
Teknium f4d4831e70 simplify(compat): tools/mcp_tool facade — drop 13 re-export blocks (127 names) + shutil re-import; siblings read sibling-defined names directly (_core kept for facade state) 2026-09-03 13:28:47 -07:00
Teknium e83816a4d1 review-fix(comments): restore lost #NNNN rationale comments across non-test source (mechanical sweep, condensed, code unchanged)
For each issue anchor present in BASE 63279301bc non-test .py and absent on HEAD, the BASE comment/docstring block was re-attached at the HEAD location of the code it explained (matched by the distinctive code line / enclosing def). Sentences already covered by an existing HEAD comment were deduped; the issue number always survives. Insert-only: no code lines changed.
2026-09-03 09:44:26 -07:00
Teknium 0c62b297c6 review-fix(mcp): preserve MCP SDK 2 input schemas in the schema-cache write-through (salvaged from #91451 / #102129)
`_write_schema_cache` in the extracted owner tools/mcp_tool_registration.py
read `t.inputSchema` with a bare camelCase getattr. mcp 2.0 renamed the
model field to `input_schema` and kept `inputSchema` only as a serialization
alias, which pydantic does not apply to attribute access, so on SDK 2.x the
cache persisted `"inputSchema": {}` for every tool and a `lazy: true` server
registered from that cache was advertised to the model with all parameters
stripped. Pre-existing on BASE (tools/mcp_tool.py); fixed with the canonical
`mcp_field(t, "input_schema", "inputSchema")` helper, as both PRs do.

Adds the real-SDK regression test from #102129 (genuine `mcp.types.Tool`
driven through `_register_server_tools` -> cache write ->
`_register_from_cache_sync`), ported to the new module layout and isolated
from the module-global registration state.

Co-authored-by: mzkarami <mehrzad.karami@gmail.com>
Co-authored-by: lijinxiao1982 <120761624+lijinxiao1982@users.noreply.github.com>
2026-09-03 09:32:31 -07:00
Teknium bccfd1de26 refactor(tools): MCP handlers inline single-use render helpers, drop banners; registration foreign-owner log inlined; body blank squeeze 2026-09-03 01:31:18 -07:00
Teknium 58a993a54d refactor(tools): MCP group L docstring/comment compaction, >118-col fixes 2026-09-03 01:30:13 -07:00
Teknium a5bee5eaab refactor(tools): MCP registration cache stand-ins -> SimpleNamespace factory; string-fragment joins 2026-09-03 01:25:48 -07:00
Teknium 9458f4c27a refactor(tools): MCP group L docstring rewrap 2026-09-03 01:20:43 -07:00
Teknium 760ac0b609 refactor(tools): MCP handlers/errors/transport/config/health/registration/oauth-manager compaction — shared _dispatch, folded utility factory, auth-type cache tuple 2026-09-03 01:18:04 -07:00
Teknium c74c187f42 refactor(tools): MCP registration/common/handlers comprehension and predicate collapses 2026-09-02 23:56:55 -07:00
Teknium da18bcd338 refactor(tools): MCP run/discovery/registration log-call folding, _publish_error helper 2026-09-02 23:40:12 -07:00
Teknium 49c38ef10f refactor(tools): MCP docstring/comment compaction, status predicate, renderer tidy 2026-09-02 23:36:18 -07:00
Teknium 7f7fd4a533 refactor(tools): MCP discovery/run/handlers defensive collapse, shared helpers, blank squeeze 2026-09-02 23:07:18 -07:00
Teknium 47be9a3629 refactor(tools): MCP SDK type-family table, drop identity capability map, layout compaction 2026-09-02 22:39:46 -07:00
Teknium 5e4f30bc9d refactor(tools): compact MCP facade/discovery/handlers/run/registration/schema/cache modules 2026-09-02 22:28:12 -07:00
Teknium d9f6d9eda0 refactor(mcp): wrap overlong lines in reg/sampling/schema/agent 2026-09-02 16:01:24 -07:00
Teknium 97fbd7e232 refactor(mcp): table-drive elicitation answers, unify sampling response log, tighten collision diagnostics 2026-09-02 15:57:42 -07:00
Teknium f59fb2e292 refactor(mcp): tighten registration candidates and sampling handler; drop dead _extract_tool_result_text 2026-09-02 15:51:24 -07:00
Teknium d6ec8c3018 refactor(mcp): unify live/cache registration into one candidate loop; phase-split sampling and elicitation handlers 2026-09-02 15:38:42 -07:00
Teknium c1f8af1e86 refactor(tools/mcp): split mcp_tool.py into transport/lifecycle/schema/handlers/... sibling modules; compact watchdog and schema cache 2026-09-02 14:44:15 -07:00