@kadoa/mcp 0.5.20 → 0.5.22
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.
- package/README.md +18 -10
- package/dist/index.js +360 -36
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -68,6 +68,7 @@ Point your client to `https://mcp.kadoa.com/mcp` with OAuth authentication.
|
|
|
68
68
|
| `get_workflow` | Get canonical intent, Assistant/session, template ownership, run health, schedule, location, monitoring, and validation details |
|
|
69
69
|
| `request_workflow_update` | Ask the workflow Assistant to change extraction intent, navigation, sourcing, pagination, or generated behavior without changing the workflow ID |
|
|
70
70
|
| `get_workflow_assistant` | Get the workflow Assistant's current activity and any pending clarification question |
|
|
71
|
+
| `get_workflow_assistant_timeline` | Read paginated customer-visible Assistant messages and questions for Lighthouse or Julie |
|
|
71
72
|
| `answer_workflow_assistant_question` | Answer the workflow Assistant's current clarification question and resume it |
|
|
72
73
|
| `interrupt_workflow_assistant` | Safely interrupt active Assistant work without pausing the workflow schedule |
|
|
73
74
|
| `resume_workflow_assistant` | Resume an idle/interrupted Lighthouse or Julie session with its persisted persona |
|
|
@@ -127,9 +128,10 @@ to retrieve the extracted records and display them as a table.
|
|
|
127
128
|
> You: Use my "Product Scraper" template to scrape https://example-shop.com.
|
|
128
129
|
|
|
129
130
|
Claude calls list_templates to find the matching template, then
|
|
130
|
-
create_workflow with `templateId` and `urls` only
|
|
131
|
-
schema
|
|
132
|
-
ID for follow-up with get_workflow
|
|
131
|
+
create_workflow with `templateId` and `urls` only - never copy the prompt,
|
|
132
|
+
entity, or schema into standalone creation. Those values are inherited from
|
|
133
|
+
the template version. Returns the workflow ID for follow-up with get_workflow
|
|
134
|
+
or fetch_data.
|
|
133
135
|
```
|
|
134
136
|
|
|
135
137
|
### Update a workflow and re-run
|
|
@@ -148,8 +150,10 @@ changes, and shows the updated field list.
|
|
|
148
150
|
|
|
149
151
|
> You: Run it again with the new schema.
|
|
150
152
|
|
|
151
|
-
Claude calls run_workflow and
|
|
152
|
-
|
|
153
|
+
Claude calls run_workflow and returns the workflow ID while the run proceeds
|
|
154
|
+
asynchronously. Check back later with get_workflow or fetch_data. If a
|
|
155
|
+
one-time or scheduled workflow fails, call run_workflow again with the same
|
|
156
|
+
workflow ID and configuration - never delete and recreate it just to retry.
|
|
153
157
|
```
|
|
154
158
|
|
|
155
159
|
### Update deterministic workflow settings
|
|
@@ -188,9 +192,11 @@ Assistant session, thread, and job identifiers.
|
|
|
188
192
|
|
|
189
193
|
> You: Does Kadoa need anything from me?
|
|
190
194
|
|
|
191
|
-
Claude calls get_workflow_assistant.
|
|
192
|
-
|
|
193
|
-
|
|
195
|
+
Claude calls get_workflow_assistant. To review the conversation, Claude calls
|
|
196
|
+
get_workflow_assistant_timeline and follows its opaque nextCursor only when
|
|
197
|
+
older messages are needed. If a clarification is pending, Claude shows the
|
|
198
|
+
question and calls answer_workflow_assistant_question with your answer. It does
|
|
199
|
+
not poll or sleep-wait for the Assistant.
|
|
194
200
|
|
|
195
201
|
> You: How does this workflow extract the data now?
|
|
196
202
|
|
|
@@ -247,14 +253,16 @@ Relevant files in `kadoa-backend`:
|
|
|
247
253
|
|
|
248
254
|
1. Merge PRs to `main` using Conventional Commits (`feat:`, `fix:`, etc.). Release Please opens/maintains a `chore(main): release mcp x.y.z` PR.
|
|
249
255
|
2. Merge the release PR. The [`release-please.yml`](.github/workflows/release-please.yml) workflow tags, drafts a GitHub Release, and publishes to npm (`latest` dist-tag).
|
|
250
|
-
3.
|
|
251
|
-
4. Merge to `main`. CI (`main-build-deploy.yml`) builds and pushes `europe-west3-docker.pkg.dev/oceanic-base-310208/kadoa-artifacts/mcp-server:<IMAGE_TAG>` (tag shown in the build summary).
|
|
256
|
+
3. After npm publication, `release-please.yml` opens or updates a deterministic PR in `kadoa-backend` that bumps `infra/docker/mcp/package.json` and refreshes `bun.lock`. The PR validates a frozen production install and Docker image build, and remains manually mergeable.
|
|
257
|
+
4. Merge the backend PR to `main`. CI (`main-build-deploy.yml`) builds and pushes `europe-west3-docker.pkg.dev/oceanic-base-310208/kadoa-artifacts/mcp-server:<IMAGE_TAG>` (tag shown in the build summary).
|
|
252
258
|
5. Trigger the **Deploy to Production** workflow ([`deploy-prod.yml`](https://github.com/kadoa-org/kadoa-backend/actions/workflows/deploy-prod.yml)) with:
|
|
253
259
|
- **Target cluster:** `gcp`
|
|
254
260
|
- **Deployment scope:** `mcp`
|
|
255
261
|
- **Image tag:** the tag from step 4
|
|
256
262
|
- **Method:** `kubectl`
|
|
257
263
|
|
|
264
|
+
The cross-repository bump requires the `BACKEND_REPO_TOKEN` secret in this repository. The selected authentication approach is a fine-grained PAT scoped only to `kadoa-org/kadoa-backend` with Contents read/write and Pull requests read/write permissions (Metadata read is automatic). If the secret is not provisioned, the release workflow skips the backend bump with a warning rather than failing npm releases; an administrator must provision it before relying on automatic hosted-server updates.
|
|
265
|
+
|
|
258
266
|
### RC / test release
|
|
259
267
|
|
|
260
268
|
Use this when you want to validate a change end-to-end against real clients (Claude Desktop, Cursor, ChatGPT) before promoting to `latest` / prod. The flow mirrors the prod one, but every step targets `rc` channels.
|
package/dist/index.js
CHANGED
|
@@ -45783,6 +45783,14 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
45783
45783
|
}
|
|
45784
45784
|
return data;
|
|
45785
45785
|
}
|
|
45786
|
+
async getTimeline(workflowId, input = {}) {
|
|
45787
|
+
const response = await this.agentApi.v5AgentWorkflowAssistantTimeline({
|
|
45788
|
+
workflowId,
|
|
45789
|
+
...input.cursor != null && { cursor: input.cursor },
|
|
45790
|
+
...input.limit != null && { limit: input.limit }
|
|
45791
|
+
});
|
|
45792
|
+
return response.data.data;
|
|
45793
|
+
}
|
|
45786
45794
|
async getPauseState(sessionId) {
|
|
45787
45795
|
const response = await this.agentApi.v5AgentPauseState({ sessionId });
|
|
45788
45796
|
return response.data.data;
|
|
@@ -46050,6 +46058,32 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
46050
46058
|
url: toPathString(localVarUrlObj),
|
|
46051
46059
|
options: localVarRequestOptions
|
|
46052
46060
|
};
|
|
46061
|
+
},
|
|
46062
|
+
v5AgentWorkflowAssistantTimeline: async (workflowId, cursor, limit, options = {}) => {
|
|
46063
|
+
assertParamExists("v5AgentWorkflowAssistantTimeline", "workflowId", workflowId);
|
|
46064
|
+
const localVarPath = `/v5/agent/workflows/{workflowId}/timeline`.replace(`{${"workflowId"}}`, encodeURIComponent(String(workflowId)));
|
|
46065
|
+
const localVarUrlObj = new URL$1(localVarPath, DUMMY_BASE_URL);
|
|
46066
|
+
let baseOptions;
|
|
46067
|
+
if (configuration) {
|
|
46068
|
+
baseOptions = configuration.baseOptions;
|
|
46069
|
+
}
|
|
46070
|
+
const localVarRequestOptions = { method: "GET", ...baseOptions, ...options };
|
|
46071
|
+
const localVarHeaderParameter = {};
|
|
46072
|
+
const localVarQueryParameter = {};
|
|
46073
|
+
if (cursor !== undefined) {
|
|
46074
|
+
localVarQueryParameter["cursor"] = cursor;
|
|
46075
|
+
}
|
|
46076
|
+
if (limit !== undefined) {
|
|
46077
|
+
localVarQueryParameter["limit"] = limit;
|
|
46078
|
+
}
|
|
46079
|
+
localVarHeaderParameter["Accept"] = "application/json";
|
|
46080
|
+
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
|
46081
|
+
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
|
46082
|
+
localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
|
|
46083
|
+
return {
|
|
46084
|
+
url: toPathString(localVarUrlObj),
|
|
46085
|
+
options: localVarRequestOptions
|
|
46086
|
+
};
|
|
46053
46087
|
}
|
|
46054
46088
|
};
|
|
46055
46089
|
}, AgentApiFp = function(configuration) {
|
|
@@ -46102,6 +46136,12 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
46102
46136
|
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
46103
46137
|
const localVarOperationServerBasePath = operationServerMap["AgentApi.v5AgentWorkflowAssistantMessage"]?.[localVarOperationServerIndex]?.url;
|
|
46104
46138
|
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
46139
|
+
},
|
|
46140
|
+
async v5AgentWorkflowAssistantTimeline(workflowId, cursor, limit, options) {
|
|
46141
|
+
const localVarAxiosArgs = await localVarAxiosParamCreator.v5AgentWorkflowAssistantTimeline(workflowId, cursor, limit, options);
|
|
46142
|
+
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
46143
|
+
const localVarOperationServerBasePath = operationServerMap["AgentApi.v5AgentWorkflowAssistantTimeline"]?.[localVarOperationServerIndex]?.url;
|
|
46144
|
+
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
46105
46145
|
}
|
|
46106
46146
|
};
|
|
46107
46147
|
}, AgentApi, CrawlerApiAxiosParamCreator = function(configuration) {
|
|
@@ -48157,6 +48197,113 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
48157
48197
|
};
|
|
48158
48198
|
}, TemplatesApi, VariablesApiAxiosParamCreator = function(configuration) {
|
|
48159
48199
|
return {
|
|
48200
|
+
v4VariablesConnectionsConnectionIdDelete: async (connectionId, options = {}) => {
|
|
48201
|
+
assertParamExists("v4VariablesConnectionsConnectionIdDelete", "connectionId", connectionId);
|
|
48202
|
+
const localVarPath = `/v4/variables/connections/{connectionId}`.replace(`{${"connectionId"}}`, encodeURIComponent(String(connectionId)));
|
|
48203
|
+
const localVarUrlObj = new URL$1(localVarPath, DUMMY_BASE_URL);
|
|
48204
|
+
let baseOptions;
|
|
48205
|
+
if (configuration) {
|
|
48206
|
+
baseOptions = configuration.baseOptions;
|
|
48207
|
+
}
|
|
48208
|
+
const localVarRequestOptions = { method: "DELETE", ...baseOptions, ...options };
|
|
48209
|
+
const localVarHeaderParameter = {};
|
|
48210
|
+
const localVarQueryParameter = {};
|
|
48211
|
+
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration);
|
|
48212
|
+
localVarHeaderParameter["Accept"] = "application/json";
|
|
48213
|
+
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
|
48214
|
+
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
|
48215
|
+
localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
|
|
48216
|
+
return {
|
|
48217
|
+
url: toPathString(localVarUrlObj),
|
|
48218
|
+
options: localVarRequestOptions
|
|
48219
|
+
};
|
|
48220
|
+
},
|
|
48221
|
+
v4VariablesConnectionsConnectionIdPatch: async (connectionId, v4VariablesConnectionsConnectionIdPatchRequest, options = {}) => {
|
|
48222
|
+
assertParamExists("v4VariablesConnectionsConnectionIdPatch", "connectionId", connectionId);
|
|
48223
|
+
const localVarPath = `/v4/variables/connections/{connectionId}`.replace(`{${"connectionId"}}`, encodeURIComponent(String(connectionId)));
|
|
48224
|
+
const localVarUrlObj = new URL$1(localVarPath, DUMMY_BASE_URL);
|
|
48225
|
+
let baseOptions;
|
|
48226
|
+
if (configuration) {
|
|
48227
|
+
baseOptions = configuration.baseOptions;
|
|
48228
|
+
}
|
|
48229
|
+
const localVarRequestOptions = { method: "PATCH", ...baseOptions, ...options };
|
|
48230
|
+
const localVarHeaderParameter = {};
|
|
48231
|
+
const localVarQueryParameter = {};
|
|
48232
|
+
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration);
|
|
48233
|
+
localVarHeaderParameter["Content-Type"] = "application/json";
|
|
48234
|
+
localVarHeaderParameter["Accept"] = "application/json";
|
|
48235
|
+
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
|
48236
|
+
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
|
48237
|
+
localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
|
|
48238
|
+
localVarRequestOptions.data = serializeDataIfNeeded(v4VariablesConnectionsConnectionIdPatchRequest, localVarRequestOptions, configuration);
|
|
48239
|
+
return {
|
|
48240
|
+
url: toPathString(localVarUrlObj),
|
|
48241
|
+
options: localVarRequestOptions
|
|
48242
|
+
};
|
|
48243
|
+
},
|
|
48244
|
+
v4VariablesConnectionsConnectionIdVerifyPost: async (connectionId, options = {}) => {
|
|
48245
|
+
assertParamExists("v4VariablesConnectionsConnectionIdVerifyPost", "connectionId", connectionId);
|
|
48246
|
+
const localVarPath = `/v4/variables/connections/{connectionId}/verify`.replace(`{${"connectionId"}}`, encodeURIComponent(String(connectionId)));
|
|
48247
|
+
const localVarUrlObj = new URL$1(localVarPath, DUMMY_BASE_URL);
|
|
48248
|
+
let baseOptions;
|
|
48249
|
+
if (configuration) {
|
|
48250
|
+
baseOptions = configuration.baseOptions;
|
|
48251
|
+
}
|
|
48252
|
+
const localVarRequestOptions = { method: "POST", ...baseOptions, ...options };
|
|
48253
|
+
const localVarHeaderParameter = {};
|
|
48254
|
+
const localVarQueryParameter = {};
|
|
48255
|
+
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration);
|
|
48256
|
+
localVarHeaderParameter["Accept"] = "application/json";
|
|
48257
|
+
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
|
48258
|
+
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
|
48259
|
+
localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
|
|
48260
|
+
return {
|
|
48261
|
+
url: toPathString(localVarUrlObj),
|
|
48262
|
+
options: localVarRequestOptions
|
|
48263
|
+
};
|
|
48264
|
+
},
|
|
48265
|
+
v4VariablesConnectionsGet: async (options = {}) => {
|
|
48266
|
+
const localVarPath = `/v4/variables/connections`;
|
|
48267
|
+
const localVarUrlObj = new URL$1(localVarPath, DUMMY_BASE_URL);
|
|
48268
|
+
let baseOptions;
|
|
48269
|
+
if (configuration) {
|
|
48270
|
+
baseOptions = configuration.baseOptions;
|
|
48271
|
+
}
|
|
48272
|
+
const localVarRequestOptions = { method: "GET", ...baseOptions, ...options };
|
|
48273
|
+
const localVarHeaderParameter = {};
|
|
48274
|
+
const localVarQueryParameter = {};
|
|
48275
|
+
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration);
|
|
48276
|
+
localVarHeaderParameter["Accept"] = "application/json";
|
|
48277
|
+
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
|
48278
|
+
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
|
48279
|
+
localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
|
|
48280
|
+
return {
|
|
48281
|
+
url: toPathString(localVarUrlObj),
|
|
48282
|
+
options: localVarRequestOptions
|
|
48283
|
+
};
|
|
48284
|
+
},
|
|
48285
|
+
v4VariablesConnectionsPost: async (v4VariablesConnectionsPostRequest, options = {}) => {
|
|
48286
|
+
const localVarPath = `/v4/variables/connections`;
|
|
48287
|
+
const localVarUrlObj = new URL$1(localVarPath, DUMMY_BASE_URL);
|
|
48288
|
+
let baseOptions;
|
|
48289
|
+
if (configuration) {
|
|
48290
|
+
baseOptions = configuration.baseOptions;
|
|
48291
|
+
}
|
|
48292
|
+
const localVarRequestOptions = { method: "POST", ...baseOptions, ...options };
|
|
48293
|
+
const localVarHeaderParameter = {};
|
|
48294
|
+
const localVarQueryParameter = {};
|
|
48295
|
+
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration);
|
|
48296
|
+
localVarHeaderParameter["Content-Type"] = "application/json";
|
|
48297
|
+
localVarHeaderParameter["Accept"] = "application/json";
|
|
48298
|
+
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
|
48299
|
+
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
|
48300
|
+
localVarRequestOptions.headers = { ...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers };
|
|
48301
|
+
localVarRequestOptions.data = serializeDataIfNeeded(v4VariablesConnectionsPostRequest, localVarRequestOptions, configuration);
|
|
48302
|
+
return {
|
|
48303
|
+
url: toPathString(localVarUrlObj),
|
|
48304
|
+
options: localVarRequestOptions
|
|
48305
|
+
};
|
|
48306
|
+
},
|
|
48160
48307
|
v4VariablesGet: async (options = {}) => {
|
|
48161
48308
|
const localVarPath = `/v4/variables/`;
|
|
48162
48309
|
const localVarUrlObj = new URL$1(localVarPath, DUMMY_BASE_URL);
|
|
@@ -48268,6 +48415,36 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
48268
48415
|
}, VariablesApiFp = function(configuration) {
|
|
48269
48416
|
const localVarAxiosParamCreator = VariablesApiAxiosParamCreator(configuration);
|
|
48270
48417
|
return {
|
|
48418
|
+
async v4VariablesConnectionsConnectionIdDelete(connectionId, options) {
|
|
48419
|
+
const localVarAxiosArgs = await localVarAxiosParamCreator.v4VariablesConnectionsConnectionIdDelete(connectionId, options);
|
|
48420
|
+
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
48421
|
+
const localVarOperationServerBasePath = operationServerMap["VariablesApi.v4VariablesConnectionsConnectionIdDelete"]?.[localVarOperationServerIndex]?.url;
|
|
48422
|
+
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
48423
|
+
},
|
|
48424
|
+
async v4VariablesConnectionsConnectionIdPatch(connectionId, v4VariablesConnectionsConnectionIdPatchRequest, options) {
|
|
48425
|
+
const localVarAxiosArgs = await localVarAxiosParamCreator.v4VariablesConnectionsConnectionIdPatch(connectionId, v4VariablesConnectionsConnectionIdPatchRequest, options);
|
|
48426
|
+
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
48427
|
+
const localVarOperationServerBasePath = operationServerMap["VariablesApi.v4VariablesConnectionsConnectionIdPatch"]?.[localVarOperationServerIndex]?.url;
|
|
48428
|
+
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
48429
|
+
},
|
|
48430
|
+
async v4VariablesConnectionsConnectionIdVerifyPost(connectionId, options) {
|
|
48431
|
+
const localVarAxiosArgs = await localVarAxiosParamCreator.v4VariablesConnectionsConnectionIdVerifyPost(connectionId, options);
|
|
48432
|
+
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
48433
|
+
const localVarOperationServerBasePath = operationServerMap["VariablesApi.v4VariablesConnectionsConnectionIdVerifyPost"]?.[localVarOperationServerIndex]?.url;
|
|
48434
|
+
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
48435
|
+
},
|
|
48436
|
+
async v4VariablesConnectionsGet(options) {
|
|
48437
|
+
const localVarAxiosArgs = await localVarAxiosParamCreator.v4VariablesConnectionsGet(options);
|
|
48438
|
+
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
48439
|
+
const localVarOperationServerBasePath = operationServerMap["VariablesApi.v4VariablesConnectionsGet"]?.[localVarOperationServerIndex]?.url;
|
|
48440
|
+
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
48441
|
+
},
|
|
48442
|
+
async v4VariablesConnectionsPost(v4VariablesConnectionsPostRequest, options) {
|
|
48443
|
+
const localVarAxiosArgs = await localVarAxiosParamCreator.v4VariablesConnectionsPost(v4VariablesConnectionsPostRequest, options);
|
|
48444
|
+
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
48445
|
+
const localVarOperationServerBasePath = operationServerMap["VariablesApi.v4VariablesConnectionsPost"]?.[localVarOperationServerIndex]?.url;
|
|
48446
|
+
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
48447
|
+
},
|
|
48271
48448
|
async v4VariablesGet(options) {
|
|
48272
48449
|
const localVarAxiosArgs = await localVarAxiosParamCreator.v4VariablesGet(options);
|
|
48273
48450
|
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
@@ -50422,7 +50599,7 @@ var import_debug, __require2, FREEFORM_ASSISTANT_ANSWER_KEY = "_freeform", Kadoa
|
|
|
50422
50599
|
}));
|
|
50423
50600
|
return channels;
|
|
50424
50601
|
}
|
|
50425
|
-
}, PUBLIC_API_URI, WSS_API_URI, REALTIME_API_URI, SDK_VERSION = "0.
|
|
50602
|
+
}, PUBLIC_API_URI, WSS_API_URI, REALTIME_API_URI, SDK_VERSION = "0.39.0", SDK_NAME = "kadoa-node-sdk", SDK_LANGUAGE = "node", debug6, isDrainControlMessage = (message) => message.type === "control.draining", isRealtimeEvent = (message) => message.type !== "heartbeat" && message.type !== "control.draining", _Realtime = class _Realtime2 {
|
|
50426
50603
|
constructor(config2) {
|
|
50427
50604
|
this.drainingSockets = /* @__PURE__ */ new Set;
|
|
50428
50605
|
this.lastHeartbeat = Date.now();
|
|
@@ -51864,6 +52041,9 @@ var init_dist2 = __esm(() => {
|
|
|
51864
52041
|
v5AgentWorkflowAssistantMessage(requestParameters, options) {
|
|
51865
52042
|
return AgentApiFp(this.configuration).v5AgentWorkflowAssistantMessage(requestParameters.workflowId, requestParameters.workflowAssistantMessageRequest, options).then((request) => request(this.axios, this.basePath));
|
|
51866
52043
|
}
|
|
52044
|
+
v5AgentWorkflowAssistantTimeline(requestParameters, options) {
|
|
52045
|
+
return AgentApiFp(this.configuration).v5AgentWorkflowAssistantTimeline(requestParameters.workflowId, requestParameters.cursor, requestParameters.limit, options).then((request) => request(this.axios, this.basePath));
|
|
52046
|
+
}
|
|
51867
52047
|
};
|
|
51868
52048
|
CrawlerApi = class extends BaseAPI {
|
|
51869
52049
|
v4CrawlBucketDataFilenameb64Get(requestParameters, options) {
|
|
@@ -52095,6 +52275,21 @@ var init_dist2 = __esm(() => {
|
|
|
52095
52275
|
}
|
|
52096
52276
|
};
|
|
52097
52277
|
VariablesApi = class extends BaseAPI {
|
|
52278
|
+
v4VariablesConnectionsConnectionIdDelete(requestParameters, options) {
|
|
52279
|
+
return VariablesApiFp(this.configuration).v4VariablesConnectionsConnectionIdDelete(requestParameters.connectionId, options).then((request) => request(this.axios, this.basePath));
|
|
52280
|
+
}
|
|
52281
|
+
v4VariablesConnectionsConnectionIdPatch(requestParameters, options) {
|
|
52282
|
+
return VariablesApiFp(this.configuration).v4VariablesConnectionsConnectionIdPatch(requestParameters.connectionId, requestParameters.v4VariablesConnectionsConnectionIdPatchRequest, options).then((request) => request(this.axios, this.basePath));
|
|
52283
|
+
}
|
|
52284
|
+
v4VariablesConnectionsConnectionIdVerifyPost(requestParameters, options) {
|
|
52285
|
+
return VariablesApiFp(this.configuration).v4VariablesConnectionsConnectionIdVerifyPost(requestParameters.connectionId, options).then((request) => request(this.axios, this.basePath));
|
|
52286
|
+
}
|
|
52287
|
+
v4VariablesConnectionsGet(options) {
|
|
52288
|
+
return VariablesApiFp(this.configuration).v4VariablesConnectionsGet(options).then((request) => request(this.axios, this.basePath));
|
|
52289
|
+
}
|
|
52290
|
+
v4VariablesConnectionsPost(requestParameters = {}, options) {
|
|
52291
|
+
return VariablesApiFp(this.configuration).v4VariablesConnectionsPost(requestParameters.v4VariablesConnectionsPostRequest, options).then((request) => request(this.axios, this.basePath));
|
|
52292
|
+
}
|
|
52098
52293
|
v4VariablesGet(options) {
|
|
52099
52294
|
return VariablesApiFp(this.configuration).v4VariablesGet(options).then((request) => request(this.axios, this.basePath));
|
|
52100
52295
|
}
|
|
@@ -52699,7 +52894,7 @@ function extractApiMessage(responseBody) {
|
|
|
52699
52894
|
if (body.validationErrors && typeof body.validationErrors === "object" && body.validationErrors !== null) {
|
|
52700
52895
|
const details = Object.entries(body.validationErrors).map(([field, err]) => `${field}: "${err}"`).join(", ");
|
|
52701
52896
|
if (details) {
|
|
52702
|
-
msg = msg ? `${msg}
|
|
52897
|
+
msg = msg ? `${msg} - Details: ${details}` : `Validation failed - Details: ${details}`;
|
|
52703
52898
|
}
|
|
52704
52899
|
}
|
|
52705
52900
|
if (!msg && Array.isArray(body.issues)) {
|
|
@@ -52709,7 +52904,7 @@ function extractApiMessage(responseBody) {
|
|
|
52709
52904
|
return path ? `${path}: "${message}"` : `"${message}"`;
|
|
52710
52905
|
}).join(", ");
|
|
52711
52906
|
if (details)
|
|
52712
|
-
msg = `Validation failed
|
|
52907
|
+
msg = `Validation failed - Details: ${details}`;
|
|
52713
52908
|
}
|
|
52714
52909
|
return msg;
|
|
52715
52910
|
}
|
|
@@ -52895,14 +53090,14 @@ function registerTools(server, ctx, capabilities) {
|
|
|
52895
53090
|
});
|
|
52896
53091
|
}));
|
|
52897
53092
|
const urlInputShape = {
|
|
52898
|
-
url: exports_external.string().optional().describe("Single URL
|
|
53093
|
+
url: exports_external.string().optional().describe("Single URL - prefer using 'urls' instead. If both are provided, 'urls' takes precedence."),
|
|
52899
53094
|
urls: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string()).min(1)).optional().describe("Starting URLs for the workflow (array of strings). Also accepts a single URL string.")
|
|
52900
53095
|
};
|
|
52901
53096
|
const extractionInputShape = {
|
|
52902
53097
|
prompt: exports_external.string().optional().describe('Natural language description of what to extract (e.g., "Extract product prices and names"). Required unless templateId is provided.'),
|
|
52903
53098
|
name: exports_external.string().optional().describe("Optional name for the workflow"),
|
|
52904
53099
|
entity: exports_external.string().optional().describe("Entity name for extraction (e.g., 'Product', 'Job Posting')"),
|
|
52905
|
-
schema: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object(SchemaFieldShape).strict())).optional().describe("Extraction schema fields. If omitted, the AI agent auto-detects the schema. When you do supply fields, mark the one that identifies a record with isKey
|
|
53100
|
+
schema: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object(SchemaFieldShape).strict())).optional().describe("Extraction schema fields. If omitted, the AI agent auto-detects the schema. When you do supply fields, mark the one that identifies a record with isKey - change detection needs it.")
|
|
52906
53101
|
};
|
|
52907
53102
|
const webhookAuthShape = exports_external.object({
|
|
52908
53103
|
type: exports_external.enum(["bearer", "basic", "header"]).describe("Authentication type"),
|
|
@@ -53030,15 +53225,15 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53030
53225
|
return channels;
|
|
53031
53226
|
}
|
|
53032
53227
|
server.registerTool("create_workflow", {
|
|
53033
|
-
description: "IMPORTANT: One workflow = one source. A single workflow can extract many different fields, tables, and sections from the same URL(s) using a rich schema. " + `Do NOT create separate workflows for different data points on the same page
|
|
53228
|
+
description: "IMPORTANT: One workflow = one source. A single workflow can extract many different fields, tables, and sections from the same URL(s) using a rich schema. " + `Do NOT create separate workflows for different data points on the same page - instead, define one workflow with a multi-field schema covering everything needed.
|
|
53034
53229
|
|
|
53035
53230
|
` + "Create a data extraction workflow using agentic navigation. Supports one-time or scheduled runs. " + "If entity and schema are provided, they guide the extraction; otherwise the AI agent auto-detects the schema from the page. " + "The workflow runs asynchronously and may take several minutes. Do NOT poll or sleep-wait for completion. " + `Return the workflow ID to the user and let them check back later with get_workflow or fetch_data.
|
|
53036
53231
|
|
|
53037
|
-
` + "PREFER TEMPLATES: If the user's request matches an existing template, instantiate it via `templateId` instead of writing a fresh prompt/schema. " + "Use `list_templates` to discover available templates and `get_template` to inspect schemas before deciding. " + "When
|
|
53232
|
+
` + "PREFER TEMPLATES: If the user's request matches an existing template, instantiate it via `templateId` instead of writing a fresh prompt/schema. " + "Use `list_templates` to discover available templates and `get_template` to inspect schemas before deciding. " + "When creating from a template, call this tool with the template's `templateId`, the source `urls`, and optional `templateVersion` only. Never copy the template prompt, entity, or schema into standalone creation, and never silently match or rewrite inline configuration.\n\n" + "NOTE: This tool is for one-time or scheduled extraction ONLY. " + "For continuous Julie realtime monitoring (watching a page for data changes and alerting), use the create_realtime_monitor tool instead.",
|
|
53038
53233
|
inputSchema: strictSchema({
|
|
53039
53234
|
...extractionInputShape,
|
|
53040
53235
|
...urlInputShape,
|
|
53041
|
-
templateId: exports_external.string().optional().describe("Instantiate this workflow from a published template.
|
|
53236
|
+
templateId: exports_external.string().optional().describe("Instantiate this workflow from a published template. Pass the templateId, source urls, and optional templateVersion. Do not copy prompt/entity/schema from the template into this call - they are inherited from the published template version, and the workflow's output conforms to its declared schema. Discover templates via list_templates and get_template."),
|
|
53042
53237
|
templateVersion: exports_external.preprocess(coerceNumber(), exports_external.number()).optional().describe("Specific published template version (integer) to instantiate. Defaults to the latest published version when templateId is set."),
|
|
53043
53238
|
description: exports_external.string().max(500).optional().describe("Description of what this workflow does (max 500 characters)"),
|
|
53044
53239
|
tags: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string())).optional().describe("Tags for organizing workflows"),
|
|
@@ -53079,7 +53274,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53079
53274
|
let workflowId;
|
|
53080
53275
|
if (args.templateId) {
|
|
53081
53276
|
if (args.prompt || args.entity || args.schema) {
|
|
53082
|
-
return errorResult("When 'templateId' is set, 'prompt', 'entity', and 'schema' must NOT be supplied
|
|
53277
|
+
return errorResult("When 'templateId' is set, 'prompt', 'entity', and 'schema' must NOT be supplied - they are inherited from the template version.");
|
|
53083
53278
|
}
|
|
53084
53279
|
const { id } = await ctx.client.workflow.create({
|
|
53085
53280
|
urls,
|
|
@@ -53235,7 +53430,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53235
53430
|
});
|
|
53236
53431
|
}));
|
|
53237
53432
|
server.registerTool("get_workflow", {
|
|
53238
|
-
description: "Get canonical workflow details, including Assistant/session linkage, extraction intent, template-controlled parts, stale-data state, job/run state, schedule timezone, location, monitoring, validation, and realtime health. For Assistant-built workflows, extractionSpec
|
|
53433
|
+
description: "Get canonical workflow details, including Assistant/session linkage, extraction intent, template-controlled parts, stale-data state, job/run state, schedule timezone, location, monitoring, validation, and realtime health. For Assistant-built workflows, extractionSpec - not the legacy prompt - is authoritative.",
|
|
53239
53434
|
inputSchema: {
|
|
53240
53435
|
workflowId: exports_external.string().describe("The workflow ID")
|
|
53241
53436
|
},
|
|
@@ -53387,6 +53582,30 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53387
53582
|
pendingQuestion: pauseState?.pendingQuestion ?? null
|
|
53388
53583
|
});
|
|
53389
53584
|
}));
|
|
53585
|
+
server.registerTool("get_workflow_assistant_timeline", {
|
|
53586
|
+
description: "Read the customer-visible conversation history for a workflow Assistant, including user messages, Assistant messages, and clarification questions with answers. " + "Works for both Shelly/Lighthouse and Julie workflows. Use get_workflow_history instead for configuration revisions. Results are chronological within each page; use nextCursor to request older items when hasMore is true.",
|
|
53587
|
+
inputSchema: strictSchema({
|
|
53588
|
+
workflowId: exports_external.string().min(1).describe("The workflow ID"),
|
|
53589
|
+
cursor: exports_external.string().min(1).optional().describe("Opaque nextCursor from the previous page"),
|
|
53590
|
+
limit: exports_external.preprocess(coerceNumber(), exports_external.number().int().min(1).max(100)).optional().describe("Maximum history items to return (default: 50, maximum: 100)")
|
|
53591
|
+
}),
|
|
53592
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }
|
|
53593
|
+
}, withErrorHandling("get_workflow_assistant_timeline", async (args) => {
|
|
53594
|
+
const timeline = await ctx.client.assistant.getTimeline(args.workflowId, {
|
|
53595
|
+
cursor: args.cursor,
|
|
53596
|
+
limit: args.limit
|
|
53597
|
+
});
|
|
53598
|
+
if (timeline.workflowId !== args.workflowId) {
|
|
53599
|
+
return errorResult(`The Assistant timeline returned workflow ID '${timeline.workflowId}' instead of '${args.workflowId}'.`);
|
|
53600
|
+
}
|
|
53601
|
+
return jsonResult({
|
|
53602
|
+
workflowId: timeline.workflowId,
|
|
53603
|
+
sessionId: timeline.sessionId,
|
|
53604
|
+
items: timeline.items,
|
|
53605
|
+
pagination: timeline.pagination,
|
|
53606
|
+
dashboardUrl: workflowDashboardUrl(timeline.workflowId)
|
|
53607
|
+
});
|
|
53608
|
+
}));
|
|
53390
53609
|
server.registerTool("answer_workflow_assistant_question", {
|
|
53391
53610
|
description: "Answer the workflow Assistant's currently pending clarification question and resume it. " + "Use `answer` for a freeform response, or `answers` for the structured key/value response described by get_workflow_assistant. Provide exactly one. The question ID must still be current.",
|
|
53392
53611
|
inputSchema: strictSchema({
|
|
@@ -53599,7 +53818,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53599
53818
|
});
|
|
53600
53819
|
}));
|
|
53601
53820
|
server.registerTool("list_workflow_runs", {
|
|
53602
|
-
description: "List a workflow's execution run history
|
|
53821
|
+
description: "List a workflow's execution run history - each run's status, start/finish time, " + "record count, and errors. Use to answer 'when did this last succeed?' " + "(status='success', limit=1) or 'recent success/failure pattern?'. Distinct from " + "get_workflow_history, which is the config audit log. `status` is normally " + "success | failed | in_progress; a run whose backend state this server does not " + "recognize reports that raw state verbatim, so treat any other value as unknown " + "rather than as a failure.",
|
|
53603
53822
|
inputSchema: {
|
|
53604
53823
|
workflowId: exports_external.string().describe("The workflow ID"),
|
|
53605
53824
|
status: exports_external.enum(["success", "failed", "in_progress"]).optional().describe("Filter runs by outcome"),
|
|
@@ -53628,7 +53847,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53628
53847
|
});
|
|
53629
53848
|
}));
|
|
53630
53849
|
server.registerTool("run_workflow", {
|
|
53631
|
-
description: "Run a workflow to extract fresh data. The run is asynchronous and may take several minutes. Do NOT poll or sleep-wait for completion. Return the workflow ID to the user and let them check status with get_workflow or fetch results later with fetch_data.",
|
|
53850
|
+
description: "Run a workflow to extract fresh data, including retrying a failed one-time or scheduled workflow. Preserve the existing workflow ID and configuration - do not delete and recreate the workflow solely to retry it. The run is asynchronous and may take several minutes. Do NOT poll or sleep-wait for completion. Return the workflow ID to the user and let them check status with get_workflow or fetch results later with fetch_data. Realtime workflows cannot be manually run.",
|
|
53632
53851
|
inputSchema: {
|
|
53633
53852
|
workflowId: exports_external.string().describe("The workflow ID to run"),
|
|
53634
53853
|
limit: exports_external.preprocess(coerceNumber(), exports_external.number()).optional().describe("Maximum number of records to extract (default: 1000)")
|
|
@@ -53651,7 +53870,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53651
53870
|
const FETCH_DATA_DEFAULT_LIMIT = 50;
|
|
53652
53871
|
const FETCH_DATA_MAX_LIMIT = 500;
|
|
53653
53872
|
server.registerTool("fetch_data", {
|
|
53654
|
-
description: "Get a PAGE of extracted data from a workflow. Use ONLY for previews, sorted/filtered slices, or explicit 'first N rows' / 'top N' queries (capped at 500 rows per call). Do NOT use this to retrieve a full dataset, 'all rows', or anything the user wants to analyze in Excel / pandas / duckdb
|
|
53873
|
+
description: "Get a PAGE of extracted data from a workflow. Use ONLY for previews, sorted/filtered slices, or explicit 'first N rows' / 'top N' queries (capped at 500 rows per call). Do NOT use this to retrieve a full dataset, 'all rows', or anything the user wants to analyze in Excel / pandas / duckdb - use export_data for those. Data is only available after the workflow run has completed (status is no longer 'Running' or 'Validating'). Do NOT poll or sleep-wait for completion.",
|
|
53655
53874
|
inputSchema: {
|
|
53656
53875
|
workflowId: exports_external.string().describe("The workflow ID"),
|
|
53657
53876
|
limit: exports_external.preprocess(coerceNumber(), exports_external.number()).optional().describe(`Maximum number of records to return. Default ${FETCH_DATA_DEFAULT_LIMIT}, max ${FETCH_DATA_MAX_LIMIT}.`),
|
|
@@ -53686,7 +53905,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53686
53905
|
return jsonResult(result);
|
|
53687
53906
|
}));
|
|
53688
53907
|
server.registerTool("export_data", {
|
|
53689
|
-
description: "PREFERRED tool for retrieving a workflow's FULL dataset. Materializes the data to object storage and returns a signed download URL. Use this whenever the user wants 'all rows', 'the full dataset', 'everything', an export, or anything destined for Excel / pandas / duckdb / a CSV file
|
|
53908
|
+
description: "PREFERRED tool for retrieving a workflow's FULL dataset. Materializes the data to object storage and returns a signed download URL. Use this whenever the user wants 'all rows', 'the full dataset', 'everything', an export, or anything destined for Excel / pandas / duckdb / a CSV file - even for small workflows. The URL is self-authenticating (open with `fetch(url)`, no Authorization header). Use fetch_data ONLY when the user explicitly asks for a small preview slice (e.g., 'first 10', 'top N sorted by X').",
|
|
53690
53909
|
inputSchema: {
|
|
53691
53910
|
workflowId: exports_external.string().describe("The workflow ID"),
|
|
53692
53911
|
format: exports_external.enum(["csv", "json"]).optional().describe("Export format. Default 'csv'."),
|
|
@@ -53812,7 +54031,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53812
54031
|
});
|
|
53813
54032
|
}));
|
|
53814
54033
|
server.registerTool("pause_workflow", {
|
|
53815
|
-
description: "Pause an ACTIVE workflow so it stops running on its schedule. Requires the workflow to be in ACTIVE state
|
|
54034
|
+
description: "Pause an ACTIVE workflow so it stops running on its schedule. Requires the workflow to be in ACTIVE state - pausing a workflow that is currently running, already paused, or in PREVIEW will return an error. Use approve_workflow to resume a paused workflow.",
|
|
53816
54035
|
inputSchema: {
|
|
53817
54036
|
workflowId: exports_external.string().min(1).describe("The workflow ID to pause")
|
|
53818
54037
|
},
|
|
@@ -53826,17 +54045,17 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53826
54045
|
});
|
|
53827
54046
|
}));
|
|
53828
54047
|
server.registerTool("update_workflow", {
|
|
53829
|
-
description: `Update a workflow's configuration. All fields are optional
|
|
54048
|
+
description: `Update a workflow's configuration. All fields are optional - only provided fields will be updated. Use this to change the name, URLs, extraction schema, entity, prompt, schedule, or other metadata.
|
|
53830
54049
|
|
|
53831
54050
|
` + `IMPORTANT: You cannot change a workflow's interval to or from REAL_TIME. Julie realtime workflows are architecturally different from scheduled workflows and must be created with create_realtime_monitor from the start. Existing workflows cannot be converted between these modes in place; do not delete and recreate a workflow as an update workaround.
|
|
53832
54051
|
|
|
53833
|
-
` + "ASSISTANT-OWNED INTENT: Use request_workflow_update
|
|
54052
|
+
` + "ASSISTANT-OWNED INTENT: Use request_workflow_update - not `userPrompt` - for agent-built workflow changes to extraction intent, navigation, pagination, data sourcing, repair, or generated scripts. `userPrompt` may be rejected with `SHELLY_INTENT_REQUIRES_EXTRACTION_SPEC` because those workflows' canonical intent is owned by the Assistant. " + "Call get_workflow first. If its template.controlledParts contains the setting, create and apply a template version instead of overriding the workflow directly. NEVER delete and recreate a workflow to work around an update limitation - that changes workflowId, breaks downstream tables/connectors, and discards history.",
|
|
53834
54053
|
inputSchema: strictSchema({
|
|
53835
54054
|
workflowId: exports_external.string().describe("The workflow ID to update"),
|
|
53836
54055
|
name: exports_external.string().optional().describe("New name for the workflow"),
|
|
53837
54056
|
urls: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string()).min(1)).optional().describe("New target URLs for the workflow (array of strings). Also accepts a single URL string."),
|
|
53838
54057
|
entity: exports_external.string().optional().describe("Entity name for extraction (e.g., 'Product', 'Job Posting')"),
|
|
53839
|
-
schema: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object(SchemaFieldShape).strict())).optional().describe("New extraction schema fields. This REPLACES the whole schema
|
|
54058
|
+
schema: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object(SchemaFieldShape).strict())).optional().describe("New extraction schema fields. This REPLACES the whole schema - list every field you want to keep, each with its isKey flag, or the omitted ones and their flags are lost. Call get_workflow first and edit the schema it returns."),
|
|
53840
54059
|
description: exports_external.string().max(500).optional().describe("Workflow description (max 500 characters)"),
|
|
53841
54060
|
tags: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string())).optional().describe("Tags for organizing workflows"),
|
|
53842
54061
|
userPrompt: exports_external.string().optional().describe("Navigation prompt for agentic-navigation mode (10-5000 characters)"),
|
|
@@ -53858,7 +54077,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
53858
54077
|
"FOUR_WEEKS",
|
|
53859
54078
|
"MONTHLY",
|
|
53860
54079
|
"CUSTOM"
|
|
53861
|
-
]).optional().describe("How often the workflow should run. CUSTOM requires schedules. Note: REAL_TIME is NOT allowed here
|
|
54080
|
+
]).optional().describe("How often the workflow should run. CUSTOM requires schedules. Note: REAL_TIME is NOT allowed here - realtime workflows must be created via create_realtime_monitor."),
|
|
53862
54081
|
schedules: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string())).optional().describe("Cron expressions for CUSTOM update interval"),
|
|
53863
54082
|
timezone: exports_external.string().min(1).optional().describe("IANA timezone for cron schedules, for example America/New_York. A timezone-only update preserves existing cron expressions."),
|
|
53864
54083
|
location: exports_external.preprocess(coerceJson(), LocationSchema).optional().describe("Scraping location: {type:'auto'} or {type:'manual', isoCode:'US'}"),
|
|
@@ -54277,22 +54496,29 @@ function registerTools(server, ctx, capabilities) {
|
|
|
54277
54496
|
});
|
|
54278
54497
|
}));
|
|
54279
54498
|
server.registerTool("list_templates", {
|
|
54280
|
-
description: "List all templates in the current team. Templates define reusable configurations (prompt, schema, notifications).",
|
|
54499
|
+
description: "List all templates in the current team. Templates define reusable configurations (prompt, schema, validation rules, notifications, and frequency). Use this to find a matching template before creating a workflow. To instantiate a template, call create_workflow with its templateId, source URLs, and optional templateVersion - never copy the template prompt, entity, or schema into standalone creation.",
|
|
54281
54500
|
inputSchema: strictSchema({}),
|
|
54282
54501
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }
|
|
54283
54502
|
}, withErrorHandling("list_templates", async () => {
|
|
54284
54503
|
const templates = await ctx.client.template.list();
|
|
54285
|
-
return jsonResult({
|
|
54504
|
+
return jsonResult({
|
|
54505
|
+
templates,
|
|
54506
|
+
count: templates.length,
|
|
54507
|
+
instructions: "To instantiate a listed template, call create_workflow with the matching templateId, source URLs, and optional templateVersion. Do not copy the template prompt, entity, or schema into standalone creation."
|
|
54508
|
+
});
|
|
54286
54509
|
}));
|
|
54287
54510
|
server.registerTool("get_template", {
|
|
54288
|
-
description: "Get a template by ID, including all published versions.",
|
|
54511
|
+
description: "Get a template by ID, including all published versions and their schemas. After inspecting it, instantiate the template with create_workflow using templateId, source URLs, and optional templateVersion. Never copy the returned prompt, entity, or schema into standalone creation - those values are inherited when templateId is passed.",
|
|
54289
54512
|
inputSchema: strictSchema({
|
|
54290
54513
|
templateId: exports_external.string().describe("The template ID")
|
|
54291
54514
|
}),
|
|
54292
54515
|
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }
|
|
54293
54516
|
}, withErrorHandling("get_template", async (args) => {
|
|
54294
54517
|
const template = await ctx.client.template.get(args.templateId);
|
|
54295
|
-
return jsonResult({
|
|
54518
|
+
return jsonResult({
|
|
54519
|
+
template,
|
|
54520
|
+
instructions: `To instantiate this template, call create_workflow with templateId "${args.templateId}", source URLs, and optional templateVersion. Do not copy this template's prompt, entity, or schema into standalone creation.`
|
|
54521
|
+
});
|
|
54296
54522
|
}));
|
|
54297
54523
|
server.registerTool("create_template", {
|
|
54298
54524
|
description: "Create a new template. After creation, use create_template_version to publish a version with prompt, schema, and notifications.",
|
|
@@ -54315,7 +54541,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
54315
54541
|
server.registerTool("update_template", {
|
|
54316
54542
|
description: `Update a template's name or description ONLY. At least one of the two must be provided.
|
|
54317
54543
|
|
|
54318
|
-
` + "This tool CANNOT change what linked workflows inherit
|
|
54544
|
+
` + "This tool CANNOT change what linked workflows inherit - prompt, schema, validation rules, notifications and frequency all live in template *versions*, which are immutable snapshots. " + "To change any of those, publish a new version with `create_template_version` (the version IS the edit), then roll it out to linked workflows with `apply_template_version`. " + "There is no in-place edit of a published version, and never report a prompt or schema change as impossible - versioning is the supported path.",
|
|
54319
54545
|
inputSchema: strictSchema({
|
|
54320
54546
|
templateId: exports_external.string().describe("The template ID to update"),
|
|
54321
54547
|
name: exports_external.preprocess(coerceNull(), exports_external.string().optional()).optional().describe("New template name"),
|
|
@@ -54371,7 +54597,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
54371
54597
|
}))).optional().describe("Predefined categories for a CLASSIFICATION field ({title, definition}[]). Required for fieldType=CLASSIFICATION; omitted otherwise.")
|
|
54372
54598
|
};
|
|
54373
54599
|
server.registerTool("create_template_version", {
|
|
54374
|
-
description: `Publish a new version of a template. Versions capture the full workflow config: prompt, schema, and notifications. All fields are optional
|
|
54600
|
+
description: `Publish a new version of a template. Versions capture the full workflow config: prompt, schema, and notifications. All fields are optional - include only what this version should set.
|
|
54375
54601
|
|
|
54376
54602
|
` + "THIS IS HOW YOU EDIT A TEMPLATE'S PROMPT OR SCHEMA. Published versions are immutable, so 'changing the template prompt' means publishing a new version here and then calling `apply_template_version` to push it onto linked workflows. " + "`update_template` only renames a template; it cannot touch prompt or schema.",
|
|
54377
54603
|
inputSchema: strictSchema({
|
|
@@ -54380,7 +54606,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
54380
54606
|
schemaId: exports_external.string().optional().describe("Existing schema ID to reference (mutually exclusive with schemaFields)"),
|
|
54381
54607
|
schemaFields: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object(TemplateSchemaFieldShape).strict())).optional().describe("Inline schema fields to create a new schema (mutually exclusive with schemaId)"),
|
|
54382
54608
|
schemaEntity: exports_external.string().optional().describe("Entity name for the inline schema"),
|
|
54383
|
-
schemaValidationRules: exports_external.preprocess(coerceJson(),
|
|
54609
|
+
schemaValidationRules: exports_external.preprocess(coerceJson(), SchemaValidationRulesSchema).optional().describe('Per-field schema validation rules keyed by field name. Each rule uses kind STRING, NUMBER, OTHER, OBJECT, or ARRAY and nested rules are supported. Rule metadata requires editedBy (default|llm|agent|ops|user) and an ISO-8601 editedAt timestamp. Example: { "price": { "kind": "NUMBER", "minimum": { "value": 0, "editedBy": "user", "editedAt": "2026-01-01T00:00:00.000Z" } } }. Not inherited from prior versions - omitting this on a new version drops any rules the previous version had.'),
|
|
54384
54610
|
notifications: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object({
|
|
54385
54611
|
eventType: exports_external.string().describe("Notification event type"),
|
|
54386
54612
|
eventConfiguration: exports_external.preprocess(coerceJson(), exports_external.record(exports_external.string(), exports_external.unknown())).optional(),
|
|
@@ -54461,7 +54687,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
54461
54687
|
return jsonResult({ schemas: schemas4, count: schemas4.length });
|
|
54462
54688
|
}));
|
|
54463
54689
|
server.registerTool("link_template_to_workflows", {
|
|
54464
|
-
description: "Link one or more EXISTING workflows to a template in a single call. " + "This is the bulk equivalent of creating a workflow with `templateId`: linked workflows adopt the template's configuration (prompt, schema, notifications) and stay in sync with it. " + "The template ENFORCES its schema on linked workflows
|
|
54690
|
+
description: "Link one or more EXISTING workflows to a template in a single call. " + "This is the bulk equivalent of creating a workflow with `templateId`: linked workflows adopt the template's configuration (prompt, schema, notifications) and stay in sync with it. " + "The template ENFORCES its schema on linked workflows - their extracted output conforms to the template's declared field names, so this is the way to make many workflows produce a consistent, canonical schema. " + "Use `list_templates`/`get_template` to find the template, and `list_workflows` to find the workflow IDs. " + "Set `force: true` to relink workflows already linked to a different template.",
|
|
54465
54691
|
inputSchema: strictSchema({
|
|
54466
54692
|
templateId: exports_external.string().describe("The template ID to link workflows to"),
|
|
54467
54693
|
workflowIds: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string()).min(1)).describe("Workflow IDs to link to the template (array of strings). Also accepts a single ID string."),
|
|
@@ -54478,7 +54704,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
54478
54704
|
return jsonResult({
|
|
54479
54705
|
success: false,
|
|
54480
54706
|
conflicts: result.conflicts,
|
|
54481
|
-
message: `Cannot link
|
|
54707
|
+
message: `Cannot link - ${result.conflicts.length} workflow(s) are already linked to another template: ${summary}. ` + "Re-run with force: true to move them to this template."
|
|
54482
54708
|
});
|
|
54483
54709
|
}
|
|
54484
54710
|
return jsonResult({
|
|
@@ -54538,7 +54764,7 @@ function registerTools(server, ctx, capabilities) {
|
|
|
54538
54764
|
});
|
|
54539
54765
|
}));
|
|
54540
54766
|
}
|
|
54541
|
-
var SchemaFieldShape, LocationSchema, MonitoringValueOperators, MonitoringValuelessOperators, MonitoringConditionOperatorSchema, MonitoringConditionSchema, MonitoringSchema, RESUMABLE_ASSISTANT_STATUSES, ACTIVE_ASSISTANT_STATUSES, IDLE_ASSISTANT_STATUSES, CLOSED_ASSISTANT_STATUSES, DASHBOARD_BASE_URL = "https://www.kadoa.com", WORKFLOW_AUDIT_WATCHED_KEYS;
|
|
54767
|
+
var SchemaFieldShape, SchemaValidationAttributionShape, SchemaValidationPresenceRule, SchemaValidationUniquenessRule, SchemaValidationStringLengthRule, SchemaValidationStringFormatRule, SchemaValidationFieldRulesSchema, SchemaValidationRulesSchema, LocationSchema, MonitoringValueOperators, MonitoringValuelessOperators, MonitoringConditionOperatorSchema, MonitoringConditionSchema, MonitoringSchema, RESUMABLE_ASSISTANT_STATUSES, ACTIVE_ASSISTANT_STATUSES, IDLE_ASSISTANT_STATUSES, CLOSED_ASSISTANT_STATUSES, DASHBOARD_BASE_URL = "https://www.kadoa.com", WORKFLOW_AUDIT_WATCHED_KEYS;
|
|
54542
54768
|
var init_tools = __esm(() => {
|
|
54543
54769
|
init_dist2();
|
|
54544
54770
|
init_zod();
|
|
@@ -54548,8 +54774,105 @@ var init_tools = __esm(() => {
|
|
|
54548
54774
|
description: exports_external.string().optional().describe("What this field contains"),
|
|
54549
54775
|
example: exports_external.string().describe("Example value"),
|
|
54550
54776
|
dataType: exports_external.enum(["STRING", "NUMBER", "BOOLEAN", "DATE", "DATETIME", "MONEY", "IMAGE", "LINK", "OBJECT", "ARRAY"]).optional().describe("Data type for the field"),
|
|
54551
|
-
isKey: exports_external.preprocess(coerceBoolean(), exports_external.boolean()).optional().describe("Marks this field as a key field
|
|
54777
|
+
isKey: exports_external.preprocess(coerceBoolean(), exports_external.boolean()).optional().describe("Marks this field as a key field - the stable identity used to match records across runs. Change detection diffs records by their key fields, so a monitored or real-time workflow without one cannot tell an updated record from a new one. Set it on whatever uniquely identifies a row (a detail URL, an ID, a ticker).")
|
|
54552
54778
|
};
|
|
54779
|
+
SchemaValidationAttributionShape = {
|
|
54780
|
+
editedBy: exports_external.enum(["default", "llm", "agent", "ops", "user"]).describe("Who last edited this rule: default, llm, agent, ops, or user"),
|
|
54781
|
+
editedByLabel: exports_external.string().optional().describe("Optional editor identifier"),
|
|
54782
|
+
editedAt: exports_external.string().datetime().describe("ISO-8601 timestamp when this rule was last edited")
|
|
54783
|
+
};
|
|
54784
|
+
SchemaValidationPresenceRule = exports_external.object({
|
|
54785
|
+
target: exports_external.number().int().min(0).max(100).step(20).describe("Expected percentage of rows with a value"),
|
|
54786
|
+
...SchemaValidationAttributionShape
|
|
54787
|
+
}).strict();
|
|
54788
|
+
SchemaValidationUniquenessRule = exports_external.object({
|
|
54789
|
+
target: exports_external.number().int().min(0).max(100).step(20).describe("Expected percentage of rows with a unique value"),
|
|
54790
|
+
...SchemaValidationAttributionShape
|
|
54791
|
+
}).strict();
|
|
54792
|
+
SchemaValidationStringLengthRule = exports_external.object({
|
|
54793
|
+
value: exports_external.number().int().min(0).describe("String length bound"),
|
|
54794
|
+
...SchemaValidationAttributionShape
|
|
54795
|
+
}).strict();
|
|
54796
|
+
SchemaValidationStringFormatRule = exports_external.discriminatedUnion("kind", [
|
|
54797
|
+
exports_external.object({
|
|
54798
|
+
kind: exports_external.literal("FREE_TEXT"),
|
|
54799
|
+
charset: exports_external.discriminatedUnion("kind", [
|
|
54800
|
+
exports_external.object({
|
|
54801
|
+
kind: exports_external.literal("PRESET"),
|
|
54802
|
+
preset: exports_external.enum(["natural_language", "alphanumeric", "alpha"])
|
|
54803
|
+
}).strict()
|
|
54804
|
+
]),
|
|
54805
|
+
...SchemaValidationAttributionShape
|
|
54806
|
+
}).strict(),
|
|
54807
|
+
exports_external.object({
|
|
54808
|
+
kind: exports_external.literal("FORMAT"),
|
|
54809
|
+
source: exports_external.discriminatedUnion("kind", [
|
|
54810
|
+
exports_external.object({
|
|
54811
|
+
kind: exports_external.literal("PRESET"),
|
|
54812
|
+
preset: exports_external.enum(["url", "email", "phone", "date", "datetime", "time", "uuid", "slug"])
|
|
54813
|
+
}).strict(),
|
|
54814
|
+
exports_external.object({
|
|
54815
|
+
kind: exports_external.literal("CUSTOM"),
|
|
54816
|
+
pattern: exports_external.string().min(1).describe("Regular expression pattern")
|
|
54817
|
+
}).strict()
|
|
54818
|
+
]),
|
|
54819
|
+
...SchemaValidationAttributionShape
|
|
54820
|
+
}).strict(),
|
|
54821
|
+
exports_external.object({
|
|
54822
|
+
kind: exports_external.literal("LIST"),
|
|
54823
|
+
source: exports_external.discriminatedUnion("kind", [
|
|
54824
|
+
exports_external.object({
|
|
54825
|
+
kind: exports_external.literal("PRESET"),
|
|
54826
|
+
preset: exports_external.enum(["language2", "country2", "country3", "currency3", "month3", "usState2"])
|
|
54827
|
+
}).strict(),
|
|
54828
|
+
exports_external.object({
|
|
54829
|
+
kind: exports_external.literal("CUSTOM"),
|
|
54830
|
+
values: exports_external.array(exports_external.string().min(1)).min(1).describe("Allowed string values")
|
|
54831
|
+
}).strict()
|
|
54832
|
+
]),
|
|
54833
|
+
...SchemaValidationAttributionShape
|
|
54834
|
+
}).strict()
|
|
54835
|
+
]);
|
|
54836
|
+
SchemaValidationFieldRulesSchema = exports_external.lazy(() => exports_external.discriminatedUnion("kind", [
|
|
54837
|
+
exports_external.object({
|
|
54838
|
+
kind: exports_external.literal("STRING"),
|
|
54839
|
+
presence: SchemaValidationPresenceRule.optional(),
|
|
54840
|
+
uniqueness: SchemaValidationUniquenessRule.optional(),
|
|
54841
|
+
minLength: SchemaValidationStringLengthRule.optional(),
|
|
54842
|
+
maxLength: SchemaValidationStringLengthRule.optional(),
|
|
54843
|
+
minHtmlElements: SchemaValidationStringLengthRule.optional(),
|
|
54844
|
+
maxHtmlElements: SchemaValidationStringLengthRule.optional(),
|
|
54845
|
+
format: SchemaValidationStringFormatRule.optional()
|
|
54846
|
+
}).strict(),
|
|
54847
|
+
exports_external.object({
|
|
54848
|
+
kind: exports_external.literal("NUMBER"),
|
|
54849
|
+
presence: SchemaValidationPresenceRule.optional(),
|
|
54850
|
+
uniqueness: SchemaValidationUniquenessRule.optional(),
|
|
54851
|
+
minimum: exports_external.object({ value: exports_external.number().describe("Minimum numeric value"), ...SchemaValidationAttributionShape }).strict().optional(),
|
|
54852
|
+
maximum: exports_external.object({ value: exports_external.number().describe("Maximum numeric value"), ...SchemaValidationAttributionShape }).strict().optional(),
|
|
54853
|
+
maxDecimalPlaces: exports_external.object({ value: exports_external.number().int().min(0).max(16), ...SchemaValidationAttributionShape }).strict().optional()
|
|
54854
|
+
}).strict(),
|
|
54855
|
+
exports_external.object({
|
|
54856
|
+
kind: exports_external.literal("OTHER"),
|
|
54857
|
+
presence: SchemaValidationPresenceRule.optional(),
|
|
54858
|
+
uniqueness: SchemaValidationUniquenessRule.optional()
|
|
54859
|
+
}).strict(),
|
|
54860
|
+
exports_external.object({
|
|
54861
|
+
kind: exports_external.literal("OBJECT"),
|
|
54862
|
+
presence: SchemaValidationPresenceRule.optional(),
|
|
54863
|
+
uniqueness: SchemaValidationUniquenessRule.optional(),
|
|
54864
|
+
properties: exports_external.record(exports_external.string(), SchemaValidationFieldRulesSchema)
|
|
54865
|
+
}).strict(),
|
|
54866
|
+
exports_external.object({
|
|
54867
|
+
kind: exports_external.literal("ARRAY"),
|
|
54868
|
+
presence: SchemaValidationPresenceRule.optional(),
|
|
54869
|
+
uniqueness: SchemaValidationUniquenessRule.optional(),
|
|
54870
|
+
minItems: exports_external.object({ value: exports_external.number().int().min(0), ...SchemaValidationAttributionShape }).strict().optional(),
|
|
54871
|
+
maxItems: exports_external.object({ value: exports_external.number().int().min(0), ...SchemaValidationAttributionShape }).strict().optional(),
|
|
54872
|
+
items: SchemaValidationFieldRulesSchema.optional()
|
|
54873
|
+
}).strict()
|
|
54874
|
+
]));
|
|
54875
|
+
SchemaValidationRulesSchema = exports_external.record(exports_external.string(), SchemaValidationFieldRulesSchema);
|
|
54553
54876
|
LocationSchema = exports_external.object({
|
|
54554
54877
|
type: exports_external.enum(["auto", "manual"]),
|
|
54555
54878
|
isoCode: exports_external.string().trim().min(2).optional()
|
|
@@ -54638,7 +54961,7 @@ var package_default;
|
|
|
54638
54961
|
var init_package = __esm(() => {
|
|
54639
54962
|
package_default = {
|
|
54640
54963
|
name: "@kadoa/mcp",
|
|
54641
|
-
version: "0.5.
|
|
54964
|
+
version: "0.5.22",
|
|
54642
54965
|
description: "Kadoa MCP Server — manage workflows from Claude Desktop, Cursor, and other MCP clients",
|
|
54643
54966
|
type: "module",
|
|
54644
54967
|
main: "dist/index.js",
|
|
@@ -54662,7 +54985,7 @@ var init_package = __esm(() => {
|
|
|
54662
54985
|
prepublishOnly: "bun run check-types && bun run test:unit && bun run build"
|
|
54663
54986
|
},
|
|
54664
54987
|
dependencies: {
|
|
54665
|
-
"@kadoa/node-sdk": "^0.
|
|
54988
|
+
"@kadoa/node-sdk": "^0.39.0",
|
|
54666
54989
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
54667
54990
|
express: "^5.2.1",
|
|
54668
54991
|
"express-rate-limit": "^8.2.1",
|
|
@@ -60241,21 +60564,22 @@ async function createServer(auth, options) {
|
|
|
60241
60564
|
const server = new McpServer({ name: "kadoa", version: package_default.version }, {
|
|
60242
60565
|
instructions: [
|
|
60243
60566
|
"IMPORTANT: One workflow = one source. A single workflow can extract many different fields, tables, and sections from the same URL(s) using a rich schema.",
|
|
60244
|
-
"Do NOT create multiple workflows for different data points on the same page
|
|
60567
|
+
"Do NOT create multiple workflows for different data points on the same page - instead, define one workflow with a multi-field schema covering everything needed.",
|
|
60245
60568
|
"",
|
|
60246
60569
|
"Kadoa workflows use agentic navigation: the AI agent can browse pages, click buttons, fill forms, select dropdowns, paginate, open detail pages, and handle multi-step interactions.",
|
|
60247
60570
|
"Describe the full navigation steps in the prompt (e.g., 'select year 2022 from the dropdown, click Search, extract the table, then repeat for 2023').",
|
|
60248
60571
|
"",
|
|
60249
|
-
"Workflow lifecycle: create_workflow \u2192 get_workflow (check status) \u2192 fetch_data (get results). Workflows run asynchronously
|
|
60572
|
+
"Workflow lifecycle: create_workflow \u2192 get_workflow (check status) \u2192 fetch_data (get results). Workflows run asynchronously - never poll or sleep-wait.",
|
|
60250
60573
|
"",
|
|
60251
60574
|
"Use create_realtime_monitor only when the user wants continuous Julie change detection with alerts. It first persists notification channels, then asynchronously returns workflow/session/thread/job IDs; use the workflow Assistant tools for follow-up status, questions, and controls.",
|
|
60252
60575
|
"For one-time or scheduled extraction, use create_workflow. Use scrape for an immediate raw HTML or markdown fetch from one URL. Use create_workflow for structured extraction, recurring runs, monitoring, or navigation-heavy jobs.",
|
|
60576
|
+
"If a one-time or scheduled workflow fails, retry it with run_workflow using the existing workflow ID. Do NOT delete and recreate the workflow just to retry it - preserve its workflow ID and configuration. Realtime workflows cannot be manually run.",
|
|
60253
60577
|
"Use list_changes and get_change to retrieve detected diffs from realtime monitoring workflows.",
|
|
60254
60578
|
"",
|
|
60255
60579
|
"Schema tips: Use descriptive field names and examples. Group related data under one entity.",
|
|
60256
|
-
"The AI agent uses the schema + prompt to understand what to extract
|
|
60580
|
+
"The AI agent uses the schema + prompt to understand what to extract - a detailed prompt with a comprehensive schema produces better results than multiple simple workflows.",
|
|
60257
60581
|
"",
|
|
60258
|
-
"Templates enforce their schema: a workflow created from a template (create_workflow with templateId) or linked to one (link_template_to_workflows) produces output whose field names conform to the template's declared schema. Use templates when you need many workflows to return a consistent, canonical set of fields
|
|
60582
|
+
"Templates enforce their schema: a workflow created from a template (create_workflow with templateId) or linked to one (link_template_to_workflows) produces output whose field names conform to the template's declared schema. Use templates when you need many workflows to return a consistent, canonical set of fields - do NOT assume the extractor will drift field names away from a template's schema."
|
|
60259
60583
|
].join(`
|
|
60260
60584
|
`)
|
|
60261
60585
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kadoa/mcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.22",
|
|
4
4
|
"description": "Kadoa MCP Server — manage workflows from Claude Desktop, Cursor, and other MCP clients",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"prepublishOnly": "bun run check-types && bun run test:unit && bun run build"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@kadoa/node-sdk": "^0.
|
|
27
|
+
"@kadoa/node-sdk": "^0.39.0",
|
|
28
28
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
29
29
|
"express": "^5.2.1",
|
|
30
30
|
"express-rate-limit": "^8.2.1",
|