Email for LangChain agents

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. 01

    Install the adapter

    langchain-mcp-adapters converts MCP tools into LangChain tools.

  2. 02

    Create a mailbox

    One per agent, so its address and its key are the same identity.

  3. 03

    Build the client

    One MultiServerMCPClient can hold MCPmailer alongside your other servers.

  4. 04

    Hand the tools to an agent

    The same list works in create_agent or a LangGraph node.

Install
pip install langchain langchain-mcp-adapters
LangChain (Python)
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.

Answer unread mail
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

01

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.

02

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.

03

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.

What LangChain can reach

The endpoint speaks Streamable HTTP MCP with 67 tools across mail, contacts, notes, and a vault, including send_email, read_message, search_inbox, and wait_for_reply. Errors are structured so LangChain can react: a quota rejection includes the reset time.