@usethrottle/mcp 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib.ts","../src/server.ts","../../core-scopes/src/scopes.ts","../../core-scopes/src/events.ts","../../core-scopes/src/issuance.ts","../../action-catalog/src/actions.ts","../../action-catalog/src/triggers.ts","../../action-catalog/src/index.ts","../src/format.ts","../../errors/dist/index.js","../src/client.ts","../src/contract.ts","../src/docs.ts","../src/handlers.ts","../src/input.ts","../src/indexes.ts"],"sourcesContent":["/**\n * Library entry point for @usethrottle/mcp, distinct from the CLI bin\n * (src/index.ts). Consumed by the hosted remote MCP server (apps/server),\n * which builds one McpServer instance per HTTP session instead of once per\n * process — see docs/superpowers/specs/2026-08-01-remote-mcp-server-design.md.\n */\nexport {\n createServer,\n registerableActions,\n buildInstructions,\n VERSION,\n type RegistrationPolicy,\n type CreateServerOptions,\n} from './server';\nexport { ThrottleClient } from './client';\nexport type { Identity, HandlerContext } from './handlers';\nexport { loadDocsIndex, loadContractIndex } from './indexes';\nexport type { DocsIndex } from './docs';\nexport type { ContractIndex } from './contract';\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { actionsForChannel, canRunAction, type ActionDefinition } from '@core/action-catalog';\nimport type { ThrottleClient } from './client';\nimport type { ContractIndex } from './contract';\nimport type { DocsIndex } from './docs';\nimport { formatError, formatResult } from './format';\nimport { HANDLERS, type HandlerContext, type Identity } from './handlers';\nimport { fieldsToZodShape } from './input';\n\n// Injected by tsup from package.json (see tsup.config.ts). Under vitest there is\n// no define step, so `typeof` guards the ReferenceError and tests read a dev\n// marker rather than a stale hard-coded number.\ndeclare const __THROTTLE_MCP_VERSION__: string | undefined;\nexport const VERSION =\n typeof __THROTTLE_MCP_VERSION__ === 'string' ? __THROTTLE_MCP_VERSION__ : '0.0.0-dev';\n\nexport interface RegistrationPolicy {\n identity: Identity;\n allowWrites: boolean;\n allowLiveWrites: boolean;\n}\n\n/**\n * Which tools this session gets. Pure and exported so the policy is testable\n * without standing up a transport.\n *\n * Four independent gates, in order of how expensive it is to get them wrong:\n *\n * 1. **Implemented.** `0.1.0` ships the read/sandbox half; the catalog describes\n * the money writes before this package implements them.\n * 2. **Scope.** Delegated to the catalog's `canRunAction`, which uses the API's own\n * `hasScope`. A tool the credential cannot execute is not registered at all,\n * rather than failing at call time — the model never sees an affordance it\n * cannot use.\n * 3. **Intent.** Holding a write scope means the credential *may* write; it does\n * not mean the operator intended this session to. That is `--allow-writes`.\n * 4. **Blast radius.** Against a production credential, writes need\n * `--allow-live-writes` on top. Sandbox-only actions invert the rule: they are\n * free in a non-production environment and forbidden in production regardless\n * of flags.\n */\nexport function registerableActions(policy: RegistrationPolicy): ActionDefinition[] {\n const isProduction = policy.identity.environment.providerEnvironment === 'production';\n return actionsForChannel('mcp').filter((action) => {\n if (!HANDLERS[action.id]) return false;\n if (!canRunAction(policy.identity.scopes, action)) return false;\n if (action.kind === 'read') return true;\n if (action.sandboxOnly) return !isProduction;\n if (!policy.allowWrites) return false;\n return !isProduction || policy.allowLiveWrites;\n });\n}\n\n/**\n * The server's `instructions`, which most clients put in front of the model before\n * it picks a tool. Leads with the environment because the single most damaging\n * mistake an agent can make here is not knowing whether it is looking at live data.\n */\nexport function buildInstructions(\n identity: Identity,\n actions: ActionDefinition[],\n policy: { allowWrites: boolean; allowLiveWrites: boolean },\n): string {\n const isProduction = identity.environment.providerEnvironment === 'production';\n const where = [\n identity.workspace?.name ?? identity.workspace?.slug ?? 'unknown workspace',\n identity.application?.name ?? identity.application?.slug ?? null,\n ]\n .filter(Boolean)\n .join(' / ');\n\n // Sandbox seeding is a write, but announcing it as \"irreversible and\n // buyer-visible\" would teach the model to be cautious about the one tool that is\n // free — and, worse, imply this session can move money when it cannot.\n const liveWrites = actions.filter((a) => a.kind === 'write' && !a.sandboxOnly);\n const sandboxWrites = actions.filter((a) => a.kind === 'write' && a.sandboxOnly);\n const lines = [\n `Throttle MCP ${VERSION}. Connected to ${where}, environment \"${identity.environment.slug}\" (${\n isProduction ? 'PRODUCTION — live data' : 'non-production — not live data'\n }).`,\n '',\n 'Conventions:',\n '- Every tool is scoped to this one workspace/application/environment; there is no way to switch from inside a tool call. Call whoami if you need to state where you are.',\n '- List tools return { data, pagination }. When pagination.hasMore is true, pass pagination.cursor back as \"cursor\" rather than raising \"limit\".',\n '- Amounts are integer minor units (2500 = $25.00).',\n '- Throttle rejects snake_case on public request bodies. Before writing integration code, confirm shapes with describe_endpoint and check bodies with validate_payload instead of guessing field names.',\n '- API errors come back as text with a stable code. On insufficient_scopes, tell the user which scope to add — do not retry.',\n ];\n\n if (liveWrites.length === 0) {\n lines.push(\n `- This session is READ-ONLY for real data${\n policy.allowWrites\n ? ' (no write tools are available to this credential)'\n : ' — writes were not enabled'\n }. Say so plainly if asked to change something.`,\n );\n if (sandboxWrites.length > 0) {\n lines.push(\n `- ${sandboxWrites\n .map((a) => a.id)\n .join(', ')} may create data, but only in this non-production environment.`,\n );\n }\n } else {\n lines.push(\n `- Write tools are enabled (${liveWrites\n .map((a) => a.id)\n .join(', ')}). They are irreversible and some are buyer-visible. Confirm with the user before calling one.`,\n );\n }\n return lines.join('\\n');\n}\n\nexport interface CreateServerOptions extends RegistrationPolicy {\n client: ThrottleClient;\n contract: ContractIndex;\n docs: DocsIndex;\n}\n\nexport function createServer(options: CreateServerOptions): McpServer {\n const actions = registerableActions(options);\n const server = new McpServer(\n { name: 'throttle', version: VERSION },\n { instructions: buildInstructions(options.identity, actions, options) },\n );\n\n const ctx: HandlerContext = {\n client: options.client,\n identity: options.identity,\n contract: options.contract,\n docs: options.docs,\n };\n\n for (const action of actions) {\n const handler = HANDLERS[action.id]!;\n server.tool(\n action.id,\n describeForModel(action),\n fieldsToZodShape(action.input),\n async (args: Record<string, unknown>) => {\n try {\n const result = await handler(ctx, args ?? {});\n return { content: [{ type: 'text' as const, text: formatResult(result) }] };\n } catch (error) {\n return {\n content: [{ type: 'text' as const, text: formatError(error) }],\n isError: true,\n };\n }\n },\n );\n }\n\n return server;\n}\n\n/** Guardrails ride along in the description so they reach the model, not just the reviewer. */\nfunction describeForModel(action: ActionDefinition): string {\n const parts = [action.description];\n if (action.guardrails && action.guardrails.length > 0) {\n parts.push(`Constraints: ${action.guardrails.join(' ')}`);\n }\n return parts.join(' ');\n}\n","/** True when the granted scope set covers the required scope.\n * Rules: '*' covers all; exact match; write→read on the same resource;\n * NO cross-resource implication. */\nexport function hasScope(granted: readonly string[], required: string): boolean {\n if (granted.includes('*')) return true;\n if (granted.includes(required)) return true;\n const sep = required.lastIndexOf(':');\n if (sep === -1) return false;\n const resource = required.slice(0, sep);\n const action = required.slice(sep + 1);\n if (action === 'read' && granted.includes(`${resource}:write`)) return true;\n return false;\n}\n\nexport interface ScopeDef {\n id: string;\n resource: string;\n action: 'read' | 'write' | 'install';\n group: string;\n label: string;\n sensitive: boolean;\n staffOnly: boolean;\n publishableAllowed: boolean;\n extensionAllowed: boolean;\n implies: string[];\n}\n\ntype Opts = {\n sensitive?: boolean;\n staffOnly?: boolean;\n publishableAllowed?: boolean;\n extensionAllowed?: boolean;\n};\n\nconst REG: Record<string, ScopeDef> = {};\n\n/** Register one resource with the given actions, generating read/write defs.\n * `write` auto-implies `read` when a read action is present. */\nfunction add(\n group: string,\n resource: string,\n actions: Array<'read' | 'write'>,\n labels: { read?: string; write?: string },\n opts: Opts = {},\n) {\n const hasRead = actions.includes('read');\n for (const action of actions) {\n const id = `${resource}:${action}`;\n const implies = action === 'write' && hasRead ? [`${resource}:read`] : [];\n REG[id] = {\n id,\n resource,\n action,\n group,\n label: (action === 'read' ? labels.read : labels.write) ?? `${action} ${resource}`,\n sensitive: opts.sensitive ?? false,\n staffOnly: opts.staffOnly ?? false,\n // publishable defaults false; only the curated set below is true\n publishableAllowed: opts.publishableAllowed ?? false,\n // extension default true for commerce scopes; Taxonomy B passes false\n extensionAllowed: opts.extensionAllowed ?? true,\n implies,\n };\n }\n}\n\n// ── Taxonomy A — integration / commerce ──────────────────────────────\nadd('Orders', 'orders', ['read', 'write'], { read: 'View orders', write: 'Manage orders' });\n// Sales quotes (B2B proposals) — unrelated to shipping_quotes / quote tokens.\nadd('Quotes', 'quotes', ['read', 'write'], { read: 'View quotes', write: 'Manage quotes' });\nadd('Orders', 'order_cancellations', ['write'], { write: 'Cancel orders' });\nadd('Orders', 'order_returns', ['read', 'write'], { read: 'View returns', write: 'Process returns' });\n\nadd('Payments', 'payments', ['read', 'write'], { read: 'View payments', write: 'Create payments' });\nadd('Payments', 'payment_authorizations', ['write'], { write: 'Authorize payments' });\nadd('Payments', 'payment_captures', ['write'], { write: 'Capture payments' });\nadd('Payments', 'payment_refunds', ['read', 'write'], { read: 'View refunds', write: 'Refund payments' }, { sensitive: true });\nadd('Payments', 'payment_voids', ['write'], { write: 'Void payments' }, { sensitive: true });\nadd('Payments', 'payment_disputes', ['read', 'write'], { read: 'View disputes', write: 'Handle disputes' }, { sensitive: true });\nadd('Payments', 'payment_methods', ['read', 'write'], { read: 'View payment methods', write: 'Tokenize payment methods' }, { sensitive: true });\n\nadd('Customers', 'customers', ['read', 'write'], { read: 'View customers', write: 'Manage customers' });\nadd('Customers', 'customer_pii', ['read'], { read: 'View customer PII' }, { sensitive: true });\nadd('Customers', 'customer_addresses', ['read', 'write'], { read: 'View addresses', write: 'Manage addresses' });\nadd('Customers', 'customer_payment_methods', ['read', 'write'], { read: 'View stored cards', write: 'Manage stored cards' }, { sensitive: true });\n\nadd('Carts', 'carts', ['read', 'write'], { read: 'View carts', write: 'Manage carts' });\nadd('Carts', 'cart_items', ['read', 'write'], { read: 'View line items', write: 'Manage line items' });\nadd('Carts', 'checkout_sessions', ['read', 'write'], { read: 'View checkout sessions', write: 'Manage checkout sessions' });\n\nadd('Discounts', 'discounts', ['read', 'write'], { read: 'View discounts', write: 'Manage discounts' });\n\nadd('Subscriptions', 'subscriptions', ['read', 'write'], { read: 'View subscriptions', write: 'Manage subscriptions' });\nadd('Subscriptions', 'subscription_pauses', ['write'], { write: 'Pause/resume subscriptions' });\nadd('Subscriptions', 'subscription_cancellations', ['write'], { write: 'Cancel subscriptions' });\nadd('Subscriptions', 'subscription_usage', ['read', 'write'], { read: 'View subscription usage', write: 'Report subscription usage' }, { extensionAllowed: false });\n\nadd('Fulfillments', 'fulfillments', ['read', 'write'], { read: 'View fulfillments', write: 'Manage fulfillments' });\nadd('Fulfillments', 'fulfillment_shipments', ['write'], { write: 'Update shipments' });\nadd('Fulfillments', 'fulfillment_digital', ['read', 'write'], { read: 'View digital delivery', write: 'Manage digital delivery' });\nadd('Fulfillments', 'fulfillment_access', ['write'], { write: 'Manage access credentials' });\nadd('Fulfillments', 'fulfillment_services', ['write'], { write: 'Manage service fulfillment' });\n\nadd('Invoices / AR', 'invoices', ['read'], { read: 'View invoices & aging' });\nadd('Invoices / AR', 'invoice_payments', ['write'], { write: 'Mark invoices paid' }, { sensitive: true });\nadd('Invoices / AR', 'invoice_dunning', ['write'], { write: 'Send dunning notices' });\n\nadd('Shipping & Tax', 'shipping_tax', ['read', 'write'], { read: 'View shipping/tax config', write: 'Edit shipping/tax config' });\nadd('Shipping & Tax', 'shipping_tax_publications', ['write'], { write: 'Publish shipping/tax config' });\nadd('Shipping & Tax', 'shipping_quotes', ['write'], { write: 'Request shipping quotes' }, { publishableAllowed: true });\nadd('Shipping & Tax', 'tax_calculations', ['write'], { write: 'Calculate tax' }, { publishableAllowed: true });\nadd('Shipping & Tax', 'shipping_tax_quote_tokens', ['read', 'write'], { read: 'View quote tokens', write: 'Manage quote tokens' });\nadd('Shipping & Tax', 'shipping_tax_snapshots', ['write'], { write: 'Accept external snapshots' });\n\nadd('Connectors', 'connectors', ['read', 'write'], { read: 'View connectors', write: 'Manage connectors' });\nadd('Connectors', 'connector_activations', ['write'], { write: 'Activate/deactivate connectors' });\n\nadd('Webhooks & Events', 'webhooks', ['read', 'write'], { read: 'View webhooks', write: 'Manage webhooks' });\nadd('Webhooks & Events', 'webhook_deliveries', ['read', 'write'], { read: 'View deliveries', write: 'Retry deliveries' });\nadd('Webhooks & Events', 'events', ['read'], { read: 'View events' });\nadd('Webhooks & Events', 'audit_logs', ['read'], { read: 'View audit log' });\n\nadd('Applications', 'applications', ['read', 'write'], { read: 'View applications', write: 'Manage applications' });\n\nadd('Workspace', 'merchant', ['read', 'write'], { read: 'View workspace settings', write: 'Edit workspace settings' });\nadd('Workspace', 'embed_config', ['read', 'write'], { read: 'View embed config', write: 'Edit embed config' });\nadd('Workspace', 'branding', ['write'], { write: 'Upload branding assets' });\n\n// ── Taxonomy B — human / admin (extensionAllowed: false) ─────────────\nconst HUMAN: Opts = { extensionAllowed: false };\nadd('Team', 'team_members', ['read', 'write'], { read: 'View members', write: 'Manage members' }, HUMAN);\nadd('Team', 'team_invites', ['read', 'write'], { read: 'View invites', write: 'Manage invites' }, HUMAN);\nadd('Platform billing', 'billing', ['read', 'write'], { read: 'View billing', write: 'Manage subscription' }, HUMAN);\nadd('Platform billing', 'billing_payment_methods', ['read', 'write'], { read: 'View billing cards', write: 'Manage billing cards' }, HUMAN);\nadd('Email', 'email_templates', ['read', 'write'], { read: 'View email templates', write: 'Edit email templates' }, HUMAN);\nadd('Email', 'email_settings', ['read', 'write'], { read: 'View email settings', write: 'Edit email settings' }, HUMAN);\nadd('Go-live', 'go_live', ['read', 'write'], { read: 'View go-live status', write: 'Submit go-live' }, HUMAN);\nadd('Partner', 'partner', ['read', 'write'], { read: 'View partner profile', write: 'Edit partner profile' }, HUMAN);\nadd('Partner', 'affiliates', ['read', 'write'], { read: 'View affiliates', write: 'Manage affiliates' }, HUMAN);\nadd('Notifications', 'notifications', ['write'], { write: 'Send notifications' }, HUMAN);\nadd('Notifications', 'preferences', ['read', 'write'], { read: 'View preferences', write: 'Edit preferences' }, HUMAN);\nadd('Integrations', 'integrations', ['read', 'write'], { read: 'View integrations', write: 'Manage integrations' }, HUMAN);\nadd('Support', 'support', ['read', 'write'], { read: 'View support tickets', write: 'Manage support tickets' }, HUMAN);\nadd('Admin (staff)', 'admin', ['read', 'write'], { read: 'View admin data', write: 'Perform admin actions' }, { sensitive: true, staffOnly: true, extensionAllowed: false });\n\n// Extensions management — admin taxonomy: extensions must never manage other extensions.\n// 'read' and 'write' are auto-generated by add(); write→read implication is handled by add().\n// 'install' is a CUSTOM action registered manually — it is independent: write does NOT imply install.\nadd('Extensions', 'extensions', ['read', 'write'],\n { read: 'View extensions & installs', write: 'Author, version & publish extensions' }, HUMAN);\n// 'install' is not auto-generated; add() only handles 'read'/'write'. Register it directly.\nREG['extensions:install'] = {\n id: 'extensions:install', resource: 'extensions', action: 'install',\n group: 'Extensions', label: 'Install, configure & manage extensions',\n sensitive: false, staffOnly: false, publishableAllowed: false, extensionAllowed: false, implies: [],\n};\n\n// ── wildcard ──────────────────────────────────────────────────────────\nREG['*'] = {\n id: '*', resource: '*', action: 'write', group: 'Global', label: 'Full access',\n sensitive: true, staffOnly: false, publishableAllowed: false, extensionAllowed: false, implies: [],\n};\n\nexport const SCOPE_REGISTRY: Readonly<Record<string, ScopeDef>> = REG;\nexport type ScopeId = string;\nexport const ALL_SCOPE_IDS: readonly string[] = Object.keys(REG);\n\n/** group label → ordered scope ids (for the picker + docs). */\nexport const SCOPE_GROUPS: Record<string, string[]> = (() => {\n const out: Record<string, string[]> = {};\n for (const def of Object.values(REG)) {\n if (def.id === '*') continue;\n (out[def.group] ??= []).push(def.id);\n }\n return out;\n})();\n","// packages/core-scopes/src/events.ts\n/** Canonical event catalog. Keep in sync with the webhook-types union\n * (a compile-time assertion in webhook-types guards this — see Task 3.3). */\nexport const ALL_EVENT_TYPES = [\n // cart\n 'cart.created', 'cart.updated', 'cart.item_added', 'cart.item_updated',\n 'cart.item_removed', 'cart.shipping_selected', 'cart.shipping_cleared',\n 'cart.discount_applied', 'cart.discount_removed', 'cart.tax_recomputed',\n 'cart.checkout_started', 'cart.converted', 'cart.abandoned', 'cart.merged',\n // checkout\n 'checkout.session.created', 'checkout.session.completed',\n // order\n 'order.created', 'order.updated', 'order.completed', 'order.cancelled',\n 'order.closed', 'order.sync_failed', 'order.sync_conflict',\n // return / RMA (#690)\n 'return.created', 'return.updated',\n // quote (sales quotes). All nine of spec §10.1 — quote.expired was emitted\n // by the expiry cron from the day it shipped but never registered here, so\n // subscribing to it 400'd and it could never be delivered.\n 'quote.requested', 'quote.proposed', 'quote.viewed', 'quote.comment_added',\n 'quote.revision_requested', 'quote.declined', 'quote.accepted', 'quote.converted',\n 'quote.expired',\n // payment\n // payment.authorization_failed / capture_failed / void_failed removed 2026-07-05:\n // no live code path emits them (Gr4vy adapter not wired into PaymentService).\n 'payment.pending', 'payment.authorized',\n 'payment.captured', 'payment.failed', 'payment.voided',\n 'payment.refunded', 'payment.partially_refunded',\n 'payment.refund_failed', 'payment.vaulted', 'payment.disputed', 'payment.dispute_cleared',\n // fulfillment\n 'fulfillment.created', 'fulfillment.completed', 'fulfillment.cancelled',\n 'fulfillment.shipment.shipped', 'fulfillment.shipment.delivered',\n 'fulfillment.digital.delivered',\n // subscription\n 'subscription.created', 'subscription.activated', 'subscription.updated',\n 'subscription.plan_changed', 'subscription.plan_change_scheduled',\n 'subscription.paused', 'subscription.resumed', 'subscription.cancelled',\n 'subscription.renewed', 'subscription.past_due', 'subscription.payment_failed',\n 'subscription.create_failed', 'subscription.trial_blocked',\n 'subscription.backup_pm_used',\n // discount\n 'discount.applied', 'discount.removed',\n // customer\n 'customer.created', 'customer.updated', 'customer.deleted',\n 'customer.payment_method_added', 'customer.payment_method_removed',\n // invoice / AR\n 'invoice.past_due',\n // shipping & tax\n 'shipping_tax.provider_connection.unhealthy',\n // workspace / platform-billing\n 'workspace.payment_method.added', 'workspace.payment_method.removed',\n 'workspace.payment_method.default_changed', 'workspace.payment_method.backup_set',\n 'workspace.payment_method.backup_used', 'workspace.platform_charge.succeeded',\n 'workspace.platform_charge.failed', 'workspace.trial_expired',\n // NOTE: extension.* removed from the outbound event catalog (2026-07-05) —\n // they remain in-app + email notifications, not deliverable webhooks.\n] as const;\n\nexport type EventType = (typeof ALL_EVENT_TYPES)[number];\n\n/** Exact-match overrides take priority over prefix rules. */\nconst EVENT_SCOPE_OVERRIDES: Record<string, string> = {\n 'payment.refunded': 'payment_refunds:read',\n 'payment.partially_refunded': 'payment_refunds:read',\n 'payment.refund_failed': 'payment_refunds:read',\n 'payment.disputed': 'payment_disputes:read',\n 'payment.dispute_cleared': 'payment_disputes:read',\n 'fulfillment.digital.delivered': 'fulfillment_digital:read',\n};\n\n// Exact-match overrides (EVENT_SCOPE_OVERRIDES) take priority over these prefix rules. Add fine-grained event→scope mappings there, not here.\n/** Ordered longest-prefix-first so `checkout.session.` beats `checkout.`. */\nconst PREFIX_RULES: Array<[string, string]> = [\n ['checkout.session.', 'carts:read'],\n ['cart.', 'carts:read'],\n ['order.', 'orders:read'],\n ['quote.', 'quotes:read'],\n ['return.', 'order_returns:read'],\n ['payment.', 'payments:read'],\n ['customer.', 'customers:read'],\n ['subscription.', 'subscriptions:read'],\n ['fulfillment.', 'fulfillments:read'],\n ['discount.', 'discounts:read'],\n ['invoice.', 'invoices:read'],\n ['shipping_tax.', 'shipping_tax:read'],\n ['workspace.', 'billing:read'],\n ['extension.', 'merchant:read'],\n];\n\n/** Map an event type to the read scope required to subscribe/receive it. */\nexport function eventReadScope(type: string): string {\n if (EVENT_SCOPE_OVERRIDES[type]) return EVENT_SCOPE_OVERRIDES[type];\n for (const [prefix, scope] of PREFIX_RULES) {\n if (type.startsWith(prefix)) return scope;\n }\n throw new Error(`Unknown event type: ${type}`);\n}\n","// packages/core-scopes/src/issuance.ts\nimport { SCOPE_REGISTRY } from './scopes';\nimport { expandLegacyScopes } from './legacy';\n\nexport interface ValidationResult { ok: boolean; invalid: string[]; }\n\n/** Validate scopes requested for an API key.\n * - legacy scopes are expanded first (migration-window safety)\n * - sk_: every scope must exist + not be staffOnly; '*' allowed\n * - pk_: every scope must be publishableAllowed; '*' NOT allowed */\nexport function validateScopesForKey(\n scopes: readonly string[],\n opts: { publishable: boolean },\n): ValidationResult {\n const expanded = expandLegacyScopes(scopes);\n const invalid: string[] = [];\n for (const id of expanded) {\n if (id === '*') {\n if (opts.publishable) invalid.push(id);\n continue;\n }\n const def = SCOPE_REGISTRY[id];\n if (!def) { invalid.push(id); continue; }\n if (opts.publishable) {\n if (!def.publishableAllowed) invalid.push(id);\n } else if (def.staffOnly) {\n invalid.push(id);\n }\n }\n return { ok: invalid.length === 0, invalid };\n}\n\n/** Validate scopes requested in an extension manifest:\n * every scope must exist + be extensionAllowed; '*' is never allowed. */\nexport function validateScopesForExtension(scopes: readonly string[]): ValidationResult {\n const expanded = expandLegacyScopes(scopes);\n const invalid: string[] = [];\n for (const id of expanded) {\n if (id === '*') { invalid.push(id); continue; }\n const def = SCOPE_REGISTRY[id];\n if (!def || !def.extensionAllowed) invalid.push(id);\n }\n return { ok: invalid.length === 0, invalid };\n}\n\n/** Scope ids a publishable key may hold (for the picker). */\nexport const PUBLISHABLE_SCOPES: string[] =\n Object.values(SCOPE_REGISTRY).filter((d) => d.publishableAllowed).map((d) => d.id);\n","import type { ActionDefinition } from './types';\n\n/**\n * The verbs, defined once.\n *\n * Curation, not coverage: each entry maps to a job somebody actually asks for.\n * Long-tail reads are served by `api_get`, which cannot mutate anything and is\n * still scope-enforced server-side, so the curated list never has to grow just\n * to reach another GET.\n *\n * Paths are the EFFECTIVE public paths. Route files that declare `/v1/...`\n * literals are registered under a `prefix: '/api'`, so both spellings resolve to\n * `/api/v1/...`; the catalog always records the resolved form.\n */\nexport const ACTIONS: readonly ActionDefinition[] = [\n // ---------------------------------------------------------------- identity\n {\n id: 'whoami',\n title: 'Identify the connected credential',\n description:\n 'Report which workspace, application and environment this credential is pinned to, and what it is allowed to do. Call this first when you need to know whether you are talking to production or a sandbox.',\n kind: 'read',\n scopes: [],\n input: [],\n requests: [{ method: 'GET', path: '/api/v1/whoami' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n\n // ------------------------------------------------------- local (no API call)\n {\n id: 'search_docs',\n title: 'Search the Throttle developer docs',\n description:\n 'Full-text search over the Throttle developer documentation. Returns titles, canonical docs.usethrottle.dev URLs, and matching excerpts. Prefer this over recalling API details from memory.',\n kind: 'read',\n scopes: [],\n input: [\n { name: 'query', type: 'string', required: true, description: 'What to search for.' },\n { name: 'limit', type: 'number', required: false, description: 'Maximum results.' },\n ],\n requests: [],\n channels: ['mcp'],\n },\n {\n id: 'describe_endpoint',\n title: 'Describe an API endpoint',\n description:\n 'Return the canonical request and response shape of a Throttle API endpoint from the published OpenAPI contract: path parameters, request body fields, required scope. Use before writing any integration code.',\n kind: 'read',\n scopes: [],\n input: [\n {\n name: 'path',\n type: 'string',\n required: true,\n description: 'Endpoint path or fragment, e.g. \"/api/v1/carts\" or \"carts\".',\n },\n {\n name: 'method',\n type: 'string',\n required: false,\n description: 'Narrow to one HTTP method.',\n enum: ['GET', 'POST', 'PATCH', 'PUT', 'DELETE'],\n },\n ],\n requests: [],\n channels: ['mcp'],\n },\n {\n id: 'validate_payload',\n title: 'Validate a request body against the API contract',\n description:\n 'Check a request body against the published contract before sending it. Names every unsupported field and gives its canonical replacement — Throttle is strict camelCase and rejects retired aliases such as line_items, unit_price, customer_id and storeId.',\n kind: 'read',\n scopes: [],\n input: [\n { name: 'method', type: 'string', required: true, description: 'HTTP method.' },\n { name: 'path', type: 'string', required: true, description: 'Endpoint path.' },\n { name: 'body', type: 'object', required: true, description: 'The request body to check.' },\n ],\n requests: [],\n channels: ['mcp'],\n },\n\n // ------------------------------------------------------------ generic reads\n {\n id: 'api_get',\n title: 'Read any Throttle API endpoint',\n description:\n 'Escape hatch for reads the curated tools do not cover: performs a GET against any /api/v1 path and returns the response. Cannot write. Confirm the path with describe_endpoint first if unsure.',\n kind: 'read',\n scopes: [],\n input: [\n {\n name: 'path',\n type: 'string',\n required: true,\n description: 'Path beginning with /api/v1, query string included.',\n },\n ],\n requests: [],\n channels: ['mcp'],\n guardrails: [\n 'GET only — reject any other method.',\n 'Reject paths outside /api/v1 so the tool cannot be pointed at another host or a non-versioned surface.',\n 'Server-side scope enforcement still applies; surface a 403 insufficient_scopes verbatim rather than retrying.',\n ],\n },\n\n // ------------------------------------------------------------------- orders\n {\n id: 'search_orders',\n title: 'Search orders',\n description: 'List orders, newest first, with optional free-text and status filters.',\n kind: 'read',\n scopes: ['orders:read'],\n input: [\n { name: 'q', type: 'string', required: false, description: 'Free-text search.' },\n { name: 'status', type: 'string', required: false, description: 'Order status filter.' },\n { name: 'paymentStatus', type: 'string', required: false, description: 'Payment status filter.' },\n { name: 'limit', type: 'number', required: false, description: 'Page size.' },\n { name: 'cursor', type: 'string', required: false, description: 'Pagination cursor.' },\n ],\n requests: [{ method: 'GET', path: '/api/v1/orders' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n {\n id: 'get_order',\n title: 'Get one order with its returns and fulfillments',\n description:\n 'Full picture of a single order: the order itself plus its payments, returns and fulfillments in one response.',\n kind: 'read',\n scopes: ['orders:read'],\n input: [{ name: 'id', type: 'string', required: true, description: 'Order id.' }],\n requests: [\n { method: 'GET', path: '/api/v1/orders/:id' },\n { method: 'GET', path: '/api/v1/orders/:id/payments' },\n { method: 'GET', path: '/api/v1/orders/:id/returns' },\n { method: 'GET', path: '/api/v1/orders/:orderId/fulfillments' },\n ],\n channels: ['mcp'],\n guardrails: [\n 'Sub-reads need their own scopes (payments:read, order_returns:read, fulfillments:read). Skip a section the credential cannot read and say so in the result rather than failing the whole call.',\n ],\n },\n\n // ---------------------------------------------------------------- customers\n {\n id: 'search_customers',\n title: 'Search customers',\n description: 'Find customers by name, email or external id.',\n kind: 'read',\n scopes: ['customers:read'],\n input: [\n { name: 'q', type: 'string', required: false, description: 'Free-text search.' },\n { name: 'limit', type: 'number', required: false, description: 'Page size.' },\n { name: 'cursor', type: 'string', required: false, description: 'Pagination cursor.' },\n ],\n requests: [{ method: 'GET', path: '/api/v1/customers' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n {\n id: 'get_customer',\n title: 'Get one customer with subscriptions and addresses',\n description:\n 'Full picture of a single customer: the record plus their subscriptions and addresses in one response.',\n kind: 'read',\n scopes: ['customers:read'],\n input: [{ name: 'id', type: 'string', required: true, description: 'Customer id.' }],\n requests: [\n { method: 'GET', path: '/api/v1/customers/:id' },\n { method: 'GET', path: '/api/v1/customers/:id/addresses' },\n { method: 'GET', path: '/api/v1/subscriptions' },\n ],\n channels: ['mcp'],\n guardrails: [\n 'Sub-reads need customer_addresses:read / subscriptions:read. Omit a section the credential cannot read instead of failing.',\n ],\n },\n\n // ------------------------------------------------------------- subscriptions\n {\n id: 'list_subscriptions',\n title: 'List subscriptions',\n description: 'List subscriptions with optional customer and status filters.',\n kind: 'read',\n scopes: ['subscriptions:read'],\n input: [\n { name: 'customerId', type: 'string', required: false, description: 'Filter by customer.' },\n { name: 'status', type: 'string', required: false, description: 'Filter by status.' },\n { name: 'limit', type: 'number', required: false, description: 'Page size.' },\n { name: 'cursor', type: 'string', required: false, description: 'Pagination cursor.' },\n ],\n requests: [{ method: 'GET', path: '/api/v1/subscriptions' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n {\n id: 'get_subscription',\n title: 'Get one subscription',\n description: 'Read a single subscription including its current period and pending changes.',\n kind: 'read',\n scopes: ['subscriptions:read'],\n input: [{ name: 'id', type: 'string', required: true, description: 'Subscription id.' }],\n requests: [{ method: 'GET', path: '/api/v1/subscriptions/:id' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n\n // ------------------------------------------------------------------- quotes\n {\n id: 'search_quotes',\n title: 'Search quotes',\n description: 'List quotes with optional status filter — useful for \"which quotes expire soon\".',\n kind: 'read',\n scopes: ['quotes:read'],\n input: [\n { name: 'status', type: 'string', required: false, description: 'Filter by quote status.' },\n { name: 'limit', type: 'number', required: false, description: 'Page size.' },\n { name: 'cursor', type: 'string', required: false, description: 'Pagination cursor.' },\n ],\n requests: [{ method: 'GET', path: '/api/v1/quotes' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n {\n id: 'get_quote',\n title: 'Get one quote',\n description: 'Read a single quote with its line items, revisions and buyer link state.',\n kind: 'read',\n scopes: ['quotes:read'],\n input: [{ name: 'id', type: 'string', required: true, description: 'Quote id.' }],\n requests: [{ method: 'GET', path: '/api/v1/quotes/:id' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n\n // ----------------------------------------------------------------- invoices\n {\n id: 'list_invoices',\n title: 'List invoices',\n description: 'List issued invoices with optional status filter.',\n kind: 'read',\n scopes: ['invoices:read'],\n input: [\n { name: 'status', type: 'string', required: false, description: 'Filter by invoice status.' },\n { name: 'limit', type: 'number', required: false, description: 'Page size.' },\n { name: 'cursor', type: 'string', required: false, description: 'Pagination cursor.' },\n ],\n requests: [{ method: 'GET', path: '/api/v1/invoices' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n {\n id: 'receivables_aging',\n title: 'Receivables aging',\n description: 'Outstanding receivables bucketed by age — answers \"what is overdue and by how long\".',\n kind: 'read',\n scopes: ['invoices:read'],\n input: [],\n requests: [{ method: 'GET', path: '/api/v1/invoices/aging' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n\n // --------------------------------------------------------------- discounts\n {\n id: 'search_discounts',\n title: 'Search discounts',\n description: 'List discount codes with optional filters — type, active state, and creation date range.',\n kind: 'read',\n scopes: ['discounts:read'],\n input: [\n { name: 'q', type: 'string', required: false, description: 'Free-text search.' },\n { name: 'code', type: 'string', required: false, description: 'Exact code match.' },\n {\n name: 'type',\n type: 'string',\n required: false,\n description: 'Filter by discount type.',\n enum: ['percentage', 'fixed_amount'],\n },\n { name: 'isActive', type: 'boolean', required: false, description: 'Filter by active state.' },\n { name: 'createdAfter', type: 'string', required: false, description: 'ISO 8601 date lower bound.' },\n { name: 'createdBefore', type: 'string', required: false, description: 'ISO 8601 date upper bound.' },\n { name: 'limit', type: 'number', required: false, description: 'Page size.' },\n { name: 'cursor', type: 'string', required: false, description: 'Pagination cursor.' },\n ],\n requests: [{ method: 'GET', path: '/api/v1/discounts' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n {\n id: 'get_discount',\n title: 'Get one discount',\n description: 'Read a single discount code: value, conditions, usage limits and redemption count.',\n kind: 'read',\n scopes: ['discounts:read'],\n input: [{ name: 'id', type: 'string', required: true, description: 'Discount id.' }],\n requests: [{ method: 'GET', path: '/api/v1/discounts/:id' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n\n // ---------------------------------------------------------------- payments\n {\n id: 'search_payments',\n title: 'Search payments',\n description:\n 'List payments with optional filters — method, status, order, amount range, or a Net-N overdue bucket. Today payments are only reachable nested inside get_order; this is the standalone entry point.',\n kind: 'read',\n scopes: ['payments:read'],\n input: [\n { name: 'method', type: 'string', required: false, description: 'Filter by payment method.' },\n { name: 'status', type: 'string', required: false, description: 'Filter by payment status.' },\n { name: 'orderId', type: 'string', required: false, description: 'Filter to one order.' },\n {\n name: 'aging',\n type: 'string',\n required: false,\n description: 'Overdue bucket filter, Net-N payments only.',\n enum: ['0_30', '31_60', '61_90', '90_plus'],\n },\n { name: 'dueFrom', type: 'string', required: false, description: 'Due-date range start, YYYY-MM-DD.' },\n { name: 'dueTo', type: 'string', required: false, description: 'Due-date range end, YYYY-MM-DD.' },\n { name: 'amountMin', type: 'number', required: false, description: 'Minimum amount, minor units.' },\n { name: 'amountMax', type: 'number', required: false, description: 'Maximum amount, minor units.' },\n { name: 'limit', type: 'number', required: false, description: 'Page size.' },\n { name: 'cursor', type: 'string', required: false, description: 'Pagination cursor.' },\n ],\n requests: [{ method: 'GET', path: '/api/v1/payments' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n {\n id: 'get_payment',\n title: 'Get one payment with its transactions',\n description: 'Read a single payment plus its full transaction history (authorize/capture/refund/void attempts).',\n kind: 'read',\n scopes: ['payments:read'],\n input: [{ name: 'id', type: 'string', required: true, description: 'Payment id.' }],\n requests: [\n { method: 'GET', path: '/api/v1/payments/:id' },\n { method: 'GET', path: '/api/v1/payments/:id/transactions' },\n ],\n channels: ['mcp'],\n guardrails: [\n 'The transactions sub-read needs its own read of the same payment scope; report it as unavailable rather than failing the whole call if the underlying request errors.',\n ],\n },\n\n // ---------------------------------------------------------------- invoices\n {\n id: 'get_invoice',\n title: 'Get one invoice',\n description: 'Read a single issued invoice: line items, totals, status and the billing snapshot at issue time.',\n kind: 'read',\n scopes: ['invoices:read'],\n input: [{ name: 'id', type: 'string', required: true, description: 'Invoice id.' }],\n requests: [{ method: 'GET', path: '/api/v1/invoices/:id' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n\n // ------------------------------------------------------------------ carts\n {\n id: 'list_abandoned_carts',\n title: 'List abandoned carts',\n description: 'Carts that were started but never finalized, with recovery status — the abandoned-cart recovery list.',\n kind: 'read',\n scopes: ['carts:read'],\n input: [\n { name: 'sinceDays', type: 'number', required: false, description: 'How many days back to look.' },\n { name: 'limit', type: 'number', required: false, description: 'Page size.' },\n { name: 'cursor', type: 'string', required: false, description: 'Pagination cursor.' },\n ],\n requests: [\n { method: 'GET', path: '/api/v1/abandoned-carts' },\n { method: 'GET', path: '/api/v1/abandoned-carts/summary' },\n ],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n guardrails: ['Report the summary as unavailable rather than failing the whole call if that sub-read errors.'],\n },\n\n // ---------------------------------------------------------------- debugging\n {\n id: 'search_events',\n title: 'Search the event log',\n description:\n 'Search the immutable event log by type or entity. The first stop when asking what actually happened to an order, cart or subscription.',\n kind: 'read',\n scopes: ['events:read'],\n input: [\n { name: 'type', type: 'string', required: false, description: 'Event type, e.g. order.created.' },\n { name: 'entityType', type: 'string', required: false, description: 'Entity type filter.' },\n { name: 'entityId', type: 'string', required: false, description: 'Entity id filter.' },\n { name: 'limit', type: 'number', required: false, description: 'Page size.' },\n { name: 'cursor', type: 'string', required: false, description: 'Pagination cursor.' },\n ],\n requests: [{ method: 'GET', path: '/api/v1/events' }],\n channels: ['mcp', 'n8n'],\n },\n {\n id: 'list_webhook_deliveries',\n title: 'List webhook deliveries',\n description: 'Recent outbound webhook deliveries, filterable by endpoint and status.',\n kind: 'read',\n scopes: ['webhook_deliveries:read'],\n input: [\n { name: 'endpointId', type: 'string', required: false, description: 'Filter by endpoint.' },\n { name: 'status', type: 'string', required: false, description: 'Filter by delivery status.' },\n { name: 'limit', type: 'number', required: false, description: 'Page size.' },\n ],\n requests: [{ method: 'GET', path: '/api/v1/webhook-deliveries' }],\n channels: ['mcp', 'n8n'],\n },\n {\n id: 'get_webhook_delivery',\n title: 'Get one webhook delivery',\n description:\n 'Full delivery record: the signed payload we sent, the response we got back, and every attempt.',\n kind: 'read',\n scopes: ['webhook_deliveries:read'],\n input: [{ name: 'id', type: 'string', required: true, description: 'Delivery id.' }],\n requests: [{ method: 'GET', path: '/api/v1/webhook-deliveries/:id' }],\n channels: ['mcp', 'n8n'],\n },\n {\n id: 'explain_checkout_failure',\n title: 'Explain why a checkout failed',\n description:\n 'Diagnose a failing checkout in one call: session state, its cart, the events it emitted, and any webhook deliveries that followed. Use this before asking the user to reproduce anything.',\n kind: 'read',\n scopes: ['checkout_sessions:read'],\n input: [\n {\n name: 'id',\n type: 'string',\n required: true,\n description: 'Checkout session id (or cart id — the tool resolves the session).',\n },\n ],\n requests: [\n { method: 'GET', path: '/api/v1/checkout-sessions/:id' },\n { method: 'GET', path: '/api/v1/checkout-sessions/:id/cart' },\n { method: 'GET', path: '/api/v1/events' },\n { method: 'GET', path: '/api/v1/webhook-deliveries' },\n ],\n channels: ['mcp'],\n guardrails: [\n 'Report which sections were unavailable rather than failing the call when a sub-read is unscoped.',\n ],\n },\n\n // ------------------------------------------------------------- extensions\n {\n id: 'list_extension_installations',\n title: 'List installed extensions',\n description: 'Extensions installed on this application, with status and configuration.',\n kind: 'read',\n scopes: ['extensions:read'],\n input: [\n {\n name: 'status',\n type: 'string',\n required: false,\n description: 'Filter by installation status.',\n enum: ['active', 'suspended', 'uninstalled'],\n },\n { name: 'limit', type: 'number', required: false, description: 'Page size.' },\n { name: 'cursor', type: 'string', required: false, description: 'Pagination cursor.' },\n ],\n requests: [{ method: 'GET', path: '/api/v1/installations' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n\n // ------------------------------------------------------------- connectors\n {\n id: 'get_connector_routing',\n title: 'Payment routing and decline rules',\n description:\n 'Read the payment-routing cascade, active routing connectors, and card/other decline rules — what determines which processor handles a payment and what happens on a decline.',\n kind: 'read',\n scopes: ['connectors:read'],\n input: [],\n requests: [\n { method: 'GET', path: '/api/v1/payment-routing' },\n { method: 'GET', path: '/api/v1/routing-connectors' },\n { method: 'GET', path: '/api/v1/card-decline' },\n { method: 'GET', path: '/api/v1/other-decline' },\n ],\n channels: ['mcp'],\n guardrails: [\n 'Every sub-read proxies live to the payment provider\\'s routing API and none are guaranteed to succeed together; report any that fail as unavailable rather than failing the whole call.',\n ],\n },\n\n {\n id: 'get_integration_status',\n title: 'Integration readiness',\n description:\n 'Answers \"am I ready to go live?\" — active connectors, webhook endpoints and their recent delivery health, and the environment this credential is pinned to.',\n kind: 'read',\n scopes: [],\n input: [],\n requests: [\n { method: 'GET', path: '/api/v1/whoami' },\n { method: 'GET', path: '/api/v1/connectors' },\n { method: 'GET', path: '/api/v1/webhook-endpoints' },\n { method: 'GET', path: '/api/v1/webhook-endpoints/coverage' },\n ],\n channels: ['mcp'],\n guardrails: [\n 'Each section needs its own scope (connectors:read, webhooks:read). Report a section as \"not readable with this credential\" instead of failing.',\n ],\n },\n // --------------------------------------------------------------- workspace\n {\n id: 'get_workspace_settings',\n title: 'Get workspace settings',\n description:\n 'Read this workspace\\'s identity and settings: name, slug, branding, onboarding state, and the default Net-N payment terms.',\n kind: 'read',\n scopes: ['merchant:read'],\n input: [],\n requests: [{ method: 'GET', path: '/api/v1/merchants/me' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n {\n id: 'get_audit_log',\n title: 'Get the workspace audit log',\n description:\n 'Recent admin actions taken on this workspace — invites, billing changes, key rotation, suspensions.',\n kind: 'read',\n scopes: ['audit_logs:read'],\n input: [\n { name: 'limit', type: 'number', required: false, description: 'Maximum entries (1-200).', default: 100 },\n ],\n requests: [{ method: 'GET', path: '/api/v1/audit-log' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n },\n {\n id: 'get_business_summary',\n title: 'Business summary',\n description:\n 'How are we doing? Orders/revenue, subscription MRR, receivables and quotes pipeline for a week/month/quarter, always compared to the immediately preceding period of equal length.',\n kind: 'read',\n scopes: [],\n input: [\n {\n name: 'period',\n type: 'string',\n required: false,\n description: 'Reporting window.',\n enum: ['week', 'month', 'quarter'],\n default: 'month',\n },\n ],\n requests: [{ method: 'GET', path: '/api/v1/analytics/business-summary' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n guardrails: [\n 'Each section needs its own scope (orders:read, subscriptions:read, invoices:read, quotes:read). A section without its scope is reported as omitted rather than failing the whole call.',\n ],\n },\n {\n id: 'get_attention_digest',\n title: 'Attention digest',\n description:\n 'What needs attention right now? Open disputes, subscriptions in dunning, overdue Net-N invoices, and webhooks with degraded delivery health — a point-in-time snapshot, not a time range.',\n kind: 'read',\n scopes: [],\n input: [],\n requests: [{ method: 'GET', path: '/api/v1/analytics/attention-digest' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n guardrails: [\n 'Each section needs its own scope (payment_disputes:read, subscriptions:read, invoices:read, webhook_deliveries:read). A section without its scope is reported as omitted rather than failing the whole call.',\n ],\n },\n\n // ------------------------------------------------------------ sandbox write\n {\n id: 'seed_test_data',\n title: 'Seed test data (non-production only)',\n description:\n 'Create a realistic customer, cart, line items and a finalized draft order so an integration has something to read. Refuses to run against production.',\n kind: 'write',\n scopes: ['customers:write', 'carts:write', 'cart_items:write'],\n input: [\n { name: 'customerEmail', type: 'string', required: false, description: 'Email for the seeded customer.' },\n { name: 'lineItems', type: 'array', required: false, description: 'Line items; a sensible default set is used when omitted.' },\n ],\n requests: [\n { method: 'POST', path: '/api/v1/customers' },\n { method: 'POST', path: '/api/v1/carts' },\n { method: 'POST', path: '/api/v1/carts/:id/items' },\n { method: 'POST', path: '/api/v1/carts/:id/finalize' },\n ],\n channels: ['mcp'],\n sandboxOnly: true,\n idempotent: true,\n guardrails: [\n 'Hard-refuse when the credential resolves to a production environment, regardless of any allow-writes flag.',\n 'Seeds a finalized DRAFT order — it does not capture a payment, which needs a browser-side tokenised payment method.',\n ],\n },\n\n // -------------------------------------------------------------- money/mail\n {\n id: 'create_quote',\n title: 'Create a quote',\n description: 'Draft a quote for a customer with line items and terms. Does not send it — use send_quote.',\n kind: 'write',\n scopes: ['quotes:write'],\n input: [\n { name: 'customerId', type: 'string', required: true, description: 'Customer the quote is for.' },\n { name: 'items', type: 'array', required: true, description: 'Quote line items: { name, unitPrice, quantity }.' },\n { name: 'expiresAt', type: 'string', required: false, description: 'ISO 8601 expiry.' },\n { name: 'netN', type: 'number', required: false, description: 'Payment terms in days. Omit for pay-in-full.' },\n { name: 'notes', type: 'string', required: false, description: 'Buyer-visible notes.' },\n ],\n requests: [{ method: 'POST', path: '/api/v1/quotes' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n idempotent: true,\n },\n {\n id: 'send_quote',\n title: 'Issue and send a quote',\n description:\n 'Issue a draft quote and email the buyer their quote link. This is buyer-visible — confirm with the user before calling it.',\n kind: 'write',\n scopes: ['quotes:write'],\n input: [{ name: 'id', type: 'string', required: true, description: 'Quote id.' }],\n requests: [{ method: 'POST', path: '/api/v1/quotes/:id/issue' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n idempotent: true,\n guardrails: ['Sends mail to a real buyer. Never call it speculatively or to \"check\" a quote.'],\n },\n {\n id: 'refund_payment',\n title: 'Refund a payment',\n description:\n 'Refund a captured payment. The amount is required — never infer a full refund from an unspecified amount.',\n kind: 'write',\n scopes: ['payment_refunds:write'],\n input: [\n { name: 'id', type: 'string', required: true, description: 'Payment id.' },\n {\n name: 'amount',\n type: 'number',\n required: true,\n description: 'Amount to refund in minor units. Required — omitting it would refund the whole payment.',\n },\n { name: 'reason', type: 'string', required: false, description: 'Reason recorded on the refund.' },\n ],\n requests: [{ method: 'POST', path: '/api/v1/payments/:id/refund' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n idempotent: true,\n guardrails: [\n 'Moves money and is irreversible. Confirm with the user first.',\n 'The API treats an omitted amount as a FULL refund, so this action requires it explicitly.',\n ],\n },\n {\n id: 'manage_subscription',\n title: 'Pause or resume a subscription',\n description: 'Pause or resume an active subscription.',\n kind: 'write',\n scopes: ['subscription_pauses:write'],\n input: [\n { name: 'id', type: 'string', required: true, description: 'Subscription id.' },\n {\n name: 'action',\n type: 'string',\n required: true,\n description: 'What to do.',\n enum: ['pause', 'resume'],\n },\n ],\n requests: [\n { method: 'POST', path: '/api/v1/subscriptions/:id/pause' },\n { method: 'POST', path: '/api/v1/subscriptions/:id/resume' },\n ],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n idempotent: true,\n },\n {\n id: 'cancel_subscription',\n title: 'Cancel a subscription',\n description: 'Cancel a subscription. Separate from pause/resume because it needs its own scope.',\n kind: 'write',\n scopes: ['subscription_cancellations:write'],\n input: [\n { name: 'id', type: 'string', required: true, description: 'Subscription id.' },\n {\n name: 'atPeriodEnd',\n type: 'boolean',\n required: false,\n description: 'Cancel at the end of the current period instead of immediately.',\n },\n ],\n requests: [{ method: 'POST', path: '/api/v1/subscriptions/:id/cancel' }],\n channels: ['mcp', 'zapier', 'make', 'n8n'],\n idempotent: true,\n guardrails: ['Ends billing for a paying customer. Confirm with the user first.'],\n },\n {\n id: 'replay_webhook_delivery',\n title: 'Replay a webhook delivery',\n description: 'Re-send a past webhook delivery to its endpoint — useful after fixing a broken handler.',\n kind: 'write',\n scopes: ['webhook_deliveries:write'],\n input: [{ name: 'id', type: 'string', required: true, description: 'Delivery id.' }],\n requests: [{ method: 'POST', path: '/api/v1/webhook-deliveries/:id/replay' }],\n channels: ['mcp', 'n8n'],\n idempotent: true,\n guardrails: ['The receiving system will process the event again. Confirm it is idempotent first.'],\n },\n {\n id: 'send_test_webhook',\n title: 'Send a test webhook',\n description: 'Send a synthetic signed event to a webhook endpoint to verify signature handling and reachability.',\n kind: 'write',\n scopes: ['webhooks:write'],\n input: [\n { name: 'id', type: 'string', required: true, description: 'Endpoint id.' },\n { name: 'eventType', type: 'string', required: false, description: 'Event type to simulate.' },\n ],\n requests: [{ method: 'POST', path: '/api/v1/webhook-endpoints/:id/test' }],\n channels: ['mcp', 'n8n'],\n idempotent: true,\n },\n];\n","import { eventReadScope } from '@core/scopes';\nimport type { TriggerDefinition } from './types';\n\n/**\n * Event-backed triggers for the no-code channels.\n *\n * Scopes are DERIVED via `eventReadScope` rather than written out, so a change to\n * the event→scope mapping in `@core/scopes` can never leave a trigger claiming a\n * scope the API would not accept at subscription time.\n *\n * MCP is absent from every `channels` list on purpose: the protocol has no\n * subscription primitive, so an agent polls `search_events` instead.\n */\nconst NO_CODE: readonly ('zapier' | 'make' | 'n8n')[] = ['zapier', 'make', 'n8n'];\n\nfunction trigger(\n id: string,\n title: string,\n eventType: string,\n description: string,\n): TriggerDefinition {\n return { id, title, eventType, description, scope: eventReadScope(eventType), channels: NO_CODE };\n}\n\nexport const TRIGGERS: readonly TriggerDefinition[] = [\n trigger('new_order', 'New order', 'order.created', 'Fires when an order is created.'),\n trigger(\n 'payment_captured',\n 'Payment captured',\n 'payment.captured',\n 'Fires when a payment is successfully captured.',\n ),\n trigger(\n 'payment_failed',\n 'Payment failed',\n 'payment.failed',\n 'Fires when a payment attempt fails.',\n ),\n trigger(\n 'new_subscription',\n 'New subscription',\n 'subscription.created',\n 'Fires when a subscription is created.',\n ),\n trigger(\n 'subscription_cancelled',\n 'Subscription cancelled',\n 'subscription.cancelled',\n 'Fires when a subscription is cancelled.',\n ),\n trigger(\n 'quote_accepted',\n 'Quote accepted',\n 'quote.accepted',\n 'Fires when a buyer accepts a quote.',\n ),\n trigger(\n 'cart_abandoned',\n 'Cart abandoned',\n 'cart.abandoned',\n 'Fires when a cart is marked abandoned.',\n ),\n trigger(\n 'invoice_past_due',\n 'Invoice past due',\n 'invoice.past_due',\n 'Fires when an invoice passes its due date unpaid.',\n ),\n];\n","import { hasScope } from '@core/scopes';\nimport { ACTIONS } from './actions';\nimport { TRIGGERS } from './triggers';\nimport type { ActionDefinition, Channel, TriggerDefinition } from './types';\n\nexport * from './types';\nexport { ACTIONS } from './actions';\nexport { TRIGGERS } from './triggers';\n\nexport function actionById(id: string): ActionDefinition | undefined {\n return ACTIONS.find((a) => a.id === id);\n}\n\nexport function actionsForChannel(channel: Channel): ActionDefinition[] {\n return ACTIONS.filter((a) => a.channels.includes(channel));\n}\n\nexport function triggersForChannel(channel: Channel): TriggerDefinition[] {\n return TRIGGERS.filter((t) => t.channels.includes(channel));\n}\n\n/**\n * Can this credential run this action?\n *\n * Delegates to `@core/scopes.hasScope`, so the `*` wildcard and the\n * `resource:write ⇒ resource:read` implication behave exactly as the API's own\n * enforcement does — a projection must never be more permissive than the server,\n * and must not be needlessly stricter either.\n */\nexport function canRunAction(granted: readonly string[], action: ActionDefinition): boolean {\n return action.scopes.every((required) => hasScope(granted as string[], required));\n}\n\n/**\n * The actions a channel should expose for a given credential.\n *\n * `includeWrites` is the projection's intent gate (the MCP server's\n * `--allow-writes`): holding a write scope means the credential *may* write,\n * which is not the same as the operator intending it to.\n */\nexport function availableActions(\n channel: Channel,\n granted: readonly string[],\n options: { includeWrites?: boolean } = {},\n): ActionDefinition[] {\n const includeWrites = options.includeWrites ?? false;\n return actionsForChannel(channel).filter((action) => {\n if (action.kind === 'write' && !includeWrites) return false;\n return canRunAction(granted, action);\n });\n}\n","/** Result shaping. Compact JSON: agents read it fine and it costs far fewer tokens. */\n\nconst MAX_CHARS = 24_000;\n\n/** Drops undefined and null so a wide API row does not spend tokens on empty fields. */\nfunction prune(value: unknown): unknown {\n if (Array.isArray(value)) return value.map(prune);\n if (value && typeof value === 'object') {\n const out: Record<string, unknown> = {};\n for (const [key, inner] of Object.entries(value as Record<string, unknown>)) {\n if (inner === undefined || inner === null) continue;\n out[key] = prune(inner);\n }\n return out;\n }\n return value;\n}\n\nexport function formatResult(value: unknown): string {\n const text = JSON.stringify(prune(value), null, 2) ?? 'null';\n if (text.length <= MAX_CHARS) return text;\n return `${text.slice(0, MAX_CHARS)}\\n\\n… truncated at ${MAX_CHARS} characters. Narrow the query (lower \"limit\", add a filter) or fetch a single record.`;\n}\n\n/**\n * Errors come back as tool text rather than transport failures: an agent can act\n * on \"missing scope orders:read\" but not on a dead connection. API error codes are\n * surfaced verbatim so the model does not paper over an auth problem by retrying.\n */\nexport function formatError(error: unknown): string {\n const e = error as { code?: string; message?: string; statusCode?: number; details?: unknown };\n if (e?.code && e?.message) {\n const detail = e.details ? `\\n\\ndetails: ${JSON.stringify(e.details)}` : '';\n return `Throttle API error ${e.code}${e.statusCode ? ` (HTTP ${e.statusCode})` : ''}: ${e.message}${detail}`;\n }\n return `Error: ${e?.message ?? String(error)}`;\n}\n","// src/index.ts\nvar ThrottleError = class extends Error {\n code;\n statusCode;\n details;\n body;\n constructor(args) {\n super(args.message);\n this.name = \"ThrottleError\";\n this.code = args.code;\n this.statusCode = args.statusCode;\n this.details = args.details;\n this.body = args.body;\n Object.setPrototypeOf(this, new.target.prototype);\n }\n};\nfunction isThrottleError(value) {\n return value instanceof ThrottleError;\n}\nexport {\n ThrottleError,\n isThrottleError\n};\n","import { ThrottleError } from '@usethrottle/errors';\n\nexport interface AuthCtx {\n apiKey: string;\n apiBaseUrl: string;\n}\n\nexport class ThrottleApiError extends ThrottleError {\n constructor(code: string, message: string, statusCode: number, details?: unknown) {\n super({ code, message, statusCode, details });\n this.name = 'ThrottleApiError';\n }\n}\nexport { ThrottleError, isThrottleError } from '@usethrottle/errors';\n\nexport interface RequestOptions {\n body?: unknown;\n query?: Record<string, unknown>;\n /**\n * Sent as `Idempotency-Key`. Writes must pass one: an agent that retries is the\n * normal case, and the API dedupes on\n * `(workspace, application, environment, key, method, path)`.\n */\n idempotencyKey?: string;\n}\n\nexport interface Pagination {\n cursor: string | null;\n hasMore: boolean;\n}\n\nexport interface ListResult<T> {\n data: T[];\n pagination: Pagination | null;\n}\n\n/** Drops undefined/null/empty params so callers can spread optional args freely. */\nexport function buildQuery(query: Record<string, unknown> | undefined): string {\n if (!query) return '';\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(query)) {\n if (value === undefined || value === null || value === '') continue;\n params.set(key, String(value));\n }\n const qs = params.toString();\n return qs ? `?${qs}` : '';\n}\n\nexport type Fetcher = typeof fetch;\n\nexport class ThrottleClient {\n constructor(\n private readonly auth: AuthCtx,\n private readonly fetchImpl: Fetcher = fetch,\n ) {}\n\n private async requestJson(\n method: string,\n path: string,\n options: RequestOptions = {},\n ): Promise<Record<string, unknown>> {\n const url = `${this.auth.apiBaseUrl.replace(/\\/$/, '')}${path}${buildQuery(options.query)}`;\n const headers: Record<string, string> = {\n 'content-type': 'application/json',\n 'x-api-key': this.auth.apiKey,\n };\n if (options.idempotencyKey) headers['idempotency-key'] = options.idempotencyKey;\n\n // A bodyless POST/PATCH/PUT advertising JSON would send an empty body that the\n // API's object-body schemas reject with `validation_error: body must be\n // object`, so default to `{}` (mirrors the CLI client).\n const sendsBody = method === 'POST' || method === 'PATCH' || method === 'PUT';\n const body =\n options.body !== undefined\n ? JSON.stringify(options.body)\n : sendsBody\n ? '{}'\n : undefined;\n\n const res = await this.fetchImpl(url, { method, headers, body });\n const text = await res.text();\n let parsed: Record<string, unknown> = {};\n try {\n parsed = text ? (JSON.parse(text) as Record<string, unknown>) : {};\n } catch {\n /* non-JSON body */\n }\n if (!res.ok) {\n const err = parsed.error as\n | { code?: string; message?: string; details?: unknown }\n | undefined;\n throw new ThrottleApiError(\n err?.code ?? `http_${res.status}`,\n err?.message ?? `Request failed (${res.status}): ${text.slice(0, 200)}`,\n res.status,\n err?.details,\n );\n }\n return parsed;\n }\n\n /** Unwraps the `{ data }` envelope. Key presence, not `??` — `{data: null}` unwraps to null. */\n async get<T>(path: string, query?: Record<string, unknown>): Promise<T> {\n const body = await this.requestJson('GET', path, { query });\n return (body && typeof body === 'object' && 'data' in body ? body.data : body) as T;\n }\n\n async list<T>(path: string, query?: Record<string, unknown>): Promise<ListResult<T>> {\n const body = await this.requestJson('GET', path, { query });\n const data = ('data' in body ? body.data : body) as T[];\n const meta = body.meta as { pagination?: Pagination } | undefined;\n return { data: Array.isArray(data) ? data : [], pagination: meta?.pagination ?? null };\n }\n\n async post<T>(path: string, options: RequestOptions = {}): Promise<T> {\n const body = await this.requestJson('POST', path, options);\n return (body && typeof body === 'object' && 'data' in body ? body.data : body) as T;\n }\n}\n\n/**\n * Runs a sub-read that the credential may not be scoped for.\n *\n * Composite tools (`get_order`, `explain_checkout_failure`,\n * `get_integration_status`) must not fail wholesale because one section is\n * unscoped or absent — an agent that gets a hard error learns nothing, whereas a\n * result that says which section was unavailable can still answer the question.\n */\nexport async function optional<T>(\n load: () => Promise<T>,\n): Promise<{ ok: true; value: T } | { ok: false; unavailable: string }> {\n try {\n return { ok: true, value: await load() };\n } catch (error) {\n const e = error as ThrottleApiError;\n const code = e?.code ?? 'error';\n const reason =\n code === 'insufficient_scopes'\n ? 'not readable with this credential (missing scope)'\n : code === 'not_found'\n ? 'not found'\n : `unavailable (${code})`;\n return { ok: false, unavailable: reason };\n }\n}\n","/**\n * `describe_endpoint` and `validate_payload`, answered from the OpenAPI contract\n * bundled at build time. No network, no API quota.\n *\n * Why this exists: Throttle's public API is strict camelCase and rejects the\n * retired snake_case aliases — and those aliases are exactly what a model writing\n * commerce code will guess, because that is what the rest of the internet's\n * examples look like. Naming the replacement turns a 400-debug loop into one call.\n */\n\nexport interface ContractField {\n name: string;\n type?: string;\n required: boolean;\n description?: string;\n enum?: string[];\n}\n\nexport interface ContractOperation {\n method: string;\n /** OpenAPI-style path, e.g. `/api/v1/customers/{customerId}/addresses/{id}`. */\n path: string;\n summary?: string;\n description?: string;\n pathParams: string[];\n queryParams: ContractField[];\n bodyFields: ContractField[] | null;\n}\n\nexport interface ContractIndex {\n generatedAt: string;\n operations: ContractOperation[];\n}\n\n/**\n * Retired public field names → canonical replacement.\n *\n * Only names the API actively rejects. Anything not listed still gets the generic\n * snake_case → camelCase suggestion below.\n */\nexport const RETIRED_FIELDS: Record<string, string> = {\n storeId: 'applicationId',\n store_id: 'applicationId',\n merchantId: 'workspaceId',\n merchant_id: 'workspaceId',\n customer_id: 'customerId',\n line_items: 'lineItems',\n unit_price: 'unitPrice',\n external_id: 'externalId',\n payment_method_id: 'paymentMethodId',\n first_name: 'firstName',\n last_name: 'lastName',\n net_n: 'netN',\n hosted_url: 'hostedUrl',\n embed_url: 'embedUrl',\n checkout_url: 'checkoutUrl',\n order_number: 'orderNumber',\n payment_status: 'paymentStatus',\n allowed_origins: 'allowedOrigins',\n enabled_events: 'enabledEvents',\n template_key: 'templateKey',\n request_id: 'requestId',\n signing_secret: 'signingSecret (returned once at creation; not accepted as input)',\n};\n\nexport function snakeToCamel(name: string): string {\n return name.replace(/_([a-z0-9])/g, (_, c: string) => c.toUpperCase());\n}\n\n/** Collapses parameter names so `/orders/{id}` and `/orders/:id` compare equal. */\nexport function normalizePath(path: string): string {\n return path\n .replace(/\\{[^}]+\\}/g, '{}')\n .replace(/:[A-Za-z0-9_]+/g, '{}')\n .replace(/\\/$/, '');\n}\n\nfunction segmentsOf(path: string): string[] {\n return path.split('?')[0].replace(/\\/$/, '').split('/').filter(Boolean);\n}\n\nfunction isParamSegment(segment: string): boolean {\n return /^\\{[^}]+\\}$/.test(segment) || /^:[A-Za-z0-9_]+$/.test(segment);\n}\n\n/**\n * Matches a caller-supplied path against a contract template.\n *\n * Callers pass CONCRETE paths — `/api/v1/carts/9f3a…/items`, straight out of the\n * conversation — so a template segment must be allowed to absorb a real id, not\n * just another placeholder. Comparing normalized strings alone silently failed on\n * every real path and sent the agent to \"no operation matched\".\n */\nexport function pathMatches(template: string, candidate: string): boolean {\n const t = segmentsOf(template);\n const c = segmentsOf(candidate);\n if (t.length !== c.length) return false;\n return t.every((segment, i) => isParamSegment(segment) || isParamSegment(c[i]) || segment === c[i]);\n}\n\n/** Fewer placeholders = a more specific template, so it wins when several match. */\nfunction paramCount(path: string): number {\n return segmentsOf(path).filter(isParamSegment).length;\n}\n\nexport function findOperations(\n index: ContractIndex,\n query: { path: string; method?: string },\n): ContractOperation[] {\n const method = query.method?.toUpperCase();\n const wanted = query.path.trim();\n const byMethod = (op: ContractOperation) => !method || op.method === method;\n\n const matched = index.operations\n .filter((op) => byMethod(op) && pathMatches(op.path, wanted))\n .sort((a, b) => paramCount(a.path) - paramCount(b.path));\n if (matched.length > 0) return matched;\n\n // Fragment search: \"carts\" or \"/carts/items\" should still find something.\n const needle = normalizePath(wanted).replace(/^\\/+/, '');\n return index.operations.filter((op) => byMethod(op) && normalizePath(op.path).includes(needle));\n}\n\nexport interface ValidationProblem {\n field: string;\n problem: string;\n suggestion?: string;\n}\n\nexport interface ValidationResult {\n ok: boolean;\n matched: string | null;\n errors: ValidationProblem[];\n warnings: ValidationProblem[];\n note?: string;\n}\n\nexport function validatePayload(\n index: ContractIndex,\n input: { method: string; path: string; body: Record<string, unknown> },\n): ValidationResult {\n const errors: ValidationProblem[] = [];\n const warnings: ValidationProblem[] = [];\n const keys = Object.keys(input.body ?? {});\n\n // The retired-alias and snake_case checks do not need a schema, so they run\n // even for operations the snapshot documents without a request body.\n for (const key of keys) {\n const retired = RETIRED_FIELDS[key];\n if (retired) {\n errors.push({\n field: key,\n problem: 'retired public field name — the API rejects it',\n suggestion: `use \"${retired}\"`,\n });\n continue;\n }\n if (key.includes('_')) {\n errors.push({\n field: key,\n problem: 'snake_case is not accepted on public request bodies',\n suggestion: `use \"${snakeToCamel(key)}\"`,\n });\n }\n }\n\n const matches = findOperations(index, { path: input.path, method: input.method });\n const operation = matches[0];\n if (!operation) {\n return {\n ok: false,\n matched: null,\n errors: [\n ...errors,\n {\n field: input.path,\n problem: `no ${input.method.toUpperCase()} operation matches this path in the published contract`,\n suggestion: 'call describe_endpoint to find the right path',\n },\n ],\n warnings,\n };\n }\n\n if (!operation.bodyFields) {\n return {\n ok: errors.length === 0,\n matched: `${operation.method} ${operation.path}`,\n errors,\n warnings,\n note: 'The contract publishes no request-body schema for this operation, so field-level checks beyond naming could not run.',\n };\n }\n\n const known = new Map(operation.bodyFields.map((f) => [f.name, f]));\n for (const key of keys) {\n if (RETIRED_FIELDS[key] || key.includes('_')) continue; // already reported\n if (!known.has(key)) {\n warnings.push({\n field: key,\n problem: 'not documented on this operation — it will be rejected if the route validates strictly',\n });\n }\n }\n for (const field of operation.bodyFields) {\n const value = (input.body ?? {})[field.name];\n if (value === undefined) {\n if (field.required) errors.push({ field: field.name, problem: 'required field is missing' });\n continue;\n }\n // Closed sets are checked whenever a value is present — an optional field with\n // a bad enum value is still a 400, so skipping optionals hid real errors.\n if (field.enum && field.enum.length > 0 && typeof value === 'string' && !field.enum.includes(value)) {\n errors.push({\n field: field.name,\n problem: `value \"${value}\" is not allowed`,\n suggestion: `one of: ${field.enum.join(', ')}`,\n });\n }\n }\n\n return {\n ok: errors.length === 0,\n matched: `${operation.method} ${operation.path}`,\n errors,\n warnings,\n };\n}\n","/**\n * `search_docs`, answered from an index of `apps/docs` bundled at build time.\n *\n * Scoring mirrors the CLI's proven approach: title hits beat heading hits, which\n * beat body hits, and an exact phrase beats scattered terms. Deliberately simple —\n * the agent gets a title, a canonical docs.usethrottle.dev URL and an excerpt, then\n * fetches the page itself if its client can.\n */\n\nexport interface DocsEntry {\n title: string;\n route: string;\n headings: string[];\n text: string;\n}\n\nexport interface DocsIndex {\n generatedAt: string;\n entries: DocsEntry[];\n}\n\nexport interface DocsHit {\n title: string;\n url: string;\n score: number;\n excerpt: string;\n}\n\nconst DOCS_ORIGIN = 'https://docs.usethrottle.dev';\n\nfunction excerptAround(text: string, needle: string, radius = 160): string {\n const at = text.toLowerCase().indexOf(needle.toLowerCase());\n if (at < 0) return text.slice(0, radius * 2).trim();\n const start = Math.max(0, at - radius);\n const end = Math.min(text.length, at + needle.length + radius);\n return `${start > 0 ? '…' : ''}${text.slice(start, end).trim()}${end < text.length ? '…' : ''}`;\n}\n\nexport function searchDocs(\n index: DocsIndex,\n query: string,\n limit = 5,\n): DocsHit[] {\n const phrase = query.trim().toLowerCase();\n if (!phrase) return [];\n const terms = phrase.split(/\\s+/).filter((t) => t.length > 1);\n\n const scored = index.entries.map((entry) => {\n const title = entry.title.toLowerCase();\n const headings = entry.headings.join(' \u0000 ').toLowerCase();\n const body = entry.text.toLowerCase();\n\n let score = 0;\n if (title === phrase) score += 100;\n else if (title.startsWith(phrase)) score += 60;\n else if (title.includes(phrase)) score += 40;\n if (headings.includes(phrase)) score += 25;\n if (body.includes(phrase)) score += 15;\n\n for (const term of terms) {\n if (title.includes(term)) score += 8;\n if (headings.includes(term)) score += 4;\n if (body.includes(term)) score += 1;\n }\n\n return { entry, score };\n });\n\n return scored\n .filter((s) => s.score > 0)\n .sort((a, b) => b.score - a.score || a.entry.route.localeCompare(b.entry.route))\n .slice(0, Math.max(1, limit))\n .map(({ entry, score }) => ({\n title: entry.title,\n url: `${DOCS_ORIGIN}${entry.route}`,\n score,\n excerpt: excerptAround(entry.text, phrase),\n }));\n}\n","import { ACTIONS } from '@core/action-catalog';\nimport { optional, type ThrottleClient } from './client';\nimport {\n findOperations,\n normalizePath,\n validatePayload,\n type ContractIndex,\n type ContractOperation,\n} from './contract';\nimport { searchDocs, type DocsIndex } from './docs';\n\n/**\n * The OpenAPI snapshot does not carry each route's required scope, but the action\n * catalog does for the verbs it covers. Surfacing it here means `describe_endpoint`\n * can answer \"and what permission do I need?\" instead of leaving the agent to guess.\n */\nfunction coveringAction(\n operation: ContractOperation,\n): { tool?: string; requiredScopes?: readonly string[] } {\n const target = normalizePath(operation.path);\n for (const action of ACTIONS) {\n const hit = action.requests.some(\n (r) => r.method === operation.method && normalizePath(r.path) === target,\n );\n if (hit) return { tool: action.id, requiredScopes: action.scopes };\n }\n return {};\n}\n\nexport interface Identity {\n type: string;\n scopes: string[];\n workspace: { id: string; name: string | null; slug: string | null } | null;\n application: { id: string; name: string | null; slug: string | null } | null;\n environment: {\n id: string;\n slug: string;\n kind: string;\n providerEnvironment: 'sandbox' | 'production';\n };\n apiKey: { id: string; name: string; keyPrefix: string } | null;\n}\n\nexport interface HandlerContext {\n client: ThrottleClient;\n identity: Identity;\n contract: ContractIndex;\n docs: DocsIndex;\n}\n\nexport type Handler = (ctx: HandlerContext, args: Record<string, any>) => Promise<unknown>;\n\nconst page = (args: Record<string, any>) => ({ limit: args.limit, cursor: args.cursor });\n\n/**\n * Handlers for the 0.1.0 surface: reads, docs/contract lookups, and sandbox\n * seeding. Money-moving writes arrive in 0.2.0 with the idempotency layer — the\n * server only registers actions that have a handler here, so the catalog can\n * describe them before this file implements them.\n */\nexport const HANDLERS: Record<string, Handler> = {\n // ---------------------------------------------------------------- identity\n whoami: async (ctx) => ({\n ...ctx.identity,\n note:\n ctx.identity.environment.providerEnvironment === 'production'\n ? 'This credential is pinned to PRODUCTION. Reads return live data.'\n : 'This credential is pinned to a non-production environment. Nothing here is live data.',\n }),\n\n // ------------------------------------------------------- docs and contract\n search_docs: async (ctx, args) => {\n const hits = searchDocs(ctx.docs, String(args.query ?? ''), Number(args.limit ?? 5));\n return hits.length > 0\n ? { hits }\n : { hits: [], note: 'No documentation matched. Try fewer or more general terms.' };\n },\n\n describe_endpoint: async (ctx, args) => {\n const operations = findOperations(ctx.contract, {\n path: String(args.path ?? ''),\n method: args.method ? String(args.method) : undefined,\n });\n if (operations.length === 0) {\n return {\n operations: [],\n note: 'No operation matched. Paths look like /api/v1/orders; try a shorter fragment such as \"orders\".',\n };\n }\n return {\n operations: operations.slice(0, 8).map((op) => ({ ...op, ...coveringAction(op) })),\n truncated: operations.length > 8 ? operations.length - 8 : undefined,\n };\n },\n\n validate_payload: async (ctx, args) =>\n validatePayload(ctx.contract, {\n method: String(args.method ?? 'POST'),\n path: String(args.path ?? ''),\n body: (args.body ?? {}) as Record<string, unknown>,\n }),\n\n // ------------------------------------------------------------- generic read\n api_get: async (ctx, args) => {\n const path = String(args.path ?? '');\n if (!path.startsWith('/api/v1/')) {\n throw new Error(\n `Refusing to call \"${path}\". api_get only reads paths beginning with /api/v1/ on the configured Throttle host.`,\n );\n }\n return ctx.client.get(path);\n },\n\n // ------------------------------------------------------------------ orders\n search_orders: async (ctx, args) =>\n ctx.client.list('/api/v1/orders', {\n q: args.q,\n status: args.status,\n paymentStatus: args.paymentStatus,\n ...page(args),\n }),\n\n get_order: async (ctx, args) => {\n const id = String(args.id);\n const order = await ctx.client.get(`/api/v1/orders/${id}`);\n const [payments, returns, fulfillments] = await Promise.all([\n optional(() => ctx.client.list(`/api/v1/orders/${id}/payments`)),\n optional(() => ctx.client.list(`/api/v1/orders/${id}/returns`)),\n optional(() => ctx.client.list(`/api/v1/orders/${id}/fulfillments`)),\n ]);\n return {\n order,\n payments: payments.ok ? payments.value.data : payments.unavailable,\n returns: returns.ok ? returns.value.data : returns.unavailable,\n fulfillments: fulfillments.ok ? fulfillments.value.data : fulfillments.unavailable,\n };\n },\n\n // --------------------------------------------------------------- customers\n search_customers: async (ctx, args) =>\n ctx.client.list('/api/v1/customers', { q: args.q, ...page(args) }),\n\n get_customer: async (ctx, args) => {\n const id = String(args.id);\n const customer = await ctx.client.get(`/api/v1/customers/${id}`);\n const [addresses, subscriptions] = await Promise.all([\n optional(() => ctx.client.list(`/api/v1/customers/${id}/addresses`)),\n optional(() => ctx.client.list('/api/v1/subscriptions', { customerId: id })),\n ]);\n return {\n customer,\n addresses: addresses.ok ? addresses.value.data : addresses.unavailable,\n subscriptions: subscriptions.ok ? subscriptions.value.data : subscriptions.unavailable,\n };\n },\n\n // ----------------------------------------------------------- subscriptions\n list_subscriptions: async (ctx, args) =>\n ctx.client.list('/api/v1/subscriptions', {\n customerId: args.customerId,\n status: args.status,\n ...page(args),\n }),\n\n get_subscription: async (ctx, args) => ctx.client.get(`/api/v1/subscriptions/${String(args.id)}`),\n\n // ------------------------------------------------------------------ quotes\n search_quotes: async (ctx, args) =>\n ctx.client.list('/api/v1/quotes', { status: args.status, ...page(args) }),\n\n get_quote: async (ctx, args) => ctx.client.get(`/api/v1/quotes/${String(args.id)}`),\n\n // ---------------------------------------------------------------- invoices\n list_invoices: async (ctx, args) =>\n ctx.client.list('/api/v1/invoices', { status: args.status, ...page(args) }),\n\n receivables_aging: async (ctx) => ctx.client.get('/api/v1/invoices/aging'),\n\n // --------------------------------------------------------------- discounts\n search_discounts: async (ctx, args) =>\n ctx.client.list('/api/v1/discounts', {\n q: args.q,\n code: args.code,\n type: args.type,\n isActive: args.isActive,\n createdAfter: args.createdAfter,\n createdBefore: args.createdBefore,\n ...page(args),\n }),\n\n get_discount: async (ctx, args) => ctx.client.get(`/api/v1/discounts/${String(args.id)}`),\n\n // ---------------------------------------------------------------- payments\n search_payments: async (ctx, args) =>\n ctx.client.list('/api/v1/payments', {\n method: args.method,\n status: args.status,\n // The route only accepts these as snake_case query params -- confirmed\n // by reading its querystring schema directly, not assumed from the\n // platform's usual camelCase convention.\n order_id: args.orderId,\n aging: args.aging,\n due_from: args.dueFrom,\n due_to: args.dueTo,\n amount_min: args.amountMin,\n amount_max: args.amountMax,\n ...page(args),\n }),\n\n get_payment: async (ctx, args) => {\n const id = String(args.id);\n const payment = await ctx.client.get(`/api/v1/payments/${id}`);\n const transactions = await optional(() => ctx.client.list(`/api/v1/payments/${id}/transactions`));\n return {\n payment,\n transactions: transactions.ok ? transactions.value.data : transactions.unavailable,\n };\n },\n\n // ---------------------------------------------------------------- invoices\n get_invoice: async (ctx, args) => ctx.client.get(`/api/v1/invoices/${String(args.id)}`),\n\n // ------------------------------------------------------------------ carts\n list_abandoned_carts: async (ctx, args) => {\n const [carts, summary] = await Promise.all([\n optional(() => ctx.client.list('/api/v1/abandoned-carts', { ...page(args) })),\n optional(() => ctx.client.get('/api/v1/abandoned-carts/summary', { sinceDays: args.sinceDays })),\n ]);\n return {\n carts: carts.ok ? carts.value.data : carts.unavailable,\n summary: summary.ok ? summary.value : summary.unavailable,\n };\n },\n\n // --------------------------------------------------------------- debugging\n search_events: async (ctx, args) =>\n ctx.client.list('/api/v1/events', {\n type: args.type,\n entityType: args.entityType,\n entityId: args.entityId,\n ...page(args),\n }),\n\n list_webhook_deliveries: async (ctx, args) =>\n ctx.client.list('/api/v1/webhook-deliveries', {\n endpointId: args.endpointId,\n status: args.status,\n limit: args.limit,\n }),\n\n get_webhook_delivery: async (ctx, args) =>\n ctx.client.get(`/api/v1/webhook-deliveries/${String(args.id)}`),\n\n send_test_webhook: async (ctx, args) =>\n ctx.client.post(`/api/v1/webhook-endpoints/${String(args.id)}/test`, {\n body: { eventType: args.eventType },\n idempotencyKey: `mcp-send-test-webhook-${String(args.id)}-${Date.now()}`,\n }),\n\n replay_webhook_delivery: async (ctx, args) =>\n ctx.client.post(`/api/v1/webhook-deliveries/${String(args.id)}/replay`, {\n idempotencyKey: `mcp-replay-webhook-delivery-${String(args.id)}-${Date.now()}`,\n }),\n\n explain_checkout_failure: async (ctx, args) => {\n const id = String(args.id);\n const session = await optional(() => ctx.client.get<any>(`/api/v1/checkout-sessions/${id}`));\n if (!session.ok) {\n return {\n note: `No checkout session ${id} (${session.unavailable}). If this is a cart id, read the cart with api_get /api/v1/carts/${id} and search_events for its activity.`,\n };\n }\n const cartId = (session.value?.cartId as string | undefined) ?? undefined;\n const [cart, sessionEvents, cartEvents, deliveries] = await Promise.all([\n optional(() => ctx.client.get(`/api/v1/checkout-sessions/${id}/cart`)),\n optional(() => ctx.client.list('/api/v1/events', { entityId: id, limit: 25 })),\n cartId\n ? optional(() => ctx.client.list('/api/v1/events', { entityId: cartId, limit: 25 }))\n : Promise.resolve({ ok: true as const, value: { data: [], pagination: null } }),\n optional(() => ctx.client.list('/api/v1/webhook-deliveries', { limit: 15 })),\n ]);\n return {\n session: session.value,\n cart: cart.ok ? cart.value : cart.unavailable,\n events: [\n ...(sessionEvents.ok ? sessionEvents.value.data : []),\n ...(cartEvents.ok ? cartEvents.value.data : []),\n ],\n eventsUnavailable: sessionEvents.ok ? undefined : sessionEvents.unavailable,\n recentWebhookDeliveries: deliveries.ok ? deliveries.value.data : deliveries.unavailable,\n hint: 'Compare the session state against the events: a session that never emitted checkout_started usually means the browser SDK failed before submitting, not a payment decline.',\n };\n },\n\n // ------------------------------------------------------------ sandbox seed\n seed_test_data: async (ctx, args) => {\n // Belt and braces: the server also refuses to register this tool against a\n // production credential, but a guard at the call site means no future\n // registration change can turn it into a live-data generator.\n if (ctx.identity.environment.providerEnvironment === 'production') {\n throw new Error(\n 'seed_test_data refuses to run against a production environment. Use a non-production API key.',\n );\n }\n const stamp = Date.now();\n const customer = await ctx.client.post<any>('/api/v1/customers', {\n body: {\n email: String(args.customerEmail ?? `mcp-seed-${stamp}@example.test`),\n firstName: 'Seed',\n lastName: 'Customer',\n },\n idempotencyKey: `mcp-seed-customer-${stamp}`,\n });\n const cart = await ctx.client.post<any>('/api/v1/carts', {\n // Unlike /api/v1/customers, cart creation requires applicationId\n // explicitly in the body (it's cross-checked against the caller's own\n // authenticated application, not inferred) -- omitting it is a real\n // 400 missing_application_id from the live API, not a hypothetical.\n body: { applicationId: ctx.identity.application?.id, customerId: customer?.id },\n idempotencyKey: `mcp-seed-cart-${stamp}`,\n });\n const requested = Array.isArray(args.lineItems) && args.lineItems.length > 0\n ? (args.lineItems as Record<string, unknown>[])\n : [{ name: 'Seed widget', unitPrice: 2500, quantity: 2 }];\n const items: unknown[] = [];\n for (const [index, item] of requested.entries()) {\n items.push(\n await ctx.client.post(`/api/v1/carts/${cart?.id}/items`, {\n body: item,\n idempotencyKey: `mcp-seed-item-${stamp}-${index}`,\n }),\n );\n }\n const order = await ctx.client.post(`/api/v1/carts/${cart?.id}/finalize`, {\n idempotencyKey: `mcp-seed-finalize-${stamp}`,\n });\n return {\n environment: ctx.identity.environment.slug,\n customer,\n cart,\n lineItems: items,\n order,\n note: 'Seeded a finalized DRAFT order. No payment was captured — that needs a browser-tokenised payment method, which a server-side key cannot produce.',\n };\n },\n\n // -------------------------------------------------------------- money/mail\n manage_subscription: async (ctx, args) => {\n const id = String(args.id);\n const action = String(args.action);\n if (action !== 'pause' && action !== 'resume') {\n throw new Error(`manage_subscription: action must be \"pause\" or \"resume\", got \"${action}\".`);\n }\n return ctx.client.post(`/api/v1/subscriptions/${id}/${action}`, {\n idempotencyKey: `mcp-manage-subscription-${id}-${action}-${Date.now()}`,\n });\n },\n\n create_quote: async (ctx, args) =>\n // The real route's body shape differs from this tool's flatter,\n // model-facing input: line items are \"items\" (not \"lineItems\"), Net-N\n // terms are nested under paymentTerms.netN with an explicit mode (not a\n // flat \"netN\"), and the buyer-visible note field is \"buyerNote\" (not\n // \"notes\"). Confirmed against packages/platform-api/src/validation/quotes.ts's\n // actual zod schema after a live call 400'd with unrecognized_keys.\n ctx.client.post('/api/v1/quotes', {\n body: {\n customerId: args.customerId,\n items: args.items,\n expiresAt: args.expiresAt,\n paymentTerms:\n args.netN !== undefined ? { mode: 'net_terms', netN: args.netN } : undefined,\n buyerNote: args.notes,\n },\n idempotencyKey: `mcp-create-quote-${String(args.customerId)}-${Date.now()}`,\n }),\n\n get_business_summary: async (ctx, args) =>\n ctx.client.get('/api/v1/analytics/business-summary', { period: args.period }),\n\n get_attention_digest: async (ctx) => ctx.client.get('/api/v1/analytics/attention-digest'),\n\n // ------------------------------------------------------------- extensions\n list_extension_installations: async (ctx, args) =>\n ctx.client.list('/api/v1/installations', { status: args.status, ...page(args) }),\n\n // ------------------------------------------------------------- connectors\n get_connector_routing: async (ctx) => {\n const [paymentRouting, routingConnectors, cardDecline, otherDecline] = await Promise.all([\n optional(() => ctx.client.get('/api/v1/payment-routing')),\n optional(() => ctx.client.get('/api/v1/routing-connectors')),\n optional(() => ctx.client.get('/api/v1/card-decline')),\n optional(() => ctx.client.get('/api/v1/other-decline')),\n ]);\n return {\n paymentRouting: paymentRouting.ok ? paymentRouting.value : paymentRouting.unavailable,\n routingConnectors: routingConnectors.ok ? routingConnectors.value : routingConnectors.unavailable,\n cardDecline: cardDecline.ok ? cardDecline.value : cardDecline.unavailable,\n otherDecline: otherDecline.ok ? otherDecline.value : otherDecline.unavailable,\n };\n },\n\n get_integration_status: async (ctx) => {\n const [connectors, endpoints, coverage] = await Promise.all([\n optional(() => ctx.client.list('/api/v1/connectors')),\n optional(() => ctx.client.list('/api/v1/webhook-endpoints')),\n optional(() => ctx.client.get('/api/v1/webhook-endpoints/coverage')),\n ]);\n return {\n environment: ctx.identity.environment,\n workspace: ctx.identity.workspace,\n application: ctx.identity.application,\n connectors: connectors.ok ? connectors.value.data : connectors.unavailable,\n webhookEndpoints: endpoints.ok ? endpoints.value.data : endpoints.unavailable,\n unsubscribedEvents: coverage.ok ? coverage.value : coverage.unavailable,\n };\n },\n\n // --------------------------------------------------------------- workspace\n get_workspace_settings: async (ctx) => ctx.client.get('/api/v1/merchants/me'),\n\n get_audit_log: async (ctx, args) => ctx.client.list('/api/v1/audit-log', { limit: args.limit }),\n};\n","import { z, type ZodTypeAny } from 'zod';\nimport type { ActionField } from '@core/action-catalog';\n\n/**\n * Projects the catalog's portable field descriptors into a zod shape for the MCP\n * SDK. The catalog stays zod-free on purpose (Zapier and Make runtimes never need\n * it), so the derivation lives here — the one place that does.\n */\nexport function fieldsToZodShape(fields: readonly ActionField[]): Record<string, ZodTypeAny> {\n const shape: Record<string, ZodTypeAny> = {};\n for (const field of fields) {\n shape[field.name] = applyModifiers(field, baseType(field));\n }\n return shape;\n}\n\nfunction baseType(field: ActionField): ZodTypeAny {\n if (field.enum && field.enum.length > 0) {\n return z.enum([...field.enum] as [string, ...string[]]);\n }\n switch (field.type) {\n case 'string':\n return z.string();\n case 'number':\n return z.number();\n case 'boolean':\n return z.boolean();\n case 'array':\n return z.array(z.unknown());\n case 'object':\n return z.record(z.unknown());\n }\n}\n\nfunction applyModifiers(field: ActionField, type: ZodTypeAny): ZodTypeAny {\n const described = type.describe(field.description);\n if (field.required) return described;\n return field.default === undefined ? described.optional() : described.default(field.default);\n}\n","import { readFileSync } from 'node:fs';\nimport type { DocsIndex } from './docs';\nimport type { ContractIndex } from './contract';\n\n/**\n * Indexes are generated into `dist/` at build time and shipped in the tarball. A\n * missing index degrades that one tool instead of preventing boot — the API tools\n * are unaffected and the failure is legible on stderr.\n */\nfunction loadIndex<T extends { generatedAt: string }>(file: string, empty: T, label: string): T {\n try {\n return JSON.parse(readFileSync(new URL(`./${file}`, import.meta.url), 'utf8')) as T;\n } catch {\n process.stderr.write(\n `throttle-mcp: ${label} index missing (${file}); that tool will return no results. Run \"pnpm --filter @usethrottle/mcp build:indexes\".\\n`,\n );\n return empty;\n }\n}\n\nexport function loadDocsIndex(): DocsIndex {\n return loadIndex<DocsIndex>('docs-index.json', { generatedAt: '', entries: [] }, 'docs');\n}\n\nexport function loadContractIndex(): ContractIndex {\n return loadIndex<ContractIndex>('contract-index.json', { generatedAt: '', operations: [] }, 'contract');\n}\n"],"mappings":"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","names":[]}
package/dist/lib.d.cts ADDED
@@ -0,0 +1,165 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { ActionDefinition } from '@core/action-catalog';
3
+
4
+ interface AuthCtx {
5
+ apiKey: string;
6
+ apiBaseUrl: string;
7
+ }
8
+ interface RequestOptions {
9
+ body?: unknown;
10
+ query?: Record<string, unknown>;
11
+ /**
12
+ * Sent as `Idempotency-Key`. Writes must pass one: an agent that retries is the
13
+ * normal case, and the API dedupes on
14
+ * `(workspace, application, environment, key, method, path)`.
15
+ */
16
+ idempotencyKey?: string;
17
+ }
18
+ interface Pagination {
19
+ cursor: string | null;
20
+ hasMore: boolean;
21
+ }
22
+ interface ListResult<T> {
23
+ data: T[];
24
+ pagination: Pagination | null;
25
+ }
26
+ type Fetcher = typeof fetch;
27
+ declare class ThrottleClient {
28
+ private readonly auth;
29
+ private readonly fetchImpl;
30
+ constructor(auth: AuthCtx, fetchImpl?: Fetcher);
31
+ private requestJson;
32
+ /** Unwraps the `{ data }` envelope. Key presence, not `??` — `{data: null}` unwraps to null. */
33
+ get<T>(path: string, query?: Record<string, unknown>): Promise<T>;
34
+ list<T>(path: string, query?: Record<string, unknown>): Promise<ListResult<T>>;
35
+ post<T>(path: string, options?: RequestOptions): Promise<T>;
36
+ }
37
+
38
+ /**
39
+ * `describe_endpoint` and `validate_payload`, answered from the OpenAPI contract
40
+ * bundled at build time. No network, no API quota.
41
+ *
42
+ * Why this exists: Throttle's public API is strict camelCase and rejects the
43
+ * retired snake_case aliases — and those aliases are exactly what a model writing
44
+ * commerce code will guess, because that is what the rest of the internet's
45
+ * examples look like. Naming the replacement turns a 400-debug loop into one call.
46
+ */
47
+ interface ContractField {
48
+ name: string;
49
+ type?: string;
50
+ required: boolean;
51
+ description?: string;
52
+ enum?: string[];
53
+ }
54
+ interface ContractOperation {
55
+ method: string;
56
+ /** OpenAPI-style path, e.g. `/api/v1/customers/{customerId}/addresses/{id}`. */
57
+ path: string;
58
+ summary?: string;
59
+ description?: string;
60
+ pathParams: string[];
61
+ queryParams: ContractField[];
62
+ bodyFields: ContractField[] | null;
63
+ }
64
+ interface ContractIndex {
65
+ generatedAt: string;
66
+ operations: ContractOperation[];
67
+ }
68
+
69
+ /**
70
+ * `search_docs`, answered from an index of `apps/docs` bundled at build time.
71
+ *
72
+ * Scoring mirrors the CLI's proven approach: title hits beat heading hits, which
73
+ * beat body hits, and an exact phrase beats scattered terms. Deliberately simple —
74
+ * the agent gets a title, a canonical docs.usethrottle.dev URL and an excerpt, then
75
+ * fetches the page itself if its client can.
76
+ */
77
+ interface DocsEntry {
78
+ title: string;
79
+ route: string;
80
+ headings: string[];
81
+ text: string;
82
+ }
83
+ interface DocsIndex {
84
+ generatedAt: string;
85
+ entries: DocsEntry[];
86
+ }
87
+
88
+ interface Identity {
89
+ type: string;
90
+ scopes: string[];
91
+ workspace: {
92
+ id: string;
93
+ name: string | null;
94
+ slug: string | null;
95
+ } | null;
96
+ application: {
97
+ id: string;
98
+ name: string | null;
99
+ slug: string | null;
100
+ } | null;
101
+ environment: {
102
+ id: string;
103
+ slug: string;
104
+ kind: string;
105
+ providerEnvironment: 'sandbox' | 'production';
106
+ };
107
+ apiKey: {
108
+ id: string;
109
+ name: string;
110
+ keyPrefix: string;
111
+ } | null;
112
+ }
113
+ interface HandlerContext {
114
+ client: ThrottleClient;
115
+ identity: Identity;
116
+ contract: ContractIndex;
117
+ docs: DocsIndex;
118
+ }
119
+
120
+ declare const VERSION: string;
121
+ interface RegistrationPolicy {
122
+ identity: Identity;
123
+ allowWrites: boolean;
124
+ allowLiveWrites: boolean;
125
+ }
126
+ /**
127
+ * Which tools this session gets. Pure and exported so the policy is testable
128
+ * without standing up a transport.
129
+ *
130
+ * Four independent gates, in order of how expensive it is to get them wrong:
131
+ *
132
+ * 1. **Implemented.** `0.1.0` ships the read/sandbox half; the catalog describes
133
+ * the money writes before this package implements them.
134
+ * 2. **Scope.** Delegated to the catalog's `canRunAction`, which uses the API's own
135
+ * `hasScope`. A tool the credential cannot execute is not registered at all,
136
+ * rather than failing at call time — the model never sees an affordance it
137
+ * cannot use.
138
+ * 3. **Intent.** Holding a write scope means the credential *may* write; it does
139
+ * not mean the operator intended this session to. That is `--allow-writes`.
140
+ * 4. **Blast radius.** Against a production credential, writes need
141
+ * `--allow-live-writes` on top. Sandbox-only actions invert the rule: they are
142
+ * free in a non-production environment and forbidden in production regardless
143
+ * of flags.
144
+ */
145
+ declare function registerableActions(policy: RegistrationPolicy): ActionDefinition[];
146
+ /**
147
+ * The server's `instructions`, which most clients put in front of the model before
148
+ * it picks a tool. Leads with the environment because the single most damaging
149
+ * mistake an agent can make here is not knowing whether it is looking at live data.
150
+ */
151
+ declare function buildInstructions(identity: Identity, actions: ActionDefinition[], policy: {
152
+ allowWrites: boolean;
153
+ allowLiveWrites: boolean;
154
+ }): string;
155
+ interface CreateServerOptions extends RegistrationPolicy {
156
+ client: ThrottleClient;
157
+ contract: ContractIndex;
158
+ docs: DocsIndex;
159
+ }
160
+ declare function createServer(options: CreateServerOptions): McpServer;
161
+
162
+ declare function loadDocsIndex(): DocsIndex;
163
+ declare function loadContractIndex(): ContractIndex;
164
+
165
+ export { type ContractIndex, type CreateServerOptions, type DocsIndex, type HandlerContext, type Identity, type RegistrationPolicy, ThrottleClient, VERSION, buildInstructions, createServer, loadContractIndex, loadDocsIndex, registerableActions };