@kadoa/mcp 0.5.13 → 0.5.15
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 +7 -5
- package/dist/index.js +87 -13
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -24,16 +24,17 @@ claude mcp add kadoa --transport http https://mcp.kadoa.com/mcp
|
|
|
24
24
|
2. Enter the URL: `https://mcp.kadoa.com/mcp`
|
|
25
25
|
3. Sign in with your Kadoa account via OAuth
|
|
26
26
|
|
|
27
|
-
### Claude
|
|
27
|
+
### Claude service connector
|
|
28
28
|
|
|
29
|
-
A Kadoa workspace admin can generate
|
|
29
|
+
A Kadoa workspace admin can generate service connector credentials under **Workspace settings → MCP connector**. The generated OAuth client is fixed to that workspace's service account.
|
|
30
30
|
|
|
31
31
|
1. In Kadoa, select **Generate credentials** and copy the MCP URL, OAuth Client ID, and OAuth Client Secret. The secret is shown once.
|
|
32
32
|
2. In Claude organization **Admin settings → Connectors**, select **Add custom connector**.
|
|
33
|
-
3. Enter `https://mcp.kadoa.com/mcp` and paste the generated OAuth Client ID/Secret under Advanced settings.
|
|
34
|
-
4.
|
|
33
|
+
3. Enter `https://service.mcp.kadoa.com/mcp` and paste the generated OAuth Client ID/Secret under Advanced settings.
|
|
34
|
+
4. In the connector's tool settings, allow only the tools that organization members should use.
|
|
35
|
+
5. Organization members find the custom connector under **Settings → Connectors** and select **Connect**.
|
|
35
36
|
|
|
36
|
-
Members do not need Kadoa accounts. All actions are attributed to the shared Kadoa service account, and team switching is unavailable. To rotate access, rotate the secret in Kadoa, replace it in Claude, and reconnect. Revoking the connector stops access immediately.
|
|
37
|
+
The service connector uses a separate hostname from the personal connector at `https://mcp.kadoa.com/mcp`, so Claude users can configure both. Members do not need Kadoa accounts. All actions are attributed to the shared Kadoa service account, and team switching is unavailable. To rotate access, rotate the secret in Kadoa, replace it in Claude, and reconnect. Revoking the connector stops access immediately.
|
|
37
38
|
|
|
38
39
|
Do not paste a Kadoa workspace API key into Claude.
|
|
39
40
|
|
|
@@ -65,6 +66,7 @@ Point your client to `https://mcp.kadoa.com/mcp` with OAuth authentication.
|
|
|
65
66
|
| `list_workflows` | List all workflows with status |
|
|
66
67
|
| `get_workflow` | Get detailed workflow information |
|
|
67
68
|
| `get_workflow_history` | Get the workflow's configuration revision history (audit log) — who changed it, when, from which channel, and a `changedFields` summary per revision |
|
|
69
|
+
| `list_workflow_runs` | List a workflow's execution run history (status, start/finish, record count, errors); filter by outcome and paginate |
|
|
68
70
|
| `run_workflow` | Execute a workflow |
|
|
69
71
|
| `fetch_data` | Get extracted data from a workflow |
|
|
70
72
|
| `delete_workflow` | Delete a workflow |
|
package/dist/index.js
CHANGED
|
@@ -48467,7 +48467,7 @@ var import_debug, __require2, ChangeDifferenceType, KadoaErrorCode, _KadoaSdkExc
|
|
|
48467
48467
|
options: localVarRequestOptions
|
|
48468
48468
|
};
|
|
48469
48469
|
},
|
|
48470
|
-
v4WorkflowsWorkflowIdHistoryGet: async (workflowId, options = {}) => {
|
|
48470
|
+
v4WorkflowsWorkflowIdHistoryGet: async (workflowId, page, limit, status, options = {}) => {
|
|
48471
48471
|
assertParamExists("v4WorkflowsWorkflowIdHistoryGet", "workflowId", workflowId);
|
|
48472
48472
|
const localVarPath = `/v4/workflows/{workflowId}/history`.replace(`{${"workflowId"}}`, encodeURIComponent(String(workflowId)));
|
|
48473
48473
|
const localVarUrlObj = new URL$1(localVarPath, DUMMY_BASE_URL);
|
|
@@ -48479,6 +48479,15 @@ var import_debug, __require2, ChangeDifferenceType, KadoaErrorCode, _KadoaSdkExc
|
|
|
48479
48479
|
const localVarHeaderParameter = {};
|
|
48480
48480
|
const localVarQueryParameter = {};
|
|
48481
48481
|
await setApiKeyToObject(localVarHeaderParameter, "x-api-key", configuration);
|
|
48482
|
+
if (page !== undefined) {
|
|
48483
|
+
localVarQueryParameter["page"] = page;
|
|
48484
|
+
}
|
|
48485
|
+
if (limit !== undefined) {
|
|
48486
|
+
localVarQueryParameter["limit"] = limit;
|
|
48487
|
+
}
|
|
48488
|
+
if (status !== undefined) {
|
|
48489
|
+
localVarQueryParameter["status"] = status;
|
|
48490
|
+
}
|
|
48482
48491
|
localVarHeaderParameter["Accept"] = "application/json";
|
|
48483
48492
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
|
48484
48493
|
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
|
@@ -48842,8 +48851,8 @@ var import_debug, __require2, ChangeDifferenceType, KadoaErrorCode, _KadoaSdkExc
|
|
|
48842
48851
|
const localVarOperationServerBasePath = operationServerMap["WorkflowsApi.v4WorkflowsWorkflowIdGet"]?.[localVarOperationServerIndex]?.url;
|
|
48843
48852
|
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
48844
48853
|
},
|
|
48845
|
-
async v4WorkflowsWorkflowIdHistoryGet(workflowId, options) {
|
|
48846
|
-
const localVarAxiosArgs = await localVarAxiosParamCreator.v4WorkflowsWorkflowIdHistoryGet(workflowId, options);
|
|
48854
|
+
async v4WorkflowsWorkflowIdHistoryGet(workflowId, page, limit, status, options) {
|
|
48855
|
+
const localVarAxiosArgs = await localVarAxiosParamCreator.v4WorkflowsWorkflowIdHistoryGet(workflowId, page, limit, status, options);
|
|
48847
48856
|
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
|
48848
48857
|
const localVarOperationServerBasePath = operationServerMap["WorkflowsApi.v4WorkflowsWorkflowIdHistoryGet"]?.[localVarOperationServerIndex]?.url;
|
|
48849
48858
|
return (axios2, basePath) => createRequestFunction(localVarAxiosArgs, axios_default, BASE_PATH, configuration)(axios2, localVarOperationServerBasePath || basePath);
|
|
@@ -49308,7 +49317,7 @@ var import_debug, __require2, ChangeDifferenceType, KadoaErrorCode, _KadoaSdkExc
|
|
|
49308
49317
|
async executeExtraction(options) {
|
|
49309
49318
|
this.validateOptions(options);
|
|
49310
49319
|
const config2 = {
|
|
49311
|
-
...merge3(DEFAULT_OPTIONS, options)
|
|
49320
|
+
...merge3(merge3({}, DEFAULT_OPTIONS), options)
|
|
49312
49321
|
};
|
|
49313
49322
|
const isRealTime = config2.interval === "REAL_TIME";
|
|
49314
49323
|
if (isRealTime) {
|
|
@@ -49591,7 +49600,7 @@ var import_debug, __require2, ChangeDifferenceType, KadoaErrorCode, _KadoaSdkExc
|
|
|
49591
49600
|
assert2(startedJob.jobId, "Job ID is not set");
|
|
49592
49601
|
debug4("Job started: %O", startedJob);
|
|
49593
49602
|
this._jobId = startedJob.jobId;
|
|
49594
|
-
const finishedJob = await this.workflowsCoreService.waitForJobCompletion(this._workflowId, startedJob.jobId);
|
|
49603
|
+
const finishedJob = await this.workflowsCoreService.waitForJobCompletion(this._workflowId, startedJob.jobId, { timeoutMs: 30 * 60 * 1000 });
|
|
49595
49604
|
debug4("Job finished: %O", finishedJob);
|
|
49596
49605
|
return this;
|
|
49597
49606
|
}
|
|
@@ -50019,7 +50028,7 @@ var import_debug, __require2, ChangeDifferenceType, KadoaErrorCode, _KadoaSdkExc
|
|
|
50019
50028
|
}));
|
|
50020
50029
|
return channels;
|
|
50021
50030
|
}
|
|
50022
|
-
}, PUBLIC_API_URI, WSS_API_URI, REALTIME_API_URI, SDK_VERSION = "0.
|
|
50031
|
+
}, PUBLIC_API_URI, WSS_API_URI, REALTIME_API_URI, SDK_VERSION = "0.36.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 {
|
|
50023
50032
|
constructor(config2) {
|
|
50024
50033
|
this.drainingSockets = /* @__PURE__ */ new Set;
|
|
50025
50034
|
this.lastHeartbeat = Date.now();
|
|
@@ -50941,6 +50950,15 @@ var import_debug, __require2, ChangeDifferenceType, KadoaErrorCode, _KadoaSdkExc
|
|
|
50941
50950
|
});
|
|
50942
50951
|
return response.data;
|
|
50943
50952
|
}
|
|
50953
|
+
async listWorkflowRuns(id, options) {
|
|
50954
|
+
const response = await this.workflowsApi.v4WorkflowsWorkflowIdHistoryGet({
|
|
50955
|
+
workflowId: id,
|
|
50956
|
+
page: options?.page,
|
|
50957
|
+
limit: options?.limit,
|
|
50958
|
+
status: options?.status
|
|
50959
|
+
});
|
|
50960
|
+
return response.data;
|
|
50961
|
+
}
|
|
50944
50962
|
async delete(id) {
|
|
50945
50963
|
await this.workflowsApi.v4WorkflowsWorkflowIdDelete({
|
|
50946
50964
|
workflowId: id
|
|
@@ -51703,7 +51721,7 @@ var init_dist2 = __esm(() => {
|
|
|
51703
51721
|
return WorkflowsApiFp(this.configuration).v4WorkflowsWorkflowIdGet(requestParameters.workflowId, options).then((request) => request(this.axios, this.basePath));
|
|
51704
51722
|
}
|
|
51705
51723
|
v4WorkflowsWorkflowIdHistoryGet(requestParameters, options) {
|
|
51706
|
-
return WorkflowsApiFp(this.configuration).v4WorkflowsWorkflowIdHistoryGet(requestParameters.workflowId, options).then((request) => request(this.axios, this.basePath));
|
|
51724
|
+
return WorkflowsApiFp(this.configuration).v4WorkflowsWorkflowIdHistoryGet(requestParameters.workflowId, requestParameters.page, requestParameters.limit, requestParameters.status, options).then((request) => request(this.axios, this.basePath));
|
|
51707
51725
|
}
|
|
51708
51726
|
v4WorkflowsWorkflowIdJobsJobIdGet(requestParameters, options) {
|
|
51709
51727
|
return WorkflowsApiFp(this.configuration).v4WorkflowsWorkflowIdJobsJobIdGet(requestParameters.workflowId, requestParameters.jobId, options).then((request) => request(this.axios, this.basePath));
|
|
@@ -51799,7 +51817,7 @@ This is the main page content.`
|
|
|
51799
51817
|
DEFAULT_OPTIONS = {
|
|
51800
51818
|
mode: "run",
|
|
51801
51819
|
pollingInterval: 5000,
|
|
51802
|
-
maxWaitTime:
|
|
51820
|
+
maxWaitTime: 30 * 60 * 1000,
|
|
51803
51821
|
location: { type: "auto" },
|
|
51804
51822
|
bypassPreview: true,
|
|
51805
51823
|
autoStart: true
|
|
@@ -52141,6 +52159,21 @@ function deriveStatusLabel(workflow) {
|
|
|
52141
52159
|
return ds ?? "Unknown";
|
|
52142
52160
|
}
|
|
52143
52161
|
}
|
|
52162
|
+
function mapRunStatus(state) {
|
|
52163
|
+
switch (state) {
|
|
52164
|
+
case "FINISHED":
|
|
52165
|
+
return "success";
|
|
52166
|
+
case "IN_PROGRESS":
|
|
52167
|
+
case "VALIDATING":
|
|
52168
|
+
return "in_progress";
|
|
52169
|
+
case "FAILED":
|
|
52170
|
+
case "FAILED_INSUFFICIENT_FUNDS":
|
|
52171
|
+
case "NOT_SUPPORTED":
|
|
52172
|
+
return "failed";
|
|
52173
|
+
default:
|
|
52174
|
+
return "failed";
|
|
52175
|
+
}
|
|
52176
|
+
}
|
|
52144
52177
|
function workflowDashboardUrl(workflowId) {
|
|
52145
52178
|
return `${DASHBOARD_BASE_URL}/workflow/${workflowId}`;
|
|
52146
52179
|
}
|
|
@@ -52735,6 +52768,35 @@ function registerTools(server, ctx, capabilities) {
|
|
|
52735
52768
|
entries
|
|
52736
52769
|
});
|
|
52737
52770
|
}));
|
|
52771
|
+
server.registerTool("list_workflow_runs", {
|
|
52772
|
+
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.",
|
|
52773
|
+
inputSchema: {
|
|
52774
|
+
workflowId: exports_external.string().describe("The workflow ID"),
|
|
52775
|
+
status: exports_external.enum(["success", "failed", "in_progress"]).optional().describe("Filter runs by outcome"),
|
|
52776
|
+
page: exports_external.preprocess(coerceNumber(), exports_external.number()).optional().describe("Page number, 1-based (default: 1)"),
|
|
52777
|
+
limit: exports_external.preprocess(coerceNumber(), exports_external.number()).optional().describe("Runs per page (default: 25)")
|
|
52778
|
+
},
|
|
52779
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true }
|
|
52780
|
+
}, withErrorHandling("list_workflow_runs", async (args) => {
|
|
52781
|
+
const response = await ctx.client.workflow.listWorkflowRuns(args.workflowId, {
|
|
52782
|
+
page: args.page,
|
|
52783
|
+
limit: args.limit,
|
|
52784
|
+
status: args.status
|
|
52785
|
+
});
|
|
52786
|
+
return jsonResult({
|
|
52787
|
+
workflowId: response.workflowId,
|
|
52788
|
+
runs: (response.workflowRuns ?? []).map((r) => ({
|
|
52789
|
+
id: r.id,
|
|
52790
|
+
status: mapRunStatus(r.state),
|
|
52791
|
+
startedAt: r.startedAt,
|
|
52792
|
+
finishedAt: r.finishedAt,
|
|
52793
|
+
records: r.records,
|
|
52794
|
+
errors: r.errors
|
|
52795
|
+
})),
|
|
52796
|
+
totalCount: response.totalCount,
|
|
52797
|
+
pagination: response.pagination
|
|
52798
|
+
});
|
|
52799
|
+
}));
|
|
52738
52800
|
server.registerTool("run_workflow", {
|
|
52739
52801
|
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.",
|
|
52740
52802
|
inputSchema: {
|
|
@@ -53662,7 +53724,7 @@ var package_default;
|
|
|
53662
53724
|
var init_package = __esm(() => {
|
|
53663
53725
|
package_default = {
|
|
53664
53726
|
name: "@kadoa/mcp",
|
|
53665
|
-
version: "0.5.
|
|
53727
|
+
version: "0.5.15",
|
|
53666
53728
|
description: "Kadoa MCP Server — manage workflows from Claude Desktop, Cursor, and other MCP clients",
|
|
53667
53729
|
type: "module",
|
|
53668
53730
|
main: "dist/index.js",
|
|
@@ -53686,7 +53748,7 @@ var init_package = __esm(() => {
|
|
|
53686
53748
|
prepublishOnly: "bun run check-types && bun run test:unit && bun run build"
|
|
53687
53749
|
},
|
|
53688
53750
|
dependencies: {
|
|
53689
|
-
"@kadoa/node-sdk": "^0.
|
|
53751
|
+
"@kadoa/node-sdk": "^0.36.0",
|
|
53690
53752
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
53691
53753
|
express: "^5.2.1",
|
|
53692
53754
|
"express-rate-limit": "^8.2.1",
|
|
@@ -57695,6 +57757,15 @@ var init_bearerAuth = __esm(() => {
|
|
|
57695
57757
|
init_errors4();
|
|
57696
57758
|
});
|
|
57697
57759
|
|
|
57760
|
+
// src/managed-connector-client.ts
|
|
57761
|
+
function isManagedConnectorClientId(clientId) {
|
|
57762
|
+
return MANAGED_CONNECTOR_CLIENT_ID_PREFIXES.some((prefix) => clientId.startsWith(prefix));
|
|
57763
|
+
}
|
|
57764
|
+
var MANAGED_CONNECTOR_CLIENT_ID_PREFIXES;
|
|
57765
|
+
var init_managed_connector_client = __esm(() => {
|
|
57766
|
+
MANAGED_CONNECTOR_CLIENT_ID_PREFIXES = ["kadoa_mcp_", "kadoa_claude_"];
|
|
57767
|
+
});
|
|
57768
|
+
|
|
57698
57769
|
// src/managed-connector-registry.ts
|
|
57699
57770
|
class ManagedConnectorRegistry {
|
|
57700
57771
|
baseUrl;
|
|
@@ -57894,7 +57965,7 @@ class KadoaOAuthProvider {
|
|
|
57894
57965
|
const thisProvider = this;
|
|
57895
57966
|
return {
|
|
57896
57967
|
async getClient(clientId) {
|
|
57897
|
-
if (clientId
|
|
57968
|
+
if (isManagedConnectorClientId(clientId)) {
|
|
57898
57969
|
const connector = await thisProvider.getManagedRegistry().get(clientId);
|
|
57899
57970
|
if (!connector)
|
|
57900
57971
|
return;
|
|
@@ -58834,6 +58905,7 @@ function escapeHtml(str) {
|
|
|
58834
58905
|
var TEAM_SELECTION_TTL, ACCESS_TOKEN_TTL;
|
|
58835
58906
|
var init_auth2 = __esm(() => {
|
|
58836
58907
|
init_errors4();
|
|
58908
|
+
init_managed_connector_client();
|
|
58837
58909
|
init_managed_connector_registry();
|
|
58838
58910
|
TEAM_SELECTION_TTL = 10 * 60 * 1000;
|
|
58839
58911
|
ACCESS_TOKEN_TTL = 7 * 24 * 3600;
|
|
@@ -58954,7 +59026,7 @@ function managedTokenHandler(options) {
|
|
|
58954
59026
|
return async (req, res, next) => {
|
|
58955
59027
|
const body = req.body ?? {};
|
|
58956
59028
|
const clientId = typeof body.client_id === "string" ? body.client_id : "";
|
|
58957
|
-
if (!clientId
|
|
59029
|
+
if (!isManagedConnectorClientId(clientId)) {
|
|
58958
59030
|
next();
|
|
58959
59031
|
return;
|
|
58960
59032
|
}
|
|
@@ -59001,6 +59073,7 @@ function managedTokenHandler(options) {
|
|
|
59001
59073
|
}
|
|
59002
59074
|
var init_managed_token_handler = __esm(() => {
|
|
59003
59075
|
init_errors4();
|
|
59076
|
+
init_managed_connector_client();
|
|
59004
59077
|
init_managed_connector_registry();
|
|
59005
59078
|
});
|
|
59006
59079
|
|
|
@@ -59064,7 +59137,7 @@ async function startHttpServer(options) {
|
|
|
59064
59137
|
limit: 50,
|
|
59065
59138
|
standardHeaders: true,
|
|
59066
59139
|
legacyHeaders: false,
|
|
59067
|
-
skip: (req) => !String(req.body?.client_id ?? "")
|
|
59140
|
+
skip: (req) => !isManagedConnectorClientId(String(req.body?.client_id ?? "")),
|
|
59068
59141
|
message: {
|
|
59069
59142
|
error: "too_many_requests",
|
|
59070
59143
|
error_description: "Too many managed connector token requests"
|
|
@@ -59229,6 +59302,7 @@ var init_http2 = __esm(async () => {
|
|
|
59229
59302
|
init_auth2();
|
|
59230
59303
|
init_redis_store();
|
|
59231
59304
|
init_client2();
|
|
59305
|
+
init_managed_connector_client();
|
|
59232
59306
|
init_managed_connector_registry();
|
|
59233
59307
|
init_managed_token_handler();
|
|
59234
59308
|
await init_src();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kadoa/mcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.15",
|
|
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.36.0",
|
|
28
28
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
29
29
|
"express": "^5.2.1",
|
|
30
30
|
"express-rate-limit": "^8.2.1",
|