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.
166 lines • 7.88 kB
TypeScript
/**
* Request kernel — the one place in the SDK that touches `fetch`.
*
* Isomorphic: uses only platform globals, no Node-only APIs. The kernel is
* safe to execute inside a V8 isolate where `fs`, `child_process`, and
* `process` are absent.
*
* Failure translation: maps HTTP status codes and network errors to the
* appropriate {@link Run402Error} subclass. Callers never see `undefined`
* or a response-shaped error value — they either get the parsed body as T
* or an exception.
*/
import type { AuthRequestMeta, CredentialsProvider, ProjectKeys } from "./credentials.js";
export interface KernelConfig {
apiBase: string;
fetch: typeof globalThis.fetch;
credentials: CredentialsProvider;
clientMetadata?: Run402ClientMetadata | false;
/** What this client may do beyond plain requests. Defaults to {@link DEFAULT_CLIENT_CAPABILITIES}. */
capabilities?: Partial<ClientCapabilities>;
/**
* Per-client observability accumulator, mutated by every request made
* through this kernel config. Set by {@link buildClient} — a fresh
* {@link ClientStats} object per `Run402` instance, monotonic (no reset)
* for the instance's lifetime. Exposed to callers via `Client.stats()` /
* `Run402.stats()`. Not meant to be set directly by SDK consumers.
* @internal
*/
stats?: ClientStats;
}
/**
* What a client is allowed to hand back to its caller. Carried on every
* {@link Client}; namespaces consult it before doing something only some
* callers may receive.
*/
export interface ClientCapabilities {
/**
* Whether a method may return (or consume) a one-time secret the SDK does
* not persist itself: a grant key, a Handoff or Invite Key, project
* credentials, a private key, a Lightning pairing. `true` for the `cli`,
* `sdk`, and `mcp` surfaces; `false` for `sandbox` (an MCP `run` snippet),
* where such a method throws `SECRET_REQUIRES_CLI` before any request.
*/
returnSecrets: boolean;
}
/** Capabilities a client has when the caller names none. */
export declare const DEFAULT_CLIENT_CAPABILITIES: Readonly<ClientCapabilities>;
/** Resolve a partial capability set against the defaults. */
export declare function resolveClientCapabilities(partial?: Partial<ClientCapabilities>): ClientCapabilities;
export interface Run402ClientMetadata {
surface?: string;
version?: string;
sdkVersion?: string;
}
export interface RequestOptions {
method?: string;
headers?: Record<string, string>;
body?: unknown;
/** Send body as a raw string (e.g. `text/plain` SQL) or bytes, skipping JSON.stringify. */
rawBody?: string | Uint8Array;
/** Include credential headers from `credentials.getAuth(path)`. Default: true. */
withAuth?: boolean;
/** Optional write capability + target, passed to `getAuth` for write-approval matching. */
authMeta?: AuthRequestMeta;
/** Short verb phrase attached to thrown errors (e.g. "provisioning project"). */
context: string;
/**
* Logical retry attempt number, surfaced verbatim in the `RUN402_TRACE`
* line's `attempt=<n>` field. Default 1 — the kernel itself never retries
* a request; a caller that re-issues the same logical request after a
* higher-level retry (e.g. a safe release-race replan) may pass an
* incrementing value so the trace reads as one logical operation's history
* rather than unrelated single-attempt calls.
*/
attempt?: number;
}
/** Cumulative request-kernel observability for one SDK instance (`Run402.stats()`). Monotonic — never resets. */
export interface ClientStats {
/** Number of fetch calls made (successful or not). */
round_trips: number;
/** Summed wall-clock time spent in fetch + body read, in milliseconds. */
wire_ms: number;
/** Summed request body bytes sent, where knowable. */
bytes_up: number;
/** Summed response body bytes received (Content-Length when present, measured otherwise). */
bytes_down: number;
}
/**
* What the seller's `PAYMENT-RESPONSE` receipt says actually settled.
*
* OBSERVED, never inferred. `network` is the chain the payment landed on
* according to the settlement receipt — not a guess from local wallet config.
* That distinction is the point: a caller must be able to tell a real payment
* from a testnet one, and a buyer holding mainnet funds makes any config-derived
* guess wrong.
*/
export interface PaymentSettlement {
success: boolean;
network: string;
transaction: string;
payer: string | null;
}
export interface ResponseEnvelope<T = unknown> {
status: number;
body: T;
/**
* Present only when the response carried an x402 settlement receipt, i.e.
* this request actually moved money. Absent/`null` means no payment was made
* on this request — NOT that a payment failed.
*/
settlement?: PaymentSettlement | null;
}
/**
* Decode the `PAYMENT-RESPONSE` receipt if the response carries one.
*
* Deliberately total: a malformed or unexpected receipt yields `null` rather
* than throwing. A caller asking "what did I just pay?" must never have its
* SUCCESSFUL response turned into an error by a reporting concern.
*
* Strict receipt VALIDATION — matching the receipt against the challenge the
* buyer accepted — belongs to the paid-fetch buyer path, which does it. This is
* disclosure of what the seller reported, and is labelled as such.
*/
export declare function decodeSettlementReceipt(res: {
headers: {
get(name: string): string | null;
};
}): PaymentSettlement | null;
/** Internal client surface passed to each namespace. */
export interface Client {
/** API base URL, e.g. `https://api.run402.com`. Exposed for namespaces that need to compute derived URLs (e.g. REST endpoints). */
readonly apiBase: string;
request<T>(path: string, opts: RequestOptions): Promise<T>;
requestWithResponse<T>(path: string, opts: RequestOptions): Promise<ResponseEnvelope<T>>;
getProjectCredentials(id: string): Promise<ProjectKeys | null>;
/** @deprecated Use getProjectCredentials. */
getProject(id: string): Promise<ProjectKeys | null>;
/** The underlying credentials provider. Namespaces use this to access optional methods (saveProject, setActiveProject, ...). */
readonly credentials: CredentialsProvider;
/**
* The injected fetch (or default `globalThis.fetch`). Namespaces use this
* when they need to hit a non-gateway URL — e.g. an S3 presigned URL from
* a multipart upload, where auth + apiBase injection would be wrong.
*/
readonly fetch: typeof globalThis.fetch;
/** Cumulative observability for this client instance. See {@link ClientStats}. */
stats(): ClientStats;
/** What this client may hand back to its caller. See {@link ClientCapabilities}. */
readonly capabilities: Readonly<ClientCapabilities>;
/**
* Refuse, before any request, an operation whose result or input is a
* one-time secret when this client may not return secrets
* (`capabilities.returnSecrets === false`, the `sandbox` surface). Throws
* {@link SecretRequiresCliError} naming `command`, the exact CLI command
* line for the same operation; a no-op on every other surface.
*/
assertSecretReturn(opts: {
command: string;
why?: string;
}): void;
}
export declare function request<T>(kernel: KernelConfig, path: string, opts: RequestOptions): Promise<T>;
export declare function requestWithResponse<T>(kernel: KernelConfig, path: string, opts: RequestOptions): Promise<ResponseEnvelope<T>>;
export declare function buildClient(kernel: KernelConfig): Client;
export declare function clientMetadataHeaders(metadata: KernelConfig["clientMetadata"]): Record<string, string>;
//# sourceMappingURL=kernel.d.ts.map