impreza-mcp 0.23.0 → 0.25.0

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/README.md CHANGED
@@ -1,15 +1,36 @@
1
- # impreza-mcp
2
-
3
- [Model Context Protocol](https://modelcontextprotocol.io) server for
4
- [Impreza Host](https://imprezahost.com). Lets AI coding tools (Claude
5
- Code, Cursor, Codex CLI, Continue, Zed, ...) deploy customer-built
6
- apps to managed Impreza VPSes without leaving the chat.
7
-
8
- When you say "deploy this for me" to Claude with this MCP server
9
- loaded, Claude calls `impreza_deploy_custom` directly — packages your
10
- project, uploads it, builds + runs on your Impreza VPS, and reports
11
- back the URL.
12
-
1
+ # impreza-mcp
2
+
3
+ [Model Context Protocol](https://modelcontextprotocol.io) server for
4
+ [Impreza Host](https://imprezahost.com). Lets AI coding tools (Claude
5
+ Code, Cursor, Codex CLI, Continue, Zed, ...) deploy customer-built
6
+ apps to managed Impreza VPSes without leaving the chat.
7
+
8
+ When you say "deploy this for me" to Claude with this MCP server
9
+ loaded, Claude calls `impreza_deploy_custom` directly — packages your
10
+ project, uploads it, builds + runs on your Impreza VPS, and reports
11
+ back the URL.
12
+
13
+ ## Deployment progress and agent restarts
14
+
15
+ Read `last_operation.progress` from `impreza_list_deployments` for the last
16
+ reported step and timestamp. Agent 0.6.6+ saves final results before sending them;
17
+ after restart it resends the same receipt without repeating the deploy.
18
+ `recovery=required` means execution was interrupted without a saved result:
19
+ contact support to reconcile it before retrying. A long-running build can
20
+ continue after the agent exits. Progress is not a live percentage or proof of
21
+ current runtime health. Existing agents update explicitly before the next deploy.
22
+ See [deployment progress](https://docs.imprezahost.com/deployment-progress.html).
23
+
24
+ ## Cancel a deployment
25
+
26
+ Use `impreza_cancel_deployment` with the deployment ID and exact
27
+ `last_operation.command_id`. Requires manage permission. Queued cancellation
28
+ is immediate; running preparation needs agent 0.6.5+. A running pull/build
29
+ finishes its step before the agent confirms cancellation and restores
30
+ configuration. `requested` is not `cancelled`. Replacement/recovery cannot
31
+ be cancelled. Cancelling a tracking Task remains separate.
32
+ Read [the cancellation guide](https://docs.imprezahost.com/deployment-cancellation.html).
33
+
13
34
  ## Runtime health and deployment operations
14
35
 
15
36
  `impreza_list_deployments` returns `runtime` and `last_operation` separately.
@@ -19,486 +40,486 @@ Running without a confirmed healthcheck is not healthy. This requires agent
19
40
  0.6.4+ for observations and does not verify external HTTP/DNS/TLS. Existing
20
41
  servers update explicitly. See [runtime health](https://docs.imprezahost.com/runtime-health.html).
21
42
 
22
- ## Retained source uploads
23
-
24
- Use `impreza_upload_context` with `dir` and an optional `label` to upload an immutable
25
- source version without deploying. The response includes its `context_id`, SHA256,
26
- size and expiry. List or inspect versions with `impreza_list_contexts`.
27
-
28
- Create an app with `impreza_deploy_custom`, `mode: "dockerfile"` and `context_id`
29
- (or deploy a local `dir` directly). Rebuild it with `impreza_redeploy_deployment`
30
- and optionally another retained `context_id`. The app identity, domain, host port,
31
- volumes and build recipe stay fixed. The selected source can differ from the
32
- running release after failure or rollback; inspect deployment history.
33
-
34
- Sources in use remain available. Unreferenced versions expire seven days after
35
- upload or their last deployment request, not seven days after detachment. Default
36
- quotas are 10 unexpired/referenced archives, 300 MiB per account and 100 MiB per
37
- archive; referenced sources count. Delete an unused version with
38
- `impreza_delete_context`, `context_id` and `confirm: true` after customer confirmation.
39
- Metadata requires read scope, upload requires deploy, and deletion requires
40
- manage. Resource-confined credentials cannot manage account uploads.
41
-
42
- The packer excludes common dependency/VCS folders, .env and .env.* (except
43
- example/sample/template files), .npmrc and .pypirc. It does not scan arbitrary
44
- secrets or interpret .gitignore/.dockerignore; review what you upload. Portal
45
- archives are sent unchanged. Legacy REST uploads remain temporary unless they
46
- opt into `retain=true`. Older uploaded-source apps can migrate by selecting a
47
- fresh retained context on redeploy. These MCP tools require 0.22.0+; no agent
48
- update is needed solely for source retention. See the
49
- [source upload guide](https://docs.imprezahost.com/source-uploads.html).
50
-
51
- ## Node.js npm builds
52
-
53
- Deploy an independent npm HTTP application without a repository Dockerfile using
54
- `impreza_deploy_custom` with `mode: "dockerfile"`, `build_strategy: "node_npm"`,
55
- `git_url` (or local `dir`), and `target_port` (usually 3000).
56
- The API generates a Node 24 recipe: npm ci, optional build script, production
57
- pruning and npm start as a non-root user. The selected project folder must contain package.json, package-lock.json
58
- and a production start script. Docker Compose 2.17+ and BuildKit
59
- must be available on the server. Workspaces, private npm configuration and build
60
- secrets require a custom Dockerfile. The app must listen on 0.0.0.0 and the
61
- configured port. Keep runtime PORT consistent with that port.
62
-
63
- Git redeploys and previews reuse the recipe snapshot. Retained uploaded sources
64
- support reuse and source-version selection; older temporary uploads remain single-use. The recipe excludes .git, node_modules, .env,
65
- .env.* and .npmrc from the source copy; this does not scan arbitrary secrets.
66
- Keep credentials out of source code. The HTTP startup probe accepts responses
67
- below 500 at / and is not a functional application test.
68
-
69
- ## Public build variables
70
-
71
- Required healthy start: opt in with require_healthy_start=true, an explicit healthcheck_path and build_strategy=node_npm. In the portal, enable Require a healthy start. Agent 0.6.3 or newer must be reported in Servers; update it explicitly and wait for the next heartbeat. startup_timeout_seconds accepts an integer from 30 to 600, default 60. The budget starts after containers are created and includes the stable health observation; Git fetch, dependency/image builds and recovery have separate time limits. Every running service must report Docker healthy and at least one serving container must exist. HTTP redirects, authentication errors and timeouts do not pass the configured 2xx probe. When the first install fails, its containers are removed and persistent volumes are preserved; the failure includes diagnostic logs. A failed replacement recovers a verified healthy previous release when available. Recovery and manual rollback use the saved release startup policy, so a slow healthy release retains its original deadline. Failure recovery does not undo database writes or mutable data. The control plane refuses incompatible agents at creation, never dispatches the policy without startup-health-v1 support in the current poll, and accepts success only with a matching health confirmation. Previews inherit the policy; redeploy keeps the snapshot. Deployment reads expose startup_health. Choose a new deployment to change the saved policy. Omission or false preserves legacy behavior; a startup timeout requires the option enabled. The public option is for generated Node builds. This does not provide zero-downtime switching or continuous automatic rollback after startup. Local MCP input support requires 0.20.0+. Existing agents update only when the customer runs the updater. See https://docs.imprezahost.com/tutorials/agent-apps-panels.html#required-startup
72
-
73
- Node health checks: with build_strategy=node_npm, optionally set healthcheck_path (for example /health or /api/ready), or fill Health check path in the portal. The generated Docker health check sends HTTP GET to 127.0.0.1 on target_port inside the container and requires status 200-299; it does not follow redirects or send credentials. The route must work without login and should report the dependencies your app needs to serve requests. Use / or a path of at most 200 ASCII characters; segments start with a letter, digit, underscore or hyphen and may then include dots or tildes. A trailing slash is allowed. URLs, query strings, fragments, percent escapes, spaces, parent segments and repeated slashes are refused. Omit the field (leave it blank in the portal) to keep the legacy / probe accepting statuses below 500; explicitly setting / requires 2xx. Existing deployment snapshots remain unchanged. The saved healthcheck_path is returned by deployment reads, inherited by new previews and retained on redeploy; changing it requires a new deployment. Static sites keep their index.html probe; custom Dockerfiles define their own HEALTHCHECK. The probe runs every 5 seconds with a 2-second request timeout. With required startup disabled, agents 0.6.2 and later observe startup for up to 60 seconds: a failed replacement recovers a verified healthy previous release when one exists. Without that recovery target, a first install can still complete with a startup warning, so inspect health and logs before treating it as ready. This default policy does not provide continuous rollback, zero-downtime routing or external uptime checks. To enforce a startup deadline, enable required healthy startup with agent 0.6.3+. Local MCP inputs require 0.19.0+; healthcheck_path alone needs no agent update beyond 0.6.2.
74
-
75
- Public build settings: generated node_npm and node_npm_static recipes accept public_build_vars, an object of string values available only to npm run build (including its prebuild/postbuild scripts). For example, {"VITE_API_URL":"https://api.example.com"} lets Vite compile a public API URL into the site. Names must start with VITE_, NEXT_PUBLIC_ or PUBLIC_, contain only uppercase letters, digits and underscores, and be at most 128 characters. Limits: 20 entries, 4096 UTF-8 bytes per value and 16384 bytes for names plus values. Empty strings are preserved; NUL is refused. Values are literal data, without shell or variable expansion. The portal exposes Public build variables as KEY=value lines; do not add surrounding quotes, which would become part of the value. These values are public and may appear in bundles, image metadata and logs: never send passwords, tokens or secrets. They are not supplied to npm ci or automatically added to runtime variables. Runtime vars still configure the running container and do not rewrite compiled browser files. Settings are saved at creation, exposed on deployment reads, inherited by new previews and reused on redeploy. Preview runtime inheritance/overrides do not change this build snapshot; create a separate deployment for different public build values. Existing snapshots default to no public build values. Other build settings, private package configuration and secrets require a custom Dockerfile. Local MCP requires 0.18.0+; no agent update is required beyond the existing build executor.
76
-
77
- See the [build configuration guide](https://docs.imprezahost.com/tutorials/agent-apps-panels.html#public-build-settings).
78
-
79
- ## Apps in project subfolders
80
-
81
- Deploy an independent npm app from a subfolder: set project_dir (default .) with node_npm or node_npm_static, or choose Project folder in the portal. For example, apps/site must contain its own package.json and matching package-lock.json; static_output_dir is relative to that folder. Only the selected folder is copied into /app for npm installation and builds. The repository/upload remains the Docker build context, so its root .dockerignore still applies. Paths allow up to 120 characters and five non-hidden segments; parent, node_modules and symlink components are refused. Missing folders or failed builds retain the previous healthy runtime. The project_dir value is returned by deployment reads, saved at creation and inherited by new previews; redeploy reuses the saved recipe. Existing snapshots default to .; changing the folder requires a new deployment. This supports independent apps in one repository, not shared workspaces or dependencies outside the folder; use a custom Dockerfile for those. The analyzer does not discover subfolders: supply the selected app metadata and review Project folder yourself. Local MCP requires 0.17.0+; no agent upgrade is required beyond the existing build executor.
82
-
83
- See the [project folder guide](https://docs.imprezahost.com/tutorials/agent-apps-panels.html#project-folder).
84
-
85
- ## Import a Compose stack
86
-
87
- Use `impreza_prepare_compose` with `compose_yaml`, then explicitly select
88
- `web_service` and the integer `target_port`. Review services, persistent
89
- volumes, required variables, changes and blockers before deploying with
90
- `impreza_deploy_custom`, `mode: "compose"`, the same YAML/service/port and
91
- `compose_review_id` set to the returned `analysis_id`.
92
-
93
- Supports self-contained public-image stacks with up to 12 services, private
94
- bridge networks, local named volumes and service dependencies. Original host
95
- port bindings are removed; only the selected HTTP service joins the proxy and
96
- receives a managed loopback port. Container and volume names become specific
97
- to the deployment. Declare CPU/memory limits per service in YAML.
98
-
99
- The review does not fetch images, execute code or reserve resources. Builds,
100
- local files, env_file, aliases, profiles, host privileges and external resources
101
- are outside this import subset. Reference uppercase variables instead of
102
- embedding secrets. Runtime values must be single-line strings up to 4 KiB,
103
- without surrounding whitespace, quotes, backslashes, dollar signs or space
104
- followed by #. Variables supply explicit references, not every service's
105
- environment. Required values are checked at creation, editing and redeploy.
106
-
107
- The imported source is saved as a manifest. Redeploy reuses it and the named
108
- data; changing the source/topology requires a new deployment. Failure recovery
109
- uses the existing agent policy and does not undo database writes. Local MCP
110
- support requires 0.21.0+. No agent update is required for this import flow.
111
- See the [Compose import guide](https://docs.imprezahost.com/compose-import.html).
112
-
113
- ## Prepare project configuration
114
-
115
- Use `impreza_prepare_project` with `package_json`, `dockerfile`, and optional
116
- `dockerfile_path` before deploying. It returns framework hints, available build
117
- and start commands, explicit ports from the final Dockerfile stage, and findings
118
- to review. Each file is limited to 32 KiB. Review files for credentials before
119
- sending; never submit .env files or secrets.
120
-
121
- This is advisory analysis of supplied text. It does not fetch a repository,
122
- execute code, generate a Dockerfile or deploy resources. Git deploys use a Dockerfile by default; supported npm projects can opt into the Node recipe. The analysis ID identifies metadata, not an executable plan.
123
- Requires an API exposing /v1/platform/deployments/custom/prepare.
124
-
125
- ## Why this host and not a mainstream one
126
-
127
- Any provider can run your app. This one is built so an **agent can obtain and
128
- operate infrastructure that is not tied to your identity**, end to end, without
129
- you opening a browser:
130
-
131
- - **No KYC, and no email address, to open an account.** An account is a
132
- generated client ID plus a recovery token. No documents, no selfie, no phone
133
- number.
134
- - **Funded in cryptocurrency.** `impreza_topup` accepts BTC, XMR, USDT and TRX,
135
- and `impreza_order_vps` buys the server from that balance. The agent can go
136
- from "I need a server" to a running deployment without a card.
137
- - **Offshore and onshore jurisdictions side by side**, chosen per project
138
- rather than per account.
139
- - **Tor is a deployment target, not an add-on.** `impreza_add_onion` gives a
140
- deployment a `.onion` address in one call, so an agent can publish a hidden
141
- service the same way it publishes a normal site.
142
- - **No API key in your config.** The hosted connector authenticates over OAuth.
143
-
144
- If none of that matters for your project, a mainstream provider is a perfectly
145
- good choice and usually cheaper to start with. This exists for the projects
146
- where it does matter: research and journalism under pressure, censorship
147
- circumvention, security work, and anything that should not be one support
148
- ticket away from being linked to a legal name.
149
-
150
- ## Retained-release rollback
151
-
152
- The source tree adds `impreza_rollback_deployment`. Read a deployment's
153
- `release_history` through `impreza_api_call` at
154
- `/platform/deployments/{id}`, then choose a `rel_...` entry with
155
- `rollback_supported: true`.
156
-
157
- Explain the selected release and possible interruption to the customer before
158
- calling the tool with `deployment_id`, `target_version` and `confirm: true`.
159
- The hosted connector uses its two-call `confirm_token` flow instead.
160
- The operation requires `manage` scope and a compatible API and agent.
161
-
162
- A historical release may no longer be retained. The agent checks local images
163
- and unchanged ports, storage and routing before replacing containers. It saves
164
- the current healthy runtime and attempts recovery if the selected release fails
165
- startup. Database contents and mutable data are not reverted. A queued response
166
- does not confirm restoration; check deployment history for the result.
167
-
168
- Available in impreza-mcp 0.12.0. Requires a compatible API and agent.
169
-
170
- ## Static npm sites
171
-
172
- Static npm sites: choose build_strategy=node_npm_static with a Git/context source (mode=dockerfile), or Static site + npm in the portal. Requires an independent npm package in the selected project folder, matching package-lock.json and a build script producing index.html in the selected output folder. Node 24 installs dependencies and runs the build; unprivileged Nginx serves only the selected output folder with configurable SPA fallback. No start script is required. Default target_port is 8080. Compose 2.17+ and BuildKit required. No SSR, server functions, workspaces, private npm configuration or build secrets. Runtime variables (including VITE_* and PORT) do not rewrite static bundles or change the configured Nginx port. Use static_output_dir (default dist) to choose a relative output folder containing index.html, and static_spa (boolean, default true) to choose SPA fallback or 404 for unknown routes. The portal exposes both fields. Paths are limited to 120 characters and five segments, without hidden, parent or node_modules segments; symlinks in the output or its parent path are refused. These settings are chosen at creation, stored in the recipe snapshot, exposed as static_options and carried to new previews. Redeploy reuses the saved recipe; changing these settings on existing deployments requires creating a new deployment. Existing snapshots keep their original recipe. Local MCP option inputs require 0.16.0+. Use public_build_vars for supported public settings; other build-time configuration requires a custom Dockerfile. Source .env/.env.*/.npmrc/.git/node_modules are excluded; review all generated files because the output folder is public. Missing index.html and symlink output fail the build. Existing preview/redeploy snapshots preserve the strategy. Local MCP requires 0.15.0+; no agent upgrade is needed beyond the existing build executor. The analyzer returns static_npm_recipe and conditional deployment_options; metadata is not proof of a static, working build.
173
-
174
- ## Status
175
-
176
- **Package version: 0.18.0.** The tool catalog covers app deployment plus account +
177
- crypto balance, catalog + ordering, domains/DNS + registration, invoices, VPS
178
- lifecycle with snapshots and backups, dedicated / bare-metal servers, plan
179
- upgrades, and Titan / Google Workspace mailboxes — with a setup wizard that
180
- generates ready-to-paste config snippets for 5 AI tools.
181
-
182
- On top of that, everything an app needs after it is running: backup and
183
- restore into the customer's **own** S3 bucket, a timer on an app with its
184
- output kept, outbound webhooks so you stop polling, and reading the app's own
185
- files to find out why it behaves as if it were not configured.
186
-
187
- On top of that, everything an app needs after it is running: backup and
188
- restore into the customer's **own** S3 bucket, a timer on an app with its
189
- output kept, outbound webhooks so you stop polling, reading the app's own
190
- files, and running the app's own command line.
191
-
192
- The local (`npx`) server and the hosted OAuth connector expose the **same 116
193
- tools**, so nothing is lost by picking either path.
194
-
195
- ### New in 0.11.0
196
-
197
- **Run the app's own command line.** WP-CLI for WordPress, `occ` for
198
- Nextcloud, `gitea admin` for Gitea, and the database client for a dump —
199
- `impreza_app_cli` to run, `impreza_get_cli_run` to collect the output. Call
200
- `impreza_get_cli_run` with no `run_id` first: it names the command lines the
201
- app has, says what each is for, and gives one example that works.
202
-
203
- - **No docker socket, and that is measured rather than claimed.** The command
204
- runs in a separate container built from the app's own image, joined to the
205
- app's own network, with its data mounted — the shape the official CLI
206
- images are designed for. `cap_drop: ALL`, and no new privilege on the
207
- machine.
208
- - **Arguments are a list, never a string.** Each element becomes one `argv`
209
- entry through `execve`, so nothing is split, globbed or substituted:
210
- quoting is not your problem, and a `$` or a `;` inside a value is just
211
- that. Verified against a live site — `option update blogname
212
- 'dollars $HOME and a ; semicolon'` reads back exactly as sent.
213
- - **Destructive, and treated as such.** A command line can do anything the
214
- app itself can, so it needs the `manage` scope and is confirmation-gated.
215
- Arguments are free rather than allowlisted: that is the same ceiling
216
- `uninstall` with `purge_data` already sits at, and a list of `wp`
217
- subcommands would age badly while protecting nothing the confirmation gate
218
- does not.
219
- - **The CLI version follows the app.** Where the command line is the app's
220
- own image it is taken from that deployment, so a catalog bump carries it —
221
- running `occ` from an older Nextcloud against a newer database is how a
222
- maintenance command corrupts an install.
223
-
224
- Custom deployments have no command line here: it is your own image and the
225
- platform cannot know what it ships. Use a scheduled task of kind `command`
226
- for those.
227
-
228
- ### New in 0.10.0
229
-
230
- **Look inside the app's own files.** `impreza_get_logs` reads stdout, which
231
- cannot answer the question a deploy that came up wrong actually raises: did
232
- that variable reach the config file? Two tools now do —
233
- `impreza_inspect_app` to ask and `impreza_get_app_read` to collect the answer.
234
-
235
- - **Four actions, and no fifth:** `list` a directory, `read` a file (capped at
236
- 256 KB), `tail` its last lines, `grep` under a path with an extended regular
237
- expression. There is no command string in the interface, and therefore no
238
- shell.
239
- - **Read-only by construction.** A one-shot container mounts the app's storage
240
- read-only — the same mechanism the backup already uses — with no docker
241
- socket and no write capability. So it also works on an app that is `failed`
242
- and will not start, which is when it is wanted most.
243
- - **Only the app's own storage:** `data`, or one of the named volumes the app's
244
- manifest declares (a WordPress exposes `data` and `wp_db`, so its database
245
- files are readable too). Call `impreza_get_app_read` with no `read_id` to
246
- see the list for a given app.
247
- - **What comes back is untrusted and often secret** — an app's config file is
248
- where its database password lives. It reaches you and nothing else: the
249
- field is on our request log's deny list, and the record is deleted within a
250
- day.
251
-
252
- ### Since 0.6.1
253
-
254
- Three releases the npm page never described, each one a whole capability:
255
-
256
- - **0.7.0 — backup and restore** of a deployment's data into the account's own
257
- Impreza S3 bucket, with a per-chunk SHA-256 manifest that sits beside the
258
- data so the copy stays verifiable with the customer's own credentials and no
259
- call to us. Plus a schedule (daily by default, keeping 3), and a restore
260
- that can land in a *different* app, which is how an app moves between
261
- servers.
262
- - **0.8.0 — scheduled tasks:** a timer on an app with the output kept, for the
263
- apps that need one to behave correctly (Nextcloud's cron, WordPress's
264
- `wp-cron` on a site with no visitors).
265
- - **0.9.0 — outbound webhooks:** subscribe to deploy, backup and VPS events
266
- and stop polling, with HMAC-signed delivery and a delivery log.
267
-
268
- ### New in 0.6.1
269
-
270
- **`tools/list` now reflects what your account actually owns.** About a third of
271
- the tools only make sense if you have the machine behind them — VPS power
272
- controls with no VPS can only ever answer "not found" — so those are left out
273
- of the listing until you own one. Typical accounts see around 70 tools instead
274
- of 97, which is roughly six thousand fewer tokens of context spent before you
275
- ask anything.
276
-
277
- Three things worth knowing about how it behaves:
278
-
279
- - **The purchase path is never filtered.** An account that owns nothing is the
280
- one that needs to buy something, so ordering, top-up, invoices and the
281
- catalogue are always listed.
282
- - **Buying something grows the list mid-session.** The server sends
283
- `notifications/tools/list_changed` on the same response as the order, so a
284
- client that honours it picks up the new tools without reconnecting.
285
- - **It fails open.** If this server cannot reach the API to ask, it lists
286
- everything rather than guess.
287
-
288
- Hiding a tool is not an authorization boundary — the API still refuses anything
289
- your account does not own. This only stops the listing from carrying tools that
290
- could never work for you.
291
-
292
- ### New in 0.6.0
293
-
294
- Four things that only make sense on a host built for anonymity:
295
-
296
- - **Dark previews** — push a branch, get a preview on its own ephemeral Tor
297
- `.onion`. Every other platform's preview URL puts your branch name into
298
- public DNS and into a permanent Certificate Transparency log; branch names
299
- carry ticket ids, customer names and unshipped features. This one creates
300
- neither record, and destroys its keys when the branch is deleted or the TTL
301
- runs out. `impreza_configure_previews`, `impreza_list_previews`,
302
- `impreza_retire_preview`.
303
- - **Agent sub-credentials** — mint a narrower credential from the one you hold
304
- and hand it to a subtask: one deployment, one hour, no spending. A child can
305
- never exceed its parent on any axis, and revoking a credential revokes
306
- everything it minted, however deep. `impreza_mint_subcredential`,
307
- `impreza_list_credentials`, `impreza_revoke_credential`,
308
- `impreza_agent_activity`.
309
- - **A privacy report you can check** — `impreza_privacy_report` returns every
310
- field we store about your account, what it is for, how long it survives and
311
- who else sees it, and then measures our own retention against the oldest
312
- record that actually survived. Counts and date ranges, never contents.
313
- - **Ask before you guess** — search our docs, validate a deployment manifest
314
- before deploying it (including a privacy lint for third-party CDNs, public
315
- DNS resolvers and leaked secrets), or run a diagnosis when something is
316
- wrong. `impreza_search_docs`, `impreza_validate_manifest`, `impreza_doctor`.
317
-
318
- Plus the Tasks extension, so long operations report completion instead of
319
- leaving you to poll, and three MCP Apps panels — a payment card, a server card
320
- and a deploy wizard — that render inside clients which support them.
321
-
322
- The table below is a **selection**, not the full list — it covers the tools
323
- most people reach for first. Your client's own tool listing is authoritative,
324
- and `impreza_api_search` finds anything not named here.
325
-
326
- | Tool | Wraps |
327
- |------|-------|
328
- | **Apps & deployments** | |
329
- | `impreza_list_servers` | `GET /v1/platform/servers` |
330
- | `impreza_list_apps` | `GET /v1/platform/apps` |
331
- | `impreza_list_deployments` | `GET /v1/platform/deployments` + `/custom` (merged) |
332
- | `impreza_upload_context` | `POST /v1/platform/deployments/custom/contexts?retain=true` |
333
- | `impreza_list_contexts` | `GET /v1/platform/deployments/custom/contexts[/{context_id}]` |
334
- | `impreza_delete_context` | `DELETE /v1/platform/deployments/custom/contexts/{context_id}` |
335
- | `impreza_deploy_custom` | `POST /v1/platform/deployments/custom` (3 modes) |
336
- | `impreza_deploy_catalog_app` | `POST /v1/platform/deployments` |
337
- | `impreza_uninstall_deployment` | `POST .../uninstall` |
338
- | `impreza_get_logs` | `POST .../logs` (sync tail, last N lines) |
339
- | `impreza_restart_deployment` | `POST .../restart` |
340
- | `impreza_redeploy_deployment` | `POST .../custom/{id}/redeploy` (in-place rebuild, same domain) |
341
- | `impreza_add_onion` | `POST .../onion/add` |
342
- | `impreza_change_domain` | `POST .../domain` |
343
- | `impreza_git_webhook_status` | `GET .../custom/{id}/git-webhook` |
344
- | `impreza_git_webhook_connect` | `POST .../custom/{id}/git-webhook/connect` |
345
- | `impreza_git_webhook_disconnect` | `POST .../custom/{id}/git-webhook/disconnect` |
346
- | **Account & balance** | |
347
- | `impreza_account_info` | `GET /v1/account` |
348
- | `impreza_list_services` | `GET /v1/account/services` |
349
- | `impreza_topup` | `POST /v1/account/topup` — top up in BTC / XMR / USDT / TRX |
350
- | `impreza_topup_status` | `GET /v1/account/topup/{invoice_id}` |
351
- | `impreza_topup_payment` | `GET /v1/account/topup/{invoice_id}/payment` — crypto address + amount to pay |
352
- | **Catalog & ordering** | |
353
- | `impreza_list_products` | `GET /v1/products` — plans + pricing (filter `type=server` for VPS/dedicated) |
354
- | `impreza_order_vps` | `POST /v1/orders` — buy from balance; born deployable (`@agent`); 202 + poll `impreza_list_servers` |
355
- | **Domains & DNS** | |
356
- | `impreza_domain_check` | `GET /v1/domains/check` |
357
- | `impreza_domain_details` | `GET /v1/domains/{domain}` |
358
- | `impreza_list_dns` | `GET /v1/domains/{domain}/dns` |
359
- | `impreza_add_dns_record` | `POST /v1/domains/{domain}/dns` |
360
- | `impreza_update_dns_record` | `PUT /v1/domains/{domain}/dns` |
361
- | `impreza_delete_dns_record` | `DELETE /v1/domains/{domain}/dns` |
362
- | `impreza_set_nameservers` | `PUT /v1/domains/{domain}/nameservers` |
363
- | **VPS lifecycle** (Proxmox) | |
364
- | `impreza_vps_status` | `GET /v1/vps/proxmox/{id}/status` |
365
- | `impreza_vps_power` | `POST /v1/vps/proxmox/{id}/{start\|shutdown\|reboot\|stop}` |
366
- | `impreza_vps_list_backups` | `GET /v1/vps/proxmox/{id}/backups` |
367
- | `impreza_vps_create_backup` | `POST /v1/vps/proxmox/{id}/backups` |
368
- | `impreza_vps_list_templates` | `GET /v1/vps/proxmox/{id}/templates` |
369
- | `impreza_vps_reinstall` | `POST /v1/vps/proxmox/{id}/reinstall` — destructive (wipes) |
370
-
371
- ## Install + setup
372
-
373
- ### Prerequisites
374
-
375
- - Node ≥ 20
376
- - An Impreza Host account with an API key + secret
377
- (clientarea → API Keys; the IP of the machine running this MCP
378
- server must be whitelisted under the key)
379
-
380
- ### One-shot via `npx`
381
-
382
- No global install needed — `npx impreza-mcp` works.
383
-
384
- ### Or install globally
385
-
386
- ```sh
387
- npm install -g impreza-mcp
388
- ```
389
-
390
- ### Get a ready-to-paste config snippet
391
-
392
- The fastest path: ask the binary itself.
393
-
394
- ```sh
395
- npx impreza-mcp setup --tool claude-code
396
- # also: cursor | continue | zed | codex-cli
397
- ```
398
-
399
- The wizard prints the JSON block to drop into your AI tool's MCP
400
- config + the exact file path + the post-config step (usually "fully
401
- quit + re-open the AI tool"). It does NOT write to disk — paste it
402
- yourself so you don't accidentally clobber an existing config with
403
- other MCP servers.
404
-
405
- ### Or wire it in manually
406
-
407
- **Claude Code** — add to `~/Library/Application Support/Claude/claude_desktop_config.json`
408
- (macOS) or `%APPDATA%/Claude/claude_desktop_config.json` (Windows):
409
-
410
- ```json
411
- {
412
- "mcpServers": {
413
- "impreza": {
414
- "command": "npx",
415
- "args": ["-y", "impreza-mcp"],
416
- "env": {
417
- "IMPREZA_API_KEY": "imp_...",
418
- "IMPREZA_API_SECRET": "..."
419
- }
420
- }
421
- }
422
- }
423
- ```
424
-
425
- Restart Claude Code. The tools appear under the MCP icon.
426
-
427
- **Cursor** — add to `~/.cursor/mcp.json` (same shape as above).
428
-
429
- **Continue** — add to `~/.continue/config.json`:
430
-
431
- ```json
432
- {
433
- "experimental": {
434
- "modelContextProtocolServers": [
435
- {
436
- "transport": {
437
- "type": "stdio",
438
- "command": "npx",
439
- "args": ["-y", "impreza-mcp"],
440
- "env": {
441
- "IMPREZA_API_KEY": "imp_...",
442
- "IMPREZA_API_SECRET": "..."
443
- }
444
- }
445
- }
446
- ]
447
- }
448
- }
449
- ```
450
-
451
- **Zed** — add to your settings:
452
-
453
- ```json
454
- {
455
- "context_servers": {
456
- "impreza": {
457
- "command": {
458
- "path": "npx",
459
- "args": ["-y", "impreza-mcp"],
460
- "env": {
461
- "IMPREZA_API_KEY": "imp_...",
462
- "IMPREZA_API_SECRET": "..."
463
- }
464
- }
465
- }
466
- }
467
- }
468
- ```
469
-
470
- ## Usage in chat
471
-
472
- After setup, talk to your AI naturally:
473
-
474
- > *"List my Impreza servers."* → calls `impreza_list_servers`
475
- >
476
- > *"Deploy this directory to my Impreza VPS, expose via .onion."* →
477
- > packages the cwd as a Dockerfile-mode custom deploy, uploads, deploys
478
- > with `onion=true`, reports the .onion address.
479
- >
480
- > *"What apps are running on my agent?"* → calls
481
- > `impreza_list_deployments` filtered to the right server.
482
-
483
- ## Auth + security
484
-
485
- `IMPREZA_API_KEY` + `IMPREZA_API_SECRET` live in the AI tool's MCP
486
- config env — not in any file on disk owned by `impreza-mcp` itself.
487
- The MCP server holds the secret only in memory and only attaches it
488
- as HTTP request headers.
489
-
490
- The IP of the machine running this MCP server (almost always your
491
- laptop) must be on the API key's whitelist. Manage the whitelist in
492
- your Impreza clientarea.
493
-
494
- ## Build
495
-
496
- ```sh
497
- npm install
498
- npm run build
499
- # dist/server.js is the entry point
500
- ```
501
-
502
- ## License
503
-
504
- MIT — see `LICENSE`.
43
+ ## Retained source uploads
44
+
45
+ Use `impreza_upload_context` with `dir` and an optional `label` to upload an immutable
46
+ source version without deploying. The response includes its `context_id`, SHA256,
47
+ size and expiry. List or inspect versions with `impreza_list_contexts`.
48
+
49
+ Create an app with `impreza_deploy_custom`, `mode: "dockerfile"` and `context_id`
50
+ (or deploy a local `dir` directly). Rebuild it with `impreza_redeploy_deployment`
51
+ and optionally another retained `context_id`. The app identity, domain, host port,
52
+ volumes and build recipe stay fixed. The selected source can differ from the
53
+ running release after failure or rollback; inspect deployment history.
54
+
55
+ Sources in use remain available. Unreferenced versions expire seven days after
56
+ upload or their last deployment request, not seven days after detachment. Default
57
+ quotas are 10 unexpired/referenced archives, 300 MiB per account and 100 MiB per
58
+ archive; referenced sources count. Delete an unused version with
59
+ `impreza_delete_context`, `context_id` and `confirm: true` after customer confirmation.
60
+ Metadata requires read scope, upload requires deploy, and deletion requires
61
+ manage. Resource-confined credentials cannot manage account uploads.
62
+
63
+ The packer excludes common dependency/VCS folders, .env and .env.* (except
64
+ example/sample/template files), .npmrc and .pypirc. It does not scan arbitrary
65
+ secrets or interpret .gitignore/.dockerignore; review what you upload. Portal
66
+ archives are sent unchanged. Legacy REST uploads remain temporary unless they
67
+ opt into `retain=true`. Older uploaded-source apps can migrate by selecting a
68
+ fresh retained context on redeploy. These MCP tools require 0.22.0+; no agent
69
+ update is needed solely for source retention. See the
70
+ [source upload guide](https://docs.imprezahost.com/source-uploads.html).
71
+
72
+ ## Node.js npm builds
73
+
74
+ Deploy an independent npm HTTP application without a repository Dockerfile using
75
+ `impreza_deploy_custom` with `mode: "dockerfile"`, `build_strategy: "node_npm"`,
76
+ `git_url` (or local `dir`), and `target_port` (usually 3000).
77
+ The API generates a Node 24 recipe: npm ci, optional build script, production
78
+ pruning and npm start as a non-root user. The selected project folder must contain package.json, package-lock.json
79
+ and a production start script. Docker Compose 2.17+ and BuildKit
80
+ must be available on the server. Workspaces, private npm configuration and build
81
+ secrets require a custom Dockerfile. The app must listen on 0.0.0.0 and the
82
+ configured port. Keep runtime PORT consistent with that port.
83
+
84
+ Git redeploys and previews reuse the recipe snapshot. Retained uploaded sources
85
+ support reuse and source-version selection; older temporary uploads remain single-use. The recipe excludes .git, node_modules, .env,
86
+ .env.* and .npmrc from the source copy; this does not scan arbitrary secrets.
87
+ Keep credentials out of source code. The HTTP startup probe accepts responses
88
+ below 500 at / and is not a functional application test.
89
+
90
+ ## Public build variables
91
+
92
+ Required healthy start: opt in with require_healthy_start=true, an explicit healthcheck_path and build_strategy=node_npm. In the portal, enable Require a healthy start. Agent 0.6.3 or newer must be reported in Servers; update it explicitly and wait for the next heartbeat. startup_timeout_seconds accepts an integer from 30 to 600, default 60. The budget starts after containers are created and includes the stable health observation; Git fetch, dependency/image builds and recovery have separate time limits. Every running service must report Docker healthy and at least one serving container must exist. HTTP redirects, authentication errors and timeouts do not pass the configured 2xx probe. When the first install fails, its containers are removed and persistent volumes are preserved; the failure includes diagnostic logs. A failed replacement recovers a verified healthy previous release when available. Recovery and manual rollback use the saved release startup policy, so a slow healthy release retains its original deadline. Failure recovery does not undo database writes or mutable data. The control plane refuses incompatible agents at creation, never dispatches the policy without startup-health-v1 support in the current poll, and accepts success only with a matching health confirmation. Previews inherit the policy; redeploy keeps the snapshot. Deployment reads expose startup_health. Choose a new deployment to change the saved policy. Omission or false preserves legacy behavior; a startup timeout requires the option enabled. The public option is for generated Node builds. This does not provide zero-downtime switching or continuous automatic rollback after startup. Local MCP input support requires 0.20.0+. Existing agents update only when the customer runs the updater. See https://docs.imprezahost.com/tutorials/agent-apps-panels.html#required-startup
93
+
94
+ Node health checks: with build_strategy=node_npm, optionally set healthcheck_path (for example /health or /api/ready), or fill Health check path in the portal. The generated Docker health check sends HTTP GET to 127.0.0.1 on target_port inside the container and requires status 200-299; it does not follow redirects or send credentials. The route must work without login and should report the dependencies your app needs to serve requests. Use / or a path of at most 200 ASCII characters; segments start with a letter, digit, underscore or hyphen and may then include dots or tildes. A trailing slash is allowed. URLs, query strings, fragments, percent escapes, spaces, parent segments and repeated slashes are refused. Omit the field (leave it blank in the portal) to keep the legacy / probe accepting statuses below 500; explicitly setting / requires 2xx. Existing deployment snapshots remain unchanged. The saved healthcheck_path is returned by deployment reads, inherited by new previews and retained on redeploy; changing it requires a new deployment. Static sites keep their index.html probe; custom Dockerfiles define their own HEALTHCHECK. The probe runs every 5 seconds with a 2-second request timeout. With required startup disabled, agents 0.6.2 and later observe startup for up to 60 seconds: a failed replacement recovers a verified healthy previous release when one exists. Without that recovery target, a first install can still complete with a startup warning, so inspect health and logs before treating it as ready. This default policy does not provide continuous rollback, zero-downtime routing or external uptime checks. To enforce a startup deadline, enable required healthy startup with agent 0.6.3+. Local MCP inputs require 0.19.0+; healthcheck_path alone needs no agent update beyond 0.6.2.
95
+
96
+ Public build settings: generated node_npm and node_npm_static recipes accept public_build_vars, an object of string values available only to npm run build (including its prebuild/postbuild scripts). For example, {"VITE_API_URL":"https://api.example.com"} lets Vite compile a public API URL into the site. Names must start with VITE_, NEXT_PUBLIC_ or PUBLIC_, contain only uppercase letters, digits and underscores, and be at most 128 characters. Limits: 20 entries, 4096 UTF-8 bytes per value and 16384 bytes for names plus values. Empty strings are preserved; NUL is refused. Values are literal data, without shell or variable expansion. The portal exposes Public build variables as KEY=value lines; do not add surrounding quotes, which would become part of the value. These values are public and may appear in bundles, image metadata and logs: never send passwords, tokens or secrets. They are not supplied to npm ci or automatically added to runtime variables. Runtime vars still configure the running container and do not rewrite compiled browser files. Settings are saved at creation, exposed on deployment reads, inherited by new previews and reused on redeploy. Preview runtime inheritance/overrides do not change this build snapshot; create a separate deployment for different public build values. Existing snapshots default to no public build values. Other build settings, private package configuration and secrets require a custom Dockerfile. Local MCP requires 0.18.0+; no agent update is required beyond the existing build executor.
97
+
98
+ See the [build configuration guide](https://docs.imprezahost.com/tutorials/agent-apps-panels.html#public-build-settings).
99
+
100
+ ## Apps in project subfolders
101
+
102
+ Deploy an independent npm app from a subfolder: set project_dir (default .) with node_npm or node_npm_static, or choose Project folder in the portal. For example, apps/site must contain its own package.json and matching package-lock.json; static_output_dir is relative to that folder. Only the selected folder is copied into /app for npm installation and builds. The repository/upload remains the Docker build context, so its root .dockerignore still applies. Paths allow up to 120 characters and five non-hidden segments; parent, node_modules and symlink components are refused. Missing folders or failed builds retain the previous healthy runtime. The project_dir value is returned by deployment reads, saved at creation and inherited by new previews; redeploy reuses the saved recipe. Existing snapshots default to .; changing the folder requires a new deployment. This supports independent apps in one repository, not shared workspaces or dependencies outside the folder; use a custom Dockerfile for those. The analyzer does not discover subfolders: supply the selected app metadata and review Project folder yourself. Local MCP requires 0.17.0+; no agent upgrade is required beyond the existing build executor.
103
+
104
+ See the [project folder guide](https://docs.imprezahost.com/tutorials/agent-apps-panels.html#project-folder).
105
+
106
+ ## Import a Compose stack
107
+
108
+ Use `impreza_prepare_compose` with `compose_yaml`, then explicitly select
109
+ `web_service` and the integer `target_port`. Review services, persistent
110
+ volumes, required variables, changes and blockers before deploying with
111
+ `impreza_deploy_custom`, `mode: "compose"`, the same YAML/service/port and
112
+ `compose_review_id` set to the returned `analysis_id`.
113
+
114
+ Supports self-contained public-image stacks with up to 12 services, private
115
+ bridge networks, local named volumes and service dependencies. Original host
116
+ port bindings are removed; only the selected HTTP service joins the proxy and
117
+ receives a managed loopback port. Container and volume names become specific
118
+ to the deployment. Declare CPU/memory limits per service in YAML.
119
+
120
+ The review does not fetch images, execute code or reserve resources. Builds,
121
+ local files, env_file, aliases, profiles, host privileges and external resources
122
+ are outside this import subset. Reference uppercase variables instead of
123
+ embedding secrets. Runtime values must be single-line strings up to 4 KiB,
124
+ without surrounding whitespace, quotes, backslashes, dollar signs or space
125
+ followed by #. Variables supply explicit references, not every service's
126
+ environment. Required values are checked at creation, editing and redeploy.
127
+
128
+ The imported source is saved as a manifest. Redeploy reuses it and the named
129
+ data; changing the source/topology requires a new deployment. Failure recovery
130
+ uses the existing agent policy and does not undo database writes. Local MCP
131
+ support requires 0.21.0+. No agent update is required for this import flow.
132
+ See the [Compose import guide](https://docs.imprezahost.com/compose-import.html).
133
+
134
+ ## Prepare project configuration
135
+
136
+ Use `impreza_prepare_project` with `package_json`, `dockerfile`, and optional
137
+ `dockerfile_path` before deploying. It returns framework hints, available build
138
+ and start commands, explicit ports from the final Dockerfile stage, and findings
139
+ to review. Each file is limited to 32 KiB. Review files for credentials before
140
+ sending; never submit .env files or secrets.
141
+
142
+ This is advisory analysis of supplied text. It does not fetch a repository,
143
+ execute code, generate a Dockerfile or deploy resources. Git deploys use a Dockerfile by default; supported npm projects can opt into the Node recipe. The analysis ID identifies metadata, not an executable plan.
144
+ Requires an API exposing /v1/platform/deployments/custom/prepare.
145
+
146
+ ## Why this host and not a mainstream one
147
+
148
+ Any provider can run your app. This one is built so an **agent can obtain and
149
+ operate infrastructure that is not tied to your identity**, end to end, without
150
+ you opening a browser:
151
+
152
+ - **No KYC, and no email address, to open an account.** An account is a
153
+ generated client ID plus a recovery token. No documents, no selfie, no phone
154
+ number.
155
+ - **Funded in cryptocurrency.** `impreza_topup` accepts BTC, XMR, USDT and TRX,
156
+ and `impreza_order_vps` buys the server from that balance. The agent can go
157
+ from "I need a server" to a running deployment without a card.
158
+ - **Offshore and onshore jurisdictions side by side**, chosen per project
159
+ rather than per account.
160
+ - **Tor is a deployment target, not an add-on.** `impreza_add_onion` gives a
161
+ deployment a `.onion` address in one call, so an agent can publish a hidden
162
+ service the same way it publishes a normal site.
163
+ - **No API key in your config.** The hosted connector authenticates over OAuth.
164
+
165
+ If none of that matters for your project, a mainstream provider is a perfectly
166
+ good choice and usually cheaper to start with. This exists for the projects
167
+ where it does matter: research and journalism under pressure, censorship
168
+ circumvention, security work, and anything that should not be one support
169
+ ticket away from being linked to a legal name.
170
+
171
+ ## Retained-release rollback
172
+
173
+ The source tree adds `impreza_rollback_deployment`. Read a deployment's
174
+ `release_history` through `impreza_api_call` at
175
+ `/platform/deployments/{id}`, then choose a `rel_...` entry with
176
+ `rollback_supported: true`.
177
+
178
+ Explain the selected release and possible interruption to the customer before
179
+ calling the tool with `deployment_id`, `target_version` and `confirm: true`.
180
+ The hosted connector uses its two-call `confirm_token` flow instead.
181
+ The operation requires `manage` scope and a compatible API and agent.
182
+
183
+ A historical release may no longer be retained. The agent checks local images
184
+ and unchanged ports, storage and routing before replacing containers. It saves
185
+ the current healthy runtime and attempts recovery if the selected release fails
186
+ startup. Database contents and mutable data are not reverted. A queued response
187
+ does not confirm restoration; check deployment history for the result.
188
+
189
+ Available in impreza-mcp 0.12.0. Requires a compatible API and agent.
190
+
191
+ ## Static npm sites
192
+
193
+ Static npm sites: choose build_strategy=node_npm_static with a Git/context source (mode=dockerfile), or Static site + npm in the portal. Requires an independent npm package in the selected project folder, matching package-lock.json and a build script producing index.html in the selected output folder. Node 24 installs dependencies and runs the build; unprivileged Nginx serves only the selected output folder with configurable SPA fallback. No start script is required. Default target_port is 8080. Compose 2.17+ and BuildKit required. No SSR, server functions, workspaces, private npm configuration or build secrets. Runtime variables (including VITE_* and PORT) do not rewrite static bundles or change the configured Nginx port. Use static_output_dir (default dist) to choose a relative output folder containing index.html, and static_spa (boolean, default true) to choose SPA fallback or 404 for unknown routes. The portal exposes both fields. Paths are limited to 120 characters and five segments, without hidden, parent or node_modules segments; symlinks in the output or its parent path are refused. These settings are chosen at creation, stored in the recipe snapshot, exposed as static_options and carried to new previews. Redeploy reuses the saved recipe; changing these settings on existing deployments requires creating a new deployment. Existing snapshots keep their original recipe. Local MCP option inputs require 0.16.0+. Use public_build_vars for supported public settings; other build-time configuration requires a custom Dockerfile. Source .env/.env.*/.npmrc/.git/node_modules are excluded; review all generated files because the output folder is public. Missing index.html and symlink output fail the build. Existing preview/redeploy snapshots preserve the strategy. Local MCP requires 0.15.0+; no agent upgrade is needed beyond the existing build executor. The analyzer returns static_npm_recipe and conditional deployment_options; metadata is not proof of a static, working build.
194
+
195
+ ## Status
196
+
197
+ **Package version: 0.18.0.** The tool catalog covers app deployment plus account +
198
+ crypto balance, catalog + ordering, domains/DNS + registration, invoices, VPS
199
+ lifecycle with snapshots and backups, dedicated / bare-metal servers, plan
200
+ upgrades, and Titan / Google Workspace mailboxes — with a setup wizard that
201
+ generates ready-to-paste config snippets for 5 AI tools.
202
+
203
+ On top of that, everything an app needs after it is running: backup and
204
+ restore into the customer's **own** S3 bucket, a timer on an app with its
205
+ output kept, outbound webhooks so you stop polling, and reading the app's own
206
+ files to find out why it behaves as if it were not configured.
207
+
208
+ On top of that, everything an app needs after it is running: backup and
209
+ restore into the customer's **own** S3 bucket, a timer on an app with its
210
+ output kept, outbound webhooks so you stop polling, reading the app's own
211
+ files, and running the app's own command line.
212
+
213
+ The local (`npx`) server and the hosted OAuth connector expose the **same 116
214
+ tools**, so nothing is lost by picking either path.
215
+
216
+ ### New in 0.11.0
217
+
218
+ **Run the app's own command line.** WP-CLI for WordPress, `occ` for
219
+ Nextcloud, `gitea admin` for Gitea, and the database client for a dump —
220
+ `impreza_app_cli` to run, `impreza_get_cli_run` to collect the output. Call
221
+ `impreza_get_cli_run` with no `run_id` first: it names the command lines the
222
+ app has, says what each is for, and gives one example that works.
223
+
224
+ - **No docker socket, and that is measured rather than claimed.** The command
225
+ runs in a separate container built from the app's own image, joined to the
226
+ app's own network, with its data mounted — the shape the official CLI
227
+ images are designed for. `cap_drop: ALL`, and no new privilege on the
228
+ machine.
229
+ - **Arguments are a list, never a string.** Each element becomes one `argv`
230
+ entry through `execve`, so nothing is split, globbed or substituted:
231
+ quoting is not your problem, and a `$` or a `;` inside a value is just
232
+ that. Verified against a live site — `option update blogname
233
+ 'dollars $HOME and a ; semicolon'` reads back exactly as sent.
234
+ - **Destructive, and treated as such.** A command line can do anything the
235
+ app itself can, so it needs the `manage` scope and is confirmation-gated.
236
+ Arguments are free rather than allowlisted: that is the same ceiling
237
+ `uninstall` with `purge_data` already sits at, and a list of `wp`
238
+ subcommands would age badly while protecting nothing the confirmation gate
239
+ does not.
240
+ - **The CLI version follows the app.** Where the command line is the app's
241
+ own image it is taken from that deployment, so a catalog bump carries it —
242
+ running `occ` from an older Nextcloud against a newer database is how a
243
+ maintenance command corrupts an install.
244
+
245
+ Custom deployments have no command line here: it is your own image and the
246
+ platform cannot know what it ships. Use a scheduled task of kind `command`
247
+ for those.
248
+
249
+ ### New in 0.10.0
250
+
251
+ **Look inside the app's own files.** `impreza_get_logs` reads stdout, which
252
+ cannot answer the question a deploy that came up wrong actually raises: did
253
+ that variable reach the config file? Two tools now do —
254
+ `impreza_inspect_app` to ask and `impreza_get_app_read` to collect the answer.
255
+
256
+ - **Four actions, and no fifth:** `list` a directory, `read` a file (capped at
257
+ 256 KB), `tail` its last lines, `grep` under a path with an extended regular
258
+ expression. There is no command string in the interface, and therefore no
259
+ shell.
260
+ - **Read-only by construction.** A one-shot container mounts the app's storage
261
+ read-only — the same mechanism the backup already uses — with no docker
262
+ socket and no write capability. So it also works on an app that is `failed`
263
+ and will not start, which is when it is wanted most.
264
+ - **Only the app's own storage:** `data`, or one of the named volumes the app's
265
+ manifest declares (a WordPress exposes `data` and `wp_db`, so its database
266
+ files are readable too). Call `impreza_get_app_read` with no `read_id` to
267
+ see the list for a given app.
268
+ - **What comes back is untrusted and often secret** — an app's config file is
269
+ where its database password lives. It reaches you and nothing else: the
270
+ field is on our request log's deny list, and the record is deleted within a
271
+ day.
272
+
273
+ ### Since 0.6.1
274
+
275
+ Three releases the npm page never described, each one a whole capability:
276
+
277
+ - **0.7.0 — backup and restore** of a deployment's data into the account's own
278
+ Impreza S3 bucket, with a per-chunk SHA-256 manifest that sits beside the
279
+ data so the copy stays verifiable with the customer's own credentials and no
280
+ call to us. Plus a schedule (daily by default, keeping 3), and a restore
281
+ that can land in a *different* app, which is how an app moves between
282
+ servers.
283
+ - **0.8.0 — scheduled tasks:** a timer on an app with the output kept, for the
284
+ apps that need one to behave correctly (Nextcloud's cron, WordPress's
285
+ `wp-cron` on a site with no visitors).
286
+ - **0.9.0 — outbound webhooks:** subscribe to deploy, backup and VPS events
287
+ and stop polling, with HMAC-signed delivery and a delivery log.
288
+
289
+ ### New in 0.6.1
290
+
291
+ **`tools/list` now reflects what your account actually owns.** About a third of
292
+ the tools only make sense if you have the machine behind them — VPS power
293
+ controls with no VPS can only ever answer "not found" — so those are left out
294
+ of the listing until you own one. Typical accounts see around 70 tools instead
295
+ of 97, which is roughly six thousand fewer tokens of context spent before you
296
+ ask anything.
297
+
298
+ Three things worth knowing about how it behaves:
299
+
300
+ - **The purchase path is never filtered.** An account that owns nothing is the
301
+ one that needs to buy something, so ordering, top-up, invoices and the
302
+ catalogue are always listed.
303
+ - **Buying something grows the list mid-session.** The server sends
304
+ `notifications/tools/list_changed` on the same response as the order, so a
305
+ client that honours it picks up the new tools without reconnecting.
306
+ - **It fails open.** If this server cannot reach the API to ask, it lists
307
+ everything rather than guess.
308
+
309
+ Hiding a tool is not an authorization boundary — the API still refuses anything
310
+ your account does not own. This only stops the listing from carrying tools that
311
+ could never work for you.
312
+
313
+ ### New in 0.6.0
314
+
315
+ Four things that only make sense on a host built for anonymity:
316
+
317
+ - **Dark previews** — push a branch, get a preview on its own ephemeral Tor
318
+ `.onion`. Every other platform's preview URL puts your branch name into
319
+ public DNS and into a permanent Certificate Transparency log; branch names
320
+ carry ticket ids, customer names and unshipped features. This one creates
321
+ neither record, and destroys its keys when the branch is deleted or the TTL
322
+ runs out. `impreza_configure_previews`, `impreza_list_previews`,
323
+ `impreza_retire_preview`.
324
+ - **Agent sub-credentials** — mint a narrower credential from the one you hold
325
+ and hand it to a subtask: one deployment, one hour, no spending. A child can
326
+ never exceed its parent on any axis, and revoking a credential revokes
327
+ everything it minted, however deep. `impreza_mint_subcredential`,
328
+ `impreza_list_credentials`, `impreza_revoke_credential`,
329
+ `impreza_agent_activity`.
330
+ - **A privacy report you can check** — `impreza_privacy_report` returns every
331
+ field we store about your account, what it is for, how long it survives and
332
+ who else sees it, and then measures our own retention against the oldest
333
+ record that actually survived. Counts and date ranges, never contents.
334
+ - **Ask before you guess** — search our docs, validate a deployment manifest
335
+ before deploying it (including a privacy lint for third-party CDNs, public
336
+ DNS resolvers and leaked secrets), or run a diagnosis when something is
337
+ wrong. `impreza_search_docs`, `impreza_validate_manifest`, `impreza_doctor`.
338
+
339
+ Plus the Tasks extension, so long operations report completion instead of
340
+ leaving you to poll, and three MCP Apps panels — a payment card, a server card
341
+ and a deploy wizard — that render inside clients which support them.
342
+
343
+ The table below is a **selection**, not the full list — it covers the tools
344
+ most people reach for first. Your client's own tool listing is authoritative,
345
+ and `impreza_api_search` finds anything not named here.
346
+
347
+ | Tool | Wraps |
348
+ |------|-------|
349
+ | **Apps & deployments** | |
350
+ | `impreza_list_servers` | `GET /v1/platform/servers` |
351
+ | `impreza_list_apps` | `GET /v1/platform/apps` |
352
+ | `impreza_list_deployments` | `GET /v1/platform/deployments` + `/custom` (merged) |
353
+ | `impreza_upload_context` | `POST /v1/platform/deployments/custom/contexts?retain=true` |
354
+ | `impreza_list_contexts` | `GET /v1/platform/deployments/custom/contexts[/{context_id}]` |
355
+ | `impreza_delete_context` | `DELETE /v1/platform/deployments/custom/contexts/{context_id}` |
356
+ | `impreza_deploy_custom` | `POST /v1/platform/deployments/custom` (3 modes) |
357
+ | `impreza_deploy_catalog_app` | `POST /v1/platform/deployments` |
358
+ | `impreza_uninstall_deployment` | `POST .../uninstall` |
359
+ | `impreza_get_logs` | `POST .../logs` (sync tail, last N lines) |
360
+ | `impreza_restart_deployment` | `POST .../restart` |
361
+ | `impreza_redeploy_deployment` | `POST .../custom/{id}/redeploy` (in-place rebuild, same domain) |
362
+ | `impreza_add_onion` | `POST .../onion/add` |
363
+ | `impreza_change_domain` | `POST .../domain` |
364
+ | `impreza_git_webhook_status` | `GET .../custom/{id}/git-webhook` |
365
+ | `impreza_git_webhook_connect` | `POST .../custom/{id}/git-webhook/connect` |
366
+ | `impreza_git_webhook_disconnect` | `POST .../custom/{id}/git-webhook/disconnect` |
367
+ | **Account & balance** | |
368
+ | `impreza_account_info` | `GET /v1/account` |
369
+ | `impreza_list_services` | `GET /v1/account/services` |
370
+ | `impreza_topup` | `POST /v1/account/topup` — top up in BTC / XMR / USDT / TRX |
371
+ | `impreza_topup_status` | `GET /v1/account/topup/{invoice_id}` |
372
+ | `impreza_topup_payment` | `GET /v1/account/topup/{invoice_id}/payment` — crypto address + amount to pay |
373
+ | **Catalog & ordering** | |
374
+ | `impreza_list_products` | `GET /v1/products` — plans + pricing (filter `type=server` for VPS/dedicated) |
375
+ | `impreza_order_vps` | `POST /v1/orders` — buy from balance; born deployable (`@agent`); 202 + poll `impreza_list_servers` |
376
+ | **Domains & DNS** | |
377
+ | `impreza_domain_check` | `GET /v1/domains/check` |
378
+ | `impreza_domain_details` | `GET /v1/domains/{domain}` |
379
+ | `impreza_list_dns` | `GET /v1/domains/{domain}/dns` |
380
+ | `impreza_add_dns_record` | `POST /v1/domains/{domain}/dns` |
381
+ | `impreza_update_dns_record` | `PUT /v1/domains/{domain}/dns` |
382
+ | `impreza_delete_dns_record` | `DELETE /v1/domains/{domain}/dns` |
383
+ | `impreza_set_nameservers` | `PUT /v1/domains/{domain}/nameservers` |
384
+ | **VPS lifecycle** (Proxmox) | |
385
+ | `impreza_vps_status` | `GET /v1/vps/proxmox/{id}/status` |
386
+ | `impreza_vps_power` | `POST /v1/vps/proxmox/{id}/{start\|shutdown\|reboot\|stop}` |
387
+ | `impreza_vps_list_backups` | `GET /v1/vps/proxmox/{id}/backups` |
388
+ | `impreza_vps_create_backup` | `POST /v1/vps/proxmox/{id}/backups` |
389
+ | `impreza_vps_list_templates` | `GET /v1/vps/proxmox/{id}/templates` |
390
+ | `impreza_vps_reinstall` | `POST /v1/vps/proxmox/{id}/reinstall` — destructive (wipes) |
391
+
392
+ ## Install + setup
393
+
394
+ ### Prerequisites
395
+
396
+ - Node ≥ 20
397
+ - An Impreza Host account with an API key + secret
398
+ (clientarea → API Keys; the IP of the machine running this MCP
399
+ server must be whitelisted under the key)
400
+
401
+ ### One-shot via `npx`
402
+
403
+ No global install needed — `npx impreza-mcp` works.
404
+
405
+ ### Or install globally
406
+
407
+ ```sh
408
+ npm install -g impreza-mcp
409
+ ```
410
+
411
+ ### Get a ready-to-paste config snippet
412
+
413
+ The fastest path: ask the binary itself.
414
+
415
+ ```sh
416
+ npx impreza-mcp setup --tool claude-code
417
+ # also: cursor | continue | zed | codex-cli
418
+ ```
419
+
420
+ The wizard prints the JSON block to drop into your AI tool's MCP
421
+ config + the exact file path + the post-config step (usually "fully
422
+ quit + re-open the AI tool"). It does NOT write to disk — paste it
423
+ yourself so you don't accidentally clobber an existing config with
424
+ other MCP servers.
425
+
426
+ ### Or wire it in manually
427
+
428
+ **Claude Code** — add to `~/Library/Application Support/Claude/claude_desktop_config.json`
429
+ (macOS) or `%APPDATA%/Claude/claude_desktop_config.json` (Windows):
430
+
431
+ ```json
432
+ {
433
+ "mcpServers": {
434
+ "impreza": {
435
+ "command": "npx",
436
+ "args": ["-y", "impreza-mcp"],
437
+ "env": {
438
+ "IMPREZA_API_KEY": "imp_...",
439
+ "IMPREZA_API_SECRET": "..."
440
+ }
441
+ }
442
+ }
443
+ }
444
+ ```
445
+
446
+ Restart Claude Code. The tools appear under the MCP icon.
447
+
448
+ **Cursor** — add to `~/.cursor/mcp.json` (same shape as above).
449
+
450
+ **Continue** — add to `~/.continue/config.json`:
451
+
452
+ ```json
453
+ {
454
+ "experimental": {
455
+ "modelContextProtocolServers": [
456
+ {
457
+ "transport": {
458
+ "type": "stdio",
459
+ "command": "npx",
460
+ "args": ["-y", "impreza-mcp"],
461
+ "env": {
462
+ "IMPREZA_API_KEY": "imp_...",
463
+ "IMPREZA_API_SECRET": "..."
464
+ }
465
+ }
466
+ }
467
+ ]
468
+ }
469
+ }
470
+ ```
471
+
472
+ **Zed** — add to your settings:
473
+
474
+ ```json
475
+ {
476
+ "context_servers": {
477
+ "impreza": {
478
+ "command": {
479
+ "path": "npx",
480
+ "args": ["-y", "impreza-mcp"],
481
+ "env": {
482
+ "IMPREZA_API_KEY": "imp_...",
483
+ "IMPREZA_API_SECRET": "..."
484
+ }
485
+ }
486
+ }
487
+ }
488
+ }
489
+ ```
490
+
491
+ ## Usage in chat
492
+
493
+ After setup, talk to your AI naturally:
494
+
495
+ > *"List my Impreza servers."* → calls `impreza_list_servers`
496
+ >
497
+ > *"Deploy this directory to my Impreza VPS, expose via .onion."* →
498
+ > packages the cwd as a Dockerfile-mode custom deploy, uploads, deploys
499
+ > with `onion=true`, reports the .onion address.
500
+ >
501
+ > *"What apps are running on my agent?"* → calls
502
+ > `impreza_list_deployments` filtered to the right server.
503
+
504
+ ## Auth + security
505
+
506
+ `IMPREZA_API_KEY` + `IMPREZA_API_SECRET` live in the AI tool's MCP
507
+ config env — not in any file on disk owned by `impreza-mcp` itself.
508
+ The MCP server holds the secret only in memory and only attaches it
509
+ as HTTP request headers.
510
+
511
+ The IP of the machine running this MCP server (almost always your
512
+ laptop) must be on the API key's whitelist. Manage the whitelist in
513
+ your Impreza clientarea.
514
+
515
+ ## Build
516
+
517
+ ```sh
518
+ npm install
519
+ npm run build
520
+ # dist/server.js is the entry point
521
+ ```
522
+
523
+ ## License
524
+
525
+ MIT — see `LICENSE`.