@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
@@ -0,0 +1,160 @@
1
+ # Provider audit
2
+
3
+ [`provider-conventions.md`](./provider-conventions.md) wrote the bar down. This
4
+ document runs it against the five maintained prebuilt connections and returns a
5
+ verdict for every applicable convention: **meets**, **misses** (with the fix),
6
+ or **n/a** (with the reason). A convention is never quietly skipped, and an
7
+ accepted miss is recorded as a provider-specific exception with its argument
8
+ rather than left blank.
9
+
10
+ Hand-written HTTP providers are audited against H1–H14; hosted-MCP proxies
11
+ against P1–P13. Applying a hand-written convention to a proxy is a category
12
+ error, not a finding, so the proxy reports have no H rows.
13
+
14
+ Every miss below is fixed in the same change that recorded it
15
+ ([#342](https://github.com/zackbart/connecta/issues/342)), except where the row
16
+ says otherwise. The mechanically checkable half of the hand-written bar is now
17
+ a test — [`test/provider-conventions.test.ts`](https://github.com/zackbart/connecta/blob/main/test/provider-conventions.test.ts)
18
+ walks the shipped surface of both `api()` providers on every run, so these
19
+ verdicts cannot rot quietly back into prose. The proxies' mechanical rows live
20
+ in their own suites, because what they assert is the wrapper's identity,
21
+ classification, and budget rather than tool shapes the wrapper does not own.
22
+
23
+ Two things this audit deliberately does not decide:
24
+
25
+ - **Whether each Cloudflare named tool earns its place.** That is
26
+ [#350](https://github.com/zackbart/connecta/issues/350), which measures the
27
+ named surface against the escape hatch with usage evidence. H14's keep/prune
28
+ judgment is reported here as open, not answered.
29
+ - **Whether a downstream catalog has drifted since a release reviewed it.**
30
+ Detection at refresh shipped with
31
+ [#343](https://github.com/zackbart/connecta/issues/343) and the maintainer-run
32
+ check is [#351](https://github.com/zackbart/connecta/issues/351). P13 is
33
+ audited as "is the list addressable by such a check", not as "is the list
34
+ current" — the answer to the second question arrives from a running
35
+ deployment, not from a reading.
36
+
37
+ ## Cloudflare — hand-written HTTP
38
+
39
+ Fifty-five tools over the v4 REST API: fifty-two named, three guarded escape
40
+ hatches. The largest surface here and the one with the most to get wrong.
41
+
42
+ | Convention | Verdict | Notes |
43
+ | --- | --- | --- |
44
+ | H1 identity | meets | `id`, required `purpose` (blank throws), optional `title`, `instructions` appended under `## Account instructions` |
45
+ | H2 names | meets | every name is `snake_case` and opens with a verb from the connector's own set; the hatches sort together as `cloudflare_api_*` |
46
+ | H3 budgets | **missed → fixed** | `cloudflare_api_get` (289), `cloudflare_api_mutate` (266), and `create_dns_record` (305) exceeded the 240-character describe budget. All three trimmed; the record-type list `create_dns_record` was spending 60 characters on is already the `type` enum |
47
+ | H4 disqualifiers | meets (a reading) | the hatch descriptions say what they will not do — mutate, upload — and `create_dns_record` now names the types it reads but cannot create |
48
+ | H5 schemas | **missed → fixed** | the top level was already exemplary — every tool a closed plain object with a `required` list, a description on every property, and an `api()` construction contract that refuses an unenforceable schema (#340) — but H5 says *every* property, and the nested ones had been read as furniture. `bulk_write_kv_values` shipped six undescribed fields inside `entries[]`, including the expiry pair whose units and floor are the whole question. All six now say what they are, and the convention test walks every depth rather than the first one |
49
+ | H5 exception | recorded | the three escape hatches' request parts — `query[]`, `headers[]`, `fields[]`, `files[]` — keep undescribed `name`/`value` members, because H5 collides with H7 there. `query` and `headers` are one shared constant the renderer inlines into all three hatches, and `cloudflare_api_upload` sits at 1,007 of the 1,024-byte budget this same audit brought it back under; describing name/value pairs the parent property has already named as name/value pairs would truncate the whole tool in discovery. The 21 properties are listed by path in `test/provider-conventions.test.ts` and asserted exactly, so a new one fails and so does a stale entry |
50
+ | H6 whose bound | meets | exemplary. `pagingInputProperties` carries a three-way `bounds` vocabulary — `cloudflare`, `clamped`, `undocumented` — and the description says which one applies |
51
+ | H7 compact fit | **missed → fixed** | `cloudflare_api_upload` rendered to 1,297 bytes. The refused-header list, inlined once per hatch, moved to the usage guide; the remaining upload descriptions were cut to the fact each adds. Now 1,007 |
52
+ | H8 output schemas | meets | 52 of 52 declare one |
53
+ | H9 projection | meets | reads project and rename; `raw: true` wherever the projection drops something recoverable; `cloudflare_api_get` is the universal unprojected read |
54
+ | H10 pagination | **missed → fixed** | two conventions live here, which H10 allows, but only the guide said so. Three of the four cursor tools had a bare `nextCursor: { type: "string" }` with no description. Both ends now state it: `cursor` says the endpoint pages by cursor, `nextCursor` says it is the only signal and no `page` object is coming |
55
+ | H11 errors | meets | mapped by the caller's next move, including the 400-with-credential-code case that is `auth_required` rather than `invalid_args`; every mapped status has a test asserting code and retryability |
56
+ | H12 credential | meets | labeled fields per authentication mode, `testCredential` on the token path (`/user/tokens/verify`) and `testCredentials` on the Global API Key pair (`/user`), each reporting who it authenticated as |
57
+ | H13 guide | **missed → fixed** | the guide was a bare string, so its summary was derived from the first content line — the zone-scoping rule, which varies per deployment and reads as an instruction. Now structured with a declared summary. `required` stays unset, deliberately: every named schema is complete enough to call on its own and the scoping convention is repeated on each `zoneId` and `accountId` property, so forcing the guide into context before every operation would buy nothing |
58
+ | H14 hatch shape | meets | split GET / JSON-mutate / upload, the split is Connecta's, the GET tool is annotated read-only, paths are provider-relative and confined |
59
+ | H14 keep/prune | **open — [#350](https://github.com/zackbart/connecta/issues/350)** | whether each of the named tools beats the hatch on schema, projection, or safety routing is a reading that needs usage evidence. Out of scope here by the issue's own terms |
60
+
61
+ ## Notion — hand-written HTTP
62
+
63
+ Fifteen tools over the public REST API, pinned to `2026-03-11`. A small,
64
+ deliberate surface.
65
+
66
+ | Convention | Verdict | Notes |
67
+ | --- | --- | --- |
68
+ | H1 identity | meets | `id`, required `purpose` (blank throws), optional `title`, `instructions` appended under `## Workspace instructions` |
69
+ | H2 names | meets | `snake_case` throughout, and Notion's own vocabulary (`query_`, `append_`, `trash_`) where the shared verbs would lie — `trash_page` is not `delete_page`, because Notion does not delete |
70
+ | H3 budgets | **missed → fixed** | `search` was 252 characters. Trimmed to 205; the clause it lost restated what `get_page` is for |
71
+ | H4 disqualifiers | meets (a reading) | `search` "Never searches page content" is the convention document's own worked example, and it came from here |
72
+ | H5 schemas | **missed → fixed** | four gaps. A schema the validator could not evaluate would have forwarded arguments unchecked rather than refusing — in a surface we wrote ourselves that is our bug being papered over; `api()` now refuses such a schema at construction for every connector (#340). `search`, `list_users`, and `get_self` carried no `required` list at all, and `create_page` carried none because its constraint is exclusive rather than positional. All four now declare one, and the shipped schemas are asserted evaluable so fail-closed handling cannot become a blanket refusal. The fourth gap was nested: `query_data_source`'s `sorts[].direction` carried an enum and no description, which the top-level-only reading of H5 had missed |
73
+ | H5 exception | recorded | `create_page` declares `required: []`, not the truth. A page needs exactly one parent, but *which* parent is an exclusive choice a plain-object `required` list cannot express, and the top-level `anyOf` that could would cost the tool its `inputKeys` in discovery — the caller would learn nothing about the arguments without expanding the schema. The rule is stated in both parent descriptions and enforced locally as `invalid_args` before any round trip, so the cost H5 exists to avoid is still avoided |
74
+ | H6 whose bound | meets | `page_size` names Notion's 1–100 and says the default is the connector's configured one |
75
+ | H7 compact fit | **missed → fixed** | `query_data_source` rendered to 1,087 bytes. Three shared property descriptions (`raw`, `start_cursor`, `properties`) were carrying guide-length prose that the renderer inlines once per tool that uses them; cut to the fact each one adds. `query_data_source` is now 909 and every other tool got smaller for free |
76
+ | H8 output schemas | meets | 15 of 15 |
77
+ | H9 projection | meets | every read projects; `raw: true` on the seven reads where the dropped detail can matter; Notion's own 25-entry property truncation is surfaced as `truncated_properties` with the `property_id` needed to fetch the rest, rather than handed back as a confident partial |
78
+ | H10 pagination | meets | one convention, one signal: `page_size` and `start_cursor` in, `has_more` beside `next_cursor` out, default 25 against Notion's 100 |
79
+ | H11 errors | meets | and unusually careful about the ambiguity: a 404 is `connector_call_failed`, not `auth_required`, because `authorize_connector` cannot fix "never shared with this integration", and the message states the ambiguity instead of picking the convenient reading |
80
+ | H12 credential | meets | one labeled integration-token field; `testCredential` calls `/v1/users/me` and reports the workspace it authenticated as |
81
+ | H13 guide | meets | structured, declared summary, `required: true` with a stated reason — the database→data-source lookup is a sequence no complete schema can express |
82
+ | H14 hatch | **missed → fixed** | Notion has no guarded raw-REST tool, which H14 explicitly permits for a finite surface — provided it says so. It did not. The guide now names the absence, so an agent does not spend a search proving there is no `notion_api_get` |
83
+
84
+ ## Linear — hosted-MCP proxy
85
+
86
+ | Convention | Verdict | Notes |
87
+ | --- | --- | --- |
88
+ | P1 add, never rewrite | meets | `listTools` maps annotations and returns every other field untouched |
89
+ | P2 identity | meets | required `purpose` (blank throws), `instructions` appended, and appended text cannot reach the classification |
90
+ | P3 routing fact | meets | read-only rides the default title *and* opens the guide, because search renders neither description |
91
+ | P4 endpoint default | **missed → fixed, departing from the letter** | `access` defaulted to `"read-write"`, which is not the safe endpoint. It is now required with no default, and construction throws naming both options. The convention says "default to the safe one"; the honest reading of its heading — *the safest **honest** default* — is that Linear has none. Defaulting to `"read-only"` would turn a deployment that does write into one whose every write fails at Linear, at runtime, where no agent can repair it; defaulting to `"read-write"` hands out writes nobody asked for. Requiring the declaration fails at construction, where an operator can act. This is the one place in the audit where the fix departs from a convention's literal text, and it is recorded here rather than smuggled |
92
+ | P5 classification | meets | reads and writes named, unlisted resolves to not-read-only, reviewed destructive beats a contradictory `readOnlyHint: true`, additive writes leave `destructiveHint` unset |
93
+ | P6 catalog varies | meets | the guide names customer requests, releases, and code review as the plan- and feature-gated areas where absence is expected |
94
+ | P7 reduction advice | **missed → fixed** | the guide was a bare string. Its derived summary was the access note cut mid-sentence at 120 characters — the one fact an agent must not get wrong, delivered as a fragment. Now structured with a declared summary per access mode. `required` stays unset: Linear's own schemas describe each call, and the guide's value is cross-tool sequence advice worth reading before a write, not before every read |
95
+ | P8 identity resolution | meets | exemplary. The guide names the read tools that produce each id, and separates Linear's human identifier (`ENG-123`) from its UUID |
96
+ | P9 authentication | meets | OAuth default, `requireHttps`, personal API key documented as a secret and paired with the narrowest access, `auth_required` → `authorize_connector` route named in the guide |
97
+ | P10 no credential test | meets | no `credential`, `testCredential`, or `testCredentials` on the wrapper |
98
+ | P11 transport vs tool error | meets | inherited whole from `remoteMcp()`; the wrapper adds no error handling and reads no downstream prose |
99
+ | P12 admission budget | meets | exemplary, and the reason P12 exists. Linear documents no MCP-specific limit and meters the underlying API per user per hour, so the connection declares no budget and documents how an operator supplies one |
100
+ | P13 drift visible | meets | both lists are module-level constants in one file per provider, and now *are* the manifest the wrapper classifies from, compared against the live catalog on every refresh ([#343](https://github.com/zackbart/connecta/issues/343)); the maintainer-run check is [#351](https://github.com/zackbart/connecta/issues/351) |
101
+
102
+ ## Stripe — hosted-MCP proxy
103
+
104
+ | Convention | Verdict | Notes |
105
+ | --- | --- | --- |
106
+ | P1 add, never rewrite | meets | annotations only |
107
+ | P2 identity | meets | required `purpose`, `instructions` appended, classification untouchable from there |
108
+ | P3 routing fact | meets | production versus sandbox appears in the title, the description, and the guide's first line |
109
+ | P4 endpoint default | meets | exemplary, and the model for the second clause: one published endpoint, `mode` required with no default, and construction throws when a recognizable key prefix contradicts the declared mode without reading anything it cannot classify |
110
+ | P5 classification | meets | including the two verdicts that needed an argument — `stripe_api_read` is a read because the tool is the boundary, `create_refund` is destructive despite its name |
111
+ | P6 catalog varies | **missed → fixed** | the doc already knew this (`get_balance_summary` is Treasury and gated; a `create_customer` example survives in Stripe's prose but not its tool table), but the *guide* did not say it, and the guide is what reaches the agent. Added |
112
+ | P7 reduction advice | **missed → fixed** | bare string; the derived summary was "Mode: production. Account purpose: …", spending the 120-character budget on the operator's prose. Now a declared, mode-shaped summary. `required` unset: the four generic tools are the routing decision and the mode warning already rides the title and description |
113
+ | P8 identity resolution | **missed → fixed** | Stripe's writes take ids and the guide never said where they come from. Added: the typed prefixes (`cus_`, `sub_`, `ch_`, `pi_`, `in_`, `acct_`), the rule that a plausible-looking id belongs to a different object or to nobody, and the read tools that produce a real one |
114
+ | P9 authentication | meets | OAuth default, `requireHttps`, restricted key documented as a secret and paired with the narrowest scope. The `auth_required` → `authorize_connector` route was added to the guide alongside P8, since a proxy's only recovery instruction lives there |
115
+ | P10 no credential test | meets | no credential slot; the mode/key contradiction throws at construction instead, which is where P10 says the H12 guarantee gets paid |
116
+ | P11 transport vs tool error | meets | inherited from `remoteMcp()`; the guide now also says that a rejected argument or plan restriction arrives in Stripe's own words and is not an authorization problem |
117
+ | P12 admission budget | meets | a citable documented number (100/s live, 25/s sandbox), transcribed per mode, with `maxConcurrency` labeled as Connecta's own conservative choice |
118
+ | P13 drift visible | meets | both lists are module-level constants in one file, and are the manifest the refresh-time drift check compares against ([#343](https://github.com/zackbart/connecta/issues/343)) |
119
+
120
+ ## Mixpanel — hosted-MCP proxy
121
+
122
+ The proxy with the most misses, and none of them subtle: it was written before
123
+ the conventions existed and inherited its shape from Linear without inheriting
124
+ Linear's reasoning.
125
+
126
+ | Convention | Verdict | Notes |
127
+ | --- | --- | --- |
128
+ | P1 add, never rewrite | meets | annotations only |
129
+ | P2 identity | meets | required `purpose`, `instructions` appended |
130
+ | P3 routing fact | **missed → fixed** | region is exactly the fact P3 names, and it appeared in neither the default title (`"Mixpanel"`) nor the guide's first line. A project lives in one residency, so a question pointed at the wrong connector comes back empty rather than wrong — which reads as the project having no data. The title now carries it (`Mixpanel (us)`, `(eu)`, `(in)`) and the guide opens with it |
131
+ | P4 endpoint default | meets | three published endpoints, an option that selects between them, and `"us"` as the default because that is where a project lives unless it was explicitly created elsewhere. Unlike Linear's, this default is honest: a wrong region cannot cause an irrecoverable write, only an empty read. Construction now also rejects a region there is no endpoint for |
132
+ | P5 classification | meets | reads and writes named, unlisted fails closed, reviewed destructive beats a contradictory `readOnlyHint: true` |
133
+ | P6 catalog varies | **missed → fixed** | the provider doc knew that 15 of the 63 classified tools are beta surfaces; the guide did not say so. Added, naming experiments, feature flags, session replay, and issue triage as the usual absentees |
134
+ | P7 reduction advice | **missed → fixed** | bare string, derived summary. Now structured with a declared, region-shaped summary. `required` unset: the project-then-context sequence is worth reading before an analysis, not before every call |
135
+ | P8 identity resolution | **missed → fixed** | the guide told an agent not to guess event and property *spelling* but said nothing about ids, and Mixpanel's `Get-`, `Update-`, and `Delete-` tools all take them. Added, naming the `List-` tools that produce each one |
136
+ | P9 authentication | meets | OAuth default, `requireHttps`, service account documented as a secret |
137
+ | P10 no credential test | partial — n/a for half | no `credential`, `testCredential`, or `testCredentials`, as required. The construction-time contradiction check P10 points at has nothing to check here: a Mixpanel service-account token does not encode its region, so there is no recognizable credential for a declared region to contradict. Recorded rather than invented — guessing a region from a token shape this release does not understand is precisely what P4 tells Stripe not to do |
138
+ | P11 transport vs tool error | meets | inherited from `remoteMcp()`; the guide now names the `auth_required` → `authorize_connector` route and says a plan restriction arrives in Mixpanel's own words |
139
+ | P12 admission budget | **missed → fixed** | the connection hardcoded a 600-call hourly budget transcribed from a limit Mixpanel meters **per user**. P12 names this case exactly: a per-runtime counter cannot approximate a per-user quota in either direction — one runtime serving several users under-counts, several isolates sharing one credential each admit a full budget. The default is removed; `callAdmission` is now an operator option with a documented example, matching Linear |
140
+ | P13 drift visible | meets | both lists are module-level constants in one file, and are the manifest the refresh-time drift check compares against ([#343](https://github.com/zackbart/connecta/issues/343)) |
141
+
142
+ ## Scoreboard
143
+
144
+ | Provider | Meets | Missed and fixed | Recorded exception | Open |
145
+ | --- | --- | --- | --- | --- |
146
+ | Cloudflare | 9 | 5 | H5 hatch request parts | H14 keep/prune ([#350](https://github.com/zackbart/connecta/issues/350)) |
147
+ | Notion | 10 | 4 | H5 exclusive parent | — |
148
+ | Linear | 11 | 2 | P4 departs from the letter | — |
149
+ | Stripe | 10 | 3 | — | — |
150
+ | Mixpanel | 7 | 5 | P10 half n/a | — |
151
+
152
+ Nineteen misses, nineteen fixes, four recorded exceptions, one judgment left to
153
+ the issue that owns it. The pattern in the misses is worth naming: sixteen of
154
+ the nineteen are a guide, a title, or a schema description failing to *say*
155
+ something the implementation already did correctly. Only three changed what a
156
+ provider does — Notion refusing an unevaluable schema, Linear requiring an
157
+ access declaration, Mixpanel dropping a budget it could not honestly compute.
158
+ The conventions are mostly not asking for different behavior. They are asking
159
+ for the behavior to reach the agent, which is a different problem and, on this
160
+ evidence, the one the providers were losing.