Skip to content
85 changes: 85 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,91 @@ async def main():
tool_result = await session.call_tool("echo", {"message": "hello"})
```

### OAuth Authentication for Clients

The SDK supports OAuth 2.0 client authentication for secure access to MCP servers that require authentication:

```python
from mcp.client.auth import UnauthorizedError
from mcp.client.oauth_providers import InMemoryOAuthProvider
from mcp.client.streamable_http import streamablehttp_client
from mcp.shared.auth import OAuthClientMetadata
from mcp import ClientSession

# Create an OAuth provider
oauth_provider = InMemoryOAuthProvider(
redirect_url="http://localhost:8080/callback",
client_metadata=OAuthClientMetadata(
redirect_uris=["http://localhost:8080/callback"],
client_name="My MCP Client",
scope="tools resources", # Request specific scopes
),
)


async def main():
# Connect with OAuth authentication
async with streamablehttp_client(
"https://example.com/mcp",
auth_provider=oauth_provider,
) as (read_stream, write_stream, _):
# Create a session
async with ClientSession(read_stream, write_stream) as session:
# Initialize (this may trigger OAuth flow)
try:
await session.initialize()
# Use authenticated session
result = await session.call_tool("protected_tool", {"arg": "value"})
except UnauthorizedError:
# Handle authorization required
print("Authorization required. Check your browser.")


# Handle OAuth callback after user authorization
async def handle_callback(authorization_code: str):
from mcp.client.streamable_http import StreamableHTTPTransport

# Create a transport instance to handle auth completion
transport = StreamableHTTPTransport(
url="https://example.com/mcp",
auth_provider=oauth_provider,
)

# Exchange authorization code for tokens
await transport.finish_auth(authorization_code)
print("Authorization successful!")
```

#### Custom OAuth Providers

You can implement custom OAuth storage by creating your own provider:

```python
from mcp.client.oauth_providers import InMemoryOAuthProvider


class DatabaseOAuthProvider(InMemoryOAuthProvider):
async def save_tokens(self, tokens):
# Save to database
# await db.save_tokens(self.client_id, tokens)
pass

async def tokens(self):
# Load from database
# return await db.load_tokens(self.client_id)
return None

# Implement other methods as needed...
```

The OAuth client implementation supports:

- Dynamic client registration
- Authorization code flow with PKCE
- Token refresh
- Multiple storage providers (in-memory and file-based included)
- Automatic token management and retry logic

### MCP Primitives

The MCP protocol defines three core primitives that servers can implement:
Expand Down
70 changes: 70 additions & 0 deletions examples/clients/simple-auth-client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Simple Auth Client Example

A demonstration of how to use the MCP Python SDK with OAuth authentication over streamable HTTP transport.

## Features

- OAuth 2.0 authentication with PKCE
- Streamable HTTP transport
- Interactive command-line interface

## Installation

```bash
cd examples/clients/simple-auth-client
uv sync --reinstall
```

## Usage

### 1. Start an MCP server with OAuth support

```bash
# Example with mcp-simple-auth
cd path/to/mcp-simple-auth
uv run mcp-simple-auth --transport streamable-http --port 3001
```

### 2. Run the client

```bash
uv run mcp-simple-auth-client

# Or with custom server URL
MCP_SERVER_URL=http://localhost:3001 uv run mcp-simple-auth-client
```

### 3. Complete OAuth flow

The client will open your browser for authentication. After completing OAuth, you can use commands:

- `list` - List available tools
- `call <tool_name> [args]` - Call a tool with optional JSON arguments
- `quit` - Exit

## Example

```
🔐 Simple MCP Auth Client
Connecting to: http://localhost:3001

Please visit the following URL to authorize the application:
http://localhost:3001/authorize?response_type=code&client_id=...

✅ Connected to MCP server at http://localhost:3001

mcp> list
📋 Available tools:
1. echo - Echo back the input text

mcp> call echo {"text": "Hello, world!"}
🔧 Tool 'echo' result:
Hello, world!

mcp> quit
👋 Goodbye!
```

## Configuration

- `MCP_SERVER_URL` - Server URL (default: http://localhost:3001)
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Simple OAuth client for MCP simple-auth server."""
Loading
Loading