@hasna/connectors 1.3.45 → 1.3.46

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 (114) hide show
  1. package/README.md +25 -0
  2. package/bin/index.js +792 -130
  3. package/bin/mcp.js +438 -52
  4. package/bin/serve.js +438 -52
  5. package/connectors/cloudflare-workers/.env.example +5 -0
  6. package/connectors/cloudflare-workers/AGENTS.md +11 -0
  7. package/connectors/cloudflare-workers/CLAUDE.md +11 -0
  8. package/connectors/cloudflare-workers/README.md +45 -0
  9. package/connectors/cloudflare-workers/package.json +47 -0
  10. package/connectors/cloudflare-workers/src/api/client.test.ts +144 -0
  11. package/connectors/cloudflare-workers/src/api/client.ts +386 -0
  12. package/connectors/cloudflare-workers/src/api/index.ts +1 -0
  13. package/connectors/cloudflare-workers/src/cli/index.ts +206 -0
  14. package/connectors/cloudflare-workers/src/index.ts +16 -0
  15. package/connectors/cloudflare-workers/src/types/index.ts +53 -0
  16. package/connectors/cloudflare-workers/src/utils/config.ts +61 -0
  17. package/connectors/cloudflare-workers/src/utils/output.ts +26 -0
  18. package/connectors/cloudflare-workers/tsconfig.build.json +4 -0
  19. package/connectors/cloudflare-workers/tsconfig.json +14 -0
  20. package/connectors/tidio/.env.example +3 -2
  21. package/connectors/tidio/CLAUDE.md +21 -96
  22. package/connectors/tidio/README.md +22 -18
  23. package/connectors/tidio/package.json +4 -2
  24. package/connectors/tidio/src/api/client.ts +26 -15
  25. package/connectors/tidio/src/api/index.ts +185 -128
  26. package/connectors/tidio/src/api/tidio.test.ts +175 -44
  27. package/connectors/tidio/src/cli/index.ts +154 -388
  28. package/connectors/tidio/src/index.ts +5 -3
  29. package/connectors/tidio/src/types/index.ts +135 -82
  30. package/connectors/tidio/src/utils/config.ts +90 -44
  31. package/connectors/wandb/.env.example +7 -0
  32. package/connectors/wandb/AGENTS.md +43 -0
  33. package/connectors/wandb/CLAUDE.md +67 -0
  34. package/connectors/wandb/README.md +65 -0
  35. package/connectors/wandb/package.json +52 -0
  36. package/connectors/wandb/src/api/client.test.ts +116 -0
  37. package/connectors/wandb/src/api/client.ts +83 -0
  38. package/connectors/wandb/src/api/graphql.ts +9 -0
  39. package/connectors/wandb/src/api/index.ts +36 -0
  40. package/connectors/wandb/src/api/projects.ts +36 -0
  41. package/connectors/wandb/src/api/viewer.ts +20 -0
  42. package/connectors/wandb/src/cli/index.ts +265 -0
  43. package/connectors/wandb/src/index.ts +22 -0
  44. package/connectors/wandb/src/types/index.ts +75 -0
  45. package/connectors/wandb/src/utils/config.ts +164 -0
  46. package/connectors/wandb/src/utils/output.ts +119 -0
  47. package/connectors/wandb/tsconfig.json +16 -0
  48. package/connectors/weights-biases/.env.example +7 -0
  49. package/connectors/weights-biases/CLAUDE.md +65 -0
  50. package/connectors/weights-biases/README.md +62 -0
  51. package/connectors/weights-biases/package.json +53 -0
  52. package/connectors/weights-biases/src/api/client.test.ts +46 -0
  53. package/connectors/weights-biases/src/api/client.ts +119 -0
  54. package/connectors/weights-biases/src/api/events.ts +18 -0
  55. package/connectors/weights-biases/src/api/index.ts +56 -0
  56. package/connectors/weights-biases/src/api/runs.ts +28 -0
  57. package/connectors/weights-biases/src/api/search.ts +10 -0
  58. package/connectors/weights-biases/src/cli/index.ts +289 -0
  59. package/connectors/weights-biases/src/index.ts +19 -0
  60. package/connectors/weights-biases/src/types/index.ts +92 -0
  61. package/connectors/weights-biases/src/utils/config.ts +168 -0
  62. package/connectors/weights-biases/src/utils/output.ts +116 -0
  63. package/connectors/weights-biases/tsconfig.json +16 -0
  64. package/connectors/zoominfo/.env.example +4 -0
  65. package/connectors/zoominfo/AGENTS.md +26 -0
  66. package/connectors/zoominfo/CLAUDE.md +20 -0
  67. package/connectors/zoominfo/README.md +69 -0
  68. package/connectors/zoominfo/package.json +52 -0
  69. package/connectors/zoominfo/src/api/client.test.ts +140 -0
  70. package/connectors/zoominfo/src/api/client.ts +228 -0
  71. package/connectors/zoominfo/src/api/index.ts +1 -0
  72. package/connectors/zoominfo/src/cli/index.ts +179 -0
  73. package/connectors/zoominfo/src/index.ts +3 -0
  74. package/connectors/zoominfo/src/types/index.ts +39 -0
  75. package/connectors/zoominfo/src/utils/config.ts +61 -0
  76. package/connectors/zoominfo/src/utils/output.ts +27 -0
  77. package/connectors/zoominfo/tsconfig.json +20 -0
  78. package/connectors/zotero/.env.example +7 -0
  79. package/connectors/zotero/.npmrc.example +2 -0
  80. package/connectors/zotero/AGENTS.md +40 -0
  81. package/connectors/zotero/CLAUDE.md +69 -0
  82. package/connectors/zotero/README.md +91 -0
  83. package/connectors/zotero/package.json +43 -0
  84. package/connectors/zotero/src/api/attachments.ts +130 -0
  85. package/connectors/zotero/src/api/client.test.ts +166 -0
  86. package/connectors/zotero/src/api/client.ts +169 -0
  87. package/connectors/zotero/src/api/collections.ts +26 -0
  88. package/connectors/zotero/src/api/index.ts +45 -0
  89. package/connectors/zotero/src/api/items.ts +64 -0
  90. package/connectors/zotero/src/cli/index.ts +386 -0
  91. package/connectors/zotero/src/index.ts +28 -0
  92. package/connectors/zotero/src/types/index.ts +129 -0
  93. package/connectors/zotero/src/utils/config.ts +245 -0
  94. package/connectors/zotero/src/utils/output.ts +119 -0
  95. package/connectors/zotero/tsconfig.json +16 -0
  96. package/connectors/zymbly/.env.example +2 -0
  97. package/connectors/zymbly/AGENTS.md +11 -0
  98. package/connectors/zymbly/CLAUDE.md +5 -0
  99. package/connectors/zymbly/README.md +35 -0
  100. package/connectors/zymbly/package.json +52 -0
  101. package/connectors/zymbly/src/api/client.test.ts +110 -0
  102. package/connectors/zymbly/src/api/client.ts +166 -0
  103. package/connectors/zymbly/src/api/index.ts +1 -0
  104. package/connectors/zymbly/src/cli/index.ts +156 -0
  105. package/connectors/zymbly/src/index.ts +12 -0
  106. package/connectors/zymbly/src/types/index.ts +34 -0
  107. package/connectors/zymbly/src/utils/config.ts +52 -0
  108. package/connectors/zymbly/src/utils/output.ts +17 -0
  109. package/connectors/zymbly/tsconfig.json +13 -0
  110. package/dist/index.js +45 -2
  111. package/dist/lib/compact-output.d.ts +40 -0
  112. package/dist/mcp/tools/jobs.d.ts +32 -0
  113. package/dist/mcp/tools/jobs.test.d.ts +1 -0
  114. package/package.json +3 -2
package/bin/serve.js CHANGED
@@ -16400,7 +16400,7 @@ var package_default;
16400
16400
  var init_package = __esm(() => {
16401
16401
  package_default = {
16402
16402
  name: "@hasna/connectors",
16403
- version: "1.3.45",
16403
+ version: "1.3.46",
16404
16404
  description: "Open source connector library - Install API connectors with a single command",
16405
16405
  type: "module",
16406
16406
  bin: {
@@ -16432,11 +16432,12 @@ var init_package = __esm(() => {
16432
16432
  "build:dashboard": "cd dashboard && bun run build",
16433
16433
  postinstall: 'mkdir -p $HOME/.hasna/connectors 2>/dev/null || true; [ "$SKIP_DASHBOARD" = "1" ] || [ ! -f dashboard/package.json ] || [ -d dashboard/node_modules ] || (cd dashboard && bun install)',
16434
16434
  dev: "bun run ./src/cli/index.tsx",
16435
+ "check:package-secrets": "bun run scripts/check-package-secrets.ts",
16435
16436
  typecheck: "tsc --noEmit && tsc -p tsconfig.social.json --noEmit",
16436
16437
  test: "bun test",
16437
16438
  "secrets:scan:npmrc": "bun run scripts/scan-npmrc-auth.mjs",
16438
16439
  "sdk:build": "cd sdk && bun run build",
16439
- prepublishOnly: "bun run secrets:scan:npmrc && bun run build && bun test"
16440
+ prepublishOnly: "bun run secrets:scan:npmrc && bun run check:package-secrets && bun run build && bun test"
16440
16441
  },
16441
16442
  keywords: [
16442
16443
  "connectors",
@@ -27814,6 +27815,13 @@ var connectors = [
27814
27815
  category: "AI & ML",
27815
27816
  tags: ["transcription", "meetings", "ai"]
27816
27817
  },
27818
+ {
27819
+ name: "wandb",
27820
+ displayName: "Weights & Biases",
27821
+ description: "ML experiment tracking and run management via GraphQL",
27822
+ category: "AI & ML",
27823
+ tags: ["ml", "experiments", "tracking"]
27824
+ },
27817
27825
  {
27818
27826
  name: "wato",
27819
27827
  displayName: "Wato",
@@ -27821,6 +27829,13 @@ var connectors = [
27821
27829
  category: "AI & ML",
27822
27830
  tags: ["ai", "agents", "memory", "workflows"]
27823
27831
  },
27832
+ {
27833
+ name: "weights-biases",
27834
+ displayName: "Weights & Biases",
27835
+ description: "ML experiment tracking (runs, events, search)",
27836
+ category: "AI & ML",
27837
+ tags: ["ai", "ml", "wandb", "experiment-tracking"]
27838
+ },
27824
27839
  {
27825
27840
  name: "wavelineextract",
27826
27841
  displayName: "Waveline Extract",
@@ -29459,6 +29474,20 @@ var connectors3 = [
29459
29474
  description: "HR platform for employees, leave, attendance, and timesheets",
29460
29475
  category: "Business Tools",
29461
29476
  tags: ["hr", "employees", "zoho"]
29477
+ },
29478
+ {
29479
+ name: "zymbly",
29480
+ displayName: "Zymbly",
29481
+ description: "Aircraft maintenance and CMMS platform for work orders, parts, and maintenance notes",
29482
+ category: "Business Tools",
29483
+ tags: ["maintenance", "aircraft", "work-orders", "cmms"]
29484
+ },
29485
+ {
29486
+ name: "zotero",
29487
+ displayName: "Zotero",
29488
+ description: "Bibliography and reference library API for items, collections, and attachments",
29489
+ category: "Business Tools",
29490
+ tags: ["bibliography", "citations", "research", "library", "references"]
29462
29491
  }
29463
29492
  ];
29464
29493
 
@@ -31969,6 +31998,13 @@ var connectors9 = [
31969
31998
  category: "Developer Tools",
31970
31999
  tags: ["cdn", "dns", "edge"]
31971
32000
  },
32001
+ {
32002
+ name: "cloudflare-workers",
32003
+ displayName: "Cloudflare Workers",
32004
+ description: "Cloudflare Workers REST API connector for scripts, multipart uploads, routes, deployments, versions, secrets, cron schedules, tails, subdomains, beta Workers, and scoped raw account or zone requests",
32005
+ category: "Developer Tools",
32006
+ tags: ["cloudflare", "workers", "serverless", "edge", "deployments", "developer-tools"]
32007
+ },
31972
32008
  {
31973
32009
  name: "googlecloud",
31974
32010
  displayName: "Google Cloud",
@@ -34361,6 +34397,13 @@ var connectors14 = [
34361
34397
  description: "Reviews and user-generated content platform for e-commerce",
34362
34398
  category: "Marketing & Sales",
34363
34399
  tags: ["reviews", "ugc", "ecommerce", "marketing"]
34400
+ },
34401
+ {
34402
+ name: "zoominfo",
34403
+ displayName: "ZoomInfo",
34404
+ description: "ZoomInfo B2B sales intelligence API for contact and company search, enrichment, lookup, and output field discovery",
34405
+ category: "Marketing & Sales",
34406
+ tags: ["sales-intelligence", "enrichment", "contacts", "companies", "b2b"]
34364
34407
  }
34365
34408
  ];
34366
34409
 
@@ -44630,30 +44673,126 @@ init_package();
44630
44673
 
44631
44674
  // src/mcp/tools/discovery.ts
44632
44675
  init_zod2();
44676
+
44677
+ // src/lib/compact-output.ts
44678
+ var DEFAULT_MCP_LIMIT = 20;
44679
+ var MAX_COMPACT_LIMIT = 100;
44680
+ var DEFAULT_TEXT_WIDTH = 96;
44681
+ var DEFAULT_OUTPUT_CHARS = 6000;
44682
+ function parseNonNegativeInt(raw, flag) {
44683
+ if (raw === undefined)
44684
+ return { value: undefined };
44685
+ if (!/^\d+$/.test(raw)) {
44686
+ return {
44687
+ value: undefined,
44688
+ error: `Invalid value for ${flag}: '${raw}'. Expected a non-negative integer.`
44689
+ };
44690
+ }
44691
+ return { value: parseInt(raw, 10) };
44692
+ }
44693
+ function normalizeLimit(value, fallback, max = MAX_COMPACT_LIMIT) {
44694
+ if (value === undefined || !Number.isFinite(value))
44695
+ return fallback;
44696
+ return Math.min(Math.max(1, Math.floor(value)), max);
44697
+ }
44698
+ function parseCursor(raw) {
44699
+ if (raw === undefined || raw === "")
44700
+ return { value: 0 };
44701
+ return parseNonNegativeInt(raw, "--cursor");
44702
+ }
44703
+ function pageItems(items, options) {
44704
+ const offset = Math.max(0, options.offset ?? 0);
44705
+ const limit = options.limit === undefined ? undefined : Math.max(1, Math.floor(options.limit));
44706
+ const paged = limit === undefined ? items.slice(offset) : items.slice(offset, offset + limit);
44707
+ const nextOffset = limit === undefined || offset + paged.length >= items.length ? null : offset + paged.length;
44708
+ return {
44709
+ items: paged,
44710
+ total: items.length,
44711
+ offset,
44712
+ limit: limit ?? null,
44713
+ nextOffset
44714
+ };
44715
+ }
44716
+ function truncateText(value, max = DEFAULT_TEXT_WIDTH) {
44717
+ const text = (value ?? "").replace(/\s+/g, " ").trim();
44718
+ if (text.length <= max)
44719
+ return text;
44720
+ if (max <= 3)
44721
+ return text.slice(0, max);
44722
+ return `${text.slice(0, max - 3).trimEnd()}...`;
44723
+ }
44724
+ function firstNonEmptyLines(value, maxLines, maxWidth = DEFAULT_TEXT_WIDTH) {
44725
+ return (value ?? "").split(`
44726
+ `).map((line) => line.trim()).filter(Boolean).slice(0, maxLines).map((line) => truncateText(line, maxWidth));
44727
+ }
44728
+ function compactConnector(connector, descriptionWidth = DEFAULT_TEXT_WIDTH) {
44729
+ return {
44730
+ name: connector.name,
44731
+ displayName: connector.displayName,
44732
+ version: connector.version,
44733
+ category: connector.category,
44734
+ description: truncateText(connector.description, descriptionWidth)
44735
+ };
44736
+ }
44737
+ function maybeTruncateOutput(text, options = {}) {
44738
+ const enabled = options.enabled ?? true;
44739
+ const maxChars = options.maxChars ?? DEFAULT_OUTPUT_CHARS;
44740
+ if (!enabled || text.length <= maxChars) {
44741
+ return { text, truncated: false };
44742
+ }
44743
+ const hint = options.hint ?? "Use --verbose for full output.";
44744
+ const omitted = text.length - maxChars;
44745
+ return {
44746
+ text: `${text.slice(0, maxChars).trimEnd()}
44747
+
44748
+ [truncated ${omitted} chars] ${hint}`,
44749
+ truncated: true
44750
+ };
44751
+ }
44752
+
44753
+ // src/mcp/tools/discovery.ts
44633
44754
  function registerDiscoveryTools(server, stripped) {
44634
44755
  server.registerTool("search_connectors", {
44635
44756
  title: "Search Connectors",
44636
44757
  description: "Search connectors by name or keyword.",
44637
- inputSchema: { query: exports_external2.string() }
44638
- }, async ({ query }) => {
44758
+ inputSchema: {
44759
+ query: exports_external2.string(),
44760
+ limit: exports_external2.number().optional(),
44761
+ verbose: exports_external2.boolean().optional()
44762
+ }
44763
+ }, async ({ query, limit, verbose }) => {
44639
44764
  const { getInstalledConnectors: getInstalledConnectors2 } = await Promise.resolve().then(() => (init_installer(), exports_installer));
44640
44765
  const { getPromotedConnectors: getPromotedConnectors2 } = await Promise.resolve().then(() => (init_promotions(), exports_promotions));
44641
44766
  const { getUsageMap: getUsageMap2 } = await Promise.resolve().then(() => (init_usage(), exports_usage));
44767
+ const resultLimit = normalizeLimit(limit, DEFAULT_MCP_LIMIT);
44642
44768
  const results = searchConnectors(query, {
44643
44769
  installed: getInstalledConnectors2(),
44644
44770
  promoted: getPromotedConnectors2(),
44645
- usage: getUsageMap2()
44771
+ usage: getUsageMap2(),
44772
+ limit: resultLimit
44646
44773
  });
44647
- return stripped(JSON.stringify(results.map((c) => ({ name: c.name, displayName: c.displayName, version: c.version, category: c.category, description: c.description, score: c.score, badges: c.badges })), null, 2));
44774
+ return stripped(JSON.stringify(results.map((c) => ({
44775
+ name: c.name,
44776
+ displayName: c.displayName,
44777
+ version: c.version,
44778
+ category: c.category,
44779
+ description: verbose ? c.description : truncateText(c.description, 120),
44780
+ score: c.score,
44781
+ badges: c.badges,
44782
+ ...verbose ? { matchReasons: c.matchReasons } : {}
44783
+ })), null, 2));
44648
44784
  });
44649
44785
  server.registerTool("list_connectors", {
44650
44786
  title: "List Connectors",
44651
- description: "List connectors. category filters; compact=true returns names only.",
44787
+ description: "List connectors with compact, paged defaults. Use verbose=true or compact=false for full metadata.",
44652
44788
  inputSchema: {
44653
44789
  category: exports_external2.string().optional(),
44654
- compact: exports_external2.boolean().optional()
44790
+ compact: exports_external2.boolean().optional(),
44791
+ limit: exports_external2.number().optional(),
44792
+ cursor: exports_external2.string().optional(),
44793
+ verbose: exports_external2.boolean().optional()
44655
44794
  }
44656
- }, async ({ category, compact }) => {
44795
+ }, async ({ category, compact, limit, cursor, verbose }) => {
44657
44796
  let connectors18 = CONNECTORS;
44658
44797
  if (category) {
44659
44798
  const matched = CATEGORIES.find((c) => c.toLowerCase() === category.toLowerCase());
@@ -44670,23 +44809,42 @@ function registerDiscoveryTools(server, stripped) {
44670
44809
  }
44671
44810
  connectors18 = getConnectorsByCategory(matched);
44672
44811
  }
44673
- const data = compact ? connectors18.map((c) => c.name) : connectors18.map((c) => ({
44812
+ const parsedCursor = parseCursor(cursor);
44813
+ if (parsedCursor.error) {
44814
+ return {
44815
+ content: [{ type: "text", text: JSON.stringify({ error: parsedCursor.error }) }],
44816
+ isError: true
44817
+ };
44818
+ }
44819
+ const page = pageItems(connectors18, {
44820
+ offset: parsedCursor.value ?? 0,
44821
+ limit: normalizeLimit(limit, DEFAULT_MCP_LIMIT)
44822
+ });
44823
+ const data = compact === true ? page.items.map((c) => c.name) : verbose || compact === false ? page.items.map((c) => ({
44674
44824
  name: c.name,
44675
44825
  displayName: c.displayName,
44676
44826
  version: c.version,
44677
44827
  category: c.category,
44678
- description: c.description
44679
- }));
44680
- return stripped(JSON.stringify(data, null, 2));
44828
+ description: c.description,
44829
+ tags: c.tags
44830
+ })) : page.items.map((c) => compactConnector(c, 120));
44831
+ return stripped(JSON.stringify({
44832
+ connectors: data,
44833
+ total: connectors18.length,
44834
+ count: data.length,
44835
+ nextCursor: page.nextOffset === null ? null : String(page.nextOffset),
44836
+ hint: page.nextOffset === null ? "Use verbose=true or compact=false for full connector metadata." : `Call again with cursor="${page.nextOffset}", or use verbose=true / compact=false for full connector metadata.`
44837
+ }, null, 2));
44681
44838
  });
44682
44839
  server.registerTool("connector_docs", {
44683
44840
  title: "Connector Documentation",
44684
- description: "Get connector docs. essential=true returns auth+envVars only.",
44841
+ description: "Get compact connector docs by default. Use verbose=true for full parsed docs or essential=true for auth+env only.",
44685
44842
  inputSchema: {
44686
44843
  name: exports_external2.string(),
44687
- essential: exports_external2.boolean().optional()
44844
+ essential: exports_external2.boolean().optional(),
44845
+ verbose: exports_external2.boolean().optional()
44688
44846
  }
44689
- }, async ({ name, essential }) => {
44847
+ }, async ({ name, essential, verbose }) => {
44690
44848
  const meta = getConnector(name);
44691
44849
  if (!meta) {
44692
44850
  return {
@@ -44702,7 +44860,7 @@ function registerDiscoveryTools(server, stripped) {
44702
44860
  isError: true
44703
44861
  };
44704
44862
  }
44705
- const data = essential ? { name: meta.name, auth: docs.auth, envVars: docs.envVars } : {
44863
+ const data = essential ? { name: meta.name, auth: docs.auth, envVars: docs.envVars } : verbose ? {
44706
44864
  name: meta.name,
44707
44865
  displayName: meta.displayName,
44708
44866
  version: meta.version,
@@ -44713,6 +44871,19 @@ function registerDiscoveryTools(server, stripped) {
44713
44871
  envVars: docs.envVars,
44714
44872
  cliCommands: docs.cliCommands,
44715
44873
  dataStorage: docs.dataStorage
44874
+ } : {
44875
+ name: meta.name,
44876
+ displayName: meta.displayName,
44877
+ version: meta.version,
44878
+ category: meta.category,
44879
+ description: truncateText(meta.description, 120),
44880
+ overview: firstNonEmptyLines(docs.overview, 1, 140)[0] ?? "",
44881
+ auth: firstNonEmptyLines(docs.auth, 4, 140),
44882
+ envVars: docs.envVars.slice(0, 8),
44883
+ envVarCount: docs.envVars.length,
44884
+ cliCommands: firstNonEmptyLines(docs.cliCommands, 8, 140),
44885
+ dataStorage: firstNonEmptyLines(docs.dataStorage, 2, 140),
44886
+ hint: `Use connector_docs({ name: "${name}", verbose: true }) for full parsed docs, or raw CLI docs with connectors docs ${name} --raw.`
44716
44887
  };
44717
44888
  return {
44718
44889
  content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
@@ -45137,9 +45308,11 @@ function registerOperationsTools(server, stripped) {
45137
45308
  description: "Discover available API operations for a connector. Returns CLI commands the connector supports (e.g. messages, products, customers). Use this before run_connector_operation to know what's available.",
45138
45309
  inputSchema: {
45139
45310
  name: exports_external2.string().describe("Connector name (e.g. stripe, gmail, anthropic)"),
45140
- command: exports_external2.string().optional().describe("Get detailed help for a specific subcommand (e.g. products, messages)")
45311
+ command: exports_external2.string().optional().describe("Get detailed help for a specific subcommand (e.g. products, messages)"),
45312
+ verbose: exports_external2.boolean().optional().describe("Include full auth status and raw help text."),
45313
+ limit: exports_external2.number().optional().describe("Limit operation rows in compact mode.")
45141
45314
  }
45142
- }, async ({ name, command }) => {
45315
+ }, async ({ name, command, verbose, limit }) => {
45143
45316
  const meta = getConnector(name);
45144
45317
  if (!meta) {
45145
45318
  return {
@@ -45171,6 +45344,32 @@ function registerOperationsTools(server, stripped) {
45171
45344
  }
45172
45345
  const ops = await getConnectorOperations(name);
45173
45346
  const auth = getAuthStatus(name);
45347
+ if (!verbose) {
45348
+ const operationLimit = normalizeLimit(limit, 50);
45349
+ const operations = ops.operations.slice(0, operationLimit).map((operation) => ({
45350
+ name: operation.name,
45351
+ aliases: operation.aliases,
45352
+ usage: operation.usage,
45353
+ summary: truncateText(operation.summary || "", 140),
45354
+ source: operation.source
45355
+ }));
45356
+ return {
45357
+ content: [
45358
+ {
45359
+ type: "text",
45360
+ text: JSON.stringify({
45361
+ connector: name,
45362
+ displayName: meta.displayName,
45363
+ auth: { type: auth.type, configured: auth.configured },
45364
+ commands: ops.commands,
45365
+ operations,
45366
+ totalOperations: ops.operations.length,
45367
+ hint: `Use list_connector_operations({ name: "${name}", verbose: true }) for full help text, or command="<subcommand>" for one command.`
45368
+ }, null, 2)
45369
+ }
45370
+ ]
45371
+ };
45372
+ }
45174
45373
  return {
45175
45374
  content: [
45176
45375
  {
@@ -45194,9 +45393,11 @@ function registerOperationsTools(server, stripped) {
45194
45393
  name: exports_external2.string().describe("Connector name (e.g. stripe, gmail, anthropic)"),
45195
45394
  args: exports_external2.array(exports_external2.string()).describe("CLI arguments for the connector command (e.g. ['products', 'list', '--limit', '5'])"),
45196
45395
  format: exports_external2.enum(["json", "pretty"]).optional().describe("Output format (default: json for structured parsing)"),
45197
- timeout: exports_external2.number().optional().describe("Timeout in milliseconds (default: 30000)")
45396
+ timeout: exports_external2.number().optional().describe("Timeout in milliseconds (default: 30000)"),
45397
+ verbose: exports_external2.boolean().optional().describe("Return full stdout/stderr without output truncation."),
45398
+ maxOutputChars: exports_external2.number().optional().describe("Maximum output characters when verbose is false (default: 6000).")
45198
45399
  }
45199
- }, async ({ name, args, format, timeout }) => {
45400
+ }, async ({ name, args, format, timeout, verbose, maxOutputChars }) => {
45200
45401
  const meta = getConnector(name);
45201
45402
  if (!meta) {
45202
45403
  return {
@@ -45219,6 +45420,11 @@ function registerOperationsTools(server, stripped) {
45219
45420
  ${result.stderr}`;
45220
45421
  const looksLikeHelp = /Usage:|Commands:|Options:/i.test(combinedOutput);
45221
45422
  if (!result.success && !looksLikeHelp) {
45423
+ const output = maybeTruncateOutput(result.stderr || result.stdout, {
45424
+ enabled: !verbose,
45425
+ maxChars: maxOutputChars ?? DEFAULT_OUTPUT_CHARS,
45426
+ hint: "Set verbose=true or maxOutputChars higher for full error output."
45427
+ });
45222
45428
  return {
45223
45429
  content: [
45224
45430
  {
@@ -45226,7 +45432,9 @@ ${result.stderr}`;
45226
45432
  text: JSON.stringify({
45227
45433
  connector: name,
45228
45434
  success: false,
45229
- error: result.stderr || result.stdout
45435
+ error: output.text,
45436
+ outputTruncated: output.truncated,
45437
+ hint: verbose ? undefined : "MCP error output is compact by default. Set verbose=true or maxOutputChars for more output."
45230
45438
  }, null, 2)
45231
45439
  }
45232
45440
  ],
@@ -45240,7 +45448,11 @@ ${result.stderr}`;
45240
45448
  text: JSON.stringify({
45241
45449
  connector: name,
45242
45450
  success: true,
45243
- output: looksLikeHelp ? (result.stdout || result.stderr).trim() : result.stdout
45451
+ output: maybeTruncateOutput(looksLikeHelp ? (result.stdout || result.stderr).trim() : result.stdout, {
45452
+ enabled: !verbose,
45453
+ maxChars: maxOutputChars ?? DEFAULT_OUTPUT_CHARS,
45454
+ hint: "Set verbose=true or maxOutputChars higher for full output."
45455
+ }).text
45244
45456
  }, null, 2)
45245
45457
  }
45246
45458
  ]
@@ -45257,11 +45469,14 @@ function registerSearchTools(server, stripped) {
45257
45469
  description: "Search for available operations across installed connectors.",
45258
45470
  inputSchema: {
45259
45471
  query: exports_external2.string(),
45260
- installedOnly: exports_external2.boolean().optional()
45472
+ installedOnly: exports_external2.boolean().optional(),
45473
+ limit: exports_external2.number().optional(),
45474
+ verbose: exports_external2.boolean().optional()
45261
45475
  }
45262
- }, async ({ query, installedOnly }) => {
45476
+ }, async ({ query, installedOnly, limit, verbose }) => {
45263
45477
  const installed = installedOnly ? getInstalledConnectors() : null;
45264
45478
  const results = [];
45479
+ const resultLimit = normalizeLimit(limit, DEFAULT_MCP_LIMIT);
45265
45480
  const connectors18 = installed || getInstalledConnectors();
45266
45481
  for (const name of connectors18) {
45267
45482
  try {
@@ -45280,22 +45495,31 @@ function registerSearchTools(server, stripped) {
45280
45495
  results.push({
45281
45496
  connector: name,
45282
45497
  operation: operation.name,
45283
- description: operation.summary || ops.helpText || ""
45498
+ description: verbose ? operation.summary || ops.helpText || "" : truncateText(operation.summary || ops.helpText || "", 160)
45284
45499
  });
45500
+ if (results.length >= resultLimit)
45501
+ break;
45285
45502
  }
45286
45503
  }
45504
+ if (results.length >= resultLimit)
45505
+ break;
45287
45506
  } catch {}
45288
45507
  }
45289
- return stripped(JSON.stringify(results, null, 2));
45508
+ return stripped(JSON.stringify({
45509
+ results,
45510
+ count: results.length,
45511
+ hint: "Use limit=<n> for more rows and verbose=true for longer descriptions."
45512
+ }, null, 2));
45290
45513
  });
45291
45514
  server.registerTool("describe_tools", {
45292
45515
  title: "Describe Tools",
45293
45516
  description: "Get detailed documentation for a connector's operations.",
45294
45517
  inputSchema: {
45295
45518
  name: exports_external2.string(),
45296
- operation: exports_external2.string().optional()
45519
+ operation: exports_external2.string().optional(),
45520
+ verbose: exports_external2.boolean().optional()
45297
45521
  }
45298
- }, async ({ name, operation }) => {
45522
+ }, async ({ name, operation, verbose }) => {
45299
45523
  const meta = getConnector(name);
45300
45524
  if (!meta) {
45301
45525
  return {
@@ -45311,7 +45535,23 @@ function registerSearchTools(server, stripped) {
45311
45535
  };
45312
45536
  }
45313
45537
  const ops = await getConnectorOperations(name);
45314
- return stripped(JSON.stringify({ connector: name, displayName: meta.displayName, ...ops }, null, 2));
45538
+ if (verbose) {
45539
+ return stripped(JSON.stringify({ connector: name, displayName: meta.displayName, ...ops }, null, 2));
45540
+ }
45541
+ return stripped(JSON.stringify({
45542
+ connector: name,
45543
+ displayName: meta.displayName,
45544
+ commands: ops.commands,
45545
+ operations: ops.operations.map((item) => ({
45546
+ name: item.name,
45547
+ aliases: item.aliases,
45548
+ usage: item.usage,
45549
+ summary: truncateText(item.summary || "", 140),
45550
+ source: item.source
45551
+ })),
45552
+ totalOperations: ops.operations.length,
45553
+ hint: `Use describe_tools({ name: "${name}", verbose: true }) for full help text.`
45554
+ }, null, 2));
45315
45555
  });
45316
45556
  }
45317
45557
  // src/mcp/tools/ranking.ts
@@ -45358,60 +45598,179 @@ init_zod2();
45358
45598
  init_database();
45359
45599
  init_jobs();
45360
45600
  init_scheduler();
45601
+ var DEFAULT_EXECUTION_OUTPUT_CHARS = 2000;
45602
+ var MAX_EXECUTION_OUTPUT_CHARS = 50000;
45603
+ function normalizeOutputChars(value) {
45604
+ return normalizeLimit(value, DEFAULT_EXECUTION_OUTPUT_CHARS, MAX_EXECUTION_OUTPUT_CHARS);
45605
+ }
45606
+ function compactExecutionText(text, options, label) {
45607
+ return maybeTruncateOutput(text, {
45608
+ enabled: !options.verbose,
45609
+ maxChars: normalizeOutputChars(options.maxOutputChars),
45610
+ hint: `Set verbose=true or maxOutputChars higher for full ${label} output.`
45611
+ });
45612
+ }
45613
+ function compactJobExecutionResult(result, options = {}) {
45614
+ const output = compactExecutionText(result.output, options, "job");
45615
+ return {
45616
+ ...result,
45617
+ output: output.text,
45618
+ outputTruncated: output.truncated,
45619
+ hint: options.verbose ? undefined : "MCP job output is compact by default. Set verbose=true or maxOutputChars for more output."
45620
+ };
45621
+ }
45622
+ function compactWorkflowExecutionResult(result, options = {}) {
45623
+ let truncatedOutputs = 0;
45624
+ const steps = result.steps.map((step) => {
45625
+ const output = compactExecutionText(step.output, options, "workflow step");
45626
+ if (output.truncated)
45627
+ truncatedOutputs++;
45628
+ return {
45629
+ ...step,
45630
+ output: output.text,
45631
+ outputTruncated: output.truncated
45632
+ };
45633
+ });
45634
+ const finalOutput = compactExecutionText(result.final_output, options, "workflow final");
45635
+ if (finalOutput.truncated)
45636
+ truncatedOutputs++;
45637
+ return {
45638
+ ...result,
45639
+ steps,
45640
+ final_output: finalOutput.text,
45641
+ finalOutputTruncated: finalOutput.truncated,
45642
+ truncatedOutputs,
45643
+ hint: options.verbose ? undefined : "MCP workflow output is compact by default. Set verbose=true or maxOutputChars for more output."
45644
+ };
45645
+ }
45361
45646
  function registerJobsTools(server, stripped) {
45362
45647
  server.registerTool("list_jobs", {
45363
45648
  title: "List Jobs",
45364
- description: "List scheduled connector jobs.",
45365
- inputSchema: {}
45366
- }, async () => {
45649
+ description: "List scheduled connector jobs with compact, paged defaults.",
45650
+ inputSchema: {
45651
+ limit: exports_external2.number().optional(),
45652
+ cursor: exports_external2.string().optional(),
45653
+ verbose: exports_external2.boolean().optional()
45654
+ }
45655
+ }, async ({ limit, cursor, verbose }) => {
45656
+ const parsedCursor = parseCursor(cursor);
45657
+ if (parsedCursor.error) {
45658
+ return { content: [{ type: "text", text: JSON.stringify({ error: parsedCursor.error }) }], isError: true };
45659
+ }
45367
45660
  const db = getDatabase();
45368
45661
  const jobs = listJobs(db);
45369
- return stripped(JSON.stringify(jobs, null, 2));
45662
+ const page = pageItems(jobs, {
45663
+ offset: parsedCursor.value ?? 0,
45664
+ limit: normalizeLimit(limit, DEFAULT_MCP_LIMIT)
45665
+ });
45666
+ const data = verbose ? page.items : page.items.map((job) => ({
45667
+ name: job.name,
45668
+ connector: job.connector,
45669
+ command: `${job.command}${job.args.length ? ` ${job.args.join(" ")}` : ""}`,
45670
+ cron: job.cron,
45671
+ enabled: job.enabled,
45672
+ strip: job.strip,
45673
+ lastRunAt: job.last_run_at
45674
+ }));
45675
+ return stripped(JSON.stringify({
45676
+ jobs: data,
45677
+ total: jobs.length,
45678
+ count: data.length,
45679
+ nextCursor: page.nextOffset === null ? null : String(page.nextOffset),
45680
+ hint: "Use verbose=true for full job records, get_latest_job_run for run output, or connectors jobs show <name>."
45681
+ }, null, 2));
45370
45682
  });
45371
45683
  server.registerTool("get_latest_job_run", {
45372
45684
  title: "Get Latest Job Run",
45373
- description: "Get the most recent run output for a job.",
45374
- inputSchema: { name: exports_external2.string() }
45375
- }, async ({ name }) => {
45685
+ description: "Get the most recent run output for a job. Output is truncated unless verbose=true.",
45686
+ inputSchema: {
45687
+ name: exports_external2.string(),
45688
+ verbose: exports_external2.boolean().optional(),
45689
+ maxOutputChars: exports_external2.number().optional()
45690
+ }
45691
+ }, async ({ name, verbose, maxOutputChars }) => {
45376
45692
  const db = getDatabase();
45377
45693
  const job = getJobByName(name, db);
45378
45694
  if (!job)
45379
45695
  return { content: [{ type: "text", text: JSON.stringify({ error: `Job "${name}" not found` }) }], isError: true };
45380
45696
  const run = getLatestRun(job.id, db);
45381
- return stripped(JSON.stringify(run ?? { message: "No runs yet" }, null, 2));
45697
+ if (!run)
45698
+ return stripped(JSON.stringify({ message: "No runs yet" }, null, 2));
45699
+ const outputLimit = normalizeLimit(maxOutputChars, 2000, 50000);
45700
+ return stripped(JSON.stringify({
45701
+ ...run,
45702
+ raw_output: run.raw_output && !verbose ? truncateText(run.raw_output, outputLimit) : run.raw_output,
45703
+ stripped_output: run.stripped_output && !verbose ? truncateText(run.stripped_output, outputLimit) : run.stripped_output,
45704
+ hint: verbose ? undefined : "Long run output is truncated in MCP. Use verbose=true or maxOutputChars for more output."
45705
+ }, null, 2));
45382
45706
  });
45383
45707
  server.registerTool("run_job", {
45384
45708
  title: "Run Job",
45385
45709
  description: "Manually trigger a scheduled job.",
45386
- inputSchema: { name: exports_external2.string() }
45387
- }, async ({ name }) => {
45710
+ inputSchema: {
45711
+ name: exports_external2.string(),
45712
+ verbose: exports_external2.boolean().optional().describe("Return full job output without truncation."),
45713
+ maxOutputChars: exports_external2.number().optional().describe("Maximum output characters when verbose is false (default: 2000).")
45714
+ }
45715
+ }, async ({ name, verbose, maxOutputChars }) => {
45388
45716
  const db = getDatabase();
45389
45717
  const job = getJobByName(name, db);
45390
45718
  if (!job)
45391
45719
  return { content: [{ type: "text", text: JSON.stringify({ error: `Job "${name}" not found` }) }], isError: true };
45392
45720
  const result = await triggerJob(job, db);
45393
- return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
45721
+ return stripped(JSON.stringify(compactJobExecutionResult(result, { verbose, maxOutputChars }), null, 2));
45394
45722
  });
45395
45723
  server.registerTool("list_workflows", {
45396
45724
  title: "List Workflows",
45397
- description: "List connector workflows.",
45398
- inputSchema: {}
45399
- }, async () => {
45725
+ description: "List connector workflows with compact, paged defaults.",
45726
+ inputSchema: {
45727
+ limit: exports_external2.number().optional(),
45728
+ cursor: exports_external2.string().optional(),
45729
+ verbose: exports_external2.boolean().optional()
45730
+ }
45731
+ }, async ({ limit, cursor, verbose }) => {
45732
+ const parsedCursor = parseCursor(cursor);
45733
+ if (parsedCursor.error) {
45734
+ return { content: [{ type: "text", text: JSON.stringify({ error: parsedCursor.error }) }], isError: true };
45735
+ }
45400
45736
  const db = getDatabase();
45401
45737
  const workflows = listWorkflows(db);
45402
- return stripped(JSON.stringify(workflows, null, 2));
45738
+ const page = pageItems(workflows, {
45739
+ offset: parsedCursor.value ?? 0,
45740
+ limit: normalizeLimit(limit, DEFAULT_MCP_LIMIT)
45741
+ });
45742
+ const data = verbose ? page.items : page.items.map((workflow) => ({
45743
+ name: workflow.name,
45744
+ enabled: workflow.enabled,
45745
+ stepCount: workflow.steps.length,
45746
+ steps: workflow.steps.slice(0, 5).map((step) => ({
45747
+ connector: step.connector,
45748
+ command: step.command
45749
+ }))
45750
+ }));
45751
+ return stripped(JSON.stringify({
45752
+ workflows: data,
45753
+ total: workflows.length,
45754
+ count: data.length,
45755
+ nextCursor: page.nextOffset === null ? null : String(page.nextOffset),
45756
+ hint: "Use verbose=true for full workflow records, or connectors workflows show <name>."
45757
+ }, null, 2));
45403
45758
  });
45404
45759
  server.registerTool("run_workflow", {
45405
45760
  title: "Run Workflow",
45406
45761
  description: "Execute a connector workflow pipeline.",
45407
- inputSchema: { name: exports_external2.string() }
45408
- }, async ({ name }) => {
45762
+ inputSchema: {
45763
+ name: exports_external2.string(),
45764
+ verbose: exports_external2.boolean().optional().describe("Return full workflow step output without truncation."),
45765
+ maxOutputChars: exports_external2.number().optional().describe("Maximum output characters per output field when verbose is false (default: 2000).")
45766
+ }
45767
+ }, async ({ name, verbose, maxOutputChars }) => {
45409
45768
  const db = getDatabase();
45410
45769
  const wf = getWorkflowByName(name, db);
45411
45770
  if (!wf)
45412
45771
  return { content: [{ type: "text", text: JSON.stringify({ error: `Workflow "${name}" not found` }) }], isError: true };
45413
45772
  const result = await runWorkflow(wf);
45414
- return stripped(JSON.stringify(result, null, 2));
45773
+ return stripped(JSON.stringify(compactWorkflowExecutionResult(result, { verbose, maxOutputChars }), null, 2));
45415
45774
  });
45416
45775
  }
45417
45776
  // src/mcp/tools/llm.ts
@@ -45462,11 +45821,38 @@ function registerAgentTools(server, stripped) {
45462
45821
  });
45463
45822
  server.registerTool("list_agents", {
45464
45823
  title: "List Agents",
45465
- description: "List all registered agents.",
45466
- inputSchema: {}
45467
- }, async () => {
45824
+ description: "List registered agents with compact, paged defaults.",
45825
+ inputSchema: {
45826
+ limit: exports_external2.number().optional(),
45827
+ cursor: exports_external2.string().optional(),
45828
+ verbose: exports_external2.boolean().optional()
45829
+ }
45830
+ }, async ({ limit, cursor, verbose }) => {
45831
+ const parsedCursor = parseCursor(cursor);
45832
+ if (parsedCursor.error) {
45833
+ return { content: [{ type: "text", text: JSON.stringify({ error: parsedCursor.error }) }], isError: true };
45834
+ }
45468
45835
  const agents = listAgents();
45469
- return { content: [{ type: "text", text: JSON.stringify(agents, null, 2) }] };
45836
+ const page = pageItems(agents, {
45837
+ offset: parsedCursor.value ?? 0,
45838
+ limit: normalizeLimit(limit, DEFAULT_MCP_LIMIT)
45839
+ });
45840
+ const data = verbose ? page.items : page.items.map((agent) => ({
45841
+ id: agent.id,
45842
+ name: agent.name,
45843
+ role: agent.role,
45844
+ lastSeenAt: agent.last_seen_at,
45845
+ projectId: agent.project_id
45846
+ }));
45847
+ return {
45848
+ content: [{ type: "text", text: JSON.stringify({
45849
+ agents: data,
45850
+ total: agents.length,
45851
+ count: data.length,
45852
+ nextCursor: page.nextOffset === null ? null : String(page.nextOffset),
45853
+ hint: "Use verbose=true for full agent records."
45854
+ }, null, 2) }]
45855
+ };
45470
45856
  });
45471
45857
  server.registerTool("heartbeat", {
45472
45858
  title: "Heartbeat",