@zackbart/connecta 0.28.1 → 0.29.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.
- package/CHANGELOG.md +788 -5
- package/README.md +62 -42
- package/bin/connecta.mjs +110 -139
- package/bin/meta-tool-names.d.mts +2 -0
- package/bin/meta-tool-names.mjs +9 -0
- package/bin/version.mjs +3 -0
- package/dist/access-tokens.js +53 -63
- package/dist/activity-request.js +8 -0
- package/dist/activity.d.ts +76 -42
- package/dist/activity.js +110 -42
- package/dist/auth/clerk-sdk/client.d.ts +65 -0
- package/dist/auth/clerk-sdk/client.js +5 -0
- package/dist/auth/clerk-sdk/generated.js +1845 -0
- package/dist/auth/clerk-transport.js +19 -0
- package/dist/auth/clerk.d.ts +17 -7
- package/dist/auth/clerk.js +189 -107
- package/dist/auth/cloudflare-access.js +25 -26
- package/dist/auth/downstream-client-metadata.d.ts +29 -0
- package/dist/auth/downstream-client-metadata.js +133 -0
- package/dist/auth/downstream-oauth.js +1584 -1580
- package/dist/auth/downstream-revocation.js +106 -0
- package/dist/auth/oauth-token-response.js +231 -0
- package/dist/auth/oauth-v2-migration.js +116 -0
- package/dist/auth/static-oauth.js +93 -71
- package/dist/auth-elicitation.js +283 -0
- package/dist/branding.d.ts +8 -16
- package/dist/branding.js +26 -59
- package/dist/byte-read-response.js +39 -0
- package/dist/call-admission.js +12 -16
- package/dist/catalog-cache.js +739 -0
- package/dist/catalog-drift.d.ts +50 -15
- package/dist/catalog-drift.js +365 -128
- package/dist/catalog-fingerprint.js +2 -4
- package/dist/catalog-freshness.js +13 -0
- package/dist/catalog-limits.js +2 -2
- package/dist/catalog-service.js +368 -224
- package/dist/catalog.js +43 -84
- package/dist/concurrency.js +3 -4
- package/dist/config-defaults.d.ts +39 -0
- package/dist/config-defaults.js +46 -0
- package/dist/config-schema.d.ts +181 -0
- package/dist/config-schema.js +435 -0
- package/dist/config-value-sources.js +102 -0
- package/dist/config.d.ts +631 -0
- package/dist/config.js +503 -0
- package/dist/connector-access.d.ts +1 -0
- package/dist/connector-access.js +13 -15
- package/dist/connector-caller.d.ts +8 -0
- package/dist/connector-caller.js +15 -6
- package/dist/connector-scope.js +1 -1
- package/dist/connectors/api-connector.d.ts +59 -7
- package/dist/connectors/api-connector.js +106 -19
- package/dist/connectors/api.js +4 -1
- package/dist/connectors/guarded-fetch.d.ts +144 -0
- package/dist/connectors/guarded-fetch.js +84 -35
- package/dist/connectors/negotiation-cache.js +46 -0
- package/dist/connectors/option-shapes.js +27 -0
- package/dist/connectors/remote-mcp.d.ts +30 -4
- package/dist/connectors/remote-mcp.js +1774 -320
- package/dist/connectors/resource-uri.js +335 -0
- package/dist/credential-contract.d.ts +10 -0
- package/dist/credential-rules.js +1 -3
- package/dist/credential-url.js +108 -0
- package/dist/credentials.d.ts +6 -1
- package/dist/credentials.js +27 -18
- package/dist/d1.d.ts +130 -0
- package/dist/d1.js +290 -0
- package/dist/describe-config.d.ts +165 -0
- package/dist/describe-config.js +315 -0
- package/dist/described.js +106 -0
- package/dist/downstream-input-context.js +119 -0
- package/dist/downstream-input.js +323 -0
- package/dist/errors.d.ts +97 -20
- package/dist/errors.js +158 -80
- package/dist/execute.js +453 -305
- package/dist/executor-admission.d.ts +1 -0
- package/dist/executor-admission.js +11 -15
- package/dist/executor-contract.d.ts +20 -0
- package/dist/executor-contract.js +48 -0
- package/dist/executor-result.js +24 -9
- package/dist/executors/quickjs-child.js +3 -4
- package/dist/executors/quickjs-runtime.js +147 -59
- package/dist/executors/quickjs.js +29 -35
- package/dist/favicon.js +1 -2
- package/dist/fix-prompt.js +1 -3
- package/dist/guest-runtime.js +188 -0
- package/dist/guest-types.d.ts +176 -0
- package/dist/guest-types.js +1 -0
- package/dist/html-security.js +24 -0
- package/dist/identity.js +1 -3
- package/dist/inbound-credential.js +52 -0
- package/dist/index.d.ts +24 -256
- package/dist/index.js +65 -478
- package/dist/invocation-auth.js +69 -0
- package/dist/invocation.js +230 -73
- package/dist/json-schema.d.ts +1 -1
- package/dist/mcp-client-context.js +35 -0
- package/dist/mcp-result.js +11 -7
- package/dist/meta-output.js +76 -0
- package/dist/meta-tool-names.d.ts +2 -0
- package/dist/meta-tool-names.js +3 -0
- package/dist/meta-tools.js +285 -209
- package/dist/module-contracts.d.ts +8 -23
- package/dist/node.d.ts +0 -2
- package/dist/node.js +2 -2
- package/dist/oauth-callback-outcome.js +1 -3
- package/dist/oauth-handoff.js +117 -0
- package/dist/oauth-sealing.js +20 -0
- package/dist/operator-record.d.ts +137 -0
- package/dist/operator-record.js +420 -0
- package/dist/operator-ui/assets.js +31 -0
- package/dist/operator-ui/contract.d.ts +72 -0
- package/dist/operator-ui/contract.js +1 -0
- package/dist/operator-ui/fix-prompts.d.ts +18 -0
- package/dist/operator-ui/generated.js +5 -4
- package/dist/operator-ui/model.d.ts +12 -87
- package/dist/operator-ui/model.js +2 -9
- package/dist/operator-ui/setup-commands.js +1 -3
- package/dist/operator-ui/view.d.ts +323 -0
- package/dist/operator-ui/view.js +62 -189
- package/dist/page-styles.js +2 -3
- package/dist/program-source.js +14 -2
- package/dist/{exempt-writes.js → program-writes.js} +55 -18
- package/dist/provider.d.ts +142 -0
- package/dist/provider.js +187 -0
- package/dist/providers/_shared/google/result-size.js +57 -0
- package/dist/providers/_shared/google/service-account.d.ts +58 -0
- package/dist/providers/_shared/google/service-account.js +500 -0
- package/dist/providers/_shared/google/workspace.d.ts +276 -0
- package/dist/providers/_shared/google/workspace.js +518 -0
- package/dist/providers/{basecamp.d.ts → basecamp/index.d.ts} +6 -28
- package/dist/providers/basecamp/index.js +997 -0
- package/dist/providers/basecamp/skill.generated.js +9 -0
- package/dist/providers/{breeze.d.ts → breeze/index.d.ts} +2 -2
- package/dist/providers/{breeze.js → breeze/index.js} +184 -140
- package/dist/providers/breeze/skill.generated.js +9 -0
- package/dist/providers/{ccb.d.ts → ccb/index.d.ts} +2 -2
- package/dist/providers/{ccb.js → ccb/index.js} +271 -116
- package/dist/providers/ccb/skill.generated.js +9 -0
- package/dist/providers/{cloudflare.d.ts → cloudflare/index.d.ts} +8 -7
- package/dist/providers/{cloudflare.js → cloudflare/index.js} +171 -738
- package/dist/providers/cloudflare/skill.generated.js +10 -0
- package/dist/providers/docs/index.d.ts +54 -0
- package/dist/providers/docs/index.js +1237 -0
- package/dist/providers/docs/skill.generated.js +9 -0
- package/dist/providers/drive/index.d.ts +53 -0
- package/dist/providers/drive/index.js +1523 -0
- package/dist/providers/drive/skill.generated.js +9 -0
- package/dist/providers/forms/index.d.ts +54 -0
- package/dist/providers/forms/index.js +1217 -0
- package/dist/providers/forms/skill.generated.js +11 -0
- package/dist/providers/github/auth.d.ts +32 -0
- package/dist/providers/github/auth.js +361 -0
- package/dist/providers/github/hosted.js +218 -0
- package/dist/providers/github/index.d.ts +13 -0
- package/dist/providers/github/index.js +140 -0
- package/dist/providers/github/key.js +100 -0
- package/dist/providers/github/rest.js +321 -0
- package/dist/providers/github/scope.d.ts +29 -0
- package/dist/providers/github/scope.js +124 -0
- package/dist/providers/github/skill.generated.js +8 -0
- package/dist/providers/gmail/index.d.ts +51 -0
- package/dist/providers/gmail/index.js +1436 -0
- package/dist/providers/gmail/skill.generated.js +9 -0
- package/dist/providers/{linear.d.ts → linear/index.d.ts} +11 -14
- package/dist/providers/linear/index.js +352 -0
- package/dist/providers/linear/skill.generated.js +8 -0
- package/dist/providers/{mixpanel.d.ts → mixpanel/index.d.ts} +5 -10
- package/dist/providers/mixpanel/index.js +416 -0
- package/dist/providers/mixpanel/skill.generated.js +9 -0
- package/dist/providers/{notion.d.ts → notion/index.d.ts} +8 -8
- package/dist/providers/{notion.js → notion/index.js} +226 -239
- package/dist/providers/notion/skill.generated.js +10 -0
- package/dist/providers/{overflow.d.ts → overflow/index.d.ts} +2 -2
- package/dist/providers/{overflow.js → overflow/index.js} +74 -111
- package/dist/providers/overflow/skill.generated.js +8 -0
- package/dist/providers/{planning-center.d.ts → planning-center/index.d.ts} +2 -2
- package/dist/providers/{planning-center.js → planning-center/index.js} +264 -104
- package/dist/providers/planning-center/skill.generated.js +10 -0
- package/dist/providers/{revenuecat.d.ts → revenuecat/index.d.ts} +5 -10
- package/dist/providers/revenuecat/index.js +557 -0
- package/dist/providers/revenuecat/skill.generated.js +11 -0
- package/dist/providers/sheets/index.d.ts +54 -0
- package/dist/providers/sheets/index.js +1237 -0
- package/dist/providers/sheets/skill.generated.js +10 -0
- package/dist/providers/slides/index.d.ts +53 -0
- package/dist/providers/slides/index.js +2645 -0
- package/dist/providers/slides/skill.generated.js +9 -0
- package/dist/providers/{stripe.d.ts → stripe/index.d.ts} +5 -12
- package/dist/providers/stripe/index.js +266 -0
- package/dist/providers/stripe/skill.generated.js +11 -0
- package/dist/providers/{tithely.d.ts → tithely/index.d.ts} +2 -2
- package/dist/providers/{tithely.js → tithely/index.js} +60 -91
- package/dist/providers/tithely/skill.generated.js +8 -0
- package/dist/providers/{vercel.d.ts → vercel/index.d.ts} +8 -8
- package/dist/providers/vercel/index.js +1038 -0
- package/dist/providers/vercel/mcp-ownership.js +212 -0
- package/dist/providers/vercel/skill.generated.js +11 -0
- package/dist/registry.d.ts +108 -171
- package/dist/registry.js +513 -925
- package/dist/request-state.js +21 -0
- package/dist/resource-read.js +100 -0
- package/dist/result-shapes.js +17 -49
- package/dist/retired-toolkits.js +1 -1
- package/dist/routes/access-tokens.js +3 -6
- package/dist/routes/activity-context.js +21 -0
- package/dist/routes/activity-disclosure.js +40 -0
- package/dist/routes/activity.js +59 -21
- package/dist/routes/actor-labels.js +3 -50
- package/dist/routes/connect.js +221 -0
- package/dist/routes/credentials.js +15 -27
- package/dist/routes/mcp.js +356 -130
- package/dist/routes/oauth-client-metadata.js +15 -0
- package/dist/routes/oauth-management.js +45 -107
- package/dist/routes/oauth.js +110 -57
- package/dist/routes/operator.js +3 -3
- package/dist/routes/shared.d.ts +25 -64
- package/dist/routes/shared.js +160 -80
- package/dist/routes/skills.js +30 -0
- package/dist/routes/ui-config.js +225 -0
- package/dist/routes/ui-data.js +40 -35
- package/dist/routes/ui.js +66 -56
- package/dist/runtime/admission.js +4 -2
- package/dist/runtime/call-admission.js +3 -1
- package/dist/runtime/connector-scope.js +1 -4
- package/dist/runtime/run.js +10 -39
- package/dist/runtime/services.js +12 -117
- package/dist/runtime/shared-read.js +1 -3
- package/dist/runtime/storage.js +8 -1
- package/dist/sent-secrets.d.ts +52 -0
- package/dist/sent-secrets.js +474 -0
- package/dist/server.js +28 -71
- package/dist/skills.js +406 -174
- package/dist/sqlite.d.ts +48 -0
- package/dist/sqlite.js +166 -0
- package/dist/storage/keys.js +428 -0
- package/dist/storage/memory.js +7 -0
- package/dist/storage/sql.d.ts +66 -0
- package/dist/storage/sql.js +534 -0
- package/dist/timeout.js +4 -2
- package/dist/tool-name.js +17 -0
- package/dist/tool-safety.d.ts +9 -35
- package/dist/tool-safety.js +20 -40
- package/dist/types.d.ts +320 -54
- package/dist/types.js +0 -1
- package/dist/ui.d.ts +7 -19
- package/dist/ui.js +76 -90
- package/dist/url-safety.js +3 -6
- package/dist/usage-guide.js +137 -0
- package/dist/validate.d.ts +7 -0
- package/dist/validate.js +309 -47
- package/dist/version.d.ts +1 -7
- package/dist/version.js +3 -7
- package/dist/worker.d.ts +11 -0
- package/dist/worker.js +434 -0
- package/documentation/architecture.md +664 -231
- package/documentation/auth.md +936 -546
- package/documentation/code-mode.md +501 -312
- package/documentation/meta-tools.md +449 -200
- package/documentation/operator-tests.md +93 -0
- package/documentation/provider-migration-0.29.md +60 -0
- package/examples/worker/AGENTS.md +34 -12
- package/examples/worker/README.md +286 -255
- package/examples/worker/kv-to-d1.wrangler.jsonc +26 -0
- package/examples/worker/scripts/copy-kv-to-d1.mjs +162 -0
- package/examples/worker/src/connecta.config.ts +151 -0
- package/examples/worker/src/index.ts +14 -197
- package/examples/worker/wrangler.jsonc +15 -35
- package/package.json +120 -54
- package/templates/node/.dockerignore +1 -2
- package/templates/node/.env.example +20 -21
- package/templates/node/AGENTS.md +21 -17
- package/templates/node/Dockerfile +3 -5
- package/templates/node/README.md +133 -58
- package/templates/node/docker-compose.yml +11 -12
- package/templates/node/package.json +4 -2
- package/templates/node/src/connecta.config.ts +119 -0
- package/templates/node/src/index.ts +9 -154
- package/templates/node/src/provision-token.ts +17 -0
- package/AGENTS.md +0 -170
- package/dist/artifacts/connector.d.ts +0 -58
- package/dist/artifacts/connector.js +0 -730
- package/dist/artifacts/document.js +0 -86
- package/dist/artifacts/guide.js +0 -140
- package/dist/artifacts/html-scan.js +0 -329
- package/dist/artifacts/json.js +0 -78
- package/dist/artifacts/kv-store.d.ts +0 -20
- package/dist/artifacts/kv-store.js +0 -140
- package/dist/artifacts/markdown.js +0 -478
- package/dist/artifacts/module.d.ts +0 -37
- package/dist/artifacts/module.js +0 -66
- package/dist/artifacts/operations.d.ts +0 -197
- package/dist/artifacts/operations.js +0 -1002
- package/dist/artifacts/refresh.d.ts +0 -55
- package/dist/artifacts/refresh.js +0 -236
- package/dist/artifacts/routes.js +0 -206
- package/dist/artifacts/types.d.ts +0 -214
- package/dist/artifacts/types.js +0 -22
- package/dist/artifacts/validate.d.ts +0 -62
- package/dist/artifacts/validate.js +0 -651
- package/dist/artifacts.d.ts +0 -6
- package/dist/artifacts.js +0 -9
- package/dist/auth/bearer.d.ts +0 -11
- package/dist/auth/bearer.js +0 -50
- package/dist/providers/basecamp.js +0 -445
- package/dist/providers/linear.js +0 -217
- package/dist/providers/mixpanel.js +0 -247
- package/dist/providers/revenuecat.js +0 -317
- package/dist/providers/stripe.js +0 -253
- package/dist/providers/vercel.js +0 -1253
- package/dist/storage/file.d.ts +0 -15
- package/dist/storage/file.js +0 -455
- package/ethos.md +0 -93
- package/examples/worker/src/cloudflare-kv.ts +0 -43
- package/examples/worker/src/d1-activity-row.ts +0 -155
- package/examples/worker/src/d1-activity.ts +0 -147
- package/examples/worker/src/d1-storage.ts +0 -138
- package/examples/worker/src/r2-artifact-blobs.ts +0 -29
- package/templates/node/src/file-activity.ts +0 -182
|
@@ -1,317 +0,0 @@
|
|
|
1
|
-
import { remoteMcp, withCredentialDefaults, } from "../connectors/remote-mcp.js";
|
|
2
|
-
import { vettedCatalog, withVettedCatalog } from "../catalog-drift.js";
|
|
3
|
-
import { defined } from "../connectors/api-connector.js";
|
|
4
|
-
/** RevenueCat publishes one hosted MCP endpoint, streamable HTTP. */
|
|
5
|
-
export const REVENUECAT_MCP_ENDPOINT = "https://mcp.revenuecat.ai/mcp";
|
|
6
|
-
/**
|
|
7
|
-
* Reviewed reads, every `Read` row of RevenueCat's tool reference as read on
|
|
8
|
-
* 2026-09-21 (P5). The list is a superset: plan, platform, and beta enrollment
|
|
9
|
-
* gate parts of the catalog, so a name this account never returns costs
|
|
10
|
-
* nothing while an unlisted new one fails closed.
|
|
11
|
-
*/
|
|
12
|
-
const READ_ONLY_TOOLS = new Set([
|
|
13
|
-
// Projects and apps
|
|
14
|
-
"get-account-billing",
|
|
15
|
-
"get-app",
|
|
16
|
-
"get-project-ui-config",
|
|
17
|
-
"list-account-billing-invoices",
|
|
18
|
-
"list-app-public-api-keys",
|
|
19
|
-
"list-apps",
|
|
20
|
-
"list-audit-logs",
|
|
21
|
-
"list-collaborators",
|
|
22
|
-
"list-projects",
|
|
23
|
-
// Products and prices
|
|
24
|
-
"get-product",
|
|
25
|
-
"get-product-store-state",
|
|
26
|
-
// Deprecated in RevenueCat's reference — superseded by the plan family's
|
|
27
|
-
// own read-back below — but still served, so the classification stands.
|
|
28
|
-
"get-product-store-state-operation",
|
|
29
|
-
"get-product-store-state-plan",
|
|
30
|
-
"list-product-store-state-plans",
|
|
31
|
-
"list-products",
|
|
32
|
-
// Entitlements
|
|
33
|
-
"get-entitlement",
|
|
34
|
-
"get-products-from-entitlement",
|
|
35
|
-
"list-entitlements",
|
|
36
|
-
// Offerings and packages
|
|
37
|
-
"get-offering",
|
|
38
|
-
"get-offering-prices",
|
|
39
|
-
"list-offerings",
|
|
40
|
-
"list-packages",
|
|
41
|
-
// Targeting and audiences
|
|
42
|
-
"get-audience",
|
|
43
|
-
"get-audience-filter-options",
|
|
44
|
-
"get-targeting-rule",
|
|
45
|
-
"list-audiences",
|
|
46
|
-
"list-targeting-rules",
|
|
47
|
-
// Paywalls
|
|
48
|
-
"get-paywall",
|
|
49
|
-
"list-paywalls",
|
|
50
|
-
// Customers and subscriptions
|
|
51
|
-
"get-customer",
|
|
52
|
-
"get-customer-center-config",
|
|
53
|
-
"get-refund-request-preferences",
|
|
54
|
-
"get-subscription",
|
|
55
|
-
"list-customer-events",
|
|
56
|
-
"list-customers",
|
|
57
|
-
"list-purchases",
|
|
58
|
-
"list-subscriptions",
|
|
59
|
-
"list-virtual-currencies-balances",
|
|
60
|
-
// Virtual currencies
|
|
61
|
-
"get-virtual-currency",
|
|
62
|
-
"list-virtual-currencies",
|
|
63
|
-
// Charts, metrics, and experiments
|
|
64
|
-
"get-benchmarks",
|
|
65
|
-
"get-chart-data",
|
|
66
|
-
"get-chart-options-schema",
|
|
67
|
-
"get-experiment",
|
|
68
|
-
"get-experiment-results",
|
|
69
|
-
"get-overview-metrics",
|
|
70
|
-
"get-revenue-metric",
|
|
71
|
-
"list-experiments",
|
|
72
|
-
// Integrations and webhooks
|
|
73
|
-
"get-webhook-integration",
|
|
74
|
-
"list-webhook-integrations",
|
|
75
|
-
// SDK compatibility
|
|
76
|
-
"list-sdk-feature-gates",
|
|
77
|
-
"list-sdk-versions",
|
|
78
|
-
// Paywall editing. Polling an async task is a read; the two tools that
|
|
79
|
-
// *start* one are writes and sit below.
|
|
80
|
-
"get-paywall-ai-task",
|
|
81
|
-
]);
|
|
82
|
-
/**
|
|
83
|
-
* Reviewed writes with their destructive verdict. Most follow the verb, and
|
|
84
|
-
* additive writes stay additive because `readOnlyHint: false` already routes
|
|
85
|
-
* them through the approval path — asserting a destruction that does not happen
|
|
86
|
-
* only inflates the copy a human reads. The verdicts the verb does not decide
|
|
87
|
-
* carry their reason on the row.
|
|
88
|
-
*
|
|
89
|
-
* `render-paywall-screenshot` is deliberately in neither map: RevenueCat's
|
|
90
|
-
* reference gives it no access column, so the live annotation stands and a
|
|
91
|
-
* catalog that omits one fails closed. Guessing from a harmless-sounding name
|
|
92
|
-
* is what P5 exists to prevent.
|
|
93
|
-
*/
|
|
94
|
-
const WRITE_TOOLS = new Map([
|
|
95
|
-
// Projects and apps
|
|
96
|
-
["create-app", "additive"],
|
|
97
|
-
["create-project", "additive"],
|
|
98
|
-
["update-app", "destructive"],
|
|
99
|
-
["update-project-ui-config", "destructive"],
|
|
100
|
-
// Filed `Write` by RevenueCat, so it cannot take the read path, but it leaves
|
|
101
|
-
// the saved credentials alone and only records a check's outcome.
|
|
102
|
-
["validate-app-credentials", "additive"],
|
|
103
|
-
// Products and prices
|
|
104
|
-
["archive-product", "destructive"],
|
|
105
|
-
["create-product", "additive"],
|
|
106
|
-
// Named `create-`, but "Configure prices for a product": the price set
|
|
107
|
-
// already exists, so this overwrites it, and it is money-facing. Deprecated
|
|
108
|
-
// in RevenueCat's reference; products are priced through the plan family
|
|
109
|
-
// below, but the tool is still served, so the classification stands.
|
|
110
|
-
["create-product-prices", "destructive"],
|
|
111
|
-
// "Fills *missing* App Store subscription territory prices" — by
|
|
112
|
-
// RevenueCat's own word it writes only where nothing is set. Deprecated in
|
|
113
|
-
// RevenueCat's reference; still served, so the classification stands.
|
|
114
|
-
["equalize-subscription-prices", "additive"],
|
|
115
|
-
// An upsert. Deprecated in RevenueCat's reference — the store-state plan
|
|
116
|
-
// family below replaces it — but still served, so the classification stands.
|
|
117
|
-
["set-product-store-state", "destructive"],
|
|
118
|
-
// Sends products to Apple for review.
|
|
119
|
-
["submit-products-to-store", "destructive"],
|
|
120
|
-
["unarchive-product", "destructive"],
|
|
121
|
-
["update-product", "destructive"],
|
|
122
|
-
// Reserves a new App Store Connect review screenshot slot; replaces nothing.
|
|
123
|
-
// Deprecated in RevenueCat's reference; still served, so the classification
|
|
124
|
-
// stands.
|
|
125
|
-
["upload-product-store-state-screenshot", "additive"],
|
|
126
|
-
// Product store state plans, the workflow RevenueCat deprecated
|
|
127
|
-
// `set-product-store-state` for. Create brings a draft into being and
|
|
128
|
-
// touches nothing else; plan recomputes an existing plan's proposed change,
|
|
129
|
-
// overwriting its previous planning; apply pushes the whole plan into
|
|
130
|
-
// RevenueCat and the app stores; update and discard act on an existing plan
|
|
131
|
-
// by name. Every step past create is asynchronous.
|
|
132
|
-
["create-product-store-state-plan", "additive"],
|
|
133
|
-
["plan-product-store-state-plan", "destructive"],
|
|
134
|
-
["apply-product-store-state-plan", "destructive"],
|
|
135
|
-
["update-product-store-state-plan", "destructive"],
|
|
136
|
-
["discard-product-store-state-plan", "destructive"],
|
|
137
|
-
// Entitlements
|
|
138
|
-
["archive-entitlement", "destructive"],
|
|
139
|
-
// Attach adds membership and removes nothing; detach is the destructive half.
|
|
140
|
-
// Filing both destructive would make the pair read identically to a human.
|
|
141
|
-
["attach-products-to-entitlement", "additive"],
|
|
142
|
-
["create-entitlement", "additive"],
|
|
143
|
-
["detach-products-from-entitlement", "destructive"],
|
|
144
|
-
["unarchive-entitlement", "destructive"],
|
|
145
|
-
["update-entitlement", "destructive"],
|
|
146
|
-
// Offerings and packages
|
|
147
|
-
["archive-offering", "destructive"],
|
|
148
|
-
// The attach/detach argument again, one level down.
|
|
149
|
-
["attach-products-to-package", "additive"],
|
|
150
|
-
["create-offering", "additive"],
|
|
151
|
-
["create-packages", "additive"],
|
|
152
|
-
["delete-package-from-offering", "destructive"],
|
|
153
|
-
["detach-products-from-package", "destructive"],
|
|
154
|
-
["unarchive-offering", "destructive"],
|
|
155
|
-
["update-offering", "destructive"],
|
|
156
|
-
// Targeting and audiences
|
|
157
|
-
["create-audience", "additive"],
|
|
158
|
-
["update-audience", "destructive"],
|
|
159
|
-
// Targeting rules follow the verb: create brings one into being, update
|
|
160
|
-
// and delete act on a rule the project already has.
|
|
161
|
-
["create-targeting-rule", "additive"],
|
|
162
|
-
["update-targeting-rule", "destructive"],
|
|
163
|
-
["delete-targeting-rule", "destructive"],
|
|
164
|
-
// Paywalls
|
|
165
|
-
["attach-offering-to-paywall", "destructive"],
|
|
166
|
-
["detach-offering-from-paywall", "destructive"],
|
|
167
|
-
// Copies an existing paywall's current draft; the original is untouched.
|
|
168
|
-
["duplicate-paywall", "additive"],
|
|
169
|
-
["publish-paywall", "destructive"],
|
|
170
|
-
["unpublish-paywall", "destructive"],
|
|
171
|
-
// Offerings and experiments added to the published reference after #512.
|
|
172
|
-
["duplicate-offering", "additive"],
|
|
173
|
-
["create-experiment", "additive"],
|
|
174
|
-
["pause-experiment", "destructive"],
|
|
175
|
-
["resume-experiment", "destructive"],
|
|
176
|
-
["start-experiment", "destructive"],
|
|
177
|
-
["stop-experiment", "destructive"],
|
|
178
|
-
["update-experiment", "destructive"],
|
|
179
|
-
// Customers and subscriptions
|
|
180
|
-
["assign-customer-offering", "destructive"],
|
|
181
|
-
["grant-customer-entitlement", "destructive"],
|
|
182
|
-
// Virtual currencies
|
|
183
|
-
["archive-virtual-currency", "destructive"],
|
|
184
|
-
["create-virtual-currency", "additive"],
|
|
185
|
-
["unarchive-virtual-currency", "destructive"],
|
|
186
|
-
["update-virtual-currency", "destructive"],
|
|
187
|
-
// Integrations and webhooks
|
|
188
|
-
// Destructive on consequence, not on the verb: no existing integration
|
|
189
|
-
// changes, but with filters omitted the new one starts delivering every
|
|
190
|
-
// customer event in the project to a URL the caller typed.
|
|
191
|
-
["create-webhook-integration", "destructive"],
|
|
192
|
-
["delete-webhook-integration", "destructive"],
|
|
193
|
-
["update-webhook-integration", "destructive"],
|
|
194
|
-
// Paywall editing. Both start an async task; the difference is what the task
|
|
195
|
-
// touches — a new paywall, or a draft that already exists.
|
|
196
|
-
["create-paywall-ai", "additive"],
|
|
197
|
-
["edit-paywall-ai", "destructive"],
|
|
198
|
-
]);
|
|
199
|
-
/**
|
|
200
|
-
* One release-reviewed manifest, used both to classify a live tool and as the
|
|
201
|
-
* baseline the drift check compares against, so the annotation a caller gets
|
|
202
|
-
* and the verdict a check reads can never disagree. Names and verdicts only —
|
|
203
|
-
* no schemas are vendored; the live `tools/list` response stays authoritative.
|
|
204
|
-
*/
|
|
205
|
-
export const REVENUECAT_VETTED_CATALOG = vettedCatalog({
|
|
206
|
-
reads: READ_ONLY_TOOLS,
|
|
207
|
-
writes: WRITE_TOOLS,
|
|
208
|
-
});
|
|
209
|
-
/** The catalog's summary bound; a longer declared value throws (`src/registry.ts`). */
|
|
210
|
-
const SUMMARY_BUDGET = 120;
|
|
211
|
-
/**
|
|
212
|
-
* Fit a purpose-bearing summary inside the catalog's bound.
|
|
213
|
-
*
|
|
214
|
-
* Stripe and Mixpanel declare static summaries because their routing fact is
|
|
215
|
-
* an enumerable variant. RevenueCat's is not: two `sk_` connectors have the
|
|
216
|
-
* same title, the same endpoint, and the same catalog, and differ only by the
|
|
217
|
-
* project the operator says each key reaches. So the summary carries that, and
|
|
218
|
-
* clipping is this function's job rather than the operator's.
|
|
219
|
-
*/
|
|
220
|
-
function boundedSummary(prefix, purpose) {
|
|
221
|
-
const full = `${prefix}${purpose}`;
|
|
222
|
-
if (full.length <= SUMMARY_BUDGET)
|
|
223
|
-
return full;
|
|
224
|
-
return `${full.slice(0, SUMMARY_BUDGET - 1).trimEnd()}…`;
|
|
225
|
-
}
|
|
226
|
-
function sharedUsageGuide() {
|
|
227
|
-
return `
|
|
228
|
-
- Resolve ids before acting; never guess one. \`list-projects\` yields the \`project_id\` every project-scoped call takes. \`list-apps\`, \`list-products\`, \`list-entitlements\`, \`list-offerings\`, \`list-paywalls\`, \`list-audiences\`, and \`list-customers\` yield the ids their \`get-\`, \`update-\`, \`archive-\`, and \`delete-\` counterparts expect. A plausible-looking id belongs to another project or to nobody.
|
|
229
|
-
- Customers are addressed by the app user id your SDK set, not by an internal key. Find one with \`list-customers\` before \`get-customer\`, and carry the id it returned unchanged.
|
|
230
|
-
- Customer and subscription objects are large, and a customer's history is larger. Page with the cursor the list returned rather than raising the page size, and reduce inside \`execute_code\` — select the fields the question needs and return those, not the whole object.
|
|
231
|
-
- Whether a customer should have access is \`gives_access\` on each subscription from \`list-subscriptions\`, which RevenueCat calls the authoritative flag. \`status\` and \`expires_date\` describe the store-side state and disagree with it during grace periods, billing retries, and promotional grants — answer access questions from \`gives_access\` and say which subscription it came from.
|
|
232
|
-
- \`get-chart-data\` is the metrics path: read \`get-chart-options-schema\` for the chart you want before calling it, rather than guessing an option name. \`get-overview-metrics\` and \`get-revenue-metric\` answer the summary questions in one call.
|
|
233
|
-
- \`create-paywall-ai\` and \`edit-paywall-ai\` are asynchronous. Poll the task id they return with \`get-paywall-ai-task\` rather than assuming the work finished when the call returned.
|
|
234
|
-
- Store changes ride the plan workflow, not the deprecated direct tools: \`create-product-store-state-plan\`, then \`plan-product-store-state-plan\`, then \`apply-product-store-state-plan\`. Every step past the create is asynchronous — read the plan back with \`get-product-store-state-plan\` between steps instead of assuming the last one finished.
|
|
235
|
-
- This connection's tool list is not a fixed set. RevenueCat gates parts of its MCP catalog by plan, platform, and beta enrollment — paywall AI editing, benchmarks, experiments, virtual currencies, and the account-billing tools are the usual absentees — so search this connector for what it actually exposes rather than assuming a documented tool is here.
|
|
236
|
-
- \`render-paywall-screenshot\` is unclassified on purpose because RevenueCat's reference gives it no access column. The current server marks it read-only, which Connecta preserves; without that annotation it fails closed onto \`call_destructive_tool\`.
|
|
237
|
-
- RevenueCat meters API v2 per minute and per domain, and the domains differ: 480 requests per minute for customer information and virtual currencies, 60 for project configuration and audiences, 25 for charts and metrics. It answers a breach with \`429\`, a \`Retry-After\` header, and a \`backoff_ms\` field. Back off on that rather than retrying immediately, and expect chart sweeps to hit the ceiling long before customer reads do.
|
|
238
|
-
- Treat every create, update, archive, unarchive, attach, detach, delete, publish, unpublish, grant, assign, and submit operation as a write. Connecta routes the maintained write catalog through \`call_destructive_tool\`; newly added tools also fail closed until a release classifies them.
|
|
239
|
-
- An \`auth_required\` failure means this connector's RevenueCat authorization is missing or expired: run \`authorize_connector\` for this connector id, then retry the same call unchanged. A rejected argument, a permission gap, or a plan restriction comes back in RevenueCat's own words instead — read it rather than re-authorizing.
|
|
240
|
-
`;
|
|
241
|
-
}
|
|
242
|
-
function oauthUsageGuide(purpose, instructions) {
|
|
243
|
-
const projectInstructions = instructions?.trim();
|
|
244
|
-
return `# RevenueCat usage
|
|
245
|
-
|
|
246
|
-
Account-scoped connection: this OAuth session reaches every RevenueCat project the account can see. Connector purpose: ${purpose}
|
|
247
|
-
|
|
248
|
-
Call \`list-projects\` first and carry the exact \`project_id\` it returned into every project-scoped call. Connecta does not pick a project, and the connector id, title, and purpose are routing hints rather than proof of which project a call will land in. If more than one project fits the request, stop and ask; never guess a \`project_id\`.
|
|
249
|
-
${sharedUsageGuide()}${projectInstructions
|
|
250
|
-
? `\n## Project instructions\n\n${projectInstructions}\n`
|
|
251
|
-
: ""}`;
|
|
252
|
-
}
|
|
253
|
-
function keyUsageGuide(purpose, instructions) {
|
|
254
|
-
const projectInstructions = instructions?.trim();
|
|
255
|
-
return `# RevenueCat usage
|
|
256
|
-
|
|
257
|
-
Single-project connection: ${purpose}. RevenueCat secret API keys are project-wide, so this key reaches exactly one project and nothing outside it. A second project is a second connector with its own key and its own id — never a \`project_id\` argument pointed somewhere else.
|
|
258
|
-
|
|
259
|
-
Confirm the project on first use: \`list-projects\` returns the one project this key can see, and its \`project_id\` is the one every project-scoped call takes. An empty or unexpected result means wrong connector, not missing data.
|
|
260
|
-
|
|
261
|
-
A RevenueCat secret key is issued read-only or write-enabled, and connecta cannot tell which this one is. It does not filter writes for a read-only key: every write is offered, reaches RevenueCat, and fails there in RevenueCat's own words. Read that refusal as "this key cannot write" rather than as a bad argument, and route the write to a connector configured with a write-enabled key.
|
|
262
|
-
${sharedUsageGuide()}${projectInstructions
|
|
263
|
-
? `\n## Project instructions\n\n${projectInstructions}\n`
|
|
264
|
-
: ""}`;
|
|
265
|
-
}
|
|
266
|
-
/** A maintained RevenueCat hosted-MCP connection. */
|
|
267
|
-
export function revenuecat(id, options) {
|
|
268
|
-
const purpose = options.purpose.trim();
|
|
269
|
-
if (!purpose) {
|
|
270
|
-
throw new Error("revenuecat() requires a non-empty project purpose.");
|
|
271
|
-
}
|
|
272
|
-
const auth = withCredentialDefaults(options.auth ?? { type: "oauth" }, {
|
|
273
|
-
credential: {
|
|
274
|
-
label: "API v2 secret key",
|
|
275
|
-
description: "A RevenueCat API v2 secret key. It reaches exactly one project, which is why two projects are two connectors; it is stored encrypted and never displayed.",
|
|
276
|
-
placeholder: "sk_…",
|
|
277
|
-
},
|
|
278
|
-
});
|
|
279
|
-
// Both static shapes reach one project. Where the key came from — the
|
|
280
|
-
// deployment file or the operator page — changes nothing an agent must know
|
|
281
|
-
// about scope, so the title, description, and guide follow the scope alone.
|
|
282
|
-
const scoped = auth.type !== "oauth";
|
|
283
|
-
const connector = remoteMcp(id, {
|
|
284
|
-
url: REVENUECAT_MCP_ENDPOINT,
|
|
285
|
-
...(options.authScope ? { authScope: options.authScope } : {}),
|
|
286
|
-
// The scope shape rides the title because browse-time discovery renders
|
|
287
|
-
// the title and the guide summary and nothing else, and reaching one
|
|
288
|
-
// project versus every project the account has is the fact an agent must
|
|
289
|
-
// not get wrong between two RevenueCat connections.
|
|
290
|
-
title: options.title ?? (scoped ? "RevenueCat (single project)" : "RevenueCat"),
|
|
291
|
-
description: scoped
|
|
292
|
-
? `RevenueCat subscriptions and revenue (one project, static key) — ${purpose}`
|
|
293
|
-
: `RevenueCat subscriptions and revenue (every project the account can reach) — ${purpose}`,
|
|
294
|
-
auth,
|
|
295
|
-
requireHttps: true,
|
|
296
|
-
usageGuide: {
|
|
297
|
-
content: scoped
|
|
298
|
-
? keyUsageGuide(purpose, options.instructions)
|
|
299
|
-
: oauthUsageGuide(purpose, options.instructions),
|
|
300
|
-
// Explicit rather than derived, and purpose-bearing rather than static:
|
|
301
|
-
// the derived summary would cut the scoping sentence mid-clause at 120
|
|
302
|
-
// characters, and two static summaries would leave two `sk_` connectors
|
|
303
|
-
// indistinguishable in the one field search returns (P3).
|
|
304
|
-
summary: scoped
|
|
305
|
-
? boundedSummary("One project only: ", purpose)
|
|
306
|
-
: boundedSummary("All account projects; list-projects first: ", purpose),
|
|
307
|
-
// Not `required`. RevenueCat's own schemas describe each call; the guide
|
|
308
|
-
// carries the project-resolution sequence, which is worth reading before
|
|
309
|
-
// a run rather than before every call.
|
|
310
|
-
},
|
|
311
|
-
...defined({
|
|
312
|
-
callAdmission: options.callAdmission,
|
|
313
|
-
maxResultBytes: options.maxResultBytes,
|
|
314
|
-
}),
|
|
315
|
-
});
|
|
316
|
-
return withVettedCatalog(connector, REVENUECAT_VETTED_CATALOG);
|
|
317
|
-
}
|
package/dist/providers/stripe.js
DELETED
|
@@ -1,253 +0,0 @@
|
|
|
1
|
-
import { remoteMcp, withCredentialDefaults, } from "../connectors/remote-mcp.js";
|
|
2
|
-
import { vettedCatalog, withVettedCatalog } from "../catalog-drift.js";
|
|
3
|
-
import { defined } from "../connectors/api-connector.js";
|
|
4
|
-
/** Stripe publishes one hosted MCP endpoint for every account and mode. */
|
|
5
|
-
export const STRIPE_MCP_ENDPOINT = "https://mcp.stripe.com/";
|
|
6
|
-
/**
|
|
7
|
-
* Stripe documents no MCP-specific limit, so these transcribe the account limit
|
|
8
|
-
* MCP traffic spends: 100 requests per second live, 25 in a sandbox. OAuth takes
|
|
9
|
-
* the sandbox rule (`mode ?? "sandbox"` below) because one session can reach
|
|
10
|
-
* either mode and the policy is fixed before the account-scoped call begins.
|
|
11
|
-
* The `maxConcurrency` figures are Connecta's own choice — Stripe says
|
|
12
|
-
* per-account and per-endpoint concurrency limits exist but publishes no number.
|
|
13
|
-
*/
|
|
14
|
-
const STRIPE_ADMISSION = {
|
|
15
|
-
production: {
|
|
16
|
-
rules: [
|
|
17
|
-
{
|
|
18
|
-
maxConcurrency: 8,
|
|
19
|
-
queueTimeoutMs: 5_000,
|
|
20
|
-
retryAfterMs: 1_000,
|
|
21
|
-
budget: { kind: "rolling-window", maxCalls: 100, windowMs: 1_000 },
|
|
22
|
-
},
|
|
23
|
-
],
|
|
24
|
-
},
|
|
25
|
-
sandbox: {
|
|
26
|
-
rules: [
|
|
27
|
-
{
|
|
28
|
-
maxConcurrency: 4,
|
|
29
|
-
queueTimeoutMs: 5_000,
|
|
30
|
-
retryAfterMs: 1_000,
|
|
31
|
-
budget: { kind: "rolling-window", maxCalls: 25, windowMs: 1_000 },
|
|
32
|
-
},
|
|
33
|
-
],
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
/**
|
|
37
|
-
* Tools whose official contract is observational rather than mutating.
|
|
38
|
-
*
|
|
39
|
-
* `stripe_api_read` is on this list because Stripe documents it as the `GET`
|
|
40
|
-
* half of the generic pair — the tool itself is the read boundary, not the
|
|
41
|
-
* endpoint an agent names inside it.
|
|
42
|
-
*/
|
|
43
|
-
const READ_ONLY_TOOLS = new Set([
|
|
44
|
-
"stripe_api_search",
|
|
45
|
-
"stripe_api_details",
|
|
46
|
-
"stripe_api_read",
|
|
47
|
-
"get_stripe_account_info",
|
|
48
|
-
"get_balance_summary",
|
|
49
|
-
"list_metrics",
|
|
50
|
-
"explain_metric",
|
|
51
|
-
"metric_drilldown",
|
|
52
|
-
"show_metric_app",
|
|
53
|
-
"list_available_accounts_or_orgs",
|
|
54
|
-
"manage_stripe_accounts",
|
|
55
|
-
"search_stripe_documentation",
|
|
56
|
-
]);
|
|
57
|
-
/**
|
|
58
|
-
* Reviewed writes with their destructive verdict. `stripe_api_write` is the
|
|
59
|
-
* sibling of `stripe_api_read` and carries every `POST`, `PATCH`, `PUT`, and
|
|
60
|
-
* `DELETE`. Additive writes leave `destructiveHint` unset: `readOnlyHint: false`
|
|
61
|
-
* already routes them through the approval path, and asserting destruction they
|
|
62
|
-
* do not perform would misstate their effect.
|
|
63
|
-
*/
|
|
64
|
-
const WRITE_TOOLS = new Map([
|
|
65
|
-
["stripe_api_write", "destructive"],
|
|
66
|
-
["create_refund", "destructive"],
|
|
67
|
-
// Creates and continues provider-side guide state; destroys nothing.
|
|
68
|
-
["stripe_implementation_planner", "additive"],
|
|
69
|
-
// Retrieval mixed with query-run creation behind one tool.
|
|
70
|
-
["stripe_analytics", "additive"],
|
|
71
|
-
["stripe_report", "additive"],
|
|
72
|
-
["send_stripe_mcp_feedback", "additive"],
|
|
73
|
-
]);
|
|
74
|
-
/**
|
|
75
|
-
* One release-reviewed manifest, used both to classify a live tool and as the
|
|
76
|
-
* baseline the drift check compares against, so the annotation a caller gets and
|
|
77
|
-
* the verdict a check reads can never disagree. Stripe publishes no stability or
|
|
78
|
-
* deprecation policy for this tool set, so treat it as unversioned: an
|
|
79
|
-
* unclassified, unannotated name fails closed onto the approval path (P5).
|
|
80
|
-
*/
|
|
81
|
-
export const STRIPE_VETTED_CATALOG = vettedCatalog({
|
|
82
|
-
reads: READ_ONLY_TOOLS,
|
|
83
|
-
writes: WRITE_TOOLS,
|
|
84
|
-
});
|
|
85
|
-
/** Stripe key prefixes carry their own mode; only a clear reading counts. */
|
|
86
|
-
const LIVE_KEY = /\b(?:sk|rk|pk)_live_/;
|
|
87
|
-
const TEST_KEY = /\b(?:sk|rk|pk)_test_/;
|
|
88
|
-
/**
|
|
89
|
-
* Refuse a recognizable key/mode mismatch. This is the only mode guard Connecta
|
|
90
|
-
* can offer, and it needs the key as a literal header to read the prefix: an
|
|
91
|
-
* operator-managed key is not in the deployment file, so its declared mode
|
|
92
|
-
* stands alone and a key pointed at the other environment fails at Stripe.
|
|
93
|
-
*/
|
|
94
|
-
function assertModeMatchesKey(id, mode, auth) {
|
|
95
|
-
if (auth.type !== "headers")
|
|
96
|
-
return;
|
|
97
|
-
for (const value of Object.values(auth.headers)) {
|
|
98
|
-
const keyMode = LIVE_KEY.test(value)
|
|
99
|
-
? "production"
|
|
100
|
-
: TEST_KEY.test(value)
|
|
101
|
-
? "sandbox"
|
|
102
|
-
: undefined;
|
|
103
|
-
if (keyMode !== undefined && keyMode !== mode) {
|
|
104
|
-
throw new Error(`stripe("${id}") declares mode "${mode}" but its auth headers carry a ` +
|
|
105
|
-
`${keyMode === "production" ? "live" : "test"}-mode Stripe key.`);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
function resolveAuth(id, options) {
|
|
110
|
-
const auth = withCredentialDefaults(options.auth ?? { type: "oauth" }, {
|
|
111
|
-
credential: {
|
|
112
|
-
label: "Secret or restricted API key",
|
|
113
|
-
description: "A Stripe secret or restricted API key for this connector's declared mode. Stripe sends it as a bearer token; it is stored encrypted and never displayed.",
|
|
114
|
-
placeholder: "sk_… or rk_…",
|
|
115
|
-
},
|
|
116
|
-
});
|
|
117
|
-
const connectedAccount = options.connectedAccount?.trim();
|
|
118
|
-
if (connectedAccount === undefined || connectedAccount === "")
|
|
119
|
-
return auth;
|
|
120
|
-
if (!connectedAccount.startsWith("acct_")) {
|
|
121
|
-
throw new Error(`stripe("${id}") connectedAccount must be a Stripe account id ("acct_...").`);
|
|
122
|
-
}
|
|
123
|
-
if (auth.type === "oauth") {
|
|
124
|
-
throw new Error(`stripe("${id}") cannot reach a connected account over OAuth; Stripe ` +
|
|
125
|
-
`requires a restricted API key for Stripe-Account calls.`);
|
|
126
|
-
}
|
|
127
|
-
if (auth.type === "credential") {
|
|
128
|
-
// `Stripe-Account` is a second header beside the credential's own, and the
|
|
129
|
-
// credential shape assembles exactly one. A Connect connector therefore
|
|
130
|
-
// still takes its restricted key as a literal header.
|
|
131
|
-
throw new Error(`stripe("${id}") cannot reach a connected account with an ` +
|
|
132
|
-
`operator-managed credential; Stripe-Account is a second static ` +
|
|
133
|
-
`header, so declare auth: { type: "headers" } for this connector.`);
|
|
134
|
-
}
|
|
135
|
-
return {
|
|
136
|
-
type: "headers",
|
|
137
|
-
headers: { ...auth.headers, "Stripe-Account": connectedAccount },
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
function oauthUsageGuide(purpose, instructions) {
|
|
141
|
-
const accountInstructions = instructions?.trim();
|
|
142
|
-
return `# Stripe usage
|
|
143
|
-
|
|
144
|
-
Scope: live and sandbox accounts. Connector purpose: ${purpose}
|
|
145
|
-
|
|
146
|
-
This OAuth session may expose both live and sandbox Stripe accounts. Call \`list_available_accounts_or_orgs\`, then carry its exact \`stripe_context\` and \`livemode\` into every account-scoped call. A live-mode write moves real money; a sandbox write changes test data. Never infer the account or mode from connector metadata.
|
|
147
|
-
|
|
148
|
-
- Call \`list_available_accounts_or_orgs\` before every account-scoped read or write. Select the intended result, then carry its \`stripe_context\` and \`livemode\` unchanged. If the account, mode, or supported selector is ambiguous, stop and ask; never guess.
|
|
149
|
-
- Organization accounts are not Stripe Connect connected accounts. A Connect call requires a separate connector with a deployment-configured restricted key plus Stripe's documented \`Stripe-Account\` header; OAuth does not support that path.
|
|
150
|
-
${sharedUsageGuide("100 requests per second in live mode and 25 in sandbox mode")}
|
|
151
|
-
${accountInstructions
|
|
152
|
-
? `\n## Account instructions\n\n${accountInstructions}\n`
|
|
153
|
-
: ""}`;
|
|
154
|
-
}
|
|
155
|
-
const MODE_COPY = {
|
|
156
|
-
production: {
|
|
157
|
-
title: "Stripe (production)",
|
|
158
|
-
blurb: "production — live money and real customers",
|
|
159
|
-
warning: "This is a PRODUCTION Stripe connection. Every write moves real money against real customers, and a refund cannot be undone. If a request could plausibly be a rehearsal, route it to a sandbox connector instead.",
|
|
160
|
-
},
|
|
161
|
-
sandbox: {
|
|
162
|
-
title: "Stripe (sandbox)",
|
|
163
|
-
blurb: "sandbox — test data, no real money",
|
|
164
|
-
warning: "This is a SANDBOX Stripe connection. Nothing here is real money and none of these objects exist in production, so never answer a question about live revenue, payouts, or a named customer from this connector.",
|
|
165
|
-
},
|
|
166
|
-
};
|
|
167
|
-
function fixedModeUsageGuide(mode, purpose, instructions) {
|
|
168
|
-
const copy = MODE_COPY[mode];
|
|
169
|
-
const accountInstructions = instructions?.trim();
|
|
170
|
-
return `# Stripe usage
|
|
171
|
-
|
|
172
|
-
Mode: ${mode}. Connector purpose: ${purpose}
|
|
173
|
-
|
|
174
|
-
${copy.warning}
|
|
175
|
-
|
|
176
|
-
- Organization accounts are not Stripe Connect connected accounts. A Connect call requires a deployment-configured restricted key plus Stripe's documented \`Stripe-Account\` header; OAuth does not support that path. Do not try to turn an organization-account call into a Connect call inside tool arguments.
|
|
177
|
-
${sharedUsageGuide(`${mode === "production" ? "100" : "25"} requests per second`)}
|
|
178
|
-
${accountInstructions
|
|
179
|
-
? `\n## Account instructions\n\n${accountInstructions}\n`
|
|
180
|
-
: ""}`;
|
|
181
|
-
}
|
|
182
|
-
function sharedUsageGuide(rate) {
|
|
183
|
-
return `
|
|
184
|
-
- Four generic tools reach any Stripe API method. Find the method with \`stripe_api_search\`, read its parameters with \`stripe_api_details\`, then call \`stripe_api_read\` (GET) or \`stripe_api_write\` (POST/PATCH/PUT/DELETE). Never guess a path or a parameter name — \`stripe_api_details\` is cheaper than a rejected write.
|
|
185
|
-
- Prefer a dedicated tool when one covers the task: \`get_balance_summary\` for balances and \`stripe_analytics\` for Sigma or Metrics reporting. Use \`stripe_api_search\` for everything else instead of assuming a retired dedicated tool still exists.
|
|
186
|
-
- \`stripe_implementation_planner\` and the query-execution intents of \`stripe_analytics\` create provider-side planning or query-run state. Connecta therefore routes both through \`call_destructive_tool\` as non-destructive writes; their retrieval paths stay behind the same tool boundary.
|
|
187
|
-
- \`stripe_api_write\` carries the blast radius of the entire write API — every POST, PATCH, PUT, and DELETE, from a customer edit to a subscription cancellation. State the method and path explicitly; expect approval on every call.
|
|
188
|
-
- Lists are cursor-paginated: \`limit\` defaults to 10 and caps at 100, \`starting_after\` and \`ending_before\` take an object id and are mutually exclusive, and \`has_more\` says whether to continue. Page inside \`execute_code\`.
|
|
189
|
-
- Any \`stripe_api_read\` list or \`stripe_api_search\` that returns full objects belongs inside \`execute_code\`, projected to the fields the question needs before \`return\`. Neither \`limit\` nor \`expand\` substitutes for that: an unprojected list of customers or invoices truncates long before it answers, and a projected one keeps the customer's name, email, and address out of the transcript.
|
|
190
|
-
- Search filters on a documented per-resource field set, not on arbitrary attributes. Charges search takes \`amount\`, \`created\`, \`currency\`, \`customer\`, \`status\`, \`refunded\`, \`disputed\`, \`metadata\`, \`billing_details.address.postal_code\`, and \`payment_method_details.<source>.*\` card fields — there is no \`payment_intent\` field. When the field you want is not searchable, retrieve the parent object and follow its reference (the PaymentIntent's \`latest_charge\`) instead of retrying the search with another spelling.
|
|
191
|
-
- The account → \`stripe_api_search\` → \`stripe_api_details\` → \`stripe_api_read\` sequence is one program, not four turns: resolve the method once, then call that method as many times as the investigation needs in the same run.
|
|
192
|
-
- Decline outcomes live on the charge — \`outcome\`, \`failure_code\`, \`failure_message\` — reached from the PaymentIntent's \`latest_charge\`, so "why did this payment fail" is a PaymentIntent read followed by one charge read.
|
|
193
|
-
- Resolve ids before acting; never guess one. Stripe ids are typed prefixes — \`cus_\` customer, \`sub_\` subscription, \`ch_\` charge, \`pi_\` payment intent, \`in_\` invoice, \`acct_\` account — and a plausible-looking id belongs to a different object or to nobody. Find the object with \`stripe_api_search\` (or a list endpoint through \`stripe_api_read\`) and carry the \`id\` it returned into the write.
|
|
194
|
-
- This connection's tool list is not a fixed set. Stripe gates parts of its MCP catalog by account, integration, and beta enrollment, so search this connector for what it actually exposes rather than assuming a documented tool is here.
|
|
195
|
-
- Amounts are integers in the currency's minor unit: \`1099\` is 10.99 USD, and zero-decimal currencies like JPY take \`10\` for 10 JPY. Never send a decimal.
|
|
196
|
-
- Send an \`Idempotency-Key\` on every write you might retry, if the tool accepts it, and reuse the same key for the retry. A retry with a fresh key is a second charge, not a second attempt.
|
|
197
|
-
- Stripe answers a rate limit with \`429\` and a \`Stripe-Rate-Limited-Reason\` header; back off on that rather than retrying immediately. Stripe documents an account ceiling of ${rate}, and any single endpoint is capped at 25 per second regardless of mode, so paging one list is the real constraint.
|
|
198
|
-
- Use \`search_stripe_documentation\` when the shape of an object or a flow is unclear; it is a read and costs nothing but a call.
|
|
199
|
-
- Treat every create, update, delete, refund, and report run as a write. Connecta routes the maintained write catalog through \`call_destructive_tool\`; newly added tools also fail closed until classified.
|
|
200
|
-
- An \`auth_required\` failure means this connector's Stripe authorization is missing or expired: run \`authorize_connector\` for this connector id, then retry the same call unchanged. A rejected argument or a plan restriction comes back in Stripe's own words instead — read it rather than re-authorizing.
|
|
201
|
-
`;
|
|
202
|
-
}
|
|
203
|
-
/** A maintained Stripe hosted-MCP connection. */
|
|
204
|
-
export function stripe(id, options) {
|
|
205
|
-
const purpose = options.purpose.trim();
|
|
206
|
-
if (!purpose) {
|
|
207
|
-
throw new Error("stripe() requires a non-empty account purpose.");
|
|
208
|
-
}
|
|
209
|
-
const auth = resolveAuth(id, options);
|
|
210
|
-
const mode = "mode" in options ? options.mode : undefined;
|
|
211
|
-
if (auth.type === "oauth" && mode !== undefined) {
|
|
212
|
-
throw new Error(`stripe("${id}") cannot declare a connector-wide mode for OAuth; Stripe returns mode with each account.`);
|
|
213
|
-
}
|
|
214
|
-
if (auth.type !== "oauth" && mode !== "production" && mode !== "sandbox") {
|
|
215
|
-
throw new Error(`stripe("${id}") with headers or credential auth requires mode ` +
|
|
216
|
-
`"production" or "sandbox".`);
|
|
217
|
-
}
|
|
218
|
-
// Only a literal header can be inspected. An operator-managed credential is
|
|
219
|
-
// not readable at construction — there is nothing in the deployment file to
|
|
220
|
-
// read — so the declared mode stands alone, and a key pointed at the other
|
|
221
|
-
// one is Stripe's own refusal to report.
|
|
222
|
-
if (auth.type === "headers") {
|
|
223
|
-
assertModeMatchesKey(id, mode, auth);
|
|
224
|
-
}
|
|
225
|
-
const copy = mode === undefined ? undefined : MODE_COPY[mode];
|
|
226
|
-
const connector = remoteMcp(id, {
|
|
227
|
-
url: STRIPE_MCP_ENDPOINT,
|
|
228
|
-
...(options.authScope ? { authScope: options.authScope } : {}),
|
|
229
|
-
title: options.title ?? copy?.title ?? "Stripe",
|
|
230
|
-
description: mode === undefined
|
|
231
|
-
? `Stripe payments (live and sandbox accounts) — ${purpose}`
|
|
232
|
-
: `Stripe payments (${copy?.blurb}) — ${purpose}`,
|
|
233
|
-
auth,
|
|
234
|
-
requireHttps: true,
|
|
235
|
-
callAdmission: STRIPE_ADMISSION[mode ?? "sandbox"],
|
|
236
|
-
usageGuide: {
|
|
237
|
-
content: mode === undefined
|
|
238
|
-
? oauthUsageGuide(purpose, options.instructions)
|
|
239
|
-
: fixedModeUsageGuide(mode, purpose, options.instructions),
|
|
240
|
-
// Explicit rather than derived: fixed credentials must lead with mode,
|
|
241
|
-
// while OAuth must lead with its account-scoped selector pair.
|
|
242
|
-
summary: mode === undefined
|
|
243
|
-
? "Live and sandbox Stripe accounts. List accounts; carry the returned stripe_context and livemode before acting."
|
|
244
|
-
: mode === "production"
|
|
245
|
-
? "PRODUCTION: real money. This static credential has one fixed live-mode scope."
|
|
246
|
-
: "Sandbox: test data only. This static credential has one fixed sandbox scope.",
|
|
247
|
-
// Not `required`. The four generic tools are the routing decision; a
|
|
248
|
-
// guide forced into every call would pay for the same prose repeatedly.
|
|
249
|
-
},
|
|
250
|
-
...defined({ maxResultBytes: options.maxResultBytes }),
|
|
251
|
-
});
|
|
252
|
-
return withVettedCatalog(connector, STRIPE_VETTED_CATALOG);
|
|
253
|
-
}
|