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

# Overview

> Programmatic client for interacting with MCP servers

`MCPClient` is an async Python client for talking to any MCP server. It handles the MCP handshake (`initialize`), transport setup, and session management—so you can focus on the operations you want to perform.

Use `MCPClient` when you want **explicit, predictable control**, like:

* **Testing MCP servers** during development
* **Building applications** that need reliable MCP interactions
* **Building higher-level clients** (including "agentic" flows) on top of a typed protocol layer

## Quick start

Connect → do work → close.

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import asyncio
from dedalus_mcp.client import MCPClient

async def main():
    # Local dev default when running `await server.serve()`
    client = await MCPClient.connect("http://127.0.0.1:8000/mcp")
    try:
        tools = await client.list_tools()
        result = await client.call_tool("add", {"a": 5, "b": 3})
        print(result)
    finally:
        await client.close()

asyncio.run(main())
```

Prefer `async with` if you want guaranteed cleanup:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from dedalus_mcp.client import MCPClient

async with await MCPClient.connect("http://127.0.0.1:8000/mcp") as client:
    tools = await client.list_tools()
```

## Connection

### Connect

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from dedalus_mcp.client import MCPClient

client = await MCPClient.connect("http://127.0.0.1:8000/mcp")
```

### Protocol info

After connecting, `initialize_result` is populated:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
print(f"Server: {client.initialize_result.serverInfo.name}")
print(f"Protocol: {client.initialize_result.protocolVersion}")
print(f"Session: {client.session_id}")
```

### Close

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
await client.close()
```

### Alternative: `open_connection(...)`

`open_connection(...)` is a convenience wrapper that yields a connected `MCPClient` and cleans up automatically:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from dedalus_mcp.client import open_connection

async with open_connection("http://127.0.0.1:8000/mcp") as client:
    tools = await client.list_tools()
```

### Ping

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
await client.ping()
```

## Operations

Most client code falls into one of these buckets:

<CardGroup cols={3}>
  <Card title="Tools" icon="wrench" href="/sdk/mcp/python/client/tools">
    List and call server-side functions
  </Card>

  <Card title="Resources" icon="database" href="/sdk/mcp/python/client/resources">
    List and read data sources
  </Card>

  <Card title="Prompts" icon="message" href="/sdk/mcp/python/client/prompts">
    List and get message templates
  </Card>
</CardGroup>

## Client capabilities (server → client)

Some MCP features are initiated by the server. If you want to support them, you configure handlers when connecting.

<CardGroup cols={2}>
  <Card title="Sampling" icon="brain" href="/sdk/mcp/python/client/sampling">
    Handle LLM completion requests from servers
  </Card>

  <Card title="Elicitation" icon="message-question" href="/sdk/mcp/python/client/elicitation">
    Gather user input during tool execution
  </Card>

  <Card title="Roots" icon="folder-tree" href="/sdk/mcp/python/client/roots">
    Advertise filesystem boundaries to servers
  </Card>

  <Card title="Logging" icon="terminal" href="/sdk/mcp/python/client/logging">
    Receive log messages from servers
  </Card>
</CardGroup>

## Authentication

For protected MCP servers:

<CardGroup cols={2}>
  <Card title="Bearer Auth" icon="key" href="/sdk/mcp/python/client/bearer-auth">
    API keys and service tokens
  </Card>

  <Card title="OAuth" icon="lock" href="/sdk/mcp/python/client/oauth">
    User consent and delegated access via browser flow
  </Card>
</CardGroup>

### DPoP authentication

For servers using DPoP (RFC 9449) sender-constrained tokens:

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from dedalus_mcp.auth.dpop import generate_dpop_keypair
from dedalus_mcp.client import DPoPAuth, MCPClient

dpop_key, _ = generate_dpop_keypair()
auth = DPoPAuth(access_token="eyJ...", dpop_key=dpop_key)

# Local dev:
client = await MCPClient.connect("http://127.0.0.1:8000/mcp", auth=auth)

# Production:
# client = await MCPClient.connect("<your MCP endpoint URL>", auth=auth)
```
