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

> Learn how to integrate Model Context Protocol (MCP) servers into your agent using MCPStdioTool for local STDIO or MCPStreamableHTTPTool for remote HTTP endpoints within the Agent Framework.

- Repository: [Microsoft/agent-framework](https://github.com/microsoft/agent-framework)
- Tags: how-to-guide
- Published: 2026-04-05

---

**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`](https://github.com/microsoft/agent-framework/blob/main/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`](https://github.com/microsoft/agent-framework/blob/main/_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`](https://github.com/microsoft/agent-framework/blob/main/_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`](https://github.com/microsoft/agent-framework/blob/main/_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.

```python
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.

```python
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`](https://github.com/microsoft/agent-framework/blob/main/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`](https://github.com/microsoft/agent-framework/blob/main/agent_framework/__init__.py), making them available as top-level imports.

## Summary

- **`MCPTool`** in [`_mcp.py`](https://github.com/microsoft/agent-framework/blob/main/_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.