@zackbart/connecta 0.15.1 → 0.16.1

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.
Files changed (335) hide show
  1. package/AGENTS.md +40 -20
  2. package/CHANGELOG.md +653 -0
  3. package/README.md +25 -5
  4. package/bin/connecta.mjs +44 -3
  5. package/dist/access-tokens.d.ts +0 -1
  6. package/dist/access-tokens.js +0 -1
  7. package/dist/activity.d.ts +50 -2
  8. package/dist/activity.js +34 -1
  9. package/dist/apps-shell.d.ts +0 -1
  10. package/dist/apps-shell.js +0 -1
  11. package/dist/auth/bearer.d.ts +0 -1
  12. package/dist/auth/bearer.js +0 -1
  13. package/dist/auth/clerk.d.ts +0 -1
  14. package/dist/auth/clerk.js +45 -9
  15. package/dist/auth/downstream-oauth.d.ts +0 -1
  16. package/dist/auth/downstream-oauth.js +0 -1
  17. package/dist/call-admission.d.ts +0 -1
  18. package/dist/call-admission.js +0 -1
  19. package/dist/catalog-drift.d.ts +99 -0
  20. package/dist/catalog-drift.js +251 -0
  21. package/dist/catalog-fingerprint.d.ts +0 -1
  22. package/dist/catalog-fingerprint.js +0 -1
  23. package/dist/catalog-limits.d.ts +0 -1
  24. package/dist/catalog-limits.js +0 -1
  25. package/dist/catalog-service.d.ts +0 -1
  26. package/dist/catalog-service.js +41 -5
  27. package/dist/catalog.d.ts +11 -1
  28. package/dist/catalog.js +20 -1
  29. package/dist/concurrency.d.ts +0 -1
  30. package/dist/concurrency.js +0 -1
  31. package/dist/connector-scope.d.ts +0 -1
  32. package/dist/connector-scope.js +0 -1
  33. package/dist/connectors/api.d.ts +29 -21
  34. package/dist/connectors/api.js +45 -19
  35. package/dist/connectors/guarded-fetch.d.ts +106 -0
  36. package/dist/connectors/guarded-fetch.js +289 -0
  37. package/dist/connectors/remote-mcp.d.ts +0 -1
  38. package/dist/connectors/remote-mcp.js +0 -1
  39. package/dist/credentials.d.ts +0 -1
  40. package/dist/credentials.js +0 -1
  41. package/dist/errors.d.ts +30 -3
  42. package/dist/errors.js +1 -1
  43. package/dist/execute.d.ts +0 -1
  44. package/dist/execute.js +0 -1
  45. package/dist/executor-admission.d.ts +11 -1
  46. package/dist/executor-admission.js +28 -1
  47. package/dist/executor-result.d.ts +0 -1
  48. package/dist/executor-result.js +0 -1
  49. package/dist/executors/quickjs-child.d.ts +0 -1
  50. package/dist/executors/quickjs-child.js +0 -1
  51. package/dist/executors/quickjs-protocol.d.ts +0 -1
  52. package/dist/executors/quickjs-protocol.js +0 -1
  53. package/dist/executors/quickjs-runtime.d.ts +0 -1
  54. package/dist/executors/quickjs-runtime.js +0 -1
  55. package/dist/executors/quickjs.d.ts +0 -1
  56. package/dist/executors/quickjs.js +2 -1
  57. package/dist/favicon.d.ts +0 -1
  58. package/dist/favicon.js +0 -1
  59. package/dist/index.d.ts +2 -3
  60. package/dist/index.js +24 -7
  61. package/dist/invocation.d.ts +0 -1
  62. package/dist/invocation.js +0 -1
  63. package/dist/json-schema.d.ts +0 -1
  64. package/dist/json-schema.js +0 -1
  65. package/dist/mcp-result.d.ts +0 -1
  66. package/dist/mcp-result.js +0 -1
  67. package/dist/meta-tools.d.ts +0 -1
  68. package/dist/meta-tools.js +0 -1
  69. package/dist/node.d.ts +0 -1
  70. package/dist/node.js +0 -1
  71. package/dist/operator-ui/generated.d.ts +2 -3
  72. package/dist/operator-ui/generated.js +3 -4
  73. package/dist/operator-ui/model.d.ts +10 -1
  74. package/dist/operator-ui/model.js +0 -1
  75. package/dist/operator-ui/view.d.ts +167 -0
  76. package/dist/operator-ui/view.js +270 -0
  77. package/dist/providers/cloudflare.d.ts +0 -1
  78. package/dist/providers/cloudflare.js +261 -299
  79. package/dist/providers/linear.d.ts +26 -5
  80. package/dist/providers/linear.js +32 -61
  81. package/dist/providers/mixpanel.d.ts +35 -4
  82. package/dist/providers/mixpanel.js +53 -79
  83. package/dist/providers/notion.d.ts +0 -1
  84. package/dist/providers/notion.js +87 -42
  85. package/dist/providers/stripe.d.ts +13 -1
  86. package/dist/providers/stripe.js +31 -60
  87. package/dist/registry.d.ts +34 -2
  88. package/dist/registry.js +85 -5
  89. package/dist/retired-toolkits.d.ts +0 -1
  90. package/dist/retired-toolkits.js +0 -1
  91. package/dist/routes/access-tokens.d.ts +0 -1
  92. package/dist/routes/access-tokens.js +0 -1
  93. package/dist/routes/activity.d.ts +0 -1
  94. package/dist/routes/activity.js +0 -1
  95. package/dist/routes/credentials.d.ts +0 -1
  96. package/dist/routes/credentials.js +0 -1
  97. package/dist/routes/mcp.d.ts +0 -1
  98. package/dist/routes/mcp.js +0 -1
  99. package/dist/routes/oauth.d.ts +0 -1
  100. package/dist/routes/oauth.js +0 -1
  101. package/dist/routes/shared.d.ts +2 -1
  102. package/dist/routes/shared.js +0 -1
  103. package/dist/routes/ui.d.ts +0 -1
  104. package/dist/routes/ui.js +0 -1
  105. package/dist/server.d.ts +0 -1
  106. package/dist/server.js +11 -1
  107. package/dist/skills.d.ts +0 -1
  108. package/dist/skills.js +0 -1
  109. package/dist/storage/file.d.ts +0 -1
  110. package/dist/storage/file.js +0 -1
  111. package/dist/storage/memory.d.ts +0 -1
  112. package/dist/storage/memory.js +0 -1
  113. package/dist/timeout.d.ts +0 -1
  114. package/dist/timeout.js +0 -1
  115. package/dist/tool-safety.d.ts +0 -1
  116. package/dist/tool-safety.js +0 -1
  117. package/dist/types.d.ts +45 -1
  118. package/dist/types.js +0 -1
  119. package/dist/ui.d.ts +0 -1
  120. package/dist/ui.js +13 -137
  121. package/dist/validate.d.ts +13 -15
  122. package/dist/validate.js +24 -11
  123. package/dist/version.d.ts +1 -2
  124. package/dist/version.js +1 -2
  125. package/documentation/architecture.md +186 -5
  126. package/documentation/auth.md +11 -0
  127. package/documentation/call-admission.md +142 -6
  128. package/documentation/cloudflare.md +92 -10
  129. package/documentation/code-first-exploration.md +2 -2
  130. package/documentation/code-mode.md +14 -14
  131. package/documentation/connector-guides.md +172 -5
  132. package/documentation/connectors.md +89 -0
  133. package/documentation/linear.md +20 -2
  134. package/documentation/mcp-ui-design.md +2 -2
  135. package/documentation/meta-tools.md +7 -1
  136. package/documentation/mixpanel.md +42 -9
  137. package/documentation/notion.md +23 -2
  138. package/documentation/operations.md +325 -5
  139. package/documentation/operator-ui.md +120 -5
  140. package/documentation/provider-audit.md +160 -0
  141. package/documentation/provider-conventions.md +667 -0
  142. package/documentation/request-admission.md +167 -5
  143. package/documentation/rich-output-design.md +1 -2
  144. package/documentation/stripe.md +15 -0
  145. package/documentation/upgrading.md +454 -0
  146. package/ethos.md +14 -9
  147. package/examples/worker/README.md +102 -12
  148. package/examples/worker/src/index.ts +46 -1
  149. package/examples/worker/wrangler.jsonc +14 -1
  150. package/package.json +10 -6
  151. package/templates/node/.dockerignore +10 -0
  152. package/templates/node/.env.example +40 -3
  153. package/templates/node/AGENTS.md +16 -1
  154. package/templates/node/Dockerfile +49 -0
  155. package/templates/node/README.md +117 -2
  156. package/templates/node/docker-compose.yml +39 -0
  157. package/templates/node/package.json +1 -1
  158. package/templates/node/src/file-activity.ts +182 -0
  159. package/templates/node/src/index.ts +80 -4
  160. package/assets/connecta-clay-hero.png +0 -0
  161. package/dist/access-tokens.d.ts.map +0 -1
  162. package/dist/access-tokens.js.map +0 -1
  163. package/dist/activity.d.ts.map +0 -1
  164. package/dist/activity.js.map +0 -1
  165. package/dist/apps-shell.d.ts.map +0 -1
  166. package/dist/apps-shell.js.map +0 -1
  167. package/dist/auth/bearer.d.ts.map +0 -1
  168. package/dist/auth/bearer.js.map +0 -1
  169. package/dist/auth/clerk.d.ts.map +0 -1
  170. package/dist/auth/clerk.js.map +0 -1
  171. package/dist/auth/downstream-oauth.d.ts.map +0 -1
  172. package/dist/auth/downstream-oauth.js.map +0 -1
  173. package/dist/call-admission.d.ts.map +0 -1
  174. package/dist/call-admission.js.map +0 -1
  175. package/dist/catalog-fingerprint.d.ts.map +0 -1
  176. package/dist/catalog-fingerprint.js.map +0 -1
  177. package/dist/catalog-limits.d.ts.map +0 -1
  178. package/dist/catalog-limits.js.map +0 -1
  179. package/dist/catalog-service.d.ts.map +0 -1
  180. package/dist/catalog-service.js.map +0 -1
  181. package/dist/catalog.d.ts.map +0 -1
  182. package/dist/catalog.js.map +0 -1
  183. package/dist/concurrency.d.ts.map +0 -1
  184. package/dist/concurrency.js.map +0 -1
  185. package/dist/connector-scope.d.ts.map +0 -1
  186. package/dist/connector-scope.js.map +0 -1
  187. package/dist/connectors/api.d.ts.map +0 -1
  188. package/dist/connectors/api.js.map +0 -1
  189. package/dist/connectors/remote-mcp.d.ts.map +0 -1
  190. package/dist/connectors/remote-mcp.js.map +0 -1
  191. package/dist/credentials.d.ts.map +0 -1
  192. package/dist/credentials.js.map +0 -1
  193. package/dist/errors.d.ts.map +0 -1
  194. package/dist/errors.js.map +0 -1
  195. package/dist/execute.d.ts.map +0 -1
  196. package/dist/execute.js.map +0 -1
  197. package/dist/executor-admission.d.ts.map +0 -1
  198. package/dist/executor-admission.js.map +0 -1
  199. package/dist/executor-result.d.ts.map +0 -1
  200. package/dist/executor-result.js.map +0 -1
  201. package/dist/executors/quickjs-child.d.ts.map +0 -1
  202. package/dist/executors/quickjs-child.js.map +0 -1
  203. package/dist/executors/quickjs-protocol.d.ts.map +0 -1
  204. package/dist/executors/quickjs-protocol.js.map +0 -1
  205. package/dist/executors/quickjs-runtime.d.ts.map +0 -1
  206. package/dist/executors/quickjs-runtime.js.map +0 -1
  207. package/dist/executors/quickjs.d.ts.map +0 -1
  208. package/dist/executors/quickjs.js.map +0 -1
  209. package/dist/favicon.d.ts.map +0 -1
  210. package/dist/favicon.js.map +0 -1
  211. package/dist/index.d.ts.map +0 -1
  212. package/dist/index.js.map +0 -1
  213. package/dist/invocation.d.ts.map +0 -1
  214. package/dist/invocation.js.map +0 -1
  215. package/dist/json-schema.d.ts.map +0 -1
  216. package/dist/json-schema.js.map +0 -1
  217. package/dist/mcp-result.d.ts.map +0 -1
  218. package/dist/mcp-result.js.map +0 -1
  219. package/dist/meta-tools.d.ts.map +0 -1
  220. package/dist/meta-tools.js.map +0 -1
  221. package/dist/node.d.ts.map +0 -1
  222. package/dist/node.js.map +0 -1
  223. package/dist/operator-ui/generated.d.ts.map +0 -1
  224. package/dist/operator-ui/generated.js.map +0 -1
  225. package/dist/operator-ui/model.d.ts.map +0 -1
  226. package/dist/operator-ui/model.js.map +0 -1
  227. package/dist/providers/cloudflare.d.ts.map +0 -1
  228. package/dist/providers/cloudflare.js.map +0 -1
  229. package/dist/providers/linear.d.ts.map +0 -1
  230. package/dist/providers/linear.js.map +0 -1
  231. package/dist/providers/mixpanel.d.ts.map +0 -1
  232. package/dist/providers/mixpanel.js.map +0 -1
  233. package/dist/providers/notion.d.ts.map +0 -1
  234. package/dist/providers/notion.js.map +0 -1
  235. package/dist/providers/stripe.d.ts.map +0 -1
  236. package/dist/providers/stripe.js.map +0 -1
  237. package/dist/registry.d.ts.map +0 -1
  238. package/dist/registry.js.map +0 -1
  239. package/dist/retired-toolkits.d.ts.map +0 -1
  240. package/dist/retired-toolkits.js.map +0 -1
  241. package/dist/routes/access-tokens.d.ts.map +0 -1
  242. package/dist/routes/access-tokens.js.map +0 -1
  243. package/dist/routes/activity.d.ts.map +0 -1
  244. package/dist/routes/activity.js.map +0 -1
  245. package/dist/routes/credentials.d.ts.map +0 -1
  246. package/dist/routes/credentials.js.map +0 -1
  247. package/dist/routes/mcp.d.ts.map +0 -1
  248. package/dist/routes/mcp.js.map +0 -1
  249. package/dist/routes/oauth.d.ts.map +0 -1
  250. package/dist/routes/oauth.js.map +0 -1
  251. package/dist/routes/shared.d.ts.map +0 -1
  252. package/dist/routes/shared.js.map +0 -1
  253. package/dist/routes/ui.d.ts.map +0 -1
  254. package/dist/routes/ui.js.map +0 -1
  255. package/dist/server.d.ts.map +0 -1
  256. package/dist/server.js.map +0 -1
  257. package/dist/skills.d.ts.map +0 -1
  258. package/dist/skills.js.map +0 -1
  259. package/dist/storage/file.d.ts.map +0 -1
  260. package/dist/storage/file.js.map +0 -1
  261. package/dist/storage/memory.d.ts.map +0 -1
  262. package/dist/storage/memory.js.map +0 -1
  263. package/dist/timeout.d.ts.map +0 -1
  264. package/dist/timeout.js.map +0 -1
  265. package/dist/tool-safety.d.ts.map +0 -1
  266. package/dist/tool-safety.js.map +0 -1
  267. package/dist/types.d.ts.map +0 -1
  268. package/dist/types.js.map +0 -1
  269. package/dist/ui.d.ts.map +0 -1
  270. package/dist/ui.js.map +0 -1
  271. package/dist/validate.d.ts.map +0 -1
  272. package/dist/validate.js.map +0 -1
  273. package/dist/version.d.ts.map +0 -1
  274. package/dist/version.js.map +0 -1
  275. package/examples/node/README.md +0 -52
  276. package/examples/node/src/index.ts +0 -71
  277. package/src/access-tokens.ts +0 -289
  278. package/src/activity.ts +0 -234
  279. package/src/apps-shell.ts +0 -370
  280. package/src/auth/bearer.ts +0 -61
  281. package/src/auth/clerk.ts +0 -553
  282. package/src/auth/downstream-oauth.ts +0 -575
  283. package/src/call-admission.ts +0 -521
  284. package/src/catalog-fingerprint.ts +0 -52
  285. package/src/catalog-limits.ts +0 -11
  286. package/src/catalog-service.ts +0 -1153
  287. package/src/catalog.ts +0 -790
  288. package/src/concurrency.ts +0 -39
  289. package/src/connector-scope.ts +0 -66
  290. package/src/connectors/api.ts +0 -159
  291. package/src/connectors/remote-mcp.ts +0 -1090
  292. package/src/credentials.ts +0 -428
  293. package/src/errors.ts +0 -364
  294. package/src/execute.ts +0 -1406
  295. package/src/executor-admission.ts +0 -328
  296. package/src/executor-result.ts +0 -107
  297. package/src/executors/quickjs-child.ts +0 -172
  298. package/src/executors/quickjs-protocol.ts +0 -99
  299. package/src/executors/quickjs-runtime.ts +0 -470
  300. package/src/executors/quickjs.ts +0 -776
  301. package/src/favicon.ts +0 -53
  302. package/src/index.ts +0 -666
  303. package/src/invocation.ts +0 -655
  304. package/src/json-schema.ts +0 -11
  305. package/src/mcp-result.ts +0 -43
  306. package/src/meta-tools.ts +0 -1607
  307. package/src/node.ts +0 -206
  308. package/src/operator-ui/browser.css +0 -423
  309. package/src/operator-ui/browser.ts +0 -1281
  310. package/src/operator-ui/generated.ts +0 -4
  311. package/src/operator-ui/model.ts +0 -111
  312. package/src/providers/cloudflare.ts +0 -3999
  313. package/src/providers/linear.ts +0 -302
  314. package/src/providers/mixpanel.ts +0 -229
  315. package/src/providers/notion.ts +0 -1879
  316. package/src/providers/stripe.ts +0 -307
  317. package/src/registry.ts +0 -1085
  318. package/src/retired-toolkits.ts +0 -14
  319. package/src/routes/access-tokens.ts +0 -115
  320. package/src/routes/activity.ts +0 -215
  321. package/src/routes/credentials.ts +0 -254
  322. package/src/routes/mcp.ts +0 -429
  323. package/src/routes/oauth.ts +0 -322
  324. package/src/routes/shared.ts +0 -247
  325. package/src/routes/ui.ts +0 -152
  326. package/src/server.ts +0 -195
  327. package/src/skills.ts +0 -271
  328. package/src/storage/file.ts +0 -123
  329. package/src/storage/memory.ts +0 -44
  330. package/src/timeout.ts +0 -84
  331. package/src/tool-safety.ts +0 -15
  332. package/src/types.ts +0 -523
  333. package/src/ui.ts +0 -744
  334. package/src/validate.ts +0 -387
  335. package/src/version.ts +0 -7
@@ -1,307 +0,0 @@
1
- import {
2
- remoteMcp,
3
- type RemoteMcpAuth,
4
- } from "../connectors/remote-mcp.js";
5
- import type {
6
- Connector,
7
- ConnectorCallAdmissionPolicy,
8
- ToolDef,
9
- } from "../types.js";
10
-
11
- /**
12
- * Which Stripe environment this instance speaks to. Required, and deliberately
13
- * undefaulted: there is no safe guess between an account that moves real money
14
- * and one that does not.
15
- */
16
- export type StripeMode = "production" | "sandbox";
17
-
18
- /** Stripe publishes one hosted MCP endpoint; the credential selects the mode. */
19
- export const STRIPE_MCP_ENDPOINT = "https://mcp.stripe.com/";
20
-
21
- export interface StripeOptions {
22
- /**
23
- * Which Stripe environment this connector reaches. Shapes the title,
24
- * description, guide, and admission budget, and is checked against a
25
- * recognizable key prefix in `auth` headers.
26
- */
27
- mode: StripeMode;
28
- /** Human-readable display name; defaults to "Stripe (<mode>)". */
29
- title?: string;
30
- /** Which business this account bills for, and what it may be asked. */
31
- purpose: string;
32
- /** OAuth by default; static headers support restricted API keys. */
33
- auth?: RemoteMcpAuth;
34
- /**
35
- * Connect platform only: act as this connected account (`acct_...`) by
36
- * sending Stripe's `Stripe-Account` header. Stripe does not support OAuth on
37
- * connected-account calls, so this requires `headers` auth.
38
- */
39
- connectedAccount?: string;
40
- /** Account-specific conventions appended to the maintained provider guide. */
41
- instructions?: string;
42
- /** Connector-specific inline result limit; omit to inherit the deployment. */
43
- maxResultBytes?: number;
44
- }
45
-
46
- /**
47
- * Stripe documents no MCP-specific rate limit, so this transcribes the account
48
- * limit the MCP server spends: 100 requests per second in live mode, 25 in a
49
- * sandbox (https://docs.stripe.com/rate-limits). The concurrency bound is
50
- * connecta's own conservative choice — Stripe documents that per-account and
51
- * per-endpoint concurrency limits exist and surface as `429` with a
52
- * `Stripe-Rate-Limited-Reason` of `global-concurrency` or
53
- * `endpoint-concurrency`, but publishes no number. Declaring `maxConcurrency`
54
- * is also what earns the right to the queue settings beside it.
55
- */
56
- const STRIPE_ADMISSION: Readonly<
57
- Record<StripeMode, ConnectorCallAdmissionPolicy>
58
- > = {
59
- production: {
60
- rules: [
61
- {
62
- maxConcurrency: 8,
63
- queueTimeoutMs: 5_000,
64
- retryAfterMs: 1_000,
65
- budget: { kind: "rolling-window", maxCalls: 100, windowMs: 1_000 },
66
- },
67
- ],
68
- },
69
- sandbox: {
70
- rules: [
71
- {
72
- maxConcurrency: 4,
73
- queueTimeoutMs: 5_000,
74
- retryAfterMs: 1_000,
75
- budget: { kind: "rolling-window", maxCalls: 25, windowMs: 1_000 },
76
- },
77
- ],
78
- },
79
- };
80
-
81
- /**
82
- * Tools whose official contract is observational rather than mutating.
83
- *
84
- * `stripe_api_read` is on this list because Stripe documents it as the `GET`
85
- * half of the generic pair — the tool itself is the read boundary, not the
86
- * endpoint an agent names inside it.
87
- */
88
- const READ_ONLY_TOOLS = new Set([
89
- "stripe_api_search",
90
- "stripe_api_details",
91
- "stripe_api_read",
92
- "get_stripe_account_info",
93
- "get_balance_summary",
94
- "search_stripe_documentation",
95
- "stripe_implementation_planner",
96
- ]);
97
-
98
- /**
99
- * The maintained write catalog. `"destructive"` tools modify or remove state
100
- * that already exists; `"additive"` ones only bring something new into being.
101
- * Both leave the read-only path — the distinction only decides whether the
102
- * connection asserts `destructiveHint`, which shapes the host's approval copy.
103
- *
104
- * `create_refund` is filed destructive despite its name: it reverses a
105
- * settled charge and moves money back out, which is a mutation of something
106
- * that already exists, not a fresh object appearing beside it.
107
- */
108
- const WRITE_TOOLS: ReadonlyMap<string, "additive" | "destructive"> = new Map([
109
- ["stripe_api_write", "destructive"],
110
- ["create_refund", "destructive"],
111
- ["stripe_report", "additive"],
112
- ["send_stripe_mcp_feedback", "additive"],
113
- ]);
114
-
115
- /**
116
- * Fill in downstream silence; keep reviewed destructive tools fail-closed.
117
- *
118
- * Silence is what a vetted classification is for, and an explicit downstream
119
- * annotation otherwise wins in both directions. `destructiveHint: true` or
120
- * `readOnlyHint: false` on an allowlisted read name is the downstream telling
121
- * us this release's allowlist is stale; `readOnlyHint: true` on a name no
122
- * release has classified says the same thing from the other side. The single
123
- * place a vetted verdict still overrides the downstream is a name this release
124
- * reviewed and filed destructive: there connecta knows what the tool does, and
125
- * a claim to the contrary is a downstream bug rather than news
126
- * ([#310](https://github.com/zackbart/connecta/issues/310),
127
- * [#315](https://github.com/zackbart/connecta/issues/315)).
128
- */
129
- function vettedSafety(definition: ToolDef): ToolDef {
130
- const downstream = definition.annotations ?? {};
131
- if (READ_ONLY_TOOLS.has(definition.name)) {
132
- if (
133
- downstream.destructiveHint === true ||
134
- downstream.readOnlyHint === false
135
- ) {
136
- return definition;
137
- }
138
- return {
139
- ...definition,
140
- annotations: {
141
- ...downstream,
142
- readOnlyHint: true,
143
- destructiveHint: downstream.destructiveHint ?? false,
144
- },
145
- };
146
- }
147
- if (WRITE_TOOLS.get(definition.name) === "destructive") {
148
- return {
149
- ...definition,
150
- annotations: {
151
- ...downstream,
152
- readOnlyHint: false,
153
- destructiveHint: true,
154
- },
155
- };
156
- }
157
- // Maintained additive writes and tools this release has never seen land here
158
- // alike. Fill-in only: a silent tool is not read-only, so drift still fails
159
- // closed onto `call_destructive_tool`, and neither population gets a
160
- // `destructiveHint` it has not earned. A tool that arrives explicitly
161
- // read-only keeps that annotation — on a name no release has reviewed, the
162
- // downstream's own word is the only evidence there is, and rewriting it
163
- // would be an overrule rather than a fill-in.
164
- return {
165
- ...definition,
166
- annotations: {
167
- ...downstream,
168
- readOnlyHint: downstream.readOnlyHint ?? false,
169
- },
170
- };
171
- }
172
-
173
- /** Stripe key prefixes carry their own mode; only a clear reading counts. */
174
- const LIVE_KEY = /\b(?:sk|rk|pk)_live_/;
175
- const TEST_KEY = /\b(?:sk|rk|pk)_test_/;
176
-
177
- /**
178
- * Refuse a deployment whose declared mode and supplied key disagree.
179
- *
180
- * This is the one half of production/sandbox routing connecta can actually
181
- * enforce. Nothing here reads or reports key material: an unrecognizable
182
- * credential (OAuth, or a key shape this release does not know) is left alone
183
- * rather than guessed at, and a mismatch names only the two modes.
184
- */
185
- function assertModeMatchesKey(
186
- id: string,
187
- mode: StripeMode,
188
- auth: RemoteMcpAuth,
189
- ): void {
190
- if (auth.type !== "headers") return;
191
- for (const value of Object.values(auth.headers)) {
192
- const keyMode = LIVE_KEY.test(value)
193
- ? "production"
194
- : TEST_KEY.test(value)
195
- ? "sandbox"
196
- : undefined;
197
- if (keyMode !== undefined && keyMode !== mode) {
198
- throw new Error(
199
- `stripe("${id}") declares mode "${mode}" but its auth headers carry a ` +
200
- `${keyMode === "production" ? "live" : "test"}-mode Stripe key.`,
201
- );
202
- }
203
- }
204
- }
205
-
206
- function resolveAuth(id: string, options: StripeOptions): RemoteMcpAuth {
207
- const auth = options.auth ?? { type: "oauth" };
208
- const connectedAccount = options.connectedAccount?.trim();
209
- if (connectedAccount === undefined || connectedAccount === "") return auth;
210
- if (!connectedAccount.startsWith("acct_")) {
211
- throw new Error(
212
- `stripe("${id}") connectedAccount must be a Stripe account id ("acct_...").`,
213
- );
214
- }
215
- if (auth.type !== "headers") {
216
- throw new Error(
217
- `stripe("${id}") cannot reach a connected account over OAuth; Stripe ` +
218
- `requires a restricted API key for Stripe-Account calls.`,
219
- );
220
- }
221
- return {
222
- type: "headers",
223
- headers: { ...auth.headers, "Stripe-Account": connectedAccount },
224
- };
225
- }
226
-
227
- const MODE_COPY: Readonly<
228
- Record<StripeMode, { title: string; blurb: string; warning: string }>
229
- > = {
230
- production: {
231
- title: "Stripe (production)",
232
- blurb: "production — live money and real customers",
233
- warning:
234
- "This is a PRODUCTION account. 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.",
235
- },
236
- sandbox: {
237
- title: "Stripe (sandbox)",
238
- blurb: "sandbox — test data, no real money",
239
- warning:
240
- "This is a SANDBOX account. 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.",
241
- },
242
- };
243
-
244
- function usageGuide(
245
- mode: StripeMode,
246
- purpose: string,
247
- instructions: string | undefined,
248
- ): string {
249
- const copy = MODE_COPY[mode];
250
- const accountInstructions = instructions?.trim();
251
- const rate = mode === "production" ? "100" : "25";
252
- return `# Stripe usage
253
-
254
- Mode: ${mode}. Account purpose: ${purpose}
255
-
256
- ${copy.warning}
257
-
258
- - 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.
259
- - Prefer a dedicated tool when one covers the task: \`get_stripe_account_info\` for which account this is, \`get_balance_summary\` for balances, \`create_refund\` for refunds, \`stripe_report\` for reports. One call instead of three, and a refund named \`create_refund\` reads far more clearly in the approval a human sees than the same refund buried in \`stripe_api_write\` arguments.
260
- - \`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.
261
- - 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\` and reduce before returning.
262
- - 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.
263
- - 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.
264
- - Stripe answers a rate limit with \`429\` and a \`Stripe-Rate-Limited-Reason\` header; back off on that rather than retrying immediately. This account's documented ceiling is ${rate} requests per second, and any single endpoint is capped at 25 per second regardless of mode, so paging one list is the real constraint.
265
- - 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.
266
- - 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.
267
- ${
268
- accountInstructions
269
- ? `\n## Account instructions\n\n${accountInstructions}\n`
270
- : ""
271
- }`;
272
- }
273
-
274
- /** A maintained Stripe hosted-MCP connection. */
275
- export function stripe(id: string, options: StripeOptions): Connector {
276
- const purpose = options.purpose.trim();
277
- if (!purpose) {
278
- throw new Error("stripe() requires a non-empty account purpose.");
279
- }
280
- const mode = options.mode;
281
- if (mode !== "production" && mode !== "sandbox") {
282
- throw new Error(
283
- `stripe("${id}") requires mode "production" or "sandbox".`,
284
- );
285
- }
286
- const auth = resolveAuth(id, options);
287
- assertModeMatchesKey(id, mode, auth);
288
- const copy = MODE_COPY[mode];
289
- const connector = remoteMcp(id, {
290
- url: STRIPE_MCP_ENDPOINT,
291
- title: options.title ?? copy.title,
292
- description: `Stripe payments (${copy.blurb}) — ${purpose}`,
293
- auth,
294
- requireHttps: true,
295
- callAdmission: STRIPE_ADMISSION[mode],
296
- usageGuide: usageGuide(mode, purpose, options.instructions),
297
- ...(options.maxResultBytes !== undefined
298
- ? { maxResultBytes: options.maxResultBytes }
299
- : {}),
300
- });
301
- return {
302
- ...connector,
303
- async listTools(ctx) {
304
- return (await connector.listTools(ctx)).map(vettedSafety);
305
- },
306
- };
307
- }