> ## Documentation Index
> Fetch the complete documentation index at: https://sendmux.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# LangGraph

> Load Sendmux mailbox and sending tools into a LangGraph agent through the LangChain MCP adapters.

Use this page to load Sendmux tools into a <a href="https://langchain-ai.github.io/langgraph/" rel="nofollow noopener noreferrer" target="_blank">LangGraph</a> agent. The <a href="https://github.com/langchain-ai/langchain-mcp-adapters" rel="nofollow noopener noreferrer" target="_blank">LangChain MCP adapters</a> convert MCP tools into LangChain tools, so anything that accepts a tool list will accept them.

<Warning>
  Replace placeholder keys and tokens before running any snippet. Do not commit
  `smx_root_`, `smx_mbx_`, or private HTTP bearer tokens to version control.
</Warning>

## Requirements

* Python 3.10 or newer.
* A Sendmux key for the surface you are calling. Mailbox work needs an `smx_mbx_` key or a scoped `smx_agent_` token.

## Install

```bash theme={null}
pip install langchain-mcp-adapters langgraph sendmux-mcp
```

## Connect over local stdio

The adapter launches the server and passes your key through the subprocess environment. Values written as `${VAR}` are expanded from the current environment, so the key never appears in source.

```python client.py theme={null}
from langchain_mcp_adapters.client import MultiServerMCPClient

client = MultiServerMCPClient(
    {
        "sendmux": {
            "transport": "stdio",
            "command": "sendmux-mcp-mailbox",
            "args": [],
            "env": {"SENDMUX_API_KEY": "${SENDMUX_MAILBOX_API_KEY}"},
        }
    }
)
```

Run more than one surface by switching to the `sendmux-mcp` entry point and naming the surfaces:

```python theme={null}
"sendmux": {
    "transport": "stdio",
    "command": "sendmux-mcp",
    "args": [],
    "env": {
        "SENDMUX_MCP_SURFACES": "mailbox,sending",
        "SENDMUX_MAILBOX_API_KEY": "${SENDMUX_MAILBOX_API_KEY}",
        "SENDMUX_SENDING_API_KEY": "${SENDMUX_SENDING_API_KEY}",
    },
}
```

## Connect over private HTTP

Use this when your graph runs somewhere it cannot spawn a process. Start the server yourself:

```bash theme={null}
SENDMUX_API_KEY=smx_mbx_... \
SENDMUX_MCP_HTTP_BEARER_TOKEN=local-mcp-token \
sendmux-mcp-mailbox --transport http --host 127.0.0.1 --port 8765
```

Then connect with the streamable HTTP transport and send the bearer token:

```python client.py theme={null}
from langchain_mcp_adapters.client import MultiServerMCPClient

client = MultiServerMCPClient(
    {
        "sendmux": {
            "transport": "streamable_http",
            "url": "http://127.0.0.1:8765/mcp",
            "headers": {"Authorization": "Bearer local-mcp-token"},
        }
    }
)
```

## Build the agent

`get_tools()` returns LangChain tools you can hand to a prebuilt agent or bind to a model inside your own graph.

```python agent.py theme={null}
import asyncio

from langchain.agents import create_agent

from client import client


async def main() -> None:
    tools = await client.get_tools()

    agent = create_agent(
        "openai:gpt-4.1",
        tools,
        prompt=(
            "You triage the mailbox you have been granted. "
            "Search before you read, and quote the message you acted on."
        ),
    )

    result = await agent.ainvoke(
        {"messages": "What arrived overnight that needs a reply?"}
    )
    print(result["messages"][-1].content)


asyncio.run(main())
```

<Note>
  Set `tool_name_prefix=True` on `MultiServerMCPClient` when you connect Sendmux
  alongside other MCP servers. It prefixes tool names with the server name and
  prevents collisions.
</Note>

## Give each user their own mailbox

Mailbox-scoped keys are the isolation boundary. Build a client per tenant rather than sharing one across the graph, so the agent working one tenant structurally cannot read another tenant's mail.

```python theme={null}
def client_for(mailbox_key: str) -> MultiServerMCPClient:
    return MultiServerMCPClient(
        {
            "sendmux": {
                "transport": "stdio",
                "command": "sendmux-mcp-mailbox",
                "args": [],
                "env": {"SENDMUX_API_KEY": mailbox_key},
            }
        }
    )
```

## Sending stays gated

A durable `smx_agent_` token includes `mailbox.read` and `email.receive`, not `email.send`. After a named human owner accepts the invite and approves sending, exchange the durable token for a one-hour Sending-resource token and pass that as `SENDMUX_SENDING_API_KEY`.

## Troubleshooting

<AccordionGroup>
  <Accordion title="get_tools returns an empty list">
    Confirm the surfaces the server started with. `sendmux-mcp` requires
    `SENDMUX_MCP_SURFACES`; the single-surface entry points do not.
  </Accordion>

  <Accordion title="The subprocess exits immediately">
    Check the key prefix. Mailbox accepts `smx_mbx_` or a scoped `smx_agent_`,
    Sending accepts a send-capable `smx_mbx_` or an owner-approved
    Sending-resource `smx_agent_`, and Management requires `smx_root_`.
  </Accordion>

  <Accordion title="Tool errors stop the graph">
    Set `handle_tool_errors=True` on `MultiServerMCPClient` to return errors as
    tool messages the model can react to instead of raising.
  </Accordion>

  <Accordion title="You granted more than one mailbox">
    Start the workflow with `mailbox_list_granted_mailboxes` and pass the
    returned `mailbox_id` to tools that act on one mailbox.
  </Accordion>
</AccordionGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Agent frameworks" icon="layer-group" href="/docs/ai-integrations/frameworks">
    Compare connections across frameworks.
  </Card>

  <Card title="MCP" icon="plug" href="/docs/ai-integrations/mcp">
    Review environment variables and tool discovery.
  </Card>

  <Card title="Mailbox API guides" icon="inbox" href="/docs/developer-tools/mailbox-api/search-and-batch">
    Use search and batch operations efficiently.
  </Card>

  <Card title="Python SDK" icon="code" href="/docs/developer-tools/sdks/python">
    Call Sendmux directly when you want full endpoint coverage.
  </Card>
</CardGroup>
