Skip to content

mcp_server

Class info

Classes

Name Children Inherits
BridgeConfig
llmling_agent.mcp_server.tool_bridge
Configuration for the ToolManager MCP bridge.
    MCPClient
    llmling_agent.mcp_server.client
    FastMCP-based client for communicating with MCP servers.
      ToolBridgeRegistry
      llmling_agent.mcp_server.tool_bridge
      Registry for managing multiple tool bridges.
        ToolManagerBridge
        llmling_agent.mcp_server.tool_bridge
        Exposes a ToolManager's tools as an MCP server for ACP agents.

          🛈 DocStrings

          MCP server integration for LLMling agent.

          BridgeConfig dataclass

          Configuration for the ToolManager MCP bridge.

          Source code in src/llmling_agent/mcp_server/tool_bridge.py
          48
          49
          50
          51
          52
          53
          54
          55
          56
          57
          58
          59
          60
          61
          62
          @dataclass
          class BridgeConfig:
              """Configuration for the ToolManager MCP bridge."""
          
              host: str = "127.0.0.1"
              """Host to bind the HTTP server to."""
          
              port: int = 0
              """Port to bind to (0 = auto-select available port)."""
          
              transport: str = "sse"
              """Transport protocol: 'sse' or 'streamable-http'."""
          
              server_name: str = "llmling-toolmanager"
              """Name for the MCP server."""
          

          host class-attribute instance-attribute

          host: str = '127.0.0.1'
          

          Host to bind the HTTP server to.

          port class-attribute instance-attribute

          port: int = 0
          

          Port to bind to (0 = auto-select available port).

          server_name class-attribute instance-attribute

          server_name: str = 'llmling-toolmanager'
          

          Name for the MCP server.

          transport class-attribute instance-attribute

          transport: str = 'sse'
          

          Transport protocol: 'sse' or 'streamable-http'.

          MCPClient

          FastMCP-based client for communicating with MCP servers.

          Source code in src/llmling_agent/mcp_server/client.py
           67
           68
           69
           70
           71
           72
           73
           74
           75
           76
           77
           78
           79
           80
           81
           82
           83
           84
           85
           86
           87
           88
           89
           90
           91
           92
           93
           94
           95
           96
           97
           98
           99
          100
          101
          102
          103
          104
          105
          106
          107
          108
          109
          110
          111
          112
          113
          114
          115
          116
          117
          118
          119
          120
          121
          122
          123
          124
          125
          126
          127
          128
          129
          130
          131
          132
          133
          134
          135
          136
          137
          138
          139
          140
          141
          142
          143
          144
          145
          146
          147
          148
          149
          150
          151
          152
          153
          154
          155
          156
          157
          158
          159
          160
          161
          162
          163
          164
          165
          166
          167
          168
          169
          170
          171
          172
          173
          174
          175
          176
          177
          178
          179
          180
          181
          182
          183
          184
          185
          186
          187
          188
          189
          190
          191
          192
          193
          194
          195
          196
          197
          198
          199
          200
          201
          202
          203
          204
          205
          206
          207
          208
          209
          210
          211
          212
          213
          214
          215
          216
          217
          218
          219
          220
          221
          222
          223
          224
          225
          226
          227
          228
          229
          230
          231
          232
          233
          234
          235
          236
          237
          238
          239
          240
          241
          242
          243
          244
          245
          246
          247
          248
          249
          250
          251
          252
          253
          254
          255
          256
          257
          258
          259
          260
          261
          262
          263
          264
          265
          266
          267
          268
          269
          270
          271
          272
          273
          274
          275
          276
          277
          278
          279
          280
          281
          282
          283
          284
          285
          286
          287
          288
          289
          290
          291
          292
          293
          294
          295
          296
          297
          298
          299
          300
          301
          302
          303
          304
          305
          306
          307
          308
          309
          310
          311
          312
          313
          314
          315
          316
          317
          318
          319
          320
          321
          322
          323
          324
          325
          326
          327
          328
          329
          330
          331
          332
          333
          334
          335
          336
          337
          338
          339
          340
          341
          342
          343
          344
          345
          346
          347
          348
          349
          350
          351
          352
          353
          354
          355
          356
          357
          358
          359
          360
          361
          362
          363
          364
          365
          366
          367
          368
          369
          370
          371
          372
          373
          374
          375
          376
          377
          378
          379
          380
          381
          382
          383
          class MCPClient:
              """FastMCP-based client for communicating with MCP servers."""
          
              def __init__(
                  self,
                  config: MCPServerConfig,
                  sampling_callback: ClientSamplingHandler[Any] | None = None,
                  message_handler: MessageHandlerT | MessageHandler | None = None,
                  accessible_roots: list[str] | None = None,
                  tool_change_callback: Callable[[], Awaitable[None]] | None = None,
                  prompt_change_callback: Callable[[], Awaitable[None]] | None = None,
                  resource_change_callback: Callable[[], Awaitable[None]] | None = None,
              ) -> None:
                  # Mutable handler swapped per call_tool for dynamic elicitation
                  self._current_elicitation_handler: ElicitationHandler | None = None
                  self.config = config
                  self._sampling_callback = sampling_callback
                  # Store message handler or mark for lazy creation
                  self._message_handler = message_handler
                  self._accessible_roots = accessible_roots or []
                  self._tool_change_callback = tool_change_callback
                  self._prompt_change_callback = prompt_change_callback
                  self._resource_change_callback = resource_change_callback
                  self._client = self._get_client(self.config)
          
              @property
              def connected(self) -> bool:
                  """Check if client is connected by examining session state."""
                  return self._client.is_connected()
          
              async def __aenter__(self) -> Self:
                  """Enter context manager."""
                  try:
                      # First attempt with configured auth
                      await self._client.__aenter__()  # type: ignore[no-untyped-call]
          
                  except Exception as first_error:
                      # OAuth fallback for HTTP/SSE if not already using OAuth
                      if not isinstance(self.config, StdioMCPServerConfig) and not self.config.auth.oauth:
                          try:
                              with contextlib.suppress(Exception):
                                  await self._client.__aexit__(None, None, None)  # type: ignore[no-untyped-call]
                              self._client = self._get_client(self.config, force_oauth=True)
                              await self._client.__aenter__()  # type: ignore[no-untyped-call]
                              logger.info("Connected with OAuth fallback")
                          except Exception:  # noqa: BLE001
                              raise first_error from None
                      else:
                          raise
          
                  return self
          
              async def __aexit__(self, *args: object) -> None:
                  """Exit context manager and cleanup."""
                  try:
                      await self._client.__aexit__(None, None, None)  # type: ignore[no-untyped-call]
                  except Exception as e:  # noqa: BLE001
                      logger.warning("Error during FastMCP client cleanup", error=e)
          
              def get_resource_fs(self) -> MCPFileSystem:
                  """Get a filesystem for accessing MCP resources."""
                  from upathtools.filesystems import MCPFileSystem
          
                  return MCPFileSystem(client=self._client)
          
              def get_tools_fs(self) -> MCPToolsFileSystem:
                  """Get a filesystem for accessing MCP tools as code."""
                  from upathtools.filesystems import MCPToolsFileSystem
          
                  return MCPToolsFileSystem(client=self._client)
          
              async def _log_handler(self, message: LogMessage) -> None:
                  """Handle server log messages."""
                  level = MCP_TO_LOGGING.get(message.level, logging.INFO)
                  logger.log(level, "MCP Server: ", data=message.data)
          
              async def _forwarding_elicitation_callback[T](
                  self,
                  message: str,
                  response_type: type[T],
                  params: ElicitRequestParams,
                  context: RequestContext[Any, Any],
              ) -> T | dict[str, Any] | Any:
                  """Forwarding callback that delegates to current handler.
          
                  This callback is registered once at connection time, but delegates to
                  _current_elicitation_handler which can be swapped per tool call.
                  """
                  from fastmcp.client.elicitation import ElicitResult
          
                  # Try current handler first (set per call_tool)
                  if self._current_elicitation_handler:
                      return await self._current_elicitation_handler(message, response_type, params, context)
                  # No handler available - decline by default
                  return ElicitResult(action="decline")
          
              def _get_client(
                  self, config: MCPServerConfig, force_oauth: bool = False
              ) -> fastmcp.Client[Any]:
                  """Create FastMCP client based on config."""
                  import fastmcp
                  from fastmcp.client import SSETransport, StreamableHttpTransport
                  from fastmcp.client.transports import StdioTransport
          
                  transport: ClientTransport
                  # Create transport based on config type
                  match config:
                      case StdioMCPServerConfig(command=command, args=args):
                          env = config.get_env_vars()
                          transport = StdioTransport(command=command, args=args, env=env)
                          oauth = False
                          if force_oauth:
                              msg = "OAuth is not supported for StdioMCPServerConfig"
                              raise ValueError(msg)
          
                      case SSEMCPServerConfig(url=url, headers=headers, auth=auth):
                          transport = SSETransport(url=url, headers=headers)
                          oauth = auth.oauth
          
                      case StreamableHTTPMCPServerConfig(url=url, headers=headers, auth=auth):
                          transport = StreamableHttpTransport(url=url, headers=headers)
                          oauth = auth.oauth
                      case _ as unreachable:
                          assert_never(unreachable)
          
                  # Create message handler if needed
                  msg_handler = self._message_handler or MCPMessageHandler(
                      self,
                      self._tool_change_callback,
                      self._prompt_change_callback,
                      self._resource_change_callback,
                  )
                  return fastmcp.Client(
                      transport,
                      log_handler=self._log_handler,
                      roots=self._accessible_roots,
                      timeout=config.timeout,
                      elicitation_handler=self._forwarding_elicitation_callback,
                      sampling_handler=self._sampling_callback,
                      message_handler=msg_handler,
                      auth="oauth" if (force_oauth or oauth) else None,
                  )
          
              async def list_tools(self) -> list[MCPTool]:
                  """Get available tools directly from the server."""
                  if not self.connected:
                      msg = "Not connected to MCP server"
                      raise RuntimeError(msg)
          
                  try:
                      tools = await self._client.list_tools()
                      logger.debug("Listed tools from MCP server", num_tools=len(tools))
                  except Exception as e:  # noqa: BLE001
                      logger.warning("Failed to list tools", error=e)
                      return []
                  else:
                      return tools
          
              async def list_prompts(self) -> list[MCPPrompt]:
                  """Get available prompts from the server."""
                  if not self.connected:
                      msg = "Not connected to MCP server"
                      raise RuntimeError(msg)
          
                  try:
                      return await self._client.list_prompts()
                  except Exception as e:  # noqa: BLE001
                      logger.debug("Failed to list prompts", error=e)
                      return []
          
              async def list_resources(self) -> list[MCPResource]:
                  """Get available resources from the server."""
                  if not self.connected:
                      msg = "Not connected to MCP server"
                      raise RuntimeError(msg)
          
                  try:
                      return await self._client.list_resources()
                  except Exception as e:
                      msg = f"Failed to list resources: {e}"
                      raise RuntimeError(msg) from e
          
              async def get_prompt(
                  self, name: str, arguments: dict[str, str] | None = None
              ) -> GetPromptResult:
                  """Get a specific prompt's content."""
                  if not self.connected:
                      msg = "Not connected to MCP server"
                      raise RuntimeError(msg)
          
                  try:
                      return await self._client.get_prompt_mcp(name, arguments)
                  except Exception as e:
                      msg = f"Failed to get prompt {name!r}: {e}"
                      raise RuntimeError(msg) from e
          
              def convert_tool(self, tool: MCPTool) -> Tool:
                  """Create a properly typed callable from MCP tool schema."""
          
                  async def tool_callable(
                      ctx: RunContext, agent_ctx: AgentContext[Any], **kwargs: Any
                  ) -> str | Any | ToolReturn:
                      """Dynamically generated MCP tool wrapper."""
                      # Filter out None values for optional params
                      schema_props = tool.inputSchema.get("properties", {})
                      required_props = set(tool.inputSchema.get("required", []))
                      filtered_kwargs = {
                          k: v
                          for k, v in kwargs.items()
                          if k in required_props or (k in schema_props and v is not None)
                      }
                      return await self.call_tool(tool.name, ctx, filtered_kwargs, agent_ctx)
          
                  # Set proper signature and annotations with both RunContext and AgentContext
                  schema = mcp_tool_to_fn_schema(tool)
                  fn_schema = FunctionSchema.from_dict(schema)
                  sig = fn_schema.to_python_signature()
          
                  tool_callable.__signature__ = create_modified_signature(  # type: ignore[attr-defined]
                      sig, inject={"ctx": RunContext, "agent_ctx": AgentContext}
                  )
                  annotations = fn_schema.get_annotations()
                  annotations["ctx"] = RunContext
                  annotations["agent_ctx"] = AgentContext
                  # Update return annotation to support multiple types
                  annotations["return"] = str | Any | ToolReturn  # type: ignore
                  tool_callable.__annotations__ = annotations
                  tool_callable.__name__ = tool.name
                  tool_callable.__doc__ = tool.description or "No description provided."
                  return Tool.from_callable(tool_callable, source="mcp")
          
              async def call_tool(
                  self,
                  name: str,
                  run_context: RunContext,
                  arguments: dict[str, Any] | None = None,
                  agent_ctx: AgentContext[Any] | None = None,
              ) -> ToolReturn | str | Any:
                  """Call an MCP tool with full PydanticAI return type support."""
                  if not self.connected:
                      msg = "Not connected to MCP server"
                      raise RuntimeError(msg)
          
                  # Create progress handler that bridges to AgentContext if available
                  progress_handler = None
                  if agent_ctx:
          
                      async def fastmcp_progress_handler(
                          progress: float,
                          total: float | None,
                          message: str | None,
                      ) -> None:
                          await agent_ctx.report_progress(progress, total, message or "")
          
                      progress_handler = fastmcp_progress_handler
          
                  # Set up per-call elicitation handler from AgentContext
                  if agent_ctx:
          
                      async def elicitation_handler[T](
                          message: str,
                          response_type: type[T],
                          params: ElicitRequestParams,
                          context: RequestContext[Any, Any],
                      ) -> T | dict[str, Any] | Any:
                          from fastmcp.client.elicitation import ElicitResult
                          from mcp.types import ElicitResult as MCPElicitResult, ErrorData
          
                          result = await agent_ctx.handle_elicitation(params)
                          match result:
                              case MCPElicitResult(action="accept", content=content):
                                  return content
                              case MCPElicitResult(action="cancel"):
                                  return ElicitResult(action="cancel")
                              case MCPElicitResult(action="decline"):
                                  return ElicitResult(action="decline")
                              case ErrorData():
                                  return ElicitResult(action="decline")
                              case _:
                                  return ElicitResult(action="decline")
          
                      self._current_elicitation_handler = elicitation_handler
          
                  try:
                      result = await self._client.call_tool(
                          name, arguments, progress_handler=progress_handler
                      )
                      content = await self._convert_mcp_content(result.content)
                      # Decision logic for return type
                      match (result.data is not None, bool(content)):
                          case (True, True):  # Both structured data and rich content -> ToolReturn
                              return ToolReturn(return_value=result.data, content=content)
                          case (True, False):  # Only structured data -> return directly
                              return result.data
                          case (False, True):  # Only content -> ToolReturn with content
                              msg = "Tool executed successfully"
                              return ToolReturn(return_value=msg, content=content)
                          case (False, False):  # Fallback to text extraction
                              return extract_text_content(result.content)
                          case _:  # Handle unexpected cases
                              msg = f"Unexpected MCP content: {result.content}"
                              raise ValueError(msg)  # noqa: TRY301
                  except Exception as e:
                      msg = f"MCP tool call failed: {e}"
                      raise RuntimeError(msg) from e
                  finally:
                      # Clear per-call handler
                      self._current_elicitation_handler = None
          
              async def _convert_mcp_content(
                  self,
                  mcp_content: Sequence[ContentBlock | TextResourceContents | BlobResourceContents],
              ) -> list[str | BinaryContent]:
                  """Convert MCP content blocks to PydanticAI content types."""
                  from llmling_agent.mcp_server.conversions import convert_mcp_content
          
                  return await convert_mcp_content(mcp_content)
          

          connected property

          connected: bool
          

          Check if client is connected by examining session state.

          __aenter__ async

          __aenter__() -> Self
          

          Enter context manager.

          Source code in src/llmling_agent/mcp_server/client.py
           97
           98
           99
          100
          101
          102
          103
          104
          105
          106
          107
          108
          109
          110
          111
          112
          113
          114
          115
          116
          117
          async def __aenter__(self) -> Self:
              """Enter context manager."""
              try:
                  # First attempt with configured auth
                  await self._client.__aenter__()  # type: ignore[no-untyped-call]
          
              except Exception as first_error:
                  # OAuth fallback for HTTP/SSE if not already using OAuth
                  if not isinstance(self.config, StdioMCPServerConfig) and not self.config.auth.oauth:
                      try:
                          with contextlib.suppress(Exception):
                              await self._client.__aexit__(None, None, None)  # type: ignore[no-untyped-call]
                          self._client = self._get_client(self.config, force_oauth=True)
                          await self._client.__aenter__()  # type: ignore[no-untyped-call]
                          logger.info("Connected with OAuth fallback")
                      except Exception:  # noqa: BLE001
                          raise first_error from None
                  else:
                      raise
          
              return self
          

          __aexit__ async

          __aexit__(*args: object) -> None
          

          Exit context manager and cleanup.

          Source code in src/llmling_agent/mcp_server/client.py
          119
          120
          121
          122
          123
          124
          async def __aexit__(self, *args: object) -> None:
              """Exit context manager and cleanup."""
              try:
                  await self._client.__aexit__(None, None, None)  # type: ignore[no-untyped-call]
              except Exception as e:  # noqa: BLE001
                  logger.warning("Error during FastMCP client cleanup", error=e)
          

          call_tool async

          call_tool(
              name: str,
              run_context: RunContext,
              arguments: dict[str, Any] | None = None,
              agent_ctx: AgentContext[Any] | None = None,
          ) -> ToolReturn | str | Any
          

          Call an MCP tool with full PydanticAI return type support.

          Source code in src/llmling_agent/mcp_server/client.py
          298
          299
          300
          301
          302
          303
          304
          305
          306
          307
          308
          309
          310
          311
          312
          313
          314
          315
          316
          317
          318
          319
          320
          321
          322
          323
          324
          325
          326
          327
          328
          329
          330
          331
          332
          333
          334
          335
          336
          337
          338
          339
          340
          341
          342
          343
          344
          345
          346
          347
          348
          349
          350
          351
          352
          353
          354
          355
          356
          357
          358
          359
          360
          361
          362
          363
          364
          365
          366
          367
          368
          369
          370
          371
          372
          373
          374
          async def call_tool(
              self,
              name: str,
              run_context: RunContext,
              arguments: dict[str, Any] | None = None,
              agent_ctx: AgentContext[Any] | None = None,
          ) -> ToolReturn | str | Any:
              """Call an MCP tool with full PydanticAI return type support."""
              if not self.connected:
                  msg = "Not connected to MCP server"
                  raise RuntimeError(msg)
          
              # Create progress handler that bridges to AgentContext if available
              progress_handler = None
              if agent_ctx:
          
                  async def fastmcp_progress_handler(
                      progress: float,
                      total: float | None,
                      message: str | None,
                  ) -> None:
                      await agent_ctx.report_progress(progress, total, message or "")
          
                  progress_handler = fastmcp_progress_handler
          
              # Set up per-call elicitation handler from AgentContext
              if agent_ctx:
          
                  async def elicitation_handler[T](
                      message: str,
                      response_type: type[T],
                      params: ElicitRequestParams,
                      context: RequestContext[Any, Any],
                  ) -> T | dict[str, Any] | Any:
                      from fastmcp.client.elicitation import ElicitResult
                      from mcp.types import ElicitResult as MCPElicitResult, ErrorData
          
                      result = await agent_ctx.handle_elicitation(params)
                      match result:
                          case MCPElicitResult(action="accept", content=content):
                              return content
                          case MCPElicitResult(action="cancel"):
                              return ElicitResult(action="cancel")
                          case MCPElicitResult(action="decline"):
                              return ElicitResult(action="decline")
                          case ErrorData():
                              return ElicitResult(action="decline")
                          case _:
                              return ElicitResult(action="decline")
          
                  self._current_elicitation_handler = elicitation_handler
          
              try:
                  result = await self._client.call_tool(
                      name, arguments, progress_handler=progress_handler
                  )
                  content = await self._convert_mcp_content(result.content)
                  # Decision logic for return type
                  match (result.data is not None, bool(content)):
                      case (True, True):  # Both structured data and rich content -> ToolReturn
                          return ToolReturn(return_value=result.data, content=content)
                      case (True, False):  # Only structured data -> return directly
                          return result.data
                      case (False, True):  # Only content -> ToolReturn with content
                          msg = "Tool executed successfully"
                          return ToolReturn(return_value=msg, content=content)
                      case (False, False):  # Fallback to text extraction
                          return extract_text_content(result.content)
                      case _:  # Handle unexpected cases
                          msg = f"Unexpected MCP content: {result.content}"
                          raise ValueError(msg)  # noqa: TRY301
              except Exception as e:
                  msg = f"MCP tool call failed: {e}"
                  raise RuntimeError(msg) from e
              finally:
                  # Clear per-call handler
                  self._current_elicitation_handler = None
          

          convert_tool

          convert_tool(tool: Tool) -> Tool
          

          Create a properly typed callable from MCP tool schema.

          Source code in src/llmling_agent/mcp_server/client.py
          263
          264
          265
          266
          267
          268
          269
          270
          271
          272
          273
          274
          275
          276
          277
          278
          279
          280
          281
          282
          283
          284
          285
          286
          287
          288
          289
          290
          291
          292
          293
          294
          295
          296
          def convert_tool(self, tool: MCPTool) -> Tool:
              """Create a properly typed callable from MCP tool schema."""
          
              async def tool_callable(
                  ctx: RunContext, agent_ctx: AgentContext[Any], **kwargs: Any
              ) -> str | Any | ToolReturn:
                  """Dynamically generated MCP tool wrapper."""
                  # Filter out None values for optional params
                  schema_props = tool.inputSchema.get("properties", {})
                  required_props = set(tool.inputSchema.get("required", []))
                  filtered_kwargs = {
                      k: v
                      for k, v in kwargs.items()
                      if k in required_props or (k in schema_props and v is not None)
                  }
                  return await self.call_tool(tool.name, ctx, filtered_kwargs, agent_ctx)
          
              # Set proper signature and annotations with both RunContext and AgentContext
              schema = mcp_tool_to_fn_schema(tool)
              fn_schema = FunctionSchema.from_dict(schema)
              sig = fn_schema.to_python_signature()
          
              tool_callable.__signature__ = create_modified_signature(  # type: ignore[attr-defined]
                  sig, inject={"ctx": RunContext, "agent_ctx": AgentContext}
              )
              annotations = fn_schema.get_annotations()
              annotations["ctx"] = RunContext
              annotations["agent_ctx"] = AgentContext
              # Update return annotation to support multiple types
              annotations["return"] = str | Any | ToolReturn  # type: ignore
              tool_callable.__annotations__ = annotations
              tool_callable.__name__ = tool.name
              tool_callable.__doc__ = tool.description or "No description provided."
              return Tool.from_callable(tool_callable, source="mcp")
          

          get_prompt async

          get_prompt(name: str, arguments: dict[str, str] | None = None) -> GetPromptResult
          

          Get a specific prompt's content.

          Source code in src/llmling_agent/mcp_server/client.py
          249
          250
          251
          252
          253
          254
          255
          256
          257
          258
          259
          260
          261
          async def get_prompt(
              self, name: str, arguments: dict[str, str] | None = None
          ) -> GetPromptResult:
              """Get a specific prompt's content."""
              if not self.connected:
                  msg = "Not connected to MCP server"
                  raise RuntimeError(msg)
          
              try:
                  return await self._client.get_prompt_mcp(name, arguments)
              except Exception as e:
                  msg = f"Failed to get prompt {name!r}: {e}"
                  raise RuntimeError(msg) from e
          

          get_resource_fs

          get_resource_fs() -> MCPFileSystem
          

          Get a filesystem for accessing MCP resources.

          Source code in src/llmling_agent/mcp_server/client.py
          126
          127
          128
          129
          130
          def get_resource_fs(self) -> MCPFileSystem:
              """Get a filesystem for accessing MCP resources."""
              from upathtools.filesystems import MCPFileSystem
          
              return MCPFileSystem(client=self._client)
          

          get_tools_fs

          get_tools_fs() -> MCPToolsFileSystem
          

          Get a filesystem for accessing MCP tools as code.

          Source code in src/llmling_agent/mcp_server/client.py
          132
          133
          134
          135
          136
          def get_tools_fs(self) -> MCPToolsFileSystem:
              """Get a filesystem for accessing MCP tools as code."""
              from upathtools.filesystems import MCPToolsFileSystem
          
              return MCPToolsFileSystem(client=self._client)
          

          list_prompts async

          list_prompts() -> list[Prompt]
          

          Get available prompts from the server.

          Source code in src/llmling_agent/mcp_server/client.py
          225
          226
          227
          228
          229
          230
          231
          232
          233
          234
          235
          async def list_prompts(self) -> list[MCPPrompt]:
              """Get available prompts from the server."""
              if not self.connected:
                  msg = "Not connected to MCP server"
                  raise RuntimeError(msg)
          
              try:
                  return await self._client.list_prompts()
              except Exception as e:  # noqa: BLE001
                  logger.debug("Failed to list prompts", error=e)
                  return []
          

          list_resources async

          list_resources() -> list[Resource]
          

          Get available resources from the server.

          Source code in src/llmling_agent/mcp_server/client.py
          237
          238
          239
          240
          241
          242
          243
          244
          245
          246
          247
          async def list_resources(self) -> list[MCPResource]:
              """Get available resources from the server."""
              if not self.connected:
                  msg = "Not connected to MCP server"
                  raise RuntimeError(msg)
          
              try:
                  return await self._client.list_resources()
              except Exception as e:
                  msg = f"Failed to list resources: {e}"
                  raise RuntimeError(msg) from e
          

          list_tools async

          list_tools() -> list[Tool]
          

          Get available tools directly from the server.

          Source code in src/llmling_agent/mcp_server/client.py
          210
          211
          212
          213
          214
          215
          216
          217
          218
          219
          220
          221
          222
          223
          async def list_tools(self) -> list[MCPTool]:
              """Get available tools directly from the server."""
              if not self.connected:
                  msg = "Not connected to MCP server"
                  raise RuntimeError(msg)
          
              try:
                  tools = await self._client.list_tools()
                  logger.debug("Listed tools from MCP server", num_tools=len(tools))
              except Exception as e:  # noqa: BLE001
                  logger.warning("Failed to list tools", error=e)
                  return []
              else:
                  return tools
          

          ToolBridgeRegistry

          Registry for managing multiple tool bridges.

          Useful when multiple ACP agents need access to different toolsets.

          Source code in src/llmling_agent/mcp_server/tool_bridge.py
          386
          387
          388
          389
          390
          391
          392
          393
          394
          395
          396
          397
          398
          399
          400
          401
          402
          403
          404
          405
          406
          407
          408
          409
          410
          411
          412
          413
          414
          415
          416
          417
          418
          419
          420
          421
          422
          423
          424
          425
          426
          427
          428
          429
          430
          431
          432
          433
          434
          435
          436
          437
          438
          439
          440
          441
          442
          443
          444
          445
          446
          447
          448
          449
          450
          451
          452
          453
          454
          455
          456
          class ToolBridgeRegistry:
              """Registry for managing multiple tool bridges.
          
              Useful when multiple ACP agents need access to different toolsets.
              """
          
              def __init__(self) -> None:
                  self._bridges: dict[str, ToolManagerBridge] = {}
                  self._port_counter = 18000  # Start port range for auto-allocation
          
              async def create_bridge(
                  self,
                  name: str,
                  tool_manager: ToolManager,
                  pool: AgentPool[Any],
                  *,
                  owner_agent_name: str | None = None,
                  input_provider: InputProvider | None = None,
              ) -> ToolManagerBridge:
                  """Create and register a new bridge.
          
                  Args:
                      name: Unique name for this bridge
                      tool_manager: ToolManager to expose
                      pool: Agent pool for context
                      owner_agent_name: Optional owner agent name
                      input_provider: Optional input provider
          
                  Returns:
                      Started ToolManagerBridge
                  """
                  if name in self._bridges:
                      msg = f"Bridge {name!r} already exists"
                      raise ValueError(msg)
          
                  config = BridgeConfig(port=self._port_counter, server_name=f"llmling-{name}")
                  self._port_counter += 1
          
                  bridge = ToolManagerBridge(
                      tool_manager=tool_manager,
                      pool=pool,
                      config=config,
                      owner_agent_name=owner_agent_name,
                      input_provider=input_provider,
                  )
                  await bridge.start()
                  self._bridges[name] = bridge
                  return bridge
          
              async def get_bridge(self, name: str) -> ToolManagerBridge:
                  """Get a bridge by name."""
                  if name not in self._bridges:
                      msg = f"Bridge {name!r} not found"
                      raise KeyError(msg)
                  return self._bridges[name]
          
              async def remove_bridge(self, name: str) -> None:
                  """Stop and remove a bridge."""
                  if name in self._bridges:
                      await self._bridges[name].stop()
                      del self._bridges[name]
          
              async def close_all(self) -> None:
                  """Stop all bridges."""
                  for bridge in list(self._bridges.values()):
                      await bridge.stop()
                  self._bridges.clear()
          
              def get_all_mcp_configs(self) -> list[HttpMcpServer | SseMcpServer]:
                  """Get MCP server configs for all active bridges."""
                  return [bridge.get_mcp_server_config() for bridge in self._bridges.values()]
          

          close_all async

          close_all() -> None
          

          Stop all bridges.

          Source code in src/llmling_agent/mcp_server/tool_bridge.py
          448
          449
          450
          451
          452
          async def close_all(self) -> None:
              """Stop all bridges."""
              for bridge in list(self._bridges.values()):
                  await bridge.stop()
              self._bridges.clear()
          

          create_bridge async

          create_bridge(
              name: str,
              tool_manager: ToolManager,
              pool: AgentPool[Any],
              *,
              owner_agent_name: str | None = None,
              input_provider: InputProvider | None = None
          ) -> ToolManagerBridge
          

          Create and register a new bridge.

          Parameters:

          Name Type Description Default
          name str

          Unique name for this bridge

          required
          tool_manager ToolManager

          ToolManager to expose

          required
          pool AgentPool[Any]

          Agent pool for context

          required
          owner_agent_name str | None

          Optional owner agent name

          None
          input_provider InputProvider | None

          Optional input provider

          None

          Returns:

          Type Description
          ToolManagerBridge

          Started ToolManagerBridge

          Source code in src/llmling_agent/mcp_server/tool_bridge.py
          396
          397
          398
          399
          400
          401
          402
          403
          404
          405
          406
          407
          408
          409
          410
          411
          412
          413
          414
          415
          416
          417
          418
          419
          420
          421
          422
          423
          424
          425
          426
          427
          428
          429
          430
          431
          432
          433
          async def create_bridge(
              self,
              name: str,
              tool_manager: ToolManager,
              pool: AgentPool[Any],
              *,
              owner_agent_name: str | None = None,
              input_provider: InputProvider | None = None,
          ) -> ToolManagerBridge:
              """Create and register a new bridge.
          
              Args:
                  name: Unique name for this bridge
                  tool_manager: ToolManager to expose
                  pool: Agent pool for context
                  owner_agent_name: Optional owner agent name
                  input_provider: Optional input provider
          
              Returns:
                  Started ToolManagerBridge
              """
              if name in self._bridges:
                  msg = f"Bridge {name!r} already exists"
                  raise ValueError(msg)
          
              config = BridgeConfig(port=self._port_counter, server_name=f"llmling-{name}")
              self._port_counter += 1
          
              bridge = ToolManagerBridge(
                  tool_manager=tool_manager,
                  pool=pool,
                  config=config,
                  owner_agent_name=owner_agent_name,
                  input_provider=input_provider,
              )
              await bridge.start()
              self._bridges[name] = bridge
              return bridge
          

          get_all_mcp_configs

          get_all_mcp_configs() -> list[HttpMcpServer | SseMcpServer]
          

          Get MCP server configs for all active bridges.

          Source code in src/llmling_agent/mcp_server/tool_bridge.py
          454
          455
          456
          def get_all_mcp_configs(self) -> list[HttpMcpServer | SseMcpServer]:
              """Get MCP server configs for all active bridges."""
              return [bridge.get_mcp_server_config() for bridge in self._bridges.values()]
          

          get_bridge async

          get_bridge(name: str) -> ToolManagerBridge
          

          Get a bridge by name.

          Source code in src/llmling_agent/mcp_server/tool_bridge.py
          435
          436
          437
          438
          439
          440
          async def get_bridge(self, name: str) -> ToolManagerBridge:
              """Get a bridge by name."""
              if name not in self._bridges:
                  msg = f"Bridge {name!r} not found"
                  raise KeyError(msg)
              return self._bridges[name]
          

          remove_bridge async

          remove_bridge(name: str) -> None
          

          Stop and remove a bridge.

          Source code in src/llmling_agent/mcp_server/tool_bridge.py
          442
          443
          444
          445
          446
          async def remove_bridge(self, name: str) -> None:
              """Stop and remove a bridge."""
              if name in self._bridges:
                  await self._bridges[name].stop()
                  del self._bridges[name]
          

          ToolManagerBridge dataclass

          Exposes a ToolManager's tools as an MCP server for ACP agents.

          This bridge allows external ACP agents to access our internal toolsets (SubagentTools, AgentManagementTools, etc.) via HTTP MCP transport.

          The bridge creates synthetic AgentContext instances for tool invocations, allowing tools that need pool access to work correctly.

          Example
          async with AgentPool() as pool:
              agent = pool.agents["my_agent"]
              bridge = ToolManagerBridge(
                  tool_manager=agent.tools,
                  pool=pool,
                  config=BridgeConfig(port=8765),
              )
              async with bridge:
                  # Bridge is running, get MCP config for ACP agent
                  mcp_config = bridge.get_mcp_server_config()
                  # Pass to ACP agent...
          
          Source code in src/llmling_agent/mcp_server/tool_bridge.py
           65
           66
           67
           68
           69
           70
           71
           72
           73
           74
           75
           76
           77
           78
           79
           80
           81
           82
           83
           84
           85
           86
           87
           88
           89
           90
           91
           92
           93
           94
           95
           96
           97
           98
           99
          100
          101
          102
          103
          104
          105
          106
          107
          108
          109
          110
          111
          112
          113
          114
          115
          116
          117
          118
          119
          120
          121
          122
          123
          124
          125
          126
          127
          128
          129
          130
          131
          132
          133
          134
          135
          136
          137
          138
          139
          140
          141
          142
          143
          144
          145
          146
          147
          148
          149
          150
          151
          152
          153
          154
          155
          156
          157
          158
          159
          160
          161
          162
          163
          164
          165
          166
          167
          168
          169
          170
          171
          172
          173
          174
          175
          176
          177
          178
          179
          180
          181
          182
          183
          184
          185
          186
          187
          188
          189
          190
          191
          192
          193
          194
          195
          196
          197
          198
          199
          200
          201
          202
          203
          204
          205
          206
          207
          208
          209
          210
          211
          212
          213
          214
          215
          216
          217
          218
          219
          220
          221
          222
          223
          224
          225
          226
          227
          228
          229
          230
          231
          232
          233
          234
          235
          236
          237
          238
          239
          240
          241
          242
          243
          244
          245
          246
          247
          248
          249
          250
          251
          252
          253
          254
          255
          256
          257
          258
          259
          260
          261
          262
          263
          264
          265
          266
          267
          268
          269
          270
          271
          272
          273
          274
          275
          276
          277
          278
          279
          280
          281
          282
          283
          284
          285
          286
          287
          288
          289
          290
          291
          292
          293
          294
          295
          296
          297
          298
          299
          300
          301
          302
          303
          304
          305
          306
          307
          308
          309
          @dataclass
          class ToolManagerBridge:
              """Exposes a ToolManager's tools as an MCP server for ACP agents.
          
              This bridge allows external ACP agents to access our internal toolsets
              (SubagentTools, AgentManagementTools, etc.) via HTTP MCP transport.
          
              The bridge creates synthetic AgentContext instances for tool invocations,
              allowing tools that need pool access to work correctly.
          
              Example:
                  ```python
                  async with AgentPool() as pool:
                      agent = pool.agents["my_agent"]
                      bridge = ToolManagerBridge(
                          tool_manager=agent.tools,
                          pool=pool,
                          config=BridgeConfig(port=8765),
                      )
                      async with bridge:
                          # Bridge is running, get MCP config for ACP agent
                          mcp_config = bridge.get_mcp_server_config()
                          # Pass to ACP agent...
                  ```
              """
          
              tool_manager: ToolManager
              """The ToolManager whose tools to expose."""
          
              pool: AgentPool[Any]
              """Agent pool for context creation."""
          
              config: BridgeConfig = field(default_factory=BridgeConfig)
              """Bridge configuration."""
          
              owner_agent_name: str | None = None
              """Name of the agent that owns this bridge (for context creation)."""
          
              input_provider: InputProvider | None = None
              """Optional input provider for tool confirmations."""
          
              _mcp: FastMCP | None = field(default=None, init=False, repr=False)
              """FastMCP server instance."""
          
              _server: Server | None = field(default=None, init=False, repr=False)
              """Uvicorn server instance."""
          
              _server_task: asyncio.Task[None] | None = field(default=None, init=False, repr=False)
              """Background task running the server."""
          
              _actual_port: int | None = field(default=None, init=False, repr=False)
              """Actual port the server is bound to."""
          
              async def __aenter__(self) -> Self:
                  """Start the MCP server."""
                  await self.start()
                  return self
          
              async def __aexit__(self, *args: object) -> None:
                  """Stop the MCP server."""
                  await self.stop()
          
              async def start(self) -> None:
                  """Start the HTTP MCP server in the background."""
                  self._mcp = FastMCP(name=self.config.server_name)
                  await self._register_tools()
                  await self._start_server()
          
              async def stop(self) -> None:
                  """Stop the HTTP MCP server."""
                  if self._server:
                      self._server.should_exit = True
                      if self._server_task:
                          try:
                              await asyncio.wait_for(self._server_task, timeout=5.0)
                          except TimeoutError:
                              self._server_task.cancel()
                              with suppress(asyncio.CancelledError):
                                  await self._server_task
                      self._server = None
                      self._server_task = None
                  self._mcp = None
                  self._actual_port = None
                  logger.info("ToolManagerBridge stopped")
          
              @property
              def port(self) -> int:
                  """Get the actual port the server is running on."""
                  if self._actual_port is None:
                      msg = "Server not started"
                      raise RuntimeError(msg)
                  return self._actual_port
          
              @property
              def url(self) -> str:
                  """Get the server URL."""
                  path = "/sse" if self.config.transport == "sse" else "/mcp"
                  return f"http://{self.config.host}:{self.port}{path}"
          
              def get_mcp_server_config(self) -> HttpMcpServer | SseMcpServer:
                  """Get ACP-compatible MCP server configuration.
          
                  Returns config suitable for passing to ACP agent's NewSessionRequest.
                  """
                  from acp.schema.mcp import HttpMcpServer, SseMcpServer
          
                  url = HttpUrl(self.url)
                  if self.config.transport == "sse":
                      return SseMcpServer(name=self.config.server_name, url=url, headers=[])
                  return HttpMcpServer(name=self.config.server_name, url=url, headers=[])
          
              def _create_proxy_context(
                  self,
                  tool_name: str,
                  tool_call_id: str,
                  tool_input: dict[str, Any],
                  mcp_ctx: Context,
              ) -> AgentContext[None]:
                  """Create a synthetic AgentContext for MCP tool invocation.
          
                  This context provides pool access for delegation tools while
                  bridging progress reporting to MCP.
                  """
                  from llmling_agent.agent.context import AgentContext
                  from llmling_agent.models.agents import AgentConfig
                  from llmling_agent.models.manifest import AgentsManifest
          
                  # Use owner agent's config or create minimal one
                  agent_config: AgentConfig
                  definition: AgentsManifest
                  if self.owner_agent_name and self.owner_agent_name in self.pool.agents:
                      agent = self.pool.agents[self.owner_agent_name]
                      agent_config = agent.context.config
                      definition = agent.context.definition
                  else:
                      # Create minimal config for bridge-only usage
                      agent_config = AgentConfig(name="bridge")
                      definition = AgentsManifest()
          
                  return AgentContext(
                      node_name=self.owner_agent_name or "bridge",
                      pool=self.pool,
                      config=agent_config,
                      definition=definition,
                      input_provider=self.input_provider,
                      data=None,
                      tool_name=tool_name,
                      tool_call_id=tool_call_id,
                      tool_input=tool_input,
                  )
          
              async def _register_tools(self) -> None:
                  """Register all ToolManager tools with the FastMCP server."""
                  if not self._mcp:
                      return
          
                  tools = await self.tool_manager.get_tools(state="enabled")
                  for tool in tools:
                      self._register_single_tool(tool)
                  msg = "Registered tools with MCP bridge"
                  logger.info(msg, tool_count=len(tools), tools=[t.name for t in tools])
          
              def _register_single_tool(self, tool: Tool) -> None:
                  """Register a single tool with the FastMCP server."""
                  if not self._mcp:
                      return
          
                  # Create a custom FastMCP Tool that wraps our tool
                  bridge_tool = _BridgeTool(tool=tool, bridge=self)
                  self._mcp.add_tool(bridge_tool)
          
              async def invoke_tool_with_context(
                  self,
                  tool: Tool,
                  agent_ctx: AgentContext[None],
                  kwargs: dict[str, Any],
              ) -> Any:
                  """Invoke a tool with proper context injection.
          
                  Handles tools that expect AgentContext, RunContext, or neither.
                  """
                  from llmling_agent.agent.context import AgentContext as AgentContextType
          
                  fn = tool.callable
                  sig = inspect.signature(fn)
          
                  # Check what context types the tool expects
                  needs_agent_ctx = any(
                      param.annotation is AgentContextType
                      or (
                          hasattr(param.annotation, "__origin__")
                          and param.annotation.__origin__ is AgentContextType
                      )
                      or str(param.annotation).startswith("AgentContext")
                      for param in sig.parameters.values()
                  )
          
                  # Find parameter name for AgentContext if needed
                  agent_ctx_param: str | None = None
                  if needs_agent_ctx:
                      for name, param in sig.parameters.items():
                          annotation = param.annotation
                          if annotation is AgentContextType or str(annotation).startswith("AgentContext"):
                              agent_ctx_param = name
                              break
          
                  # Invoke with appropriate context injection
                  if agent_ctx_param:
                      kwargs[agent_ctx_param] = agent_ctx
          
                  # Execute the tool
                  result = fn(**kwargs)
                  if inspect.isawaitable(result):
                      result = await result
          
                  return result
          
              async def _start_server(self) -> None:
                  """Start the uvicorn server in the background."""
                  import socket
          
                  import uvicorn
          
                  if not self._mcp:
                      msg = "MCP server not initialized"
                      raise RuntimeError(msg)
          
                  # Determine actual port (auto-select if 0)
                  port = self.config.port
                  if port == 0:
                      with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
                          s.bind((self.config.host, 0))
                          port = s.getsockname()[1]
                  self._actual_port = port
                  # Create the ASGI app
                  app = self._mcp.http_app(transport=self.config.transport)  # type: ignore[arg-type]
                  # Configure uvicorn
                  cfg = uvicorn.Config(app=app, host=self.config.host, port=port, log_level="warning")
                  self._server = uvicorn.Server(cfg)
                  # Start server in background task
                  name = f"mcp-bridge-{self.config.server_name}"
                  self._server_task = asyncio.create_task(self._server.serve(), name=name)
                  await asyncio.sleep(0.1)  # Wait briefly for server to start
                  msg = "ToolManagerBridge started"
                  logger.info(msg, url=self.url, transport=self.config.transport)
          

          config class-attribute instance-attribute

          config: BridgeConfig = field(default_factory=BridgeConfig)
          

          Bridge configuration.

          input_provider class-attribute instance-attribute

          input_provider: InputProvider | None = None
          

          Optional input provider for tool confirmations.

          owner_agent_name class-attribute instance-attribute

          owner_agent_name: str | None = None
          

          Name of the agent that owns this bridge (for context creation).

          pool instance-attribute

          pool: AgentPool[Any]
          

          Agent pool for context creation.

          port property

          port: int
          

          Get the actual port the server is running on.

          tool_manager instance-attribute

          tool_manager: ToolManager
          

          The ToolManager whose tools to expose.

          url property

          url: str
          

          Get the server URL.

          __aenter__ async

          __aenter__() -> Self
          

          Start the MCP server.

          Source code in src/llmling_agent/mcp_server/tool_bridge.py
          118
          119
          120
          121
          async def __aenter__(self) -> Self:
              """Start the MCP server."""
              await self.start()
              return self
          

          __aexit__ async

          __aexit__(*args: object) -> None
          

          Stop the MCP server.

          Source code in src/llmling_agent/mcp_server/tool_bridge.py
          123
          124
          125
          async def __aexit__(self, *args: object) -> None:
              """Stop the MCP server."""
              await self.stop()
          

          get_mcp_server_config

          get_mcp_server_config() -> HttpMcpServer | SseMcpServer
          

          Get ACP-compatible MCP server configuration.

          Returns config suitable for passing to ACP agent's NewSessionRequest.

          Source code in src/llmling_agent/mcp_server/tool_bridge.py
          164
          165
          166
          167
          168
          169
          170
          171
          172
          173
          174
          def get_mcp_server_config(self) -> HttpMcpServer | SseMcpServer:
              """Get ACP-compatible MCP server configuration.
          
              Returns config suitable for passing to ACP agent's NewSessionRequest.
              """
              from acp.schema.mcp import HttpMcpServer, SseMcpServer
          
              url = HttpUrl(self.url)
              if self.config.transport == "sse":
                  return SseMcpServer(name=self.config.server_name, url=url, headers=[])
              return HttpMcpServer(name=self.config.server_name, url=url, headers=[])
          

          invoke_tool_with_context async

          invoke_tool_with_context(tool: Tool, agent_ctx: AgentContext[None], kwargs: dict[str, Any]) -> Any
          

          Invoke a tool with proper context injection.

          Handles tools that expect AgentContext, RunContext, or neither.

          Source code in src/llmling_agent/mcp_server/tool_bridge.py
          236
          237
          238
          239
          240
          241
          242
          243
          244
          245
          246
          247
          248
          249
          250
          251
          252
          253
          254
          255
          256
          257
          258
          259
          260
          261
          262
          263
          264
          265
          266
          267
          268
          269
          270
          271
          272
          273
          274
          275
          276
          277
          278
          279
          280
          async def invoke_tool_with_context(
              self,
              tool: Tool,
              agent_ctx: AgentContext[None],
              kwargs: dict[str, Any],
          ) -> Any:
              """Invoke a tool with proper context injection.
          
              Handles tools that expect AgentContext, RunContext, or neither.
              """
              from llmling_agent.agent.context import AgentContext as AgentContextType
          
              fn = tool.callable
              sig = inspect.signature(fn)
          
              # Check what context types the tool expects
              needs_agent_ctx = any(
                  param.annotation is AgentContextType
                  or (
                      hasattr(param.annotation, "__origin__")
                      and param.annotation.__origin__ is AgentContextType
                  )
                  or str(param.annotation).startswith("AgentContext")
                  for param in sig.parameters.values()
              )
          
              # Find parameter name for AgentContext if needed
              agent_ctx_param: str | None = None
              if needs_agent_ctx:
                  for name, param in sig.parameters.items():
                      annotation = param.annotation
                      if annotation is AgentContextType or str(annotation).startswith("AgentContext"):
                          agent_ctx_param = name
                          break
          
              # Invoke with appropriate context injection
              if agent_ctx_param:
                  kwargs[agent_ctx_param] = agent_ctx
          
              # Execute the tool
              result = fn(**kwargs)
              if inspect.isawaitable(result):
                  result = await result
          
              return result
          

          start async

          start() -> None
          

          Start the HTTP MCP server in the background.

          Source code in src/llmling_agent/mcp_server/tool_bridge.py
          127
          128
          129
          130
          131
          async def start(self) -> None:
              """Start the HTTP MCP server in the background."""
              self._mcp = FastMCP(name=self.config.server_name)
              await self._register_tools()
              await self._start_server()
          

          stop async

          stop() -> None
          

          Stop the HTTP MCP server.

          Source code in src/llmling_agent/mcp_server/tool_bridge.py
          133
          134
          135
          136
          137
          138
          139
          140
          141
          142
          143
          144
          145
          146
          147
          148
          async def stop(self) -> None:
              """Stop the HTTP MCP server."""
              if self._server:
                  self._server.should_exit = True
                  if self._server_task:
                      try:
                          await asyncio.wait_for(self._server_task, timeout=5.0)
                      except TimeoutError:
                          self._server_task.cancel()
                          with suppress(asyncio.CancelledError):
                              await self._server_task
                  self._server = None
                  self._server_task = None
              self._mcp = None
              self._actual_port = None
              logger.info("ToolManagerBridge stopped")
          

          create_tool_bridge async

          create_tool_bridge(
              tool_manager: ToolManager,
              pool: AgentPool[Any],
              *,
              host: str = "127.0.0.1",
              port: int = 0,
              transport: str = "sse",
              owner_agent_name: str | None = None,
              input_provider: InputProvider | None = None
          ) -> AsyncIterator[ToolManagerBridge]
          

          Create and start a ToolManagerBridge as a context manager.

          Parameters:

          Name Type Description Default
          tool_manager ToolManager

          ToolManager whose tools to expose

          required
          pool AgentPool[Any]

          Agent pool for context creation

          required
          host str

          Host to bind to

          '127.0.0.1'
          port int

          Port to bind to (0 = auto-select)

          0
          transport str

          Transport protocol ('sse' or 'streamable-http')

          'sse'
          owner_agent_name str | None

          Name of owning agent for context

          None
          input_provider InputProvider | None

          Optional input provider

          None

          Yields:

          Type Description
          AsyncIterator[ToolManagerBridge]

          Running ToolManagerBridge instance

          Source code in src/llmling_agent/mcp_server/tool_bridge.py
          349
          350
          351
          352
          353
          354
          355
          356
          357
          358
          359
          360
          361
          362
          363
          364
          365
          366
          367
          368
          369
          370
          371
          372
          373
          374
          375
          376
          377
          378
          379
          380
          381
          382
          383
          @asynccontextmanager
          async def create_tool_bridge(
              tool_manager: ToolManager,
              pool: AgentPool[Any],
              *,
              host: str = "127.0.0.1",
              port: int = 0,
              transport: str = "sse",
              owner_agent_name: str | None = None,
              input_provider: InputProvider | None = None,
          ) -> AsyncIterator[ToolManagerBridge]:
              """Create and start a ToolManagerBridge as a context manager.
          
              Args:
                  tool_manager: ToolManager whose tools to expose
                  pool: Agent pool for context creation
                  host: Host to bind to
                  port: Port to bind to (0 = auto-select)
                  transport: Transport protocol ('sse' or 'streamable-http')
                  owner_agent_name: Name of owning agent for context
                  input_provider: Optional input provider
          
              Yields:
                  Running ToolManagerBridge instance
              """
              config = BridgeConfig(host=host, port=port, transport=transport)
              bridge = ToolManagerBridge(
                  tool_manager=tool_manager,
                  pool=pool,
                  config=config,
                  owner_agent_name=owner_agent_name,
                  input_provider=input_provider,
              )
              async with bridge:
                  yield bridge