@pushto/cli 0.4.10 → 0.5.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.
Files changed (56) hide show
  1. package/dist/commands/__tests__/mcp-add.test.d.ts +2 -0
  2. package/dist/commands/__tests__/mcp-add.test.d.ts.map +1 -0
  3. package/dist/commands/__tests__/mcp-add.test.js +112 -0
  4. package/dist/commands/__tests__/mcp-add.test.js.map +1 -0
  5. package/dist/commands/__tests__/mcp-serve.test.d.ts +2 -0
  6. package/dist/commands/__tests__/mcp-serve.test.d.ts.map +1 -0
  7. package/dist/commands/__tests__/mcp-serve.test.js +169 -0
  8. package/dist/commands/__tests__/mcp-serve.test.js.map +1 -0
  9. package/dist/commands/deploy.d.ts.map +1 -1
  10. package/dist/commands/deploy.js +63 -101
  11. package/dist/commands/deploy.js.map +1 -1
  12. package/dist/commands/mcp.d.ts +7 -0
  13. package/dist/commands/mcp.d.ts.map +1 -0
  14. package/dist/commands/mcp.js +137 -0
  15. package/dist/commands/mcp.js.map +1 -0
  16. package/dist/index.js +12 -1
  17. package/dist/index.js.map +1 -1
  18. package/dist/lib/__tests__/deploy-local.test.d.ts +2 -0
  19. package/dist/lib/__tests__/deploy-local.test.d.ts.map +1 -0
  20. package/dist/lib/__tests__/deploy-local.test.js +103 -0
  21. package/dist/lib/__tests__/deploy-local.test.js.map +1 -0
  22. package/dist/lib/__tests__/mcp-serve-client.test.d.ts +2 -0
  23. package/dist/lib/__tests__/mcp-serve-client.test.d.ts.map +1 -0
  24. package/dist/lib/__tests__/mcp-serve-client.test.js +74 -0
  25. package/dist/lib/__tests__/mcp-serve-client.test.js.map +1 -0
  26. package/dist/lib/__tests__/npm-packaging.test.js +1 -1
  27. package/dist/lib/__tests__/npm-packaging.test.js.map +1 -1
  28. package/dist/lib/mcp-serve/agent-config.d.ts +26 -0
  29. package/dist/lib/mcp-serve/agent-config.d.ts.map +1 -0
  30. package/dist/lib/mcp-serve/agent-config.js +38 -0
  31. package/dist/lib/mcp-serve/agent-config.js.map +1 -0
  32. package/dist/lib/mcp-serve/client.d.ts +22 -0
  33. package/dist/lib/mcp-serve/client.d.ts.map +1 -0
  34. package/dist/lib/mcp-serve/client.js +68 -0
  35. package/dist/lib/mcp-serve/client.js.map +1 -0
  36. package/dist/lib/mcp-serve/deploy-local.d.ts +13 -0
  37. package/dist/lib/mcp-serve/deploy-local.d.ts.map +1 -0
  38. package/dist/lib/mcp-serve/deploy-local.js +99 -0
  39. package/dist/lib/mcp-serve/deploy-local.js.map +1 -0
  40. package/dist/lib/mcp-serve/serve.d.ts +19 -0
  41. package/dist/lib/mcp-serve/serve.d.ts.map +1 -0
  42. package/dist/lib/mcp-serve/serve.js +60 -0
  43. package/dist/lib/mcp-serve/serve.js.map +1 -0
  44. package/dist/lib/mcp-serve/token.d.ts +20 -0
  45. package/dist/lib/mcp-serve/token.d.ts.map +1 -0
  46. package/dist/lib/mcp-serve/token.js +43 -0
  47. package/dist/lib/mcp-serve/token.js.map +1 -0
  48. package/dist/lib/perform-deploy.d.ts +74 -0
  49. package/dist/lib/perform-deploy.d.ts.map +1 -0
  50. package/dist/lib/perform-deploy.js +112 -0
  51. package/dist/lib/perform-deploy.js.map +1 -0
  52. package/dist/version.d.ts +1 -1
  53. package/dist/version.d.ts.map +1 -1
  54. package/dist/version.js +3 -3
  55. package/dist/version.js.map +1 -1
  56. package/package.json +2 -1
@@ -0,0 +1,38 @@
1
+ import path from 'node:path';
2
+ /** The one-liner for claude code — the wedge's front door. */
3
+ export const CLAUDE_ADD_COMMAND = 'claude mcp add pushto -- pushto mcp serve';
4
+ /** argv form of the same command for spawning without a shell. */
5
+ export const CLAUDE_ADD_ARGV = ['mcp', 'add', 'pushto', '--', 'pushto', 'mcp', 'serve'];
6
+ export const PUSHTO_SERVER_ENTRY = { command: 'pushto', args: ['mcp', 'serve'] };
7
+ export const cursorConfigPath = (home) => path.join(home, '.cursor', 'mcp.json');
8
+ /** The generic snippet for any mcp client config. */
9
+ export const genericSnippet = () => JSON.stringify({ mcpServers: { pushto: PUSHTO_SERVER_ENTRY } }, null, 2);
10
+ /**
11
+ * Merge the pushto server entry into an existing cursor mcp.json, preserving
12
+ * every other server. A file that exists but does not parse is NEVER
13
+ * clobbered — the user gets told instead.
14
+ */
15
+ export const mergeCursorConfig = (existing) => {
16
+ let parsed;
17
+ if (existing === null || existing.trim() === '') {
18
+ parsed = {};
19
+ }
20
+ else {
21
+ try {
22
+ const raw = JSON.parse(existing);
23
+ if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {
24
+ return { ok: false, reason: 'the file is not a json object.' };
25
+ }
26
+ parsed = raw;
27
+ }
28
+ catch {
29
+ return { ok: false, reason: 'the file is not valid json.' };
30
+ }
31
+ }
32
+ const servers = parsed.mcpServers ?? {};
33
+ const current = servers.pushto;
34
+ const already = current !== undefined && JSON.stringify(current) === JSON.stringify(PUSHTO_SERVER_ENTRY);
35
+ const merged = JSON.stringify({ ...parsed, mcpServers: { ...servers, pushto: PUSHTO_SERVER_ENTRY } }, null, 2);
36
+ return { ok: true, merged: `${merged}\n`, already };
37
+ };
38
+ //# sourceMappingURL=agent-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-config.js","sourceRoot":"","sources":["../../../src/lib/mcp-serve/agent-config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,8DAA8D;AAC9D,MAAM,CAAC,MAAM,kBAAkB,GAAG,2CAA2C,CAAC;AAE9E,kEAAkE;AAClE,MAAM,CAAC,MAAM,eAAe,GAAsB,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;AAE3G,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,EAAW,CAAC;AAE1F,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;AAEjG,qDAAqD;AACrD,MAAM,CAAC,MAAM,cAAc,GAAG,GAAW,EAAE,CACzC,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,mBAAmB,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAM3E;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAAuB,EAAsB,EAAE;IAC/E,IAAI,MAAgD,CAAC;IACrD,IAAI,QAAQ,KAAK,IAAI,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAChD,MAAM,GAAG,EAAE,CAAC;IACd,CAAC;SAAM,CAAC;QACN,IAAI,CAAC;YACH,MAAM,GAAG,GAAY,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC1C,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;gBAClE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,gCAAgC,EAAE,CAAC;YACjE,CAAC;YACD,MAAM,GAAG,GAA+C,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,6BAA6B,EAAE,CAAC;QAC9D,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IAC/B,MAAM,OAAO,GACX,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;IAE3F,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAC3B,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,EAAE,EACtE,IAAI,EACJ,CAAC,CACF,CAAC;IACF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,EAAE,OAAO,EAAE,CAAC;AACtD,CAAC,CAAC"}
@@ -0,0 +1,22 @@
1
+ export interface CatalogTool {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: Record<string, unknown> | null;
5
+ available: boolean;
6
+ unavailableReason?: string;
7
+ }
8
+ /**
9
+ * Authed client for the private /api/mcp contract. Holds the minted MCP
10
+ * bearer in memory only (never on disk — the CLI session in conf is the
11
+ * only persistent credential), re-mints once on 401, and sends the CLI
12
+ * version so the server can gate drifted clients later.
13
+ */
14
+ export declare class McpApiClient {
15
+ private readonly baseUrl;
16
+ private token;
17
+ constructor(baseUrl?: string);
18
+ private authed;
19
+ listTools(): Promise<CatalogTool[]>;
20
+ callTool(name: string, args: unknown): Promise<unknown>;
21
+ }
22
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/lib/mcp-serve/client.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC5C,SAAS,EAAE,OAAO,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;GAKG;AACH,qBAAa,YAAY;IAGX,OAAO,CAAC,QAAQ,CAAC,OAAO;IAFpC,OAAO,CAAC,KAAK,CAAuB;gBAEP,OAAO,GAAE,MAAsC;YAE9D,MAAM;IA0Bd,SAAS,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAWnC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CAoB9D"}
@@ -0,0 +1,68 @@
1
+ import { config } from '../config.js';
2
+ import { buildError } from '../errors.js';
3
+ import { VERSION } from '../../version.js';
4
+ import { mintMcpToken, ProxyFailure } from './token.js';
5
+ /**
6
+ * Authed client for the private /api/mcp contract. Holds the minted MCP
7
+ * bearer in memory only (never on disk — the CLI session in conf is the
8
+ * only persistent credential), re-mints once on 401, and sends the CLI
9
+ * version so the server can gate drifted clients later.
10
+ */
11
+ export class McpApiClient {
12
+ baseUrl;
13
+ token = null;
14
+ constructor(baseUrl = `${config.get('apiUrl')}/api`) {
15
+ this.baseUrl = baseUrl;
16
+ }
17
+ async authed(path, init, retried = false) {
18
+ if (!this.token)
19
+ this.token = (await mintMcpToken()).token;
20
+ let res;
21
+ try {
22
+ res = await fetch(`${this.baseUrl}${path}`, {
23
+ ...init,
24
+ headers: {
25
+ ...(init.headers ?? {}),
26
+ authorization: `Bearer ${this.token}`,
27
+ 'content-type': 'application/json',
28
+ 'x-pushto-cli-version': VERSION,
29
+ },
30
+ signal: init.signal ?? AbortSignal.timeout(60_000),
31
+ });
32
+ }
33
+ catch {
34
+ throw new ProxyFailure(buildError('NETWORK', 'could not reach pushto. check your connection.'));
35
+ }
36
+ if (res.status === 401 && !retried) {
37
+ this.token = null;
38
+ return this.authed(path, init, true);
39
+ }
40
+ return res;
41
+ }
42
+ async listTools() {
43
+ const res = await this.authed('/mcp', { method: 'GET' });
44
+ if (!res.ok) {
45
+ throw new ProxyFailure(buildError('SERVER_ERROR', `tool catalog fetch failed (${res.status}).`));
46
+ }
47
+ const body = (await res.json());
48
+ return body.tools;
49
+ }
50
+ async callTool(name, args) {
51
+ const res = await this.authed('/mcp', {
52
+ method: 'POST',
53
+ body: JSON.stringify({ tool: name, args }),
54
+ });
55
+ let body;
56
+ try {
57
+ body = (await res.json());
58
+ }
59
+ catch {
60
+ throw new ProxyFailure(buildError('SERVER_ERROR', `tool call returned an unreadable response (${res.status}).`));
61
+ }
62
+ if (!res.ok) {
63
+ throw new ProxyFailure(buildError('SERVER_ERROR', body.error ?? `tool call failed (${res.status}).`));
64
+ }
65
+ return body.result;
66
+ }
67
+ }
68
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/lib/mcp-serve/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { LocalTool } from './serve.js';
2
+ /**
3
+ * pushto.deploy.local — deploy the working directory this server was
4
+ * spawned in. Client-side by necessity: only this process has the cwd.
5
+ *
6
+ * Slug resolution follows the cli-upload-local-slug rules verbatim: the
7
+ * directory's own .pushto (readLocalSlug) or an explicit create — the
8
+ * global slug is NEVER consulted (importing resolveSlug here would ship
9
+ * this directory into whatever project init/use last touched, the exact
10
+ * 2026-07-30 incident, and the guard fails the build for it).
11
+ */
12
+ export declare const deployLocalTool: LocalTool;
13
+ //# sourceMappingURL=deploy-local.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy-local.d.ts","sourceRoot":"","sources":["../../../src/lib/mcp-serve/deploy-local.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,SA2F7B,CAAC"}
@@ -0,0 +1,99 @@
1
+ import path from 'node:path';
2
+ import { readLocalSlug } from '../resolve-slug.js';
3
+ import { slugifyProjectName } from '../project-name.js';
4
+ import { createAndLinkProject } from '../create-project.js';
5
+ import { prepareArtifact } from '../prepare-artifact.js';
6
+ import { zipAndCheck, uploadArtifact, triggerDynamicDeploy, describeGit } from '../perform-deploy.js';
7
+ import { buildError } from '../errors.js';
8
+ /**
9
+ * pushto.deploy.local — deploy the working directory this server was
10
+ * spawned in. Client-side by necessity: only this process has the cwd.
11
+ *
12
+ * Slug resolution follows the cli-upload-local-slug rules verbatim: the
13
+ * directory's own .pushto (readLocalSlug) or an explicit create — the
14
+ * global slug is NEVER consulted (importing resolveSlug here would ship
15
+ * this directory into whatever project init/use last touched, the exact
16
+ * 2026-07-30 incident, and the guard fails the build for it).
17
+ */
18
+ export const deployLocalTool = {
19
+ name: 'pushto.deploy.local',
20
+ description: 'deploy the current working directory to pushto. no repo connection needed. if nothing is linked here, call again with create: true to make a project named after the folder.',
21
+ inputSchema: {
22
+ type: 'object',
23
+ properties: {
24
+ create: { type: 'boolean', description: 'create and link a project when none exists here' },
25
+ name: { type: 'string', description: 'project name when creating; defaults to the folder name' },
26
+ },
27
+ },
28
+ handler: async (rawArgs) => {
29
+ const args = (rawArgs ?? {});
30
+ const cwd = process.cwd();
31
+ let slug = readLocalSlug(cwd);
32
+ if (!slug) {
33
+ if (!args.create) {
34
+ return buildError('NO_PROJECT', 'no project is linked in this directory. call pushto.deploy.local again with create: true to make one named after the folder, or run pushto link <slug> for an existing project.');
35
+ }
36
+ const name = args.name?.trim() || path.basename(cwd);
37
+ const candidate = slugifyProjectName(name);
38
+ const created = await createAndLinkProject(candidate, { displayName: name, cwd });
39
+ if (!created.ok) {
40
+ return buildError(created.network ? 'NETWORK' : 'SERVER_ERROR', created.error);
41
+ }
42
+ slug = candidate;
43
+ }
44
+ // Progress narration goes to stderr — stdout belongs to the protocol.
45
+ const prep = await prepareArtifact(cwd, (line) => console.error(`[deploy] ${line}`));
46
+ if (prep.kind === 'failed') {
47
+ const tail = prep.buildOutput.trim().split('\n').slice(-30).join('\n');
48
+ return buildError('BUILD_FAILED', prep.message, { details: { buildOutput: tail } });
49
+ }
50
+ try {
51
+ const zipped = await zipAndCheck(prep.zipDir);
52
+ if (!zipped.ok)
53
+ return zipped.error;
54
+ const uploaded = await uploadArtifact(slug, zipped.buffer);
55
+ if (!uploaded.ok)
56
+ return uploaded.error;
57
+ const base = {
58
+ slug,
59
+ version: uploaded.deployment.version,
60
+ fileCount: uploaded.deployment.fileCount,
61
+ };
62
+ if (uploaded.deployment.container) {
63
+ return {
64
+ summary: `deployed ${slug}. live at ${uploaded.deployment.url}.`,
65
+ data: { ...base, url: uploaded.deployment.url },
66
+ };
67
+ }
68
+ const trig = await triggerDynamicDeploy(slug, describeGit(), prep.kind === 'artifact' ? prep.framework : undefined);
69
+ switch (trig.kind) {
70
+ case 'container':
71
+ return {
72
+ summary: `deployed ${slug} as ${trig.framework ?? 'a server app'}. live at ${trig.url ?? uploaded.deployment.url}.`,
73
+ data: { ...base, url: trig.url ?? uploaded.deployment.url, framework: trig.framework },
74
+ };
75
+ case 'static':
76
+ return {
77
+ summary: `deployed ${slug}. live at ${uploaded.deployment.url}.`,
78
+ data: { ...base, url: uploaded.deployment.url },
79
+ };
80
+ case 'still-building':
81
+ return {
82
+ summary: `${slug} uploaded; the build is still running. check pushto.deploy.status or pushto.logs.tail in a minute.`,
83
+ data: { ...base, url: uploaded.deployment.url, stillBuilding: true },
84
+ };
85
+ case 'gated':
86
+ return buildError('PAID_FEATURE', trig.detail);
87
+ case 'failed':
88
+ return buildError('BUILD_FAILED', trig.detail, {
89
+ details: { hint: 'read pushto.logs.tail and pushto.errors.episodes for the cause.' },
90
+ });
91
+ }
92
+ }
93
+ finally {
94
+ if (prep.kind === 'artifact')
95
+ prep.cleanup();
96
+ }
97
+ },
98
+ };
99
+ //# sourceMappingURL=deploy-local.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy-local.js","sourceRoot":"","sources":["../../../src/lib/mcp-serve/deploy-local.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import type { McpApiClient } from './client.js';
2
+ /**
3
+ * A tool implemented inside the stdio server itself (not proxied to the web
4
+ * registry). Exists because only this process has the user's working
5
+ * directory — pushto.deploy.local plugs in here.
6
+ */
7
+ export interface LocalTool {
8
+ name: string;
9
+ description: string;
10
+ inputSchema: Record<string, unknown>;
11
+ handler: (args: unknown) => Promise<unknown>;
12
+ }
13
+ /**
14
+ * Run the stdio MCP server until stdin closes. stdout carries protocol
15
+ * frames ONLY — all human logging in this process goes to stderr, enforced
16
+ * by the stdout-purity integration test.
17
+ */
18
+ export declare const runMcpServe: (client: McpApiClient, localTools: LocalTool[]) => Promise<void>;
19
+ //# sourceMappingURL=serve.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../../src/lib/mcp-serve/serve.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9C;AAcD;;;;GAIG;AACH,eAAO,MAAM,WAAW,GACtB,QAAQ,YAAY,EACpB,YAAY,SAAS,EAAE,KACtB,OAAO,CAAC,IAAI,CAyCd,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
4
+ import { VERSION } from '../../version.js';
5
+ import { ProxyFailure } from './token.js';
6
+ /**
7
+ * Tool failures become structured text content the agent can branch on —
8
+ * never a thrown error, which would kill the stdio session. ProxyFailure
9
+ * unwraps to its PushtoError (code + human + fix); anything else gets the
10
+ * UNEXPECTED shape.
11
+ */
12
+ const formatToolError = (err) => {
13
+ if (err instanceof ProxyFailure)
14
+ return JSON.stringify(err.pushtoError);
15
+ const message = err instanceof Error ? err.message : String(err);
16
+ return JSON.stringify({ code: 'UNEXPECTED', human: message, retryable: false });
17
+ };
18
+ /**
19
+ * Run the stdio MCP server until stdin closes. stdout carries protocol
20
+ * frames ONLY — all human logging in this process goes to stderr, enforced
21
+ * by the stdout-purity integration test.
22
+ */
23
+ export const runMcpServe = async (client, localTools) => {
24
+ const server = new Server({ name: 'pushto', version: VERSION }, { capabilities: { tools: {} } });
25
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
26
+ const remote = await client.listTools();
27
+ return {
28
+ tools: [
29
+ ...remote
30
+ .filter((t) => t.available)
31
+ .map((t) => ({
32
+ name: t.name,
33
+ description: t.description,
34
+ inputSchema: t.inputSchema ?? { type: 'object' },
35
+ })),
36
+ ...localTools.map((t) => ({
37
+ name: t.name,
38
+ description: t.description,
39
+ inputSchema: t.inputSchema,
40
+ })),
41
+ ],
42
+ };
43
+ });
44
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
45
+ const local = localTools.find((t) => t.name === req.params.name);
46
+ try {
47
+ const result = local
48
+ ? await local.handler(req.params.arguments)
49
+ : await client.callTool(req.params.name, req.params.arguments);
50
+ return { content: [{ type: 'text', text: JSON.stringify(result) }] };
51
+ }
52
+ catch (err) {
53
+ return { content: [{ type: 'text', text: formatToolError(err) }], isError: true };
54
+ }
55
+ });
56
+ const transport = new StdioServerTransport();
57
+ await server.connect(transport);
58
+ console.error(`pushto mcp server up (cli ${VERSION}). tools proxy to the pushto api.`);
59
+ };
60
+ //# sourceMappingURL=serve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../src/lib/mcp-serve/serve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { PushtoError } from '@pushto/shared/errors';
2
+ export interface MintedToken {
3
+ token: string;
4
+ expiresAt: string;
5
+ }
6
+ /**
7
+ * The mcp-serve boundary's internal throwable. The CLI's house pattern is
8
+ * typed error OBJECTS (never throw), but the stdio server's request handlers
9
+ * need exception control flow to reach one formatting point — so this
10
+ * wrapper exists strictly inside lib/mcp-serve/ and is always unwrapped back
11
+ * to its PushtoError at the handler boundary. It must never cross into
12
+ * command-level code.
13
+ */
14
+ export declare class ProxyFailure extends Error {
15
+ readonly pushtoError: PushtoError;
16
+ constructor(pushtoError: PushtoError);
17
+ }
18
+ /** Mint a fresh MCP bearer from the CLI session. */
19
+ export declare const mintMcpToken: () => Promise<MintedToken>;
20
+ //# sourceMappingURL=token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../../src/lib/mcp-serve/token.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,qBAAa,YAAa,SAAQ,KAAK;aACT,WAAW,EAAE,WAAW;gBAAxB,WAAW,EAAE,WAAW;CAIrD;AAED,oDAAoD;AACpD,eAAO,MAAM,YAAY,QAAa,OAAO,CAAC,WAAW,CA4BxD,CAAC"}
@@ -0,0 +1,43 @@
1
+ import { api } from '../api.js';
2
+ import { buildError } from '../errors.js';
3
+ /**
4
+ * The mcp-serve boundary's internal throwable. The CLI's house pattern is
5
+ * typed error OBJECTS (never throw), but the stdio server's request handlers
6
+ * need exception control flow to reach one formatting point — so this
7
+ * wrapper exists strictly inside lib/mcp-serve/ and is always unwrapped back
8
+ * to its PushtoError at the handler boundary. It must never cross into
9
+ * command-level code.
10
+ */
11
+ export class ProxyFailure extends Error {
12
+ pushtoError;
13
+ constructor(pushtoError) {
14
+ super(pushtoError.human);
15
+ this.pushtoError = pushtoError;
16
+ this.name = 'ProxyFailure';
17
+ }
18
+ }
19
+ /** Mint a fresh MCP bearer from the CLI session. */
20
+ export const mintMcpToken = async () => {
21
+ let res;
22
+ try {
23
+ res = await api('/cli/mcp-token', { method: 'POST' });
24
+ }
25
+ catch {
26
+ throw new ProxyFailure(buildError('NETWORK', 'could not reach pushto to mint an agent token. check your connection.'));
27
+ }
28
+ if (res.status === 401) {
29
+ throw new ProxyFailure(buildError('NOT_AUTHENTICATED', 'your pushto login expired.', {
30
+ fix: { label: 'log in again', cmd: 'pushto login' },
31
+ }));
32
+ }
33
+ if (!res.ok) {
34
+ throw new ProxyFailure(buildError('SERVER_ERROR', `token mint failed (${res.status}). try again in a moment.`));
35
+ }
36
+ try {
37
+ return (await res.json());
38
+ }
39
+ catch {
40
+ throw new ProxyFailure(buildError('SERVER_ERROR', 'token mint returned an unreadable response.'));
41
+ }
42
+ };
43
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../../src/lib/mcp-serve/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAQ1C;;;;;;;GAOG;AACH,MAAM,OAAO,YAAa,SAAQ,KAAK;IACT;IAA5B,YAA4B,WAAwB;QAClD,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QADC,gBAAW,GAAX,WAAW,CAAa;QAElD,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED,oDAAoD;AACpD,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,IAA0B,EAAE;IAC3D,IAAI,GAAa,CAAC;IAClB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,GAAG,CAAC,gBAAgB,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,YAAY,CACpB,UAAU,CAAC,SAAS,EAAE,uEAAuE,CAAC,CAC/F,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QACvB,MAAM,IAAI,YAAY,CACpB,UAAU,CAAC,mBAAmB,EAAE,4BAA4B,EAAE;YAC5D,GAAG,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,GAAG,EAAE,cAAc,EAAE;SACpD,CAAC,CACH,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,YAAY,CACpB,UAAU,CAAC,cAAc,EAAE,sBAAsB,GAAG,CAAC,MAAM,2BAA2B,CAAC,CACxF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAgB,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,YAAY,CACpB,UAAU,CAAC,cAAc,EAAE,6CAA6C,CAAC,CAC1E,CAAC;IACJ,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,74 @@
1
+ import type { PushtoError } from '@pushto/shared/errors';
2
+ /**
3
+ * The pure mechanics of a deploy — zip, upload, trigger — shared by the
4
+ * deploy command (which owns every spinner, box, and exit around them) and
5
+ * pushto.deploy.local in the mcp server (which has no terminal at all).
6
+ * Nothing here prints, prompts, or exits; everything returns typed results.
7
+ *
8
+ * Guard note: this file deliberately imports zip-project and NOT
9
+ * resolve-slug — callers hand it a slug they resolved under the
10
+ * cli-upload-local-slug rules.
11
+ */
12
+ export type ZipOutcome = {
13
+ ok: true;
14
+ buffer: Buffer;
15
+ fileCount: number;
16
+ sizeBytes: number;
17
+ } | {
18
+ ok: false;
19
+ error: PushtoError;
20
+ fileCount: number;
21
+ sizeBytes: number;
22
+ };
23
+ export declare const zipAndCheck: (zipDir: string) => Promise<ZipOutcome>;
24
+ export interface UploadedDeployment {
25
+ version: number;
26
+ fileCount: number;
27
+ buildDuration: number;
28
+ url: string;
29
+ altUrl?: string;
30
+ /** non-null when the upload alone produced a running container */
31
+ container: string | null;
32
+ }
33
+ export type UploadOutcome = {
34
+ ok: true;
35
+ deployment: UploadedDeployment;
36
+ } | {
37
+ ok: false;
38
+ error: PushtoError;
39
+ };
40
+ export declare const uploadArtifact: (slug: string, buffer: Buffer) => Promise<UploadOutcome>;
41
+ export interface GitDescription {
42
+ hash: string | null;
43
+ message: string | null;
44
+ branch: string;
45
+ }
46
+ /** Re-exported so callers describe commits without importing zip-project. */
47
+ export declare const describeGit: () => GitDescription;
48
+ export type TriggerOutcome = {
49
+ kind: 'container';
50
+ url: string | null;
51
+ framework: string | null;
52
+ buildDuration: number | null;
53
+ } | {
54
+ kind: 'static';
55
+ message: string | null;
56
+ } | {
57
+ kind: 'gated';
58
+ detail: string;
59
+ } | {
60
+ kind: 'still-building';
61
+ detail: string | null;
62
+ } | {
63
+ kind: 'failed';
64
+ detail: string;
65
+ };
66
+ /**
67
+ * Trigger the dynamic-deploy pass after an upload. Status classification
68
+ * mirrors the deploy command's hard-won branch semantics exactly: 403 =
69
+ * free-tier gate on a genuinely dynamic project, 504 = server stopped
70
+ * waiting but the build continues, 409 = a build for this version is
71
+ * already in flight (both non-failures).
72
+ */
73
+ export declare const triggerDynamicDeploy: (slug: string, git: GitDescription, builtFramework: string | undefined) => Promise<TriggerOutcome>;
74
+ //# sourceMappingURL=perform-deploy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"perform-deploy.d.ts","sourceRoot":"","sources":["../../src/lib/perform-deploy.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD;;;;;;;;;GASG;AAEH,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAClE;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5E,eAAO,MAAM,WAAW,GAAU,QAAQ,MAAM,KAAG,OAAO,CAAC,UAAU,CA2BpE,CAAC;AAEF,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,MAAM,aAAa,GACrB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,UAAU,EAAE,kBAAkB,CAAA;CAAE,GAC5C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,CAAC;AAEtC,eAAO,MAAM,cAAc,GAAU,MAAM,MAAM,EAAE,QAAQ,MAAM,KAAG,OAAO,CAAC,aAAa,CAiCxF,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,6EAA6E;AAC7E,eAAO,MAAM,WAAW,QAAO,cAA8B,CAAC;AAE9D,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACjG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvC;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC/B,MAAM,MAAM,EACZ,KAAK,cAAc,EACnB,gBAAgB,MAAM,GAAG,SAAS,KACjC,OAAO,CAAC,cAAc,CAmDxB,CAAC"}
@@ -0,0 +1,112 @@
1
+ import { api, deploySignal } from './api.js';
2
+ import { safeJson } from './safe-json.js';
3
+ import { getGitInfo, zipDirectory } from './zip-project.js';
4
+ import { SERVER_UPLOAD_CAP_BYTES, fmtMB } from './upload-limits.js';
5
+ import { buildError } from './errors.js';
6
+ export const zipAndCheck = async (zipDir) => {
7
+ const { buffer, fileCount } = await zipDirectory(zipDir);
8
+ if (fileCount === 0) {
9
+ return {
10
+ ok: false,
11
+ fileCount,
12
+ sizeBytes: buffer.length,
13
+ error: buildError('NO_FILES', 'no files found in this directory. is everything gitignored, or are you in the wrong directory?', { fix: { label: 'see what would upload', cmd: 'pushto doctor' } }),
14
+ };
15
+ }
16
+ if (buffer.length > SERVER_UPLOAD_CAP_BYTES) {
17
+ return {
18
+ ok: false,
19
+ fileCount,
20
+ sizeBytes: buffer.length,
21
+ error: buildError('ARTIFACT_TOO_LARGE', `deploy is ${fmtMB(buffer.length)} but the server cap is ${fmtMB(SERVER_UPLOAD_CAP_BYTES)}. add large files to .gitignore or .pushtoignore.`, { fix: { label: 'see the biggest files', cmd: 'pushto doctor' } }),
22
+ };
23
+ }
24
+ return { ok: true, buffer, fileCount, sizeBytes: buffer.length };
25
+ };
26
+ export const uploadArtifact = async (slug, buffer) => {
27
+ let res;
28
+ try {
29
+ res = await api(`/cli/projects/${slug}/upload`, {
30
+ method: 'POST',
31
+ headers: { 'Content-Type': 'application/zip' },
32
+ body: new Uint8Array(buffer),
33
+ signal: deploySignal(),
34
+ });
35
+ }
36
+ catch {
37
+ return { ok: false, error: buildError('NETWORK', 'upload did not reach pushto. check your connection.') };
38
+ }
39
+ if (!res.ok) {
40
+ const data = await safeJson(res);
41
+ return { ok: false, error: buildError('SERVER_ERROR', data.error ?? 'deploy failed.') };
42
+ }
43
+ const data = await safeJson(res);
44
+ return {
45
+ ok: true,
46
+ deployment: {
47
+ version: data.deployment.version,
48
+ fileCount: data.deployment.fileCount,
49
+ buildDuration: data.deployment.buildDuration,
50
+ url: data.url,
51
+ altUrl: data.altUrl,
52
+ container: data.container ?? null,
53
+ },
54
+ };
55
+ };
56
+ /** Re-exported so callers describe commits without importing zip-project. */
57
+ export const describeGit = () => getGitInfo();
58
+ /**
59
+ * Trigger the dynamic-deploy pass after an upload. Status classification
60
+ * mirrors the deploy command's hard-won branch semantics exactly: 403 =
61
+ * free-tier gate on a genuinely dynamic project, 504 = server stopped
62
+ * waiting but the build continues, 409 = a build for this version is
63
+ * already in flight (both non-failures).
64
+ */
65
+ export const triggerDynamicDeploy = async (slug, git, builtFramework) => {
66
+ let res;
67
+ try {
68
+ res = await api(`/cli/projects/${slug}/deploy`, {
69
+ method: 'POST',
70
+ headers: { 'Content-Type': 'application/json' },
71
+ body: JSON.stringify({
72
+ commitHash: git.hash,
73
+ commitMessage: git.message,
74
+ branch: git.branch,
75
+ builtFramework,
76
+ }),
77
+ signal: deploySignal(),
78
+ });
79
+ }
80
+ catch (err) {
81
+ return { kind: 'failed', detail: err instanceof Error ? err.message : 'network error during deploy' };
82
+ }
83
+ if (res.ok) {
84
+ const data = await safeJson(res);
85
+ if (data.container) {
86
+ return {
87
+ kind: 'container',
88
+ url: data.url ?? null,
89
+ framework: data.deployment?.framework ?? null,
90
+ buildDuration: data.deployment?.buildDuration ?? null,
91
+ };
92
+ }
93
+ return { kind: 'static', message: data.message ?? null };
94
+ }
95
+ if (res.status === 403) {
96
+ const data = await safeJson(res);
97
+ return { kind: 'gated', detail: data.error ?? 'dynamic deploys are a paid feature.' };
98
+ }
99
+ if (res.status === 504) {
100
+ return { kind: 'still-building', detail: null };
101
+ }
102
+ if (res.status === 409) {
103
+ const data = await safeJson(res);
104
+ return {
105
+ kind: 'still-building',
106
+ detail: data.error ?? 'a build for this version is already in progress',
107
+ };
108
+ }
109
+ const data = await safeJson(res);
110
+ return { kind: 'failed', detail: data.error ?? `server returned ${res.status}` };
111
+ };
112
+ //# sourceMappingURL=perform-deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"perform-deploy.js","sourceRoot":"","sources":["../../src/lib/perform-deploy.ts"],"names":[],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.4.10";
1
+ export declare const VERSION = "0.5.0";
2
2
  //# sourceMappingURL=version.d.ts.map