Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

**BEFORE CODING**:
1. **Always read this entire CLAUDE.md file first** - Contains critical patterns and constraints
2. **Check current test status** - All changes must maintain 269+ passing tests
2. **Check current test status** - All changes must maintain 260+ passing tests
3. **Follow existing patterns** - Simplified architecture patterns are established and documented
4. **Use official SDK** - All CyberArk operations MUST use ark-sdk-python (never direct HTTP)
5. **MANDATORY: Use context7 MCP tools for ALL API documentation** - Before working with any library or API, use context7 MCP server tools to get up-to-date documentation
Expand Down Expand Up @@ -98,7 +98,7 @@ Use context7 resolve-library-id and get-library-docs tools:

**Current Status**: ✅ **SERVICE ACCOUNT TOKEN BRIDGE COMPLETE** - OAuth mode verifies user identity via OIDC JWT, then uses a shared service account platform token for all PCloud API calls.
**Last Updated**: February 27, 2026
**Recent Achievement**: Technical debt cleanup — removed dead code (session_manager.py, token_auth.py, HTTP bypasses, unused server methods), simplified AppContext to use `is_oauth` flag, fixed token_verifier exception handling, updated all documentation. 276 passing tests with zero regression.
**Recent Achievement**: Technical debt cleanup — removed dead code (session_manager.py, token_auth.py, HTTP bypasses, unused server methods), simplified AppContext to use `is_oauth` flag, fixed token_verifier exception handling, updated all documentation. 260 passing tests with zero regression.

## Architecture

Expand All @@ -115,7 +115,7 @@ The server provides 53 MCP tools for comprehensive CyberArk operations, built on
- **Applications Management Tools (8 tools)**: Complete application lifecycle - `list_applications`, `get_application_details`, `add_application`, `delete_application`, `list_application_auth_methods`, `get_application_auth_method_details`, `add_application_auth_method`, `delete_application_auth_method`, `get_applications_stats`
- **Session Monitoring Tools (6 tools)**: Privileged session monitoring and analytics - `list_sessions`, `list_sessions_by_filter`, `get_session_details`, `list_session_activities`, `count_sessions`, `get_session_statistics`

> **Complete PCloud Coverage**: All tools provide comprehensive coverage of CyberArk's 5 PCloud services with enterprise-grade CRUD operations, advanced analytics, member management, and privileged session monitoring. Built on official ark-sdk-python library with 210+ passing tests and zero regression.
> **Complete PCloud Coverage**: All tools provide comprehensive coverage of CyberArk's 5 PCloud services with enterprise-grade CRUD operations, advanced analytics, member management, and privileged session monitoring. Built on official ark-sdk-python library with 260+ passing tests and zero regression.

## Enhanced Platform Data Combination

Expand Down Expand Up @@ -274,7 +274,7 @@ The codebase underwent a systematic simplification process achieving **~27% code
- **Simplified Testing**: Cleaner test patterns with reduced mocking complexity

**Performance & Reliability**:
- **Zero Functional Regression**: All 261+ tests passing with complete functionality coverage
- **Zero Functional Regression**: All 260+ tests passing with complete functionality coverage
- **Preserved SDK Integration**: Official ark-sdk-python patterns maintained
- **Graceful Error Handling**: Centralized error management with consistent logging
- **Backward Compatibility**: No breaking changes to MCP tool interfaces
Expand Down Expand Up @@ -332,8 +332,8 @@ async def app_lifespan(server: FastMCP) -> AsyncIterator[AppContext]:
- `exceptions.py` - Custom exceptions: CyberArkAPIError, SDK compatibility layer

### Testing Validation ✅ **VERIFIED**
- **261+ tests passing** - Zero functionality regression across all phases
- **Test Coverage Maintained** - 16 token verifier + 14 OAuth integration tests added
- **260+ tests passing** - Zero functionality regression across all phases
- **Test Coverage Maintained** - Token verifier + OAuth integration tests added
- **Integration Tests Updated** - MCP tool parameter passing verified for all 53 tools
- **Performance Baseline** - No degradation in execution performance

Expand Down Expand Up @@ -404,7 +404,7 @@ async def app_lifespan(server: FastMCP) -> AsyncIterator[AppContext]:

## Testing Strategy

**Test Files**: 261+ total tests across 15 test files
**Test Files**: 260 total tests across 14 test files
- `tests/test_core_functionality.py` - Authentication, server core, platform management (comprehensive error handling)
- `tests/test_account_operations.py` - Account lifecycle management with CRUD operations
- `tests/test_applications_service.py` - Applications service testing with authentication methods
Expand Down Expand Up @@ -482,7 +482,7 @@ async def get_account_password(account_id: str) -> Dict[str, Any]:
2. **NEVER bypass patterns** - Always use @handle_sdk_errors decorator
3. **ALWAYS follow TDD** - Write failing test first, then implementation
4. **SDK-only operations** - Never create direct HTTP requests
5. **Preserve test coverage** - All 261+ tests must continue passing
5. **Preserve test coverage** - All 260+ tests must continue passing
6. **Use existing models** - Leverage ark-sdk-python model classes

**🔍 Mandatory Context7 Workflow**:
Expand All @@ -493,7 +493,7 @@ async def get_account_password(account_id: str) -> Dict[str, Any]:
- get-library-docs with the resolved ID
2. Write failing test using current patterns
3. Implement using up-to-date SDK methods
4. Verify all 261+ tests still pass
4. Verify all 260+ tests still pass
```

## References
Expand Down
186 changes: 51 additions & 135 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,14 @@

An MCP server for CyberArk Privilege Cloud, built on the official [ark-sdk-python](https://github.com/cyberark/ark-sdk-python) library. Provides 53 tools for privileged access management.

Supports two authentication modes:
- **OAuth per-user mode** (recommended) -- each user authenticates with their own CyberArk Identity credentials via OAuth. Requires [Streamable HTTP transport](#docker-deployment) and an OIDC app in CyberArk Identity ([setup guide](docs/CYBERARK_IDENTITY_SETUP.md)).
- **Legacy service account mode** -- a single shared service account authenticates all requests via stdio transport. Simpler setup, shown in [Quick Start](#quick-start) below.

## Quick Start

> This sets up the **legacy service account mode** via stdio. For OAuth per-user mode, see [OAuth Per-User Mode](#oauth-per-user-mode).

**1. Install uv** (if not already installed):
```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
Expand Down Expand Up @@ -38,51 +44,73 @@ curl -LsSf https://astral.sh/uv/install.sh | sh

**3. Restart Claude Desktop** - The MCP server will appear in the tools menu (hammer icon) when connected.

### Claude Code

```bash
claude mcp add cyberark-privilege-cloud \
-e CYBERARK_CLIENT_ID=your-service-user-username \
-e CYBERARK_CLIENT_SECRET=your-service-user-password \
-- uvx --from git+https://github.com/aaearon/mcp-privilege-cloud.git mcp-privilege-cloud
```

## Example Prompts

Once configured, you can ask Claude things like:

**Account Management:**
- "List all accounts in the Production safe"
- "Show me Windows accounts that are failing management"
- "Create a new local admin account for server PROD-WEB-01"
- "Which accounts haven't had their passwords changed in 90 days?"

**Safe Management:**
- "Create a new safe called 'DevOps-Credentials' with 30-day retention"
- "Add the DevOps team as safe members with retrieve permissions"
- "Show me all safes and their member counts"

**Platform & Session Monitoring:**
- "List all active platforms and their account counts"
- "Show me active privileged sessions"
- "Get session activity for the last hour"

## Prerequisites

- [CyberArk Identity Service User](https://docs.cyberark.com/identity-administration/latest/en/content/ispss/ispss-add-service-user.htm) with:
- Appropriate Identity roles for the desired operations (e.g., Privilege Cloud Administrator for platform management)
- Safe permissions granting access to the safes and accounts you want to manage
- For OAuth per-user mode: an OIDC app in CyberArk Identity (see [setup guide](docs/CYBERARK_IDENTITY_SETUP.md))

## Client Integration
## Configuration

### Claude Desktop
### OAuth Per-User Mode

See [Quick Start](#quick-start) above for configuration.
Each connecting user authenticates with their own CyberArk Identity credentials via OAuth. The server verifies user identity from the OIDC JWT, then uses a shared service account platform token for all PCloud API calls.

If the configuration file doesn't exist, create it. If it already exists with other MCP servers, add the `cyberark-privilege-cloud` entry to the existing `mcpServers` object.
Requires Streamable HTTP transport -- see [Docker Deployment](#docker-deployment) or set `MCP_TRANSPORT=streamable-http` when running locally.

### Claude Code
| Variable | Required | Description |
|----------|----------|-------------|
| `CYBERARK_IDENTITY_TENANT_URL` | Yes | CyberArk Identity tenant URL (e.g., `https://abc1234.id.cyberark.cloud`) |
| `CYBERARK_CLIENT_ID` | Yes | Service account login name (for PCloud platform token) |
| `CYBERARK_CLIENT_SECRET` | Yes | Service account password |
| `CYBERARK_OAUTH_CLIENT_ID` | Yes | OIDC app client ID from Trust tab (for DCR and JWT audience) |
| `CYBERARK_OAUTH_CLIENT_SECRET` | Yes | OIDC app client secret from Trust tab (injected server-side in /token proxy) |
| `MCP_TRANSPORT` | No | Transport protocol (default: `stdio`; set to `streamable-http` for OAuth) |
| `MCP_HOST` | No | Server bind host (default: `127.0.0.1`) |
| `MCP_PORT` | No | Server bind port (default: `8000`) |
| `MCP_SERVER_URL` | No | Public URL for OAuth metadata (default: `http://{host}:{port}`) |

See [CyberArk Identity Setup](docs/CYBERARK_IDENTITY_SETUP.md) for full configuration instructions.

### Legacy Service Account Mode

| Variable | Required | Description |
|----------|----------|-------------|
| `CYBERARK_CLIENT_ID` | Yes | Your Service User username |
| `CYBERARK_CLIENT_SECRET` | Yes | Your Service User password |

Add the MCP server using the Claude Code CLI:
## Docker Deployment

The included `Dockerfile` and `docker-compose.yml` run the server in Streamable HTTP mode, suitable for OAuth per-user authentication and remote MCP clients.

```bash
claude mcp add cyberark-privilege-cloud \
-e CYBERARK_CLIENT_ID=your-service-user-username \
-e CYBERARK_CLIENT_SECRET=your-service-user-password \
-- uvx --from git+https://github.com/aaearon/mcp-privilege-cloud.git mcp-privilege-cloud
# Create .env with your credentials (see .env.example)
docker compose up -d --build
```

When deploying behind a reverse proxy, configure it to strip trailing slashes from request paths. MCP clients may POST to `/mcp/` (trailing slash), causing a 307 redirect that strips the `Authorization` header. Set `MCP_SERVER_URL` to the public URL of your server.

## Available Tools (53 Total)

**Account Management (18 tools):**
Expand All @@ -108,97 +136,6 @@ claude mcp add cyberark-privilege-cloud \
- **Session Management**: `list_sessions`, `list_sessions_by_filter`, `get_session_details`, `count_sessions`
- **Activity Tracking**: `list_session_activities`, `get_session_statistics`

## Features

- **Complete Account Lifecycle**: Create, read, update, delete accounts with advanced search and password management
- **Comprehensive Safe Operations**: Full CRUD operations plus member management with granular permissions
- **Platform Management**: Complete platform lifecycle including statistics, import/export, and target platform operations
- **Applications Management**: Full application lifecycle with authentication method management
- **Session Monitoring**: Real-time session tracking, activity monitoring, and analytics
- **Enterprise Security**: Built on official ark-sdk-python with OAuth and comprehensive error handling

## Configuration

The server supports two authentication modes. It auto-detects which mode to use based on the environment variables present.

### OAuth Per-User Mode (Recommended)

Each connecting user authenticates with their own CyberArk Identity credentials via OAuth. The server verifies user identity from the OIDC JWT, then uses a **service account platform token** for all PCloud API calls. Requires an OAuth2 app configured in CyberArk Identity (see [CyberArk Identity Setup](docs/CYBERARK_IDENTITY_SETUP.md)).

| Variable | Required | Description |
|----------|----------|-------------|
| `CYBERARK_IDENTITY_TENANT_URL` | Yes | CyberArk Identity tenant URL (e.g., `https://abc1234.id.cyberark.cloud`) |
| `CYBERARK_CLIENT_ID` | Yes | Service account login name (used for PCloud platform token) |
| `CYBERARK_CLIENT_SECRET` | Yes | Service account password |
| `CYBERARK_OAUTH_CLIENT_ID` | Yes | OIDC app client ID from Trust tab (used for DCR and JWT audience validation) |
| `CYBERARK_OAUTH_CLIENT_SECRET` | Yes | OIDC app client secret from Trust tab (injected server-side in /token proxy) |
| `MCP_TRANSPORT` | No | Transport protocol: `stdio`, `sse`, or `streamable-http` (default: `stdio`) |
| `MCP_HOST` | No | Server bind host (default: `127.0.0.1`) |
| `MCP_PORT` | No | Server bind port (default: `8000`) |

### Legacy Service Account Mode

A single shared service account authenticates all requests. Simpler setup but all operations run under one identity.

| Variable | Required | Description |
|----------|----------|-------------|
| `CYBERARK_CLIENT_ID` | Yes | Your Service User username |
| `CYBERARK_CLIENT_SECRET` | Yes | Your Service User password |
| `MCP_TRANSPORT` | No | Transport protocol: `stdio`, `sse`, or `streamable-http` (default: `stdio`) |

**For Claude Desktop/Claude Code**: Pass these directly in the configuration (see [Client Integration](#client-integration)). No `.env` file is needed.

**For local development/testing**: Create a `.env` file in the project root directory:

```bash
# OAuth per-user mode (recommended)
# Service account — for PCloud API access via platform token
[email protected]
CYBERARK_CLIENT_SECRET=service-user-password
# OIDC app — from Trust tab, for DCR
CYBERARK_OAUTH_CLIENT_ID=your-oidc-app-client-id
CYBERARK_OAUTH_CLIENT_SECRET=your-oidc-app-client-secret
CYBERARK_IDENTITY_TENANT_URL=https://abc1234.id.cyberark.cloud

# OR legacy service account mode
CYBERARK_CLIENT_ID=your-service-user-username
CYBERARK_CLIENT_SECRET=your-service-user-password

# Transport: stdio (default), sse, or streamable-http
# MCP_TRANSPORT=streamable-http
```

## Reverse Proxy Deployment

When deploying behind a reverse proxy with OAuth enabled, you **must** configure the proxy to strip trailing slashes from request paths. MCP clients (e.g. Copilot Studio) POST to `/mcp/` (trailing slash), which causes a 307 redirect to `/mcp`. HTTP clients strip the `Authorization` header on redirect, breaking OAuth Bearer token authentication.

Also set `MCP_SERVER_URL` to the public URL of your server so that OAuth discovery metadata contains reachable URLs.

**Traefik example** (dynamic config):
```yaml
http:
middlewares:
strip-trailing-slash:
replacePathRegex:
regex: "^(/.+?)/$"
replacement: "${1}"
routers:
mcp:
rule: "Host(`mcp.example.com`)"
entryPoints:
- web-secure
service: mcp
middlewares:
- strip-trailing-slash
tls:
certResolver: myresolver
services:
mcp:
loadBalancer:
servers:
- url: "http://backend:8000"
```

## Troubleshooting

| Issue | Solution |
Expand All @@ -207,7 +144,7 @@ http:
| Authentication failed | Verify Service User credentials in CyberArk Identity |
| Permission errors | Ensure the Service User has appropriate Identity roles and safe permissions |
| Connection issues | Verify you're using the `.cloud` domain (not `.com`) |
| OAuth 401 behind reverse proxy | Ensure the proxy strips trailing slashes (see Reverse Proxy Deployment above) |
| OAuth 401 behind reverse proxy | Ensure the proxy strips trailing slashes (see [Docker Deployment](#docker-deployment)) |
| `uvx` not found | Install uv: `curl -LsSf https://astral.sh/uv/install.sh \| sh` |

**Verify MCP server manually:**
Expand All @@ -217,50 +154,29 @@ uvx --from git+https://github.com/aaearon/mcp-privilege-cloud.git mcp-privilege-

## Development

### Installation

```bash
git clone https://github.com/aaearon/mcp-privilege-cloud.git
cd mcp-privilege-cloud
uv sync
```

### Running Tests

```bash
uv run pytest # Run all tests
uv run pytest --cov=mcp_privilege_cloud # Run with coverage
uv run pytest -m integration # Integration tests only
```

### Running the Server Locally

```bash
uv run mcp-privilege-cloud # With uv
python -m mcp_privilege_cloud # Direct module execution
uv run mcp-privilege-cloud # Run the server locally
```

### Testing with MCP Inspector

```bash
npx @modelcontextprotocol/inspector
```

Configure with command `uv run mcp-privilege-cloud` and your credentials.

## Documentation

- **[API Reference](docs/API_REFERENCE.md)** - Complete tool specifications and parameters
- **[Architecture](docs/ARCHITECTURE.md)** - System design and components
- **[CyberArk Identity Setup](docs/CYBERARK_IDENTITY_SETUP.md)** - OAuth app configuration guide
- **[Development Guide](DEVELOPMENT.md)** - Contributing and development workflows
- **[Development Guide](docs/DEVELOPMENT.md)** - Contributing and development workflows
- **[Testing Guide](docs/TESTING.md)** - Detailed testing instructions

## Security

- Never commit credentials to version control
- Use secure environment variable management
- Grant minimal required permissions to Service Users
- In OAuth mode, DCR returns public clients only -- secrets are injected server-side
- Official SDK provides automatic token management and secure protocols

## License
Expand Down
Loading