@zackbart/connecta 0.15.1 → 0.16.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.
Files changed (332) hide show
  1. package/AGENTS.md +28 -15
  2. package/CHANGELOG.md +466 -0
  3. package/README.md +19 -4
  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 +0 -1
  27. package/dist/catalog.d.ts +0 -1
  28. package/dist/catalog.js +0 -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 +0 -1
  42. package/dist/errors.js +0 -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 +250 -276
  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 +58 -8
  129. package/documentation/code-mode.md +12 -12
  130. package/documentation/connector-guides.md +172 -5
  131. package/documentation/connectors.md +89 -0
  132. package/documentation/linear.md +20 -2
  133. package/documentation/mcp-ui-design.md +2 -2
  134. package/documentation/mixpanel.md +42 -9
  135. package/documentation/notion.md +16 -0
  136. package/documentation/operations.md +283 -5
  137. package/documentation/operator-ui.md +120 -5
  138. package/documentation/provider-audit.md +160 -0
  139. package/documentation/provider-conventions.md +631 -0
  140. package/documentation/request-admission.md +167 -5
  141. package/documentation/rich-output-design.md +1 -2
  142. package/documentation/stripe.md +15 -0
  143. package/ethos.md +13 -8
  144. package/examples/worker/README.md +96 -12
  145. package/examples/worker/src/index.ts +46 -1
  146. package/examples/worker/wrangler.jsonc +14 -1
  147. package/package.json +4 -5
  148. package/templates/node/.dockerignore +10 -0
  149. package/templates/node/.env.example +40 -3
  150. package/templates/node/AGENTS.md +11 -1
  151. package/templates/node/Dockerfile +49 -0
  152. package/templates/node/README.md +117 -2
  153. package/templates/node/docker-compose.yml +39 -0
  154. package/templates/node/package.json +1 -1
  155. package/templates/node/src/file-activity.ts +182 -0
  156. package/templates/node/src/index.ts +80 -4
  157. package/assets/connecta-clay-hero.png +0 -0
  158. package/dist/access-tokens.d.ts.map +0 -1
  159. package/dist/access-tokens.js.map +0 -1
  160. package/dist/activity.d.ts.map +0 -1
  161. package/dist/activity.js.map +0 -1
  162. package/dist/apps-shell.d.ts.map +0 -1
  163. package/dist/apps-shell.js.map +0 -1
  164. package/dist/auth/bearer.d.ts.map +0 -1
  165. package/dist/auth/bearer.js.map +0 -1
  166. package/dist/auth/clerk.d.ts.map +0 -1
  167. package/dist/auth/clerk.js.map +0 -1
  168. package/dist/auth/downstream-oauth.d.ts.map +0 -1
  169. package/dist/auth/downstream-oauth.js.map +0 -1
  170. package/dist/call-admission.d.ts.map +0 -1
  171. package/dist/call-admission.js.map +0 -1
  172. package/dist/catalog-fingerprint.d.ts.map +0 -1
  173. package/dist/catalog-fingerprint.js.map +0 -1
  174. package/dist/catalog-limits.d.ts.map +0 -1
  175. package/dist/catalog-limits.js.map +0 -1
  176. package/dist/catalog-service.d.ts.map +0 -1
  177. package/dist/catalog-service.js.map +0 -1
  178. package/dist/catalog.d.ts.map +0 -1
  179. package/dist/catalog.js.map +0 -1
  180. package/dist/concurrency.d.ts.map +0 -1
  181. package/dist/concurrency.js.map +0 -1
  182. package/dist/connector-scope.d.ts.map +0 -1
  183. package/dist/connector-scope.js.map +0 -1
  184. package/dist/connectors/api.d.ts.map +0 -1
  185. package/dist/connectors/api.js.map +0 -1
  186. package/dist/connectors/remote-mcp.d.ts.map +0 -1
  187. package/dist/connectors/remote-mcp.js.map +0 -1
  188. package/dist/credentials.d.ts.map +0 -1
  189. package/dist/credentials.js.map +0 -1
  190. package/dist/errors.d.ts.map +0 -1
  191. package/dist/errors.js.map +0 -1
  192. package/dist/execute.d.ts.map +0 -1
  193. package/dist/execute.js.map +0 -1
  194. package/dist/executor-admission.d.ts.map +0 -1
  195. package/dist/executor-admission.js.map +0 -1
  196. package/dist/executor-result.d.ts.map +0 -1
  197. package/dist/executor-result.js.map +0 -1
  198. package/dist/executors/quickjs-child.d.ts.map +0 -1
  199. package/dist/executors/quickjs-child.js.map +0 -1
  200. package/dist/executors/quickjs-protocol.d.ts.map +0 -1
  201. package/dist/executors/quickjs-protocol.js.map +0 -1
  202. package/dist/executors/quickjs-runtime.d.ts.map +0 -1
  203. package/dist/executors/quickjs-runtime.js.map +0 -1
  204. package/dist/executors/quickjs.d.ts.map +0 -1
  205. package/dist/executors/quickjs.js.map +0 -1
  206. package/dist/favicon.d.ts.map +0 -1
  207. package/dist/favicon.js.map +0 -1
  208. package/dist/index.d.ts.map +0 -1
  209. package/dist/index.js.map +0 -1
  210. package/dist/invocation.d.ts.map +0 -1
  211. package/dist/invocation.js.map +0 -1
  212. package/dist/json-schema.d.ts.map +0 -1
  213. package/dist/json-schema.js.map +0 -1
  214. package/dist/mcp-result.d.ts.map +0 -1
  215. package/dist/mcp-result.js.map +0 -1
  216. package/dist/meta-tools.d.ts.map +0 -1
  217. package/dist/meta-tools.js.map +0 -1
  218. package/dist/node.d.ts.map +0 -1
  219. package/dist/node.js.map +0 -1
  220. package/dist/operator-ui/generated.d.ts.map +0 -1
  221. package/dist/operator-ui/generated.js.map +0 -1
  222. package/dist/operator-ui/model.d.ts.map +0 -1
  223. package/dist/operator-ui/model.js.map +0 -1
  224. package/dist/providers/cloudflare.d.ts.map +0 -1
  225. package/dist/providers/cloudflare.js.map +0 -1
  226. package/dist/providers/linear.d.ts.map +0 -1
  227. package/dist/providers/linear.js.map +0 -1
  228. package/dist/providers/mixpanel.d.ts.map +0 -1
  229. package/dist/providers/mixpanel.js.map +0 -1
  230. package/dist/providers/notion.d.ts.map +0 -1
  231. package/dist/providers/notion.js.map +0 -1
  232. package/dist/providers/stripe.d.ts.map +0 -1
  233. package/dist/providers/stripe.js.map +0 -1
  234. package/dist/registry.d.ts.map +0 -1
  235. package/dist/registry.js.map +0 -1
  236. package/dist/retired-toolkits.d.ts.map +0 -1
  237. package/dist/retired-toolkits.js.map +0 -1
  238. package/dist/routes/access-tokens.d.ts.map +0 -1
  239. package/dist/routes/access-tokens.js.map +0 -1
  240. package/dist/routes/activity.d.ts.map +0 -1
  241. package/dist/routes/activity.js.map +0 -1
  242. package/dist/routes/credentials.d.ts.map +0 -1
  243. package/dist/routes/credentials.js.map +0 -1
  244. package/dist/routes/mcp.d.ts.map +0 -1
  245. package/dist/routes/mcp.js.map +0 -1
  246. package/dist/routes/oauth.d.ts.map +0 -1
  247. package/dist/routes/oauth.js.map +0 -1
  248. package/dist/routes/shared.d.ts.map +0 -1
  249. package/dist/routes/shared.js.map +0 -1
  250. package/dist/routes/ui.d.ts.map +0 -1
  251. package/dist/routes/ui.js.map +0 -1
  252. package/dist/server.d.ts.map +0 -1
  253. package/dist/server.js.map +0 -1
  254. package/dist/skills.d.ts.map +0 -1
  255. package/dist/skills.js.map +0 -1
  256. package/dist/storage/file.d.ts.map +0 -1
  257. package/dist/storage/file.js.map +0 -1
  258. package/dist/storage/memory.d.ts.map +0 -1
  259. package/dist/storage/memory.js.map +0 -1
  260. package/dist/timeout.d.ts.map +0 -1
  261. package/dist/timeout.js.map +0 -1
  262. package/dist/tool-safety.d.ts.map +0 -1
  263. package/dist/tool-safety.js.map +0 -1
  264. package/dist/types.d.ts.map +0 -1
  265. package/dist/types.js.map +0 -1
  266. package/dist/ui.d.ts.map +0 -1
  267. package/dist/ui.js.map +0 -1
  268. package/dist/validate.d.ts.map +0 -1
  269. package/dist/validate.js.map +0 -1
  270. package/dist/version.d.ts.map +0 -1
  271. package/dist/version.js.map +0 -1
  272. package/examples/node/README.md +0 -52
  273. package/examples/node/src/index.ts +0 -71
  274. package/src/access-tokens.ts +0 -289
  275. package/src/activity.ts +0 -234
  276. package/src/apps-shell.ts +0 -370
  277. package/src/auth/bearer.ts +0 -61
  278. package/src/auth/clerk.ts +0 -553
  279. package/src/auth/downstream-oauth.ts +0 -575
  280. package/src/call-admission.ts +0 -521
  281. package/src/catalog-fingerprint.ts +0 -52
  282. package/src/catalog-limits.ts +0 -11
  283. package/src/catalog-service.ts +0 -1153
  284. package/src/catalog.ts +0 -790
  285. package/src/concurrency.ts +0 -39
  286. package/src/connector-scope.ts +0 -66
  287. package/src/connectors/api.ts +0 -159
  288. package/src/connectors/remote-mcp.ts +0 -1090
  289. package/src/credentials.ts +0 -428
  290. package/src/errors.ts +0 -364
  291. package/src/execute.ts +0 -1406
  292. package/src/executor-admission.ts +0 -328
  293. package/src/executor-result.ts +0 -107
  294. package/src/executors/quickjs-child.ts +0 -172
  295. package/src/executors/quickjs-protocol.ts +0 -99
  296. package/src/executors/quickjs-runtime.ts +0 -470
  297. package/src/executors/quickjs.ts +0 -776
  298. package/src/favicon.ts +0 -53
  299. package/src/index.ts +0 -666
  300. package/src/invocation.ts +0 -655
  301. package/src/json-schema.ts +0 -11
  302. package/src/mcp-result.ts +0 -43
  303. package/src/meta-tools.ts +0 -1607
  304. package/src/node.ts +0 -206
  305. package/src/operator-ui/browser.css +0 -423
  306. package/src/operator-ui/browser.ts +0 -1281
  307. package/src/operator-ui/generated.ts +0 -4
  308. package/src/operator-ui/model.ts +0 -111
  309. package/src/providers/cloudflare.ts +0 -3999
  310. package/src/providers/linear.ts +0 -302
  311. package/src/providers/mixpanel.ts +0 -229
  312. package/src/providers/notion.ts +0 -1879
  313. package/src/providers/stripe.ts +0 -307
  314. package/src/registry.ts +0 -1085
  315. package/src/retired-toolkits.ts +0 -14
  316. package/src/routes/access-tokens.ts +0 -115
  317. package/src/routes/activity.ts +0 -215
  318. package/src/routes/credentials.ts +0 -254
  319. package/src/routes/mcp.ts +0 -429
  320. package/src/routes/oauth.ts +0 -322
  321. package/src/routes/shared.ts +0 -247
  322. package/src/routes/ui.ts +0 -152
  323. package/src/server.ts +0 -195
  324. package/src/skills.ts +0 -271
  325. package/src/storage/file.ts +0 -123
  326. package/src/storage/memory.ts +0 -44
  327. package/src/timeout.ts +0 -84
  328. package/src/tool-safety.ts +0 -15
  329. package/src/types.ts +0 -523
  330. package/src/ui.ts +0 -744
  331. package/src/validate.ts +0 -387
  332. package/src/version.ts +0 -7
@@ -1,39 +0,0 @@
1
- const DEFAULT_DISCOVERY_CONCURRENCY = 4;
2
-
3
- export function resolveDiscoveryConcurrency(
4
- value: number | undefined,
5
- ): number {
6
- return value !== undefined && Number.isInteger(value) && value > 0
7
- ? value
8
- : DEFAULT_DISCOVERY_CONCURRENCY;
9
- }
10
-
11
- /** Run `fn` over `items` with at most `limit` operations in flight. */
12
- export async function mapSettledWithConcurrency<T, R>(
13
- items: readonly T[],
14
- limit: number,
15
- fn: (item: T, index: number) => Promise<R>,
16
- ): Promise<PromiseSettledResult<R>[]> {
17
- const settled = Array<PromiseSettledResult<R>>(items.length);
18
- const remaining = items.entries();
19
- const workers = Array.from(
20
- { length: Math.min(limit, items.length) },
21
- async () => {
22
- for (;;) {
23
- const next = remaining.next();
24
- if (next.done) return;
25
- const [index, item] = next.value;
26
- try {
27
- settled[index] = {
28
- status: "fulfilled",
29
- value: await fn(item, index),
30
- };
31
- } catch (reason) {
32
- settled[index] = { status: "rejected", reason };
33
- }
34
- }
35
- },
36
- );
37
- await Promise.all(workers);
38
- return settled;
39
- }
@@ -1,66 +0,0 @@
1
- import type { Connector, ConnectorContext } from "./types.js";
2
-
3
- /** Enough for local transport abort/close without letting cleanup own latency. */
4
- const CONNECTOR_SCOPE_CLOSE_BUDGET_MS = 100;
5
-
6
- /**
7
- * Bound on cleanup continued after the caller-facing window expires.
8
- *
9
- * `remoteMcp` spends at most one second asking the downstream to terminate its
10
- * session, leaving another second for the local close. Custom hooks still get a
11
- * finite background window: handing a never-settling promise to a Worker's
12
- * `waitUntil` would otherwise keep the invocation alive until the platform cap.
13
- */
14
- const CONNECTOR_SCOPE_DEFER_BUDGET_MS = 2_000;
15
-
16
- /** Runtime hook for work that may safely continue after a response is ready. */
17
- export type DeferredWork = (promise: Promise<unknown>) => void;
18
-
19
- /** Resolve when `work` settles or `budgetMs` expires; never reject. */
20
- function waitAtMost(work: Promise<void>, budgetMs: number): Promise<void> {
21
- return new Promise((resolve) => {
22
- const timer = setTimeout(resolve, budgetMs);
23
- work.then(() => {
24
- clearTimeout(timer);
25
- resolve();
26
- });
27
- });
28
- }
29
-
30
- /**
31
- * Tell a connector that a scope owned by the core has ended.
32
- *
33
- * Scope teardown is deliberately best-effort: a missing hook is a no-op and a
34
- * rejected hook is swallowed so cleanup can never replace the probe result that
35
- * caused it. The hook gets a small, fixed completion window so edge runtimes do
36
- * not cut off a real close as the response ends. When the runtime supplies
37
- * `defer`, the bounded tail is handed to it without extending the caller-facing
38
- * window. Callers own the at-most-once guarantee and must not use the scope
39
- * again after this returns.
40
- */
41
- export async function closeConnectorScope(
42
- connector: Connector,
43
- ctx: ConnectorContext,
44
- defer?: DeferredWork,
45
- ): Promise<void> {
46
- try {
47
- const closing = connector.closeScope?.(ctx);
48
- if (!closing) return;
49
- // Attach both handlers before either timer can win, so a late rejection is
50
- // consumed rather than becoming an unhandled rejection.
51
- const settled = closing.then(
52
- () => {},
53
- () => {},
54
- );
55
- if (defer) {
56
- try {
57
- defer(waitAtMost(settled, CONNECTOR_SCOPE_DEFER_BUDGET_MS));
58
- } catch {
59
- // A runtime hook is best-effort too; the caller cap still applies.
60
- }
61
- }
62
- await waitAtMost(settled, CONNECTOR_SCOPE_CLOSE_BUDGET_MS);
63
- } catch {
64
- // The scope is over whether or not the connector managed to clean it up.
65
- }
66
- }
@@ -1,159 +0,0 @@
1
- import { precompileValidator, validateToolInput } from "../validate.js";
2
- import type {
3
- Connector,
4
- ConnectorCallAdmissionPolicy,
5
- ConnectorCredentialConfig,
6
- ConnectorCredentialValues,
7
- ConnectorContext,
8
- ConnectorUsageGuide,
9
- CredentialTestResult,
10
- JsonSchema,
11
- ToolAnnotations,
12
- ToolDef,
13
- } from "../types.js";
14
-
15
- export interface ApiTool {
16
- name: string;
17
- description?: string;
18
- /** A plain JSON Schema object describing the tool input. */
19
- inputSchema?: JsonSchema;
20
- /** A plain JSON Schema object describing the tool's structured output. */
21
- outputSchema?: JsonSchema;
22
- /**
23
- * Standard MCP-style behavior hints. Only an explicit readOnlyHint: true
24
- * admits the tool to call_tool and execute_code.
25
- */
26
- annotations?: ToolAnnotations;
27
- handler: (args: any, ctx: ConnectorContext) => Promise<unknown> | unknown;
28
- }
29
-
30
- export interface ApiOptions {
31
- /** Human-readable display name; the connector id remains the address prefix. */
32
- title?: string;
33
- description?: string;
34
- /**
35
- * Max inline result size (bytes) for this connector's tools before
36
- * call_tool truncates and stashes the full text for get_result
37
- * paging. Overrides the deployment's `calls.maxResultBytes`; omit to inherit
38
- * it. Must be a whole number of bytes >= 1; anything else warns at startup
39
- * and is ignored.
40
- */
41
- maxResultBytes?: number;
42
- /** Optional per-runtime downstream call-admission policy. */
43
- callAdmission?: ConnectorCallAdmissionPolicy;
44
- /**
45
- * Optional agent-facing usage guide served by `skills` as
46
- * `connector:<id>`. A string is markdown; the structured form adds bounded
47
- * discovery metadata. See `Connector.usageGuide`.
48
- */
49
- usageGuide?: string | ConnectorUsageGuide;
50
- /** Optional operator-managed credential exposed through ctx.credential and /credentials. */
51
- credential?: ConnectorCredentialConfig;
52
- /** Optional validation behind /credentials' Test action. */
53
- testCredential?: (
54
- value: string,
55
- ctx: ConnectorContext,
56
- ) => Promise<CredentialTestResult>;
57
- /** Optional validation for named multi-field credentials. */
58
- testCredentials?: (
59
- values: ConnectorCredentialValues,
60
- ctx: ConnectorContext,
61
- ) => Promise<CredentialTestResult>;
62
- /**
63
- * Validate call arguments against each tool's `inputSchema` before invoking
64
- * the handler (default true). Mismatches fail with a non-retryable
65
- * `invalid_args` ConnectorCallError instead of reaching the handler. Set
66
- * false to restore the pre-validation pass-through for deployments relying
67
- * on loose coercion.
68
- */
69
- validateArgs?: boolean;
70
- /**
71
- * Fail-closed on a tool whose `inputSchema` the validator cannot evaluate
72
- * (default false). The default surfaces such a schema as a one-time warning
73
- * and then passes the raw arguments through, so a broken schema never breaks
74
- * an otherwise working tool. Set true to instead reject those calls with a
75
- * non-retryable `invalid_args` ConnectorCallError, so a schema that cannot be
76
- * enforced never silently admits unvalidated input. Only consulted when
77
- * `validateArgs` is not false.
78
- */
79
- strictValidation?: boolean;
80
- tools: ApiTool[];
81
- }
82
-
83
- /**
84
- * A connector defined entirely in code: static tool defs + fetch handlers.
85
- * Tool inputs are plain JSON Schema objects (bring your own zod-to-json-schema
86
- * conversion if you prefer zod). call_tool JSON-wraps the handler's return.
87
- *
88
- * Arguments are validated against `inputSchema` before the handler runs
89
- * (disable with `validateArgs: false`). Remote MCP inputs are also validated,
90
- * but in the shared invocation path against the request-local downstream
91
- * catalog. These API-only controls stay here because hand-written handlers may
92
- * deliberately accept loose coercion or choose fail-closed schema handling.
93
- */
94
- export function api(id: string, opts: ApiOptions): Connector {
95
- const defs: ToolDef[] = opts.tools.map((t) => ({
96
- name: t.name,
97
- ...(t.description !== undefined ? { description: t.description } : {}),
98
- ...(t.inputSchema !== undefined ? { inputSchema: t.inputSchema } : {}),
99
- ...(t.outputSchema !== undefined ? { outputSchema: t.outputSchema } : {}),
100
- ...(t.annotations !== undefined ? { annotations: t.annotations } : {}),
101
- }));
102
- const byName = new Map(opts.tools.map((t) => [t.name, t]));
103
- const validateArgs = opts.validateArgs ?? true;
104
- const strictValidation = opts.strictValidation ?? false;
105
- if (validateArgs) {
106
- // Compile each schema now so a validator-hostile inputSchema surfaces once
107
- // here rather than silently on its first call. Warning-only; never throws.
108
- for (const t of opts.tools) {
109
- if (t.inputSchema)
110
- precompileValidator(t.inputSchema, { address: `${id}.${t.name}` });
111
- }
112
- }
113
- return {
114
- id,
115
- ...(opts.title !== undefined ? { title: opts.title } : {}),
116
- kind: "api",
117
- ...(opts.description !== undefined
118
- ? { description: opts.description }
119
- : {}),
120
- ...(opts.maxResultBytes !== undefined
121
- ? { maxResultBytes: opts.maxResultBytes }
122
- : {}),
123
- ...(opts.callAdmission !== undefined
124
- ? { callAdmission: opts.callAdmission }
125
- : {}),
126
- ...(opts.usageGuide !== undefined ? { usageGuide: opts.usageGuide } : {}),
127
- ...(opts.credential !== undefined ? { credential: opts.credential } : {}),
128
- ...(opts.testCredential !== undefined
129
- ? { testCredential: opts.testCredential }
130
- : {}),
131
- ...(opts.testCredentials !== undefined
132
- ? { testCredentials: opts.testCredentials }
133
- : {}),
134
- staticTools: defs,
135
- async listTools() {
136
- return defs;
137
- },
138
- async callTool(name, args, ctx) {
139
- const tool = byName.get(name);
140
- if (!tool) {
141
- throw new Error(`Unknown tool "${name}" on connector "${id}"`);
142
- }
143
- const input = args ?? {};
144
- if (validateArgs && tool.inputSchema) {
145
- const invalid = validateToolInput(tool.inputSchema, input, {
146
- address: `${id}.${name}`,
147
- logger: ctx.logger,
148
- failClosed: strictValidation,
149
- });
150
- if (invalid) throw invalid;
151
- }
152
- // `await` (not a bare promise return) so a handler that throws before
153
- // its first await never sits handler-less for the thenable-adoption
154
- // microtask — workerd and vitest both report that gap as an unhandled
155
- // rejection even though the caller catches the failure.
156
- return await tool.handler(input, ctx);
157
- },
158
- };
159
- }