@zackbart/connecta 0.4.1 → 0.5.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 (64) hide show
  1. package/CHANGELOG.md +169 -0
  2. package/README.md +40 -5
  3. package/SECURITY.md +10 -6
  4. package/dist/activity.d.ts +8 -0
  5. package/dist/activity.d.ts.map +1 -1
  6. package/dist/activity.js +1 -0
  7. package/dist/activity.js.map +1 -1
  8. package/dist/connectors/api.d.ts +13 -0
  9. package/dist/connectors/api.d.ts.map +1 -1
  10. package/dist/connectors/api.js +2 -0
  11. package/dist/connectors/api.js.map +1 -1
  12. package/dist/connectors/remote-mcp.d.ts +13 -0
  13. package/dist/connectors/remote-mcp.d.ts.map +1 -1
  14. package/dist/connectors/remote-mcp.js +2 -0
  15. package/dist/connectors/remote-mcp.js.map +1 -1
  16. package/dist/execute.d.ts +4 -4
  17. package/dist/execute.d.ts.map +1 -1
  18. package/dist/execute.js.map +1 -1
  19. package/dist/index.d.ts +35 -1
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +27 -0
  22. package/dist/index.js.map +1 -1
  23. package/dist/meta-tools.d.ts +22 -4
  24. package/dist/meta-tools.d.ts.map +1 -1
  25. package/dist/meta-tools.js +91 -18
  26. package/dist/meta-tools.js.map +1 -1
  27. package/dist/registry.d.ts +183 -2
  28. package/dist/registry.d.ts.map +1 -1
  29. package/dist/registry.js +293 -27
  30. package/dist/registry.js.map +1 -1
  31. package/dist/server.d.ts +7 -1
  32. package/dist/server.d.ts.map +1 -1
  33. package/dist/server.js +67 -7
  34. package/dist/server.js.map +1 -1
  35. package/dist/skills.d.ts +52 -1
  36. package/dist/skills.d.ts.map +1 -1
  37. package/dist/skills.js +161 -1
  38. package/dist/skills.js.map +1 -1
  39. package/dist/toolkits.d.ts +44 -0
  40. package/dist/toolkits.d.ts.map +1 -0
  41. package/dist/toolkits.js +134 -0
  42. package/dist/toolkits.js.map +1 -0
  43. package/dist/types.d.ts +20 -1
  44. package/dist/types.d.ts.map +1 -1
  45. package/dist/ui.d.ts +28 -0
  46. package/dist/ui.d.ts.map +1 -1
  47. package/dist/ui.js +89 -8
  48. package/dist/ui.js.map +1 -1
  49. package/dist/version.d.ts +1 -1
  50. package/dist/version.js +1 -1
  51. package/package.json +5 -2
  52. package/src/activity.ts +9 -0
  53. package/src/connectors/api.ts +15 -0
  54. package/src/connectors/remote-mcp.ts +15 -0
  55. package/src/execute.ts +4 -4
  56. package/src/index.ts +69 -1
  57. package/src/meta-tools.ts +126 -25
  58. package/src/registry.ts +416 -29
  59. package/src/server.ts +98 -7
  60. package/src/skills.ts +184 -1
  61. package/src/toolkits.ts +215 -0
  62. package/src/types.ts +20 -1
  63. package/src/ui.ts +92 -8
  64. package/src/version.ts +1 -1
package/dist/index.d.ts CHANGED
@@ -1,8 +1,39 @@
1
1
  import { Registry } from "./registry.js";
2
+ import { type ToolkitConfig } from "./toolkits.js";
2
3
  import type { ActivityReadGate, ActivityStore } from "./activity.js";
3
4
  import type { Connector, ConnectaBranding, Executor, InboundAuth, KVStorage, Logger } from "./types.js";
4
5
  export interface ConnectaConfig {
5
6
  connectors: Connector[];
7
+ /**
8
+ * Named scoped views over `connectors`, selected per client connection with
9
+ * `?toolkit=<name>` on the `/mcp` URL. One deployment belongs to one org;
10
+ * a toolkit is the slice of it a group of team members sees.
11
+ *
12
+ * ```ts
13
+ * toolkits: {
14
+ * support: { connectors: ["zendesk", "notion"] },
15
+ * exec: {
16
+ * connectors: ["zendesk", "notion", "gmail"],
17
+ * excludeTools: ["gmail.send_message"],
18
+ * },
19
+ * }
20
+ * ```
21
+ *
22
+ * Inside a toolkit-scoped session every meta-tool behaves as if out-of-scope
23
+ * connectors and tools do not exist, and an out-of-scope address fails
24
+ * exactly as a nonexistent one does. No `?toolkit=` ⇒ the full registry, so
25
+ * adding toolkits changes nothing for connections that don't ask for one; an
26
+ * unknown name is an error, never a silent fallback.
27
+ *
28
+ * Toolkits scope VISIBILITY, not identity: they do not decide *which* team
29
+ * member may select which toolkit. Gate that in `auth` (per-member binding is
30
+ * a follow-up).
31
+ *
32
+ * Definitions are validated at construction: an unknown connector id, an
33
+ * empty connector selection, an empty `includeTools`, a malformed tool
34
+ * address, or an address naming no tool on an in-code connector all throw.
35
+ */
36
+ toolkits?: ToolkitConfig;
6
37
  /**
7
38
  * Privacy-minimal downstream tool activity storage. Writes are best-effort
8
39
  * and never change tool results. Implement `list` to enable the Activity UI.
@@ -46,7 +77,9 @@ export interface ConnectaConfig {
46
77
  toolCatalogStaleSeconds?: number;
47
78
  /**
48
79
  * Max inline result size (bytes) before call_tool/batch_call truncate and
49
- * stash the full text for get_result paging. Default 50_000.
80
+ * stash the full text for get_result paging. Must be a whole number of bytes
81
+ * >= 1; anything else (0, negative, fractional, NaN, Infinity) warns at
82
+ * startup and falls back to the default 50_000.
50
83
  */
51
84
  maxResultBytes?: number;
52
85
  /**
@@ -121,6 +154,7 @@ export { bearerToken } from "./auth/bearer.js";
121
154
  export { memoryStorage } from "./storage/memory.js";
122
155
  export { CONNECTA_VERSION } from "./version.js";
123
156
  export type { Registry } from "./registry.js";
157
+ export type { ToolkitConfig, ToolkitDefinition } from "./toolkits.js";
124
158
  export type { RemoteMcpOptions, RemoteMcpAuth } from "./connectors/remote-mcp.js";
125
159
  export type { ApiOptions, ApiTool } from "./connectors/api.js";
126
160
  export type { Connector, ConnectaBranding, ConnectorCredentialAccess, ConnectorCredentialConfig, ConnectorCredentialFieldConfig, ConnectorCredentialValues, ConnectorContext, ConnectorStatus, CredentialTestResult, ExecuteResult, Executor, ExecutorProvider, InboundAuth, UiAuthConfig, AuthResult, JsonSchema, KVStorage, Logger, ToolDef, ToolAnnotations, } from "./types.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,6 +1,8 @@
1
1
  import { CredentialVault } from "./credentials.js";
2
2
  import { Registry } from "./registry.js";
3
3
  import { createFetchHandler } from "./server.js";
4
+ import { droppedBrandingUrls } from "./ui.js";
5
+ import { resolveToolkits } from "./toolkits.js";
4
6
  import { memoryStorage } from "./storage/memory.js";
5
7
  import { CONNECTA_VERSION } from "./version.js";
6
8
  function defaultLogger() {
@@ -44,6 +46,25 @@ function warnInsecureConfig(config, inboundAuth, logger) {
44
46
  "it at their own host and capture the authorization code. Set " +
45
47
  "`publicUrl` to a fixed https origin.");
46
48
  }
49
+ // Toolkits with no inbound auth: a toolkit is a scoped VIEW selected by the
50
+ // caller, not an authentication boundary. With nothing gating /mcp, any
51
+ // caller picks any toolkit — or omits the parameter and sees everything.
52
+ if (inboundAuth.length === 0 && config.toolkits) {
53
+ logger.warn("[connecta] toolkits are configured but there is no inbound " +
54
+ "authentication: a toolkit is a scoped view a client selects with " +
55
+ "?toolkit=, not an access check, so any caller can choose any toolkit " +
56
+ "or omit the parameter and see every connector. Configure `auth` " +
57
+ "(for example bearerToken(...) or Clerk).");
58
+ }
59
+ // Branding URLs that failed their scheme gate. Rendering silently falls back
60
+ // (a bad URL must not take the page down), so this warning is the only way an
61
+ // operator learns their value never reached the page.
62
+ const dropped = droppedBrandingUrls(config.branding);
63
+ if (dropped.length > 0) {
64
+ logger.warn(`[connecta] branding ${dropped.join(", ")} dropped: a branding URL is ` +
65
+ "used as an href, so it must be an absolute http(s) URL (favicon.href " +
66
+ "may also be a root-relative path). The default is rendered instead.");
67
+ }
47
68
  // OAuth connectors whose callback performs no state/CSRF check: the public
48
69
  // /oauth/callback/<id> route would exchange any delivered code.
49
70
  for (const connector of oauthConnectors) {
@@ -74,6 +95,11 @@ export function createConnecta(config) {
74
95
  toolCatalogStaleSeconds: config.toolCatalogStaleSeconds,
75
96
  maxResultBytes: config.maxResultBytes,
76
97
  });
98
+ // Throws on every structural mistake it can see (see resolveToolkits): a
99
+ // typo must not become a scope the operator never wrote. Note this is about
100
+ // the scope being *intended*, not about it being an access check — a toolkit
101
+ // scopes visibility, and `auth` remains the thing deciding who gets in.
102
+ const toolkits = resolveToolkits(config.toolkits, config.connectors);
77
103
  const inboundAuth = normalizeAuth(config.auth);
78
104
  warnInsecureConfig(config, inboundAuth, logger);
79
105
  const handler = createFetchHandler({
@@ -95,6 +121,7 @@ export function createConnecta(config) {
95
121
  credentialVault,
96
122
  deploymentInfo: config.deploymentInfo,
97
123
  branding: config.branding,
124
+ ...(toolkits ? { toolkits } : {}),
98
125
  });
99
126
  return {
100
127
  fetch: (request, _env, ctx) => handler(request, ctx && typeof ctx.waitUntil === "function"
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
2
  import { type ActivityRequestContext } from "./activity.js";
3
- import type { Registry } from "./registry.js";
3
+ import { type RegistryView } from "./registry.js";
4
4
  interface TextContent {
5
5
  type: "text";
6
6
  text: string;
@@ -38,6 +38,22 @@ export declare const MAX_RETRY_BACKOFF_MS = 10000;
38
38
  * `runCall`. Exported for direct testing.
39
39
  */
40
40
  export declare function retryBackoffMs(attempt: number, retryAfterMs: number | undefined): number | undefined;
41
+ /**
42
+ * Move a byte `end` back to the nearest UTF-8 codepoint boundary in
43
+ * `(offset, total]`, so decoding `bytes[offset, end)` never splits a codepoint
44
+ * (which would emit U+FFFD and break byte-exact reassembly). If backing up
45
+ * would make no progress — a single codepoint wider than the window — extend
46
+ * forward to the end of that codepoint instead so paging always advances.
47
+ * Assumes `offset` is itself a codepoint boundary (offsets are the prior
48
+ * `nextOffset`, which this function guarantees, and 0 is always a boundary).
49
+ *
50
+ * The return is always `> offset` while `offset < total`, whatever `end` is
51
+ * asked for. That is the belt-and-braces half of issue #32: cap validation
52
+ * keeps an empty window from arising in the first place, and this keeps an
53
+ * empty window from turning into a `nextOffset === offset` paging loop if one
54
+ * ever does. Exported for direct testing of that invariant.
55
+ */
56
+ export declare function alignEndToCharBoundary(bytes: Uint8Array, offset: number, end: number, total: number): number;
41
57
  export interface SearchArgs {
42
58
  query?: string;
43
59
  connector?: string;
@@ -70,6 +86,7 @@ export interface CallArgs {
70
86
  export interface GetResultArgs {
71
87
  id: string;
72
88
  offset?: number;
89
+ /** Page size in bytes; a whole number >= 1. Defaults to the deployment cap. */
73
90
  maxBytes?: number;
74
91
  }
75
92
  export interface BatchCall {
@@ -98,11 +115,12 @@ export interface SkillArgs {
98
115
  /**
99
116
  * The nine meta-tool handlers over a registry. Exported for direct testing;
100
117
  * registerMetaTools() wires them onto an McpServer. `opts.maxResultBytes`
101
- * overrides the registry's default result-size cap; `opts.defaultToolTimeoutMs`
118
+ * overrides the registry's default result-size cap (a connector's own
119
+ * `maxResultBytes` overrides it in turn); `opts.defaultToolTimeoutMs`
102
120
  * supplies a deadline for calls that don't carry one. (execute_code, the
103
121
  * optional tenth tool, is registered separately by registerExecuteTool.)
104
122
  */
105
- export declare function createMetaTools(registry: Registry, baseUrl: string, opts?: {
123
+ export declare function createMetaTools(registry: RegistryView, baseUrl: string, opts?: {
106
124
  maxResultBytes?: number;
107
125
  /** Deadline applied when a call passes no `timeoutMs`. Off when unset. */
108
126
  defaultToolTimeoutMs?: number;
@@ -121,7 +139,7 @@ export declare function createMetaTools(registry: Registry, baseUrl: string, opt
121
139
  authorizeConnector(args: AuthorizeArgs): Promise<ToolResult>;
122
140
  };
123
141
  /** Register the nine meta-tools onto an McpServer instance. */
124
- export declare function registerMetaTools(server: McpServer, registry: Registry, ctx: {
142
+ export declare function registerMetaTools(server: McpServer, registry: RegistryView, ctx: {
125
143
  baseUrl: string;
126
144
  maxResultBytes?: number;
127
145
  defaultToolTimeoutMs?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"meta-tools.d.ts","sourceRoot":"","sources":["../src/meta-tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"meta-tools.d.ts","sourceRoot":"","sources":["../src/meta-tools.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,8 @@ import { compactSchema, rankTools, summarizeDescription } from "./catalog.js";
3
3
  import { recordToolActivity, } from "./activity.js";
4
4
  import { unwrapMcpResult } from "./mcp-result.js";
5
5
  import { classifyCallError, ConnectorCallError, messageLooksRetryable, } from "./errors.js";
6
- import { AVAILABLE_SKILLS } from "./skills.js";
6
+ import { isValidMaxResultBytes, MIN_MAX_RESULT_BYTES, resolveMaxResultBytes, } from "./registry.js";
7
+ import { connectorGuide, connectorSkillName, hasConnectorGuides, listSkills, resolveSkill, } from "./skills.js";
7
8
  const RESULT_TTL_SECONDS = 900;
8
9
  export function jsonResult(obj) {
9
10
  return {
@@ -102,16 +103,25 @@ function isContinuationByte(b) {
102
103
  * forward to the end of that codepoint instead so paging always advances.
103
104
  * Assumes `offset` is itself a codepoint boundary (offsets are the prior
104
105
  * `nextOffset`, which this function guarantees, and 0 is always a boundary).
106
+ *
107
+ * The return is always `> offset` while `offset < total`, whatever `end` is
108
+ * asked for. That is the belt-and-braces half of issue #32: cap validation
109
+ * keeps an empty window from arising in the first place, and this keeps an
110
+ * empty window from turning into a `nextOffset === offset` paging loop if one
111
+ * ever does. Exported for direct testing of that invariant.
105
112
  */
106
- function alignEndToCharBoundary(bytes, offset, end, total) {
113
+ export function alignEndToCharBoundary(bytes, offset, end, total) {
107
114
  if (end >= total)
108
115
  return total;
109
- let e = end;
116
+ // A window that reaches no further than `offset` yields no bytes and no
117
+ // progress; widen it to one byte and let the codepoint walk below finish it.
118
+ const wanted = Math.max(end, offset + 1);
119
+ let e = wanted;
110
120
  while (e > offset && isContinuationByte(bytes[e]))
111
121
  e--;
112
122
  if (e === offset) {
113
123
  // Window is narrower than the codepoint at `offset`; take the whole thing.
114
- e = end;
124
+ e = wanted;
115
125
  while (e < total && isContinuationByte(bytes[e]))
116
126
  e++;
117
127
  }
@@ -210,12 +220,13 @@ async function guardValue(value, results, cap) {
210
220
  /**
211
221
  * The nine meta-tool handlers over a registry. Exported for direct testing;
212
222
  * registerMetaTools() wires them onto an McpServer. `opts.maxResultBytes`
213
- * overrides the registry's default result-size cap; `opts.defaultToolTimeoutMs`
223
+ * overrides the registry's default result-size cap (a connector's own
224
+ * `maxResultBytes` overrides it in turn); `opts.defaultToolTimeoutMs`
214
225
  * supplies a deadline for calls that don't carry one. (execute_code, the
215
226
  * optional tenth tool, is registered separately by registerExecuteTool.)
216
227
  */
217
228
  export function createMetaTools(registry, baseUrl, opts = {}) {
218
- const cap = opts.maxResultBytes ?? registry.maxResultBytes;
229
+ const globalCap = resolveMaxResultBytes(opts.maxResultBytes, registry.maxResultBytes);
219
230
  const defaultToolTimeoutMs = normalizeTimeoutMs(opts.defaultToolTimeoutMs);
220
231
  const probeTimeoutMs = normalizeTimeoutMs(opts.probeTimeoutMs) ?? DEFAULT_PROBE_TIMEOUT_MS;
221
232
  // createMetaTools() is called once per inbound MCP request. Sharing this
@@ -276,6 +287,13 @@ export function createMetaTools(registry, baseUrl, opts = {}) {
276
287
  return failed(errorDetails("unknown_address", `Unknown address "${call.address}"`));
277
288
  }
278
289
  const results = registry.resultsStorage();
290
+ // Result-size cap for THIS call: the connector's own override wins, then
291
+ // the deployment-wide value, then the built-in default (already folded
292
+ // into `globalCap`). Resolved per call so one batch_call can mix a
293
+ // tight-capped connector with siblings on the global cap. An override the
294
+ // registry already warned about at startup is dropped here, so the
295
+ // connector simply inherits `globalCap`.
296
+ const cap = resolveMaxResultBytes(resolved.connector.maxResultBytes, globalCap);
279
297
  const fields = call.fields && call.fields.length > 0 ? call.fields : null;
280
298
  // An explicit per-call deadline always wins; the config default only fills
281
299
  // the gap, and stays off entirely when the deployment sets none.
@@ -423,21 +441,23 @@ export function createMetaTools(registry, baseUrl, opts = {}) {
423
441
  }
424
442
  return {
425
443
  async skills(args = {}) {
444
+ const connectors = registry.listConnectors();
426
445
  if (!args.name) {
427
446
  return {
428
447
  content: [
429
448
  {
430
449
  type: "text",
431
450
  text: 'Available skills. Fetch one with skills({ name: "<name>" }).\n\n' +
432
- AVAILABLE_SKILLS.map((skill) => `- \`${skill.name}\` — ${skill.description}`).join("\n"),
451
+ listSkills(connectors)
452
+ .map((skill) => `- \`${skill.name}\` — ${skill.description}`)
453
+ .join("\n"),
433
454
  },
434
455
  ],
435
456
  };
436
457
  }
437
- const skill = AVAILABLE_SKILLS.find((item) => item.name === args.name);
438
- if (!skill) {
439
- return errorResult(`Unknown skill "${args.name}". Available: ${AVAILABLE_SKILLS.map((item) => item.name).join(", ")}.`);
440
- }
458
+ const skill = resolveSkill(args.name, connectors);
459
+ if (!skill.found)
460
+ return errorResult(skill.message);
441
461
  return { content: [{ type: "text", text: skill.content }] };
442
462
  },
443
463
  async listConnectors(args = {}) {
@@ -459,11 +479,16 @@ export function createMetaTools(registry, baseUrl, opts = {}) {
459
479
  }
460
480
  }
461
481
  else {
482
+ // "error" comes from THIS view's own observations — a sibling
483
+ // toolkit's failure is not this session's experience — while
484
+ // ok/unknown may lean on the deployment-wide success signal, since
485
+ // "the connector answers at all" is a fact about the connector.
486
+ // Unscoped, the two are the same log, so this is unchanged there.
462
487
  status = {
463
488
  state: observed?.consecutiveFailures &&
464
489
  observed.consecutiveFailures > 0
465
490
  ? "error"
466
- : observed?.lastSuccessAt || c.kind === "api"
491
+ : registry.hasObservedSuccess(c.id) || c.kind === "api"
467
492
  ? "ok"
468
493
  : "unknown",
469
494
  ...(observed?.lastError ? { message: observed.lastError } : {}),
@@ -521,6 +546,9 @@ export function createMetaTools(registry, baseUrl, opts = {}) {
521
546
  connectorId: c.id,
522
547
  connectorTitle: c.title,
523
548
  connectorDescription: c.description,
549
+ ...(connectorGuide(c)
550
+ ? { connectorGuideSkill: connectorSkillName(c.id) }
551
+ : {}),
524
552
  tool: ranked.tool,
525
553
  score: ranked.score,
526
554
  order: orderBase + ranked.order,
@@ -540,6 +568,9 @@ export function createMetaTools(registry, baseUrl, opts = {}) {
540
568
  id: match.connectorId,
541
569
  ...(match.connectorTitle ? { title: match.connectorTitle } : {}),
542
570
  description: match.connectorDescription,
571
+ ...(match.connectorGuideSkill
572
+ ? { guide: match.connectorGuideSkill }
573
+ : {}),
543
574
  tools: [],
544
575
  };
545
576
  byConnector.set(match.connectorId, group);
@@ -621,6 +652,9 @@ export function createMetaTools(registry, baseUrl, opts = {}) {
621
652
  address,
622
653
  name: tool.name,
623
654
  description: summarizeDescription(tool.description, args.fullDescriptions === true),
655
+ ...(connectorGuide(resolved.connector)
656
+ ? { guide: connectorSkillName(resolved.connector.id) }
657
+ : {}),
624
658
  inputSchema: format === "json" ? schema : compactSchema(schema),
625
659
  ...(tool.outputSchema
626
660
  ? {
@@ -641,6 +675,16 @@ export function createMetaTools(registry, baseUrl, opts = {}) {
641
675
  return (await runCall(args, "call_destructive_tool", { allowDestructive: true })).toolResult;
642
676
  },
643
677
  async getResult(args) {
678
+ // Client-supplied page size: a normal input-validation error, not a
679
+ // clamp. Callers arriving over MCP are rejected earlier by the
680
+ // registered zod schema and never reach this branch, so it exists for
681
+ // in-process callers of createMetaTools — which have no schema in front
682
+ // of them — and to keep the rule true of the handler on its own terms.
683
+ if (args.maxBytes !== undefined &&
684
+ !isValidMaxResultBytes(args.maxBytes)) {
685
+ return errorResult(`Invalid maxBytes ${args.maxBytes}: must be a whole number of bytes ` +
686
+ `>= ${MIN_MAX_RESULT_BYTES}. Omit it to use the deployment default.`);
687
+ }
644
688
  const results = registry.resultsStorage();
645
689
  const stored = await results.get(`result:${args.id}`);
646
690
  if (stored === null || stored === undefined) {
@@ -649,7 +693,11 @@ export function createMetaTools(registry, baseUrl, opts = {}) {
649
693
  const bytes = enc.encode(stored);
650
694
  const total = bytes.length;
651
695
  const offset = Math.max(0, Math.trunc(args.offset ?? 0));
652
- const maxBytes = args.maxBytes ?? cap;
696
+ // Page size only: a stashed result carries no connector identity, so
697
+ // get_result keeps the deployment-wide default when none is requested.
698
+ // Both sides are validated by now — the argument above, `globalCap` at
699
+ // intake — so `offset + maxBytes` always reaches past `offset`.
700
+ const maxBytes = args.maxBytes ?? globalCap;
653
701
  // Align the slice end to a codepoint boundary so a multi-byte char is
654
702
  // never split across pages (which would emit U+FFFD on both sides).
655
703
  // `nextOffset` is this aligned end, so it is a valid boundary for the
@@ -768,10 +816,32 @@ const SEARCH_DESC = 'Start here when a tool address is unknown. Exact/name match
768
816
  const DESCRIBE_DESC = 'Inspect known tool addresses when search_tools did not include a sufficient schema. Returns descriptions, input/output schemas, and behavior annotations; format "compact" is the default.';
769
817
  const CALL_DESC = 'Use for one tool explicitly annotated readOnlyHint: true. For 2–10 independent read-only calls use batch_call; for dependent steps or data reduction use execute_code when available. Unannotated, write-capable, and destructive tools are refused and require call_destructive_tool. fields selects JSON dot-paths, resultMode "value" unwraps results, timeoutMs sets a deadline, safe maxRetries are annotation-gated, diagnostics adds timing, and large results page through get_result.';
770
818
  const CALL_DESTRUCTIVE_DESC = "Invoke any tool that is not explicitly annotated readOnlyHint: true, including unannotated, write-capable, or destructive tools. The MCP destructiveHint on this meta-tool lets the host request human approval before execution. Use only after reviewing the downstream tool schema and consequences.";
771
- const GET_RESULT_DESC = "Page a truncated result stashed by call_tool/batch_call. Input { id, offset?, maxBytes? } → { text, offset, nextOffset?, totalBytes } sliced by byte offset. Unknown/expired id is an error.";
819
+ const GET_RESULT_DESC = "Page a truncated result stashed by call_tool/batch_call. Input { id, offset?, maxBytes? } → { text, offset, nextOffset?, totalBytes } sliced by byte offset. maxBytes is a whole number of bytes >= 1 (omit for the deployment default). Unknown/expired id is an error.";
772
820
  const BATCH_DESC = "Use for 2–10 independent tools explicitly annotated readOnlyHint: true. Calls run in parallel with shared request-scoped clients; use execute_code when available instead for dependencies or in-sandbox reduction. Unannotated, write-capable, and destructive tools are refused. Batch timeout, safe retry, result mode, and diagnostics defaults may be overridden per call.";
773
821
  const AUTHORIZE_DESC = "Use after a connector reports auth_required. Starts downstream OAuth and returns an authorizationUrl for the operator to open. force=true wipes stored credentials first and restarts consent.";
774
822
  const SKILLS_DESC = 'List or fetch concise guidance for choosing among Connecta meta-tools. Call skills({ name: "usage" }) once when the routing workflow is unfamiliar; do not refetch it in the same task.';
823
+ /**
824
+ * Sentences appended to a meta-tool description only when this connection
825
+ * actually has connector guides. Tool descriptions are always-loaded context,
826
+ * so a deployment with no guides gets every base description unchanged rather
827
+ * than paying for text about a feature it does not use.
828
+ *
829
+ * Registration is per connection and reads the connection's own registry view,
830
+ * so under a toolkit these sentences reflect the SCOPED connector set: a scoped
831
+ * session whose connectors carry no guides sees the base descriptions, and
832
+ * never learns from a tool description that guides exist out of scope.
833
+ */
834
+ const GUIDE_NOTES = {
835
+ skills: ' skills({}) also lists this deployment\'s per-connector usage guides as "connector:<connectorId>"; fetch the guide for a connector before working with it for the first time.',
836
+ search: " A connector group carrying `guide` has a usage guide; fetch it with skills({ name: <guide> }).",
837
+ describe: " An entry carrying `guide` belongs to a connector with a usage guide; fetch it with skills({ name: <guide> }).",
838
+ };
839
+ /** `base`, plus its guide note when any VISIBLE connector carries a guide. */
840
+ function describedFor(registry, base, note) {
841
+ return hasConnectorGuides(registry.listConnectors())
842
+ ? base + GUIDE_NOTES[note]
843
+ : base;
844
+ }
775
845
  /**
776
846
  * Connecta refuses downstream tools that are not explicitly annotated
777
847
  * read-only, so its own meta-tools must carry the same hints — otherwise a
@@ -799,7 +869,7 @@ export function registerMetaTools(server, registry, ctx) {
799
869
  activity: ctx.activity,
800
870
  });
801
871
  server.registerTool("skills", {
802
- description: SKILLS_DESC,
872
+ description: describedFor(registry, SKILLS_DESC, "skills"),
803
873
  inputSchema: { name: z.string().optional() },
804
874
  annotations: {
805
875
  readOnlyHint: true,
@@ -814,7 +884,7 @@ export function registerMetaTools(server, registry, ctx) {
814
884
  annotations: READ_ONLY_REMOTE,
815
885
  }, async (args) => mt.listConnectors(args));
816
886
  server.registerTool("search_tools", {
817
- description: SEARCH_DESC,
887
+ description: describedFor(registry, SEARCH_DESC, "search"),
818
888
  inputSchema: {
819
889
  query: z.string().optional(),
820
890
  connector: z.string().optional(),
@@ -826,7 +896,7 @@ export function registerMetaTools(server, registry, ctx) {
826
896
  annotations: READ_ONLY_REMOTE,
827
897
  }, async (args) => mt.searchTools(args));
828
898
  server.registerTool("describe_tools", {
829
- description: DESCRIBE_DESC,
899
+ description: describedFor(registry, DESCRIBE_DESC, "describe"),
830
900
  inputSchema: {
831
901
  addresses: z.array(z.string()),
832
902
  format: z.enum(["compact", "json"]).optional(),
@@ -885,7 +955,10 @@ export function registerMetaTools(server, registry, ctx) {
885
955
  inputSchema: {
886
956
  id: z.string(),
887
957
  offset: z.number().int().nonnegative().optional(),
888
- maxBytes: z.number().int().positive().optional(),
958
+ // Same rule as isValidMaxResultBytes, expressed for the wire: sharing
959
+ // the floor constant keeps the schema from drifting away from the
960
+ // in-handler check if MIN_MAX_RESULT_BYTES ever moves.
961
+ maxBytes: z.number().int().min(MIN_MAX_RESULT_BYTES).optional(),
889
962
  },
890
963
  annotations: READ_ONLY_LOCAL,
891
964
  }, async (args) => mt.getResult(args));