openai-agents-mcp

repository·main·Indexed 41 days ago

https://github.com/lastmile-ai/openai-agents-mcp

An MCP (Model Context Protocol) extension for the OpenAI Agents SDK (version 0.0.8) that enables agents to use MCP tools alongside native SDK tools. It provides an extended Agent class, RunnerContext for configuration via mcp_agent.config.yaml, and MCPAgentHooks for managing the lifecycle of MCP-enabled agents.

Tokens
6K
Snippets
21
Records
24
Agent score
51%

What's inside openai-agents-mcp

  1. How MCP servers and tools work with Agents SDK

    main

    The openai-agents-mcp extension allows you to connect OpenAI Agents to MCP servers. When you use the Agent class from agents_mcp, the agent automatically aggregates tools from the specified mcp_servers alongside any local tools you provide. This creates a single, unified list of tools that the agent can use seamlessly.

    To use this extension, replace the standard import:

    # Instead of:
    # from agents import Agent
    
    # Use:
    from agents_mcp import Agent
    from agents_mcp import Agent
    
    agent = Agent(
        name="MCP Agent",
        instructions="You are a helpful assistant.",
        tools=[get_current_weather], # Local tools
        mcp_servers=["fetch", "filesystem"], # MCP servers defined in config
    )
  2. Configure MCP using different methods

    main

    There are four ways to configure MCP settings in the Agents SDK:

    If you have mcp_agent.config.yaml and mcp_agent.secrets.yaml in your project directory, the SDK finds them automatically.

    2. Explicit Config Path

    Pass the path to your config file via RunnerContext.

    from agents_mcp import RunnerContext
    
    context = RunnerContext(mcp_config_path="/path/to/mcp_agent.config.yaml")

    3. Programmatic Configuration

    Define settings directly in code using MCPSettings and MCPServerSettings from mcp_agent.config.

    from mcp_agent.config import MCPSettings, MCPServerSettings
    from agents_mcp import RunnerContext
    
    mcp_config = MCPSettings(
        servers={
            "fetch": MCPServerSettings(command="uvx", args=["mcp-server-fetch"]),
            "filesystem": MCPServerSettings(command="npx", args=["-y", "@modelcontextprotocol/server-filesystem", "."])
        }
    )
    
    context = RunnerContext(mcp_config=mcp_config)

    4. Custom Server Registry

    Use a custom ServerRegistry if you need specialized server management.

    from mcp_agent.mcp_server_registry import ServerRegistry
    from mcp_agent.config import get_settings
    from agents_mcp import Agent
    
    settings = get_settings("/path/to/config.yaml")
    server_registry = ServerRegistry(config=settings)
    
    agent = Agent(
        name="Custom Registry Agent",
        instructions="You have access to custom MCP servers.",
        mcp_servers=["fetch", "filesystem"],
        mcp_server_registry=server_registry
    )
  3. Configure MCP servers via mcp_agent.config.yaml

    main

    MCP servers are defined in an mcp_agent.config.yaml file located in your project directory or a parent directory. Each server entry requires a command and args.

    Example configuration:

    $schema: "https://raw.githubusercontent.com/lastmile-ai/mcp-agent/main/schema/mcp-agent.config.schema.json"
    
    mcp:
      servers:
        fetch:
          command: "uvx"
          args: ["mcp-server-fetch"]
        filesystem:
          command: "npx"
          args: ["-y", "@modelcontextprotocol/server-filesystem", "."]
        slack:
          command: "npx"
          args: ["-y", "@modelcontextprotocol/server-slack"]

    For sensitive information like API keys, use a separate mcp_agent.secrets.yaml file or environment variables.

  4. Stream responses from an MCP agent

    main

    To stream responses from an agent instead of waiting for the full result, use Runner.run_streamed(). Note that this method is not awaited directly; instead, you iterate over the events in the returned stream.

    from agents_mcp import Runner, ResponseTextDeltaEvent
    
    # Use run_streamed (do not await the call itself)
    result = Runner.run_streamed(
        agent,
        input="Print the first paragraph of https://openai.github.io/openai-agents-python/",
        context=context,
    )
    
    # Iterate through the stream events
    async for event in result.stream_events():
        if event.type == "raw_response_event" and isinstance(event.data, ResponseTextDeltaEvent):
            print(event.data.delta, end="", flush=True)
    result = Runner.run_streamed(  # Note: No await here
        agent,
        input="Print the first paragraph of https://openai.github.io/openai-agents-python/",
        context=context,
    )
    
    # Stream the events
    async for event in result.stream_events():
        if event.type == "raw_response_event" and isinstance(event.data, ResponseTextDeltaEvent):
            print(event.data.delta, end="", flush=True)
  5. Run an agent with MCP tools

    main

    To run an agent that uses both local tools and MCP servers, use Runner.run() with a RunnerContext.

    from agents_mcp import Agent, Runner, RunnerContext
    
    # Define agent with local tools and MCP servers
    agent = Agent(
        name="MCP Assistant",
        instructions="You are a helpful assistant with access to tools.",
        tools=[get_current_weather],
        mcp_servers=["fetch", "filesystem"],
    )
    
    # Execute the agent
    result = await Runner.run(
        agent,
        input="What's the weather in Miami? Also, can you fetch the OpenAI website?",
        context=RunnerContext(),
    )
    
    print(result.response.value)
  6. Configure MCP servers for an Agent

    main

    To use MCP tools, provide a list of server names to the mcp_servers argument when instantiating an Agent.

    • mcp_servers: A list[str] containing the names of the MCP servers to use. Each name must correspond to a server registered in your mcp_agent.config.yaml.
    • mcp_server_registry: (Optional) A ServerRegistry instance. If not provided, the agent will attempt to load it from the run context (initialized from mcp_agent.config.yaml).
  7. Use RunnerContext to manage MCP settings

    main

    The RunnerContext class is used with MCP-enabled Agents to manage Model Context Protocol (MCP) server configurations. It is designed to be compliant with the TContext generic parameter in the OpenAI Agent SDK.

    You can initialize a RunnerContext in two ways:

    1. Directly providing mcp_config: Pass an MCPSettings object containing your server configurations.
    2. Providing a mcp_config_path: Pass the file path to your mcp_agent.config.yaml file.

    Automatic Discovery: If both mcp_config and mcp_config_path are omitted, the context will attempt to find a file named mcp_agent.config.yaml by searching recursively upwards from the current working directory.

    You can also pass arbitrary keyword arguments (**kwargs) to the constructor to attach additional custom attributes to the context instance.

    from agents_mcp.context import RunnerContext
    
    # Option 1: Using a config path
    context = RunnerContext(mcp_config_path="./path/to/mcp_agent.config.yaml")
    
    # Option 2: Using an MCPSettings object (if available)
    # context = RunnerContext(mcp_config=my_mcp_settings)
    
    # Option 3: Adding custom attributes
    context = RunnerContext(mcp_config_path="mcp_agent.config.yaml", custom_id="agent-001")
    print(context.custom_id)  # Output: agent-001
  8. Convert MCP content to text

    main

    The mcp_content_to_text function converts MCP content types (Text, Image, or Embedded Resources) into a single string representation suitable for LLM context.

    Conversion Logic:

    • TextContent: Returns the raw text.
    • ImageContent: Returns a placeholder string: [Image: <mime_type>].
    • EmbeddedResource:
      • If it contains text, returns the text.
      • If it contains a blob, returns [Resource: <mime_type>].
    • Lists: If passed a list of content items, they are joined by newlines.
    • Fallback: Returns the string representation of the object.
    from agents_mcp.tools import mcp_content_to_text
    
    # Example with a single text content item
    text = mcp_content_to_text(text_content_item)
    
    # Example with a list of content items
    full_text = mcp_content_to_text([item1, item2])
  9. Transform an Agent into a tool with as_tool()

    main

    The as_tool() method allows you to wrap an Agent so it can be called as a tool by other agents.

    Key Differences from Handoffs:

    1. Input: Unlike handoffs (which pass conversation history), this tool receives generated input.
    2. Control Flow: Unlike handoffs (where the new agent takes over), this tool is called as a standard tool, and the original agent continues the conversation after receiving the result.

    Arguments:

    • tool_name (str | None): The name of the tool. Defaults to the agent's name (transformed to function style).
    • tool_description (str | None): A description of what the tool does.
    • custom_output_extractor (Callable): A function to extract specific data from the RunResult. If omitted, the last message from the agent is used.
    # Example of transforming an agent into a tool
    agent_tool = agent.as_tool(
        tool_name="research_assistant",
        tool_description="Use this tool to perform deep research on a topic."
    )
    
    # The resulting 'agent_tool' can now be passed into the 'tools' list of another Agent
    other_agent = Agent(name="Manager", tools=[agent_tool])
  10. Load an MCP server registry with load_mcp_server_registry

    main

    Use load_mcp_server_registry to initialize a ServerRegistry instance. You can provide an existing MCPSettings object or specify a path to a configuration file.

    • If config is provided, it uses that MCPSettings object.
    • If config is not provided, config_path must be provided to load settings from a file.
    from agents_mcp.server_registry import load_mcp_server_registry
    
    # Option 1: Load from a config file path
    registry = load_mcp_server_registry(config_path="path/to/mcp_agent.config.yaml")
    
    # Option 2: Load from an existing MCPSettings object
    # registry = load_mcp_server_registry(config=my_mcp_settings)
  11. Create an agent with MCP server support

    main

    To use Model Context Protocol (MCP) tools alongside standard local tools, use the Agent class from agents_mcp. You can specify which MCP servers to enable by passing a list of server names to the mcp_servers argument. These server names must correspond to servers defined in your mcp_agent.config.yaml file.

    from agents import Runner
    from agents_mcp import Agent
    
    # existing_tools_still_work refers to your standard local tools
    agent = Agent(
        name="MCP Assistant",
        tools=[existing_tools_still_work],
        mcp_servers=["fetch", "filesystem"]
    )
    
    result = await Runner.run(
        starting_agent=agent,
        input="Hello",
        context=Context()
    )