You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,6 +16,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
16
16
17
17
### Fixed
18
18
19
+
**`CMCPProxy._client_for_upstream` pooled every unpinned upstream server in a session behind one shared `httpx.AsyncClient` (#281).** The pinned branch already keys its cached client on the fingerprint (a matching pin *is* the same verified peer, so sharing there is correct), but both unpinned branches plain `http://` and the `PLACEHOLDER_FINGERPRINT` dev-mode pin collapsed to the single literal key `"unpinned"`, regardless of which server the entry actually pointed at. A gateway session whose catalog lists two or more unrelated unpinned upstreams (the supported, if discouraged, dev/demo path this same method's docstring describes) got one `httpx.AsyncClient` for all of them: one cookie jar, and one shared pool of `max_connections`/`max_keepalive_connections`, across servers whose only thing in common was that neither presented a real pin.
20
+
19
21
-**`POST /mcp``tools/call` 500'd on a non-string `name`, and silently accepted a non-object `arguments`.**`_handle_tool_call` read `tool_name: str = params.get("name", "").lower()` and `arguments: dict[str, Any] = params.get("arguments", {})`: the `.get(field, default)` default only covers a genuinely *absent* field, so a caller-supplied `name` that is present but not a string (an int, a list, a bool, `null`) reached `.lower()` and raised an unhandled `AttributeError`, caught only by the outermost `_unhandled_error_handler` and logged as `UNHANDLED_EXCEPTION`/`INTERNAL_ERROR` for what is ordinary client input validation, not an internal failure. `arguments` had the matching gap on the other side: `_arg_shape_violation` (the #518/#562 depth/key-count/string-length gate) only recognizes `dict`, `list` and `str`, so a scalar `arguments` (an int, for instance) silently returned "no violation" and reached `call_tool` with a shape its own type annotation says cannot occur.
20
22
21
23
Both fields are exactly as caller-controlled as `_cmcp` a few lines below, already guarded with "A malformed `_cmcp` (string, list, number) must not 500 the call path" `name` and `arguments` were the two places that same reasoning wasn't applied. Both now return the same `-32602 Invalid params` JSON-RPC error the adjacent depth/key/string-length and non-dict-`params` checks already return, before `call_tool` is ever reached.
0 commit comments