<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.

**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.

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