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

# MCP Integration

> Connect agents to any MCP server for filesystem, database, and API tools

MCP (Model Context Protocol) lets agents connect to external tool servers, instantly adding file system access, database queries, API integrations, and more.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, MCP

agent = Agent(
    name="FileAgent",
    instructions="You help users manage their files.",
    tools=MCP("npx -y @modelcontextprotocol/server-filesystem /tmp"),
)

agent.start("List all files in the /tmp directory.")
```

The user asks to inspect the filesystem; the agent calls MCP tools on the connected server.

<Note>
  MCP tool turns are treated specially: a mid-response network failure surfaces `provider_outcome_unknown` instead of silently re-running the tool. See [Replay-Safe Retries](/docs/features/replay-safe-retries).
</Note>

<Warning>
  **Fail-closed behavior (PraisonAI [#4423](https://github.com/MervinPraison/PraisonAI/pull/4423), merged 2026-08-26):** `MCP(...)` now raises when a stdio server times out, errors on init, or advertises zero tools — instead of returning a usable-but-empty object that silently degrades `Agent(tools=mcp)` into a tool-less chat. Wrap construction in `try/except` if your app should degrade gracefully. Filters (`allowed_tools` / `disabled_tools`) that intentionally remove every tool are still allowed. See [Errors on construction](#errors-on-construction).
</Warning>

## Which MCP package do I need?

Three packages cover three MCP roles — connecting, light serving, and full hosting.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q{What do I want to do?}
    Q -->|Connect to external<br/>MCP servers| C["praisonaiagents[mcp]<br/>MCP class (this page)"]
    Q -->|Serve a small<br/>tool set| L["praisonai-code<br/>praisonai serve mcp"]
    Q -->|Serve full capabilities /<br/>recipes with auth| H["praisonai-mcp<br/>heavy host"]

    classDef question fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef client fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef light fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef heavy fill:#8B0000,stroke:#7C90A0,color:#fff

    class Q question
    class C client
    class L light
    class H heavy
```

This page covers the **client** layer. To serve your own agents, see the [praisonai-mcp Package](/docs/features/praisonai-mcp-package) and [The Three MCP Layers](/docs/features/mcp-three-layers).

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "MCP Flow"
        Agent[🤖 Agent] --> MCP[🔌 MCP Client]
        MCP --> Server[🖥️ MCP Server]
        Server --> Tools[🔧 Tools]
        Tools --> Server
        Server --> MCP
        MCP --> Agent
    end

    classDef agent fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef mcp fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef server fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff

    class Agent agent
    class MCP mcp
    class Server,Tools server
```

## Quick Start

<Steps>
  <Step title="Connect to an MCP server">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent, MCP

    agent = Agent(
        instructions="You can read and write files.",
        tools=MCP("npx -y @modelcontextprotocol/server-filesystem /tmp"),
    )
    agent.start("Create a file called notes.txt with the text 'Hello World'.")
    ```
  </Step>

  <Step title="SSE-based MCP server">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent, MCP

    agent = Agent(
        instructions="You can search and retrieve web content.",
        tools=MCP("https://mcp.example.com/sse"),
    )
    agent.start("Search for the latest news about AI.")
    ```
  </Step>

  <Step title="Streamable HTTP MCP server">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent, MCP

    # Streamable HTTP endpoint — auto-detected from the URL
    agent = Agent(
        name="RemoteToolAgent",
        instructions="Use the remote MCP tools to answer the user.",
        tools=MCP(
            "https://api.example.com/mcp",
            headers={"Authorization": "Bearer YOUR_TOKEN"},
            timeout=60,
        ),
    )

    agent.start("List the tools you have and use them to check the current weather in London.")
    ```

    Requires an up-to-date `mcp` package (`pip install -U 'mcp'`). The transport is powered by the official SDK's `streamablehttp_client`.

    Pass the full endpoint URL your server exposes. Bare-host URLs are no longer rewritten to `/mcp` (see [PraisonAI #3032](https://github.com/MervinPraison/PraisonAI/issues/3032)).
  </Step>

  <Step title="Multiple MCP servers">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent, MCP

    filesystem_tools = MCP("npx -y @modelcontextprotocol/server-filesystem /home/user")
    database_tools = MCP("npx -y @modelcontextprotocol/server-sqlite /db/app.sqlite")

    agent = Agent(
        instructions="You manage files and database records.",
        tools=[*filesystem_tools, *database_tools],
    )
    agent.start("Read the config file and update the database with its settings.")
    ```
  </Step>
</Steps>

***

## Three equivalent forms

`MCP(...)` accepts the command in three equivalent forms — pick whichever reads best for your stdio server.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Same MCP session, three ways to spell it"
        A["MCP('npx -y @pkg /tmp')<br/>all-in-one string"] --> Result[("command='npx'<br/>args=['-y', '@pkg', '/tmp']")]
        B["MCP('npx -y @pkg', args=['/tmp'])<br/>string + args"] --> Result
        C["MCP(command='npx',<br/>args=['-y', '@pkg', '/tmp'])<br/>fully separated"] --> Result
    end

    classDef form fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef result fill:#10B981,stroke:#7C90A0,color:#fff

    class A,B,C form
    class Result result
```

Pick the form that matches how the command reaches your code.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q{How does the command<br/>reach your code?}
    Q -->|As one string I paste from README| A["Form 1: MCP('cmd -flag arg')"]
    Q -->|As a base command + list<br/>of allowed paths / URLs| B["Form 2: MCP('cmd -flag', args=[paths...])"]
    Q -->|Programmatically constructed<br/>from separate variables| C["Form 3: MCP(command=cmd, args=[...])"]

    classDef question fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef form fill:#6366F1,stroke:#7C90A0,color:#fff

    class Q question
    class A,B,C form
```

<Tabs>
  <Tab title="Form 1 — single string">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent, MCP

    agent = Agent(
        name="FS",
        instructions="You manage files.",
        tools=MCP("npx -y @modelcontextprotocol/server-filesystem /tmp"),
    )
    agent.start("List files under /tmp")
    ```
  </Tab>

  <Tab title="Form 2 — string + args">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent, MCP

    allowed_dirs = ["/tmp", "/var/logs"]

    agent = Agent(
        name="FS",
        instructions="You manage files.",
        tools=MCP("npx -y @modelcontextprotocol/server-filesystem", args=allowed_dirs),
    )
    agent.start("List files in the allowed directories")
    ```
  </Tab>

  <Tab title="Form 3 — fully separated">
    ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    from praisonaiagents import Agent, MCP
    import os

    agent = Agent(
        name="GitHub",
        instructions="You manage GitHub issues.",
        tools=MCP(
            command="npx",
            args=["-y", "@modelcontextprotocol/server-github"],
            env={"GITHUB_PERSONAL_ACCESS_TOKEN": os.environ["GITHUB_TOKEN"]},
        ),
    )
    agent.start("List my open issues")
    ```
  </Tab>
</Tabs>

### Merge rules

A multi-token string is split with `shlex`: the first token becomes the command, and the remaining tokens are prepended to any explicit `args`.

| Input                                             | Resulting `cmd`     | Resulting `args`         |
| ------------------------------------------------- | ------------------- | ------------------------ |
| `MCP("npx -y @pkg /tmp")`                         | `"npx"`             | `["-y", "@pkg", "/tmp"]` |
| `MCP("npx -y @pkg", args=["/tmp"])`               | `"npx"`             | `["-y", "@pkg", "/tmp"]` |
| `MCP(command="npx", args=["-y", "@pkg", "/tmp"])` | `"npx"`             | `["-y", "@pkg", "/tmp"]` |
| `MCP("/usr/bin/python", args=["app.py"])`         | `"/usr/bin/python"` | `["app.py"]`             |
| `MCP('"/opt/my app"', args=["run"])`              | `"/opt/my app"`     | `["run"]`                |

<Note>
  `MCP("cmd multi word", args=[...])` requires PraisonAI containing [#3943](https://github.com/MervinPraison/PraisonAI/pull/3943) (merged 2026-08-15). On older versions this form silently discovered 0 tools — upgrade with `pip install -U praisonaiagents` or switch to Form 1 or Form 3.
</Note>

<Tip>
  On Windows, `shlex.split(..., posix=False)` is used and surrounding double-quotes are stripped from each token. Quote paths that contain spaces: `MCP('"C:\\Program Files\\node\\npx.cmd" -y @pkg')`.
</Tip>

***

## How It Works

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Agent
    participant MCP
    participant Server

    User->>Agent: Request
    Agent->>MCP: Connect to server
    MCP->>Server: Initialize + list tools
    Server-->>MCP: Available tools
    MCP-->>Agent: Tool definitions
    Agent->>MCP: Call tool
    MCP->>Server: Execute tool
    Server-->>MCP: Result
    MCP-->>Agent: Tool result
    Agent-->>User: Response
```

| Phase       | What happens                                          |
| ----------- | ----------------------------------------------------- |
| 1. Connect  | MCP client connects to the server on first use        |
| 2. Discover | Server reports its available tools                    |
| 3. Execute  | Agent calls tools via the MCP protocol                |
| 4. Return   | Results flow back through the MCP client to the agent |

For string forms, the command is parsed with `shlex` before the server spawns.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User as Your code
    participant MCP as MCP.__init__
    participant Shlex as shlex.split
    participant Runner as MCP stdio runner

    User->>MCP: MCP("npx -y @pkg", args=["/tmp"])
    MCP->>Shlex: split("npx -y @pkg")
    Shlex-->>MCP: ["npx", "-y", "@pkg"]
    MCP->>MCP: cmd = "npx"<br/>args = ["-y", "@pkg"] + ["/tmp"]
    MCP->>Runner: spawn("npx", ["-y", "@pkg", "/tmp"])
    Runner-->>User: tools discovered
```

***

## Errors on construction

Since PraisonAI [#4423](https://github.com/MervinPraison/PraisonAI/pull/4423) the stdio `MCP(...)` client fails closed instead of returning an empty tool list. Three errors can surface from `MCP.__init__`:

| Exception                                       | When                                                                                                  | What to do                                                                                                                                      |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `TimeoutError`                                  | The MCP server did not finish the handshake within `timeout=` seconds.                                | Increase `timeout=`, or diagnose why the subprocess never responded (Node not installed, wrong `npx` shim on Windows, offline `-y` install).    |
| `RuntimeError: MCP initialization failed: ...`  | The runner surfaced an init error from the server.                                                    | Read the wrapped error; usually a wrong command, missing package, or a server that crashed on startup.                                          |
| `RuntimeError: MCP server produced 0 tools ...` | The server initialized but listed no tools. Most common on Windows when `npx` is not the `.cmd` shim. | On Windows: `MCP(command="npx.cmd", args=["-y", "@pkg"])`. Or switch to a Python MCP server: `MCP(command=sys.executable, args=["server.py"])`. |

An explicit `allowed_tools` / `disabled_tools` filter that legitimately removes every tool is **not** an error and does not raise.

Pick the right recovery based on which error you see.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q{Which error<br/>from MCP?} 
    Q -->|TimeoutError| T[Raise timeout=<br/>or check Node / npx]
    Q -->|RuntimeError:<br/>init failed| I[Read wrapped error<br/>fix command / package]
    Q -->|RuntimeError:<br/>0 tools| Z{On Windows?}
    Z -->|Yes| W[Use command='npx.cmd']
    Z -->|No| P[Use command=sys.executable<br/>args=['server.py']]

    classDef question fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef timeout fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef fix fill:#10B981,stroke:#7C90A0,color:#fff

    class Q,Z question
    class T timeout
    class I,W,P fix
```

Wrap construction if you want to degrade gracefully.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, MCP

try:
    tools = MCP("npx -y @modelcontextprotocol/server-time", timeout=30)
except (TimeoutError, RuntimeError) as e:
    print(f"MCP unavailable: {e}")
    tools = []

agent = Agent(instructions="You are a helpful assistant.", tools=tools)
agent.start("What is the current time?")
```

### Timeout

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import MCP

try:
    tools = MCP("npx -y @modelcontextprotocol/server-time", timeout=5)
except TimeoutError as e:
    print(e)
    # MCP initialization timed out after 5 seconds
    # (command='npx' args=['-y', '@modelcontextprotocol/server-time']).
```

### Init error

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import MCP

try:
    tools = MCP("python /path/does/not/exist.py", timeout=30)
except RuntimeError as e:
    print(e)
    # MCP initialization failed: <underlying error>
    # (command='python' args=['/path/does/not/exist.py']).
```

### Zero tools on Windows

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import sys
from praisonaiagents import Agent, MCP

# Old shape that used to silently return zero tools on Windows:
# tools = MCP("npx -y @modelcontextprotocol/server-time")   # now raises

# Windows fix — pass the .cmd shim explicitly:
tools = MCP(command="npx.cmd", args=["-y", "@modelcontextprotocol/server-time"])

# Or use a Python MCP server (works on every platform):
tools = MCP(command=sys.executable, args=["path/to/server.py"])

agent = Agent(instructions="Use the time tool.", tools=tools)
agent.start("What is the current time in UTC?")
```

### Intentional empty via filter

A filter that removes every tool is a valid empty config and does not raise.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import MCP

# Server advertises tools, but the caller disables all of them.
tools = MCP(
    "npx -y @modelcontextprotocol/server-filesystem /tmp",
    disabled_tools=["read_file", "write_file", "list_directory"],
)
assert list(tools) == []
```

On Windows, see [Windows SDK Quickstart → Troubleshooting](/docs/features/windows-sdk-quickstart#troubleshooting). For transport details, see [MCP Transports](/docs/mcp/transports#fail-closed-on-empty-or-timed-out-servers).

***

## MCP Server Types

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q{What transport does the server use?}
    Q -->|Command line| Stdio[stdio\nnpx / python command]
    Q -->|Remote HTTP endpoint| HTTP[Streamable HTTP\nhttps://server/mcp]
    Q -->|Legacy SSE| SSE[SSE\nhttps://server/sse]

    classDef decision fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef type fill:#6366F1,stroke:#7C90A0,color:#fff

    class Q decision
    class Stdio,HTTP,SSE type
```

Remote Streamable HTTP servers connect through the official MCP SDK client.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant Agent
    participant MCP as MCP HTTP-Stream Client
    participant Server as Remote MCP Server

    User->>Agent: "Check the weather in London"
    Agent->>MCP: streamablehttp_client(url, headers, timeout)
    MCP->>Server: HTTP POST /mcp (initialize)
    Server-->>MCP: session established (SSE stream)
    MCP-->>Agent: tool list
    Agent->>MCP: call weather_tool(location="London")
    MCP->>Server: HTTP POST /mcp (tools/call)
    Server-->>MCP: result
    MCP-->>Agent: tool result
    Agent-->>User: "London is 12°C, cloudy…"
```

***

## Common Patterns

### Pattern 1 — File management agent

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, MCP

agent = Agent(
    name="FileManager",
    instructions="You help users organize and manage their files efficiently.",
    tools=MCP("npx -y @modelcontextprotocol/server-filesystem /home/user/documents"),
)
response = agent.start("Find all PDF files and create a summary list.")
print(response)
```

### Pattern 2 — Database agent

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, MCP

agent = Agent(
    name="DBAgent",
    instructions="You query and analyze database records.",
    tools=MCP("npx -y @modelcontextprotocol/server-sqlite /path/to/database.sqlite"),
)
agent.start("Show me all users who signed up in the last 30 days.")
```

### Pattern 3 — GitHub integration

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, MCP
import os

agent = Agent(
    name="GitHubAgent",
    instructions="You help manage GitHub repositories and issues.",
    tools=MCP(
        "npx -y @modelcontextprotocol/server-github",
        env={"GITHUB_PERSONAL_ACCESS_TOKEN": os.environ["GITHUB_TOKEN"]},
    ),
)
agent.start("List the 5 most recent open issues in my repository.")
```

***

## Best Practices

<AccordionGroup>
  <Accordion title="Use official MCP servers">
    Start with the official `@modelcontextprotocol` npm packages for common integrations (filesystem, SQLite, GitHub, etc.). They're well-tested and actively maintained.
  </Accordion>

  <Accordion title="Scope filesystem access">
    When using the filesystem MCP server, pass the narrowest directory path you need. Giving access to `/` or `/home` when you only need `/app/data` creates unnecessary risk.
  </Accordion>

  <Accordion title="Environment variables for credentials">
    Never hardcode API keys or tokens in your code. Pass them as environment variables to the MCP server via the `env` parameter, and source them from your environment or secrets manager.
  </Accordion>

  <Accordion title="Combine multiple servers">
    Agents can use tools from multiple MCP servers simultaneously. Unpack each server's tools with `*MCP(...)` and combine them into a single `tools` list for maximum capability. Loading via [`load_mcp_tools`](/docs/features/load-mcp-tools) auto-namespaces each server's tools (e.g. `filesystem_search`, `github_search`) so overlapping names never collide.
  </Accordion>

  <Accordion title="Handle server availability">
    `MCP(...)` fails closed since PraisonAI [#4423](https://github.com/MervinPraison/PraisonAI/pull/4423): a stdio server that times out, errors on init, or lists zero tools raises `TimeoutError` or `RuntimeError` at construction. Wrap the constructor in `try/except (TimeoutError, RuntimeError)` when your app should keep running without those tools, and log the wrapped `command` / `args` / `init_error` in the error message for diagnosis.
  </Accordion>
</AccordionGroup>

***

## Related

<CardGroup cols={2}>
  <Card icon="wrench" href="/docs/features/tools">
    Tools — built-in tools and custom tool functions
  </Card>

  <Card icon="plug" href="/docs/features/mcp-tool-filtering">
    MCP Tool Filtering — filter which tools to expose per agent
  </Card>
</CardGroup>
