How to Use Model Context Protocol (MCP) with MCPStdioTool and MCPStreamableHTTPTool in Agent Framework

The Microsoft Agent Framework treats MCP servers as attachable tools, enabling agents to discover and invoke remote functions through either local STDIO processes via MCPStdioTool or HTTP endpoints via MCPStreamableHTTPTool.

The Model Context Protocol (MCP) provides a standardized interface for AI agents to interact with external data sources and services. According to the microsoft/agent-framework source code, the integration resides in python/packages/core/agent_framework/_mcp.py, where the abstract MCPTool class manages the MCP lifecycle and two concrete implementations handle different transport mechanisms. This guide demonstrates how to instantiate these tools, manage connections with async context managers, and authenticate HTTP requests.

Architecture of MCP Integration

The MCP implementation in the Agent Framework follows a layered architecture that abstracts transport details while exposing a unified interface to agents.

The MCPTool Base Class

The MCPTool class serves as the foundation for all MCP integrations in _mcp.py. It handles session management, automatic reconnection, and the conversion of remote MCP functions into local FunctionTool objects that agents can invoke.

Key methods include:

  • connect() – Establishes the client transport and opens a ClientSession with the MCP server
  • load_tools() and load_prompts() – Query the server for available capabilities and wrap them as callable functions
  • call_tool() – Forwards invocations to the remote server, injects OpenTelemetry metadata, and handles response parsing
  • __aenter__/__aexit__ – Enable use as an async context manager for automatic connection cleanup

MCPStdioTool Implementation

Located at line 1244 of _mcp.py, MCPStdioTool wraps the stdio_client from the official MCP SDK. It spawns a local subprocess defined by a command and argument list, communicating over standard input/output streams. This approach is ideal for local development or when running self-contained MCP executables.

MCPStreamableHTTPTool Implementation

Starting at line 1380 of _mcp.py, MCPStreamableHTTPTool utilizes streamable_http_client for connecting to hosted MCP services. It supports custom HTTP header injection through a header_provider callback, which receives runtime kwargs and returns headers for authentication or request signing. The class uses a ContextVar to propagate these headers into the underlying HTTP transport during tool invocation.

Using MCPStdioTool for Local Subprocess Servers

MCPStdioTool is the optimal choice when your MCP server runs as a local command-line executable, such as the official filesystem server or custom Python scripts.

The class accepts command and args parameters that define how to spawn the subprocess. When wrapped in an async context manager, it automatically starts the server, discovers available functions, and cleans up the process on exit.

from agent_framework import Agent, MCPStdioTool
from agent_framework.openai import OpenAIChatClient

async def demo_stdio():
    # Initialize the tool with server command details

    mcp_tool = MCPStdioTool(
        name="filesystem",
        command="npx",
        args=["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
        description="File-system operations via MCP",
    )

    # Context manager handles connection lifecycle

    async with mcp_tool:
        agent = Agent(
            client=OpenAIChatClient(),
            name="DocsAgent",
            instructions="You are a helpful assistant that can read/write files.",
            tools=mcp_tool,  # All discovered functions become available

        )
        
        # Agent automatically calls remote MCP functions

        result = await agent.run("List the files in the current directory")
        print(result)

# asyncio.run(demo_stdio())

Key implementation details:

  • The tool spawns the process defined by command and args upon entering the context manager
  • All functions exposed by the MCP server (e.g., list_files, read_file) are automatically loaded via load_tools()
  • Connection errors trigger automatic reconnection attempts through the base class logic

Using MCPStreamableHTTPTool for HTTP Endpoints

For cloud-hosted MCP services or microservices architectures, MCPStreamableHTTPTool provides HTTP-based connectivity with support for dynamic authentication headers.

The header_provider callback enables per-request customization of HTTP headers. It receives the runtime kwargs from the agent invocation and returns a dictionary of headers, allowing you to inject bearer tokens, API keys, or correlation IDs.

from agent_framework import Agent, MCPStreamableHTTPTool
from agent_framework.openai import OpenAIChatClient

def auth_header_provider(kwargs: dict) -> dict[str, str]:
    """Dynamically generate headers for each tool call."""
    token = kwargs.get("auth_token", "unknown")
    return {"Authorization": f"Bearer {token}"}

async def demo_http():
    mcp_tool = MCPStreamableHTTPTool(
        name="learn-mcp",
        url="https://learn.microsoft.com/api/mcp",
        description="Microsoft Learn MCP endpoint",
        header_provider=auth_header_provider,  # Called on every invocation

    )

    async with mcp_tool:
        agent = Agent(
            client=OpenAIChatClient(),
            name="LearnAgent",
            instructions="You can query Microsoft Learn content via the MCP endpoint.",
            tools=mcp_tool,
        )
        
        # Pass runtime kwargs that header_provider can access

        result = await agent.run(
            "What is the latest version of the Agent Framework?",
            stream=False,
        )
        print(result)

# asyncio.run(demo_http())

Implementation specifics:

  • Headers returned by header_provider are temporarily stored in a ContextVar (_mcp_call_headers) during the request lifecycle
  • The overridden call_tool method injects these headers into the HTTP transport before delegating to the base implementation
  • You can provide a custom httpx.AsyncClient via the constructor, or let the tool create one automatically

For a complete end-to-end example, see python/samples/02-agents/providers/openai/client_with_local_mcp.py in the repository, which demonstrates streaming responses with MCPStreamableHTTPTool.

Selecting the Right Transport Protocol

Choose between STDIO and HTTP transports based on your deployment environment and security requirements.

  • Use MCPStdioTool when running local development servers, packaged CLI tools, or when network egress is restricted. The subprocess model provides isolation but requires the executable to be present on the local filesystem.

  • Use MCPStreamableHTTPTool when integrating with SaaS platforms, microservices, or geographically distributed teams. The HTTP transport supports load balancing and requires no local dependencies beyond network access, though you must implement header_provider for authentication.

Both classes are exported publicly from agent_framework/__init__.py, making them available as top-level imports.

Summary

  • MCPTool in _mcp.py provides the abstract foundation for MCP integration, handling session lifecycle and tool discovery
  • MCPStdioTool (line 1244) connects to local subprocesses via STDIO, ideal for command-line MCP servers
  • MCPStreamableHTTPTool (line 1380) connects to HTTP endpoints and supports dynamic headers via header_provider
  • Both implementations work as async context managers, ensuring proper connection cleanup
  • The framework automatically converts remote MCP functions into FunctionTool objects that agents invoke through standard agent.run() calls

Frequently Asked Questions

What is the difference between MCPStdioTool and MCPStreamableHTTPTool?

MCPStdioTool spawns a local subprocess and communicates over standard input/output streams, making it suitable for local executables like the filesystem server. MCPStreamableHTTPTool connects to remote HTTP endpoints using the streamable_http_client transport, designed for cloud-hosted MCP services that require network connectivity.

How do I authenticate requests with MCPStreamableHTTPTool?

Supply a header_provider callback function that receives the runtime kwargs from the agent invocation and returns a dictionary of HTTP headers. The tool injects these headers into every request through a ContextVar mechanism, enabling dynamic token injection without global state.

Can I use multiple MCP tools with a single Agent?

Yes. The Agent's tools parameter accepts a list, allowing you to pass multiple MCPTool instances simultaneously. Each tool establishes its own connection and registers its discovered functions, enabling agents to call functions across different MCP servers within the same conversation.

What happens if the MCP server disconnects during execution?

The base MCPTool class implements automatic reconnection logic. If the connection drops, the framework attempts to re-establish the session before failing the tool call, ensuring resilience against transient network issues or subprocess restarts.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →