@kadoa/mcp 0.3.5-rc.5 → 0.3.5-rc.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/dist/index.js +188 -117
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -49312,21 +49312,88 @@ function registerTools(server, ctx) {
|
|
|
49312
49312
|
}))
|
|
49313
49313
|
});
|
|
49314
49314
|
}));
|
|
49315
|
+
const urlInputShape = {
|
|
49316
|
+
url: exports_external.string().optional().describe("Single URL — prefer using 'urls' instead. If both are provided, 'urls' takes precedence."),
|
|
49317
|
+
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.")
|
|
49318
|
+
};
|
|
49319
|
+
const extractionInputShape = {
|
|
49320
|
+
prompt: exports_external.string().describe('Natural language description of what to extract (e.g., "Extract product prices and names")'),
|
|
49321
|
+
name: exports_external.string().optional().describe("Optional name for the workflow"),
|
|
49322
|
+
entity: exports_external.string().optional().describe("Entity name for extraction (e.g., 'Product', 'Job Posting')"),
|
|
49323
|
+
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.")
|
|
49324
|
+
};
|
|
49325
|
+
const notificationsInputShape = {
|
|
49326
|
+
notifications: exports_external.object({
|
|
49327
|
+
email: exports_external.boolean().optional().describe("Send email notifications to the account email when data changes"),
|
|
49328
|
+
webhook: exports_external.object({
|
|
49329
|
+
url: exports_external.string().url().describe("Webhook endpoint URL"),
|
|
49330
|
+
httpMethod: exports_external.enum(["POST", "GET", "PUT", "PATCH"]).optional().describe("HTTP method (defaults to POST)")
|
|
49331
|
+
}).optional().describe("Send notifications via HTTP webhook"),
|
|
49332
|
+
slack: exports_external.object({
|
|
49333
|
+
webhookUrl: exports_external.string().url().describe("Slack incoming webhook URL")
|
|
49334
|
+
}).optional().describe("Send notifications to a Slack channel"),
|
|
49335
|
+
websocket: exports_external.boolean().optional().describe("Enable WebSocket notifications for programmatic real-time consumption")
|
|
49336
|
+
}).optional().describe("Notification channels to alert when data changes.")
|
|
49337
|
+
};
|
|
49338
|
+
function resolveUrls(args) {
|
|
49339
|
+
const urls = args.urls ?? (args.url ? [args.url] : []);
|
|
49340
|
+
return urls.length > 0 ? urls : null;
|
|
49341
|
+
}
|
|
49342
|
+
function buildExtraction(args) {
|
|
49343
|
+
if (!args.schema)
|
|
49344
|
+
return;
|
|
49345
|
+
return (builder) => {
|
|
49346
|
+
const entity = builder.entity(args.entity || "Data");
|
|
49347
|
+
for (const field of args.schema) {
|
|
49348
|
+
entity.field(field.name, field.description || field.name, field.dataType || "STRING", { example: field.example });
|
|
49349
|
+
}
|
|
49350
|
+
return entity;
|
|
49351
|
+
};
|
|
49352
|
+
}
|
|
49353
|
+
function buildNotificationChannels(n) {
|
|
49354
|
+
const channels = {};
|
|
49355
|
+
if (n.email)
|
|
49356
|
+
channels.EMAIL = true;
|
|
49357
|
+
if (n.websocket)
|
|
49358
|
+
channels.WEBSOCKET = true;
|
|
49359
|
+
if (n.webhook) {
|
|
49360
|
+
channels.WEBHOOK = {
|
|
49361
|
+
name: "mcp-webhook",
|
|
49362
|
+
webhookUrl: n.webhook.url,
|
|
49363
|
+
httpMethod: n.webhook.httpMethod || "POST"
|
|
49364
|
+
};
|
|
49365
|
+
}
|
|
49366
|
+
if (n.slack) {
|
|
49367
|
+
channels.SLACK = {
|
|
49368
|
+
name: "mcp-slack",
|
|
49369
|
+
webhookUrl: n.slack.webhookUrl
|
|
49370
|
+
};
|
|
49371
|
+
}
|
|
49372
|
+
return channels;
|
|
49373
|
+
}
|
|
49374
|
+
async function describeNotifications(n) {
|
|
49375
|
+
if (!n)
|
|
49376
|
+
return [];
|
|
49377
|
+
const channels = [];
|
|
49378
|
+
if (n.email) {
|
|
49379
|
+
const user = await ctx.client.user.getCurrentUser();
|
|
49380
|
+
channels.push(`email (${user.email})`);
|
|
49381
|
+
}
|
|
49382
|
+
if (n.slack)
|
|
49383
|
+
channels.push(`slack (${n.slack.webhookUrl})`);
|
|
49384
|
+
if (n.webhook)
|
|
49385
|
+
channels.push(`webhook (${n.webhook.url})`);
|
|
49386
|
+
if (n.websocket)
|
|
49387
|
+
channels.push("websocket");
|
|
49388
|
+
return channels;
|
|
49389
|
+
}
|
|
49315
49390
|
server.registerTool("create_workflow", {
|
|
49316
|
-
description:
|
|
49391
|
+
description: "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.
|
|
49317
49392
|
|
|
49318
|
-
` +
|
|
49319
|
-
` + `• REAL_TIME workflows are fundamentally different from regular extraction workflows. They route to a separate Observer service, run continuously, and cannot be triggered manually.
|
|
49320
|
-
` + `• A regular workflow CANNOT be converted to real-time after creation (and vice versa). The interval=REAL_TIME flag MUST be set at creation time.
|
|
49321
|
-
` + `• If the user wants to monitor a page for changes, set interval='REAL_TIME' here. Do NOT create a regular workflow and then try to change its interval to REAL_TIME via update_workflow — this will be rejected.
|
|
49322
|
-
` + "• When the user says 'monitor', 'track', 'watch', or 'alert me' — ASK if they want real-time continuous monitoring (interval='REAL_TIME') or scheduled extraction. Do NOT assume one or the other.",
|
|
49393
|
+
` + "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.",
|
|
49323
49394
|
inputSchema: strictSchema({
|
|
49324
|
-
|
|
49325
|
-
|
|
49326
|
-
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."),
|
|
49327
|
-
name: exports_external.string().optional().describe("Optional name for the workflow"),
|
|
49328
|
-
entity: exports_external.string().optional().describe("Entity name for extraction (e.g., 'Product', 'Job Posting')"),
|
|
49329
|
-
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."),
|
|
49395
|
+
...extractionInputShape,
|
|
49396
|
+
...urlInputShape,
|
|
49330
49397
|
interval: exports_external.enum([
|
|
49331
49398
|
"ONLY_ONCE",
|
|
49332
49399
|
"EVERY_10_MINUTES",
|
|
@@ -49343,103 +49410,35 @@ function registerTools(server, ctx) {
|
|
|
49343
49410
|
"BIWEEKLY",
|
|
49344
49411
|
"TRIWEEKLY",
|
|
49345
49412
|
"FOUR_WEEKS",
|
|
49346
|
-
"MONTHLY"
|
|
49347
|
-
|
|
49348
|
-
|
|
49349
|
-
notifications: exports_external.object({
|
|
49350
|
-
email: exports_external.boolean().optional().describe("Send email notifications to the account email when data changes"),
|
|
49351
|
-
webhook: exports_external.object({
|
|
49352
|
-
url: exports_external.string().url().describe("Webhook endpoint URL"),
|
|
49353
|
-
httpMethod: exports_external.enum(["POST", "GET", "PUT", "PATCH"]).optional().describe("HTTP method (defaults to POST)")
|
|
49354
|
-
}).optional().describe("Send notifications via HTTP webhook"),
|
|
49355
|
-
slack: exports_external.object({
|
|
49356
|
-
webhookUrl: exports_external.string().url().describe("Slack incoming webhook URL")
|
|
49357
|
-
}).optional().describe("Send notifications to a Slack channel"),
|
|
49358
|
-
websocket: exports_external.boolean().optional().describe("Enable WebSocket notifications for programmatic real-time consumption")
|
|
49359
|
-
}).optional().describe("Notification channels to alert when data changes. At least one channel is required for REAL_TIME workflows.")
|
|
49413
|
+
"MONTHLY"
|
|
49414
|
+
]).optional().describe("How often the workflow runs. Defaults to ONLY_ONCE."),
|
|
49415
|
+
...notificationsInputShape
|
|
49360
49416
|
}),
|
|
49361
49417
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false }
|
|
49362
49418
|
}, withErrorHandling("create_workflow", async (args) => {
|
|
49363
|
-
const urls =
|
|
49364
|
-
if (urls
|
|
49419
|
+
const urls = resolveUrls(args);
|
|
49420
|
+
if (!urls) {
|
|
49365
49421
|
return errorResult("At least one URL is required. Provide 'urls' (array) or 'url' (string).");
|
|
49366
49422
|
}
|
|
49367
|
-
let interval = args.interval;
|
|
49368
|
-
if (!interval && REALTIME_INTENT_KEYWORDS.test(args.prompt || "")) {
|
|
49369
|
-
const answer = await elicit("Your request sounds like it could be either real-time monitoring or scheduled extraction. Which do you want?", {
|
|
49370
|
-
workflowType: {
|
|
49371
|
-
type: "string",
|
|
49372
|
-
enum: ["Real-time monitoring (continuous, alerts on changes)", "Scheduled extraction (one-time or recurring data pull)"],
|
|
49373
|
-
description: "Choose the workflow type"
|
|
49374
|
-
}
|
|
49375
|
-
}, ["workflowType"]);
|
|
49376
|
-
if (answer === null) {} else if (typeof answer.workflowType === "string" && answer.workflowType.startsWith("Real-time")) {
|
|
49377
|
-
interval = "REAL_TIME";
|
|
49378
|
-
}
|
|
49379
|
-
}
|
|
49380
|
-
const n = args.notifications;
|
|
49381
|
-
const hasNotifications = n && (n.email || n.webhook || n.slack || n.websocket);
|
|
49382
|
-
if (interval === "REAL_TIME" && !hasNotifications) {
|
|
49383
|
-
return errorResult("Real-time workflows require at least one notification channel so you get alerted when data changes. " + "Add a notifications object with one or more channels: email, webhook, slack, or websocket.");
|
|
49384
|
-
}
|
|
49385
|
-
const extraction = args.schema ? (builder2) => {
|
|
49386
|
-
const entity = builder2.entity(args.entity || "Data");
|
|
49387
|
-
for (const field of args.schema) {
|
|
49388
|
-
entity.field(field.name, field.description || field.name, field.dataType || "STRING", { example: field.example });
|
|
49389
|
-
}
|
|
49390
|
-
return entity;
|
|
49391
|
-
} : undefined;
|
|
49392
|
-
const isRealTime = interval === "REAL_TIME";
|
|
49393
49423
|
let builder = ctx.client.extract({
|
|
49394
49424
|
urls,
|
|
49395
49425
|
name: args.name || "Untitled Workflow",
|
|
49396
|
-
|
|
49426
|
+
navigationMode: "agentic-navigation",
|
|
49397
49427
|
userPrompt: args.prompt,
|
|
49398
|
-
extraction,
|
|
49399
|
-
interval
|
|
49428
|
+
extraction: buildExtraction(args),
|
|
49429
|
+
interval: args.interval
|
|
49400
49430
|
});
|
|
49431
|
+
const n = args.notifications;
|
|
49432
|
+
const hasNotifications = n && (n.email || n.webhook || n.slack || n.websocket);
|
|
49401
49433
|
if (hasNotifications) {
|
|
49402
|
-
const channels = {};
|
|
49403
|
-
if (n.email)
|
|
49404
|
-
channels.EMAIL = true;
|
|
49405
|
-
if (n.websocket)
|
|
49406
|
-
channels.WEBSOCKET = true;
|
|
49407
|
-
if (n.webhook) {
|
|
49408
|
-
channels.WEBHOOK = {
|
|
49409
|
-
name: "mcp-webhook",
|
|
49410
|
-
webhookUrl: n.webhook.url,
|
|
49411
|
-
httpMethod: n.webhook.httpMethod || "POST"
|
|
49412
|
-
};
|
|
49413
|
-
}
|
|
49414
|
-
if (n.slack) {
|
|
49415
|
-
channels.SLACK = {
|
|
49416
|
-
name: "mcp-slack",
|
|
49417
|
-
webhookUrl: n.slack.webhookUrl
|
|
49418
|
-
};
|
|
49419
|
-
}
|
|
49420
49434
|
builder = builder.withNotifications({
|
|
49421
49435
|
events: ["workflow_data_change"],
|
|
49422
|
-
channels
|
|
49436
|
+
channels: buildNotificationChannels(n)
|
|
49423
49437
|
});
|
|
49424
49438
|
}
|
|
49425
49439
|
const workflow = await builder.create();
|
|
49426
|
-
const enabledChannels =
|
|
49427
|
-
|
|
49428
|
-
const user = await ctx.client.user.getCurrentUser();
|
|
49429
|
-
enabledChannels.push(`email (${user.email})`);
|
|
49430
|
-
}
|
|
49431
|
-
if (n?.slack)
|
|
49432
|
-
enabledChannels.push(`slack (${n.slack.webhookUrl})`);
|
|
49433
|
-
if (n?.webhook)
|
|
49434
|
-
enabledChannels.push(`webhook (${n.webhook.url})`);
|
|
49435
|
-
if (n?.websocket)
|
|
49436
|
-
enabledChannels.push("websocket");
|
|
49437
|
-
let message = "Workflow created successfully.";
|
|
49438
|
-
if (interval === "REAL_TIME") {
|
|
49439
|
-
message += " This real-time workflow monitors continuously — no manual runs needed.";
|
|
49440
|
-
} else {
|
|
49441
|
-
message += " The AI agent will start extracting data automatically.";
|
|
49442
|
-
}
|
|
49440
|
+
const enabledChannels = await describeNotifications(n);
|
|
49441
|
+
let message = "Workflow created successfully. The AI agent will start extracting data automatically.";
|
|
49443
49442
|
if (enabledChannels.length > 0) {
|
|
49444
49443
|
message += ` Notifications on data changes via: ${enabledChannels.join(", ")}.`;
|
|
49445
49444
|
}
|
|
@@ -49450,6 +49449,50 @@ function registerTools(server, ctx) {
|
|
|
49450
49449
|
message
|
|
49451
49450
|
});
|
|
49452
49451
|
}));
|
|
49452
|
+
server.registerTool("create_realtime_monitor", {
|
|
49453
|
+
description: "Create a real-time monitoring workflow that continuously watches a page for changes and sends alerts. " + "Use this when the user wants to monitor, track, or watch a page in real-time. " + "At least one notification channel (email, webhook, slack, or websocket) is required so the user gets alerted on changes. " + `Real-time monitors route to a separate Observer service and CANNOT be converted to/from regular extraction workflows after creation.
|
|
49454
|
+
|
|
49455
|
+
` + "If entity and schema are provided, they guide what to monitor; otherwise the AI agent auto-detects what to watch. " + "Do NOT poll or sleep-wait for completion. Return the workflow ID and let the user check back with get_workflow or fetch_data.",
|
|
49456
|
+
inputSchema: strictSchema({
|
|
49457
|
+
...extractionInputShape,
|
|
49458
|
+
...urlInputShape,
|
|
49459
|
+
...notificationsInputShape
|
|
49460
|
+
}),
|
|
49461
|
+
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false }
|
|
49462
|
+
}, withErrorHandling("create_realtime_monitor", async (args) => {
|
|
49463
|
+
const urls = resolveUrls(args);
|
|
49464
|
+
if (!urls) {
|
|
49465
|
+
return errorResult("At least one URL is required. Provide 'urls' (array) or 'url' (string).");
|
|
49466
|
+
}
|
|
49467
|
+
const n = args.notifications;
|
|
49468
|
+
const hasNotifications = n && (n.email || n.webhook || n.slack || n.websocket);
|
|
49469
|
+
if (!hasNotifications) {
|
|
49470
|
+
return errorResult("Real-time monitors require at least one notification channel so you get alerted when data changes. " + "Add a notifications object with one or more channels: email, webhook, slack, or websocket.");
|
|
49471
|
+
}
|
|
49472
|
+
let builder = ctx.client.extract({
|
|
49473
|
+
urls,
|
|
49474
|
+
name: args.name || "Untitled Monitor",
|
|
49475
|
+
userPrompt: args.prompt,
|
|
49476
|
+
extraction: buildExtraction(args),
|
|
49477
|
+
interval: "REAL_TIME"
|
|
49478
|
+
});
|
|
49479
|
+
builder = builder.withNotifications({
|
|
49480
|
+
events: ["workflow_data_change"],
|
|
49481
|
+
channels: buildNotificationChannels(n)
|
|
49482
|
+
});
|
|
49483
|
+
const workflow = await builder.create();
|
|
49484
|
+
const enabledChannels = await describeNotifications(n);
|
|
49485
|
+
let message = "Real-time monitor created successfully. It will continuously watch for changes — no manual runs needed.";
|
|
49486
|
+
if (enabledChannels.length > 0) {
|
|
49487
|
+
message += ` Notifications on data changes via: ${enabledChannels.join(", ")}.`;
|
|
49488
|
+
}
|
|
49489
|
+
message += " Use fetch_data to retrieve the latest data.";
|
|
49490
|
+
return jsonResult({
|
|
49491
|
+
success: true,
|
|
49492
|
+
workflowId: workflow.workflowId,
|
|
49493
|
+
message
|
|
49494
|
+
});
|
|
49495
|
+
}));
|
|
49453
49496
|
server.registerTool("list_workflows", {
|
|
49454
49497
|
description: "List all workflows with their current status",
|
|
49455
49498
|
inputSchema: {
|
|
@@ -49550,28 +49593,35 @@ function registerTools(server, ctx) {
|
|
|
49550
49593
|
});
|
|
49551
49594
|
}));
|
|
49552
49595
|
server.registerTool("delete_workflow", {
|
|
49553
|
-
description: "Delete a workflow permanently",
|
|
49596
|
+
description: "Delete a workflow permanently. This is irreversible. " + "You MUST first call this tool without confirmed=true to preview what will be deleted, " + "then show the user the workflow name and ask for confirmation, " + "then call again with confirmed=true only after the user explicitly agrees.",
|
|
49554
49597
|
inputSchema: {
|
|
49555
|
-
workflowId: exports_external.string().describe("The workflow ID to delete")
|
|
49598
|
+
workflowId: exports_external.string().describe("The workflow ID to delete"),
|
|
49599
|
+
confirmed: exports_external.boolean().optional().describe("Set to true only after the user has explicitly confirmed deletion. Omit or set to false for the initial preview call.")
|
|
49556
49600
|
},
|
|
49557
49601
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true }
|
|
49558
49602
|
}, withErrorHandling("delete_workflow", async (args) => {
|
|
49559
49603
|
let workflowName = args.workflowId;
|
|
49604
|
+
let workflowStatus = "unknown";
|
|
49560
49605
|
try {
|
|
49561
49606
|
const workflow = await ctx.client.workflow.get(args.workflowId);
|
|
49562
49607
|
workflowName = workflow.name || args.workflowId;
|
|
49608
|
+
workflowStatus = workflow.displayState ?? workflow.state ?? "unknown";
|
|
49563
49609
|
} catch {}
|
|
49564
|
-
|
|
49565
|
-
confirm: {
|
|
49566
|
-
|
|
49567
|
-
|
|
49610
|
+
if (!args.confirmed) {
|
|
49611
|
+
const confirmation = await elicit(`Are you sure you want to permanently delete "${workflowName}" (${workflowStatus})? This cannot be undone.`, { confirm: { type: "boolean", description: "Confirm deletion" } }, ["confirm"]);
|
|
49612
|
+
if (confirmation !== null) {
|
|
49613
|
+
if (!confirmation.confirm) {
|
|
49614
|
+
return jsonResult({ success: false, message: "Deletion cancelled by user." });
|
|
49615
|
+
}
|
|
49616
|
+
} else {
|
|
49617
|
+
return jsonResult({
|
|
49618
|
+
pending: true,
|
|
49619
|
+
workflowId: args.workflowId,
|
|
49620
|
+
workflowName,
|
|
49621
|
+
status: workflowStatus,
|
|
49622
|
+
message: `⚠️ You are about to permanently delete "${workflowName}" (${workflowStatus}). This cannot be undone. Ask the user to confirm, then call delete_workflow again with confirmed=true.`
|
|
49623
|
+
});
|
|
49568
49624
|
}
|
|
49569
|
-
}, ["confirm"]);
|
|
49570
|
-
if (confirmation !== null && !confirmation.confirm) {
|
|
49571
|
-
return jsonResult({
|
|
49572
|
-
success: false,
|
|
49573
|
-
message: "Deletion cancelled by user."
|
|
49574
|
-
});
|
|
49575
49625
|
}
|
|
49576
49626
|
await ctx.client.workflow.delete(args.workflowId);
|
|
49577
49627
|
return jsonResult({
|
|
@@ -49700,15 +49750,26 @@ function registerTools(server, ctx) {
|
|
|
49700
49750
|
});
|
|
49701
49751
|
}));
|
|
49702
49752
|
server.registerTool("delete_notification_channel", {
|
|
49703
|
-
description: "Delete a notification channel by ID",
|
|
49753
|
+
description: "Delete a notification channel by ID. " + "Call first without confirmed=true to preview, then with confirmed=true after user agrees.",
|
|
49704
49754
|
inputSchema: {
|
|
49705
|
-
channelId: exports_external.string().describe("The channel ID to delete")
|
|
49755
|
+
channelId: exports_external.string().describe("The channel ID to delete"),
|
|
49756
|
+
confirmed: exports_external.boolean().optional().describe("Set to true only after the user has explicitly confirmed deletion.")
|
|
49706
49757
|
},
|
|
49707
49758
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true }
|
|
49708
49759
|
}, withErrorHandling("delete_notification_channel", async (args) => {
|
|
49709
|
-
|
|
49710
|
-
|
|
49711
|
-
|
|
49760
|
+
if (!args.confirmed) {
|
|
49761
|
+
const confirmation = await elicit(`Are you sure you want to delete notification channel "${args.channelId}"?`, { confirm: { type: "boolean", description: "Confirm deletion" } }, ["confirm"]);
|
|
49762
|
+
if (confirmation !== null) {
|
|
49763
|
+
if (!confirmation.confirm) {
|
|
49764
|
+
return jsonResult({ success: false, message: "Deletion cancelled by user." });
|
|
49765
|
+
}
|
|
49766
|
+
} else {
|
|
49767
|
+
return jsonResult({
|
|
49768
|
+
pending: true,
|
|
49769
|
+
channelId: args.channelId,
|
|
49770
|
+
message: `⚠️ About to delete notification channel "${args.channelId}". Ask the user to confirm, then call again with confirmed=true.`
|
|
49771
|
+
});
|
|
49772
|
+
}
|
|
49712
49773
|
}
|
|
49713
49774
|
await ctx.client.notification.channels.deleteChannel(args.channelId);
|
|
49714
49775
|
return jsonResult({
|
|
@@ -49820,15 +49881,26 @@ function registerTools(server, ctx) {
|
|
|
49820
49881
|
});
|
|
49821
49882
|
}));
|
|
49822
49883
|
server.registerTool("delete_notification_setting", {
|
|
49823
|
-
description: "Delete a notification setting by ID. This removes the event-to-channel mapping but does not delete the channels themselves.",
|
|
49884
|
+
description: "Delete a notification setting by ID. This removes the event-to-channel mapping but does not delete the channels themselves. " + "Call first without confirmed=true to preview, then with confirmed=true after user agrees.",
|
|
49824
49885
|
inputSchema: {
|
|
49825
|
-
settingsId: exports_external.string().describe("The notification settings ID to delete")
|
|
49886
|
+
settingsId: exports_external.string().describe("The notification settings ID to delete"),
|
|
49887
|
+
confirmed: exports_external.boolean().optional().describe("Set to true only after the user has explicitly confirmed deletion.")
|
|
49826
49888
|
},
|
|
49827
49889
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true }
|
|
49828
49890
|
}, withErrorHandling("delete_notification_setting", async (args) => {
|
|
49829
|
-
|
|
49830
|
-
|
|
49831
|
-
|
|
49891
|
+
if (!args.confirmed) {
|
|
49892
|
+
const confirmation = await elicit(`Are you sure you want to delete notification setting "${args.settingsId}"?`, { confirm: { type: "boolean", description: "Confirm deletion" } }, ["confirm"]);
|
|
49893
|
+
if (confirmation !== null) {
|
|
49894
|
+
if (!confirmation.confirm) {
|
|
49895
|
+
return jsonResult({ success: false, message: "Deletion cancelled by user." });
|
|
49896
|
+
}
|
|
49897
|
+
} else {
|
|
49898
|
+
return jsonResult({
|
|
49899
|
+
pending: true,
|
|
49900
|
+
settingsId: args.settingsId,
|
|
49901
|
+
message: `⚠️ About to delete notification setting "${args.settingsId}". Ask the user to confirm, then call again with confirmed=true.`
|
|
49902
|
+
});
|
|
49903
|
+
}
|
|
49832
49904
|
}
|
|
49833
49905
|
await ctx.client.notification.settings.deleteSettings(args.settingsId);
|
|
49834
49906
|
return jsonResult({
|
|
@@ -49890,7 +49962,7 @@ function registerTools(server, ctx) {
|
|
|
49890
49962
|
});
|
|
49891
49963
|
}));
|
|
49892
49964
|
}
|
|
49893
|
-
var SchemaFieldShape
|
|
49965
|
+
var SchemaFieldShape;
|
|
49894
49966
|
var init_tools = __esm(() => {
|
|
49895
49967
|
init_zod();
|
|
49896
49968
|
init_dist2();
|
|
@@ -49904,7 +49976,6 @@ var init_tools = __esm(() => {
|
|
|
49904
49976
|
isRequired: exports_external.boolean().optional(),
|
|
49905
49977
|
isUnique: exports_external.boolean().optional()
|
|
49906
49978
|
};
|
|
49907
|
-
REALTIME_INTENT_KEYWORDS = /\b(monitor|track|watch|alert|real[- ]?time|live|continuous|notify)\b/i;
|
|
49908
49979
|
});
|
|
49909
49980
|
|
|
49910
49981
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/middleware/hostHeaderValidation.js
|