{"id":51862741,"url":"https://github.com/mctlhq/mctl-api","last_synced_at":"2026-07-24T10:30:24.061Z","repository":{"id":369852292,"uuid":"1173996389","full_name":"mctlhq/mctl-api","owner":"mctlhq","description":"mctl platform API server + MCP server","archived":false,"fork":false,"pushed_at":"2026-07-23T18:45:00.000Z","size":542,"stargazers_count":0,"open_issues_count":22,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-07-23T20:08:39.618Z","etag":null,"topics":["gitops","kubernetes","mcp","mcp-server","platform-engineering"],"latest_commit_sha":null,"homepage":"https://mctl.ai/mcp","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mctlhq.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-06T00:52:14.000Z","updated_at":"2026-07-23T18:44:43.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mctlhq/mctl-api","commit_stats":null,"previous_names":["mctlhq/mctl-api"],"tags_count":59,"template":false,"template_full_name":null,"purl":"pkg:github/mctlhq/mctl-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mctlhq%2Fmctl-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mctlhq%2Fmctl-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mctlhq%2Fmctl-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mctlhq%2Fmctl-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mctlhq","download_url":"https://codeload.github.com/mctlhq/mctl-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mctlhq%2Fmctl-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35839500,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-24T02:00:07.870Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gitops","kubernetes","mcp","mcp-server","platform-engineering"],"created_at":"2026-07-24T10:30:19.613Z","updated_at":"2026-07-24T10:30:24.032Z","avatar_url":"https://github.com/mctlhq.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mctl-api\n\nControl plane API for the mctl.ai Internal Developer Platform — dual-protocol (REST + MCP) access to manage services, workspaces, databases, previews, and platform operations.\n\n## What It Does\n\nmctl-api is the central gateway for the mctl.ai platform. It exposes every platform operation — deploying services, creating team workspaces, provisioning databases, managing custom domains — as both REST endpoints and MCP tools. AI coding assistants (Claude, Copilot, Cursor, Gemini, and others) connect via the MCP protocol, while Backstage and CLI tools use the REST API. All write operations are executed through Argo Workflows and reconciled by ArgoCD through a GitOps repository.\n\n## Architecture\n\n```\nAI Clients (Copilot CLI / Claude / Cursor / VS Code / Windsurf / Gemini / Continue.dev)\n    │\n    ▼\nMCP Server (/mcp endpoint, Streamable HTTP)\n    │\n    ▼\nREST API (/api/v1/*)  ◄── Backstage / CLI / HTTP clients\n    │\n    ├──► Argo Workflows    (submits deploy/provision/rollback jobs)\n    ├──► GitOps Repo       (reads service configs, commits changes)\n    ├──► ArgoCD            (sync status, health checks)\n    ├──► Kubernetes        (resource quota usage)\n    ├──► Loki              (service log queries)\n    └──► PostgreSQL        (audit log)\n```\n\n## Tech Stack\n\n| Category | Details |\n|----------|---------|\n| Language | Go 1.25 |\n| HTTP Router | chi v5.2 |\n| MCP Server | mcp-go v0.31 (Streamable HTTP transport) |\n| Auth | GitHub token resolution, Dex/OIDC JWT, OAuth 2.0 PKCE |\n| Database | PostgreSQL via pgx v5.9 (audit logs) |\n| Kubernetes | client-go v0.32 (quota reader) |\n| Rate Limiting | httprate v0.15 (100 req/min read, 20 req/min write) |\n| Container Registry | ghcr.io/mctlhq/mctl-api |\n| Linting | golangci-lint (errcheck, govet, staticcheck, gosec, bodyclose) |\n\n## Project Structure\n\n```\nmctl-api/\n├── cmd/api/main.go              # Entry point, server bootstrap\n├── internal/\n│   ├── api/                     # REST handlers \u0026 router\n│   │   ├── handlers_read.go     # Read operations (list, status, config)\n│   │   ├── handlers_write.go    # Write operations (deploy, create, retire)\n│   │   ├── handlers_domains.go  # Custom domain management\n│   │   ├── handlers_repos.go    # Repository access management\n│   │   ├── oauth_handlers.go    # OAuth 2.0 Authorization Code + PKCE\n│   │   └── router.go            # Route definitions \u0026 middleware\n│   ├── auth/                    # GitHub + OIDC + OAuth authentication\n│   ├── mcp/                     # MCP server implementation (tool registry)\n│   ├── operations/              # Platform operation registry \u0026 executor\n│   ├── argocd/                  # ArgoCD API client\n│   ├── gitops/                  # GitOps repo reader (clone, parse values)\n│   ├── audit/                   # Audit logging (PostgreSQL-backed)\n│   ├── k8s/                     # Kubernetes quota reader\n│   ├── loki/                    # Loki log query client\n│   └── openapi/                 # Embedded OpenAPI spec\n├── e2e/                         # End-to-end tests (build tag: e2e)\n├── helm/                        # Kubernetes Helm chart\n├── Dockerfile                   # Multi-stage Alpine build\n├── Makefile                     # Dev commands (run, test, lint, build)\n├── .golangci.yml                # Linter configuration\n├── .env.example                 # Environment variable template\n├── mcp-config.example.json      # MCP client config examples\n└── .github/workflows/build.yml  # CI/CD pipeline\n```\n\n## Getting Started\n\n### Prerequisites\n\n- Go 1.25+\n- GitHub CLI (`gh`) — for obtaining auth tokens\n- Access to the `mctlhq` GitHub organization\n\n### Local Development\n\n```bash\n# Run API against local gitops clone\nmake run\n\n# Run MCP stdio server pointing at local API\nmake run-mcp\n\n# Both together\nmake run \u0026\nmake run-mcp\n```\n\nAuth is bypassed locally (`AUTH_REQUIRED` defaults to `false` when unset). Set `AUTH_REQUIRED=true` to test authentication.\n\n### Docker\n\n```bash\ndocker build -t mctl-api .\ndocker run -p 8080:8080 mctl-api\n```\n\n## Configuration\n\n### Environment Variables\n\n| Variable | Description | Default | Required |\n|----------|-------------|---------|----------|\n| `PORT` | HTTP server port | `8080` | No |\n| `AUTH_REQUIRED` | Enable authentication | `true` | No |\n| `ADMIN_USERS` | Admin GitHub usernames (comma-separated) | — | No |\n| `GITOPS_REPO_URL` | GitOps repository URL | `https://github.com/mctlhq/mctl-gitops.git` | No |\n| `GITOPS_BRANCH` | GitOps branch | `main` | No |\n| `GITOPS_LOCAL_PATH` | Local cache path for gitops clone | `/tmp/mctl-gitops` | No |\n| `GITOPS_REPO_TOKEN` | GitHub token for HTTPS clone | — | No |\n| `GITOPS_SSH_KEY_PATH` | SSH key path for git clone | — | No |\n| `ARGOCD_URL` | ArgoCD API endpoint | `https://ops.mctl.ai` | No |\n| `ARGOCD_TOKEN` | ArgoCD auth token (from Vault) | — | Yes |\n| `ARGO_WORKFLOWS_NAMESPACE` | Kubernetes namespace for workflows | `argo-workflows` | No |\n| `GITHUB_ORG` | Required GitHub organization | `mctlhq` | No |\n| `DEX_ISSUER_URL` | OIDC issuer URL | `https://ops.mctl.ai/api/dex` | No |\n| `DEX_CLIENT_ID` | JWT audience for Dex | — | No |\n| `SELF_URL` | Public base URL | `https://api.mctl.ai` | No |\n| `ALLOWED_ORIGINS` | CORS allowed origins | — | No |\n| `OAUTH_GITHUB_CLIENT_ID` | GitHub OAuth app client ID | — | No |\n| `OAUTH_GITHUB_CLIENT_SECRET` | GitHub OAuth app client secret | — | No |\n| `OAUTH_JWT_SECRET` | JWT signing secret for OAuth tokens | — | No |\n| `OAUTH_ALLOWED_REDIRECT_URIS` | Allowed OAuth redirect URIs | — | No |\n| `AUDIT_DB_URL` | PostgreSQL connection string (falls back to in-memory) | — | No |\n| `BACKSTAGE_URL` | Backstage catalog URL | — | No |\n| `BACKSTAGE_TOKEN` | Backstage service token | — | No |\n| `LOKI_URL` | Loki base URL for log queries | — | No |\n\n## API / Endpoints\n\n### Authentication\n\nThree authentication methods are supported:\n\n| Method | Detection | Validation |\n|--------|-----------|------------|\n| GitHub personal token | No dots in token | GitHub API → resolve org membership |\n| Dex/OIDC JWT | 3 dot-separated parts | JWKS validation → groups from claims |\n| OAuth 2.0 + PKCE | Authorization Code flow | For Claude.ai custom connectors |\n\nGet a token: run `gh auth token` or visit [mctl.ai/mcp](https://mctl.ai/mcp) to sign in and copy a pre-filled config. Your GitHub account must be a member of the `mctlhq` organization.\n\n### REST API\n\n```bash\n# Health check\ncurl https://api.mctl.ai/healthz\n\n# List tenants\ncurl -H \"Authorization: Bearer $(gh auth token)\" https://api.mctl.ai/api/v1/tenants\n\n# List services\ncurl -H \"Authorization: Bearer $(gh auth token)\" https://api.mctl.ai/api/v1/services\n\n# Service status\ncurl -H \"Authorization: Bearer $(gh auth token)\" https://api.mctl.ai/api/v1/status/billing/payment-api\n\n# Service logs (last 50 lines, past 30 minutes)\ncurl -H \"Authorization: Bearer $(gh auth token)\" \\\n     \"https://api.mctl.ai/api/v1/logs/billing/payment-api?lines=50\u0026since=30m\"\n\n# Trigger a deploy\ncurl -H \"Authorization: Bearer $(gh auth token)\" \\\n     -H \"Content-Type: application/json\" \\\n     -d '{\"team_name\":\"billing\",\"component_name\":\"payment-api\",\"action\":\"deploy\",\"git_tag\":\"v1.2.0\"}' \\\n     https://api.mctl.ai/api/v1/operations/deploy-service/execute\n```\n\n### OpenAPI Documentation\n\n| URL | Description |\n|-----|-------------|\n| `https://api.mctl.ai/openapi.yaml` | Raw OpenAPI 3.0 spec |\n| `https://api.mctl.ai/docs` | Interactive Swagger UI |\n\n### MCP Setup\n\nThe MCP endpoint is available at `https://api.mctl.ai/mcp` (Streamable HTTP). All clients use the same auth — a GitHub token passed as a Bearer header.\n\n**Copilot CLI** — add to `~/.copilot/mcp-config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"mctl\": {\n      \"type\": \"http\",\n      \"url\": \"https://api.mctl.ai/mcp\",\n      \"headers\": { \"Authorization\": \"Bearer \u003cyour-github-token\u003e\" }\n    }\n  }\n}\n```\n\n**Claude Desktop** (Streamable HTTP) — add to `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"mctl\": {\n      \"type\": \"http\",\n      \"url\": \"https://api.mctl.ai/mcp\",\n      \"headers\": { \"Authorization\": \"Bearer \u003cyour-github-token\u003e\" }\n    }\n  }\n}\n```\n\n**Claude Desktop** (stdio, local binary):\n\n```bash\ngo install github.com/mctlhq/mctl-api/cmd/mcp@latest\n```\n\n```json\n{\n  \"mcpServers\": {\n    \"mctl\": {\n      \"command\": \"/Users/\u003cyou\u003e/go/bin/mcp\",\n      \"env\": { \"MCTL_API_URL\": \"https://api.mctl.ai\" }\n    }\n  }\n}\n```\n\n**Cursor** — Settings → Cursor Settings → MCP → Add server (same JSON as Copilot CLI).\n\n**VS Code** — create `.vscode/mcp.json`:\n\n```json\n{\n  \"servers\": {\n    \"mctl\": {\n      \"type\": \"http\",\n      \"url\": \"https://api.mctl.ai/mcp\",\n      \"headers\": { \"Authorization\": \"Bearer ${input:mctlToken}\" }\n    }\n  },\n  \"inputs\": [\n    { \"id\": \"mctlToken\", \"type\": \"promptString\", \"description\": \"GitHub token (run: gh auth token)\", \"password\": true }\n  ]\n}\n```\n\n**Windsurf** — Settings → Windsurf Settings → MCP → Add server (same JSON as Copilot CLI).\n\n**Gemini CLI** — add to `~/.gemini/settings.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"mctl\": {\n      \"httpUrl\": \"https://api.mctl.ai/mcp\",\n      \"headers\": { \"Authorization\": \"Bearer \u003cyour-github-token\u003e\" }\n    }\n  }\n}\n```\n\n**Continue.dev** — add to `~/.continue/config.json`:\n\n```json\n{\n  \"mcpServers\": [\n    {\n      \"name\": \"mctl\",\n      \"transport\": {\n        \"type\": \"streamable-http\",\n        \"url\": \"https://api.mctl.ai/mcp\",\n        \"headers\": { \"Authorization\": \"Bearer \u003cyour-github-token\u003e\" }\n      }\n    }\n  ]\n}\n```\n\n### MCP Tools\n\n**Read operations** (safe, no side effects):\n\n| Tool | Description |\n|------|-------------|\n| `mctl_list_tenants` | List all team workspaces with quotas |\n| `mctl_list_services` | List services, optional team filter |\n| `mctl_get_tenant` | Get workspace details and members |\n| `mctl_get_service_status` | ArgoCD health + sync state |\n| `mctl_get_service_config` | Full service config from GitOps repo |\n| `mctl_get_resource_usage` | Live CPU/memory/pods from K8s ResourceQuota |\n| `mctl_get_service_logs` | Recent log lines from Loki |\n\n**Write operations** (trigger Argo Workflows):\n\n| Tool | Description |\n|------|-------------|\n| `mctl_deploy_service` | Onboard, deploy, or update-config a service |\n| `mctl_create_tenant` | Create team workspace (namespace, quotas, Vault) |\n| `mctl_provision_database` | Provision PostgreSQL on shared CNPG cluster |\n| `mctl_rollback_service` | Roll back to a previous image tag |\n| `mctl_retire_service` | Permanently remove a service |\n| `mctl_create_preview` / `mctl_delete_preview` | Ephemeral preview environments |\n| `mctl_add_custom_domain` / `mctl_remove_custom_domain` | Custom domain management |\n| `mctl_list_repos` / `mctl_sync_repos` / `mctl_grant_repo_access` | Repository access |\n\n## Testing\n\n```bash\n# Unit tests\nmake test\n\n# Lint\nmake lint\n\n# End-to-end tests (requires running platform)\ngo test -tags=e2e ./e2e/ -run TestE2E_FullPlatformSmokeTest\n```\n\nLinting uses golangci-lint with errcheck, govet, staticcheck, gosec, bodyclose, and other checkers configured in `.golangci.yml`.\n\n## CI/CD\n\nGitHub Actions workflow (`.github/workflows/build.yml`):\n\n- **Triggers:** Semver tags (`*.*.*`) and pull requests to `main`\n- **Steps:** Checkout → Go 1.25 setup → golangci-lint → Build + test → Docker build → Push to GHCR → Trivy vulnerability scan → GitOps tag update → Telegram notification\n- **Registry:** `ghcr.io/mctlhq/mctl-api`\n- **Dependabot:** Enabled for `go.mod` dependency updates\n\n## Deployment\n\nDeployed to Kubernetes via Helm chart (`helm/`). ArgoCD syncs the desired state from the mctl-gitops repository.\n\n**Domain:** `api.mctl.ai`\n\nVault secrets required before first deploy:\n\n```bash\n# ArgoCD API token\nvault kv put platform/mctl-api/argocd-token token=\"\u003ctoken\u003e\"\n\n# Backstage service token\nvault kv put platform/mctl-api/backstage-token token=\"\u003ctoken\u003e\"\n\n# Dex SSO client secret\nvault kv put platform/mctl-api/sso client-id=\"mctl-api\" client-secret=\"\u003csecret\u003e\"\n```\n\n## Release Process\n\n```bash\ngit tag 0.2.0 \u0026\u0026 git push origin 0.2.0\n# → CI builds ghcr.io/mctlhq/mctl-api:0.2.0\n# → CI commits new tag to mctl-gitops → ArgoCD deploys\n```\n\nTags use **no `v` prefix**. Every push to `main` also builds a `latest` image for local development.\n\n## Related Projects\n\n| Repository | Description |\n|------------|-------------|\n| [mctl-gitops](https://github.com/mctlhq/mctl-gitops) | GitOps repository — Helm values, ArgoCD app definitions |\n| [mctl-portal](https://github.com/mctlhq/mctl-portal) | Web portal for token management and MCP config generation |\n| [mctl-web](https://github.com/mctlhq/mctl-web) | Marketing site (mctl.ai) |\n| [mctl-agent](https://github.com/mctlhq/mctl-agent) | Platform agent components |\n\n## License\n\nApache 2.0\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmctlhq%2Fmctl-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmctlhq%2Fmctl-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmctlhq%2Fmctl-api/lists"}