# LangChain and MCPmailer

LangChain and LangGraph agents pick up the MCPmailer tools through langchain-mcp-adapters.

langchain-mcp-adapters turns an MCP server into ordinary LangChain tools, so the same list works in a LangGraph graph or a plain agent with no extra wrapping.

## Setup

1. **Install the adapter** langchain-mcp-adapters converts MCP tools into LangChain tools.
1. **Create a mailbox** One per agent, so its address and its key are the same identity.
1. **Build the client** One MultiServerMCPClient can hold MCPmailer alongside your other servers.
1. **Hand the tools to an agent** The same list works in create_agent or a LangGraph node.

## Install

```bash
pip install langchain langchain-mcp-adapters
```

## LangChain (Python)

```py
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import create_agent

client = MultiServerMCPClient({
    "mcpmailer": {
        "transport": "streamable_http",
        "url": "https://connect.mcpmailer.com/mcp",
        "headers": {"Authorization": "Bearer mmk_live_..."},
    }
})

agent = create_agent("openai:gpt-4.1", await client.get_tools())
```

## Answer unread mail

get_tools returns plain LangChain tools, so this is an ordinary agent invocation. Nothing about the graph changes because the tools arrived over MCP.

```py
import os
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import create_agent

client = MultiServerMCPClient({
    "mcpmailer": {
        "transport": "streamable_http",
        "url": "https://connect.mcpmailer.com/mcp",
        "headers": {"Authorization": f"Bearer {os.environ['MCPMAILER_KEY']}"},
    }
})

agent = create_agent(
    "openai:gpt-4.1",
    await client.get_tools(),
    prompt="You answer support email. Reply in thread, never start new ones.",
)

result = await agent.ainvoke(
    {"messages": "Check for unread mail and answer anything you can."}
)
print(result["messages"][-1].content)
```

## Worth knowing

### A session per call, unless you ask otherwise

get_tools opens a new session for each tool invocation. For a run that makes several calls in a row, use the client session() context manager and keep one open.

### Prefix names when you load several servers

tool_name_prefix=True namespaces our tools, which matters once a second MCP server in the same client also exposes something called search.

### Async only

get_tools and ainvoke are coroutines. In a sync codebase, drive them from asyncio.run rather than reaching for the sync agent helpers.


Docs: https://mcpmailer.com/docs.md