init: scaffold with PLAN.md, package.json, tsconfig.json
This commit is contained in:
@@ -0,0 +1,281 @@
|
||||
# Komodo MCP Server — Implementation Plan
|
||||
|
||||
**Date:** 2026-09-07
|
||||
**Status:** Planning (pre-OpenChamber handoff)
|
||||
**Author:** Hermes Conrad, Grade 36 Bureaucrat
|
||||
|
||||
---
|
||||
|
||||
## 1. Problem Statement
|
||||
|
||||
We run Komodo (build/deploy platform) at `10.10.2.114:9120` / `komodo.example.com`. Currently all Komodo operations go through raw `curl` + `komodo-token.sh` auth. An MCP server would let any Hermes agent (or any MCP-capable tool) interact with Komodo natively — query builds, trigger deploys, inspect stacks, manage secrets — without bespoke shell scripts per operation.
|
||||
|
||||
## 2. Research Findings
|
||||
|
||||
| Check | Result |
|
||||
|-------|--------|
|
||||
| GitHub search ("komodo mcp server") | **Zero results** — no existing project |
|
||||
| GitHub search ("mcp server" + "komodo-dev") | None |
|
||||
| Komodo official docs / integrations | No MCP mention — they have REST/RPC API only |
|
||||
| npm registry ("komodo mcp") | None |
|
||||
| Similar projects (mcp-servers monorepo, etc.) | No Komodo adapter exists anywhere |
|
||||
|
||||
**Conclusion: We are building the first Komodo MCP server.** Clean slate, no competition. This is Form 1-A territory — originator's privilege.
|
||||
|
||||
## 3. Komodo API Surface
|
||||
|
||||
### 3.1 Architecture
|
||||
- **Protocol:** RPC-style HTTP. All calls: `POST /{read|write|execute}/{RequestName}`
|
||||
- **Auth:** `Authorization: Bearer <JWT>` (obtained via login POST)
|
||||
- **Content-Type:** `application/json` for all requests
|
||||
- **Response:** JSON (list endpoints return bare arrays, not wrapped `data`)
|
||||
- **REST-style paths (`/servers`, `/api/servers`)** → serve the SPA HTML, do NOT use
|
||||
|
||||
### 3.2 Endpoint Categories
|
||||
|
||||
#### Read (~50 endpoints)
|
||||
```
|
||||
read/ListStacks, read/ListStackServices
|
||||
read/ListBuilds, read/GetBuild
|
||||
read/ListServers, read/GetServer
|
||||
read/ListProcedures, read/GetProcedure
|
||||
read/ListDeployments, read/GetDeployment
|
||||
read/ListAlerters, read/GetAlerter
|
||||
read/ListImageRegistryAccounts, read/GetImageRegistryAccount
|
||||
read/ListSyncResources, read/GetSyncResource
|
||||
read/ListResources, read/GetResource
|
||||
read/ListResourceSyncContents
|
||||
read/SearchStacks, read/SearchBuilds, read/SearchServers
|
||||
read/SearchProcedures, read/SearchDeployments, read/SearchAlerters
|
||||
read/SearchImageRegistryAccounts, read/SearchSyncResources
|
||||
read/ListServerStats
|
||||
read/GetStack, read/GetStackServices
|
||||
read/GetDeploymentLogs
|
||||
read/GetResourceSyncDifferences
|
||||
read/GetBuildAggregatedStatus
|
||||
read/GetUser, read/ListUsers, read/GetLicenseInfo
|
||||
read/GetGlobalStats, read/GetResourceStats
|
||||
read/ListTags, read/GetTag, read/ListTagMappings
|
||||
read/ListBinding, read/GetBinding
|
||||
read/GetConcurrencyLimitUsage
|
||||
read/ListExecutions
|
||||
read/ListAccessRequests, read/GetAccessRequest
|
||||
```
|
||||
|
||||
#### Write (~60 endpoints)
|
||||
```
|
||||
write/CreateStack, write/UpdateStack, write/DeleteStack
|
||||
write/CreateBuild, write/UpdateBuild, write/DeleteBuild
|
||||
write/CreateServer, write/UpdateServer, write/DeleteServer
|
||||
write/CreateProcedure, write/UpdateProcedure, write/DeleteProcedure
|
||||
write/CreateDeployment, write/UpdateDeployment, write/DeleteDeployment
|
||||
write/CreateAlerter, write/UpdateAlerter, write/DeleteAlerter
|
||||
write/CreateImageRegistryAccount, write/UpdateImageRegistryAccount
|
||||
write/CreateSyncResource, write/UpdateSyncResource, write/DeleteSyncResource
|
||||
write/UpdateStackServiceNames
|
||||
write/UpdateServerTemplate, write/UpdateServerTemplateInstances
|
||||
write/BindStack, write/BindServer
|
||||
write/AddTag, write/UpdateTag, write/DeleteTag, write/UpdateTagMapping
|
||||
write/UpdateBinding, write/UpdateAllBindings
|
||||
write/MarkResourceSyncDeployed
|
||||
write/UpdateUser, write/UpdateUserPermissions
|
||||
write/UpdateConcurrencyLimit
|
||||
write/AcknowledgeAccessRequest
|
||||
write/CreateTagMapping, write/DeleteTagMapping
|
||||
write/UpdateProcedureSchedule
|
||||
write/CreateCustomPermission, write/UpdateCustomPermission, write/DeleteCustomPermission
|
||||
write/UpdateCustomPermissionTagBindings
|
||||
```
|
||||
|
||||
#### Execute (~40 endpoints)
|
||||
```
|
||||
execute/RunBuild
|
||||
execute/DeployStack, execute/DeployStackService
|
||||
execute/RunProcedure, execute/RunProcedureStage
|
||||
execute/RunDeploymentAction, execute/RunDeploymentSync
|
||||
execute/RunResourceSync, execute/RunResourceSyncSync
|
||||
execute/RunStackRefreshCache, execute/RunStackRefreshContent
|
||||
execute/RunStackPull, execute/RunStackPullDeployment
|
||||
execute/RunStackStop, execute/RunStackRestart
|
||||
execute/RunStackPause, execute/RunStackUnpause
|
||||
execute/RunStackRemoveOrphanContainers
|
||||
execute/RunStackToggleServiceDependencies
|
||||
execute/RunStackAutoUpdate, execute/RunStackCommit
|
||||
execute/RunServerRefresh, execute/RunServerRefreshContainers
|
||||
execute/RunServerUpdatePeriphery, execute/RunServerPruneImages
|
||||
execute/RunServerPruneContainers, execute/RunServerPruneNetworks
|
||||
execute/RunServerStats, execute/RunServerRunCommand
|
||||
execute/RunServerScripts, execute/RunServerCopy
|
||||
execute/RunServerMove, execute/RunDeploymentExecute
|
||||
execute/RunDeploymentRedeploy, execute/RunDeploymentDestroy
|
||||
execute/RunDeploymentStop, execute/RunDeploymentLogs
|
||||
execute/RunSyncDeployment
|
||||
execute/GetMcpToken
|
||||
```
|
||||
|
||||
### 3.3 Auth Flow
|
||||
1. `POST /auth/login` with `{ username, password }` → returns JWT
|
||||
2. Use JWT as `Authorization: Bearer <token>` for all subsequent requests
|
||||
3. Token expiry: unknown — cache and re-login on 401
|
||||
|
||||
### 3.4 Our Instance
|
||||
- **Host:** `10.10.2.114:9120` (LXC 121 on yavin)
|
||||
- **NPM Proxy:** `https://komodo.example.com` (websockets ON)
|
||||
- **Deploy host:** `10.10.2.52` (ProjectE)
|
||||
- **Registry:** `git.example.com` (Gitea built-in)
|
||||
- **Secrets:** Bitwarden items — never write to files
|
||||
|
||||
## 4. Design Decisions
|
||||
|
||||
### 4.1 Tool Grouping (NOT one tool per endpoint)
|
||||
|
||||
Komodo has 150+ endpoints. Exposing each as a separate MCP tool would overwhelm any model. Instead, group by entity type with **action-based tools**:
|
||||
|
||||
| MCP Tool | Komodo Endpoints Covered |
|
||||
|----------|-------------------------|
|
||||
| `komodo_list` | All `read/List*` + `read/Search*` endpoints |
|
||||
| `komodo_get` | All `read/Get*` endpoints |
|
||||
| `komodo_create` | All `write/Create*` endpoints |
|
||||
| `komodo_update` | All `write/Update*` endpoints |
|
||||
| `komodo_delete` | All `write/Delete*` endpoints |
|
||||
| `komodo_execute` | All `execute/*` endpoints |
|
||||
| `komodo_logs` | `execute/GetDeploymentLogs`, `read/GetDeploymentLogs` |
|
||||
|
||||
Each tool takes a `resource_type` enum (stack, build, server, procedure, deployment, alerter, etc.) plus a `params` object. The server maps resource_type → Komodo endpoint.
|
||||
|
||||
**~7 tools total** — manageable for any model, covers full API surface.
|
||||
|
||||
### 4.2 Transport
|
||||
- **HTTP/SSE** on a configurable port (default: `9800`)
|
||||
- Hermes connects via `mcp_servers.komodo.url: http://localhost:9800/sse`
|
||||
- No stdio — this runs as a persistent service on the homelab
|
||||
|
||||
### 4.3 Auth Management
|
||||
- Credentials stored in Bitwarden, fetched at runtime via `bw` CLI
|
||||
- Token cached in memory, auto-refreshed on 401
|
||||
- Config in MCP server startup args or env vars pointing to Bitwarden item IDs
|
||||
|
||||
### 4.4 Tech Stack
|
||||
- **Runtime:** Node.js 22+ (consistent with existing MCP servers)
|
||||
- **Language:** TypeScript
|
||||
- **MCP SDK:** `@modelcontextprotocol/sdk`
|
||||
- **HTTP transport:** `StreamableHTTPServerTransport` (modern MCP standard)
|
||||
- **No external deps** beyond MCP SDK — raw HTTP to Komodo API
|
||||
|
||||
### 4.5 Location
|
||||
- **Gitea repo:** `BuzzbeeSCD/komodo-mcp-server` (private)
|
||||
- **Deploy:** On the same LXC as Komodo (10.10.2.114) or as a Hermes MCP server running locally
|
||||
- **Local dev:** `/home/user/workspace/komodo-mcp-server/`
|
||||
|
||||
## 5. Implementation Plan
|
||||
|
||||
### Phase 1: Scaffold + Auth
|
||||
1. Init TypeScript project with MCP SDK
|
||||
2. Implement Komodo auth (JWT login, token caching, auto-refresh)
|
||||
3. Basic server skeleton with health check
|
||||
4. Single `komodo_read` tool as proof-of-concept
|
||||
|
||||
### Phase 2: Full CRUD Coverage
|
||||
5. Implement `komodo_list` with resource_type routing
|
||||
6. Implement `komodo_get` with resource_type + ID routing
|
||||
7. Implement `komodo_create` / `komodo_update` / `komodo_delete`
|
||||
8. Validation layer — required params per resource_type
|
||||
|
||||
### Phase 3: Execute Operations
|
||||
9. Implement `komodo_execute` for build/deploy/procedure triggers
|
||||
10. Implement `komodo_logs` for deployment log retrieval
|
||||
11. SSE support for long-running operations (builds, deploys)
|
||||
|
||||
### Phase 4: Packaging + Deploy
|
||||
12. systemd service unit for persistent operation
|
||||
13. Hermes config integration (`mcp_servers.komodo`)
|
||||
14. Bitwarden credential integration
|
||||
15. Documentation + skill creation
|
||||
|
||||
## 6. Tool Schemas (Draft)
|
||||
|
||||
### `komodo_list`
|
||||
```json
|
||||
{
|
||||
"name": "komodo_list",
|
||||
"description": "List or search Komodo resources (stacks, builds, servers, procedures, deployments, alerters, etc.)",
|
||||
"parameters": {
|
||||
"resource_type": {
|
||||
"type": "string",
|
||||
"enum": ["stack", "build", "server", "procedure", "deployment", "alerter", "image_registry_account", "sync_resource", "user", "tag", "execution", "access_request"]
|
||||
},
|
||||
"search": { "type": "string", "description": "Optional search/filter query" },
|
||||
"project": { "type": "string", "description": "Filter by project name or ID" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `komodo_get`
|
||||
```json
|
||||
{
|
||||
"name": "komodo_get",
|
||||
"description": "Get a single Komodo resource by ID",
|
||||
"parameters": {
|
||||
"resource_type": { "type": "string", "enum": ["..." /* same as list */] },
|
||||
"id": { "type": "string", "description": "Resource ID or name" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `komodo_execute`
|
||||
```json
|
||||
{
|
||||
"name": "komodo_execute",
|
||||
"description": "Execute a Komodo operation (build, deploy, procedure run, server refresh, etc.)",
|
||||
"parameters": {
|
||||
"operation": {
|
||||
"type": "string",
|
||||
"enum": ["run_build", "deploy_stack", "deploy_stack_service", "run_procedure", "run_procedure_stage", "run_resource_sync", "refresh_stack_cache", "refresh_stack_content", "stack_pull", "stack_stop", "stack_restart", "stack_pause", "stack_unpause", "server_refresh", "server_update_periphery", "server_prune_images", "server_prune_containers", "server_run_command", "server_scripts", "get_mcp_token"]
|
||||
},
|
||||
"id": { "type": "string", "description": "Resource ID or name" },
|
||||
"params": { "type": "object", "description": "Additional parameters for the operation" }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 7. Risks & Mitigations
|
||||
|
||||
| Risk | Mitigation |
|
||||
|------|-----------|
|
||||
| Token expiry unknown | Re-login on 401; cache token in memory |
|
||||
| Komodo API undocumented endpoints | Start with known endpoints from komodo-ops skill; expand empirically |
|
||||
| 150+ endpoints in `enum` lists overwhelm models | Keep `resource_type` enum short — ~12 types, not 150 endpoints |
|
||||
| Long-running builds block MCP tool calls | Use fire-and-forget for execute ops; return execution ID for status polling |
|
||||
| SSE transport complexity | Use stdio for local Hermes integration first, HTTP later if remote access needed |
|
||||
|
||||
## 8. Success Criteria
|
||||
|
||||
- [ ] `komodo_list` returns live data from our Komodo instance
|
||||
- [ ] `komodo_execute run_build` triggers an actual build
|
||||
- [ ] `komodo_execute deploy_stack` triggers an actual deploy
|
||||
- [ ] Token auto-refreshes on expiry without manual intervention
|
||||
- [ ] Hermes can use Komodo tools via `mcp_servers.komodo` config
|
||||
- [ ] Service runs as systemd unit with auto-restart
|
||||
|
||||
## 9. Files to Create
|
||||
|
||||
```
|
||||
komodo-mcp-server/
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
├── src/
|
||||
│ ├── index.ts # Entry point, MCP server setup
|
||||
│ ├── komodo-client.ts # Komodo API client (auth, HTTP, token caching)
|
||||
│ ├── tools/
|
||||
│ │ ├── list.ts # komodo_list tool
|
||||
│ │ ├── get.ts # komodo_get tool
|
||||
│ │ ├── create.ts # komodo_create tool
|
||||
│ │ ├── update.ts # komodo_update tool
|
||||
│ │ ├── delete.ts # komodo_delete tool
|
||||
│ │ ├── execute.ts # komodo_execute tool
|
||||
│ │ └── logs.ts # komodo_logs tool
|
||||
│ └── types.ts # Komodo API type definitions
|
||||
├── references/
|
||||
│ └── api.md # Full endpoint → tool mapping reference
|
||||
└── README.md
|
||||
```
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"name": "komodo-mcp-server",
|
||||
"version": "1.0.0",
|
||||
"description": "MCP server for Komodo build/deploy platform — full API coverage",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"start": "node dist/index.js",
|
||||
"dev": "tsx src/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.12.1",
|
||||
"zod": "^3.24.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.0.0",
|
||||
"tsx": "^4.19.0",
|
||||
"typescript": "^5.7.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "Node16",
|
||||
"moduleResolution": "Node16",
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
Reference in New Issue
Block a user