带有AWS基础架构的Okta MCP服务器
用于Okta管理的完整模型上下文协议(MCP)服务器实现,通过AWS Bedrock在AWS上部署LiteLLM代理,用于Claude Sonnet 4.5集成。
🏗️ 建筑
Roo/Claude桌面(本地机器) ↓ StrongDM隧道 EC2实例(AWS eu-west-3) ├── MCP服务器 │ ├── MCP管理服务器(端口8080)-完全读/写访问 │ └── MCP只读服务器(端口8081)-只读访问 │ ├── LiteLLM代理(端口4000) │ └── AWS基岩–克劳德十四行诗4.5 │ ├── 可观测性堆栈 │ ├── Grafana(端口3000)-仪表板和可视化 │ ├── 洛基(端口3100)-日志聚合 │ └── Promtail–日志收集 │ └── 自动更新图层 └── 守望台——每5分钟自动更新一次Docker镜像
✨ 特性
🔐 身份验证和安全
- 双重身份验证层:StrongDM+Okta OAuth 2.0
- 网关隔离:MCP服务器从不直接暴露
- 每用户会话管理:跟踪和审核所有会议
- 基于JWT的Okta认证:私钥身份验证(比API令牌更安全)
- 健康检查端点:监控服务可用性
🛠️ Okta管理工具
用户管理
list_users-列出所有分页用户find_user-通用用户查找(精确+模糊回退)get_user-获取详细的用户信息search_users-使用Okta搜索语法搜索用户search_users_fuzzy-按姓名/电子邮件进行模糊搜索create_user-创建新用户(仅限管理员)deactivate_user-停用现有用户(仅限管理员)delete_user-删除用户(仅限管理员)
🆕 配置文件属性搜索和批量操作
search_users_by_attribute-按任何配置文件字段(部门、部门、头衔、位置等)查找用户add_users_to_group_by_attribute-根据配置文件条件将用户批量添加到组中remove_users_from_group_by_attribute-根据配置文件条件从组中批量删除用户- 模拟运行支持:应用前预览更改
示例工作流:
“列出公司IT部门的所有用户” “将部门=‘工程’的所有用户添加到eng团队组” “尝试将销售部门添加到销售团队组中” “从全职福利组中删除所有承包商”
群组管理
list_groups-查看所有组search_groups_fuzzy-按名称模糊搜索组get_group-获取组详细信息list_group_users-查看组成员资格create_group-创建新组(仅限管理员)delete_group-删除组(仅限管理员)add_user_to_group-将单个用户添加到组(仅限管理员)remove_user_from_group-从组中删除用户(仅限管理员)add_users_to_group-批量将用户添加到组(仅限管理员)
应用程序管理
list_applications-查看所有应用程序get_application-获取应用程序详细信息list_application_users-查看分配给应用程序的用户list_application_groups-查看分配给应用程序的组get_application_schema-获取应用程序用户配置文件架构(显示可用角色字段)list_application_available_roles-列出应用程序上配置/可用的所有角色list_application_roles_in_use-列出当前分配给用户的唯一角色get_user_application_roles-获取应用程序的特定用户角色check_role_exists_on_application-验证应用程序上是否存在特定角色assign_user_to_application-将用户分配到应用程序(仅限管理员)assign_user_to_application_with_role-将用户分配到具有特定角色的应用程序(仅限管理员)update_user_application_role-更新已分配用户的角色(仅限管理员)assign_group_to_application-将组分配给应用程序(仅限管理员)create_application-创建新应用程序(仅限管理员)unassign_users_from_application_by_attribute-按属性筛选器批量取消分配用户(仅限管理员)
政策与审计
list_policies-查看身份验证策略get_policy-获取政策详细信息get_logs-使用筛选器查询系统审核日志check_permissions-查看已授予的OAuth作用域
基础设施
- Terraform管理的AWS部署 (VPC、EC2、秘密管理器、IAM)
- 基于Docker的服务 Watchtower自动更新
- 双MCP服务器: 管理员(完全访问)和只读(安全查询)
- StrongDM: 强大的DM集成
- LiteLLM API网关: 适用于AWS Bedrock的OpenAI兼容API
- 完全可观察性: Grafana+Loki+Promtail测井堆栈
- 自动化部署 通过用户数据脚本
🚀 快速开始
先决条件
- AWS CLI已配置凭据
- 地形>=1.0
- 使用OAuth 2.0应用程序的Okta帐户
- 用于EC2访问的SSH密钥对
- Docker镜像推送到Docker Hub(自定义构建可选)
1.克隆和配置
git clone
cd okta-mcp-aws
# Copy and configure variables
cp terraform.tfvars.example terraform.tfvars
Edit terraform.tfvars:
text
aws_region = "eu-west-3"
project_name = "okta-mcp"
key_name = "your-key-name"
# Okta OAuth Apps (3 separate apps)
okta_domain = "your-domain.okta.com"
okta_admin_client_id = "admin-app-client-id"
okta_readonly_client_id = "readonly-app-client-id"
okta_gateway_client_id = "gateway-app-client-id"
okta_issuer = "https://your-domain.okta.com/oauth2/default"
# Private keys (stored in AWS Secrets Manager)
admin_private_key_pem = "-----BEGIN RSA PRIVATE KEY-----\n..."
readonly_private_key_pem = "-----BEGIN RSA PRIVATE KEY-----\n..."
# LiteLLM keys
litellm_master_key = "sk-YOUR-SECURE-MASTER-KEY"
litellm_admin_key = "sk-ADMIN-TEAM-KEY"
litellm_reader_key = "sk-READER-TEAM-KEY"
# Gateway settings
gateway_redirect_uri = "https://okta-gateway.your-domain.com/oauth/callback"
gateway_session_secret = "your-secure-session-secret"
gateway_internal_auth = "your-internal-auth-token"
# Docker images (optional - uses public images by default)
docker_image = "blackstaa/okta-mcp-server:latest"
gateway_image = "blackstaa/okta-mcp-gateway:latest"
Deploy Infrastructure
bash
terraform init
terraform plan
terraform apply
Verify Deployment
# Get instance IP
terraform output instance_public_ip
# SSH into instance
ssh -i ~/.ssh/your-key.pem ec2-user@
# Check all services
docker ps
# Should see all containers as (healthy):
# - okta-mcp-admin
# - okta-mcp-readonly
# - litellm-proxy
# - grafana
# - loki
# - promtail
# - watchtower
Test Endpoints
# Test admin MCP health
curl http://localhost:8080/health
# Test readonly MCP health
curl http://localhost:8081/health
# Test LiteLLM
export LITELLM_KEY=$(terraform output -raw litellm_master_key)
curl http://localhost:4000/v1/models \
-H "Authorization: Bearer $LITELLM_KEY"
Configure StrongDM
Create two HTTP resources in StrongDM:
Admin MCP Server:
Hostname: 10.2.0.37 (or your EC2 private IP)
Port: 8080
Healthcheck Path: /health
Subdomain: okta-mcp-admin
Readonly MCP Server:
Hostname: 10.2.0.37
Port: 8081
Healthcheck Path: /health
Subdomain: okta-mcp-readonly
6. Connect Roo/Claude Desktop
Configure Roo (VS Code settings.json):
{
"roo-cline.mcpServers": {
"okta-admin": {
"transport": {
"type": "sse",
"url": "http://okta-mcp-admin.your-sdm-domain.network/sse"
}
},
"okta-readonly": {
"transport": {
"type": "sse",
"url": "http://okta-mcp-readonly.your-sdm-domain.network/sse"
}
}
}
}
🔧 Configuration
Okta OAuth 2.0 Setup
Create two OAuth 2.0 API Services applications in Okta:
1. Admin MCP Server App
Grant Type: Client Credentials
Scopes:
okta.users.read
okta.users.manage
okta.groups.read
okta.groups.manage
okta.apps.read
okta.apps.manage
okta.policies.read
okta.logs.read
2. Readonly MCP Server App
Grant Type: Client Credentials
Scopes:
okta.users.read
okta.groups.read
okta.apps.read
okta.policies.read
okta.logs.read
Generate private keys for both apps and add to terraform.tfvars
AWS Bedrock Setup
Enable AWS Bedrock in eu-west-3
Subscribe to Claude Sonnet 4.5 in AWS Marketplace
Request model access in Bedrock console
Ensure IAM role has bedrock:InvokeModel permission
LiteLLM Configuration
The deployment includes these Bedrock models (configured in litellm-config.yaml):
model_list:
# Claude Sonnet 4.5 (primary)
- model_name: bedrock-sonnet
litellm_params:
model: bedrock/eu.anthropic.claude-sonnet-4-5-20250929-v1:0
aws_region_name: eu-west-3
# Claude Haiku 4.5 (fast, cheap)
- model_name: bedrock-haiku
litellm_params:
model: bedrock/eu.anthropic.claude-haiku-4-5-20251001-v1:0
aws_region_name: eu-west-3
# Llama 3.3 70B (open source)
- model_name: bedrock-llama
litellm_params:
model: bedrock/eu.meta.llama3-3-70b-instruct-v1:0
aws_region_name: eu-west-3
# Mistral Large
- model_name: bedrock-mistral
litellm_params:
model: bedrock/eu.mistral.mistral-large-2402-v1:0
aws_region_name: eu-west-3
🔐 Security
Secrets in AWS Secrets Manager - No hardcoded credentials
Private key JWT authentication - More secure than API tokens
StrongDM tunnel - Secure access with audit logging
IAM role-based access - EC2 instance uses IAM for AWS services
VPC isolation - EC2 in private subnet with NAT gateway
Security groups - Restricted inbound access (VPC range only)
Data residency - All AI processing stays in AWS eu-west-3
Auto-updates - Watchtower keeps containers current with security patches
Health monitoring - /health endpoints for uptime monitoring
📊 Monitoring
Access Grafana Dashboards
bash
# Create SSH tunnel to Grafana
ssh -L 3000:localhost:3000 -i ~/.ssh/your-key.pem ec2-user@ -N
# Open browser to http://localhost:3000
# Default credentials: admin/admin
Check Service Logs
bash
# View all container logs
docker logs -f okta-mcp-admin
docker logs -f okta-mcp-gateway-admin
docker logs -f litellm-proxy
# Check Watchtower auto-update logs
docker logs watchtower
# View aggregated logs in Loki (via Grafana)
# Query: {container="okta-mcp-admin"}
Check Service Health
bash
# Check all container health status
docker ps
# View detailed healthcheck logs
docker inspect okta-mcp-admin | jq '.[].State.Health'
# Test health endpoints
curl http://localhost:8080/health
curl http://localhost:8081/health
# Via StrongDM
curl http://okta-mcp-admin.your-sdm-domain.network/health
🐛 Troubleshooting
MCP Server Connection Failed
Verify MCP server is running: docker ps | grep okta-mcp
Check server health: curl http://localhost:8080/health
View server logs: docker logs okta-mcp-admin
Verify StrongDM tunnel is active
Test SSE endpoint: curl http://localhost:8080/sse
Container Shows "unhealthy"
bash
# Check healthcheck logs
docker inspect okta-mcp-admin | jq '.[].State.Health.Log[-1]'
# Verify health endpoint responds
docker exec okta-mcp-admin curl -f http://localhost:8080/health
# Restart container if needed
docker restart okta-mcp-admin
Watchtower Not Updating Images
bash
# Check Watchtower logs
docker logs watchtower
# Verify containers have label
docker inspect okta-mcp-admin | grep watchtower.enable
# Manually trigger update
docker restart watchtower
# Check Docker Hub for new images
docker pull blackstaa/okta-mcp-server:latest
LiteLLM Bedrock Errors
Error: "Not subscribed to Bedrock model"
Subscribe to Claude Sonnet 4.5 in AWS Marketplace
Wait 2-3 minutes for subscription to propagate
Error: "AccessDeniedException"
Check IAM role has bedrock:InvokeModel permission
Verify model access enabled in Bedrock console
Confirm correct AWS region (eu-west-3)
Okta Authentication Failed
bash
# Verify credentials in Secrets Manager
aws secretsmanager get-secret-value --secret-id okta-mcp-admin-key
# Check private key format (must include \n for newlines)
# Verify OAuth scopes in Okta application
# Test OAuth token generation
docker logs okta-mcp-admin | grep "OAuth"
StrongDM Healthcheck Failing
bash
# Verify health endpoint works locally
curl http://localhost:8080/health
# Check StrongDM configuration
# - Healthcheck Path should be: /health
# - Port should match: 8080 or 8081
# - Security group allows traffic from VPC range (10.2.0.0/16)
# View MCP server logs
docker logs okta-mcp-admin --tail 50
# Pull latest images
docker pull blackstaa/okta-mcp-server:latest
docker pull blackstaa/okta-mcp-gateway:latest
# Restart services
cd /opt/okta-litellm
docker compose down
docker compose up -d
# Verify all containers healthy
docker ps
Update Infrastructure
bash
🔄 Updates and Maintenance
Auto-Updates via Watchtower
Watchtower automatically checks for new Docker images every 5 minutes and updates containers with the label com.centurylinklabs.watchtower.enable=true.
Monitored images:
blackstaa/okta-mcp-server:latest (admin + readonly servers)
To deploy updates:
Build and push new Docker image to Docker Hub
Wait up to 5 minutes for Watchtower to detect and apply update
Verify update: docker ps (check container "Created" time)
Manual Updates
bash
ssh -i ~/.ssh/your-key.pem ec2-user@
# Pull latest images
docker pull blackstaa/okta-mcp-server:latest
# Restart services
cd /opt/okta-litellm
docker-compose down
docker-compose up -d
# Make changes to Terraform files
terraform plan
terraform apply
# For user-data.sh changes, recreate instance:
terraform taint aws_instance.okta_mcp
terraform apply
📁 Project Structure
.
├── terraform/
│ ├── main.tf # Main infrastructure
│ ├── vpc.tf # VPC and networking
│ ├── iam.tf # IAM roles and policies
│ ├── secrets.tf # Secrets Manager resources
│ ├── security_groups.tf # Security group rules
│ ├── outputs.tf # Terraform outputs
│ ├── variables.tf # Input variables
│ └── terraform.tfvars # Your configuration (gitignored)
├── src/
│ └── okta_mcp_server/
│ ├── server.py # MCP server entrypoint
│ ├── oauth_jwt_client.py # Okta OAuth client
│ └── tools/ # MCP tool implementations
│ ├── users/
│ │ ├── users.py # User read operations
│ │ └── users_admin.py # User write + attribute search
│ ├── groups/ # Group operations
│ ├── applications/ # App operations
│ └── policies/ # Policy operations
├── Dockerfile # MCP server container image
├── docker-compose.yml # Service orchestration (in user-data.sh)
├── user-data.sh # EC2 initialization script
├── litellm-config.yaml # LiteLLM model configuration
├── loki-config.yaml # Loki log aggregation config
├── promtail-config.yaml # Promtail log collection config
└── README.md # This file
## 💰 Cost Estimate
**AWS Resources (eu-west-3):**
- EC2 t3.medium: ~$30/month
- NAT Gateway: ~$32/month
- EBS storage (30GB): ~$3/month
- Secrets Manager (2 secrets): ~$1/month
- Data transfer: Variable (~$5-10/month)
**AWS Bedrock Claude Sonnet 4.5:** Pay-per-use
- Input: $3 per million tokens
- Cached input: $0.30 per million tokens (90% discount)
- Output: $15 per million tokens
**Infrastructure Base:** ~$71-76/month
**With Prompt Caching + MCP Filtering:**
- Light use (5 queries/day): ~**$72-77/month** (minimal Bedrock cost)
- Moderate use (20 queries/day): ~**$76-81/month** (+$5 Bedrock)
- Heavy use (100 queries/day): ~**$95-100/month** (+$24 Bedrock)
**Note:** Prompt caching reduces token costs by ~90% for system prompts and tool definitions. MCP tool filtering further reduces context size. Most costs come from infrastructure, not AI usage.
🤝 Contributing
Fork the repository
Create a feature branch (git checkout -b feature/amazing-feature)
Make your changes
Test thoroughly with both admin and readonly servers
Commit your changes (git commit -m 'feat: add amazing feature')
Push to the branch (git push origin feature/amazing-feature)
Open a Pull Request
📝 License
MIT License - See LICENSE file for details
🙏 Acknowledgments
Model Context Protocol by Anthropic
LiteLLM by BerriAI
Okta Management API
AWS Bedrock
Grafana Stack for observability
Watchtower for auto-updates
📞 Support
For issues and questions:
Open a GitHub issue with detailed logs
Check MCP documentation
Review AWS Bedrock docs
Check container logs: docker logs
View Grafana dashboards for system metrics
Built with ❤️ for secure, privacy-focused Okta automation with enterprise-grade observability```