run402-mcp
Version:
MCP server for Run402 — full-stack backend infrastructure for AI agents: Postgres, auth, storage, serverless functions and atomic deploys. Paid with x402/MPP. Includes $0.03 image generation.
131 lines • 5.33 kB
JavaScript
/**
* `apps` namespace — marketplace browse/fork and app version publishing.
*/
import { gateSecret } from "../secret-gate.js";
import { requireProjectCredentials } from "../project-credentials.js";
export class Apps {
client;
constructor(client) {
this.client = client;
}
/** Browse public forkable apps. Optional `tags` filter is OR-combined. */
async browse(tags) {
const path = tags && tags.length > 0
? `/apps/v1?${tags.map((t) => `tag=${encodeURIComponent(t)}`).join("&")}`
: "/apps/v1";
return this.client.request(path, {
context: "browsing apps",
withAuth: false,
});
}
/** Upsert declarative app-install convergence state for `run402 up`. */
async upsertInstallState(input) {
return this.client.request("/apply/v1/app-installs", {
method: "POST",
body: input,
context: "upserting app install state",
authMeta: {
capability: "project.deploy",
target: { project_id: input.project_id },
},
});
}
/** Read declarative app-install convergence state for diagnostics/resume. */
async getInstallState(projectId, appKey) {
const params = new URLSearchParams({ project_id: projectId, app_key: appKey });
return this.client.request(`/apply/v1/app-installs?${params.toString()}`, {
context: "reading app install state",
});
}
/**
* Fork a published app into a new project. Payment flows through x402
* when the fork has a price.
*/
async fork(opts) {
gateSecret(this.client, "apps.fork", opts);
const result = await this.client.request("/fork/v1", {
method: "POST",
body: {
version_id: opts.versionId,
name: opts.name,
subdomain: opts.subdomain,
},
context: "forking app",
});
// Persist the new project + make it active, if the provider supports it.
const creds = this.client.credentials;
if (creds.saveProject) {
await creds.saveProject(result.project_id, {
anon_key: result.anon_key,
service_key: result.service_key,
});
}
if (creds.setActiveProject) {
await creds.setActiveProject(result.project_id);
}
return result;
}
/** Publish a project as a forkable app version. */
async publish(projectId, opts = {}) {
const project = await requireProjectCredentials(this.client, projectId, "publishing app");
const body = {};
if (opts.description !== undefined)
body.description = opts.description;
if (opts.tags !== undefined)
body.tags = opts.tags;
if (opts.visibility !== undefined)
body.visibility = opts.visibility;
if (opts.fork_allowed !== undefined)
body.fork_allowed = opts.fork_allowed;
return this.client.request(`/projects/v1/admin/${projectId}/publish`, {
method: "POST",
headers: { Authorization: `Bearer ${project.service_key}` },
body,
context: "publishing app",
});
}
/** List all published versions of a project. */
async listVersions(projectId) {
const project = await requireProjectCredentials(this.client, projectId, "listing versions");
return this.client.request(`/projects/v1/admin/${projectId}/versions`, {
headers: { Authorization: `Bearer ${project.service_key}` },
context: "listing versions",
});
}
/** Update metadata (description/tags/visibility/fork_allowed) of a published version. */
async updateVersion(projectId, versionId, opts) {
const project = await requireProjectCredentials(this.client, projectId, "updating version");
const body = {};
if (opts.description !== undefined)
body.description = opts.description;
if (opts.tags !== undefined)
body.tags = opts.tags;
if (opts.visibility !== undefined)
body.visibility = opts.visibility;
if (opts.fork_allowed !== undefined)
body.fork_allowed = opts.fork_allowed;
await this.client.request(`/projects/v1/admin/${projectId}/versions/${versionId}`, {
method: "PATCH",
headers: { Authorization: `Bearer ${project.service_key}` },
body,
context: "updating version",
});
}
/** Delete a published version. */
async deleteVersion(projectId, versionId) {
const project = await requireProjectCredentials(this.client, projectId, "deleting version");
await this.client.request(`/projects/v1/admin/${projectId}/versions/${versionId}`, {
method: "DELETE",
headers: { Authorization: `Bearer ${project.service_key}` },
context: "deleting version",
});
}
/** Inspect a published app by version id. Public — no auth. */
async getApp(versionId) {
return this.client.request(`/apps/v1/${versionId}`, {
context: "fetching app details",
withAuth: false,
});
}
}
//# sourceMappingURL=apps.js.map