@kadoa/mcp 0.5.5 → 0.5.7
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 +11 -0
- package/dist/index.js +149 -54
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -85,6 +85,17 @@ Claude checks the run status with get_workflow, then calls fetch_data
|
|
|
85
85
|
to retrieve the extracted records and display them as a table.
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
+
### Create a workflow from a template
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
> You: Use my "Product Scraper" template to scrape https://example-shop.com.
|
|
92
|
+
|
|
93
|
+
Claude calls list_templates to find the matching template, then
|
|
94
|
+
create_workflow with `templateId` and `urls` only — the prompt and
|
|
95
|
+
schema are inherited from the template version. Returns the workflow
|
|
96
|
+
ID for follow-up with get_workflow or fetch_data.
|
|
97
|
+
```
|
|
98
|
+
|
|
88
99
|
### Update a workflow and re-run
|
|
89
100
|
|
|
90
101
|
```
|
package/dist/index.js
CHANGED
|
@@ -14552,7 +14552,7 @@ function finalize(ctx, schema) {
|
|
|
14552
14552
|
result.$schema = "http://json-schema.org/draft-07/schema#";
|
|
14553
14553
|
} else if (ctx.target === "draft-04") {
|
|
14554
14554
|
result.$schema = "http://json-schema.org/draft-04/schema#";
|
|
14555
|
-
} else if (ctx.target === "openapi-3.0") {}
|
|
14555
|
+
} else if (ctx.target === "openapi-3.0") {}
|
|
14556
14556
|
if (ctx.external?.uri) {
|
|
14557
14557
|
const id = ctx.external.registry.get(schema)?.id;
|
|
14558
14558
|
if (!id)
|
|
@@ -14817,7 +14817,7 @@ var formatMap, stringProcessor = (schema, ctx, _json, _params) => {
|
|
|
14817
14817
|
if (val === undefined) {
|
|
14818
14818
|
if (ctx.unrepresentable === "throw") {
|
|
14819
14819
|
throw new Error("Literal `undefined` cannot be represented in JSON Schema");
|
|
14820
|
-
}
|
|
14820
|
+
}
|
|
14821
14821
|
} else if (typeof val === "bigint") {
|
|
14822
14822
|
if (ctx.unrepresentable === "throw") {
|
|
14823
14823
|
throw new Error("BigInt literals cannot be represented in JSON Schema");
|
|
@@ -44498,9 +44498,9 @@ function createClientDomains(params) {
|
|
|
44498
44498
|
const dataFetcherService = new DataFetcherService(client.apis.workflows);
|
|
44499
44499
|
const channelsService = new NotificationChannelsService(client.apis.notifications, userService);
|
|
44500
44500
|
const settingsService = new NotificationSettingsService(client.apis.notifications);
|
|
44501
|
-
const workflowsCoreService = new WorkflowsCoreService(client.apis.workflows);
|
|
44502
44501
|
const schemasService = new SchemasService(client);
|
|
44503
44502
|
const templatesService = new TemplatesService(client);
|
|
44503
|
+
const workflowsCoreService = new WorkflowsCoreService(client.apis.workflows, templatesService);
|
|
44504
44504
|
const variablesService = new VariablesService(client);
|
|
44505
44505
|
const channelSetupService = new NotificationSetupService(channelsService, settingsService);
|
|
44506
44506
|
const coreService = new ValidationCoreService(client);
|
|
@@ -48714,7 +48714,7 @@ var import_debug, __require2, ChangeDifferenceType, KadoaErrorCode, _KadoaSdkExc
|
|
|
48714
48714
|
}));
|
|
48715
48715
|
return channels;
|
|
48716
48716
|
}
|
|
48717
|
-
}, PUBLIC_API_URI, WSS_API_URI, REALTIME_API_URI, SDK_VERSION = "0.
|
|
48717
|
+
}, PUBLIC_API_URI, WSS_API_URI, REALTIME_API_URI, SDK_VERSION = "0.33.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 {
|
|
48718
48718
|
constructor(config2) {
|
|
48719
48719
|
this.drainingSockets = /* @__PURE__ */ new Set;
|
|
48720
48720
|
this.lastHeartbeat = Date.now();
|
|
@@ -49443,36 +49443,82 @@ var import_debug, __require2, ChangeDifferenceType, KadoaErrorCode, _KadoaSdkExc
|
|
|
49443
49443
|
});
|
|
49444
49444
|
}
|
|
49445
49445
|
}, JobStateEnum, TERMINAL_JOB_STATES, TERMINAL_RUN_STATES2, debug9, WorkflowsCoreService = class {
|
|
49446
|
-
constructor(workflowsApi) {
|
|
49446
|
+
constructor(workflowsApi, templatesService) {
|
|
49447
49447
|
this.workflowsApi = workflowsApi;
|
|
49448
|
+
this.templatesService = templatesService;
|
|
49448
49449
|
}
|
|
49449
49450
|
async create(input) {
|
|
49450
49451
|
validateAdditionalData(input.additionalData);
|
|
49451
|
-
|
|
49452
|
+
const isFromTemplate = input.templateId != null;
|
|
49453
|
+
if (isFromTemplate) {
|
|
49454
|
+
const conflicting = [];
|
|
49455
|
+
if (input.userPrompt != null)
|
|
49456
|
+
conflicting.push("userPrompt");
|
|
49457
|
+
if (input.entity != null)
|
|
49458
|
+
conflicting.push("entity");
|
|
49459
|
+
if (input.fields != null)
|
|
49460
|
+
conflicting.push("fields");
|
|
49461
|
+
if (input.schemaId != null)
|
|
49462
|
+
conflicting.push("schemaId");
|
|
49463
|
+
if (input.monitoring != null)
|
|
49464
|
+
conflicting.push("monitoring");
|
|
49465
|
+
if (input.navigationMode != null)
|
|
49466
|
+
conflicting.push("navigationMode");
|
|
49467
|
+
if (conflicting.length > 0) {
|
|
49468
|
+
throw new KadoaSdkException(`Fields are defined by the template and cannot be supplied when creating from a template: ${conflicting.join(", ")}`, {
|
|
49469
|
+
code: "VALIDATION_ERROR",
|
|
49470
|
+
details: { conflicting }
|
|
49471
|
+
});
|
|
49472
|
+
}
|
|
49473
|
+
} else if (!input.userPrompt) {
|
|
49452
49474
|
throw new KadoaSdkException("userPrompt is required to create a workflow", {
|
|
49453
49475
|
code: "VALIDATION_ERROR",
|
|
49454
49476
|
details: { urls: input.urls }
|
|
49455
49477
|
});
|
|
49456
49478
|
}
|
|
49457
49479
|
const domainName = new URL(input.urls[0]).hostname;
|
|
49458
|
-
|
|
49459
|
-
|
|
49460
|
-
|
|
49461
|
-
|
|
49462
|
-
|
|
49463
|
-
|
|
49464
|
-
|
|
49465
|
-
|
|
49466
|
-
|
|
49467
|
-
|
|
49468
|
-
|
|
49469
|
-
|
|
49470
|
-
|
|
49471
|
-
|
|
49472
|
-
|
|
49473
|
-
|
|
49474
|
-
|
|
49475
|
-
|
|
49480
|
+
let request;
|
|
49481
|
+
if (isFromTemplate) {
|
|
49482
|
+
const templateId = input.templateId;
|
|
49483
|
+
const templateVersion = input.templateVersion ?? await this.resolveLatestVersion(templateId);
|
|
49484
|
+
request = {
|
|
49485
|
+
urls: input.urls,
|
|
49486
|
+
templateId,
|
|
49487
|
+
templateVersion,
|
|
49488
|
+
...input.name != null && { name: input.name },
|
|
49489
|
+
...input.description != null && { description: input.description },
|
|
49490
|
+
...input.tags != null && { tags: input.tags },
|
|
49491
|
+
...input.interval != null && { interval: input.interval },
|
|
49492
|
+
...input.schedules != null && { schedules: input.schedules },
|
|
49493
|
+
...input.location != null && { location: input.location },
|
|
49494
|
+
...input.bypassPreview != null && {
|
|
49495
|
+
bypassPreview: input.bypassPreview
|
|
49496
|
+
},
|
|
49497
|
+
...input.additionalData != null && {
|
|
49498
|
+
additionalData: input.additionalData
|
|
49499
|
+
},
|
|
49500
|
+
...input.limit != null && { limit: input.limit }
|
|
49501
|
+
};
|
|
49502
|
+
} else {
|
|
49503
|
+
request = {
|
|
49504
|
+
urls: input.urls,
|
|
49505
|
+
name: input.name ?? domainName,
|
|
49506
|
+
description: input.description,
|
|
49507
|
+
userPrompt: input.userPrompt,
|
|
49508
|
+
navigationMode: "agentic-navigation",
|
|
49509
|
+
schemaId: input.schemaId,
|
|
49510
|
+
...input.entity != null && { entity: input.entity },
|
|
49511
|
+
fields: input.fields,
|
|
49512
|
+
bypassPreview: input.bypassPreview ?? true,
|
|
49513
|
+
tags: input.tags,
|
|
49514
|
+
interval: input.interval,
|
|
49515
|
+
monitoring: input.monitoring,
|
|
49516
|
+
location: input.location,
|
|
49517
|
+
schedules: input.schedules,
|
|
49518
|
+
additionalData: input.additionalData,
|
|
49519
|
+
limit: input.limit
|
|
49520
|
+
};
|
|
49521
|
+
}
|
|
49476
49522
|
const response = await this.workflowsApi.v4WorkflowsPost({
|
|
49477
49523
|
publicWorkflowCreateRequest: request
|
|
49478
49524
|
});
|
|
@@ -49487,6 +49533,23 @@ var import_debug, __require2, ChangeDifferenceType, KadoaErrorCode, _KadoaSdkExc
|
|
|
49487
49533
|
}
|
|
49488
49534
|
return { id: workflowId };
|
|
49489
49535
|
}
|
|
49536
|
+
async resolveLatestVersion(templateId) {
|
|
49537
|
+
if (!this.templatesService) {
|
|
49538
|
+
throw new KadoaSdkException("TemplatesService is required to resolve a template's latest version. Pass `templateVersion` explicitly or construct WorkflowsCoreService with a TemplatesService.", {
|
|
49539
|
+
code: "INTERNAL_ERROR",
|
|
49540
|
+
details: { templateId }
|
|
49541
|
+
});
|
|
49542
|
+
}
|
|
49543
|
+
const template = await this.templatesService.get(templateId);
|
|
49544
|
+
const latest = template.latestVersion;
|
|
49545
|
+
if (latest == null) {
|
|
49546
|
+
throw new KadoaSdkException(`Template ${templateId} has no published versions; supply templateVersion explicitly or publish a version first.`, {
|
|
49547
|
+
code: "VALIDATION_ERROR",
|
|
49548
|
+
details: { templateId }
|
|
49549
|
+
});
|
|
49550
|
+
}
|
|
49551
|
+
return latest;
|
|
49552
|
+
}
|
|
49490
49553
|
async get(id) {
|
|
49491
49554
|
const response = await this.workflowsApi.v4WorkflowsWorkflowIdGet({
|
|
49492
49555
|
workflowId: id
|
|
@@ -50848,7 +50911,7 @@ function registerTools(server, ctx) {
|
|
|
50848
50911
|
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.")
|
|
50849
50912
|
};
|
|
50850
50913
|
const extractionInputShape = {
|
|
50851
|
-
prompt: exports_external.string().describe('Natural language description of what to extract (e.g., "Extract product prices and names")'),
|
|
50914
|
+
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.'),
|
|
50852
50915
|
name: exports_external.string().optional().describe("Optional name for the workflow"),
|
|
50853
50916
|
entity: exports_external.string().optional().describe("Entity name for extraction (e.g., 'Product', 'Job Posting')"),
|
|
50854
50917
|
schema: exports_external.preprocess(coerceArray(), exports_external.array(exports_external.object(SchemaFieldShape))).optional().describe("Extraction schema fields. If omitted, the AI agent auto-detects the schema.")
|
|
@@ -50953,10 +51016,12 @@ function registerTools(server, ctx) {
|
|
|
50953
51016
|
|
|
50954
51017
|
` + "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.
|
|
50955
51018
|
|
|
50956
|
-
` + "NOTE: This tool is for one-time or scheduled extraction ONLY. " + "For continuous real-time monitoring (watching a page for changes and alerting), use the create_realtime_monitor tool instead.",
|
|
51019
|
+
` + "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 `templateId` is set, only `urls` is required — `prompt`, `entity`, and `schema` must NOT be supplied; they are inherited from the template version.\n\n" + "NOTE: This tool is for one-time or scheduled extraction ONLY. " + "For continuous real-time monitoring (watching a page for changes and alerting), use the create_realtime_monitor tool instead.",
|
|
50957
51020
|
inputSchema: strictSchema({
|
|
50958
51021
|
...extractionInputShape,
|
|
50959
51022
|
...urlInputShape,
|
|
51023
|
+
templateId: exports_external.string().optional().describe("Instantiate this workflow from a published template. When set, only 'urls' is required — prompt/entity/schema must NOT be supplied; they are inherited from the template version. Discover templates via list_templates."),
|
|
51024
|
+
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."),
|
|
50960
51025
|
description: exports_external.string().max(500).optional().describe("Description of what this workflow does (max 500 characters)"),
|
|
50961
51026
|
tags: exports_external.preprocess(coerceArray(true), exports_external.array(exports_external.string())).optional().describe("Tags for organizing workflows"),
|
|
50962
51027
|
limit: exports_external.preprocess(coerceNumber(), exports_external.number()).optional().describe("Maximum number of records to extract per run. Useful for limiting scope or cost control."),
|
|
@@ -50991,32 +51056,62 @@ function registerTools(server, ctx) {
|
|
|
50991
51056
|
if (args.updateInterval === "CUSTOM" && (!args.schedules || args.schedules.length === 0)) {
|
|
50992
51057
|
return errorResult("updateInterval='CUSTOM' requires at least one cron expression in the 'schedules' field (e.g. '0 8 * * 2' for Tuesdays at 8am UTC).");
|
|
50993
51058
|
}
|
|
50994
|
-
let builder = ctx.client.extract({
|
|
50995
|
-
urls,
|
|
50996
|
-
name: args.name || "Untitled Workflow",
|
|
50997
|
-
userPrompt: args.prompt,
|
|
50998
|
-
extraction: buildExtraction(args),
|
|
50999
|
-
interval: args.updateInterval,
|
|
51000
|
-
description: args.description,
|
|
51001
|
-
schedules: args.schedules
|
|
51002
|
-
});
|
|
51003
51059
|
const n = args.notifications;
|
|
51004
|
-
const hasNotifications = n && (n.email || n.webhook || n.slack || n.websocket);
|
|
51005
|
-
|
|
51006
|
-
|
|
51007
|
-
|
|
51008
|
-
|
|
51060
|
+
const hasNotifications = !!(n && (n.email || n.webhook || n.slack || n.websocket));
|
|
51061
|
+
let workflowId;
|
|
51062
|
+
if (args.templateId) {
|
|
51063
|
+
if (args.prompt || args.entity || args.schema) {
|
|
51064
|
+
return errorResult("When 'templateId' is set, 'prompt', 'entity', and 'schema' must NOT be supplied — they are inherited from the template version.");
|
|
51065
|
+
}
|
|
51066
|
+
const { id } = await ctx.client.workflow.create({
|
|
51067
|
+
urls,
|
|
51068
|
+
name: args.name || "Untitled Workflow",
|
|
51069
|
+
description: args.description,
|
|
51070
|
+
interval: args.updateInterval,
|
|
51071
|
+
schedules: args.schedules,
|
|
51072
|
+
tags: args.tags && args.tags.length > 0 ? args.tags : undefined,
|
|
51073
|
+
limit: args.limit,
|
|
51074
|
+
templateId: args.templateId,
|
|
51075
|
+
templateVersion: args.templateVersion
|
|
51009
51076
|
});
|
|
51010
|
-
|
|
51011
|
-
|
|
51012
|
-
|
|
51013
|
-
|
|
51014
|
-
|
|
51015
|
-
|
|
51016
|
-
|
|
51017
|
-
|
|
51018
|
-
|
|
51019
|
-
|
|
51077
|
+
workflowId = id;
|
|
51078
|
+
if (hasNotifications) {
|
|
51079
|
+
await ctx.client.notification.configure({
|
|
51080
|
+
workflowId,
|
|
51081
|
+
events: ["workflow_data_change"],
|
|
51082
|
+
channels: buildNotificationChannels(n)
|
|
51083
|
+
});
|
|
51084
|
+
}
|
|
51085
|
+
} else {
|
|
51086
|
+
if (!args.prompt) {
|
|
51087
|
+
return errorResult("'prompt' is required unless 'templateId' is provided.");
|
|
51088
|
+
}
|
|
51089
|
+
let builder = ctx.client.extract({
|
|
51090
|
+
urls,
|
|
51091
|
+
name: args.name || "Untitled Workflow",
|
|
51092
|
+
userPrompt: args.prompt,
|
|
51093
|
+
extraction: buildExtraction(args),
|
|
51094
|
+
interval: args.updateInterval,
|
|
51095
|
+
description: args.description,
|
|
51096
|
+
schedules: args.schedules
|
|
51097
|
+
});
|
|
51098
|
+
if (hasNotifications) {
|
|
51099
|
+
builder = builder.withNotifications({
|
|
51100
|
+
events: ["workflow_data_change"],
|
|
51101
|
+
channels: buildNotificationChannels(n)
|
|
51102
|
+
});
|
|
51103
|
+
}
|
|
51104
|
+
const workflow = await builder.create();
|
|
51105
|
+
workflowId = workflow.workflowId;
|
|
51106
|
+
const needsUpdate = args.limit !== undefined || args.tags && args.tags.length > 0;
|
|
51107
|
+
if (needsUpdate) {
|
|
51108
|
+
const updates = {};
|
|
51109
|
+
if (args.limit !== undefined)
|
|
51110
|
+
updates.limit = args.limit;
|
|
51111
|
+
if (args.tags && args.tags.length > 0)
|
|
51112
|
+
updates.tags = args.tags;
|
|
51113
|
+
await ctx.client.workflow.update(workflowId, updates);
|
|
51114
|
+
}
|
|
51020
51115
|
}
|
|
51021
51116
|
const enabledChannels = await describeNotifications(n);
|
|
51022
51117
|
let message = "Workflow created successfully. The AI agent will start extracting data automatically.";
|
|
@@ -51026,8 +51121,8 @@ function registerTools(server, ctx) {
|
|
|
51026
51121
|
message += " Use fetch_data to retrieve the latest extracted results.";
|
|
51027
51122
|
return jsonResult({
|
|
51028
51123
|
success: true,
|
|
51029
|
-
workflowId
|
|
51030
|
-
dashboardUrl: workflowDashboardUrl(
|
|
51124
|
+
workflowId,
|
|
51125
|
+
dashboardUrl: workflowDashboardUrl(workflowId),
|
|
51031
51126
|
message
|
|
51032
51127
|
});
|
|
51033
51128
|
}));
|
|
@@ -51987,7 +52082,7 @@ var package_default;
|
|
|
51987
52082
|
var init_package = __esm(() => {
|
|
51988
52083
|
package_default = {
|
|
51989
52084
|
name: "@kadoa/mcp",
|
|
51990
|
-
version: "0.5.
|
|
52085
|
+
version: "0.5.7",
|
|
51991
52086
|
description: "Kadoa MCP Server — manage workflows from Claude Desktop, Cursor, and other MCP clients",
|
|
51992
52087
|
type: "module",
|
|
51993
52088
|
main: "dist/index.js",
|
|
@@ -52011,7 +52106,7 @@ var init_package = __esm(() => {
|
|
|
52011
52106
|
prepublishOnly: "bun run check-types && bun run test:unit && bun run build"
|
|
52012
52107
|
},
|
|
52013
52108
|
dependencies: {
|
|
52014
|
-
"@kadoa/node-sdk": "^0.
|
|
52109
|
+
"@kadoa/node-sdk": "^0.33.0",
|
|
52015
52110
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
52016
52111
|
express: "^5.2.1",
|
|
52017
52112
|
ioredis: "^5.6.1",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kadoa/mcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.7",
|
|
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.33.0",
|
|
28
28
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
29
29
|
"express": "^5.2.1",
|
|
30
30
|
"ioredis": "^5.6.1",
|