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.
219 lines • 10.6 kB
TypeScript
import type { Client } from "../kernel.js";
import { Run402Error, type NextAction } from "../errors.js";
export declare const DEFAULT_PAYMENT_MAX_USD_MICROS = 100000;
export declare const X402_COMMERCE_RESULT_SCHEMA_VERSION: "x402-commerce-result.v1";
export declare const X402_PAYMENT_POLICY_ERROR_CODES: readonly ["MERCHANT_RECEIPT_REQUIRED", "MERCHANT_RECEIPT_UNAVAILABLE"];
export declare const X402_GATEWAY_AVAILABILITY_ERROR_CODE: "MERCHANT_EVIDENCE_UNAVAILABLE";
export declare const X402_MUTATION_STATES: readonly ["not_started", "committed", "unknown"];
export declare const X402_RECOVERY_ACTIONS: readonly ["retry", "reconcile_payment"];
export interface PayFetchOptions {
/** Maximum atomic USD units this call may authorize. Defaults to 100,000 ($0.10). */
maxUsdMicros?: number;
/** Forwarded as `Idempotency-Key` for key-deduplicated paid HTTP surfaces. */
idempotencyKey?: string;
/**
* Require a verified wallet-rooted merchant offer before authorizing
* payment and a matching verified receipt after settlement.
*/
requireReceipt?: boolean;
/**
* Lightning only: refuse an `lnbtc` payment whose invoice plus routing
* headroom exceeds this many sats. Absent, the rail's per-call ceiling applies.
*/
maxSats?: number;
/**
* Lightning only: pay the `lnbtc` entry with this Nostr Wallet Connect
* pairing instead of the configured wallet, on whichever network its node
* is on. A bearer secret: the CLI reads it from a file or stdin, and the MCP
* sandbox refuses it (`SECRET_REQUIRES_CLI`).
*/
lightningPairing?: string;
}
export declare const X402_EVIDENCE_STATUSES: readonly ["verified", "absent", "invalid", "untrusted", "unavailable"];
export type PaymentEvidenceStatus = (typeof X402_EVIDENCE_STATUSES)[number];
export interface PaymentNextAction extends NextAction {
type: "retry" | "reconcile_payment";
why: string;
request?: "repeat_identical";
reusePayer?: true;
reuseIdempotencyKey?: true;
}
export interface PaymentRawEvidence {
offer: unknown | null;
merchantReceipt: unknown | null;
signerAuthorization: unknown | null;
/** MPP only: the seller's decoded `Payment-Receipt` (`{ method, reference, status, timestamp }`). */
protocolReceipt?: unknown | null;
}
/** The payment protocol that paid, and its scheme or method. */
export type PaymentProtocol = "x402" | "mpp";
export interface PaymentReceipt {
protocol: PaymentProtocol;
/** x402 scheme (`exact`) or MPP method (`tempo`). */
method: "exact" | "tempo";
network: string;
paymentId: string | null;
amountUsdMicros: number;
/** Lightning only: the invoice amount in millisatoshis (the USD amount is the seller's, not reported). */
amountMsat?: number;
asset: string;
payer: string | null;
payTo: string;
transaction: string;
resourceUrl: string;
settlement: {
status: PaymentEvidenceStatus;
};
fundsMoved: PaymentFundsMoved;
deduplicated: boolean;
delivery: {
status: "fulfilled" | "failed" | "unknown";
replay: boolean;
};
offer: {
status: PaymentEvidenceStatus;
resourceUrl: string | null;
validUntil: string | null;
};
merchantReceipt: {
status: PaymentEvidenceStatus;
claim: "service_delivered" | null;
issuedAt: string | null;
};
signerRelationship: {
kind: "direct" | "delegated" | "unverified" | null;
merchantRoot: string | null;
signer: string | null;
authorizationExpiresAt: string | null;
};
policy: {
requireReceipt: boolean;
status: "satisfied" | "unsatisfied" | "not_required";
};
evidence: PaymentRawEvidence;
}
export type PayFetchOutcome = "not_required" | "settled" | "already_settled";
export interface PayFetchResult {
/** The upstream response. The SDK never consumes its body. */
response: Response;
/** On-chain receipt, or null when no payment was needed / no transaction reference is available. */
payment: PaymentReceipt | null;
outcome: PayFetchOutcome;
/** True for a re-presented proof or a key-deduplicated upstream result. */
replay: boolean;
/** Stable Run402 tenant-payment identity when the target supplied one. */
paymentId?: string | null;
/** Whether this HTTP request reused an existing Run402 payment identity. */
deduplicated?: boolean | null;
/** Funds movement initiated by this HTTP attempt, when declared by Run402. */
fundsMoved?: PaymentFundsMoved | null;
/** Tenant delivery state for this attempt. */
delivery?: "first" | "replay" | "none" | null;
/** Confirmed settlement time supplied by Run402. */
settledAt?: string | null;
/** Durable intent state when the request is a status-bearing replay. */
intentState?: string | null;
/** Canonical recovery actions. Never recommends a second payment. */
nextActions?: PaymentNextAction[];
}
export declare function payFetchResultToJson(result: PayFetchResult, body: unknown): Record<string, unknown>;
export type PaymentFundsMoved = boolean | "unknown";
export type PaymentBuyerErrorCode = "PAYMENT_EXCEEDS_MAX" | "PAYMENT_WALLET_UNFUNDED" | "PAYMENT_DEPENDENCY_MISSING" | "PAYMENT_NETWORK_UNSUPPORTED" | "PAYMENT_INTENT_PENDING" | "PAYMENT_DESTINATION_DRAINING" | "PAYMENT_INTENT_DESTINATION_CHANGED" | "PAYMENT_INTENT_FENCE_EXPIRED" | "PAYMENT_AUTHORIZATION_LIFETIME_EXCEEDED" | "PAYMENT_CALLER_IDENTITY_NOT_ACTIVE" | "IDEMPOTENCY_KEY_REUSED" | "IDEMPOTENCY_KEY_INVALID" | "IDEMPOTENCY_KEY_PAYER_REQUIRED" | "PAYMENT_SETTLEMENT_FAILED" | "MERCHANT_RECEIPT_REQUIRED" | "MERCHANT_RECEIPT_UNAVAILABLE";
export interface PayResponseMetadata {
paymentId: string | null;
deduplicated: boolean | null;
fundsMoved: PaymentFundsMoved | null;
delivery: "first" | "replay" | "none" | null;
settledAt: string | null;
intentState: string | null;
}
/** Structured local failure from {@link Pay.fetch}. */
export declare class PaymentBuyerError extends Run402Error {
readonly kind: "payment_buyer_error";
readonly code: PaymentBuyerErrorCode;
readonly fundsMoved: PaymentFundsMoved;
readonly paymentId: string | null;
readonly intentState: string | null;
readonly delivery: "first" | "replay" | "none" | null;
readonly deduplicated: boolean | null;
readonly settledAt: string | null;
readonly cause?: unknown;
constructor(init: {
code: PaymentBuyerErrorCode;
message: string;
fundsMoved: PaymentFundsMoved;
details?: Record<string, unknown>;
nextActions: NextAction[];
retryable?: boolean;
safeToRetry?: boolean;
cause?: unknown;
status?: number | null;
body?: Record<string, unknown>;
});
toJSON(): Record<string, unknown>;
}
/**
* A receipt policy failed after a paid response was received. The original
* response and commerce result remain available for reconciliation.
*/
export declare class PaymentPolicyError extends PaymentBuyerError {
readonly response: Response;
readonly result: PayFetchResult;
readonly mutationState: "not_started" | "committed" | "unknown";
readonly safeToRetry: boolean;
readonly nextActions: PaymentNextAction[];
constructor(init: {
response: Response;
result: PayFetchResult;
message: string;
fundsMoved: PaymentFundsMoved;
mutationState: "not_started" | "committed" | "unknown";
safeToRetry: boolean;
nextActions: PaymentNextAction[];
});
}
export declare function isPaymentBuyerError(error: unknown): error is PaymentBuyerError;
export declare function isPaymentPolicyError(error: unknown): error is PaymentPolicyError;
export type PayExecutor = (url: string, init: RequestInit | undefined, options: Required<Pick<PayFetchOptions, "maxUsdMicros" | "requireReceipt">> & Pick<PayFetchOptions, "idempotencyKey" | "maxSats" | "lightningPairing">) => Promise<PayFetchResult>;
/** Arbitrary-URL buyer namespace. Node supplies the x402 executor; isomorphic callers may inject one. */
export declare class Pay {
private readonly client;
private readonly executor?;
constructor(client: Client, executor?: PayExecutor | undefined);
fetch(url: string | URL, init?: RequestInit, options?: PayFetchOptions): Promise<PayFetchResult>;
}
export declare function merchantReceiptRequiredError(details?: Record<string, unknown>): PaymentBuyerError;
export declare function paymentExceedsMaxError(challengedAmountUsdMicros: number, maxUsdMicros: number): PaymentBuyerError;
export declare function walletUnavailableError(details?: Record<string, unknown>): PaymentBuyerError;
/**
* The paid stack is an OPTIONAL peer set, so a consumer can legitimately be
* unable to pay while holding a perfectly funded wallet. Reporting that as
* PAYMENT_WALLET_UNFUNDED sends the caller to fund an already-funded wallet —
* an unattended agent then loops between `init` (reports funded) and the
* payment (reports unfunded). The remedy is an install, so say so.
*/
export declare function paidStackUnavailableError(missingPackages: readonly string[], details?: Record<string, unknown>): PaymentBuyerError;
export declare function responseSignalsReplay(response: Response, inspect: boolean): Promise<boolean>;
/** Parse platform-owned payment response headers without consuming the response body. */
export declare function payResponseMetadata(response: Response): PayResponseMetadata;
export declare const RUN402_PENDING_CLASSIFIER_VERSION = 1;
/** Exact DNS-label classifier for Run402-owned tenant and deployment hosts. */
export declare function isTrustedRun402PaymentUrl(input: string | URL, options?: {
allowTestLocalhost?: boolean;
}): boolean;
/**
* Trust a pending result only at the complete signed-response boundary. The
* caller supplies `paymentBearing` and `redirectsDisabled` from its executor;
* shape alone is intentionally insufficient for arbitrary/custom domains.
*/
export declare function isTrustedRun402PendingResponse(input: {
requestUrl: string;
response: Response;
envelope: Record<string, unknown> | null;
paymentBearing: boolean;
redirectsDisabled: boolean;
allowTestLocalhost?: boolean;
}): boolean;
export declare function readPaymentErrorEnvelope(response: Response): Promise<Record<string, unknown> | null>;
export declare function gatewayPaymentBuyerError(response: Response, envelope: Record<string, unknown>): PaymentBuyerError | null;
//# sourceMappingURL=pay.d.ts.map