@zackbart/connecta 0.3.0 → 0.4.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 (69) hide show
  1. package/CHANGELOG.md +143 -0
  2. package/README.md +34 -14
  3. package/SECURITY.md +1 -1
  4. package/dist/catalog.d.ts.map +1 -1
  5. package/dist/catalog.js +62 -0
  6. package/dist/catalog.js.map +1 -1
  7. package/dist/connectors/api.d.ts +10 -0
  8. package/dist/connectors/api.d.ts.map +1 -1
  9. package/dist/connectors/api.js +16 -39
  10. package/dist/connectors/api.js.map +1 -1
  11. package/dist/connectors/remote-mcp.d.ts +14 -1
  12. package/dist/connectors/remote-mcp.d.ts.map +1 -1
  13. package/dist/connectors/remote-mcp.js +29 -0
  14. package/dist/connectors/remote-mcp.js.map +1 -1
  15. package/dist/credentials.d.ts +2 -1
  16. package/dist/credentials.d.ts.map +1 -1
  17. package/dist/credentials.js +4 -2
  18. package/dist/credentials.js.map +1 -1
  19. package/dist/errors.d.ts +20 -0
  20. package/dist/errors.d.ts.map +1 -1
  21. package/dist/errors.js +39 -1
  22. package/dist/errors.js.map +1 -1
  23. package/dist/executors/quickjs.d.ts.map +1 -1
  24. package/dist/executors/quickjs.js +32 -4
  25. package/dist/executors/quickjs.js.map +1 -1
  26. package/dist/index.d.ts +34 -0
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +45 -1
  29. package/dist/index.js.map +1 -1
  30. package/dist/json-schema.d.ts +3 -0
  31. package/dist/json-schema.d.ts.map +1 -0
  32. package/dist/json-schema.js +6 -0
  33. package/dist/json-schema.js.map +1 -0
  34. package/dist/meta-tools.d.ts +34 -2
  35. package/dist/meta-tools.d.ts.map +1 -1
  36. package/dist/meta-tools.js +104 -15
  37. package/dist/meta-tools.js.map +1 -1
  38. package/dist/server.d.ts +4 -0
  39. package/dist/server.d.ts.map +1 -1
  40. package/dist/server.js +34 -6
  41. package/dist/server.js.map +1 -1
  42. package/dist/storage/file.d.ts.map +1 -1
  43. package/dist/storage/file.js +19 -3
  44. package/dist/storage/file.js.map +1 -1
  45. package/dist/ui.d.ts +1 -1
  46. package/dist/ui.d.ts.map +1 -1
  47. package/dist/ui.js +13 -9
  48. package/dist/ui.js.map +1 -1
  49. package/dist/validate.d.ts +71 -0
  50. package/dist/validate.d.ts.map +1 -0
  51. package/dist/validate.js +96 -0
  52. package/dist/validate.js.map +1 -0
  53. package/dist/version.d.ts +1 -1
  54. package/dist/version.js +1 -1
  55. package/package.json +5 -1
  56. package/src/catalog.ts +61 -0
  57. package/src/connectors/api.ts +25 -50
  58. package/src/connectors/remote-mcp.ts +52 -0
  59. package/src/credentials.ts +6 -3
  60. package/src/errors.ts +45 -2
  61. package/src/executors/quickjs.ts +32 -4
  62. package/src/index.ts +94 -1
  63. package/src/json-schema.ts +11 -0
  64. package/src/meta-tools.ts +156 -28
  65. package/src/server.ts +39 -6
  66. package/src/storage/file.ts +18 -2
  67. package/src/ui.ts +13 -8
  68. package/src/validate.ts +154 -0
  69. package/src/version.ts +1 -1
package/dist/ui.js CHANGED
@@ -9,15 +9,16 @@ export const CONNECTA_FAVICON_SVG = `<svg xmlns="http://www.w3.org/2000/svg" vie
9
9
  export function resolveBranding(branding) {
10
10
  const productName = branding?.productName?.trim() || "Connecta";
11
11
  const ownerName = branding?.ownerName?.trim();
12
+ // Operator branding URLs become masthead/callback hrefs, so a non-http(s)
13
+ // scheme (javascript:, data:) is dropped the same as an unset URL — the
14
+ // callers already render a <span> instead of an <a> when it is absent.
15
+ const productUrl = branding?.productUrl?.trim();
16
+ const ownerUrl = branding?.ownerUrl?.trim();
12
17
  return {
13
18
  productName,
14
- ...(branding?.productUrl?.trim()
15
- ? { productUrl: branding.productUrl.trim() }
16
- : {}),
19
+ ...(productUrl && isSafeHttpUrl(productUrl) ? { productUrl } : {}),
17
20
  ...(ownerName ? { ownerName } : {}),
18
- ...(branding?.ownerUrl?.trim()
19
- ? { ownerUrl: branding.ownerUrl.trim() }
20
- : {}),
21
+ ...(ownerUrl && isSafeHttpUrl(ownerUrl) ? { ownerUrl } : {}),
21
22
  description: branding?.description?.trim() ||
22
23
  `Manage the services this ${productName} instance makes available to agents.`,
23
24
  pageTitle: branding?.pageTitle?.trim() ||
@@ -205,10 +206,13 @@ function jsonForInlineScript(value) {
205
206
  * normal sign-in flow and a short-lived session token; bearer-only deployments
206
207
  * retain the manual-token fallback.
207
208
  */
208
- export function renderUiHtml(uiAuth, mcpUrl = "/mcp", branding) {
209
+ export function renderUiHtml(uiAuth, mcpUrl = "/mcp", branding, nonce) {
209
210
  const auth = uiAuth ?? { kind: "bearer" };
210
211
  const brand = resolveBranding(branding);
211
212
  const title = brand.pageTitle;
213
+ // When the /ui response ships a nonce-based CSP, every <script> it emits must
214
+ // carry that nonce to run; without a nonce the markup is unchanged.
215
+ const nonceAttr = nonce ? ` nonce="${nonce}"` : "";
212
216
  // Top-left corner. With an owner set it reads "<owner> <product>"; without
213
217
  // one the product label stands alone. Either half links out when the
214
218
  // matching URL is configured.
@@ -225,7 +229,7 @@ export function renderUiHtml(uiAuth, mcpUrl = "/mcp", branding) {
225
229
  : `<span class="product">${escapeHtmlAttr(brand.productName)}</span>`
226
230
  : "";
227
231
  const clerkScript = uiAuth?.kind === "clerk"
228
- ? `<script defer crossorigin="anonymous" data-clerk-publishable-key="${escapeHtmlAttr(uiAuth.publishableKey)}" src="${escapeHtmlAttr(uiAuth.frontendApiUrl)}/npm/@clerk/clerk-js@6/dist/clerk.browser.js"></script>`
232
+ ? `<script${nonceAttr} defer crossorigin="anonymous" data-clerk-publishable-key="${escapeHtmlAttr(uiAuth.publishableKey)}" src="${escapeHtmlAttr(uiAuth.frontendApiUrl)}/npm/@clerk/clerk-js@6/dist/clerk.browser.js"></script>`
229
233
  : "";
230
234
  return `<!doctype html>
231
235
  <html lang="en">
@@ -584,7 +588,7 @@ ${clerkScript}
584
588
  </section>
585
589
  </main>
586
590
 
587
- <script>
591
+ <script${nonceAttr}>
588
592
  const AUTH = ${jsonForInlineScript(auth)};
589
593
  const MCP_URL = ${jsonForInlineScript(mcpUrl)};
590
594
  const filterUiConnectors = ${filterUiConnectors.toString()};
package/dist/ui.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ import { ConnectorCallError } from "./errors.js";
2
+ import type { JsonSchema, Logger } from "./types.js";
3
+ export interface ValidateToolInputOptions {
4
+ /**
5
+ * Tool address used in the error and warning text, conventionally
6
+ * `"connectorId.toolName"`.
7
+ */
8
+ address: string;
9
+ /**
10
+ * Destination for the one-time warning emitted when a schema turns out to be
11
+ * unusable. Default console.
12
+ */
13
+ logger?: Logger;
14
+ /**
15
+ * Fail-closed on a schema the validator cannot evaluate (default false =
16
+ * today's fail-open behavior). When true, a schema that cannot be compiled —
17
+ * or that only fails on first use, e.g. an unresolvable `$ref` — yields a
18
+ * non-retryable `invalid_args` error instead of passing the raw arguments
19
+ * through, so unvalidated input is never silently admitted. The happy path
20
+ * (a schema that compiles and validates) is unaffected.
21
+ */
22
+ failClosed?: boolean;
23
+ }
24
+ export interface PrecompileValidatorOptions {
25
+ /**
26
+ * Tool address used in the warning text, conventionally
27
+ * `"connectorId.toolName"`.
28
+ */
29
+ address: string;
30
+ /**
31
+ * Destination for the warning emitted when the schema cannot be compiled.
32
+ * Default console.
33
+ */
34
+ logger?: Logger;
35
+ }
36
+ /**
37
+ * Validate call arguments against a tool's JSON Schema.
38
+ *
39
+ * Returns a non-retryable `invalid_args` ConnectorCallError describing the
40
+ * mismatch, or null when the arguments are acceptable. It deliberately returns
41
+ * rather than throws: the caller decides what to do with the failure, which is
42
+ * what lets a connector own its error prose, or strip connector-wide
43
+ * convention arguments (a `confirm` flag on writes, say) that individual tool
44
+ * schemas do not declare before deciding the call is really invalid.
45
+ *
46
+ * A schema the validator cannot compile (or that only fails on first use, e.g.
47
+ * an unresolvable `$ref`) is warned about once and then passed through — a
48
+ * broken schema should not break an otherwise working tool. Pass
49
+ * `failClosed: true` to instead reject such calls with `invalid_args`, for
50
+ * callers that would rather refuse a call than forward unvalidated arguments.
51
+ *
52
+ * The compiled validator is cached by **schema object identity**, so pass a
53
+ * stable object: hold the parsed manifest and hand the same schema back on
54
+ * every call. A schema rebuilt per call is a cache miss every time — it still
55
+ * validates correctly, but recompiles the validator on each call, silently and
56
+ * with nothing to show for it but latency.
57
+ *
58
+ * `api()` uses this internally; it is exported for connectors that implement
59
+ * the `Connector` interface directly.
60
+ */
61
+ export declare function validateToolInput(schema: JsonSchema, args: unknown, opts: ValidateToolInputOptions): ConnectorCallError | null;
62
+ /**
63
+ * Eagerly compile and cache a tool's inputSchema so a schema the validator
64
+ * cannot use surfaces once at connector construction rather than silently on
65
+ * the first call. Reuses the same module-level cache `validateToolInput` reads,
66
+ * so the runtime path hits the cache. Warning-only: it never throws and never
67
+ * changes call behavior. A schema that only fails on first `validate()` (e.g.
68
+ * an unresolvable `$ref`) still slips through here and is caught at call time.
69
+ */
70
+ export declare function precompileValidator(schema: JsonSchema, opts: PrecompileValidatorOptions): void;
71
+ //# sourceMappingURL=validate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAErD,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA6BD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,wBAAwB,GAC7B,kBAAkB,GAAG,IAAI,CAqC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,IAAI,EAAE,0BAA0B,GAC/B,IAAI,CAQN"}
@@ -0,0 +1,96 @@
1
+ import { Validator } from "@cfworker/json-schema";
2
+ import { ConnectorCallError } from "./errors.js";
3
+ // Lazy validator cache keyed by the schema object itself; null marks a schema
4
+ // the validator rejected (warned once, then passed through rather than
5
+ // breaking a working tool). A WeakMap so schemas belonging to a discarded
6
+ // connector are collectable, the same pattern compactSchema uses.
7
+ const validators = new WeakMap();
8
+ function unevaluableSchema(address) {
9
+ return new ConnectorCallError("invalid_args", `Cannot validate arguments for "${address}": its inputSchema could not be evaluated`);
10
+ }
11
+ function disableValidation(schema, address, logger, err) {
12
+ validators.set(schema, null);
13
+ logger.warn(`[connecta] tool "${address}" has an inputSchema the validator cannot use (${err instanceof Error ? err.message : String(err)}) — arguments are not validated`);
14
+ }
15
+ /**
16
+ * Validate call arguments against a tool's JSON Schema.
17
+ *
18
+ * Returns a non-retryable `invalid_args` ConnectorCallError describing the
19
+ * mismatch, or null when the arguments are acceptable. It deliberately returns
20
+ * rather than throws: the caller decides what to do with the failure, which is
21
+ * what lets a connector own its error prose, or strip connector-wide
22
+ * convention arguments (a `confirm` flag on writes, say) that individual tool
23
+ * schemas do not declare before deciding the call is really invalid.
24
+ *
25
+ * A schema the validator cannot compile (or that only fails on first use, e.g.
26
+ * an unresolvable `$ref`) is warned about once and then passed through — a
27
+ * broken schema should not break an otherwise working tool. Pass
28
+ * `failClosed: true` to instead reject such calls with `invalid_args`, for
29
+ * callers that would rather refuse a call than forward unvalidated arguments.
30
+ *
31
+ * The compiled validator is cached by **schema object identity**, so pass a
32
+ * stable object: hold the parsed manifest and hand the same schema back on
33
+ * every call. A schema rebuilt per call is a cache miss every time — it still
34
+ * validates correctly, but recompiles the validator on each call, silently and
35
+ * with nothing to show for it but latency.
36
+ *
37
+ * `api()` uses this internally; it is exported for connectors that implement
38
+ * the `Connector` interface directly.
39
+ */
40
+ export function validateToolInput(schema, args, opts) {
41
+ const logger = opts.logger ?? console;
42
+ let validator = validators.get(schema);
43
+ if (validator === undefined) {
44
+ try {
45
+ validator = new Validator(schema, "2020-12", false);
46
+ validators.set(schema, validator);
47
+ }
48
+ catch (err) {
49
+ disableValidation(schema, opts.address, logger, err);
50
+ validator = null;
51
+ }
52
+ }
53
+ // A schema the validator could not compile (or that a prior call disabled):
54
+ // pass through by default, refuse when the caller opted into fail-closed.
55
+ if (validator === null) {
56
+ return opts.failClosed ? unevaluableSchema(opts.address) : null;
57
+ }
58
+ let result;
59
+ try {
60
+ result = validator.validate(args);
61
+ }
62
+ catch (err) {
63
+ // e.g. an unresolvable $ref — surfaces on first validate, not compile.
64
+ disableValidation(schema, opts.address, logger, err);
65
+ return opts.failClosed ? unevaluableSchema(opts.address) : null;
66
+ }
67
+ if (result && !result.valid) {
68
+ const units = result.errors.filter((u) => u.instanceLocation !== "#");
69
+ const detail = (units.length > 0 ? units : result.errors)
70
+ .slice(0, 3)
71
+ .map((u) => `${u.instanceLocation}: ${u.error}`)
72
+ .join("; ");
73
+ return new ConnectorCallError("invalid_args", `Invalid arguments for "${opts.address}": ${detail || "input does not match the tool's inputSchema"}`);
74
+ }
75
+ return null;
76
+ }
77
+ /**
78
+ * Eagerly compile and cache a tool's inputSchema so a schema the validator
79
+ * cannot use surfaces once at connector construction rather than silently on
80
+ * the first call. Reuses the same module-level cache `validateToolInput` reads,
81
+ * so the runtime path hits the cache. Warning-only: it never throws and never
82
+ * changes call behavior. A schema that only fails on first `validate()` (e.g.
83
+ * an unresolvable `$ref`) still slips through here and is caught at call time.
84
+ */
85
+ export function precompileValidator(schema, opts) {
86
+ if (validators.has(schema))
87
+ return;
88
+ const logger = opts.logger ?? console;
89
+ try {
90
+ validators.set(schema, new Validator(schema, "2020-12", false));
91
+ }
92
+ catch (err) {
93
+ disableValidation(schema, opts.address, logger, err);
94
+ }
95
+ }
96
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -4,5 +4,5 @@
4
4
  * a bump that forgets this file fails the build rather than shipping a stale
5
5
  * version to `/health` and to downstream MCP handshakes.
6
6
  */
7
- export declare const CONNECTA_VERSION = "0.3.0";
7
+ export declare const CONNECTA_VERSION = "0.4.1";
8
8
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -4,5 +4,5 @@
4
4
  * a bump that forgets this file fails the build rather than shipping a stale
5
5
  * version to `/health` and to downstream MCP handshakes.
6
6
  */
7
- export const CONNECTA_VERSION = "0.3.0";
7
+ export const CONNECTA_VERSION = "0.4.1";
8
8
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zackbart/connecta",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "description": "One MCP to rule them all — a single MCP endpoint aggregating many downstream connectors behind nine meta-tools.",
@@ -43,6 +43,10 @@
43
43
  "types": "./dist/node.d.ts",
44
44
  "import": "./dist/node.js"
45
45
  },
46
+ "./json-schema": {
47
+ "types": "./dist/json-schema.d.ts",
48
+ "import": "./dist/json-schema.js"
49
+ },
46
50
  "./quickjs": {
47
51
  "types": "./dist/executors/quickjs.d.ts",
48
52
  "import": "./dist/executors/quickjs.js"
package/src/catalog.ts CHANGED
@@ -79,6 +79,41 @@ function refName(ref: string): string {
79
79
  return ref.split("/").pop() ?? ref;
80
80
  }
81
81
 
82
+ /**
83
+ * Whether a schema declares anything renderSchema knows how to render on its
84
+ * own. Used to decide if the non-allOf half of a schema is worth rendering:
85
+ * without this, a plain `{ allOf: [...] }` would render its (empty) local half
86
+ * through the raw-JSON fallback and emit `{} & …`.
87
+ */
88
+ function declaresShape(s: Record<string, unknown>): boolean {
89
+ return (
90
+ typeof s.$ref === "string" ||
91
+ Array.isArray(s.oneOf) ||
92
+ Array.isArray(s.anyOf) ||
93
+ Array.isArray(s.enum) ||
94
+ s.const !== undefined ||
95
+ s.items !== undefined ||
96
+ s.properties !== undefined ||
97
+ s.type !== undefined
98
+ );
99
+ }
100
+
101
+ /**
102
+ * Parenthesize a top-level union so it doesn't read as part of a surrounding
103
+ * `&`. Only separators outside braces count, so a nested union or a property
104
+ * description containing a pipe doesn't trigger stray parentheses.
105
+ */
106
+ function grouped(part: string): string {
107
+ let nesting = 0;
108
+ for (let i = 0; i < part.length; i += 1) {
109
+ const char = part[i];
110
+ if (char === "{" || char === "(" || char === "[") nesting += 1;
111
+ else if (char === "}" || char === ")" || char === "]") nesting -= 1;
112
+ else if (nesting === 0 && part.startsWith(" | ", i)) return `(${part})`;
113
+ }
114
+ return part;
115
+ }
116
+
82
117
  function renderSchema(
83
118
  schema: unknown,
84
119
  defs: Record<string, unknown>,
@@ -91,6 +126,27 @@ function renderSchema(
91
126
  }
92
127
  const s = schema as Record<string, unknown>;
93
128
 
129
+ // allOf composes rather than replaces: it is checked before every other
130
+ // keyword, and renders the schema's own shape alongside its members instead
131
+ // of returning early. A schema carrying both allOf and properties (the usual
132
+ // OpenAPI-derived "extend this base" shape, and equally legal with $ref,
133
+ // enum, const, or items) would otherwise silently drop whichever half lost
134
+ // the branch race. The schema's own shape comes first, being the more
135
+ // specific half, and is rendered at the current depth because its members
136
+ // sit at this nesting level, not one below.
137
+ if (Array.isArray(s.allOf)) {
138
+ const { allOf: _members, ...own } = s;
139
+ const parts = declaresShape(own)
140
+ ? [renderSchema(own, defs, seen, depth)]
141
+ : [];
142
+ for (const member of s.allOf) {
143
+ parts.push(renderSchema(member, defs, seen, depth + 1));
144
+ }
145
+ if (parts.length === 0) return "unknown";
146
+ if (parts.length === 1) return parts[0] as string;
147
+ return parts.map(grouped).join(" & ");
148
+ }
149
+
94
150
  if (typeof s.$ref === "string") {
95
151
  const name = refName(s.$ref);
96
152
  if (seen.has(name)) return name;
@@ -112,6 +168,11 @@ function renderSchema(
112
168
  if (Array.isArray(s.enum)) {
113
169
  return s.enum.map((value) => JSON.stringify(value)).join(" | ");
114
170
  }
171
+ // Checked before type/properties so a discriminator like
172
+ // { type: "string", const: "emoji" } renders as "emoji" rather than string.
173
+ // JSON.stringify(undefined) returns undefined (not a string), so an explicit
174
+ // `const: undefined` must fall through to the regular type rendering.
175
+ if (s.const !== undefined) return JSON.stringify(s.const);
115
176
 
116
177
  const type = s.type;
117
178
  if (type === "array" || s.items) {
@@ -1,5 +1,4 @@
1
- import { Validator } from "@cfworker/json-schema";
2
- import { ConnectorCallError } from "../errors.js";
1
+ import { precompileValidator, validateToolInput } from "../validate.js";
3
2
  import type {
4
3
  Connector,
5
4
  ConnectorCredentialConfig,
@@ -50,6 +49,16 @@ export interface ApiOptions {
50
49
  * on loose coercion.
51
50
  */
52
51
  validateArgs?: boolean;
52
+ /**
53
+ * Fail-closed on a tool whose `inputSchema` the validator cannot evaluate
54
+ * (default false). The default surfaces such a schema as a one-time warning
55
+ * and then passes the raw arguments through, so a broken schema never breaks
56
+ * an otherwise working tool. Set true to instead reject those calls with a
57
+ * non-retryable `invalid_args` ConnectorCallError, so a schema that cannot be
58
+ * enforced never silently admits unvalidated input. Only consulted when
59
+ * `validateArgs` is not false.
60
+ */
61
+ strictValidation?: boolean;
53
62
  tools: ApiTool[];
54
63
  }
55
64
 
@@ -74,34 +83,15 @@ export function api(id: string, opts: ApiOptions): Connector {
74
83
  }));
75
84
  const byName = new Map(opts.tools.map((t) => [t.name, t]));
76
85
  const validateArgs = opts.validateArgs ?? true;
77
- // Lazy per-tool validator cache; null marks a schema the validator rejected
78
- // (warned once, then passed through rather than breaking a working tool).
79
- const validators = new Map<string, Validator | null>();
80
- const disableValidation = (
81
- tool: ApiTool,
82
- ctx: ConnectorContext,
83
- err: unknown,
84
- ) => {
85
- validators.set(tool.name, null);
86
- ctx.logger.warn(
87
- `[connecta] tool "${id}.${tool.name}" has an inputSchema the validator cannot use (${
88
- err instanceof Error ? err.message : String(err)
89
- }) — arguments are not validated`,
90
- );
91
- };
92
- const validatorFor = (tool: ApiTool, ctx: ConnectorContext) => {
93
- let validator = validators.get(tool.name);
94
- if (validator === undefined) {
95
- try {
96
- validator = new Validator(tool.inputSchema as never, "2020-12", false);
97
- validators.set(tool.name, validator);
98
- } catch (err) {
99
- disableValidation(tool, ctx, err);
100
- validator = null;
101
- }
86
+ const strictValidation = opts.strictValidation ?? false;
87
+ if (validateArgs) {
88
+ // Compile each schema now so a validator-hostile inputSchema surfaces once
89
+ // here rather than silently on its first call. Warning-only; never throws.
90
+ for (const t of opts.tools) {
91
+ if (t.inputSchema)
92
+ precompileValidator(t.inputSchema, { address: `${id}.${t.name}` });
102
93
  }
103
- return validator;
104
- };
94
+ }
105
95
  return {
106
96
  id,
107
97
  title: opts.title,
@@ -121,27 +111,12 @@ export function api(id: string, opts: ApiOptions): Connector {
121
111
  }
122
112
  const input = args ?? {};
123
113
  if (validateArgs && tool.inputSchema) {
124
- const validator = validatorFor(tool, ctx);
125
- let result;
126
- try {
127
- result = validator?.validate(input);
128
- } catch (err) {
129
- // e.g. an unresolvable $ref — surfaces on first validate, not compile.
130
- disableValidation(tool, ctx, err);
131
- }
132
- if (result && !result.valid) {
133
- const units = result.errors.filter(
134
- (u) => u.instanceLocation !== "#",
135
- );
136
- const detail = (units.length > 0 ? units : result.errors)
137
- .slice(0, 3)
138
- .map((u) => `${u.instanceLocation}: ${u.error}`)
139
- .join("; ");
140
- throw new ConnectorCallError(
141
- "invalid_args",
142
- `Invalid arguments for "${id}.${name}": ${detail || "input does not match the tool's inputSchema"}`,
143
- );
144
- }
114
+ const invalid = validateToolInput(tool.inputSchema, input, {
115
+ address: `${id}.${name}`,
116
+ logger: ctx.logger,
117
+ failClosed: strictValidation,
118
+ });
119
+ if (invalid) throw invalid;
145
120
  }
146
121
  return tool.handler(input, ctx);
147
122
  },
@@ -10,6 +10,7 @@ import type {
10
10
  Connector,
11
11
  ConnectorContext,
12
12
  ConnectorStatus,
13
+ Logger,
13
14
  ToolDef,
14
15
  } from "../types.js";
15
16
 
@@ -23,6 +24,19 @@ export interface RemoteMcpOptions {
23
24
  title?: string;
24
25
  description?: string;
25
26
  auth?: RemoteMcpAuth;
27
+ /**
28
+ * Refuse to connect to a non-`https://` `url` at construction (default
29
+ * false). Loopback hosts (`localhost`, `127.0.0.1`, `[::1]`) are always
30
+ * allowed for local development. Off by default, static `headers` credentials
31
+ * over a cleartext connection are warned about but permitted; set this true
32
+ * to make that misconfiguration a hard error instead.
33
+ */
34
+ requireHttps?: boolean;
35
+ /**
36
+ * Destination for the cleartext-credential warning emitted at construction.
37
+ * Default console.
38
+ */
39
+ logger?: Logger;
26
40
  /**
27
41
  * @internal Testing seam. When set, this transport is used instead of the
28
42
  * HTTP transport, letting tests point the connector at an in-process MCP
@@ -35,6 +49,15 @@ function msg(err: unknown): string {
35
49
  return err instanceof Error ? err.message : String(err);
36
50
  }
37
51
 
52
+ function isLoopbackHost(hostname: string): boolean {
53
+ return (
54
+ hostname === "localhost" ||
55
+ hostname === "127.0.0.1" ||
56
+ hostname === "[::1]" ||
57
+ hostname === "::1"
58
+ );
59
+ }
60
+
38
61
  interface ConnectionState {
39
62
  client: Client | null;
40
63
  transport: Transport | null;
@@ -60,6 +83,27 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
60
83
  // from the isolate singleton. Those are request-bound in Cloudflare Workers.
61
84
  const states = new WeakMap<object, ConnectionState>();
62
85
  const isOauth = opts.auth?.type === "oauth";
86
+ const logger = opts.logger ?? console;
87
+
88
+ // Check the destination scheme once at construction: buildTransport (and the
89
+ // SDK's fetch) attach any static credentials to every request, so an http://
90
+ // endpoint sends bearer tokens / API keys in cleartext. Loopback is exempt
91
+ // for local development.
92
+ const destination = new URL(opts.url);
93
+ const insecureDestination =
94
+ destination.protocol !== "https:" && !isLoopbackHost(destination.hostname);
95
+ if (insecureDestination) {
96
+ if (opts.requireHttps) {
97
+ throw new Error(
98
+ `[connecta] connector "${id}" url ${opts.url} is not https:// (and not loopback) — refusing to connect (requireHttps).`,
99
+ );
100
+ }
101
+ if (opts.auth?.type === "headers") {
102
+ logger.warn(
103
+ `[connecta] connector "${id}" sends static credentials to ${opts.url} over a non-https:// connection — those tokens will be transmitted in cleartext.`,
104
+ );
105
+ }
106
+ }
63
107
 
64
108
  /** Typed per-call auth signal; the SDK's UnauthorizedError stays as cause. */
65
109
  const authRequiredError = (cause: unknown) =>
@@ -98,6 +142,14 @@ export function remoteMcp(id: string, opts: RemoteMcpOptions): Connector {
98
142
  return state.provider;
99
143
  };
100
144
 
145
+ // NOTE: StreamableHTTPClientTransport speaks over fetch, which transparently
146
+ // follows 3xx redirects. A malicious or compromised downstream MCP could
147
+ // redirect to an internal address (e.g. http://169.254.169.254/…) and fetch
148
+ // would re-issue the request — potentially carrying static auth headers. The
149
+ // scheme check above only guards the first hop; a fully robust guard (manual
150
+ // redirect handling + per-hop re-validation + stripping auth headers cross-
151
+ // origin) lives in the SDK transport and is deferred to a future non-patch
152
+ // release rather than reimplemented here.
101
153
  const buildTransport = (
102
154
  ctx: ConnectorContext,
103
155
  state: ConnectionState,
@@ -21,7 +21,8 @@ interface CredentialPlaintext {
21
21
 
22
22
  export interface CredentialFieldMetadata {
23
23
  configured: true;
24
- lastFour: string;
24
+ /** Only emitted when the value is long enough that four chars don't leak much. */
25
+ lastFour?: string;
25
26
  updatedAt: string;
26
27
  }
27
28
 
@@ -200,7 +201,9 @@ export class CredentialVault {
200
201
  field,
201
202
  {
202
203
  configured: true as const,
203
- lastFour: value.slice(-4),
204
+ // Only reveal the tail on values comfortably longer than four chars;
205
+ // for a short secret those four would be half of it.
206
+ ...(value.length >= 12 ? { lastFour: value.slice(-4) } : {}),
204
207
  updatedAt: credential.updatedAt,
205
208
  },
206
209
  ]),
@@ -208,7 +211,7 @@ export class CredentialVault {
208
211
  const single = fields.value;
209
212
  return {
210
213
  configured: true,
211
- ...(single ? { lastFour: single.lastFour } : {}),
214
+ ...(single?.lastFour ? { lastFour: single.lastFour } : {}),
212
215
  updatedAt: credential.updatedAt,
213
216
  fields,
214
217
  };