lattice-mcp 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +40 -21
- package/README.md +169 -71
- package/index.js +22 -7
- package/package.json +3 -2
package/AGENTS.md
CHANGED
|
@@ -32,8 +32,9 @@ Those live in [`lattice-api`](https://github.com/aidenappl/lattice-api) and
|
|
|
32
32
|
- **Runtime:** Node ≥18 (needs global `fetch` and `AbortSignal.timeout`). `"type": "module"` —
|
|
33
33
|
ESM only, top-level `await` is used at the bottom of `index.js`.
|
|
34
34
|
- **`@modelcontextprotocol/sdk` ^1.29.0** — `McpServer` + `StdioServerTransport`.
|
|
35
|
-
- **`zod
|
|
36
|
-
|
|
35
|
+
- **`zod` ^4.4.3** — argument schemas. Declared explicitly as of **1.1.1** (it was previously
|
|
36
|
+
only resolved transitively through the MCP SDK, a latent fragility); the range matches the
|
|
37
|
+
version the SDK resolves.
|
|
37
38
|
- No build step, no bundler, no tests, no lint config. `node --check index.js` is the only
|
|
38
39
|
static gate.
|
|
39
40
|
|
|
@@ -90,9 +91,12 @@ and supply the real token.
|
|
|
90
91
|
the noun (`lattice_list_database_instances`). The prefix is what disambiguates these from
|
|
91
92
|
`monitor_*` and `forta_*` tools in a shared client.
|
|
92
93
|
- **`api(method, path, params, body)`** — `params` become query string entries (undefined/null
|
|
93
|
-
are dropped), `body` is JSON-encoded.
|
|
94
|
-
|
|
95
|
-
|
|
94
|
+
are dropped), `body` is JSON-encoded. Failures are returned as tool output, never thrown, so
|
|
95
|
+
they surface to the agent rather than crashing the transport. A network-level failure returns
|
|
96
|
+
`{success:false, error_message: "API request failed: …"}`; a response that arrives but is not
|
|
97
|
+
JSON (e.g. a 502/504 HTML page from the TLS proxy) returns
|
|
98
|
+
`{success:false, error_code: <http status>, error_message: "API returned a non-JSON response …"}`
|
|
99
|
+
with a truncated body — bodies are never logged, only returned, since they can carry secrets.
|
|
96
100
|
- **`body(obj)`** strips `undefined` keys. **Always use it on PUT/PATCH tools.** The API treats
|
|
97
101
|
a present-but-null field as an explicit clear, so forwarding raw `{...fields}` on an update
|
|
98
102
|
would wipe every field the caller didn't pass.
|
|
@@ -122,28 +126,42 @@ exits immediately if either is missing. In practice these come from the `env` bl
|
|
|
122
126
|
|
|
123
127
|
**Tool groups**, in file order:
|
|
124
128
|
|
|
129
|
+
The counts below sum to **125**, matching the header and `grep -c 'server.tool(' index.js`. The
|
|
130
|
+
first six rows are the original, pre-`1.1.0` tools (registered top-of-file with no banner comment);
|
|
131
|
+
every bolded row corresponds to a `// ───` banner group and matches its exact in-file name.
|
|
132
|
+
|
|
125
133
|
| Group | Tools | Notes |
|
|
126
134
|
|-------|-------|-------|
|
|
127
135
|
| Overview & health | 2 | `lattice_overview`, `lattice_health` |
|
|
128
136
|
| Workers | 3 + 4 actions | list/get/metrics; reboot, upgrade, stop-all, start-all |
|
|
129
|
-
| Stacks | 2 +
|
|
130
|
-
| Containers |
|
|
131
|
-
| Deployments | 4 | list/get/logs, rollback,
|
|
132
|
-
|
|
|
133
|
-
|
|
|
134
|
-
| **
|
|
135
|
-
| **
|
|
136
|
-
| **
|
|
137
|
-
| **
|
|
138
|
-
| **
|
|
139
|
-
| **
|
|
140
|
-
| **
|
|
141
|
-
| **
|
|
137
|
+
| Stacks | 2 + 5 actions | list/get; deploy, restart, stop, start, update |
|
|
138
|
+
| Containers | 4 + 8 actions | list/get/logs/lifecycle; start, stop, restart, kill, pause, unpause, remove, recreate. (`lattice_get_container_metrics` is *not* here — it lives under **Discovery & diagnostics**.) |
|
|
139
|
+
| Deployments | 4 | list/get/logs, rollback. (`lattice_approve_deployment` is *not* here — it lives under **Stacks — lifecycle, compose & deploy tokens**.) |
|
|
140
|
+
| Instance self-update | 2 | `lattice_update_api`, `lattice_update_web` — tell the API/web container to pull its latest image and redeploy itself |
|
|
141
|
+
| Audit & API tokens | 4 | `lattice_get_audit_log`; API token list/create/delete |
|
|
142
|
+
| **Database instances** | **11** | CRUD, `lattice_database_action` (start/stop/restart/remove enum), `lattice_get_database_credentials`, snapshot list/create/restore/delete |
|
|
143
|
+
| **Backup destinations** | **6** | list/get/create/update/delete + `lattice_test_backup_destination` |
|
|
144
|
+
| **Registries** | **8** | list/create/update/delete, `lattice_test_registry`, `lattice_test_registry_inline`, `lattice_list_registry_repositories`, `lattice_list_registry_tags` |
|
|
145
|
+
| **Discovery & diagnostics** | **7** | `lattice_search`, `lattice_get_anomalies`, `lattice_get_fleet_metrics`, `lattice_get_versions`, `lattice_refresh_versions`, `lattice_get_container_metrics`, `lattice_get_self` |
|
|
146
|
+
| **Stacks — lifecycle, compose & deploy tokens** | **13** | create/delete, `lattice_get_stack_containers`, compose update/sync/import, export/import, `lattice_save_stack_as_template`, deploy-token list/create/delete, `lattice_approve_deployment` |
|
|
147
|
+
| **Containers — definition CRUD** | **3** | `lattice_create_container`, `lattice_update_container`, `lattice_delete_container` |
|
|
148
|
+
| **Workers — registration, tokens, volumes, networks** | **16** | worker create/update/delete, `lattice_get_worker_container_stats`, worker-token ×3, volume ×3, worker-network ×3, `lattice_list_all_networks`, `lattice_delete_network`, `lattice_force_remove_container` |
|
|
149
|
+
| **Global env vars, templates, webhooks** | **12** | env-var CRUD (4), template list/create/delete (3), webhook list/create/update/delete/test (5) |
|
|
150
|
+
| **Users & instance configuration** | **11** | user CRUD (4); SSO get/update (2); SMTP get/update/test (3); notification-prefs get/update (2) |
|
|
142
151
|
|
|
143
152
|
Bolded groups were added in **1.1.0**, closing a gap where the MCP had drifted roughly two
|
|
144
153
|
months behind `lattice-api` — database instances shipped in the API in May 2026 and were
|
|
145
154
|
entirely unreachable from the MCP until then.
|
|
146
155
|
|
|
156
|
+
**1.1.1** is a bug-fix release (no tool count change). It corrects three request-shape/route bugs
|
|
157
|
+
verified against `lattice-api` handlers: `lattice_get_self` now calls `GET /auth/self` (the old
|
|
158
|
+
`GET /admin/self` route never existed and always 404'd — the endpoint is `HandleAuthSelf` on the
|
|
159
|
+
bearer-authed `/auth` subrouter); `lattice_force_remove_container` now sends `{container_name}` in
|
|
160
|
+
the JSON body (`HandleForceRemoveContainer` reads it there, not from query params, so the old call
|
|
161
|
+
always 400'd); and `lattice_test_backup_destination` now marks `worker_id` as **required** (a query
|
|
162
|
+
param the handler 400s without — the test dispatches over the worker's WebSocket). It also hardens
|
|
163
|
+
`api()` against non-JSON responses (see *How code is written here*) and declares `zod` explicitly.
|
|
164
|
+
|
|
147
165
|
**Consolidations.** Where `lattice-api` exposes several paths served by one handler, this repo
|
|
148
166
|
exposes one tool with an enum rather than N tools. `lattice_database_action` covers
|
|
149
167
|
`/start`, `/stop`, `/restart` and `/remove`. Worker actions are the historical exception — they
|
|
@@ -187,9 +205,10 @@ predate this convention and remain separate tools.
|
|
|
187
205
|
- **Do not break tool names.** They are a public contract: renaming one silently breaks any
|
|
188
206
|
saved workflow or prompt that referenced it. Add a new tool and deprecate in the description
|
|
189
207
|
instead.
|
|
190
|
-
- **`zod` is
|
|
191
|
-
|
|
192
|
-
|
|
208
|
+
- **`zod` is declared explicitly** in `package.json` (`^4.4.3`) as of **1.1.1**. It used to
|
|
209
|
+
resolve only transitively through the MCP SDK, which meant a SDK change that dropped or hoisted
|
|
210
|
+
it differently would break every tool schema at startup. Keep the declared range aligned with
|
|
211
|
+
the version the SDK actually resolves (check `package-lock.json`).
|
|
193
212
|
- **Keep destructive descriptions honest.** If a tool destroys data, the description must say so
|
|
194
213
|
and name the safer alternative.
|
|
195
214
|
- Publishing is outward-facing and effectively irreversible (npm unpublish is restricted after
|
package/README.md
CHANGED
|
@@ -1,18 +1,55 @@
|
|
|
1
1
|
# lattice-mcp
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Model Context Protocol server for [Lattice](https://github.com/aidenappl/lattice-api), the container orchestration platform that runs every `appleby.cloud` service. Gives Claude Code direct, typed access to workers, stacks, containers, deployments, databases, registries, networks, volumes and instance configuration.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> **appleby.cloud platform** · MCP server · published to npm as `lattice-mcp` · consumed via `npx -y lattice-mcp`
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
`lattice-mcp` is a single-file Node ESM program (`index.js`) that speaks MCP over stdio and translates tool calls into HTTP requests against the `lattice-api` admin surface. It exposes **125 typed tools** and holds no business logic, caching or state of its own — every behaviour (pagination, validation, side effects) comes from `lattice-api`.
|
|
12
|
+
|
|
13
|
+
Once configured, ask Claude Code things like:
|
|
14
|
+
|
|
15
|
+
- "What's the status of all stacks?"
|
|
16
|
+
- "Show me logs for the forta-api container"
|
|
17
|
+
- "Which containers are unhealthy?" (`lattice_get_anomalies` is the best first call)
|
|
18
|
+
- "Deploy stack 5" / "Rollback the last deployment on stack 12"
|
|
19
|
+
- "What image tags can I deploy from the registry?"
|
|
20
|
+
|
|
21
|
+
## Role in the appleby.cloud ecosystem
|
|
22
|
+
|
|
23
|
+
| Repo | Relationship |
|
|
24
|
+
|------|--------------|
|
|
25
|
+
| [`lattice-api`](https://github.com/aidenappl/lattice-api) | The API this wraps — its route table is the source of truth for tool coverage. |
|
|
26
|
+
| [`lattice-web`](https://github.com/aidenappl/lattice-web) | Next.js dashboard over the same API. |
|
|
27
|
+
| [`lattice-runner`](https://github.com/aidenappl/lattice-runner) | Agent on each worker VM; WebSocket back to `lattice-api`. |
|
|
28
|
+
| `monitor-mcp` / `forta-mcp` / `keyring-mcp` / `openbucket-mcp` | Sibling MCP servers, same single-file structure. |
|
|
29
|
+
|
|
30
|
+
## Tech stack
|
|
31
|
+
|
|
32
|
+
- **Node ≥18** (needs global `fetch` and `AbortSignal.timeout`), ESM (`"type": "module"`).
|
|
33
|
+
- **`@modelcontextprotocol/sdk` ^1.29.0** — `McpServer` + `StdioServerTransport`.
|
|
34
|
+
- **`zod` ^4.4.3** for argument schemas (a declared dependency as of 1.1.1).
|
|
35
|
+
- No build step, no bundler. `node --check index.js` is the only static gate.
|
|
36
|
+
|
|
37
|
+
## Getting started
|
|
38
|
+
|
|
39
|
+
### Prerequisites
|
|
40
|
+
|
|
41
|
+
- Node ≥18.
|
|
42
|
+
- A Lattice API URL and API token. Generate a token from the Lattice web dashboard under **Settings > API Tokens**.
|
|
43
|
+
|
|
44
|
+
### Setup
|
|
45
|
+
|
|
46
|
+
Quickest — interactive setup writes the `lattice` block into `~/.mcp.json`:
|
|
6
47
|
|
|
7
48
|
```bash
|
|
8
49
|
npx lattice-mcp --setup
|
|
9
50
|
```
|
|
10
51
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
## Manual Setup
|
|
14
|
-
|
|
15
|
-
Add to `~/.mcp.json`:
|
|
52
|
+
Or configure it manually in `~/.mcp.json`:
|
|
16
53
|
|
|
17
54
|
```json
|
|
18
55
|
{
|
|
@@ -29,21 +66,41 @@ Add to `~/.mcp.json`:
|
|
|
29
66
|
}
|
|
30
67
|
```
|
|
31
68
|
|
|
32
|
-
|
|
69
|
+
Restart Claude Code after setup so the new server and tools are picked up.
|
|
70
|
+
|
|
71
|
+
### Environment variables
|
|
72
|
+
|
|
73
|
+
| Variable | Required | Description |
|
|
74
|
+
|----------|----------|-------------|
|
|
75
|
+
| `LATTICE_API_URL` | Yes | Lattice API base URL |
|
|
76
|
+
| `LATTICE_API_TOKEN` | Yes | Bearer token for authentication (sent on every request) |
|
|
77
|
+
|
|
78
|
+
## Development
|
|
79
|
+
|
|
80
|
+
| Command | What it does |
|
|
81
|
+
|---------|--------------|
|
|
82
|
+
| `node index.js --setup` | Interactive setup — writes the `lattice` block into `~/.mcp.json` |
|
|
83
|
+
| `npm install` | Install dependencies (not vendored) |
|
|
84
|
+
| `node --check index.js` | Syntax gate — the only static check that exists |
|
|
85
|
+
| `LATTICE_API_URL=… LATTICE_API_TOKEN=… node index.js` | Run the server on stdio |
|
|
86
|
+
| `grep -c 'server.tool(' index.js` | Confirm the tool count (should be 125) |
|
|
87
|
+
| `npm publish` | Publish to npm — **this is deployment** (requires 2FA passkey from an interactive terminal) |
|
|
33
88
|
|
|
34
89
|
## Tools
|
|
35
90
|
|
|
36
|
-
|
|
91
|
+
All 125 tools, grouped as they appear in `index.js`. ⚠️ marks destructive tools; their descriptions state the blast radius.
|
|
92
|
+
|
|
93
|
+
### Overview & health
|
|
37
94
|
| Tool | Description |
|
|
38
95
|
|------|-------------|
|
|
39
|
-
| `lattice_overview` | Fleet overview — worker
|
|
96
|
+
| `lattice_overview` | Fleet overview — worker/stack/container counts, failed stacks, CPU/memory |
|
|
40
97
|
| `lattice_health` | API health and database connectivity |
|
|
41
98
|
|
|
42
99
|
### Workers
|
|
43
100
|
| Tool | Description |
|
|
44
101
|
|------|-------------|
|
|
45
|
-
| `lattice_list_workers` | List workers with status, IP, versions |
|
|
46
|
-
| `lattice_get_worker` | Detailed worker info |
|
|
102
|
+
| `lattice_list_workers` | List workers with status, IP, versions, heartbeat |
|
|
103
|
+
| `lattice_get_worker` | Detailed worker info including metrics |
|
|
47
104
|
| `lattice_get_worker_metrics` | CPU, memory, disk, network metrics |
|
|
48
105
|
| `lattice_reboot_worker` | Reboot a worker machine |
|
|
49
106
|
| `lattice_upgrade_worker` | Upgrade worker runner to latest |
|
|
@@ -55,11 +112,11 @@ Generate an API token from the Lattice web dashboard under **Settings > API Toke
|
|
|
55
112
|
|------|-------------|
|
|
56
113
|
| `lattice_list_stacks` | List stacks with status and worker assignment |
|
|
57
114
|
| `lattice_get_stack` | Full stack details including compose YAML |
|
|
58
|
-
| `lattice_update_stack` | Update stack configuration |
|
|
59
115
|
| `lattice_deploy_stack` | Deploy a stack (all or specific containers) |
|
|
60
116
|
| `lattice_restart_stack` | Restart all containers in a stack |
|
|
61
117
|
| `lattice_stop_stack` | Stop all containers in a stack |
|
|
62
118
|
| `lattice_start_stack` | Start all containers in a stack |
|
|
119
|
+
| `lattice_update_stack` | Update stack configuration |
|
|
63
120
|
|
|
64
121
|
### Containers
|
|
65
122
|
| Tool | Description |
|
|
@@ -74,8 +131,8 @@ Generate an API token from the Lattice web dashboard under **Settings > API Toke
|
|
|
74
131
|
| `lattice_kill_container` | Force kill a container |
|
|
75
132
|
| `lattice_pause_container` | Pause a running container |
|
|
76
133
|
| `lattice_unpause_container` | Unpause a paused container |
|
|
77
|
-
| `lattice_remove_container` | Remove a container |
|
|
78
|
-
| `lattice_recreate_container` | Remove and recreate a container |
|
|
134
|
+
| `lattice_remove_container` | Remove a container ⚠️ |
|
|
135
|
+
| `lattice_recreate_container` | Remove and recreate a container ⚠️ |
|
|
79
136
|
|
|
80
137
|
### Deployments
|
|
81
138
|
| Tool | Description |
|
|
@@ -83,36 +140,21 @@ Generate an API token from the Lattice web dashboard under **Settings > API Toke
|
|
|
83
140
|
| `lattice_list_deployments` | List deployments with status and timing |
|
|
84
141
|
| `lattice_get_deployment` | Deployment details with container-level status |
|
|
85
142
|
| `lattice_get_deployment_logs` | Pull, create, start, swap events with timing |
|
|
86
|
-
| `lattice_rollback_deployment` | Rollback to previous state |
|
|
143
|
+
| `lattice_rollback_deployment` | Rollback to previous state ⚠️ |
|
|
144
|
+
|
|
145
|
+
### Instance self-update
|
|
146
|
+
| Tool | Description |
|
|
147
|
+
|------|-------------|
|
|
148
|
+
| `lattice_update_api` | Trigger the Lattice API container to self-update |
|
|
149
|
+
| `lattice_update_web` | Trigger the Lattice web container to update |
|
|
87
150
|
|
|
88
|
-
###
|
|
151
|
+
### Audit & API tokens
|
|
89
152
|
| Tool | Description |
|
|
90
153
|
|------|-------------|
|
|
91
|
-
| `lattice_get_audit_log` | Recent audit log entries |
|
|
92
|
-
| `lattice_update_api` | Trigger API self-update |
|
|
93
|
-
| `lattice_update_web` | Trigger web container update |
|
|
154
|
+
| `lattice_get_audit_log` | Recent audit log entries (who did what, when) |
|
|
94
155
|
| `lattice_list_api_tokens` | List API tokens |
|
|
95
156
|
| `lattice_create_api_token` | Create a new API token |
|
|
96
|
-
| `lattice_delete_api_token` | Delete an API token |
|
|
97
|
-
|
|
98
|
-
## Example Prompts
|
|
99
|
-
|
|
100
|
-
- "What's the status of all stacks?"
|
|
101
|
-
- "Show me logs for the forta-api container"
|
|
102
|
-
- "Deploy stack 5"
|
|
103
|
-
- "Which containers are unhealthy?"
|
|
104
|
-
- "Rollback the last deployment on stack 12"
|
|
105
|
-
|
|
106
|
-
## Environment Variables
|
|
107
|
-
|
|
108
|
-
| Variable | Required | Description |
|
|
109
|
-
|----------|----------|-------------|
|
|
110
|
-
| `LATTICE_API_URL` | Yes | Lattice API base URL |
|
|
111
|
-
| `LATTICE_API_TOKEN` | Yes | API token for authentication |
|
|
112
|
-
|
|
113
|
-
## License
|
|
114
|
-
|
|
115
|
-
MIT
|
|
157
|
+
| `lattice_delete_api_token` | Delete an API token ⚠️ |
|
|
116
158
|
|
|
117
159
|
### Database instances
|
|
118
160
|
| Tool | Description |
|
|
@@ -132,18 +174,22 @@ MIT
|
|
|
132
174
|
### Backup destinations
|
|
133
175
|
| Tool | Description |
|
|
134
176
|
|------|-------------|
|
|
135
|
-
| `lattice_list_backup_destinations`
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `
|
|
177
|
+
| `lattice_list_backup_destinations` | List backup destinations |
|
|
178
|
+
| `lattice_get_backup_destination` | One destination's configuration |
|
|
179
|
+
| `lattice_create_backup_destination` | Create a destination |
|
|
180
|
+
| `lattice_update_backup_destination` | Update a destination |
|
|
181
|
+
| `lattice_delete_backup_destination` | Delete a destination ⚠️ |
|
|
182
|
+
| `lattice_test_backup_destination` | Test connectivity without writing a backup (requires a connected `worker_id`) |
|
|
139
183
|
|
|
140
184
|
### Registries
|
|
141
185
|
| Tool | Description |
|
|
142
186
|
|------|-------------|
|
|
143
|
-
| `lattice_list_registries` | Configured registries |
|
|
144
|
-
| `lattice_create_registry`
|
|
145
|
-
| `
|
|
146
|
-
| `
|
|
187
|
+
| `lattice_list_registries` | Configured container registries |
|
|
188
|
+
| `lattice_create_registry` | Add a registry |
|
|
189
|
+
| `lattice_update_registry` | Update a registry |
|
|
190
|
+
| `lattice_delete_registry` | Delete a registry ⚠️ |
|
|
191
|
+
| `lattice_test_registry` | Test a saved registry's stored credentials |
|
|
192
|
+
| `lattice_test_registry_inline` | Test registry credentials before saving |
|
|
147
193
|
| `lattice_list_registry_repositories` | What images exist |
|
|
148
194
|
| `lattice_list_registry_tags` | **What versions are deployable** |
|
|
149
195
|
|
|
@@ -153,53 +199,105 @@ MIT
|
|
|
153
199
|
| `lattice_search` | Search workers, stacks and containers in one call |
|
|
154
200
|
| `lattice_get_anomalies` | **Restart loops, unhealthy containers, offline workers — best first call** |
|
|
155
201
|
| `lattice_get_fleet_metrics` | Aggregated fleet CPU/memory/disk/network |
|
|
156
|
-
| `lattice_get_versions`
|
|
202
|
+
| `lattice_get_versions` | Runner versions and what's outdated |
|
|
203
|
+
| `lattice_refresh_versions` | Re-poll every worker for its current runner version |
|
|
157
204
|
| `lattice_get_container_metrics` | Per-container metrics over time |
|
|
158
205
|
| `lattice_get_self` | Which user the token authenticates as |
|
|
159
206
|
|
|
160
|
-
### Stacks —
|
|
207
|
+
### Stacks — lifecycle, compose & deploy tokens
|
|
161
208
|
| Tool | Description |
|
|
162
209
|
|------|-------------|
|
|
163
|
-
| `lattice_create_stack`
|
|
210
|
+
| `lattice_create_stack` | Create an empty stack |
|
|
211
|
+
| `lattice_delete_stack` | Delete a stack and all its containers ⚠️ |
|
|
164
212
|
| `lattice_get_stack_containers` | Containers in a stack |
|
|
165
|
-
| `lattice_update_stack_compose`
|
|
213
|
+
| `lattice_update_stack_compose` | Replace a stack's compose YAML |
|
|
214
|
+
| `lattice_sync_stack_compose` | Reconcile container records against stored compose YAML |
|
|
166
215
|
| `lattice_import_compose` | Create a stack from compose YAML |
|
|
167
|
-
| `lattice_export_stack`
|
|
216
|
+
| `lattice_export_stack` | Export a stack's full definition as portable JSON |
|
|
217
|
+
| `lattice_import_stack_export` | Recreate a stack from an export document |
|
|
168
218
|
| `lattice_save_stack_as_template` | Save a stack as a reusable template |
|
|
169
219
|
| `lattice_list_deploy_tokens` | CI deploy tokens — `last_used_at` shows whether CI reaches Lattice |
|
|
170
|
-
| `lattice_create_deploy_token`
|
|
220
|
+
| `lattice_create_deploy_token` | Create a CI deploy token |
|
|
221
|
+
| `lattice_delete_deploy_token` | Delete a CI deploy token ⚠️ |
|
|
171
222
|
| `lattice_approve_deployment` | Approve a deployment awaiting approval |
|
|
172
223
|
|
|
173
224
|
### Container definitions
|
|
174
225
|
| Tool | Description |
|
|
175
226
|
|------|-------------|
|
|
176
|
-
| `lattice_create_container`
|
|
177
|
-
| `
|
|
227
|
+
| `lattice_create_container` | Add a container definition to a stack |
|
|
228
|
+
| `lattice_update_container` | Update a container definition |
|
|
229
|
+
| `lattice_delete_container` | Delete definition and its running container ⚠️ |
|
|
178
230
|
|
|
179
|
-
### Workers —
|
|
231
|
+
### Workers — registration, tokens, volumes, networks
|
|
180
232
|
| Tool | Description |
|
|
181
233
|
|------|-------------|
|
|
182
|
-
| `lattice_create_worker`
|
|
183
|
-
| `
|
|
184
|
-
| `
|
|
185
|
-
| `
|
|
186
|
-
| `
|
|
187
|
-
| `
|
|
234
|
+
| `lattice_create_worker` | Register a worker |
|
|
235
|
+
| `lattice_update_worker` | Update a worker's name, hostname, IP, status, labels |
|
|
236
|
+
| `lattice_delete_worker` | Delete a worker ⚠️ |
|
|
237
|
+
| `lattice_get_worker_container_stats` | Live per-container stats from one worker |
|
|
238
|
+
| `lattice_list_worker_tokens` | Worker registration tokens |
|
|
239
|
+
| `lattice_create_worker_token` | Create a registration token for a worker |
|
|
240
|
+
| `lattice_delete_worker_token` | Delete a worker token ⚠️ |
|
|
241
|
+
| `lattice_list_worker_volumes` | Docker volumes on a worker |
|
|
242
|
+
| `lattice_create_worker_volume` | Create a Docker volume on a worker |
|
|
243
|
+
| `lattice_delete_worker_volume` | Delete a Docker volume ⚠️ |
|
|
244
|
+
| `lattice_list_worker_networks` | Docker networks on a worker |
|
|
245
|
+
| `lattice_create_worker_network` | Create a Docker network on a worker |
|
|
246
|
+
| `lattice_delete_worker_network` | Delete a Docker network ⚠️ |
|
|
247
|
+
| `lattice_list_all_networks` | Every tracked network across the fleet |
|
|
248
|
+
| `lattice_delete_network` | Delete a tracked network by Lattice ID ⚠️ |
|
|
188
249
|
| `lattice_force_remove_container` | Force-remove a wedged container ⚠️ |
|
|
189
250
|
|
|
190
251
|
### Env vars, templates & webhooks
|
|
191
252
|
| Tool | Description |
|
|
192
253
|
|------|-------------|
|
|
193
|
-
| `lattice_list_env_vars`
|
|
194
|
-
| `
|
|
195
|
-
| `
|
|
254
|
+
| `lattice_list_env_vars` | Global `${VAR}` interpolation values (secrets masked) |
|
|
255
|
+
| `lattice_create_env_var` | Create a global environment variable |
|
|
256
|
+
| `lattice_update_env_var` | Update a global environment variable |
|
|
257
|
+
| `lattice_delete_env_var` | Delete a global environment variable ⚠️ |
|
|
258
|
+
| `lattice_list_templates` | Saved stack templates |
|
|
259
|
+
| `lattice_create_template` | Create a stack template |
|
|
260
|
+
| `lattice_delete_template` | Delete a stack template ⚠️ |
|
|
261
|
+
| `lattice_list_webhooks` | Outbound event webhooks |
|
|
262
|
+
| `lattice_create_webhook` | Create an outbound webhook |
|
|
263
|
+
| `lattice_update_webhook` | Update a webhook |
|
|
264
|
+
| `lattice_delete_webhook` | Delete a webhook ⚠️ |
|
|
265
|
+
| `lattice_test_webhook` | Send a test payload to a webhook |
|
|
196
266
|
|
|
197
267
|
### Users & instance configuration
|
|
198
268
|
| Tool | Description |
|
|
199
269
|
|------|-------------|
|
|
200
|
-
| `lattice_list_users`
|
|
201
|
-
| `
|
|
202
|
-
| `
|
|
203
|
-
| `
|
|
270
|
+
| `lattice_list_users` | List Lattice users with roles and status |
|
|
271
|
+
| `lattice_create_user` | Create a local Lattice user |
|
|
272
|
+
| `lattice_update_user` | Update a user's name, role or active flag ⚠️ |
|
|
273
|
+
| `lattice_delete_user` | Delete a Lattice user ⚠️ |
|
|
274
|
+
| `lattice_get_sso_config` | Get the Forta SSO configuration |
|
|
275
|
+
| `lattice_update_sso_config` | Update SSO config ⚠️ (can lock out SSO users) |
|
|
276
|
+
| `lattice_get_smtp_config` | Get the SMTP configuration |
|
|
277
|
+
| `lattice_update_smtp_config` | Update the SMTP configuration |
|
|
278
|
+
| `lattice_test_smtp` | Send a test email with the saved SMTP config |
|
|
279
|
+
| `lattice_get_notification_prefs` | Per-event notification preferences |
|
|
280
|
+
| `lattice_update_notification_prefs` | Update notification preferences |
|
|
281
|
+
|
|
282
|
+
## Project structure
|
|
283
|
+
|
|
284
|
+
Everything lives in one file:
|
|
285
|
+
|
|
286
|
+
| Path | Role |
|
|
287
|
+
|------|------|
|
|
288
|
+
| `index.js` | The whole server: `--setup` flow, config read, `api()` HTTP helper, `text()`/`body()` helpers, all 125 `server.tool(...)` registrations, transport connect. |
|
|
289
|
+
| `package.json` | npm metadata; `bin.lattice-mcp` → `index.js`. |
|
|
290
|
+
| `AGENTS.md` | Contributor/agent guide — conventions, handler contracts, verification. |
|
|
291
|
+
| `README.md` | This file. |
|
|
292
|
+
|
|
293
|
+
## Deployment
|
|
204
294
|
|
|
205
|
-
|
|
295
|
+
Published to npm as `lattice-mcp` (public). Consumers run `npx -y lattice-mcp`, which resolves the latest published version — so **publishing is deployment**, and a running MCP server must be restarted to pick up a new version. `npm publish` requires 2FA via passkey from an interactive terminal.
|
|
296
|
+
|
|
297
|
+
## Contributing & further reading
|
|
298
|
+
|
|
299
|
+
Read [`AGENTS.md`](./AGENTS.md) before changing code — it documents the one-shape tool pattern, the `body()`/`api()` helpers, the "read the handler before adding a tool" rule, and the verification steps. Related repos: [`lattice-api`](https://github.com/aidenappl/lattice-api), [`lattice-web`](https://github.com/aidenappl/lattice-web), [`lattice-runner`](https://github.com/aidenappl/lattice-runner).
|
|
300
|
+
|
|
301
|
+
## License
|
|
302
|
+
|
|
303
|
+
MIT
|
package/index.js
CHANGED
|
@@ -77,12 +77,27 @@ async function api(method, path, params, body) {
|
|
|
77
77
|
opts.headers["Content-Type"] = "application/json";
|
|
78
78
|
opts.body = JSON.stringify(body);
|
|
79
79
|
}
|
|
80
|
+
let res;
|
|
80
81
|
try {
|
|
81
|
-
|
|
82
|
-
return await res.json();
|
|
82
|
+
res = await fetch(url.toString(), opts);
|
|
83
83
|
} catch (err) {
|
|
84
|
+
// Network-level failure (DNS, connection refused, timeout) — no response at all.
|
|
84
85
|
return { success: false, error: err.message, error_message: `API request failed: ${err.message}` };
|
|
85
86
|
}
|
|
87
|
+
// Response arrived. Read the body once as text, then try to parse it as JSON.
|
|
88
|
+
// On parse failure surface the HTTP status and a truncated text body rather than
|
|
89
|
+
// an opaque parse error — a 502/504 HTML page from the TLS proxy lands here.
|
|
90
|
+
// Never log bodies anywhere; responses can carry secrets.
|
|
91
|
+
const raw = await res.text();
|
|
92
|
+
try {
|
|
93
|
+
return JSON.parse(raw);
|
|
94
|
+
} catch {
|
|
95
|
+
return {
|
|
96
|
+
success: false,
|
|
97
|
+
error_code: res.status,
|
|
98
|
+
error_message: `API returned a non-JSON response (HTTP ${res.status})${raw ? `: ${raw.slice(0, 500)}` : ""}`,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
86
101
|
}
|
|
87
102
|
|
|
88
103
|
function text(data) {
|
|
@@ -99,7 +114,7 @@ function body(obj) {
|
|
|
99
114
|
|
|
100
115
|
const server = new McpServer({
|
|
101
116
|
name: "lattice",
|
|
102
|
-
version: "1.
|
|
117
|
+
version: "1.1.1",
|
|
103
118
|
});
|
|
104
119
|
|
|
105
120
|
// Overview
|
|
@@ -559,9 +574,9 @@ server.tool("lattice_delete_backup_destination", "Delete a backup destination. I
|
|
|
559
574
|
return { content: text(res) };
|
|
560
575
|
});
|
|
561
576
|
|
|
562
|
-
server.tool("lattice_test_backup_destination", "Test connectivity and credentials for a backup destination without writing a real backup", {
|
|
577
|
+
server.tool("lattice_test_backup_destination", "Test connectivity and credentials for a backup destination without writing a real backup. The test is dispatched over the worker's WebSocket, so worker_id is required and that worker must be connected", {
|
|
563
578
|
id: z.number().describe("Backup destination ID"),
|
|
564
|
-
worker_id: z.number().
|
|
579
|
+
worker_id: z.number().describe("Worker to run the test from — required; the test runs on this worker over its WebSocket, so it must be connected"),
|
|
565
580
|
}, async ({ id, worker_id }) => {
|
|
566
581
|
const res = await api("POST", `/admin/backup-destinations/${id}/test`, { worker_id });
|
|
567
582
|
return { content: text(res) };
|
|
@@ -682,7 +697,7 @@ server.tool("lattice_get_container_metrics", "Get a single container's CPU, memo
|
|
|
682
697
|
});
|
|
683
698
|
|
|
684
699
|
server.tool("lattice_get_self", "Get the user this API token authenticates as, including role", {}, async () => {
|
|
685
|
-
const res = await api("GET", "/
|
|
700
|
+
const res = await api("GET", "/auth/self");
|
|
686
701
|
return { content: text(res) };
|
|
687
702
|
});
|
|
688
703
|
|
|
@@ -974,7 +989,7 @@ server.tool("lattice_force_remove_container", "Force-remove a container on a wor
|
|
|
974
989
|
id: z.number().describe("Worker ID"),
|
|
975
990
|
name: z.string().describe("Container name to force-remove"),
|
|
976
991
|
}, async ({ id, name }) => {
|
|
977
|
-
const res = await api("POST", `/admin/workers/${id}/force-remove`, { name });
|
|
992
|
+
const res = await api("POST", `/admin/workers/${id}/force-remove`, null, { container_name: name });
|
|
978
993
|
return { content: text(res) };
|
|
979
994
|
});
|
|
980
995
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lattice-mcp",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "MCP server for Lattice container orchestration platform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"url": "git+https://github.com/aidenappl/lattice-mcp.git"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@modelcontextprotocol/sdk": "^1.29.0"
|
|
27
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
28
|
+
"zod": "^4.4.3"
|
|
28
29
|
}
|
|
29
30
|
}
|