Files
Pietro Zullo ebef017114 python/server/middleware&tel (#650)
* chore: add example server pretty print JSON RPC for transparency

* updated telemetry module

* chore: agent side tel - langchain adapter - client tel

* server side tel:

* update API reference

* python transports and primitive reports are publishes only if not skipped

* remove wrongly generate files

* properly typed middleware

* remove examples

* feat(docs): add middleware and session management documentation

- Introduced new documentation for middleware, detailing hooks, minimal examples, and best practices for integrating middleware in MCP servers.
- Added a session management guide explaining session ID handling, usage patterns, and examples for managing per-client state in MCP servers.
- Updated  to include links to the new middleware and session management pages.

* generate docs

* remove few events

* adapter tel

* adapter tel

* api ref docs update

* google adapter fix

* fix version

* fix event naming

* server example is streamable and echo tool fix

* removed initialize middleware hook, initialize requests are not passed thorugh normal handlers

* api ref

* beta on middleware
2025-12-10 17:02:08 +01:00

165 lines
5.0 KiB
Python

"""
Session manager for MCP connections.
This module provides a session manager for MCP connections,
which handles authentication, initialization, and tool discovery.
"""
from datetime import timedelta
from typing import Any
from mcp.types import CallToolResult, GetPromptResult, Prompt, ReadResourceResult, Resource, Tool
from pydantic import AnyUrl
from mcp_use.client.connectors.base import BaseConnector
from mcp_use.telemetry.telemetry import telemetry
class MCPSession:
"""Session manager for MCP connections.
This class manages the lifecycle of an MCP connection, including
authentication, initialization, and tool discovery.
"""
def __init__(
self,
connector: BaseConnector,
auto_connect: bool = True,
) -> None:
"""Initialize a new MCP session.
Args:
connector: The connector to use for communicating with the MCP implementation.
auto_connect: Whether to automatically connect to the MCP implementation.
"""
self.connector = connector
self.session_info: dict[str, Any] | None = None
self.auto_connect = auto_connect
self._record_telemetry = True
self.connector._record_telemetry = False
async def __aenter__(self) -> "MCPSession":
"""Enter the async context manager.
Returns:
The session instance.
"""
await self.connect()
return self
async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
"""Exit the async context manager.
Args:
exc_type: The exception type, if an exception was raised.
exc_val: The exception value, if an exception was raised.
exc_tb: The exception traceback, if an exception was raised.
"""
await self.disconnect()
async def connect(self) -> None:
"""Connect to the MCP implementation."""
await self.connector.connect()
async def disconnect(self) -> None:
"""Disconnect from the MCP implementation."""
await self.connector.disconnect()
@telemetry("session_initialize")
async def initialize(self) -> dict[str, Any]:
"""Initialize the MCP session and discover available tools.
Returns:
The session information returned by the MCP implementation.
"""
# Make sure we're connected
if not self.is_connected and self.auto_connect:
await self.connect()
# Initialize the session
self.session_info = await self.connector.initialize()
return self.session_info
@property
def is_connected(self) -> bool:
"""Check if the connector is connected.
Returns:
True if the connector is connected, False otherwise.
"""
return self.connector.is_connected
# Convenience methods for MCP operations
@telemetry("session_call_tool")
async def call_tool(
self, name: str, arguments: dict[str, Any], read_timeout_seconds: timedelta | None = None
) -> CallToolResult:
"""Call an MCP tool.
Args:
name: The name of the tool to call.
arguments: The arguments to pass to the tool.
read_timeout_seconds: Optional timeout for the tool call.
Returns:
The result of the tool call.
Raises:
RuntimeError: If the connection is lost and cannot be reestablished.
"""
return await self.connector.call_tool(name, arguments, read_timeout_seconds)
@telemetry("session_list_tools")
async def list_tools(self) -> list[Tool]:
"""List all available tools from the MCP server.
Returns:
List of available tools.
"""
return await self.connector.list_tools()
@telemetry("session_list_resources")
async def list_resources(self) -> list[Resource]:
"""List all available resources from the MCP server.
Returns:
List of available resources.
"""
return await self.connector.list_resources()
@telemetry("session_read_resource")
async def read_resource(self, uri: AnyUrl) -> ReadResourceResult:
"""Read a resource by URI.
Args:
uri: The URI of the resource to read.
Returns:
The resource content.
"""
return await self.connector.read_resource(uri)
@telemetry("session_list_prompts")
async def list_prompts(self) -> list[Prompt]:
"""List all available prompts from the MCP server.
Returns:
List of available prompts.
"""
return await self.connector.list_prompts()
@telemetry("session_get_prompt")
async def get_prompt(self, name: str, arguments: dict[str, Any] | None = None) -> GetPromptResult:
"""Get a prompt by name.
Args:
name: The name of the prompt to get.
arguments: Optional arguments for the prompt.
Returns:
The prompt result with messages.
"""
return await self.connector.get_prompt(name, arguments)