From 1e56e35dcc0f269e241879c6ec80c47db8651300 Mon Sep 17 00:00:00 2001 From: shankar0123 Date: Mon, 23 Mar 2026 19:18:50 -0400 Subject: [PATCH] docs: add MCP server guide and OpenAPI spec guide New docs/mcp.md covers MCP server setup with Claude Desktop, Cursor, and Claude Code, lists all 76 tools across 16 domains, includes example conversations, and documents security considerations. New docs/openapi.md covers Swagger UI setup, SDK generation for TypeScript/Python/Go/Java, Postman import, spec validation, and contract testing with schemathesis. Updated cross-references in concepts.md and architecture.md. Co-Authored-By: Claude Opus 4.6 --- docs/architecture.md | 2 + docs/concepts.md | 2 +- docs/mcp.md | 193 +++++++++++++++++++++++++++++++++++++++++++ docs/openapi.md | 191 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 387 insertions(+), 1 deletion(-) create mode 100644 docs/mcp.md create mode 100644 docs/openapi.md diff --git a/docs/architecture.md b/docs/architecture.md index 993ed41..3f26dea 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -677,3 +677,5 @@ certctl uses a layered testing approach aligned with the handler → service → - [Quick Start](quickstart.md) — Get certctl running locally - [Advanced Demo](demo-advanced.md) — Issue a certificate end-to-end - [Connector Guide](connectors.md) — Build custom connectors +- [MCP Server Guide](mcp.md) — AI-native access to the API +- [OpenAPI Spec](openapi.md) — Full API reference and SDK generation diff --git a/docs/concepts.md b/docs/concepts.md index 1905596..f3cb6e0 100644 --- a/docs/concepts.md +++ b/docs/concepts.md @@ -200,4 +200,4 @@ The agent fleet overview page groups agents by OS, architecture, and version, sh Now that you understand the concepts, head to the [Quick Start Guide](quickstart.md) to get certctl running locally in under 5 minutes. You'll see a pre-loaded dashboard with demo certificates, explore the API, and understand how everything fits together. -For a deeper look at the system design, see the [Architecture Guide](architecture.md). For terminal-based workflows, check out the CLI Guide (docs coming soon). For AI-native integration, see the MCP Server Guide (docs coming soon). +For a deeper look at the system design, see the [Architecture Guide](architecture.md). For terminal-based workflows, check out the CLI Guide (docs coming soon). For AI-native integration, see the [MCP Server Guide](mcp.md). For the full API reference, see the [OpenAPI Spec Guide](openapi.md). diff --git a/docs/mcp.md b/docs/mcp.md new file mode 100644 index 0000000..060dcc8 --- /dev/null +++ b/docs/mcp.md @@ -0,0 +1,193 @@ +# MCP Server Guide + +certctl ships with an MCP (Model Context Protocol) server that lets AI assistants manage your certificate infrastructure through natural language. Ask Claude to "show me all expiring certificates," "revoke the VPN cert," or "what agents are offline?" and the MCP server translates that into API calls against your certctl instance. + +This guide covers setup, configuration, and usage with Claude, Cursor, and other MCP-compatible tools. + +## What Is MCP? + +MCP is an open protocol that connects AI assistants to external tools and data sources. Instead of copying and pasting API responses into a chat window, MCP lets the AI call your tools directly. The certctl MCP server exposes all 76 API endpoints as MCP tools — the AI sees typed schemas describing what each tool does, what parameters it accepts, and what it returns. + +The MCP server is a separate binary (`cmd/mcp-server/`) that communicates via stdio transport. It's a stateless HTTP proxy: every MCP tool call becomes an HTTP request to the certctl REST API. No new state, no new database tables, no new attack surface beyond what the API already exposes. + +## Prerequisites + +You need: + +1. A running certctl server (see [Quick Start](quickstart.md)) +2. The MCP server binary — either built from source or from a Docker image +3. An MCP-compatible AI client (Claude Desktop, Cursor, VS Code with Copilot, etc.) + +## Building the MCP Server + +```bash +cd certctl +go build -o certctl-mcp ./cmd/mcp-server/ +``` + +The binary has zero runtime dependencies beyond the certctl server it connects to. + +## Configuration + +The MCP server reads two environment variables: + +| Variable | Required | Default | Description | +|----------|----------|---------|-------------| +| `CERTCTL_SERVER_URL` | No | `http://localhost:8443` | URL of the certctl REST API | +| `CERTCTL_API_KEY` | No | (empty) | API key for authentication (passed as `Bearer` token) | + +If your certctl server has auth enabled (the default), you must provide the API key. The MCP server passes it through to every HTTP request. + +## Setting Up with Claude Desktop + +Add this to your Claude Desktop MCP configuration file (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS, `%APPDATA%\Claude\claude_desktop_config.json` on Windows): + +```json +{ + "mcpServers": { + "certctl": { + "command": "/path/to/certctl-mcp", + "env": { + "CERTCTL_SERVER_URL": "http://localhost:8443", + "CERTCTL_API_KEY": "your-api-key-here" + } + } + } +} +``` + +Restart Claude Desktop. You should see "certctl" appear in the MCP tools list with 76 available tools. + +## Setting Up with Cursor + +In Cursor, go to Settings → MCP Servers and add: + +```json +{ + "certctl": { + "command": "/path/to/certctl-mcp", + "env": { + "CERTCTL_SERVER_URL": "http://localhost:8443", + "CERTCTL_API_KEY": "your-api-key-here" + } + } +} +``` + +## Setting Up with Claude Code + +Add certctl as an MCP server in your project's `.mcp.json`: + +```json +{ + "mcpServers": { + "certctl": { + "command": "/path/to/certctl-mcp", + "env": { + "CERTCTL_SERVER_URL": "http://localhost:8443", + "CERTCTL_API_KEY": "your-api-key-here" + } + } + } +} +``` + +## Available Tools + +The MCP server registers 76 tools organized across 16 resource domains: + +| Domain | Tools | Examples | +|--------|-------|---------| +| Certificates | 10 | List, get, create, update, archive, versions, renew, deploy, revoke, deployments | +| CRL & OCSP | 3 | Get JSON CRL, get DER CRL by issuer, check OCSP status | +| Issuers | 5 | List, get, create, delete, test connection | +| Targets | 5 | List, get, create, update, delete | +| Agents | 6 | List, get, register, heartbeat, get work, report job status | +| Jobs | 4 | List, get, cancel, approve/reject | +| Policies | 5 | List, get, create, update, delete, list violations | +| Profiles | 5 | List, get, create, update, delete | +| Teams | 5 | List, get, create, update, delete | +| Owners | 5 | List, get, create, update, delete | +| Agent Groups | 5 | List, get, create, update, delete | +| Audit | 2 | List events (with filters), get event by ID | +| Notifications | 3 | List, get, mark as read | +| Stats | 5 | Summary, certs by status, expiration timeline, job trends, issuance rate | +| Metrics | 1 | System metrics (gauges, counters, uptime) | +| Health | 3 | Health check, readiness probe, auth info | + +Every tool has typed input parameters with `jsonschema` descriptions, so the AI knows exactly what arguments to provide and what each field means. + +## Example Conversations + +Once configured, you can interact with certctl through natural language: + +**"Show me all certificates expiring in the next 14 days"** +The AI calls `certctl_list_certificates` with `status=Expiring` and interprets the results. + +**"Renew the API production certificate"** +The AI calls `certctl_trigger_renewal` with `id=mc-api-prod`. + +**"Who owns the payments gateway cert?"** +The AI calls `certctl_get_certificate` with `id=mc-payments-prod` and reads the `owner_id` and `team_id` fields. + +**"Are any agents offline?"** +The AI calls `certctl_list_agents` and checks the heartbeat timestamps. + +**"Revoke the old VPN cert — the key was compromised"** +The AI calls `certctl_revoke_certificate` with `id=mc-vpn-old` and `reason=keyCompromise`. + +**"Give me a summary of the certificate fleet"** +The AI calls `certctl_dashboard_summary` for aggregate stats, then optionally `certctl_certificates_by_status` for the breakdown. + +**"Create a new cert for staging.api.example.com owned by the platform team"** +The AI calls `certctl_create_certificate` with the common name, team ID, and owner ID. + +## Architecture + +``` +┌──────────────────┐ stdio ┌──────────────────┐ HTTP ┌──────────────────┐ +│ AI Assistant │ ◄────────────► │ certctl MCP │ ───────────► │ certctl Server │ +│ (Claude, Cursor) │ │ cmd/mcp-server/ │ + Bearer │ :8443 │ +└──────────────────┘ └──────────────────┘ token └──────────────────┘ + │ + ┌──────┴──────┐ + │ 76 tools │ + │ 16 domains │ + │ Typed input │ + │ structs │ + └─────────────┘ +``` + +The MCP server is intentionally thin: + +- **No state** — every request is a pass-through HTTP call. Restart it anytime. +- **No new auth** — uses the same API key as the REST API. +- **No new dependencies** — just the official MCP Go SDK (`modelcontextprotocol/go-sdk`). +- **No new attack surface** — the AI can only do what the API key allows. + +## Security Considerations + +The MCP server inherits the security properties of the REST API: + +- **API key scoping**: The MCP server uses whatever API key you configure. If certctl gets API key scoping in a future release (per-resource or per-action permissions), the MCP server will automatically respect those restrictions. +- **Audit trail**: Every tool call results in an HTTP request that's logged in the API audit middleware — actor, method, path, status, and latency are all recorded. +- **Read-only usage**: For read-only AI access, you could configure a restricted API key (when key scoping ships). Until then, be aware that the AI can call write endpoints (create, update, delete, revoke) if the API key permits it. +- **No private key exposure**: The MCP server never sees or transmits private keys — the same architectural guarantee as the REST API. + +## Troubleshooting + +**"MCP server not connecting"** +Check that `CERTCTL_SERVER_URL` is reachable from where the MCP binary runs. Try `curl $CERTCTL_SERVER_URL/health` to verify. + +**"401 Unauthorized on every tool call"** +Your `CERTCTL_API_KEY` is missing or wrong. Check the key matches what the certctl server expects. + +**"Tool calls return empty results"** +The certctl server might have no data. Run the demo seed (`docker compose up`) to populate demo data, or check that your database has records. + +## What's Next + +- [Quick Start](quickstart.md) — Get certctl running locally +- [OpenAPI Spec](openapi.md) — Full API reference and SDK generation +- [Architecture](architecture.md) — System design deep dive +- [Concepts](concepts.md) — Certificate lifecycle fundamentals diff --git a/docs/openapi.md b/docs/openapi.md new file mode 100644 index 0000000..6518971 --- /dev/null +++ b/docs/openapi.md @@ -0,0 +1,191 @@ +# OpenAPI Specification Guide + +certctl ships with a complete OpenAPI 3.1 specification at `api/openapi.yaml`. This spec documents all 78 API operations (76 resource endpoints + health + readiness), every request/response schema, pagination conventions, authentication requirements, and error formats. It's the single source of truth for the REST API. + +This guide covers how to use the spec for API exploration, client SDK generation, and integration testing. + +## Where to Find It + +The spec lives at `api/openapi.yaml` in the repository root. It's versioned alongside the code and updated with every API change. + +```bash +# View the spec +cat api/openapi.yaml + +# Count operations +grep "operationId:" api/openapi.yaml | wc -l +# 78 +``` + +## Viewing with Swagger UI + +The fastest way to explore the API interactively is Swagger UI. Run it as a Docker container pointing at the spec: + +```bash +# From the certctl repo root +docker run -p 8080:8080 \ + -e SWAGGER_JSON=/spec/openapi.yaml \ + -v $(pwd)/api:/spec \ + swaggerapi/swagger-ui +``` + +Open http://localhost:8080 to see the full API reference with "Try it out" buttons for every endpoint. + +Alternatively, use Redoc for a cleaner read-only view: + +```bash +docker run -p 8080:80 \ + -e SPEC_URL=/spec/openapi.yaml \ + -v $(pwd)/api:/usr/share/nginx/html/spec \ + redocly/redoc +``` + +## API Structure + +The spec organizes endpoints into 16 tags: + +| Tag | Endpoints | Description | +|-----|-----------|-------------| +| Certificates | 12 | CRUD, versions, renewal, deployment, revocation, deployments | +| CRL & OCSP | 3 | JSON CRL, DER CRL per issuer, OCSP responder | +| Issuers | 5 | CA connector management | +| Targets | 5 | Deployment target management | +| Agents | 7 | Registration, heartbeat, CSR submission, work polling | +| Jobs | 5 | Job queue with approve/reject | +| Policies | 5 | Policy rules and violations | +| Profiles | 5 | Certificate enrollment profiles | +| Teams | 5 | Team management | +| Owners | 5 | Certificate owners | +| Agent Groups | 5 | Dynamic agent grouping | +| Audit | 2 | Immutable audit trail | +| Notifications | 3 | Notification events | +| Stats | 5 | Dashboard statistics | +| Metrics | 1 | System metrics | +| Health | 3 | Health, readiness, auth info | + +## Authentication + +The spec declares a `bearerAuth` security scheme applied globally. All endpoints under `/api/v1/` require a Bearer token by default: + +```bash +curl -H "Authorization: Bearer your-api-key" \ + http://localhost:8443/api/v1/certificates +``` + +Three endpoints are exempt from auth (declared with `security: []` in the spec): `/health`, `/ready`, and `/api/v1/auth/info`. The auth info endpoint tells clients whether authentication is enabled and what type is required — useful for GUIs that need to show/hide a login screen. + +## Pagination Convention + +All list endpoints follow the same pagination pattern: + +**Request parameters:** +- `page` (integer, default 1) — page number +- `per_page` (integer, default 50, max 500) — results per page + +**Response envelope:** +```json +{ + "data": [...], + "total": 150, + "page": 1, + "per_page": 50 +} +``` + +Certificates also support cursor-based pagination for large datasets: +- `cursor` (string) — opaque cursor token from previous response +- `page_size` (integer) — results per page when using cursor mode + +## Generating Client SDKs + +The OpenAPI spec can generate typed client libraries for any language. Here are examples using common generators: + +### TypeScript (openapi-typescript-codegen) + +```bash +npx openapi-typescript-codegen \ + --input api/openapi.yaml \ + --output src/generated/certctl \ + --client axios +``` + +### Python (openapi-python-client) + +```bash +pip install openapi-python-client +openapi-python-client generate --path api/openapi.yaml +``` + +### Go (oapi-codegen) + +```bash +go install github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest +oapi-codegen -generate types,client -package certctl api/openapi.yaml > certctl_client.go +``` + +### Java (OpenAPI Generator) + +```bash +npx @openapitools/openapi-generator-cli generate \ + -i api/openapi.yaml \ + -g java \ + -o generated/java-client +``` + +## Validating the Spec + +Verify the spec is valid OpenAPI 3.1: + +```bash +# Using spectral (recommended) +npx @stoplight/spectral-cli lint api/openapi.yaml + +# Using swagger-cli +npx @apidevtools/swagger-cli validate api/openapi.yaml +``` + +## Using with Postman + +Import the spec directly into Postman: + +1. Open Postman → Import → File → select `api/openapi.yaml` +2. Postman creates a collection with all 78 operations organized by tag +3. Set the `baseUrl` variable to `http://localhost:8443` +4. Add an `Authorization: Bearer your-api-key` header to the collection + +## Key Schemas + +The spec defines typed schemas for all domain objects. Key schemas to know: + +| Schema | Description | +|--------|-------------| +| `ManagedCertificate` | Core certificate record with status, expiry, owner, tags, profile | +| `CertificateVersion` | Individual cert version with PEM, serial, fingerprint, validity | +| `Agent` | Agent with heartbeat, metadata (OS, arch, IP, version), capabilities | +| `Job` | Job record with type, status (7 states), certificate/target references | +| `PolicyRule` | Policy with type (5 types), config, severity, enabled state | +| `CertificateProfile` | Enrollment profile with allowed key types, max TTL, constraints | +| `AuditEvent` | Immutable audit record with actor, action, resource, timestamp | +| `RevocationReason` | RFC 5280 reason code enum (8 values) | +| `DashboardSummary` | Aggregate stats (total certs, expiring, agents, jobs) | + +## Integration Testing + +Use the spec to generate contract tests that verify the API matches the spec: + +```bash +# Using schemathesis for fuzz testing against the spec +pip install schemathesis +schemathesis run api/openapi.yaml \ + --base-url http://localhost:8443 \ + --header "Authorization: Bearer your-api-key" +``` + +This sends randomized valid requests to every endpoint and verifies the responses match the declared schemas. + +## What's Next + +- [MCP Server Guide](mcp.md) — AI-native access to the certctl API +- [Quick Start](quickstart.md) — Get certctl running locally +- [Connector Guide](connectors.md) — Build custom issuer and target connectors +- [Architecture](architecture.md) — System design deep dive