MCP

Connect to any MCP server as a context provider.

Connect to any MCP (Model Context Protocol) server. The provider wraps the server's tools in a sub-agent, exposing them as query_mcp_<name>.

Use GitHub’s hosted read-only endpoint for this example. Create a GitHub personal access token with access to the repositories you intend to query, then install the dependencies in a virtual environment:

uv pip install -U "agno[mcp]" openai
export OPENAI_API_KEY="your-openai-api-key"
export GITHUB_TOKEN="your-github-personal-access-token"

Save as mcp_context.py and run python mcp_context.py:

mcp_context.py
import asyncio
import os

from agno.agent import Agent
from agno.context.mcp import MCPContextProvider
from agno.models.openai import OpenAIResponses

async def main():
    github = MCPContextProvider(
        server_name="github",
        transport="streamable-http",
        url="https://api.githubcopilot.com/mcp/readonly",
        headers={"Authorization": f"Bearer {os.environ['GITHUB_TOKEN']}"},
        model=OpenAIResponses(id="gpt-5.4-mini"),
        query_timeout=60,
    )
    try:
        await github.asetup()
        status = await github.astatus()
        if not status.ok:
            raise RuntimeError(status.detail)
        agent = Agent(
            model=OpenAIResponses(id="gpt-5.4"),
            tools=github.get_tools(),
            instructions=github.instructions(),
        )
        await agent.aprint_response("List my recent pull requests")
    finally:
        await github.aclose()

if __name__ == "__main__":
    asyncio.run(main())

The outer tool is query_mcp_github. An MCP query wrapper can invoke any selected server tool, including writes. This example restricts tools on the GitHub server using its /readonly endpoint. For other servers, configure their permissions or an explicit mcp_kwargs={"include_tools": [...]} allowlist. The default sub-agent prompt permits a write when the caller asks for it; it is not an access-control boundary.

Transport Options

Configuration fragment: run your installed local MCP server. Set its required environment and use its real executable and arguments.

mcp = MCPContextProvider(
    server_name="local-server",
    transport="stdio",
    command="python",
    args=["/absolute/path/to/your_mcp_server.py"],
)

These transport fragments reuse the imports above and require a running server. The SSE/HTTP URLs and bearer value are placeholders for your service.

Configuration

ParameterTypeDefaultDescription
server_namestrrequiredName of the MCP server. Used in tool name.
transportstrrequired"stdio", "sse", or "streamable-http".
commandstrNoneCommand to run (stdio transport).
argslist[str]NoneCommand arguments (stdio transport).
urlstrNoneServer URL (sse/http transports).
headersdictNoneHTTP headers (sse/http transports).
envdictNoneEnvironment variables for the subprocess.
mcp_kwargsdictNoneForward MCPTools options such as include_tools or exclude_tools; supplied keys override provider-generated options.
query_timeoutfloatNonePositive query-tool deadline (Python 3.11+), including acquisition and answer streaming.
timeout_secondsint30Connection timeout.
idstr"mcp_<name>"Tool becomes query_<id>.
modelModelNoneModel for the sub-agent.

Tools Exposed

ToolDescription
query_mcp_<name>Query the MCP server. Sub-agent calls the server's tools internally.

Lifecycle Management

Keep setup, queries and teardown in the same async lifecycle, as in the complete example. asetup() is best-effort: it logs a failed connection and returns normally. await astatus() retries the connection and reports its result; synchronous status() can report ok=True with “not yet connected” and is not a startup gate.

Use aquery() for direct calls. Synchronous query() raises NotImplementedError. query_timeout bounds the exposed query tool, not direct calls, raw tools or updates. See query deadlines.

Resources