@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
@@ -0,0 +1,166 @@
1
+ import type {
2
+ HttpMethod,
3
+ JsonObject,
4
+ QueryParams,
5
+ RequestOptions,
6
+ ZymblyConfig,
7
+ } from "../types";
8
+ import { ZymblyApiError } from "../types";
9
+
10
+ const DEFAULT_BASE_URL = "https://api.zymbly.com/v1";
11
+
12
+ function normalizePath(path: string): string {
13
+ const trimmed = path.trim();
14
+ if (!trimmed) {
15
+ throw new Error("Zymbly API path is required");
16
+ }
17
+ if (/^https?:\/\//i.test(trimmed)) {
18
+ throw new Error("Zymbly API paths must be relative, not absolute URLs");
19
+ }
20
+ const normalized = trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
21
+ if (normalized.split("/").some((part) => part === "..")) {
22
+ throw new Error("Zymbly API paths cannot contain parent-directory segments");
23
+ }
24
+ return normalized;
25
+ }
26
+
27
+ function encodePath(value: string | number): string {
28
+ return encodeURIComponent(String(value));
29
+ }
30
+
31
+ function appendQuery(url: URL, query?: QueryParams): void {
32
+ if (!query) {
33
+ return;
34
+ }
35
+ for (const [key, value] of Object.entries(query)) {
36
+ if (Array.isArray(value)) {
37
+ for (const item of value) {
38
+ if (item !== undefined && item !== null) {
39
+ url.searchParams.append(key, String(item));
40
+ }
41
+ }
42
+ continue;
43
+ }
44
+ if (value !== undefined && value !== null) {
45
+ url.searchParams.set(key, String(value));
46
+ }
47
+ }
48
+ }
49
+
50
+ function parseResponse(text: string, contentType: string | null): unknown {
51
+ if (!text) {
52
+ return {};
53
+ }
54
+ if (contentType?.includes("json") || text.startsWith("{") || text.startsWith("[")) {
55
+ try {
56
+ return JSON.parse(text);
57
+ } catch {
58
+ return { raw: text };
59
+ }
60
+ }
61
+ return text;
62
+ }
63
+
64
+ function extractErrorMessage(data: unknown, fallback: string): string {
65
+ if (typeof data === "string" && data.trim()) {
66
+ return data.slice(0, 500);
67
+ }
68
+ if (data && typeof data === "object") {
69
+ const record = data as Record<string, unknown>;
70
+ const message = record.message ?? record.error ?? record.detail ?? record.title;
71
+ if (typeof message === "string" && message.trim()) {
72
+ return message;
73
+ }
74
+ }
75
+ return fallback;
76
+ }
77
+
78
+ export class ZymblyClient {
79
+ private readonly apiKey?: string;
80
+ private readonly baseUrl: string;
81
+
82
+ constructor(config: ZymblyConfig = {}) {
83
+ this.apiKey = config.apiKey;
84
+ this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/+$/, "");
85
+ }
86
+
87
+ async request<T = unknown>(path: string, options: RequestOptions = {}): Promise<T> {
88
+ const method = options.method || (options.body ? "POST" : "GET");
89
+ const url = this.buildUrl(path, options.query);
90
+ const headers: Record<string, string> = {
91
+ Accept: "application/json",
92
+ ...options.headers,
93
+ };
94
+ const body = this.prepareBody(method, options);
95
+ if (body !== undefined && !headers["Content-Type"]) {
96
+ headers["Content-Type"] = "application/json";
97
+ }
98
+ if (options.auth !== false) {
99
+ headers.Authorization = `Bearer ${this.requireApiKey()}`;
100
+ }
101
+ const response = await fetch(url.toString(), { method, headers, body });
102
+ const text = await response.text();
103
+ const data = parseResponse(text, response.headers.get("content-type"));
104
+ if (!response.ok) {
105
+ throw new ZymblyApiError(
106
+ extractErrorMessage(data, response.statusText || `Zymbly request failed with ${response.status}`),
107
+ response.status,
108
+ data,
109
+ );
110
+ }
111
+ return data as T;
112
+ }
113
+
114
+ listWorkOrders<T = unknown>(query?: QueryParams): Promise<T> {
115
+ return this.request<T>("/work-orders", { query });
116
+ }
117
+
118
+ getWorkOrder<T = unknown>(workOrderId: string): Promise<T> {
119
+ return this.request<T>(`/work-orders/${encodePath(workOrderId)}`);
120
+ }
121
+
122
+ searchParts<T = unknown>(query?: QueryParams): Promise<T> {
123
+ return this.request<T>("/parts", { query });
124
+ }
125
+
126
+ createMaintenanceNote<T = unknown>(workOrderId: string, note: string): Promise<T> {
127
+ return this.request<T>(`/work-orders/${encodePath(workOrderId)}/notes`, {
128
+ method: "POST",
129
+ body: { note },
130
+ });
131
+ }
132
+
133
+ createMaintenanceNoteWithBody<T = unknown>(workOrderId: string, body: JsonObject): Promise<T> {
134
+ return this.request<T>(`/work-orders/${encodePath(workOrderId)}/notes`, {
135
+ method: "POST",
136
+ body,
137
+ });
138
+ }
139
+
140
+ rawRequest<T = unknown>(method: HttpMethod, path: string, options: Omit<RequestOptions, "method"> = {}): Promise<T> {
141
+ return this.request<T>(path, { ...options, method });
142
+ }
143
+
144
+ private buildUrl(path: string, query?: QueryParams): URL {
145
+ const url = new URL(`${this.baseUrl}${normalizePath(path)}`);
146
+ appendQuery(url, query);
147
+ return url;
148
+ }
149
+
150
+ private prepareBody(method: HttpMethod, options: RequestOptions): string | undefined {
151
+ if (method === "GET") {
152
+ return undefined;
153
+ }
154
+ if (options.body === undefined) {
155
+ return undefined;
156
+ }
157
+ return typeof options.body === "string" ? options.body : JSON.stringify(options.body);
158
+ }
159
+
160
+ private requireApiKey(): string {
161
+ if (!this.apiKey) {
162
+ throw new Error("Zymbly API key is required. Use config set-key or set ZYMBLY_API_KEY.");
163
+ }
164
+ return this.apiKey;
165
+ }
166
+ }
@@ -0,0 +1 @@
1
+ export { ZymblyClient } from "./client";
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env bun
2
+ import { Command } from "commander";
3
+ import { ZymblyClient } from "../api";
4
+ import type { HttpMethod, JsonObject, JsonValue, OutputFormat, QueryParams, QueryValue } from "../types";
5
+ import {
6
+ clearConfig,
7
+ getApiKey,
8
+ getBaseUrl,
9
+ getConfigPath,
10
+ setApiKey,
11
+ setBaseUrl,
12
+ } from "../utils/config";
13
+ import { error, print, success } from "../utils/output";
14
+
15
+ const VERSION = "0.0.1";
16
+ const DEFAULT_BASE_URL = "https://api.zymbly.com/v1";
17
+
18
+ function parseJson(value: string | undefined, label: string): JsonValue {
19
+ if (!value) {
20
+ return {};
21
+ }
22
+ try {
23
+ return JSON.parse(value) as JsonValue;
24
+ } catch (err) {
25
+ const message = err instanceof Error ? err.message : String(err);
26
+ throw new Error(`Invalid ${label}: ${message}`);
27
+ }
28
+ }
29
+
30
+ function parseObject(value: string | undefined, label: string): JsonObject {
31
+ const parsed = parseJson(value, label);
32
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
33
+ throw new Error(`${label} must be a JSON object`);
34
+ }
35
+ return parsed as JsonObject;
36
+ }
37
+
38
+ function parseQueryParams(value: string | undefined): QueryParams | undefined {
39
+ if (!value) {
40
+ return undefined;
41
+ }
42
+ const parsed = parseObject(value, "query");
43
+ const query: QueryParams = {};
44
+ for (const [key, entry] of Object.entries(parsed)) {
45
+ if (Array.isArray(entry)) {
46
+ query[key] = entry.map((item) => {
47
+ if (typeof item === "string" || typeof item === "number" || typeof item === "boolean" || item === null || item === undefined) {
48
+ return item as QueryValue;
49
+ }
50
+ throw new Error(`query.${key} must contain only string, number, boolean, null, or undefined values`);
51
+ });
52
+ continue;
53
+ }
54
+ if (typeof entry === "string" || typeof entry === "number" || typeof entry === "boolean" || entry === null || entry === undefined) {
55
+ query[key] = entry as QueryValue;
56
+ continue;
57
+ }
58
+ throw new Error(`query.${key} must be a string, number, boolean, null, or an array of those values`);
59
+ }
60
+ return query;
61
+ }
62
+
63
+ function getFormat(command: Command): OutputFormat {
64
+ return (command.optsWithGlobals().format || "pretty") as OutputFormat;
65
+ }
66
+
67
+ function getClient(command: Command): ZymblyClient {
68
+ const options = command.optsWithGlobals();
69
+ const apiKey = options.apiKey || getApiKey();
70
+ const baseUrl = options.baseUrl || getBaseUrl();
71
+ if (!apiKey) {
72
+ error("No Zymbly API key configured. Use config set-key or set ZYMBLY_API_KEY.");
73
+ process.exit(1);
74
+ }
75
+ return new ZymblyClient({ apiKey, baseUrl });
76
+ }
77
+
78
+ async function run(command: Command, action: (client: ZymblyClient) => Promise<unknown>): Promise<void> {
79
+ try {
80
+ print(await action(getClient(command)), getFormat(command));
81
+ } catch (err) {
82
+ error(err instanceof Error ? err.message : String(err));
83
+ process.exit(1);
84
+ }
85
+ }
86
+
87
+ const program = new Command()
88
+ .name("connect-zymbly")
89
+ .description("Zymbly aircraft maintenance API connector")
90
+ .version(VERSION)
91
+ .option("-k, --api-key <key>", "Zymbly API key")
92
+ .option("--base-url <url>", "API base URL", DEFAULT_BASE_URL)
93
+ .option("-f, --format <format>", "Output format: json or pretty", "pretty");
94
+
95
+ const config = program.command("config").description("Manage local configuration");
96
+ config.command("set-key <key>").description("Save API key").action((key: string) => {
97
+ setApiKey(key);
98
+ success("Zymbly API key saved");
99
+ });
100
+ config.command("set-base-url <url>").description("Save API base URL").action((url: string) => {
101
+ setBaseUrl(url);
102
+ success("Zymbly base URL saved");
103
+ });
104
+ config.command("show").description("Show current configuration").action(() => {
105
+ const key = getApiKey();
106
+ print({
107
+ configPath: getConfigPath(),
108
+ baseUrl: getBaseUrl() || DEFAULT_BASE_URL,
109
+ apiKey: key ? `${key.slice(0, 6)}...` : null,
110
+ });
111
+ });
112
+ config.command("clear").description("Clear local configuration").action(() => {
113
+ clearConfig();
114
+ success("Zymbly configuration cleared");
115
+ });
116
+
117
+ const workOrders = program.command("work-orders").description("Manage work orders");
118
+ workOrders
119
+ .command("list")
120
+ .description("List work orders")
121
+ .option("-q, --query <json>", "Query params JSON object")
122
+ .action((opts, cmd) => run(cmd, (client) => client.listWorkOrders(parseQueryParams(opts.query))));
123
+ workOrders
124
+ .command("get <workOrderId>")
125
+ .description("Get a work order by ID")
126
+ .action((workOrderId: string, _opts, cmd) => run(cmd, (client) => client.getWorkOrder(workOrderId)));
127
+
128
+ const parts = program.command("parts").description("Search aircraft parts");
129
+ parts
130
+ .command("search")
131
+ .description("Search parts catalog")
132
+ .option("-q, --query <json>", "Query params JSON object")
133
+ .action((opts, cmd) => run(cmd, (client) => client.searchParts(parseQueryParams(opts.query))));
134
+
135
+ const notes = program.command("notes").description("Maintenance notes");
136
+ notes
137
+ .command("create <workOrderId>")
138
+ .description("Create a maintenance note on a work order")
139
+ .requiredOption("-n, --note <text>", "Note text")
140
+ .action((workOrderId: string, opts, cmd) => run(cmd, (client) => client.createMaintenanceNote(workOrderId, opts.note)));
141
+
142
+ program
143
+ .command("raw <method> <path>")
144
+ .description("Call a raw Zymbly API path")
145
+ .option("-b, --body <json>", "JSON body")
146
+ .option("-q, --query <json>", "Query params JSON object")
147
+ .action((method: string, path: string, opts, cmd) =>
148
+ run(cmd, (client) =>
149
+ client.rawRequest(method.toUpperCase() as HttpMethod, path, {
150
+ body: opts.body ? parseJson(opts.body, "body") : undefined,
151
+ query: parseQueryParams(opts.query),
152
+ }),
153
+ ),
154
+ );
155
+
156
+ program.parse();
@@ -0,0 +1,12 @@
1
+ export { ZymblyClient } from "./api";
2
+ export type {
3
+ HttpMethod,
4
+ JsonObject,
5
+ JsonPrimitive,
6
+ JsonValue,
7
+ OutputFormat,
8
+ QueryParams,
9
+ RequestOptions,
10
+ ZymblyConfig,
11
+ } from "./types";
12
+ export { ZymblyApiError } from "./types";
@@ -0,0 +1,34 @@
1
+ export type JsonPrimitive = string | number | boolean | null;
2
+ export type JsonValue = JsonPrimitive | JsonObject | JsonValue[];
3
+ export interface JsonObject {
4
+ [key: string]: JsonValue | undefined;
5
+ }
6
+
7
+ export type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
8
+ export type OutputFormat = "json" | "pretty";
9
+ export type QueryValue = string | number | boolean | null | undefined;
10
+ export type QueryParams = Record<string, QueryValue | QueryValue[]>;
11
+
12
+ export interface ZymblyConfig {
13
+ apiKey?: string;
14
+ baseUrl?: string;
15
+ }
16
+
17
+ export interface RequestOptions {
18
+ method?: HttpMethod;
19
+ body?: JsonValue | string;
20
+ headers?: Record<string, string>;
21
+ query?: QueryParams;
22
+ auth?: boolean;
23
+ }
24
+
25
+ export class ZymblyApiError extends Error {
26
+ constructor(
27
+ message: string,
28
+ public readonly status: number,
29
+ public readonly details?: unknown,
30
+ ) {
31
+ super(message);
32
+ this.name = "ZymblyApiError";
33
+ }
34
+ }
@@ -0,0 +1,52 @@
1
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+
5
+ interface StoredConfig {
6
+ apiKey?: string;
7
+ baseUrl?: string;
8
+ }
9
+
10
+ const CONFIG_PATH = join(homedir(), ".config", "hasna-connectors", "zymbly.json");
11
+
12
+ function readConfig(): StoredConfig {
13
+ if (!existsSync(CONFIG_PATH)) {
14
+ return {};
15
+ }
16
+ try {
17
+ return JSON.parse(readFileSync(CONFIG_PATH, "utf8")) as StoredConfig;
18
+ } catch {
19
+ return {};
20
+ }
21
+ }
22
+
23
+ function writeConfig(config: StoredConfig): void {
24
+ mkdirSync(dirname(CONFIG_PATH), { recursive: true });
25
+ writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2));
26
+ }
27
+
28
+ export function getConfigPath(): string {
29
+ return CONFIG_PATH;
30
+ }
31
+
32
+ export function getApiKey(): string | undefined {
33
+ return process.env.ZYMBLY_API_KEY || readConfig().apiKey;
34
+ }
35
+
36
+ export function getBaseUrl(): string | undefined {
37
+ return process.env.ZYMBLY_BASE_URL || readConfig().baseUrl;
38
+ }
39
+
40
+ export function setApiKey(apiKey: string): void {
41
+ writeConfig({ ...readConfig(), apiKey });
42
+ }
43
+
44
+ export function setBaseUrl(baseUrl: string): void {
45
+ writeConfig({ ...readConfig(), baseUrl });
46
+ }
47
+
48
+ export function clearConfig(): void {
49
+ if (existsSync(CONFIG_PATH)) {
50
+ rmSync(CONFIG_PATH);
51
+ }
52
+ }
@@ -0,0 +1,17 @@
1
+ import type { OutputFormat } from "../types";
2
+
3
+ export function print(data: unknown, format: OutputFormat = "pretty"): void {
4
+ if (format === "json") {
5
+ console.log(JSON.stringify(data));
6
+ return;
7
+ }
8
+ console.log(JSON.stringify(data, null, 2));
9
+ }
10
+
11
+ export function error(message: string): void {
12
+ console.error(message);
13
+ }
14
+
15
+ export function success(message: string): void {
16
+ console.log(message);
17
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "strict": true,
7
+ "declaration": true,
8
+ "outDir": "dist",
9
+ "skipLibCheck": true,
10
+ "types": ["bun-types"]
11
+ },
12
+ "include": ["src/**/*"]
13
+ }
package/dist/index.js CHANGED
@@ -5764,7 +5764,7 @@ function extractGoogleError(body) {
5764
5764
  // package.json
5765
5765
  var package_default = {
5766
5766
  name: "@hasna/connectors",
5767
- version: "1.3.45",
5767
+ version: "1.3.46",
5768
5768
  description: "Open source connector library - Install API connectors with a single command",
5769
5769
  type: "module",
5770
5770
  bin: {
@@ -5796,11 +5796,12 @@ var package_default = {
5796
5796
  "build:dashboard": "cd dashboard && bun run build",
5797
5797
  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)',
5798
5798
  dev: "bun run ./src/cli/index.tsx",
5799
+ "check:package-secrets": "bun run scripts/check-package-secrets.ts",
5799
5800
  typecheck: "tsc --noEmit && tsc -p tsconfig.social.json --noEmit",
5800
5801
  test: "bun test",
5801
5802
  "secrets:scan:npmrc": "bun run scripts/scan-npmrc-auth.mjs",
5802
5803
  "sdk:build": "cd sdk && bun run build",
5803
- prepublishOnly: "bun run secrets:scan:npmrc && bun run build && bun test"
5804
+ prepublishOnly: "bun run secrets:scan:npmrc && bun run check:package-secrets && bun run build && bun test"
5804
5805
  },
5805
5806
  keywords: [
5806
5807
  "connectors",
@@ -18603,6 +18604,13 @@ var connectors = [
18603
18604
  category: "AI & ML",
18604
18605
  tags: ["transcription", "meetings", "ai"]
18605
18606
  },
18607
+ {
18608
+ name: "wandb",
18609
+ displayName: "Weights & Biases",
18610
+ description: "ML experiment tracking and run management via GraphQL",
18611
+ category: "AI & ML",
18612
+ tags: ["ml", "experiments", "tracking"]
18613
+ },
18606
18614
  {
18607
18615
  name: "wato",
18608
18616
  displayName: "Wato",
@@ -18610,6 +18618,13 @@ var connectors = [
18610
18618
  category: "AI & ML",
18611
18619
  tags: ["ai", "agents", "memory", "workflows"]
18612
18620
  },
18621
+ {
18622
+ name: "weights-biases",
18623
+ displayName: "Weights & Biases",
18624
+ description: "ML experiment tracking (runs, events, search)",
18625
+ category: "AI & ML",
18626
+ tags: ["ai", "ml", "wandb", "experiment-tracking"]
18627
+ },
18613
18628
  {
18614
18629
  name: "wavelineextract",
18615
18630
  displayName: "Waveline Extract",
@@ -20248,6 +20263,20 @@ var connectors3 = [
20248
20263
  description: "HR platform for employees, leave, attendance, and timesheets",
20249
20264
  category: "Business Tools",
20250
20265
  tags: ["hr", "employees", "zoho"]
20266
+ },
20267
+ {
20268
+ name: "zymbly",
20269
+ displayName: "Zymbly",
20270
+ description: "Aircraft maintenance and CMMS platform for work orders, parts, and maintenance notes",
20271
+ category: "Business Tools",
20272
+ tags: ["maintenance", "aircraft", "work-orders", "cmms"]
20273
+ },
20274
+ {
20275
+ name: "zotero",
20276
+ displayName: "Zotero",
20277
+ description: "Bibliography and reference library API for items, collections, and attachments",
20278
+ category: "Business Tools",
20279
+ tags: ["bibliography", "citations", "research", "library", "references"]
20251
20280
  }
20252
20281
  ];
20253
20282
 
@@ -22758,6 +22787,13 @@ var connectors9 = [
22758
22787
  category: "Developer Tools",
22759
22788
  tags: ["cdn", "dns", "edge"]
22760
22789
  },
22790
+ {
22791
+ name: "cloudflare-workers",
22792
+ displayName: "Cloudflare Workers",
22793
+ 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",
22794
+ category: "Developer Tools",
22795
+ tags: ["cloudflare", "workers", "serverless", "edge", "deployments", "developer-tools"]
22796
+ },
22761
22797
  {
22762
22798
  name: "googlecloud",
22763
22799
  displayName: "Google Cloud",
@@ -25150,6 +25186,13 @@ var connectors14 = [
25150
25186
  description: "Reviews and user-generated content platform for e-commerce",
25151
25187
  category: "Marketing & Sales",
25152
25188
  tags: ["reviews", "ugc", "ecommerce", "marketing"]
25189
+ },
25190
+ {
25191
+ name: "zoominfo",
25192
+ displayName: "ZoomInfo",
25193
+ description: "ZoomInfo B2B sales intelligence API for contact and company search, enrichment, lookup, and output field discovery",
25194
+ category: "Marketing & Sales",
25195
+ tags: ["sales-intelligence", "enrichment", "contacts", "companies", "b2b"]
25153
25196
  }
25154
25197
  ];
25155
25198
 
@@ -0,0 +1,40 @@
1
+ import type { ConnectorMeta } from "./registry.js";
2
+ export declare const DEFAULT_COMPACT_LIMIT = 20;
3
+ export declare const DEFAULT_MCP_LIMIT = 20;
4
+ export declare const MAX_COMPACT_LIMIT = 100;
5
+ export declare const DEFAULT_TEXT_WIDTH = 96;
6
+ export declare const DEFAULT_OUTPUT_CHARS = 6000;
7
+ export type ParseIntResult = {
8
+ value: number | undefined;
9
+ error?: string;
10
+ };
11
+ export declare function parseNonNegativeInt(raw: string | undefined, flag: string): ParseIntResult;
12
+ export declare function normalizeLimit(value: number | undefined, fallback: number, max?: number): number;
13
+ export declare function parseCursor(raw: string | undefined): ParseIntResult;
14
+ export declare function pageItems<T>(items: T[], options: {
15
+ offset?: number;
16
+ limit?: number;
17
+ }): {
18
+ items: T[];
19
+ total: number;
20
+ offset: number;
21
+ limit: number | null;
22
+ nextOffset: number | null;
23
+ };
24
+ export declare function truncateText(value: string | undefined, max?: number): string;
25
+ export declare function firstNonEmptyLines(value: string | undefined, maxLines: number, maxWidth?: number): string[];
26
+ export declare function compactConnector(connector: ConnectorMeta, descriptionWidth?: number): {
27
+ name: string;
28
+ displayName: string;
29
+ version: string | undefined;
30
+ category: string;
31
+ description: string;
32
+ };
33
+ export declare function maybeTruncateOutput(text: string, options?: {
34
+ maxChars?: number;
35
+ enabled?: boolean;
36
+ hint?: string;
37
+ }): {
38
+ text: string;
39
+ truncated: boolean;
40
+ };
@@ -1,7 +1,39 @@
1
1
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { type WorkflowResult } from "../../lib/workflow-runner.js";
3
+ import { triggerJob } from "../../lib/scheduler.js";
4
+ type JobExecutionResult = Awaited<ReturnType<typeof triggerJob>>;
5
+ type ExecutionCompactOptions = {
6
+ verbose?: boolean;
7
+ maxOutputChars?: number;
8
+ };
9
+ export declare function compactJobExecutionResult(result: JobExecutionResult, options?: ExecutionCompactOptions): {
10
+ output: string;
11
+ outputTruncated: boolean;
12
+ hint: string | undefined;
13
+ run_id: string;
14
+ exit_code: number;
15
+ };
16
+ export declare function compactWorkflowExecutionResult(result: WorkflowResult, options?: ExecutionCompactOptions): {
17
+ steps: {
18
+ output: string;
19
+ outputTruncated: boolean;
20
+ step: number;
21
+ connector: string;
22
+ command: string;
23
+ exit_code: number;
24
+ }[];
25
+ final_output: string;
26
+ finalOutputTruncated: boolean;
27
+ truncatedOutputs: number;
28
+ hint: string | undefined;
29
+ workflow_id: string;
30
+ workflow_name: string;
31
+ success: boolean;
32
+ };
2
33
  export declare function registerJobsTools(server: McpServer, stripped: (text: string) => Promise<{
3
34
  content: {
4
35
  type: "text";
5
36
  text: string;
6
37
  }[];
7
38
  }>): void;
39
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/connectors",
3
- "version": "1.3.45",
3
+ "version": "1.3.46",
4
4
  "description": "Open source connector library - Install API connectors with a single command",
5
5
  "type": "module",
6
6
  "bin": {
@@ -32,11 +32,12 @@
32
32
  "build:dashboard": "cd dashboard && bun run build",
33
33
  "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)",
34
34
  "dev": "bun run ./src/cli/index.tsx",
35
+ "check:package-secrets": "bun run scripts/check-package-secrets.ts",
35
36
  "typecheck": "tsc --noEmit && tsc -p tsconfig.social.json --noEmit",
36
37
  "test": "bun test",
37
38
  "secrets:scan:npmrc": "bun run scripts/scan-npmrc-auth.mjs",
38
39
  "sdk:build": "cd sdk && bun run build",
39
- "prepublishOnly": "bun run secrets:scan:npmrc && bun run build && bun test"
40
+ "prepublishOnly": "bun run secrets:scan:npmrc && bun run check:package-secrets && bun run build && bun test"
40
41
  },
41
42
  "keywords": [
42
43
  "connectors",