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.
377 lines • 11.6 kB
TypeScript
/**
* The secret gate: every SDK method whose result carries a one-time secret the
* caller would otherwise receive (a grant key, a Handoff or Invite Key, a Room
* Invite Key, project credentials, a private key, a Lightning pairing, a
* sign-in session or write-approval token), or whose input IS such a bearer
* secret, calls {@link gateSecret} as its first statement. On a client whose
* `capabilities.returnSecrets` is false — the `sandbox` surface an MCP `run`
* snippet executes on — that call throws `SECRET_REQUIRES_CLI` before any
* request, naming the exact CLI command for the same operation. On every
* other surface it is a no-op.
*
* The gate is the method itself, keyed on a client capability: there is no
* tool-name denylist and no path filter anywhere else, so every future door
* that builds a `sandbox` client inherits it for free.
*
* {@link SECRET_RETURNING_METHODS} is the registry: one entry per gated
* method (by its dotted path from the client root), with the command builder
* and, for a method that carries a secret only when a particular option is
* supplied, the predicate that says so. `sdk/src/node/secret-gate.test.ts`
* owns the inventory: it fails when a method's types carry a secret-named
* field and no entry names it, and when a registered method reaches the
* network on a `sandbox` client.
*
* A command never embeds a secret value: where the input is the secret, the
* command carries its placeholder (`<kgh1_…>`), never the key.
*/
import type { Client } from "./kernel.js";
type Args = any[];
export interface SecretGateEntry {
/** The exact CLI command line for the same operation, built from the call's own arguments. */
command: (...args: Args) => string;
/** When present, the call is gated only when this returns true (the secret-bearing option was supplied). */
when?: (...args: Args) => boolean;
/** Why the operation belongs to the CLI; defaults to the generic one-time-secret sentence. */
why?: string;
}
/**
* Every gated method, by its dotted path from the client root. The command is
* the CLI line for the same operation; the drift test calls each one on a
* `sandbox` client and requires the refusal before any request.
*/
export declare const SECRET_RETURNING_METHODS: {
"grants.create": {
when: (_projectId: unknown, input: unknown) => boolean;
command: (projectId: unknown, input: unknown) => string;
why: string;
};
"grants.createKey": {
command: (projectId: unknown) => string;
why: string;
};
"grants.rotateKey": {
command: (projectId: unknown, keyId: unknown) => string;
why: string;
};
"repos.handoff": {
command: (opts: unknown) => string;
};
"repos.invite": {
command: (opts: unknown) => string;
};
"repos.resume": {
command: () => string;
why: string;
};
"repos.join": {
command: () => string;
why: string;
};
"rooms.invite": {
command: (orgId: unknown, roomKey: unknown) => string;
};
"rooms.join": {
command: () => string;
why: string;
};
"projects.provision": {
command: (opts: unknown) => string;
why: string;
};
"projects.list": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"projects.info": {
command: (id: unknown) => string;
why: string;
};
"projects.keys": {
command: (id: unknown) => string;
why: string;
};
"credentials.projectKeys.import": {
command: (projectId: unknown) => string;
why: string;
};
"credentials.projectKeys.export": {
command: (projectId: unknown) => string;
why: string;
};
"credentials.issue": {
command: (projectId: unknown, input: unknown) => string;
why: string;
};
"credentials.rotate": {
command: (projectId: unknown, credentialId: unknown) => string;
why: string;
};
"credentials.mintToken": {
command: (projectId: unknown, opts: unknown) => string;
why: string;
};
"apps.fork": {
command: (opts: unknown) => string;
why: string;
};
"branches.create": {
command: (projectId: unknown) => string;
why: string;
};
"admin.transfers.initiate": {
when: (input: unknown) => boolean;
command: (input: unknown) => string;
why: string;
};
"admin.transfers.accept": {
command: (transferId: unknown) => string;
why: string;
};
"admin.rotateWebhookSecret": {
command: () => string;
why: string;
};
"wallets.create": {
command: (name: unknown) => string;
why: string;
};
"wallets.import": {
command: (name: unknown) => string;
why: string;
};
"agent.lightningWallet.mint": {
command: () => string;
why: string;
};
"agent.lightningWallet.get": {
command: () => string;
why: string;
};
"agent.lightningWallet.waitForActive": {
command: () => string;
why: string;
};
init: {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"actions.run": {
when: (input: unknown) => boolean;
command: (input: unknown) => "run402 projects provision" | "run402 up";
why: string;
};
"actions.up": {
command: () => string;
why: string;
};
"session.exchangeCliToken": {
command: () => string;
why: string;
};
"session.devicePoll": {
command: () => string;
why: string;
};
"session.verifyEmail": {
command: () => string;
why: string;
};
"session.passkeyVerify": {
command: () => string;
why: string;
};
"session.consumeRecoveryCode": {
command: () => string;
why: string;
};
"session.whoami": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"session.refresh": {
command: () => string;
why: string;
};
"session.revoke": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"session.enrollPasskeyOptions": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"session.enrollPasskeyVerify": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"session.stepUpOptions": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"session.stepUpVerify": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"session.issueRecoveryCodes": {
command: () => string;
why: string;
};
"session.listAuthenticators": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"session.revokeAuthenticator": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"session.sourceAccessWrappers": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"session.sourceAccessRecoveryBundle": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"writeApproval.requestChallenge": {
command: () => string;
why: string;
};
"writeApproval.exchangeClaimCode": {
command: () => string;
why: string;
};
"me.overview": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"me.status": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"orgs.adopt.challenge": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"orgs.adopt.submit": {
when: (opts: unknown) => boolean;
command: () => string;
why: string;
};
"admin.channels.connectTelegram": {
when: (_opts: unknown, proofs: unknown) => boolean;
command: () => string;
why: string;
};
"admin.channels.revokeTelegram": {
when: (_id: unknown, proofs: unknown) => boolean;
command: (id: unknown) => string;
why: string;
};
"admin.rules.create": {
when: (_i: unknown, proofs: unknown) => boolean;
command: () => string;
why: string;
};
"admin.rules.update": {
when: (_id: unknown, _p: unknown, proofs: unknown) => boolean;
command: () => string;
why: string;
};
"admin.rules.delete": {
when: (_id: unknown, proofs: unknown) => boolean;
command: (id: unknown) => string;
why: string;
};
"admin.setNotificationPreferences": {
when: (_p: unknown, proofs: unknown) => boolean;
command: () => string;
why: string;
};
"auth.verifyMagicLink": {
command: (projectId: unknown) => string;
why: string;
};
"auth.verify": {
command: (projectId: unknown) => string;
why: string;
};
"auth.verifyEmailCode": {
command: (projectId: unknown, opts: unknown) => string;
why: string;
};
"auth.setUserPassword": {
command: (projectId: unknown) => string;
why: string;
};
"auth.setPassword": {
command: (projectId: unknown) => string;
why: string;
};
"auth.createPasskeyRegistrationOptions": {
command: (projectId: unknown) => string;
why: string;
};
"auth.verifyPasskeyRegistration": {
command: (projectId: unknown) => string;
why: string;
};
"auth.verifyPasskeyLogin": {
command: (projectId: unknown) => string;
why: string;
};
"auth.listPasskeys": {
command: (projectId: unknown) => string;
why: string;
};
"auth.deletePasskey": {
command: (projectId: unknown) => string;
why: string;
};
"live.changes": {
when: (_projectId: unknown, opts: unknown) => boolean;
command: (projectId: unknown, opts: unknown) => string;
why: string;
};
"live.subscribe": {
when: (_projectId: unknown, opts: unknown) => boolean;
command: (projectId: unknown, opts: unknown) => string;
why: string;
};
"escalations.ackWithToken": {
command: () => string;
why: string;
};
"ci.exchangeToken": {
command: () => string;
why: string;
};
};
export type SecretReturningMethod = keyof typeof SECRET_RETURNING_METHODS;
/** Dotted path → entry, typed loosely for callers that look methods up by string. */
export declare const SECRET_GATE_REGISTRY: Readonly<Record<string, SecretGateEntry>>;
/**
* Refuse this call before any request when the client may not return
* secrets. The first statement of every registered method. The command is
* built only on refusal, so the check costs nothing on the permissive path.
*/
export declare function gateSecret(client: {
readonly capabilities?: Readonly<Client["capabilities"]>;
assertSecretReturn?: Client["assertSecretReturn"];
}, method: SecretReturningMethod, ...args: Args): void;
export {};
//# sourceMappingURL=secret-gate.d.ts.map