Skip to main content
Glama
fctr-identity

TAKO MCP Server for Okta

README.md
<div align="center">
  <a href="https://fctr.io">
    <img src="https://fctr.io/images/logo.svg" alt="fctr.io" width="110" height="auto">
  </a>
  
  <p><em>Built by the Fctr Identity team • Not affiliated with Okta</em></p>
  
  <h1>TAKO MCP Server for Okta <i>(beta v0.1)</i></h1>
  
  <h3>⚔ Powered by Anthropic's Code Execution with MCP Architecture</h3>
  <p>Production-ready MCP server implementing Anthropic's <a href="https://www.anthropic.com/engineering/code-execution-with-mcp"><strong>Code Execution with MCP</strong></a> pattern with dual-mode operation, context-engineering, enhanced security sandbox, and enterprise-grade features.</p>

</div>

## Overview

A production-ready MCP server for Okta administration with dual-mode operation. **Successor to [okta-mcp-server](https://github.com/fctr-id/okta-mcp-server)**.

This server enables AI assistants to query Okta resources using the [Model Context Protocol](https://modelcontextprotocol.io). It is designed for IAM engineers, security teams, and Okta administrators who want to give their AI tools safe, controlled access to their Okta environment.

**Key Features:**
- šŸ”„ **Dual-Mode Operation** - Standard MCP server mode or autonomous agent mode
- 🌐 **Flexible Transports** - STDIO for desktop clients, HTTP for remote deployments
- šŸ”‘ **Okta Tokens** - API Token (simple) or OAuth2 with Private Key JWT (production)
- šŸ“Š **CSV Export** - Save query results to files for reporting
- šŸ”’ **Secure Execution** - AST-based sandbox with whitelisted operations
- āœ… **MCP Compliant** - Elicitation, Progress notifications, logging, and tool annotations

## šŸ“‹ Table of Contents

- [Core Concepts](#-core-concepts)
- [Quick Start](#-quick-start)
- [Configuration](#%EF%B8%8F-configuration)
  - [Okta Authentication](#okta-authentication)
- [MCP Client Setup](#-mcp-client-setup)
- [Available Tools](#%EF%B8%8F-available-tools)
- [Security](#-security)
- [Rate Limits](#-rate-limits)
- [Get Help](#-get-help)
- [License](#-license)

---

## 🧠 Core Concepts

Before installing, it's helpful to understand the two key configuration choices: **Mode** and **Transport**.

### 1. Operating Modes
Controls *how* the AI interacts with the server. Set via `ENABLE_AGENT_MODE` environment variable.

| Feature | Basic MCP Mode (`false`) | Agent Mode (`true`) |
|---------|--------------------------|---------------------|
| ***Context Size*** | Higher - all tools loaded upfront | Lower - progressive discovery |
| ***Token Cost*** | Higher initial cost | Lower initial cost |
| ***Use Case*** | MCP gateways, tool composition, granular control | Autonomous AI workflows |
| ***Architecture*** | Standard MCP tool exposure | Meta-tool discovery pattern |
| ***Data Fetching*** | Sample data (3 results) + endpoint metadata | Full result sets via code execution |
| ***Available Tools*** | `read_system_instructions`, `get_code_generation_prompt`, `execute_code`, `okta_*` tools | `get_available_operations`, `get_operation_details`, `get_code_generation_prompt`, `execute_code` |

### Basic MCP ServerMode (Default)

Tools exposed directly to the LLM. The AI calls `read_system_instructions()` first, then uses `okta_*` tools for sample data and `execute_code()` for full results.

![Basic MCP Mode](docs/images/default-mcp-mode-workflow.png)

**Can be used for:**
| Category | Supported Platforms |
|----------|---------------------|
| ***Desktop Clients*** | Claude Desktop, Cursor, Zed, VS Code (Windsurf) |
| ***Enterprise Gateways*** | Obot.ai, Smithery, Lasso Security |
| ***Agent Frameworks*** | LangGraph, LlamaIndex, Goose |

### Agent Mode

AI discovers APIs dynamically via `get_available_operations()` and `get_operation_details()`, then generates code for execution. This mode is ideal for complex, multi-step queries where the agent explores the API surface as needed.

![Agent Mode](docs/images/agent-mode-workflow.jpeg)

### 2. Transports
Controls *how* clients connect to the server.

| Transport | Description | Best For |
|-----------|-------------|----------|
| **STDIO** (Default) | Communicates via standard input/output pipes. | Local desktop apps (Claude, Cursor, VS Code). |
| **HTTP (SSE)** | Exposes a web server endpoint (`/mcp`). | Remote deployments, Docker, Web-based agents. |

---

## šŸš€ Quick Start

Choose the installation method that fits your workflow.

### Option A: Docker (Recommended)

The fastest way to get started without managing Python dependencies.

```bash
# 1. Clone the repository
git clone https://github.com/fctr-id/fctr-okta-mcp-server.git
cd fctr-okta-mcp-server

# 2. Create directories for persistent data
mkdir -p logs okta_results  # Windows: New-Item -ItemType Directory -Path logs, okta_results -Force

# 3. Create a .env file (see Configuration section for all options)
cp .env.sample .env
# Edit .env with your Okta credentials

# 4. Build with Docker
docker build --target stdio -t tako-mcp-server:stdio .  # STDIO mode
docker build --target http -t tako-mcp-server:http .    # HTTP mode
```

### Option B: Local Python (uv)

We recommend [uv](https://docs.astral.sh/uv/) for fast, reliable package management.

```bash
# 1. Clone and setup
git clone https://github.com/fctr-id/fctr-okta-mcp-server.git
cd fctr-okta-mcp-server

# 2. Create virtual environment
uv venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate

# 3. Install dependencies
uv pip install -e .

# 4. Create a .env file (see Configuration section for all options)
cp .env.sample .env
# Edit .env with your Okta credentials

# 5. Run (HTTP - for remote/web access)
python -m fctr_okta_mcp.server --http-transport --i-understand-the-risks
```

---

## āš™ļø Configuration

Configuration is managed via environment variables. Set these in a `.env` file or pass them directly.

### Environment Variables

| Variable | Required | Default | Description |
|----------|:--------:|---------|-------------|
| `OKTA_CLIENT_ORGURL` | Yes | - | Okta org URL (e.g., `https://example.okta.com`) |
| `TOKEN_METHOD` | | `API_TOKEN` | Auth method: `API_TOKEN` or `OAUTH2` |
| `OKTA_API_TOKEN` | * | - | API token (required if `TOKEN_METHOD=API_TOKEN`) |
| `OKTA_OAUTH2_CLIENT_ID` | * | - | OAuth2 client ID (required if `TOKEN_METHOD=OAUTH2`) |
| `OKTA_OAUTH2_PRIVATE_KEY_PEM` | * | - | Private key in PEM format |
| `OKTA_OAUTH2_SCOPES` | | `okta.users.read okta.groups.read okta.apps.read` | OAuth2 scopes |
| `ENABLE_AGENT_MODE` | | `false` | Enable Agent Mode |
| `MCP_BASE_URL` | | `http://127.0.0.1:8000` | Base URL for HTTP transport (supports https for reverse proxy) |
| `OKTA_CONCURRENT_LIMIT` | | `10` | Max concurrent API requests ([configure by plan](#-rate-limits)) |
| `OKTA_MCP_EXECUTION_TIMEOUT_SECONDS` | | `300` | Code execution timeout |
| `OKTA_MCP_LOG_LEVEL` | | `INFO` | Log level: `DEBUG`, `INFO`, `WARNING`, `ERROR` |

### Okta Authentication

<details>
<summary><strong>Option 1: API Token (Default)</strong></summary>

Best for development and simple deployments.

1. Go to **Okta Admin** → **Security** → **API** → **Tokens**
2. Create a new token with read permissions
3. Configure:

```env
TOKEN_METHOD=API_TOKEN
OKTA_API_TOKEN=your-api-token-here
```
</details>

<details>
<summary><strong>Option 2: OAuth2 with Private Key JWT (Recommended for Production)</strong></summary>

More secure, uses client credentials flow with private key JWT (RFC 7523).

**Step 1: Create OAuth2 App in Okta**
1. Go to **Okta Admin** → **Applications** → **Create App Integration**
2. Select **API Services** → **Next**
3. Name your application and click **Save**
4. Note the **Client ID**

**Step 2: Configure Public Key Authentication**
1. In your app, go to **General** → **Client Credentials** → **Edit**
2. Select **Public key / Private key**
3. Click **Add Key** → **Generate new key**
4. Download the private key (PEM format)
5. Click **Save**

**Step 3: Grant API Scopes**
1. Go to **Okta API Scopes** tab
2. Grant required scopes: `okta.users.read`, `okta.groups.read`, `okta.apps.read`, `okta.logs.read`, `okta.policies.read`

**Step 4: Configure Environment**
```env
TOKEN_METHOD=OAUTH2
OKTA_OAUTH2_CLIENT_ID=your-client-id
OKTA_OAUTH2_SCOPES=okta.users.read okta.groups.read okta.apps.read
OKTA_OAUTH2_PRIVATE_KEY_PEM="-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqh...
...your-private-key...
-----END PRIVATE KEY-----"
```

> **Tip**: The private key can be multi-line (as shown) or single-line with `\n` escapes.
</details>

---

## šŸ”Œ MCP Client Setup

### STDIO Transport (Desktop Clients)

For Claude Desktop, VS Code, Cursor, and other local MCP clients:

```json
{
  "mcpServers": {
    "tako-mcp": {
      "command": "path/to/.venv/Scripts/python",
      "args": ["-m", "fctr_okta_mcp.server"],
      "env": {
        "OKTA_CLIENT_ORGURL": "https://your-org.okta.com",
        "OKTA_API_TOKEN": "your_api_token",
        "ENABLE_AGENT_MODE": "true"
      }
    }
  }
}
```

### HTTP Transport (Remote/Web)

For web-based deployments, remote access, or programmatic clients.

**Start the server first:**
```bash
python -m fctr_okta_mcp.server --http-transport --i-understand-the-risks
```

Then configure your MCP client:
```json
{
  "mcpServers": {
    "tako-mcp": {
      "url": "http://localhost:8000/mcp",
      "type": "http"
    }
  }
}
```

### Docker (STDIO)

See [Quick Start - Docker](#option-a-docker-recommended) for build instructions.

```json
{
  "mcpServers": {
    "tako-mcp": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-v", "./logs:/app/logs",
        "-v", "./okta_results:/app/okta_results",
        "-e", "OKTA_CLIENT_ORGURL",
        "-e", "OKTA_API_TOKEN",
        "-e", "ENABLE_AGENT_MODE=true",
        "tako-mcp-server:stdio"
      ],
      "env": {
        "OKTA_CLIENT_ORGURL": "https://your-org.okta.com",
        "OKTA_API_TOKEN": "your_api_token"
      }
    }
  }
}
```

### Docker (HTTP)

For HTTP transport with Docker:

```bash
docker run -p 8000:8000 \
  -v ./logs:/app/logs \
  -v ./okta_results:/app/okta_results \
  -e OKTA_CLIENT_ORGURL=https://your-org.okta.com \
  -e OKTA_API_TOKEN=your_api_token \
  -e MCP_BASE_URL=http://localhost:8000 \
  tako-mcp-server:http
```

> **Note**: The server binds to `0.0.0.0:8000` inside the container (required for Docker networking), but `MCP_BASE_URL` controls what URL is reported to MCP clients.

---

## šŸ› ļø Available Tools

When in **Basic MCP Mode**, the following tools are available:

### User Management
- `okta_user_list` - List users with filtering, search, and pagination
- `okta_user_get` - Get detailed user profile by ID or login
- `okta_user_list_groups` - List groups a user belongs to
- `okta_user_list_applications` - List applications assigned to a user
- `okta_user_list_factors` - List enrolled authentication factors

### Group Operations
- `okta_group_list` - List groups with filtering and pagination
- `okta_group_get` - Get detailed group information
- `okta_group_list_users` - List members of a group
- `okta_group_list_applications` - List applications assigned to a group

### Application Management
- `okta_app_list` - List applications with filtering
- `okta_app_get` - Get detailed application information
- `okta_app_list_users` - List users assigned to an application
- `okta_app_list_groups` - List groups assigned to an application

### System Logs
- `okta_log_get_events` - Query system log events with advanced filtering

### Policies & Network Zones
- `okta_policy_list_rules` - List rules for a specific policy
- `okta_policy_get_rule` - Get detailed policy rule configuration
- `okta_network_list_zones` - List network zones
- `okta_network_get_zone` - Get detailed network zone information

### Utilities
- `okta_datetime_now` - Get current UTC timestamp for queries
- `okta_datetime_parse_relative` - Parse natural language time expressions (e.g., "24 hours ago")

> In **Agent Mode**, these tools are hidden. The agent uses `get_available_operations` to discover them dynamically.

---

## šŸ”’ Security

### Code Execution Sandbox

All generated Python code is validated before execution:

| Layer | Protection |
|-------|------------|
| **Pattern Blocking** | `os.system`, `subprocess`, `exec`, `eval`, `open` |
| **Import Control** | All modules pre-injected; imports blocked |
| **Function Whitelist** | Only safe builtins (`len`, `str`, `dict`, etc.) |
| **HTTP Restriction** | Only `GET` requests allowed |

### Data Privacy

- Okta data is sent to the AI model during queries
- Large result sets export to CSV; only summaries return to AI
- **Auto-Cleanup**: CSV files generated in HTTP mode are automatically deleted after 1 hour
- Ensure organizational policies permit AI processing of Okta data

---

## 🚨 Rate Limits

**Step 1:** Identify your Okta API rate limit percentage (we recommend setting it to 100% in the Okta Admin Console).

<img src="docs/images/api-rate-limits.png" alt="API Rate Limits Configuration" width="800">

**Step 2:** Set `OKTA_CONCURRENT_LIMIT` in your `.env` file based on your Okta plan:

| Tenant Type | API Rate Limit % | Recommended Setting | Tested Maximum (āš ļø) |
|-------------|------------------|---------------------|---------------------|
| Integrator | 50% | 22 | 30 |
| Integrator | 75% | 34 | 40 |
| Integrator | 100% | 45 | 50 |
| One App | 50% | 135 | 200 |
| One App | 75% | 203 | 300 |
| One App | 100% | 270 | 400 |
| Enterprise | 50% | 135 | 200 |
| Enterprise | 75% | 203 | 300 |
| Enterprise | 100% | 270 | 400 |
| Workforce Identity | 50% | 135 | 270 |
| Workforce Identity | 75% | 203 | 405 |
| Workforce Identity | 100% | 270 | 540 |

**āš ļø Monitor for Rate Limit Warnings:**
```
WARNING - Concurrent limit rate exceeded
```

**If you see this frequently:**
- Reduce your `OKTA_CONCURRENT_LIMIT` by 10-20%
- Cancel the sync and try a lower value
- Contact support@fctr.io if issues persist

---

## šŸ†˜ Get Help

**Before raising an issue, check:**
1. šŸ“ Server configuration and `.env` file
2. šŸ”‘ Okta API token permissions
3. šŸ”Œ MCP client compatibility
4. šŸ“Š Server logs in `logs/` directory

**Support Channels:**
- šŸ› [GitHub Issues](https://github.com/fctr-id/fctr-okta-mcp-server/issues) - Bug reports and feature requests
- šŸ“§ Email: support@fctr.io - General support
- šŸ’¬ Slack: dan@fctr.io - Quick questions

---

## šŸ“„ License

[Elastic License 2.0](https://www.elastic.co/licensing/elastic-license) - See [LICENSE](LICENSE).

āœ… Use for internal purposes • āœ… Modify and distribute  
āŒ Hosted/managed service • āŒ Remove license notices

<p align="center">
  🌟 Ā© 2025 Fctr Identity. Made with ā¤ļø for the Okta and AI communities.
</p>