> ## 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 OAuth Authentication

> Authenticate with remote MCP servers using OAuth 2.1

Connect to OAuth-protected remote MCP servers with PraisonAI's built-in OAuth 2.1 support.

<Warning>
  OAuth implementation is **experimental**. The current implementation stores placeholder tokens only and real token exchange is **not yet implemented**. For production use, we recommend using `headers:` with API key authentication instead.
</Warning>

## Status

| Capability                                               | Status                        |
| -------------------------------------------------------- | ----------------------------- |
| OAuth utilities (PKCE, state, callback)                  | ✅ Production ready            |
| Token storage (`~/.praisonai/mcp-auth.json`, 0600 perms) | ✅ Production ready            |
| Token exchange via authorisation server                  | ⚠️ Experimental (placeholder) |
| `praisonai mcp auth` CLI flow                            | ⚠️ Experimental               |
| Wired into `mcp_http_stream.py` for live requests        | ❌ Not yet                     |

## Quick Start

<Steps>
  <Step title="Configure Remote Server">
    Add a remote MCP server with OAuth to your config. Servers declared in `~/.praisonai/config.yaml` (global) or `./.praisonai/config.yaml` (project) are automatically picked up by `praisonai run`:

    ```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    # ~/.praisonai/config.yaml  (or .praisonai/config.yaml for project-scoped)
    mcp:
      servers:
        github:
          type: remote
          url: https://api.github.com/mcp
          oauth:
            client_id: your_client_id
            scopes:
              - repo
              - user
    ```
  </Step>

  <Step title="Authenticate">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    praisonai mcp auth github
    ```

    This opens your browser for OAuth authorization.
  </Step>

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

    agent = Agent(
        instructions="You help with GitHub tasks",
        tools=MCP("https://api.github.com/mcp")
    )
    ```
  </Step>
</Steps>

## CLI Commands

### Authenticate

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai mcp auth <server-name>
```

**\[EXPERIMENTAL]** Authenticate with an OAuth-enabled MCP server. WARNING: OAuth implementation is currently experimental and stores placeholder tokens only.

Initiates OAuth 2.1 authorization flow:

1. Opens browser for user authorization
2. Waits for callback with authorization code
3. Stores tokens securely in `~/.praisonai/mcp-auth.json`

**Options:**

| Option      | Default | Description                       |
| ----------- | ------- | --------------------------------- |
| `--timeout` | `300`   | Timeout for OAuth flow in seconds |

### Logout

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai mcp logout <server-name>
```

Removes stored OAuth credentials for a server.

**Options:**

| Option  | Description              |
| ------- | ------------------------ |
| `--yes` | Skip confirmation prompt |

### List Servers

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai mcp list
```

Shows all configured servers with their type (local/remote) and status.

## Configuration Schema

### Remote Server with OAuth

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
mcp:
  servers:
    my-server:
      type: remote
      url: https://mcp.example.com/mcp
      enabled: true
      timeout: 30000  # milliseconds
      oauth:
        client_id: your_client_id
        client_secret: your_client_secret  # optional
        scopes:
          - read
          - write
```

### Remote Server with API Key

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
mcp:
  servers:
    tavily:
      type: remote
      url: https://mcp.tavily.com/mcp
      headers:
        Authorization: Bearer ${TAVILY_API_KEY}
```

### Local Server (stdio)

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
mcp:
  servers:
    filesystem:
      type: local
      command: npx
      args:
        - -y
        - "@anthropic-ai/mcp-server-filesystem"
        - /tmp
```

## Python SDK

### Using Auth Storage

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

# Initialize storage
storage = MCPAuthStorage()

# Check if authenticated
entry = storage.get("github")
if entry and entry.get("tokens"):
    print("Authenticated!")
    print(f"Token: {entry['tokens']['access_token'][:20]}...")

# Check token expiration
if storage.is_token_expired("github"):
    print("Token expired, need to re-authenticate")
```

### PKCE Utilities

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents.mcp import (
    generate_state,
    generate_code_verifier,
    generate_code_challenge,
    get_redirect_url
)

# Generate PKCE parameters
state = generate_state()
verifier = generate_code_verifier()
challenge = generate_code_challenge(verifier)

# Get redirect URL for OAuth provider
redirect_url = get_redirect_url()
print(f"Redirect URL: {redirect_url}")
# Output: http://127.0.0.1:19876/mcp/oauth/callback
```

### OAuth Callback Handler

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents.mcp import OAuthCallbackHandler, generate_state
import webbrowser

handler = OAuthCallbackHandler()
state = generate_state()

# Build authorization URL
auth_url = f"https://auth.example.com/authorize?state={state}&..."

# Open browser
webbrowser.open(auth_url)

# Wait for callback (blocks until received or timeout)
try:
    code = handler.wait_for_callback(state, timeout=300)
    print(f"Received authorization code: {code[:20]}...")
except TimeoutError:
    print("OAuth flow timed out")
```

## Token Storage

OAuth tokens are stored in `~/.praisonai/mcp-auth.json` with secure file permissions (0600).

**Storage structure:**

```json theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
{
  "github": {
    "server_url": "https://api.github.com/mcp",
    "tokens": {
      "access_token": "gho_xxx...",
      "refresh_token": "ghr_xxx...",
      "expires_at": 1234567890,
      "scope": "repo user"
    },
    "client_info": {
      "client_id": "xxx",
      "client_secret": "xxx"
    }
  }
}
```

## Security

* **File permissions**: Token storage uses 0600 permissions (owner read/write only)
* **PKCE**: All OAuth flows use PKCE (Proof Key for Code Exchange) for security
* **State parameter**: CSRF protection via random state parameter
* **URL validation**: Tokens are invalidated if server URL changes

## Troubleshooting

| Issue                              | Solution                              |
| ---------------------------------- | ------------------------------------- |
| "Server not found"                 | Add server to config first            |
| "OAuth is only for remote servers" | Use `type: remote` in config          |
| "Authentication timed out"         | Increase `--timeout` or check browser |
| "No credentials stored"            | Run `praisonai mcp auth <name>` first |

## Related

* [MCP Server](./praisonai-mcp) - Deploy PraisonAI as MCP server
* [Remote MCP](./mcp-remote) - Connect to remote MCP servers
* [MCP Tools](./mcp-tools) - Using MCP tools with agents
