UNPKG

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.

426 lines • 21.2 kB
/** * @run402/sdk — typed TypeScript client for the Run402 API. * * This is the isomorphic entry point. Works in Node 22, Deno, Bun, and V8 * isolates with no filesystem. For Node consumers that want zero-config * defaults (keystore + wallet + x402), use `@run402/sdk/node` instead. */ import { buildClient } from "./kernel.js"; import { Projects } from "./namespaces/projects.js"; import { Assets } from "./namespaces/assets.js"; import { Functions } from "./namespaces/functions.js"; import { Secrets } from "./namespaces/secrets.js"; import { Cache } from "./namespaces/cache.js"; import { Subdomains } from "./namespaces/subdomains.js"; import { Domains } from "./namespaces/domains.js"; import { Sites } from "./namespaces/sites.js"; import { Service } from "./namespaces/service.js"; import { Tier } from "./namespaces/tier.js"; import { Ai } from "./namespaces/ai.js"; import { Auth } from "./namespaces/auth.js"; import { Billing } from "./namespaces/billing.js"; import { Vouchers } from "./namespaces/vouchers.js"; import { Wallets, ScopedWallet } from "./namespaces/wallets.js"; import { Apps } from "./namespaces/apps.js"; import { Email } from "./namespaces/email.js"; import { Contracts } from "./namespaces/contracts.js"; import { Credentials } from "./namespaces/credentials.js"; import { Admin } from "./namespaces/admin.js"; import { Deploy } from "./namespaces/deploy.js"; import { Ci } from "./namespaces/ci.js"; import { Jobs } from "./namespaces/jobs.js"; import { Archives } from "./namespaces/archives.js"; import { Snapshots } from "./namespaces/snapshots.js"; import { Branches } from "./namespaces/branches.js"; import { Session } from "./namespaces/session.js"; import { WriteApproval } from "./namespaces/write-approval.js"; import { Me } from "./namespaces/me.js"; import { Orgs, ScopedOrg } from "./namespaces/org.js"; import { Grants } from "./namespaces/grants.js"; import { Events } from "./namespaces/events.js"; import { Live } from "./namespaces/live.js"; import { Rooms } from "./namespaces/rooms.js"; import { Escalations } from "./namespaces/escalations.js"; import { Errors } from "./namespaces/errors.js"; import { Pay } from "./namespaces/pay.js"; import { IdentityLinks } from "./namespaces/identity-links.js"; import { Buzz } from "./namespaces/buzz.js"; import { Agent } from "./namespaces/agent.js"; import { Repos } from "./namespaces/repos.js"; import { ScopedRun402 } from "./scoped.js"; import { LocalError } from "./errors.js"; export class Run402 { apiBase; projects; assets; functions; secrets; cache; subdomains; domains; sites; service; tier; ai; image; auth; billing; vouchers; wallets; apps; email; contracts; credentials; admin; /** * Internal engine. Unified apply has no public `r.deploy` or `r.apply` * root surface — the sole hero is `r.project(id).apply`. * This property exists only so the scoped sub-client can delegate to the * engine implementation; do not call directly from user code. * @internal */ _applyEngine; ci; jobs; archives; snapshots; branches; /** * A person's sign-in session: the browser, loopback (`run402 login`), and * device (`run402 login --device`, read-only) mints, plus refresh, revoke, * step-up, passkey enrollment, and authenticators. Distinct from the agent's * per-wallet SIWX identity. */ session; /** * The passkey-signed, target-scoped write approval a signed-in person needs * to provision, deploy, or write secrets from the command line * (`r.writeApproval.requestChallenge` + `exchangeClaimCode`). */ writeApproval; /** The caller's own account reads: `r.me.overview()` and `r.me.status()`. */ me; /** * Org collection + identity (gateway v1.77+, first-class in v1.82): * `r.orgs.create()` / `list()` / `whoami()`. For operations on a single org by * id use the scoped sub-client {@link Run402.org} (`r.org(id).get()` / * `rename()` / `members.*` / `invites.*` / `audit()`). Distinct from the local, * network-free {@link Run402.whoami}. */ orgs; /** * Per-project capability grants for agent/CI principals, and the grant keys * minted against them — scoped, revocable credentials an owner hands an * agent without a wallet of its own, and the supported way back in when a * project's API keys are lost (they are issued once at create and never * re-issued). Also available project-scoped as `r.project(id).grants`. */ grants; /** * Cursored project events feed — "what happened since I last looked". * Also available project-scoped as `r.project(id).events`. */ events; /** * tenant-live-changes: change hints for live tables (`tables[].live: true`), * as a reconnecting SSE subscription or a held read. Also project-scoped as * `r.project(id).live`. */ live; /** * Agent-messaging coordination rooms — presence, room-visible addressed * messages, advisory claims. Org-scoped; a project id names its default * room (`r.rooms.forProject(projectId)` is the zero-config rendezvous). */ rooms; /** * The agent→human hotline: raise an escalation when YOU judge a person is * needed, then poll it until a named human takes ownership. Mandatory * delivery, confidential (never mirrored into a feed or a room), and it * climbs to the next contact level if nobody answers. */ escalations; /** Pay arbitrary x402-priced URLs with a spend ceiling and structured receipt. */ pay; /** * Release-error-rollup query surface — verdict-first, grouped error * fingerprints with a gateway-computed promote-vs-revert verdict, plus the * `watch` promote-gate poll loop. Also available project-scoped as * `r.project(id).errors`. */ errors; /** Public dual-proof associations between the active agent principal and external identities. */ identityLinks; /** The calling agent's own facts: its Lightning wallet. */ agent; /** Buzz human adoption, community installation, and bounded agent enrollment workflows. */ buzz; /** * vault — the host-blind encrypted Git remote (`r402s/v0`). Vault reads * (record, heads listing, policy) run anywhere; the verbs that touch a git * tree or the on-disk keystore (`init`, `push`, `compact`, `verify`, * `deploy`, `restore`) are Node-only and load `@run402/sdk/node` lazily. * * This namespace is where ALL vault protocol logic lives: the CLI's * `run402 repos …`, `git-remote-run402`, and the MCP tools are adapters * over it and add no behaviour of their own. * * Durability is keystore-qualified: the vault protects source history from * host-side loss while a principal keystore survives. */ repos; idempotency = { fromParts, }; #client; constructor(opts) { if (!opts || typeof opts !== "object") { throw new LocalError("Run402 requires an options object", "constructing client"); } if (!opts.apiBase || typeof opts.apiBase !== "string") { throw new LocalError("Run402 requires opts.apiBase (a non-empty string)", "constructing client"); } if (!opts.credentials) { throw new LocalError("Run402 requires opts.credentials. For Node defaults use `import { run402 } from '@run402/sdk/node'`. For sandbox/Deno/V8, pass a CredentialsProvider directly.", "constructing client"); } if (typeof opts.credentials.getAuth !== "function" || (typeof opts.credentials.getProjectCredentials !== "function" && // eslint-disable-next-line @typescript-eslint/no-deprecated -- older custom providers implement only getProject typeof opts.credentials.getProject !== "function")) { throw new LocalError("Run402 credentials provider is missing required methods (getAuth, getProjectCredentials)", "constructing client"); } const kernel = { apiBase: opts.apiBase, fetch: opts.fetch ?? globalThis.fetch.bind(globalThis), credentials: opts.credentials, clientMetadata: opts.clientMetadata, capabilities: opts.capabilities, }; this.apiBase = opts.apiBase; const client = buildClient(kernel); this.#client = client; this.projects = new Projects(client); this.assets = new Assets(client); this.functions = new Functions(client); this.secrets = new Secrets(client); this.cache = new Cache(client); this.subdomains = new Subdomains(client); this.domains = new Domains(client); this.sites = new Sites(client); this.service = new Service(client); this.tier = new Tier(client); this.ai = new Ai(client); Object.defineProperty(this, "image", { value: this.ai, enumerable: false, }); this.auth = new Auth(client); this.billing = new Billing(client); this.vouchers = new Vouchers(client); this.wallets = new Wallets(client); this.apps = new Apps(client); this.email = new Email(client); this.contracts = new Contracts(client); this.credentials = new Credentials(client); this.admin = new Admin(client); this._applyEngine = new Deploy(client); this.ci = new Ci(client); this.jobs = new Jobs(client); this.archives = new Archives(client); this.snapshots = new Snapshots(client); this.branches = new Branches(client); this.session = new Session(client); this.writeApproval = new WriteApproval(client); this.me = new Me(client); this.orgs = new Orgs(client); this.grants = new Grants(client); this.events = new Events(client); this.live = new Live(client); this.rooms = new Rooms(client); this.escalations = new Escalations(client); this.pay = new Pay(client, opts.payExecutor); this.errors = new Errors(client); this.identityLinks = new IdentityLinks(client); this.agent = new Agent(client); this.buzz = new Buzz(client); this.repos = new Repos(client); } project(id) { if (id !== undefined) { return new ScopedRun402(this, this.#client, id); } return this.#projectFromActive(); } async #projectFromActive() { const getter = this.#client.credentials.getActiveProject; if (!getter) { throw new LocalError("r.project() with no id requires a credential provider that implements getActiveProject(). Pass an explicit id, or use @run402/sdk/node.", "scoping client to project"); } const active = await getter.call(this.#client.credentials); if (!active) { throw new LocalError("No active project set. Call `r.projects.use(id)` (or `run402 projects use <project_id>`) to set one, or pass an explicit id to `r.project(id)`.", "scoping client to project"); } return new ScopedRun402(this, this.#client, active); } /** * Persist `id` as the active project (via `r.projects.use(id)`) AND return a * project-scoped sub-client in one call. Equivalent to: * * await r.projects.use(id); * return r.project(id); * * Note: this mutates the credential provider's persistent active-project * state (the keystore on Node). Concurrent CLI runs share that state. For * transient in-script scoping that does not change the user's CLI default, * use {@link project} instead. */ async useProject(id) { await this.projects.use(id); return this.project(id); } /** * Return an org-scoped sub-client with `id` pre-bound — the org analog of * {@link Run402.project}. Instance operations (`get`, `rename`, `members.*`, * `invites.*`, `audit`) drop their org-id argument. Synchronous: an org id is * always explicit (there is no "active org" fallback). Collection/identity * operations (`create`, `list`, `whoami`) live on {@link Run402.orgs}. */ org(id) { return new ScopedOrg(this.#client, id); } /** * Return a wallet-scoped sub-client with `address` pre-bound — the wallet * analog of {@link Run402.project}. Exposes `getLabel()` / `setLabel(label)` * without the address as a swappable positional. Lazy and synchronous (no key * or network access at construction). */ wallet(address) { return new ScopedWallet(this.#client, address); } /** * Identify the active wallet and project: `{ local_label, server_label, * address, activeProject }`. `local_label` is the local wallet/profile * selector (e.g. "kychon", or "default"); `server_label` is the server-side * display name (null when unknown/offline); `address` is the wallet address; * `activeProject` is the currently-selected project id (null if none). * * Degrades gracefully: providers that don't implement `getWalletIdentity` * (sandbox/session) still get `address` from `readWallet` when available. */ async whoami() { const creds = this.#client.credentials; const identity = creds.getWalletIdentity ? await creds.getWalletIdentity.call(creds) : null; let address = identity?.address ?? null; if (address == null && creds.readWallet) { address = (await creds.readWallet.call(creds))?.address ?? null; } const activeProject = creds.getActiveProject ? await creds.getActiveProject.call(creds) : null; return { local_label: identity?.name ?? null, server_label: identity?.label ?? null, address, activeProject: activeProject ?? null, }; } /** * Cumulative request-kernel observability for this SDK instance: round * trips, wire time, and bytes transferred, across every namespace call * this instance has made. Monotonic — never resets — and reflects only * THIS `Run402` instance (a fresh one, e.g. from a fresh `getSdk()` call, * starts back at zero). See `RUN402_TRACE` in `kernel.ts` for the matching * per-request stderr trace line. */ stats() { return this.#client.stats(); } /** * What this client may hand back to its caller. `returnSecrets` is false on * the `sandbox` surface, where every method that would return or consume a * one-time secret refuses with `SECRET_REQUIRES_CLI`. */ get capabilities() { return this.#client.capabilities; } } /** * Build a `FileSet` from a path-keyed record of byte sources. A passthrough * convenience: the SDK can consume the same shape whether you call this or * pass the literal directly. Useful for IDE autocomplete on the * `ContentSource` union and for keeping deploy specs declarative. * * @example * await (await r.project(project)).apply({ * project, * site: { replace: files({ * "index.html": "<h1>hi</h1>", * "logo.png": logoBytes, * "data.json": new Blob([JSON.stringify(d)], { type: "application/json" }), * })}, * }); */ export function files(record) { return record; } export function fromParts(...parts) { const cleaned = parts .filter((part) => part !== undefined && part !== null && String(part).trim() !== "") .map((part) => encodeURIComponent(String(part))); if (cleaned.length === 0) { throw new LocalError("idempotency.fromParts requires at least one non-empty part", "building idempotency key"); } return cleaned.join(":"); } /** * Factory wrapper equivalent to `new Run402(opts)`. Reads better in code-mode * sandbox examples: `const r = run402({ ... })`. */ export function run402(opts) { return new Run402(opts); } export { DEFAULT_CLIENT_CAPABILITIES } from "./kernel.js"; export { Run402Error, PaymentRequired, ProjectCredentialNotFound, ProjectNotFound, Unauthorized, NotAuthorizedError, ApiError, NetworkError, PaymentAttemptError, LocalError, SecretRequiresCliError, Run402DeployError, TransferFreezeError, StepUpRequiredError, WriteApprovalRequiredError, PROJECT_CREDENTIAL_ERROR_CODES, isRun402Error, isPaymentRequired, isProjectCredentialError, isProjectCredentialExpired, isProjectCredentialInvalid, isProjectCredentialNotFound, isProjectCredentialProjectMismatch, isProjectNotFound, isUnauthorized, isNotAuthorized, isApiError, isNetworkError, isPaymentAttemptError, isLocalError, isSecretRequiresCli, isDeployError, isTransferFreezeError, isStepUpRequired, isWriteApprovalRequired, isRetryableRun402Error, getQuotaScope, } from "./errors.js"; export { withRetry } from "./retry.js"; export { SECRET_RETURNING_METHODS } from "./secret-gate.js"; export { Run402Action } from "./actions.js"; export { defineConfig, dir, emailTrigger, file, nodeFunction, scheduleTrigger, sqlFile, } from "./config.js"; export { PROJECT_OPERATION_AUTH_CLASSIFICATIONS, projectOperationAuthClassification, } from "./project-auth-classification.js"; export { CI_SESSION_CREDENTIALS, createCiSessionCredentials, githubActionsCredentials, isCiSessionCredentials, } from "./ci-credentials.js"; export { GRANT_KEY_CREDENTIALS, GRANT_KEY_ENV, grantKeyFromEnv, isGrantKeyCredentials, } from "./grant-key-credentials.js"; export * from "./app-up.js"; export { CONTROL_PLANE_SESSION_CREDENTIALS, controlPlaneSessionCredentials, isControlPlaneSessionCredentials, } from "./control-plane-credentials.js"; export { EMPTY_STATIC_MANIFEST_METADATA, ROUTE_HTTP_METHODS, buildDeployResolveSummary, isDeployResolveRouteHit, isDeployResolveStaticHit, normalizeDeployResolveRequest, normalizeStaticManifestMetadata, summarizeDeployResult, } from "./namespaces/deploy.types.js"; export { Ci, CI_AUDIENCE, CI_BINDING_REVOKED_ERROR, CI_GITHUB_ACTIONS_ISSUER, CI_GITHUB_ACTIONS_PROVIDER, DEFAULT_CI_DELEGATION_CHAIN_ID, V1_CI_ALLOWED_ACTIONS, V1_CI_ALLOWED_EVENTS_DEFAULT, assertCiDeployableSpec, buildCiDelegationResourceUri, buildCiDelegationStatement, isCiBindingRevoked, normalizeCiRouteScopes, normalizeCiDelegationValues, validateCiNonce, validateCiRouteScope, validateCiSubjectMatch, } from "./namespaces/ci.js"; export { ScopedRun402 } from "./scoped.js"; export { Transfers } from "./namespaces/transfers.js"; export { Deploy } from "./namespaces/deploy.js"; export { FunctionRunTerminalError, FunctionRuns, classifyFunctionLogLine } from "./namespaces/functions.js"; export { Session } from "./namespaces/session.js"; export { WriteApproval } from "./namespaces/write-approval.js"; export { Me } from "./namespaces/me.js"; export { Orgs, ScopedOrg, OrgMembers, OrgInvites, OrgAdopt } from "./namespaces/org.js"; export { Grants } from "./namespaces/grants.js"; export { Events } from "./namespaces/events.js"; export { Rooms, ScopedRoom } from "./namespaces/rooms.js"; export { Escalations } from "./namespaces/escalations.js"; export { waitFor } from "./wait.js"; export { Errors } from "./namespaces/errors.js"; export { Vouchers } from "./namespaces/vouchers.js"; export { Pay, PaymentBuyerError, PaymentPolicyError, DEFAULT_PAYMENT_MAX_USD_MICROS, X402_COMMERCE_RESULT_SCHEMA_VERSION, X402_EVIDENCE_STATUSES, X402_GATEWAY_AVAILABILITY_ERROR_CODE, X402_MUTATION_STATES, X402_PAYMENT_POLICY_ERROR_CODES, X402_RECOVERY_ACTIONS, RUN402_PENDING_CLASSIFIER_VERSION, isPaymentBuyerError, isPaymentPolicyError, isTrustedRun402PaymentUrl, isTrustedRun402PendingResponse, payFetchResultToJson, } from "./namespaces/pay.js"; export { Archives } from "./namespaces/archives.js"; export { Snapshots } from "./namespaces/snapshots.js"; export { Branches } from "./namespaces/branches.js"; export { IdentityLinks, NostrIdentityLinks } from "./namespaces/identity-links.js"; export { Agent, AgentLightningWallets } from "./namespaces/agent.js"; export { Buzz, BuzzHumanAdoptions, BuzzHumanAdoptionOffers, BuzzCommunityInstallations, BuzzAgentEnrollments, BuzzNotifications } from "./namespaces/buzz.js"; export { ScopedWallet } from "./namespaces/wallets.js"; // vault (r402s/v0) — the crypto core is SDK code with a public API (task 5.0 // layering: the CLI/MCP are thin shims over these). Isomorphic: WebCrypto + // noble + @hpke/core, no I/O. The keystore + creation journal live under // `@run402/sdk/node`. export * from "./namespaces/vault.crypto.js"; export { Repos, vaultRemoteUrl, vaultRemoteUrlForRepo, parseVaultRemoteUrl, vaultRemoteAddressForm, vaultSlugReleasedInfo, VAULT_LOSS_WARNING_THRESHOLDS, vaultLossWarningTrip, vaultLossWarningTripped, vaultLossWarningMessage, vaultUnmirroredFinding, vaultDegradedReadNote, handoffVaultFromWire, handoffMembershipFromWire, } from "./namespaces/repos.js"; export { normalizeEdgeEvidence, mergeEdgeVerification } from "./namespaces/edge-evidence.js"; export { RestPermissionDenied } from "./rest-diagnostics.js"; //# sourceMappingURL=index.js.map