Metadata-Version: 2.4
Name: mcp-cloudnex
Version: 1.0.0
Summary: MCP Server for CloudNex - Bridge between AI assistants and CloudNex cloud security data
Author: CloudNex Team
License: MIT
Keywords: mcp,cloudnex,cloud-security,compliance,ai,model-context-protocol
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.11
Description-Content-Type: text/markdown
Requires-Dist: mcp>=1.0.0
Requires-Dist: fastapi>=0.109.0
Requires-Dist: uvicorn[standard]>=0.27.0
Requires-Dist: httpx>=0.25.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: pydantic-settings>=2.0.0
Requires-Dist: python-dotenv>=1.0.0
Provides-Extra: dev
Requires-Dist: pytest>=7.4.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: pytest-httpx>=0.25.0; extra == "dev"

# CloudNex MCP Server

Enterprise MCP server exposing CloudNex cloud security data to AI assistants via the [Model Context Protocol](https://modelcontextprotocol.io/).

## Features

- **21 read-only tools** for scans, findings, providers, compliance, overviews, users, roles, and resources
- **Hub catalog tools** for compliance frameworks and security check metadata (no auth)
- **2 MCP resources** for quick scan and findings summaries
- **stdio** mode for Cursor / Claude Desktop
- **HTTP** mode with per-request API key override via headers
- JSON:API backend with `Authorization: Api-Key {prefix.key}` authentication

## Quick Start

```bash
cd cloudnex_mcp
cp .env.example .env
# Edit .env with your CLOUDNEX_API_URL and CLOUDNEX_API_KEY

pip install -e ".[dev]"
python run_server.py          # stdio MCP
python run_http_server.py     # HTTP on port 8001
```

## Docker

```bash
docker compose up --build
curl http://localhost:8001/health
```

## Cursor Configuration

Add to `.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "cloudnex": {
      "command": "mcp-cloudnex",
      "env": {
        "CLOUDNEX_API_URL": "https://your-instance.com/api/v1",
        "CLOUDNEX_API_KEY": "cn_your-prefix.your-key"
      }
    }
  }
}
```

Or using the run script:

```json
{
  "mcpServers": {
    "cloudnex": {
      "command": "python",
      "args": ["/path/to/cloudnex_mcp/run_server.py"],
      "env": {
        "CLOUDNEX_API_URL": "https://your-instance.com/api/v1",
        "CLOUDNEX_API_KEY": "cn_your-prefix.your-key"
      }
    }
  }
}
```

## Claude Desktop Configuration

Add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "cloudnex": {
      "command": "mcp-cloudnex",
      "env": {
        "CLOUDNEX_API_URL": "https://your-instance.com/api/v1",
        "CLOUDNEX_API_KEY": "cn_your-prefix.your-key",
        "CLOUDNEX_HUB_URL": "https://hub.cloudnex.com"
      }
    }
  }
}
```

## HTTP API

| Endpoint | Method | Description |
|----------|--------|-------------|
| `/health` | GET | Health check |
| `/mcp/tools` | GET | List tools |
| `/mcp/tools/call` | POST | Execute a tool |
| `/mcp/resources` | GET | List resources |
| `/mcp/resources/read` | POST | Read a resource |

Pass API key per request:

```
X-API-Key: cn_prefix.key
# or
Authorization: Api-Key cn_prefix.key
```

## Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `CLOUDNEX_API_URL` | `""` | CloudNex JSON:API base URL |
| `CLOUDNEX_API_KEY` | `""` | Tenant API key (`prefix.key`) |
| `CLOUDNEX_HUB_URL` | `https://hub.cloudnex.com` | Public check catalog |
| `CLOUDNEX_MCP_SERVER_PORT` | `8001` | HTTP server port |
| `CLOUDNEX_LOG_LEVEL` | `INFO` | Log level |
| `CLOUDNEX_CORS_ORIGINS` | `*` | Comma-separated CORS origins |

## Testing

```bash
pip install -e ".[dev]"
pytest tests/ -q

# Include integration tests (live backend):
pytest tests/ -m integration
```

Full end-to-end guide (API key, Cursor, Claude Desktop, NEXA chat): [docs/TESTING.md](docs/TESTING.md)

## RBAC

All backend tools respect CloudNex tenant RBAC. API keys are tenant-scoped; data visibility depends on role permissions and provider group assignments. Use `get_my_profile` to verify the authenticated context.
