@zackbart/connecta 0.7.9 → 0.8.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 (180) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/README.md +67 -144
  3. package/dist/auth/bearer.d.ts +1 -1
  4. package/dist/auth/bearer.js +4 -4
  5. package/dist/auth/bearer.js.map +1 -1
  6. package/dist/auth/clerk.d.ts +1 -1
  7. package/dist/auth/clerk.js +1 -1
  8. package/dist/call-admission.d.ts.map +1 -1
  9. package/dist/call-admission.js +9 -3
  10. package/dist/call-admission.js.map +1 -1
  11. package/dist/catalog-fingerprint.d.ts +20 -0
  12. package/dist/catalog-fingerprint.d.ts.map +1 -0
  13. package/dist/catalog-fingerprint.js +34 -0
  14. package/dist/catalog-fingerprint.js.map +1 -0
  15. package/dist/catalog-limits.d.ts +10 -0
  16. package/dist/catalog-limits.d.ts.map +1 -0
  17. package/dist/catalog-limits.js +10 -0
  18. package/dist/catalog-limits.js.map +1 -0
  19. package/dist/catalog-service.d.ts +138 -0
  20. package/dist/catalog-service.d.ts.map +1 -0
  21. package/dist/catalog-service.js +407 -0
  22. package/dist/catalog-service.js.map +1 -0
  23. package/dist/catalog.js +2 -2
  24. package/dist/catalog.js.map +1 -1
  25. package/dist/concurrency.d.ts +4 -0
  26. package/dist/concurrency.d.ts.map +1 -0
  27. package/dist/concurrency.js +31 -0
  28. package/dist/concurrency.js.map +1 -0
  29. package/dist/connectors/api.d.ts.map +1 -1
  30. package/dist/connectors/api.js +22 -12
  31. package/dist/connectors/api.js.map +1 -1
  32. package/dist/connectors/remote-mcp.d.ts.map +1 -1
  33. package/dist/connectors/remote-mcp.js +44 -19
  34. package/dist/connectors/remote-mcp.js.map +1 -1
  35. package/dist/credential-health.d.ts +0 -22
  36. package/dist/credential-health.d.ts.map +1 -1
  37. package/dist/credential-health.js +14 -10
  38. package/dist/credential-health.js.map +1 -1
  39. package/dist/credentials.d.ts +3 -2
  40. package/dist/credentials.d.ts.map +1 -1
  41. package/dist/errors.d.ts +1 -1
  42. package/dist/errors.d.ts.map +1 -1
  43. package/dist/errors.js.map +1 -1
  44. package/dist/execute.d.ts +9 -8
  45. package/dist/execute.d.ts.map +1 -1
  46. package/dist/execute.js +144 -321
  47. package/dist/execute.js.map +1 -1
  48. package/dist/executor-result.d.ts +0 -3
  49. package/dist/executor-result.d.ts.map +1 -1
  50. package/dist/executor-result.js +2 -2
  51. package/dist/executor-result.js.map +1 -1
  52. package/dist/executors/quickjs-child.js +3 -3
  53. package/dist/executors/quickjs-child.js.map +1 -1
  54. package/dist/executors/quickjs-protocol.d.ts +4 -1
  55. package/dist/executors/quickjs-protocol.d.ts.map +1 -1
  56. package/dist/executors/quickjs-runtime.d.ts.map +1 -1
  57. package/dist/executors/quickjs-runtime.js +7 -2
  58. package/dist/executors/quickjs-runtime.js.map +1 -1
  59. package/dist/executors/quickjs.d.ts.map +1 -1
  60. package/dist/executors/quickjs.js +4 -1
  61. package/dist/executors/quickjs.js.map +1 -1
  62. package/dist/favicon.js +2 -2
  63. package/dist/favicon.js.map +1 -1
  64. package/dist/index.d.ts +5 -0
  65. package/dist/index.d.ts.map +1 -1
  66. package/dist/index.js +44 -17
  67. package/dist/index.js.map +1 -1
  68. package/dist/invocation.d.ts +96 -0
  69. package/dist/invocation.d.ts.map +1 -0
  70. package/dist/invocation.js +369 -0
  71. package/dist/invocation.js.map +1 -0
  72. package/dist/meta-tools.d.ts +8 -86
  73. package/dist/meta-tools.d.ts.map +1 -1
  74. package/dist/meta-tools.js +145 -583
  75. package/dist/meta-tools.js.map +1 -1
  76. package/dist/operator-ui/generated.d.ts +3 -0
  77. package/dist/operator-ui/generated.d.ts.map +1 -0
  78. package/dist/operator-ui/generated.js +5 -0
  79. package/dist/operator-ui/generated.js.map +1 -0
  80. package/dist/operator-ui/model.d.ts +94 -0
  81. package/dist/operator-ui/model.d.ts.map +1 -0
  82. package/dist/operator-ui/model.js +28 -0
  83. package/dist/operator-ui/model.js.map +1 -0
  84. package/dist/registry.d.ts +22 -6
  85. package/dist/registry.d.ts.map +1 -1
  86. package/dist/registry.js +328 -35
  87. package/dist/registry.js.map +1 -1
  88. package/dist/routes/activity.d.ts +3 -0
  89. package/dist/routes/activity.d.ts.map +1 -0
  90. package/dist/routes/activity.js +173 -0
  91. package/dist/routes/activity.js.map +1 -0
  92. package/dist/routes/credentials.d.ts +3 -0
  93. package/dist/routes/credentials.d.ts.map +1 -0
  94. package/dist/routes/credentials.js +181 -0
  95. package/dist/routes/credentials.js.map +1 -0
  96. package/dist/routes/mcp.d.ts +8 -0
  97. package/dist/routes/mcp.d.ts.map +1 -0
  98. package/dist/routes/mcp.js +383 -0
  99. package/dist/routes/mcp.js.map +1 -0
  100. package/dist/routes/oauth.d.ts +4 -0
  101. package/dist/routes/oauth.d.ts.map +1 -0
  102. package/dist/routes/oauth.js +268 -0
  103. package/dist/routes/oauth.js.map +1 -0
  104. package/dist/routes/shared.d.ts +97 -0
  105. package/dist/routes/shared.d.ts.map +1 -0
  106. package/dist/routes/shared.js +199 -0
  107. package/dist/routes/shared.js.map +1 -0
  108. package/dist/routes/ui.d.ts +3 -0
  109. package/dist/routes/ui.d.ts.map +1 -0
  110. package/dist/routes/ui.js +122 -0
  111. package/dist/routes/ui.js.map +1 -0
  112. package/dist/server.d.ts +9 -40
  113. package/dist/server.d.ts.map +1 -1
  114. package/dist/server.js +63 -1293
  115. package/dist/server.js.map +1 -1
  116. package/dist/skills.d.ts +0 -15
  117. package/dist/skills.d.ts.map +1 -1
  118. package/dist/skills.js +6 -5
  119. package/dist/skills.js.map +1 -1
  120. package/dist/storage/file.d.ts.map +1 -1
  121. package/dist/storage/file.js +3 -1
  122. package/dist/storage/file.js.map +1 -1
  123. package/dist/storage/memory.d.ts.map +1 -1
  124. package/dist/storage/memory.js +3 -1
  125. package/dist/storage/memory.js.map +1 -1
  126. package/dist/toolkits.d.ts +0 -22
  127. package/dist/toolkits.d.ts.map +1 -1
  128. package/dist/toolkits.js +2 -2
  129. package/dist/toolkits.js.map +1 -1
  130. package/dist/types.d.ts +9 -2
  131. package/dist/types.d.ts.map +1 -1
  132. package/dist/ui.d.ts +3 -93
  133. package/dist/ui.d.ts.map +1 -1
  134. package/dist/ui.js +26 -1393
  135. package/dist/ui.js.map +1 -1
  136. package/dist/version.d.ts +1 -1
  137. package/dist/version.js +1 -1
  138. package/package.json +15 -8
  139. package/src/auth/bearer.ts +4 -4
  140. package/src/auth/clerk.ts +1 -1
  141. package/src/call-admission.ts +8 -5
  142. package/src/catalog-fingerprint.ts +52 -0
  143. package/src/catalog-limits.ts +11 -0
  144. package/src/catalog-service.ts +601 -0
  145. package/src/catalog.ts +2 -2
  146. package/src/concurrency.ts +39 -0
  147. package/src/connectors/api.ts +22 -12
  148. package/src/connectors/remote-mcp.ts +52 -22
  149. package/src/credential-health.ts +13 -10
  150. package/src/credentials.ts +2 -2
  151. package/src/errors.ts +1 -1
  152. package/src/execute.ts +194 -409
  153. package/src/executor-result.ts +2 -2
  154. package/src/executors/quickjs-child.ts +8 -4
  155. package/src/executors/quickjs-protocol.ts +1 -1
  156. package/src/executors/quickjs-runtime.ts +5 -1
  157. package/src/executors/quickjs.ts +11 -8
  158. package/src/favicon.ts +2 -2
  159. package/src/index.ts +49 -17
  160. package/src/invocation.ts +527 -0
  161. package/src/meta-tools.ts +366 -906
  162. package/src/operator-ui/browser.css +413 -0
  163. package/src/operator-ui/browser.ts +1121 -0
  164. package/src/operator-ui/generated.ts +4 -0
  165. package/src/operator-ui/model.ts +127 -0
  166. package/src/registry.ts +434 -44
  167. package/src/routes/activity.ts +220 -0
  168. package/src/routes/credentials.ts +266 -0
  169. package/src/routes/mcp.ts +485 -0
  170. package/src/routes/oauth.ts +328 -0
  171. package/src/routes/shared.ts +330 -0
  172. package/src/routes/ui.ts +153 -0
  173. package/src/server.ts +66 -1703
  174. package/src/skills.ts +6 -5
  175. package/src/storage/file.ts +3 -1
  176. package/src/storage/memory.ts +3 -1
  177. package/src/toolkits.ts +2 -2
  178. package/src/types.ts +9 -2
  179. package/src/ui.ts +52 -1493
  180. package/src/version.ts +1 -1
@@ -9,6 +9,7 @@ import { ListToolsResultSchema } from "@modelcontextprotocol/sdk/types.js";
9
9
  import { CfWorkerJsonSchemaValidator } from "@modelcontextprotocol/sdk/validation/cfworker";
10
10
  import { z } from "zod";
11
11
  import { KvOAuthProvider } from "../auth/downstream-oauth.js";
12
+ import { MAX_CATALOG_TOOLS } from "../catalog-limits.js";
12
13
  import { ConnectorCallError } from "../errors.js";
13
14
  import { CONNECTA_VERSION } from "../version.js";
14
15
  import type {
@@ -109,18 +110,16 @@ const TERMINATE_SESSION_BUDGET_MS = 1_000;
109
110
  * cap the bytes a caller can be made to hold, not the number of round trips it
110
111
  * took to get them.
111
112
  */
112
- const MAX_TOOLS = 100_000;
113
-
114
113
  /**
115
114
  * Absolute backstop on `tools/list` pages in one refresh — a runaway guard, not
116
115
  * the primary defense.
117
116
  *
118
117
  * The walk terminates on its own well before this: a cursor handed back twice
119
118
  * is a definite loop, two consecutive pages that add no new tools are a server
120
- * going nowhere, and MAX_TOOLS caps what any of it can accumulate. This exists
121
- * only so the loop is finite even if a downstream somehow satisfies all three
122
- * forever on a path with no discovery deadline. Set high enough that no honest
123
- * server reaches it.
119
+ * going nowhere, and MAX_CATALOG_TOOLS caps what any of it can accumulate.
120
+ * This exists only so the loop is finite even if a downstream somehow
121
+ * satisfies all three forever on a path with no discovery deadline. Set high
122
+ * enough that no honest server reaches it.
124
123
  */
125
124
  const MAX_TOOL_PAGES = 10_000;
126
125
 
@@ -298,7 +297,9 @@ function redirectedInit(init: RequestInit, status: number): RequestInit {
298
297
  if (!becomesGet) return init;
299
298
  const headers = new Headers(init.headers);
300
299
  for (const name of BODY_HEADERS) headers.delete(name);
301
- return { ...init, method: "GET", body: undefined, headers };
300
+ const redirected = { ...init, method: "GET", headers };
301
+ delete redirected.body;
302
+ return redirected;
302
303
  }
303
304
 
304
305
  /**
@@ -546,10 +547,14 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
546
547
  const url = new URL(opts.url);
547
548
  const guardedFetch = redirectSafeFetch(id, opts.redirects);
548
549
  if (opts.auth?.type === "oauth") {
550
+ // The SDK class declares `sessionId` as an own `string | undefined`
551
+ // property while its Transport interface declares it optional. They are
552
+ // runtime-compatible; exact optional types only exposes that declaration
553
+ // mismatch at this boundary.
549
554
  return new StreamableHTTPClientTransport(url, {
550
555
  authProvider: provider ?? newProvider(ctx),
551
556
  fetch: guardedFetch,
552
- });
557
+ }) as unknown as Transport;
553
558
  }
554
559
  const headers =
555
560
  opts.auth?.type === "headers" ? opts.auth.headers : undefined;
@@ -559,7 +564,7 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
559
564
  ...(headers ? { requestInit: { headers } } : {}),
560
565
  fetch: guardedFetch,
561
566
  },
562
- );
567
+ ) as unknown as Transport;
563
568
  };
564
569
 
565
570
  const reset = (state: ConnectionState) => {
@@ -742,12 +747,18 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
742
747
 
743
748
  const connector: Connector = {
744
749
  id,
745
- title: opts.title,
750
+ ...(opts.title !== undefined ? { title: opts.title } : {}),
746
751
  kind: "mcp",
747
- description: opts.description,
748
- maxResultBytes: opts.maxResultBytes,
749
- callAdmission: opts.callAdmission,
750
- usageGuide: opts.usageGuide,
752
+ ...(opts.description !== undefined
753
+ ? { description: opts.description }
754
+ : {}),
755
+ ...(opts.maxResultBytes !== undefined
756
+ ? { maxResultBytes: opts.maxResultBytes }
757
+ : {}),
758
+ ...(opts.callAdmission !== undefined
759
+ ? { callAdmission: opts.callAdmission }
760
+ : {}),
761
+ ...(opts.usageGuide !== undefined ? { usageGuide: opts.usageGuide } : {}),
751
762
 
752
763
  // `tools/list` is cursor-paginated: the server chooses the page size and
753
764
  // signals "there is more" with a `nextCursor`, which the SDK's
@@ -830,9 +841,9 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
830
841
  }
831
842
  // Checked here rather than on arrival: this bounds what a *walk* may
832
843
  // accumulate; a one-page server was always free to send its page.
833
- if (listed.length > MAX_TOOLS) {
844
+ if (listed.length > MAX_CATALOG_TOOLS) {
834
845
  throw new Error(
835
- `Connector "${id}" advertised further tools/list pages past ${listed.length} tools, over the ${MAX_TOOLS}-tool ceiling one catalog refresh will collect.`,
846
+ `Connector "${id}" advertised further tools/list pages past ${listed.length} tools, over the ${MAX_CATALOG_TOOLS}-tool ceiling one catalog refresh will collect.`,
836
847
  );
837
848
  }
838
849
  // Opaque by contract: handed straight back, never parsed, rewritten,
@@ -863,10 +874,28 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
863
874
  primeToolMetadata(client, listed);
864
875
  return listed.map((t) => ({
865
876
  name: t.name,
866
- description: t.description,
867
- inputSchema: t.inputSchema as ToolDef["inputSchema"],
868
- outputSchema: t.outputSchema as ToolDef["outputSchema"],
869
- annotations: t.annotations as ToolDef["annotations"],
877
+ ...(t.description !== undefined ? { description: t.description } : {}),
878
+ ...(t.inputSchema !== undefined
879
+ ? {
880
+ inputSchema: t.inputSchema as NonNullable<
881
+ ToolDef["inputSchema"]
882
+ >,
883
+ }
884
+ : {}),
885
+ ...(t.outputSchema !== undefined
886
+ ? {
887
+ outputSchema: t.outputSchema as NonNullable<
888
+ ToolDef["outputSchema"]
889
+ >,
890
+ }
891
+ : {}),
892
+ ...(t.annotations !== undefined
893
+ ? {
894
+ annotations: t.annotations as NonNullable<
895
+ ToolDef["annotations"]
896
+ >,
897
+ }
898
+ : {}),
870
899
  }));
871
900
  },
872
901
 
@@ -942,7 +971,7 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
942
971
  const url = await getProvider(ctx, state).pendingAuthorizationUrl();
943
972
  return {
944
973
  state: "auth_required",
945
- authorizationUrl: url,
974
+ ...(url !== undefined ? { authorizationUrl: url } : {}),
946
975
  message: "Authorization required — open the URL to connect.",
947
976
  };
948
977
  }
@@ -1013,9 +1042,10 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
1013
1042
  };
1014
1043
  } catch (err) {
1015
1044
  if (state.authRequired) {
1045
+ const authorizationUrl = await p.pendingAuthorizationUrl();
1016
1046
  return {
1017
1047
  state: "auth_required",
1018
- authorizationUrl: await p.pendingAuthorizationUrl(),
1048
+ ...(authorizationUrl !== undefined ? { authorizationUrl } : {}),
1019
1049
  message: "Authorization required — open the URL to connect.",
1020
1050
  };
1021
1051
  }
@@ -117,8 +117,8 @@ export interface CredentialHealthConfig {
117
117
  onRequest?: boolean;
118
118
  }
119
119
 
120
- export const DEFAULT_CREDENTIAL_CHECK_INTERVAL_SECONDS = 900;
121
- export const DEFAULT_CREDENTIAL_CHECK_CONCURRENCY = 4;
120
+ const DEFAULT_CREDENTIAL_CHECK_INTERVAL_SECONDS = 900;
121
+ const DEFAULT_CREDENTIAL_CHECK_CONCURRENCY = 4;
122
122
 
123
123
  /**
124
124
  * How long a read of one connector's record is served from memory before going
@@ -362,7 +362,7 @@ export interface CredentialCheckOptions {
362
362
  * their back. A connector whose only hook cannot test its declared shape is
363
363
  * checkable only if it also implements `status()`.
364
364
  */
365
- export function isCheckableConnector(connector: Connector): boolean {
365
+ function isCheckableConnector(connector: Connector): boolean {
366
366
  const hasCredentialStore = Boolean(
367
367
  connector.credential || connector.hasStoredCredential,
368
368
  );
@@ -408,8 +408,9 @@ function testHookFor(
408
408
  }
409
409
  // A single-value shape with nothing under the reserved field is still nothing
410
410
  // to test, so the stored value gets the last word even when the rule fits.
411
- if (mode === "single" && typeof storedValues.value === "string") {
412
- return (ctx) => connector.testCredential!(storedValues.value, ctx);
411
+ const storedValue = storedValues.value;
412
+ if (mode === "single" && typeof storedValue === "string") {
413
+ return (ctx) => connector.testCredential!(storedValue, ctx);
413
414
  }
414
415
  return undefined;
415
416
  }
@@ -420,14 +421,16 @@ async function mapWithConcurrency<T, R>(
420
421
  limit: number,
421
422
  fn: (item: T) => Promise<R>,
422
423
  ): Promise<R[]> {
423
- const out = new Array<R>(items.length);
424
- let next = 0;
424
+ const out = Array<R>(items.length);
425
+ const remaining = items.entries();
425
426
  const workers = Array.from(
426
427
  { length: Math.min(limit, items.length) },
427
428
  async () => {
428
- while (next < items.length) {
429
- const index = next++;
430
- out[index] = await fn(items[index]);
429
+ for (;;) {
430
+ const next = remaining.next();
431
+ if (next.done) return;
432
+ const [index, item] = next.value;
433
+ out[index] = await fn(item);
431
434
  }
432
435
  },
433
436
  );
@@ -24,7 +24,7 @@ interface CredentialPlaintext {
24
24
  updatedBy: string;
25
25
  }
26
26
 
27
- export interface CredentialFieldMetadata {
27
+ interface CredentialFieldMetadata {
28
28
  configured: true;
29
29
  /** Only emitted when the value is long enough that four chars don't leak much. */
30
30
  lastFour?: string;
@@ -41,7 +41,7 @@ export interface CredentialMetadata {
41
41
  }
42
42
 
43
43
  /** Which hook a testable credential is checked with. */
44
- export type CredentialTestMode = "single" | "multiple";
44
+ type CredentialTestMode = "single" | "multiple";
45
45
 
46
46
  /** Operator-safe explanation shared by every surface that detects shape drift. */
47
47
  export const STORED_CREDENTIAL_SHAPE_MISMATCH_ERROR =
package/src/errors.ts CHANGED
@@ -49,7 +49,7 @@ export class ConnectorCallError extends Error {
49
49
  * the assignment would not keep it off the instance. Keeping the window out
50
50
  * of the wire format is `classifyCallError`'s job, not this constructor's.
51
51
  */
52
- readonly retryAfterMs?: number;
52
+ readonly retryAfterMs: number | undefined;
53
53
 
54
54
  constructor(
55
55
  code: ConnectorCallErrorCode,