Skip to content

Conversation

@nikomatsakis
Copy link
Member

Summary

This PR adds a cookbook module with documented patterns for common MCP server tasks, along with improvements to the tool handling and session APIs.

New Features

  • Concurrent tool execution: tool_fn now runs tools concurrently (vs tool_fn_mut for stateful tools)
  • Session proxying: build_session_from and proxy_session for injecting MCP servers into proxied sessions
  • Simplified handler architecture: Reduced public API surface and renamed handlers for clarity

Documentation

Added cookbook module with documented, compiling examples for:

  • Roles and endpoints - Understanding JrRole, JrEndpoint, and how proxies work
  • Reusable components - Defining agents/proxies with Component
  • Custom message handlers - Implementing JrMessageHandler
  • Connecting as a client - Using with_client to send requests
  • Global MCP server - Adding MCP servers to a handler chain
  • Per-session MCP server - Creating MCP servers per session

All cookbook examples compile and run (not just ignored).

Breaking Changes

  • Renamed await_when_result_receivedon_receiving_result
  • Renamed await_when_ok_response_receivedon_receiving_ok_result
  • Renamed add_to_new_sessioninto_dynamic_handler
  • Renamed McpSessionHandlerMcpNewSessionHandler

Extracts the concurrent stream processing pattern from task_actor into
a reusable utility function. This pattern receives items from a stream,
spawns concurrent work for each, and drains remaining futures when the
stream closes.

Uses futures-concurrency race() instead of select! macro for cleaner
concurrent waiting.
- Change tool_with_responder to return impl JrResponder<Role>
- Make ToolCall and ToolFnResponder module-private (pub(super))
- Limit sacp::handler exports to JrMessageHandler and NullHandler
- Remove ChainedHandler, NamedHandler, etc from public API
Adds tool_fn alongside tool_fn_mut for tools that don't need mutable
state and can run concurrently. Also adds the tool_fn! macro and
removes unused role field/method from handler structs.
Uses process_stream_concurrently to run multiple tool invocations
in parallel. Required Arc-wrapping the function and the same
to_future_hack workaround for async closure lifetime issues.
Adds SessionBuilder::proxy_session() which forwards a session request
to the agent while injecting custom MCP servers, then proxies all
messages without requiring an ActiveSession handle.

Also makes ProxySessionMessages generic and pub(crate) for reuse.
- Generate single acp:UUID at McpServer construction time (not per-session)
- McpNewSessionHandler now owns McpActiveSession directly
- Add otherwise_delegate() to MatchMessageFrom for inline handler delegation
- Implement JrMessageHandler for &mut H to enable delegation pattern
- Rename add_to_new_session to into_dynamic_handler (consumes self)
- Make McpNewSessionHandler pub(crate) - not part of public API
- Remove Clone from McpNewSessionHandler (owns mutable state now)
- Relax trait bounds on McpActiveSession struct definition
- await_when_result_received -> on_receiving_result
- await_when_ok_response_received -> on_receiving_ok_result
- add_to_new_session -> into_dynamic_handler
- Add cookbook module documenting roles, endpoints, and common patterns
- Extract patterns from lib.rs into dedicated submodules:
  - reusable_components: Defining agents/proxies with Component
  - custom_message_handlers: Implementing JrMessageHandler
  - connecting_as_client: Using with_client to send requests
  - global_mcp_server: Adding MCP servers to handler chains
  - per_session_mcp_server: Creating per-session MCP servers
- Slim down lib.rs to reference cookbook instead of duplicating content
Convert ignore doctests to real compiling examples for:
- reusable_components: Component impl with InitializeRequest handler
- custom_message_handlers: JrMessageHandler impl with MatchMessage
- global_mcp_server: McpServer with tool_fn in proxy Component

The connecting_as_client and per_session_mcp_server patterns remain
as ignore examples since they require runtime infrastructure.
- connecting_as_client: use "." instead of current_dir() to avoid
  io::Error conversion issues
- per_session_mcp_server: update to use build_session_from() and
  proxy_session() API instead of outdated run_session pattern
@nikomatsakis nikomatsakis merged commit f26a71e into symposium-dev:main Dec 21, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant