impreza-mcp 0.44.0 → 0.46.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
@@ -268,24 +268,23 @@ Static npm sites: choose build_strategy=node_npm_static with a Git/context sourc
268
268
 
269
269
  ## Status
270
270
 
271
- **Package version: 0.38.0.** The tool catalog covers app deployment plus account +
271
+ **Package version: 0.46.0.** The tool catalog covers app deployment plus account +
272
272
  crypto balance, catalog + ordering, domains/DNS + registration, invoices, VPS
273
273
  lifecycle with snapshots and backups, dedicated / bare-metal servers, plan
274
274
  upgrades, and Titan / Google Workspace mailboxes — with a setup wizard that
275
275
  generates ready-to-paste config snippets for 5 AI tools.
276
276
 
277
- On top of that, everything an app needs after it is running: backup and
278
- restore into the customer's **own** S3 bucket, a timer on an app with its
279
- output kept, outbound webhooks so you stop polling, and reading the app's own
280
- files to find out why it behaves as if it were not configured.
281
-
282
277
  On top of that, everything an app needs after it is running: backup and
283
278
  restore into the customer's **own** S3 bucket, a timer on an app with its
284
279
  output kept, outbound webhooks so you stop polling, reading the app's own
285
280
  files, and running the app's own command line.
286
281
 
287
- The local (`npx`) server and the hosted OAuth connector expose the **same 116
288
- tools**, so nothing is lost by picking either path.
282
+ The local (`npx`) server and the hosted OAuth connector expose the **same tool
283
+ catalog — 184 tools on both sides**. Two declared, one-direction gaps remain:
284
+ `impreza_get_log_request` stays hosted-only (only the control plane resolves a
285
+ bare `request_id`; locally, call `impreza_tail_logs` again on the application —
286
+ requests dedupe), and `impreza_upload_context` stays local-only (binary tarball
287
+ streaming does not fit the hosted transport).
289
288
 
290
289
  ### New in 0.11.0
291
290
 
@@ -731,6 +730,51 @@ See the [Tor runtime guide](https://docs.imprezahost.com/onion-services.html#run
731
730
  for availability and verification. This option is separate from using Tor to
732
731
  connect the MCP client itself and from publishing an inbound onion address.
733
732
 
733
+ ## Local and hosted parity (0.46.0)
734
+
735
+ The local package now carries the 16 tools that only the hosted connector had:
736
+
737
+ - projects and environments: `impreza_rename_project`, `impreza_delete_project`,
738
+ `impreza_rename_environment` and `impreza_delete_environment`;
739
+ - variable groups: `impreza_get_variable_group` and `impreza_set_variable_group`;
740
+ - configuration promotion: `impreza_prepare_config_promotion`,
741
+ `impreza_get_config_promotion` and `impreza_apply_config_promotion`;
742
+ - ordered environment deploys: `impreza_deploy_environment`,
743
+ `impreza_get_environment_deploy` and `impreza_list_environment_deploys`;
744
+ - agent updates: `impreza_get_update_policy`, `impreza_set_update_policy` and
745
+ `impreza_request_agent_update`;
746
+ - Shield: `impreza_set_shield`.
747
+
748
+ Tool annotations (read-only, destructive, idempotent) now match the hosted
749
+ connector. A destructive tool called with `confirm` missing or false is refused
750
+ before any request is sent.
751
+
752
+ ## Point-in-time PostgreSQL recovery (0.45.0)
753
+
754
+ Six tools cover status, configuration, a recovery drill, and prepare/get/apply
755
+ of a reviewed UTC recovery point: `impreza_get_pitr`, `impreza_configure_pitr`,
756
+ `impreza_drill_pitr`, `impreza_prepare_pitr_restore`,
757
+ `impreza_get_pitr_restore`, and `impreza_apply_pitr_restore`. Status uses read
758
+ scope; changes use deploy scope. The hosted connector requires a credential
759
+ without resource confinement because physical PostgreSQL recovery can cover
760
+ several bindings on a provider.
761
+
762
+ WAL and base backups consume the account's storage. After six consecutive
763
+ failures, automatic work pauses until the cause is repaired and configuration
764
+ is saved again. Disabling stops protection but retains stored objects. A
765
+ restore requires the review digest and `confirm: true`, creates a new database,
766
+ and never redirects the live application. Poll the review until its receipt
767
+ says `verified` or `failed`; acceptance alone is not a successful recovery.
768
+
769
+ ## Scheduled tasks (0.45.0)
770
+
771
+ `impreza_create_task` creates a scheduled task on an app and `impreza_update_task`
772
+ changes one that exists (any field you leave out keeps its current value, so
773
+ `enabled=false` pauses a task without losing its schedule or history), as on the
774
+ hosted connector. They replace `impreza_schedule_task`, which is gone: update
775
+ any client or prompt that still calls it. `impreza_list_tasks`,
776
+ `impreza_run_task` and `impreza_delete_task` are unchanged.
777
+
734
778
  ## VPS resize (0.44.0)
735
779
 
736
780
  `impreza_vps_resize` gives a configurable VPS more vCPUs, memory or disk. Price it
@@ -772,3 +816,4 @@ uninstalled application does not delete key material.
772
816
 
773
817
  See the [onion guide](https://docs.imprezahost.com/onion-services.html)
774
818
  for permissions, customer update steps and supported limitations.
819
+
@@ -0,0 +1,83 @@
1
+ import type { ImprezaClient } from './client.js';
2
+ export declare const PITR_TOOLS: {
3
+ name: "impreza_get_pitr" | "impreza_configure_pitr" | "impreza_drill_pitr" | "impreza_prepare_pitr_restore" | "impreza_get_pitr_restore" | "impreza_apply_pitr_restore";
4
+ title: "Read point-in-time recovery" | "Configure point-in-time recovery" | "Test point-in-time recovery" | "Review point-in-time restore" | "Read point-in-time restore review" | "Apply point-in-time restore";
5
+ description: string;
6
+ inputSchema: {
7
+ type: "object";
8
+ properties: {
9
+ readonly deployment_id: {
10
+ type: string;
11
+ pattern: string;
12
+ description: string;
13
+ };
14
+ } | {
15
+ readonly deployment_id: {
16
+ type: string;
17
+ pattern: string;
18
+ description: string;
19
+ };
20
+ readonly enabled: {
21
+ readonly type: "boolean";
22
+ };
23
+ readonly drain_minutes: {
24
+ readonly type: "integer";
25
+ readonly minimum: 5;
26
+ readonly maximum: 60;
27
+ };
28
+ readonly keep_bases: {
29
+ readonly type: "integer";
30
+ readonly minimum: 1;
31
+ readonly maximum: 7;
32
+ };
33
+ } | {
34
+ readonly deployment_id: {
35
+ type: string;
36
+ pattern: string;
37
+ description: string;
38
+ };
39
+ } | {
40
+ readonly deployment_id: {
41
+ type: string;
42
+ pattern: string;
43
+ description: string;
44
+ };
45
+ readonly target_time: {
46
+ readonly type: "string";
47
+ readonly pattern: "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$";
48
+ };
49
+ readonly target_binding_id: {
50
+ readonly type: "string";
51
+ readonly pattern: "^bnd_[a-f0-9]{24}$";
52
+ };
53
+ } | {
54
+ readonly pitr_plan_id: {
55
+ type: string;
56
+ pattern: string;
57
+ };
58
+ } | {
59
+ readonly pitr_plan_id: {
60
+ type: string;
61
+ pattern: string;
62
+ };
63
+ readonly review_digest: {
64
+ readonly type: "string";
65
+ readonly pattern: "^[a-f0-9]{64}$";
66
+ };
67
+ readonly confirm: {
68
+ readonly type: "boolean";
69
+ readonly const: true;
70
+ };
71
+ };
72
+ required: ("deployment_id" | "review_digest" | "confirm" | "enabled" | "target_time" | "pitr_plan_id")[];
73
+ additionalProperties: boolean;
74
+ };
75
+ annotations: {
76
+ idempotentHint?: boolean;
77
+ readOnlyHint: boolean;
78
+ destructiveHint: boolean;
79
+ openWorldHint: boolean;
80
+ };
81
+ }[];
82
+ export declare function isPitrTool(name: string): boolean;
83
+ export declare function callPitrTool(client: ImprezaClient, name: string, args: Record<string, unknown>): Promise<unknown>;
@@ -0,0 +1,45 @@
1
+ import { z } from 'zod';
2
+ const deployment = z.string().regex(/^dpl_(?:[a-f0-9]{16}|[a-f0-9]{24})$(?![\s\S])/);
3
+ const plan = z.string().regex(/^ppl_[a-f0-9]{24}$(?![\s\S])/);
4
+ const utc = z.string().regex(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$(?![\s\S])/)
5
+ .refine(v => { const n = Date.parse(v); return Number.isFinite(n) && new Date(n).toISOString() === v.replace('Z', '.000Z'); }, 'Use a valid UTC instant');
6
+ const schemas = {
7
+ impreza_get_pitr: z.object({ deployment_id: deployment }).strict(),
8
+ impreza_configure_pitr: z.object({ deployment_id: deployment, enabled: z.boolean(), drain_minutes: z.number().int().min(5).max(60).optional(), keep_bases: z.number().int().min(1).max(7).optional() }).strict(),
9
+ impreza_drill_pitr: z.object({ deployment_id: deployment }).strict(),
10
+ impreza_prepare_pitr_restore: z.object({ deployment_id: deployment, target_time: utc, target_binding_id: z.string().regex(/^bnd_[a-f0-9]{24}$(?![\s\S])/).optional() }).strict(),
11
+ impreza_get_pitr_restore: z.object({ pitr_plan_id: plan }).strict(),
12
+ impreza_apply_pitr_restore: z.object({ pitr_plan_id: plan, review_digest: z.string().regex(/^[a-f0-9]{64}$(?![\s\S])/), confirm: z.literal(true) }).strict(),
13
+ };
14
+ const depProperty = { type: 'string', pattern: '^dpl_(?:[a-f0-9]{16}|[a-f0-9]{24})$', description: 'The managed PostgreSQL provider deployment, not the consuming app.' };
15
+ const planProperty = { type: 'string', pattern: '^ppl_[a-f0-9]{24}$' };
16
+ const specs = [
17
+ ['impreza_get_pitr', 'Read point-in-time recovery', 'Read PostgreSQL PITR status, stored bases, recoverable boundary and latest drill. Read scope. No changes. A configured interval is not a guarantee of zero data loss.', { deployment_id: depProperty }, ['deployment_id'], true, false],
18
+ ['impreza_configure_pitr', 'Configure point-in-time recovery', 'Enable or disable PostgreSQL PITR on a managed provider. Deploy scope. Enabling creates a replication slot and stores base backups/WAL in the account bucket; storage usage increases. Disabling stops protection and drops the slot but retains stored objects. A stopped shipper can retain WAL on the server. No restore or traffic cutover.', { deployment_id: depProperty, enabled: { type: 'boolean' }, drain_minutes: { type: 'integer', minimum: 5, maximum: 60 }, keep_bases: { type: 'integer', minimum: 1, maximum: 7 } }, ['deployment_id', 'enabled'], false, true],
19
+ ['impreza_drill_pitr', 'Test point-in-time recovery', 'Queue a PostgreSQL physical recovery drill using the latest shipped WAL. Deploy scope. Creates temporary recovery resources; does not replace the live database or switch traffic. Read status until the drill is verified. A cluster drill is not validation of every application record.', { deployment_id: depProperty }, ['deployment_id'], false, false],
20
+ ['impreza_prepare_pitr_restore', 'Review point-in-time restore', 'Prepare a 15-minute review for a UTC point-in-time restore into a NEW database, using the current storage generation. Deploy scope. Does not queue recovery or switch traffic. Review the source, target, available WAL range and digest before applying. Optional target_binding_id selects an eligible binding.', { deployment_id: depProperty, target_time: { type: 'string', pattern: '^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$' }, target_binding_id: { type: 'string', pattern: '^bnd_[a-f0-9]{24}$' } }, ['deployment_id', 'target_time'], false, false],
21
+ ['impreza_get_pitr_restore', 'Read point-in-time restore review', 'Read a PITR restore review and its saved receipt. Read scope. Accepted means queued, not recovered or verified. Follow receipt.phase to verified or failed before using the new database.', { pitr_plan_id: planProperty }, ['pitr_plan_id'], true, false],
22
+ ['impreza_apply_pitr_restore', 'Apply point-in-time restore', 'Apply the exact reviewed PITR restore with user confirmation, confirm=true and the review_digest. Deploy scope. Queues recovery into a NEW database, preserving the serving database and traffic. Repeating the accepted plan returns its receipt; acceptance is not verified completion.', { pitr_plan_id: planProperty, review_digest: { type: 'string', pattern: '^[a-f0-9]{64}$' }, confirm: { type: 'boolean', const: true } }, ['pitr_plan_id', 'review_digest', 'confirm'], false, false],
23
+ ];
24
+ export const PITR_TOOLS = specs.map(([name, title, description, properties, required, readOnlyHint, destructiveHint]) => ({
25
+ name, title, description: description + ' Hosted MCP requires an account credential without resource confinement.', inputSchema: { type: 'object', properties, required: [...required], additionalProperties: false },
26
+ annotations: { readOnlyHint, destructiveHint, openWorldHint: true, ...(readOnlyHint ? {} : { idempotentHint: name === 'impreza_apply_pitr_restore' }) },
27
+ }));
28
+ const routes = {
29
+ impreza_get_pitr: ['GET', '/v1/platform/deployments/{deployment_id}/pitr'],
30
+ impreza_configure_pitr: ['POST', '/v1/platform/deployments/{deployment_id}/pitr'],
31
+ impreza_drill_pitr: ['POST', '/v1/platform/deployments/{deployment_id}/pitr/drill'],
32
+ impreza_prepare_pitr_restore: ['POST', '/v1/platform/deployments/{deployment_id}/prepare-pitr-restore'],
33
+ impreza_get_pitr_restore: ['GET', '/v1/pitr-restores/{pitr_plan_id}'],
34
+ impreza_apply_pitr_restore: ['POST', '/v1/pitr-restores/{pitr_plan_id}/apply'],
35
+ };
36
+ export function isPitrTool(name) { return Object.hasOwn(routes, name); }
37
+ export async function callPitrTool(client, name, args) {
38
+ const route = routes[name], schema = schemas[name];
39
+ if (!route || !schema)
40
+ throw new Error('Unknown recovery workflow');
41
+ const body = schema.parse(args);
42
+ const path = route[1].replace(/\{([a-z_]+)\}/g, (_, key) => { const value = body[key]; delete body[key]; return encodeURIComponent(String(value)); });
43
+ return route[0] === 'GET' ? client.get(path) : client.post(path, body);
44
+ }
45
+ //# sourceMappingURL=pitr-workflows.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pitr-workflows.js","sourceRoot":"","sources":["../src/pitr-workflows.ts"],"names":[],"mappings":"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"}