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
feat(session-group): add read_resource and get_prompt routing
ClientSessionGroup could aggregate resources and prompts and call_tool
against them, but offered no routed way to actually read a resource or get a
prompt: callers had to track the owning session themselves.
Add read_resource(name, ...) and get_prompt(name, arguments, ...) mirroring
call_tool: they resolve the aggregate key (honoring component_name_hook) to
the owning session via new _resource_to_session / _prompt_to_session reverse
indexes and forward the resource's wire URI / prompt's wire name. Both carry
the same allow_input_required overloads as ClientSession. Reverse indexes are
cleaned up on disconnect_from_server. Adds unit + in-memory end-to-end tests
and documents the methods in the session-groups guide.
Copy file name to clipboardExpand all lines: docs/client/session-groups.md
+15-1Lines changed: 15 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -60,6 +60,20 @@ Run it again. `print(sorted(group.tools))` now shows both:
60
60
The hook runs on **every** name from **every** server, not only on conflicts: there is no
61
61
prefix-on-collision mode. Pick one scheme and let it apply everywhere.
62
62
63
+
## Reading resources and prompts
64
+
65
+
`call_tool` is not the only routed call. `group.read_resource(name)` and `group.get_prompt(name, arguments)` work the same way: you pass the aggregate key (the one in `group.resources` / `group.prompts`, prefixed if you use a hook), and the group finds the owning session and forwards the call with the resource's real URI or the prompt's real name.
66
+
67
+
```python
68
+
# `Library.hours` is the group key; `library://hours` goes on the wire.
69
+
result =await group.read_resource("Library.hours")
70
+
71
+
# `arguments` are forwarded to the owning server unchanged.
Both raise `KeyError` if the key isn't an aggregated resource/prompt, and both accept the same `allow_input_required` flag as `ClientSession`, so a server that needs input mid-call behaves identically through the group.
76
+
63
77
## Adding and removing servers
64
78
65
79
`connect_to_server` returns the `ClientSession` it opened. Keep it if you ever want that server gone: `await group.disconnect_from_server(session)` removes its tools, resources, and prompts from the group.
@@ -74,7 +88,7 @@ If you already hold a connected `ClientSession` (`Client.session` is one), hand
74
88
75
89
*`ClientSessionGroup` holds many server connections and merges their tools, resources, and prompts into one `dict` each.
76
90
*`connect_to_server(params)` per server. It takes transport parameters, never the URL or `Transport` a `Client` takes.
77
-
*`group.call_tool(name, arguments)` routes to the owning server for you.
91
+
*`group.call_tool(name, arguments)` routes to the owning server for you; `group.read_resource(name)` and `group.get_prompt(name, arguments)` route the same way.
78
92
* Names must be unique across the whole group; two servers with a `search` tool cannot coexist on their own.
79
93
*`component_name_hook=` rewrites every registered name. The dict key changes, the wire name does not.
80
94
*`connect_with_session` adds a session you already hold; `disconnect_from_server` removes one.
0 commit comments