@webhooks-cc/mcp 1.22.0 → 1.23.0
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/bin/mcp.js +116 -2
- package/dist/{chunk-VO7HGSRN.mjs → chunk-TMX4P6ZZ.mjs} +115 -1
- package/dist/index.js +116 -2
- package/dist/index.mjs +2 -2
- package/dist/tools.js +115 -1
- package/dist/tools.mjs +1 -1
- package/package.json +2 -2
package/dist/bin/mcp.js
CHANGED
|
@@ -456,7 +456,7 @@ var import_zod3 = require("zod");
|
|
|
456
456
|
var import_sdk2 = require("@webhooks-cc/sdk");
|
|
457
457
|
|
|
458
458
|
// src/version.ts
|
|
459
|
-
var VERSION = true ? "1.
|
|
459
|
+
var VERSION = true ? "1.23.0" : "0.0.0-dev";
|
|
460
460
|
var MCP_USER_AGENT = `webhooks-cc-mcp/${VERSION}`;
|
|
461
461
|
|
|
462
462
|
// src/tools.ts
|
|
@@ -707,6 +707,17 @@ function keyText(key) {
|
|
|
707
707
|
}
|
|
708
708
|
function approvalResultText(result) {
|
|
709
709
|
if (typeof result.key === "string") return keyText(result);
|
|
710
|
+
if (typeof result.spreadsheetId === "string") {
|
|
711
|
+
const tabs = Array.isArray(result.tabs) ? result.tabs.join(", ") : "";
|
|
712
|
+
return `Approved. The chosen spreadsheet is ${String(result.spreadsheetId)} (${String(result.url)}), on connection ${String(result.connectionId)}${tabs ? `; its tabs: ${tabs}` : ""}. Use them in a Sheets destination's config.`;
|
|
713
|
+
}
|
|
714
|
+
if (Array.isArray(result.fields)) {
|
|
715
|
+
return `Approved. AI setup proposed (nothing is saved until you apply it):
|
|
716
|
+
${JSON.stringify(result, null, 2)}`;
|
|
717
|
+
}
|
|
718
|
+
if (typeof result.connectionId === "string") {
|
|
719
|
+
return `Approved. The Google account ${result.email ? `${String(result.email)} ` : ""}is connected as ${result.connectionId}.`;
|
|
720
|
+
}
|
|
710
721
|
if (typeof result.url === "string") {
|
|
711
722
|
return `Approved. The share link is ${result.url} (anyone with it can read the copy until ${String(result.expiresAt)}).`;
|
|
712
723
|
}
|
|
@@ -2319,7 +2330,7 @@ function registerTools(target, client, options = {}) {
|
|
|
2319
2330
|
);
|
|
2320
2331
|
server.tool(
|
|
2321
2332
|
"wait_for_approval",
|
|
2322
|
-
"Wait for the account's owner to answer an approval (from create_api_key, create_share_link, remove_domain or
|
|
2333
|
+
"Wait for the account's owner to answer an approval (from create_api_key, create_share_link, remove_domain, rename_account, connect_google, pick_spreadsheet or ai_setup) and collect what it grants or did, such as the new API key, the share link or AI setup's proposals. If they have not answered yet, call it again.",
|
|
2323
2334
|
{
|
|
2324
2335
|
id: import_zod2.z.string().describe("The approval id"),
|
|
2325
2336
|
timeout: durationOrTimestampSchema.default("45s").describe('How long to wait for the person, for example "45s"')
|
|
@@ -2487,6 +2498,109 @@ function registerTools(target, client, options = {}) {
|
|
|
2487
2498
|
return textContent(approvalAskText(pending));
|
|
2488
2499
|
})
|
|
2489
2500
|
);
|
|
2501
|
+
server.tool(
|
|
2502
|
+
"list_google_connections",
|
|
2503
|
+
"List the Google accounts connected for Google Sheets destinations (id, email, when connected), and whether Google Sheets is set up on this server.",
|
|
2504
|
+
{},
|
|
2505
|
+
withErrorHandling(async () => jsonContent(await client.google.connections()))
|
|
2506
|
+
);
|
|
2507
|
+
server.tool(
|
|
2508
|
+
"connect_google",
|
|
2509
|
+
"Connect a Google account for Google Sheets destinations. The account's owner must approve it: this returns a link and a code to show them, and approving takes them to Google to choose the account. Then call wait_for_approval for the new connection's id.",
|
|
2510
|
+
{},
|
|
2511
|
+
withErrorHandling(async () => textContent(approvalAskText(await client.google.connect())))
|
|
2512
|
+
);
|
|
2513
|
+
server.tool(
|
|
2514
|
+
"pick_spreadsheet",
|
|
2515
|
+
"Have the account's owner choose an existing spreadsheet from Google Drive with a connected account (to add rows to it from a Sheets destination). Returns a link and a code to show them; the page opens Google's picker. Then call wait_for_approval for the spreadsheet's id and tabs. To use a new spreadsheet instead, call create_spreadsheet.",
|
|
2516
|
+
{
|
|
2517
|
+
connectionId: import_zod2.z.string().describe("The Google connection's id, from list_google_connections")
|
|
2518
|
+
},
|
|
2519
|
+
withErrorHandling(
|
|
2520
|
+
async ({ connectionId }) => textContent(approvalAskText(await client.google.pick(connectionId)))
|
|
2521
|
+
)
|
|
2522
|
+
);
|
|
2523
|
+
server.tool(
|
|
2524
|
+
"create_spreadsheet",
|
|
2525
|
+
"Create a new spreadsheet with a header row in a connected Google account, for a Sheets destination. Needs no approval: the app reaches only spreadsheets it created or that were chosen for it.",
|
|
2526
|
+
{
|
|
2527
|
+
connectionId: import_zod2.z.string().describe("The Google connection's id, from list_google_connections"),
|
|
2528
|
+
title: import_zod2.z.string().max(200).optional().describe("The spreadsheet's title"),
|
|
2529
|
+
sheet: import_zod2.z.string().max(100).optional().describe('The tab rows go to (default "Sheet1")'),
|
|
2530
|
+
headers: import_zod2.z.array(import_zod2.z.string().max(200)).max(50).describe("The header row, one per column")
|
|
2531
|
+
},
|
|
2532
|
+
withErrorHandling(
|
|
2533
|
+
async ({ connectionId, title, sheet, headers }) => jsonContent(await client.google.createSpreadsheet({ connectionId, title, sheet, headers }))
|
|
2534
|
+
)
|
|
2535
|
+
);
|
|
2536
|
+
server.tool(
|
|
2537
|
+
"list_sheet_tabs",
|
|
2538
|
+
"List a spreadsheet's tabs (one created by the app or chosen with pick_spreadsheet), to choose the one a Sheets destination writes to.",
|
|
2539
|
+
{
|
|
2540
|
+
connectionId: import_zod2.z.string().describe("The Google connection's id"),
|
|
2541
|
+
spreadsheetId: import_zod2.z.string().describe("The spreadsheet's id")
|
|
2542
|
+
},
|
|
2543
|
+
withErrorHandling(
|
|
2544
|
+
async ({ connectionId, spreadsheetId }) => jsonContent({ tabs: await client.google.tabs(connectionId, spreadsheetId) })
|
|
2545
|
+
)
|
|
2546
|
+
);
|
|
2547
|
+
server.tool(
|
|
2548
|
+
"disconnect_google",
|
|
2549
|
+
"Disconnect a Google account (id from list_google_connections) and revoke its access at Google. Sheets destinations using it fail until another account is chosen.",
|
|
2550
|
+
{
|
|
2551
|
+
connectionId: import_zod2.z.string().describe("The Google connection's id")
|
|
2552
|
+
},
|
|
2553
|
+
withErrorHandling(async ({ connectionId }) => {
|
|
2554
|
+
await client.google.disconnect(connectionId);
|
|
2555
|
+
return textContent(`Disconnected the Google account ${connectionId}.`);
|
|
2556
|
+
})
|
|
2557
|
+
);
|
|
2558
|
+
server.tool(
|
|
2559
|
+
"ai_setup_status",
|
|
2560
|
+
"Whether AI setup is offered for an endpoint, and how many AI assists the plan has left in a rolling 30 days.",
|
|
2561
|
+
{
|
|
2562
|
+
slug: import_zod2.z.string().describe("The endpoint's slug")
|
|
2563
|
+
},
|
|
2564
|
+
withErrorHandling(async ({ slug }) => jsonContent(await client.ai.status(slug)))
|
|
2565
|
+
);
|
|
2566
|
+
server.tool(
|
|
2567
|
+
"ai_setup",
|
|
2568
|
+
"Have AI propose email fields (or a layout, or a repaired field) from 1 to 5 of an endpoint's captured emails. It sends those emails (subject, sender, recipients, text, headers; never attachments) to Anthropic's model, so the account's owner must approve it: this returns a link and a code to show them, and the page lists the emails. Then call wait_for_approval for the proposals, each with the value it found in every email. Nothing is saved: apply the fields with update_endpoint. Uses one AI assist.",
|
|
2569
|
+
{
|
|
2570
|
+
slug: import_zod2.z.string().describe("The endpoint's slug"),
|
|
2571
|
+
requestIds: import_zod2.z.array(import_zod2.z.string()).min(1).max(5).describe("1 to 5 of the endpoint's email request ids, from list_emails"),
|
|
2572
|
+
ask: import_zod2.z.union([
|
|
2573
|
+
import_zod2.z.object({
|
|
2574
|
+
kind: import_zod2.z.literal("field"),
|
|
2575
|
+
name: import_zod2.z.string().describe("The field's name: letters, digits and _"),
|
|
2576
|
+
description: import_zod2.z.string().describe('What the field is, such as "the order number"')
|
|
2577
|
+
}),
|
|
2578
|
+
import_zod2.z.object({
|
|
2579
|
+
kind: import_zod2.z.literal("layout"),
|
|
2580
|
+
description: import_zod2.z.string().optional().describe("What these emails are")
|
|
2581
|
+
}),
|
|
2582
|
+
import_zod2.z.object({
|
|
2583
|
+
kind: import_zod2.z.literal("repair"),
|
|
2584
|
+
field: import_zod2.z.object({
|
|
2585
|
+
name: import_zod2.z.string(),
|
|
2586
|
+
from: import_zod2.z.string(),
|
|
2587
|
+
header: import_zod2.z.string().optional(),
|
|
2588
|
+
pattern: import_zod2.z.string()
|
|
2589
|
+
}).describe("The field to repair, as the endpoint has it")
|
|
2590
|
+
})
|
|
2591
|
+
]).describe("What to propose")
|
|
2592
|
+
},
|
|
2593
|
+
withErrorHandling(
|
|
2594
|
+
async ({ slug, requestIds, ask }) => textContent(
|
|
2595
|
+
approvalAskText(
|
|
2596
|
+
await client.ai.setup(slug, {
|
|
2597
|
+
requestIds,
|
|
2598
|
+
ask
|
|
2599
|
+
})
|
|
2600
|
+
)
|
|
2601
|
+
)
|
|
2602
|
+
)
|
|
2603
|
+
);
|
|
2490
2604
|
server.tool(
|
|
2491
2605
|
"stop_share",
|
|
2492
2606
|
"Stop a public preview or live tunnel by its id (from list_shares). The CLI running it is told why and exits.",
|
|
@@ -487,6 +487,17 @@ function keyText(key) {
|
|
|
487
487
|
}
|
|
488
488
|
function approvalResultText(result) {
|
|
489
489
|
if (typeof result.key === "string") return keyText(result);
|
|
490
|
+
if (typeof result.spreadsheetId === "string") {
|
|
491
|
+
const tabs = Array.isArray(result.tabs) ? result.tabs.join(", ") : "";
|
|
492
|
+
return `Approved. The chosen spreadsheet is ${String(result.spreadsheetId)} (${String(result.url)}), on connection ${String(result.connectionId)}${tabs ? `; its tabs: ${tabs}` : ""}. Use them in a Sheets destination's config.`;
|
|
493
|
+
}
|
|
494
|
+
if (Array.isArray(result.fields)) {
|
|
495
|
+
return `Approved. AI setup proposed (nothing is saved until you apply it):
|
|
496
|
+
${JSON.stringify(result, null, 2)}`;
|
|
497
|
+
}
|
|
498
|
+
if (typeof result.connectionId === "string") {
|
|
499
|
+
return `Approved. The Google account ${result.email ? `${String(result.email)} ` : ""}is connected as ${result.connectionId}.`;
|
|
500
|
+
}
|
|
490
501
|
if (typeof result.url === "string") {
|
|
491
502
|
return `Approved. The share link is ${result.url} (anyone with it can read the copy until ${String(result.expiresAt)}).`;
|
|
492
503
|
}
|
|
@@ -2099,7 +2110,7 @@ function registerTools(target, client, options = {}) {
|
|
|
2099
2110
|
);
|
|
2100
2111
|
server.tool(
|
|
2101
2112
|
"wait_for_approval",
|
|
2102
|
-
"Wait for the account's owner to answer an approval (from create_api_key, create_share_link, remove_domain or
|
|
2113
|
+
"Wait for the account's owner to answer an approval (from create_api_key, create_share_link, remove_domain, rename_account, connect_google, pick_spreadsheet or ai_setup) and collect what it grants or did, such as the new API key, the share link or AI setup's proposals. If they have not answered yet, call it again.",
|
|
2103
2114
|
{
|
|
2104
2115
|
id: z.string().describe("The approval id"),
|
|
2105
2116
|
timeout: durationOrTimestampSchema.default("45s").describe('How long to wait for the person, for example "45s"')
|
|
@@ -2267,6 +2278,109 @@ function registerTools(target, client, options = {}) {
|
|
|
2267
2278
|
return textContent(approvalAskText(pending));
|
|
2268
2279
|
})
|
|
2269
2280
|
);
|
|
2281
|
+
server.tool(
|
|
2282
|
+
"list_google_connections",
|
|
2283
|
+
"List the Google accounts connected for Google Sheets destinations (id, email, when connected), and whether Google Sheets is set up on this server.",
|
|
2284
|
+
{},
|
|
2285
|
+
withErrorHandling(async () => jsonContent(await client.google.connections()))
|
|
2286
|
+
);
|
|
2287
|
+
server.tool(
|
|
2288
|
+
"connect_google",
|
|
2289
|
+
"Connect a Google account for Google Sheets destinations. The account's owner must approve it: this returns a link and a code to show them, and approving takes them to Google to choose the account. Then call wait_for_approval for the new connection's id.",
|
|
2290
|
+
{},
|
|
2291
|
+
withErrorHandling(async () => textContent(approvalAskText(await client.google.connect())))
|
|
2292
|
+
);
|
|
2293
|
+
server.tool(
|
|
2294
|
+
"pick_spreadsheet",
|
|
2295
|
+
"Have the account's owner choose an existing spreadsheet from Google Drive with a connected account (to add rows to it from a Sheets destination). Returns a link and a code to show them; the page opens Google's picker. Then call wait_for_approval for the spreadsheet's id and tabs. To use a new spreadsheet instead, call create_spreadsheet.",
|
|
2296
|
+
{
|
|
2297
|
+
connectionId: z.string().describe("The Google connection's id, from list_google_connections")
|
|
2298
|
+
},
|
|
2299
|
+
withErrorHandling(
|
|
2300
|
+
async ({ connectionId }) => textContent(approvalAskText(await client.google.pick(connectionId)))
|
|
2301
|
+
)
|
|
2302
|
+
);
|
|
2303
|
+
server.tool(
|
|
2304
|
+
"create_spreadsheet",
|
|
2305
|
+
"Create a new spreadsheet with a header row in a connected Google account, for a Sheets destination. Needs no approval: the app reaches only spreadsheets it created or that were chosen for it.",
|
|
2306
|
+
{
|
|
2307
|
+
connectionId: z.string().describe("The Google connection's id, from list_google_connections"),
|
|
2308
|
+
title: z.string().max(200).optional().describe("The spreadsheet's title"),
|
|
2309
|
+
sheet: z.string().max(100).optional().describe('The tab rows go to (default "Sheet1")'),
|
|
2310
|
+
headers: z.array(z.string().max(200)).max(50).describe("The header row, one per column")
|
|
2311
|
+
},
|
|
2312
|
+
withErrorHandling(
|
|
2313
|
+
async ({ connectionId, title, sheet, headers }) => jsonContent(await client.google.createSpreadsheet({ connectionId, title, sheet, headers }))
|
|
2314
|
+
)
|
|
2315
|
+
);
|
|
2316
|
+
server.tool(
|
|
2317
|
+
"list_sheet_tabs",
|
|
2318
|
+
"List a spreadsheet's tabs (one created by the app or chosen with pick_spreadsheet), to choose the one a Sheets destination writes to.",
|
|
2319
|
+
{
|
|
2320
|
+
connectionId: z.string().describe("The Google connection's id"),
|
|
2321
|
+
spreadsheetId: z.string().describe("The spreadsheet's id")
|
|
2322
|
+
},
|
|
2323
|
+
withErrorHandling(
|
|
2324
|
+
async ({ connectionId, spreadsheetId }) => jsonContent({ tabs: await client.google.tabs(connectionId, spreadsheetId) })
|
|
2325
|
+
)
|
|
2326
|
+
);
|
|
2327
|
+
server.tool(
|
|
2328
|
+
"disconnect_google",
|
|
2329
|
+
"Disconnect a Google account (id from list_google_connections) and revoke its access at Google. Sheets destinations using it fail until another account is chosen.",
|
|
2330
|
+
{
|
|
2331
|
+
connectionId: z.string().describe("The Google connection's id")
|
|
2332
|
+
},
|
|
2333
|
+
withErrorHandling(async ({ connectionId }) => {
|
|
2334
|
+
await client.google.disconnect(connectionId);
|
|
2335
|
+
return textContent(`Disconnected the Google account ${connectionId}.`);
|
|
2336
|
+
})
|
|
2337
|
+
);
|
|
2338
|
+
server.tool(
|
|
2339
|
+
"ai_setup_status",
|
|
2340
|
+
"Whether AI setup is offered for an endpoint, and how many AI assists the plan has left in a rolling 30 days.",
|
|
2341
|
+
{
|
|
2342
|
+
slug: z.string().describe("The endpoint's slug")
|
|
2343
|
+
},
|
|
2344
|
+
withErrorHandling(async ({ slug }) => jsonContent(await client.ai.status(slug)))
|
|
2345
|
+
);
|
|
2346
|
+
server.tool(
|
|
2347
|
+
"ai_setup",
|
|
2348
|
+
"Have AI propose email fields (or a layout, or a repaired field) from 1 to 5 of an endpoint's captured emails. It sends those emails (subject, sender, recipients, text, headers; never attachments) to Anthropic's model, so the account's owner must approve it: this returns a link and a code to show them, and the page lists the emails. Then call wait_for_approval for the proposals, each with the value it found in every email. Nothing is saved: apply the fields with update_endpoint. Uses one AI assist.",
|
|
2349
|
+
{
|
|
2350
|
+
slug: z.string().describe("The endpoint's slug"),
|
|
2351
|
+
requestIds: z.array(z.string()).min(1).max(5).describe("1 to 5 of the endpoint's email request ids, from list_emails"),
|
|
2352
|
+
ask: z.union([
|
|
2353
|
+
z.object({
|
|
2354
|
+
kind: z.literal("field"),
|
|
2355
|
+
name: z.string().describe("The field's name: letters, digits and _"),
|
|
2356
|
+
description: z.string().describe('What the field is, such as "the order number"')
|
|
2357
|
+
}),
|
|
2358
|
+
z.object({
|
|
2359
|
+
kind: z.literal("layout"),
|
|
2360
|
+
description: z.string().optional().describe("What these emails are")
|
|
2361
|
+
}),
|
|
2362
|
+
z.object({
|
|
2363
|
+
kind: z.literal("repair"),
|
|
2364
|
+
field: z.object({
|
|
2365
|
+
name: z.string(),
|
|
2366
|
+
from: z.string(),
|
|
2367
|
+
header: z.string().optional(),
|
|
2368
|
+
pattern: z.string()
|
|
2369
|
+
}).describe("The field to repair, as the endpoint has it")
|
|
2370
|
+
})
|
|
2371
|
+
]).describe("What to propose")
|
|
2372
|
+
},
|
|
2373
|
+
withErrorHandling(
|
|
2374
|
+
async ({ slug, requestIds, ask }) => textContent(
|
|
2375
|
+
approvalAskText(
|
|
2376
|
+
await client.ai.setup(slug, {
|
|
2377
|
+
requestIds,
|
|
2378
|
+
ask
|
|
2379
|
+
})
|
|
2380
|
+
)
|
|
2381
|
+
)
|
|
2382
|
+
)
|
|
2383
|
+
);
|
|
2270
2384
|
server.tool(
|
|
2271
2385
|
"stop_share",
|
|
2272
2386
|
"Stop a public preview or live tunnel by its id (from list_shares). The CLI running it is told why and exits.",
|
package/dist/index.js
CHANGED
|
@@ -480,7 +480,7 @@ var import_zod3 = require("zod");
|
|
|
480
480
|
var import_sdk2 = require("@webhooks-cc/sdk");
|
|
481
481
|
|
|
482
482
|
// src/version.ts
|
|
483
|
-
var VERSION = true ? "1.
|
|
483
|
+
var VERSION = true ? "1.23.0" : "0.0.0-dev";
|
|
484
484
|
var MCP_USER_AGENT = `webhooks-cc-mcp/${VERSION}`;
|
|
485
485
|
|
|
486
486
|
// src/tools.ts
|
|
@@ -731,6 +731,17 @@ function keyText(key) {
|
|
|
731
731
|
}
|
|
732
732
|
function approvalResultText(result) {
|
|
733
733
|
if (typeof result.key === "string") return keyText(result);
|
|
734
|
+
if (typeof result.spreadsheetId === "string") {
|
|
735
|
+
const tabs = Array.isArray(result.tabs) ? result.tabs.join(", ") : "";
|
|
736
|
+
return `Approved. The chosen spreadsheet is ${String(result.spreadsheetId)} (${String(result.url)}), on connection ${String(result.connectionId)}${tabs ? `; its tabs: ${tabs}` : ""}. Use them in a Sheets destination's config.`;
|
|
737
|
+
}
|
|
738
|
+
if (Array.isArray(result.fields)) {
|
|
739
|
+
return `Approved. AI setup proposed (nothing is saved until you apply it):
|
|
740
|
+
${JSON.stringify(result, null, 2)}`;
|
|
741
|
+
}
|
|
742
|
+
if (typeof result.connectionId === "string") {
|
|
743
|
+
return `Approved. The Google account ${result.email ? `${String(result.email)} ` : ""}is connected as ${result.connectionId}.`;
|
|
744
|
+
}
|
|
734
745
|
if (typeof result.url === "string") {
|
|
735
746
|
return `Approved. The share link is ${result.url} (anyone with it can read the copy until ${String(result.expiresAt)}).`;
|
|
736
747
|
}
|
|
@@ -2343,7 +2354,7 @@ function registerTools(target, client, options = {}) {
|
|
|
2343
2354
|
);
|
|
2344
2355
|
server.tool(
|
|
2345
2356
|
"wait_for_approval",
|
|
2346
|
-
"Wait for the account's owner to answer an approval (from create_api_key, create_share_link, remove_domain or
|
|
2357
|
+
"Wait for the account's owner to answer an approval (from create_api_key, create_share_link, remove_domain, rename_account, connect_google, pick_spreadsheet or ai_setup) and collect what it grants or did, such as the new API key, the share link or AI setup's proposals. If they have not answered yet, call it again.",
|
|
2347
2358
|
{
|
|
2348
2359
|
id: import_zod2.z.string().describe("The approval id"),
|
|
2349
2360
|
timeout: durationOrTimestampSchema.default("45s").describe('How long to wait for the person, for example "45s"')
|
|
@@ -2511,6 +2522,109 @@ function registerTools(target, client, options = {}) {
|
|
|
2511
2522
|
return textContent(approvalAskText(pending));
|
|
2512
2523
|
})
|
|
2513
2524
|
);
|
|
2525
|
+
server.tool(
|
|
2526
|
+
"list_google_connections",
|
|
2527
|
+
"List the Google accounts connected for Google Sheets destinations (id, email, when connected), and whether Google Sheets is set up on this server.",
|
|
2528
|
+
{},
|
|
2529
|
+
withErrorHandling(async () => jsonContent(await client.google.connections()))
|
|
2530
|
+
);
|
|
2531
|
+
server.tool(
|
|
2532
|
+
"connect_google",
|
|
2533
|
+
"Connect a Google account for Google Sheets destinations. The account's owner must approve it: this returns a link and a code to show them, and approving takes them to Google to choose the account. Then call wait_for_approval for the new connection's id.",
|
|
2534
|
+
{},
|
|
2535
|
+
withErrorHandling(async () => textContent(approvalAskText(await client.google.connect())))
|
|
2536
|
+
);
|
|
2537
|
+
server.tool(
|
|
2538
|
+
"pick_spreadsheet",
|
|
2539
|
+
"Have the account's owner choose an existing spreadsheet from Google Drive with a connected account (to add rows to it from a Sheets destination). Returns a link and a code to show them; the page opens Google's picker. Then call wait_for_approval for the spreadsheet's id and tabs. To use a new spreadsheet instead, call create_spreadsheet.",
|
|
2540
|
+
{
|
|
2541
|
+
connectionId: import_zod2.z.string().describe("The Google connection's id, from list_google_connections")
|
|
2542
|
+
},
|
|
2543
|
+
withErrorHandling(
|
|
2544
|
+
async ({ connectionId }) => textContent(approvalAskText(await client.google.pick(connectionId)))
|
|
2545
|
+
)
|
|
2546
|
+
);
|
|
2547
|
+
server.tool(
|
|
2548
|
+
"create_spreadsheet",
|
|
2549
|
+
"Create a new spreadsheet with a header row in a connected Google account, for a Sheets destination. Needs no approval: the app reaches only spreadsheets it created or that were chosen for it.",
|
|
2550
|
+
{
|
|
2551
|
+
connectionId: import_zod2.z.string().describe("The Google connection's id, from list_google_connections"),
|
|
2552
|
+
title: import_zod2.z.string().max(200).optional().describe("The spreadsheet's title"),
|
|
2553
|
+
sheet: import_zod2.z.string().max(100).optional().describe('The tab rows go to (default "Sheet1")'),
|
|
2554
|
+
headers: import_zod2.z.array(import_zod2.z.string().max(200)).max(50).describe("The header row, one per column")
|
|
2555
|
+
},
|
|
2556
|
+
withErrorHandling(
|
|
2557
|
+
async ({ connectionId, title, sheet, headers }) => jsonContent(await client.google.createSpreadsheet({ connectionId, title, sheet, headers }))
|
|
2558
|
+
)
|
|
2559
|
+
);
|
|
2560
|
+
server.tool(
|
|
2561
|
+
"list_sheet_tabs",
|
|
2562
|
+
"List a spreadsheet's tabs (one created by the app or chosen with pick_spreadsheet), to choose the one a Sheets destination writes to.",
|
|
2563
|
+
{
|
|
2564
|
+
connectionId: import_zod2.z.string().describe("The Google connection's id"),
|
|
2565
|
+
spreadsheetId: import_zod2.z.string().describe("The spreadsheet's id")
|
|
2566
|
+
},
|
|
2567
|
+
withErrorHandling(
|
|
2568
|
+
async ({ connectionId, spreadsheetId }) => jsonContent({ tabs: await client.google.tabs(connectionId, spreadsheetId) })
|
|
2569
|
+
)
|
|
2570
|
+
);
|
|
2571
|
+
server.tool(
|
|
2572
|
+
"disconnect_google",
|
|
2573
|
+
"Disconnect a Google account (id from list_google_connections) and revoke its access at Google. Sheets destinations using it fail until another account is chosen.",
|
|
2574
|
+
{
|
|
2575
|
+
connectionId: import_zod2.z.string().describe("The Google connection's id")
|
|
2576
|
+
},
|
|
2577
|
+
withErrorHandling(async ({ connectionId }) => {
|
|
2578
|
+
await client.google.disconnect(connectionId);
|
|
2579
|
+
return textContent(`Disconnected the Google account ${connectionId}.`);
|
|
2580
|
+
})
|
|
2581
|
+
);
|
|
2582
|
+
server.tool(
|
|
2583
|
+
"ai_setup_status",
|
|
2584
|
+
"Whether AI setup is offered for an endpoint, and how many AI assists the plan has left in a rolling 30 days.",
|
|
2585
|
+
{
|
|
2586
|
+
slug: import_zod2.z.string().describe("The endpoint's slug")
|
|
2587
|
+
},
|
|
2588
|
+
withErrorHandling(async ({ slug }) => jsonContent(await client.ai.status(slug)))
|
|
2589
|
+
);
|
|
2590
|
+
server.tool(
|
|
2591
|
+
"ai_setup",
|
|
2592
|
+
"Have AI propose email fields (or a layout, or a repaired field) from 1 to 5 of an endpoint's captured emails. It sends those emails (subject, sender, recipients, text, headers; never attachments) to Anthropic's model, so the account's owner must approve it: this returns a link and a code to show them, and the page lists the emails. Then call wait_for_approval for the proposals, each with the value it found in every email. Nothing is saved: apply the fields with update_endpoint. Uses one AI assist.",
|
|
2593
|
+
{
|
|
2594
|
+
slug: import_zod2.z.string().describe("The endpoint's slug"),
|
|
2595
|
+
requestIds: import_zod2.z.array(import_zod2.z.string()).min(1).max(5).describe("1 to 5 of the endpoint's email request ids, from list_emails"),
|
|
2596
|
+
ask: import_zod2.z.union([
|
|
2597
|
+
import_zod2.z.object({
|
|
2598
|
+
kind: import_zod2.z.literal("field"),
|
|
2599
|
+
name: import_zod2.z.string().describe("The field's name: letters, digits and _"),
|
|
2600
|
+
description: import_zod2.z.string().describe('What the field is, such as "the order number"')
|
|
2601
|
+
}),
|
|
2602
|
+
import_zod2.z.object({
|
|
2603
|
+
kind: import_zod2.z.literal("layout"),
|
|
2604
|
+
description: import_zod2.z.string().optional().describe("What these emails are")
|
|
2605
|
+
}),
|
|
2606
|
+
import_zod2.z.object({
|
|
2607
|
+
kind: import_zod2.z.literal("repair"),
|
|
2608
|
+
field: import_zod2.z.object({
|
|
2609
|
+
name: import_zod2.z.string(),
|
|
2610
|
+
from: import_zod2.z.string(),
|
|
2611
|
+
header: import_zod2.z.string().optional(),
|
|
2612
|
+
pattern: import_zod2.z.string()
|
|
2613
|
+
}).describe("The field to repair, as the endpoint has it")
|
|
2614
|
+
})
|
|
2615
|
+
]).describe("What to propose")
|
|
2616
|
+
},
|
|
2617
|
+
withErrorHandling(
|
|
2618
|
+
async ({ slug, requestIds, ask }) => textContent(
|
|
2619
|
+
approvalAskText(
|
|
2620
|
+
await client.ai.setup(slug, {
|
|
2621
|
+
requestIds,
|
|
2622
|
+
ask
|
|
2623
|
+
})
|
|
2624
|
+
)
|
|
2625
|
+
)
|
|
2626
|
+
)
|
|
2627
|
+
);
|
|
2514
2628
|
server.tool(
|
|
2515
2629
|
"stop_share",
|
|
2516
2630
|
"Stop a public preview or live tunnel by its id (from list_shares). The CLI running it is told why and exits.",
|
package/dist/index.mjs
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
registerTools,
|
|
14
14
|
waitForRequestShape,
|
|
15
15
|
withErrorHandling
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-TMX4P6ZZ.mjs";
|
|
17
17
|
|
|
18
18
|
// src/index.ts
|
|
19
19
|
import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -262,7 +262,7 @@ import {
|
|
|
262
262
|
} from "@webhooks-cc/sdk";
|
|
263
263
|
|
|
264
264
|
// src/version.ts
|
|
265
|
-
var VERSION = true ? "1.
|
|
265
|
+
var VERSION = true ? "1.23.0" : "0.0.0-dev";
|
|
266
266
|
var MCP_USER_AGENT = `webhooks-cc-mcp/${VERSION}`;
|
|
267
267
|
|
|
268
268
|
// src/sandbox-tools.ts
|
package/dist/tools.js
CHANGED
|
@@ -498,6 +498,17 @@ function keyText(key) {
|
|
|
498
498
|
}
|
|
499
499
|
function approvalResultText(result) {
|
|
500
500
|
if (typeof result.key === "string") return keyText(result);
|
|
501
|
+
if (typeof result.spreadsheetId === "string") {
|
|
502
|
+
const tabs = Array.isArray(result.tabs) ? result.tabs.join(", ") : "";
|
|
503
|
+
return `Approved. The chosen spreadsheet is ${String(result.spreadsheetId)} (${String(result.url)}), on connection ${String(result.connectionId)}${tabs ? `; its tabs: ${tabs}` : ""}. Use them in a Sheets destination's config.`;
|
|
504
|
+
}
|
|
505
|
+
if (Array.isArray(result.fields)) {
|
|
506
|
+
return `Approved. AI setup proposed (nothing is saved until you apply it):
|
|
507
|
+
${JSON.stringify(result, null, 2)}`;
|
|
508
|
+
}
|
|
509
|
+
if (typeof result.connectionId === "string") {
|
|
510
|
+
return `Approved. The Google account ${result.email ? `${String(result.email)} ` : ""}is connected as ${result.connectionId}.`;
|
|
511
|
+
}
|
|
501
512
|
if (typeof result.url === "string") {
|
|
502
513
|
return `Approved. The share link is ${result.url} (anyone with it can read the copy until ${String(result.expiresAt)}).`;
|
|
503
514
|
}
|
|
@@ -2110,7 +2121,7 @@ function registerTools(target, client, options = {}) {
|
|
|
2110
2121
|
);
|
|
2111
2122
|
server.tool(
|
|
2112
2123
|
"wait_for_approval",
|
|
2113
|
-
"Wait for the account's owner to answer an approval (from create_api_key, create_share_link, remove_domain or
|
|
2124
|
+
"Wait for the account's owner to answer an approval (from create_api_key, create_share_link, remove_domain, rename_account, connect_google, pick_spreadsheet or ai_setup) and collect what it grants or did, such as the new API key, the share link or AI setup's proposals. If they have not answered yet, call it again.",
|
|
2114
2125
|
{
|
|
2115
2126
|
id: import_zod.z.string().describe("The approval id"),
|
|
2116
2127
|
timeout: durationOrTimestampSchema.default("45s").describe('How long to wait for the person, for example "45s"')
|
|
@@ -2278,6 +2289,109 @@ function registerTools(target, client, options = {}) {
|
|
|
2278
2289
|
return textContent(approvalAskText(pending));
|
|
2279
2290
|
})
|
|
2280
2291
|
);
|
|
2292
|
+
server.tool(
|
|
2293
|
+
"list_google_connections",
|
|
2294
|
+
"List the Google accounts connected for Google Sheets destinations (id, email, when connected), and whether Google Sheets is set up on this server.",
|
|
2295
|
+
{},
|
|
2296
|
+
withErrorHandling(async () => jsonContent(await client.google.connections()))
|
|
2297
|
+
);
|
|
2298
|
+
server.tool(
|
|
2299
|
+
"connect_google",
|
|
2300
|
+
"Connect a Google account for Google Sheets destinations. The account's owner must approve it: this returns a link and a code to show them, and approving takes them to Google to choose the account. Then call wait_for_approval for the new connection's id.",
|
|
2301
|
+
{},
|
|
2302
|
+
withErrorHandling(async () => textContent(approvalAskText(await client.google.connect())))
|
|
2303
|
+
);
|
|
2304
|
+
server.tool(
|
|
2305
|
+
"pick_spreadsheet",
|
|
2306
|
+
"Have the account's owner choose an existing spreadsheet from Google Drive with a connected account (to add rows to it from a Sheets destination). Returns a link and a code to show them; the page opens Google's picker. Then call wait_for_approval for the spreadsheet's id and tabs. To use a new spreadsheet instead, call create_spreadsheet.",
|
|
2307
|
+
{
|
|
2308
|
+
connectionId: import_zod.z.string().describe("The Google connection's id, from list_google_connections")
|
|
2309
|
+
},
|
|
2310
|
+
withErrorHandling(
|
|
2311
|
+
async ({ connectionId }) => textContent(approvalAskText(await client.google.pick(connectionId)))
|
|
2312
|
+
)
|
|
2313
|
+
);
|
|
2314
|
+
server.tool(
|
|
2315
|
+
"create_spreadsheet",
|
|
2316
|
+
"Create a new spreadsheet with a header row in a connected Google account, for a Sheets destination. Needs no approval: the app reaches only spreadsheets it created or that were chosen for it.",
|
|
2317
|
+
{
|
|
2318
|
+
connectionId: import_zod.z.string().describe("The Google connection's id, from list_google_connections"),
|
|
2319
|
+
title: import_zod.z.string().max(200).optional().describe("The spreadsheet's title"),
|
|
2320
|
+
sheet: import_zod.z.string().max(100).optional().describe('The tab rows go to (default "Sheet1")'),
|
|
2321
|
+
headers: import_zod.z.array(import_zod.z.string().max(200)).max(50).describe("The header row, one per column")
|
|
2322
|
+
},
|
|
2323
|
+
withErrorHandling(
|
|
2324
|
+
async ({ connectionId, title, sheet, headers }) => jsonContent(await client.google.createSpreadsheet({ connectionId, title, sheet, headers }))
|
|
2325
|
+
)
|
|
2326
|
+
);
|
|
2327
|
+
server.tool(
|
|
2328
|
+
"list_sheet_tabs",
|
|
2329
|
+
"List a spreadsheet's tabs (one created by the app or chosen with pick_spreadsheet), to choose the one a Sheets destination writes to.",
|
|
2330
|
+
{
|
|
2331
|
+
connectionId: import_zod.z.string().describe("The Google connection's id"),
|
|
2332
|
+
spreadsheetId: import_zod.z.string().describe("The spreadsheet's id")
|
|
2333
|
+
},
|
|
2334
|
+
withErrorHandling(
|
|
2335
|
+
async ({ connectionId, spreadsheetId }) => jsonContent({ tabs: await client.google.tabs(connectionId, spreadsheetId) })
|
|
2336
|
+
)
|
|
2337
|
+
);
|
|
2338
|
+
server.tool(
|
|
2339
|
+
"disconnect_google",
|
|
2340
|
+
"Disconnect a Google account (id from list_google_connections) and revoke its access at Google. Sheets destinations using it fail until another account is chosen.",
|
|
2341
|
+
{
|
|
2342
|
+
connectionId: import_zod.z.string().describe("The Google connection's id")
|
|
2343
|
+
},
|
|
2344
|
+
withErrorHandling(async ({ connectionId }) => {
|
|
2345
|
+
await client.google.disconnect(connectionId);
|
|
2346
|
+
return textContent(`Disconnected the Google account ${connectionId}.`);
|
|
2347
|
+
})
|
|
2348
|
+
);
|
|
2349
|
+
server.tool(
|
|
2350
|
+
"ai_setup_status",
|
|
2351
|
+
"Whether AI setup is offered for an endpoint, and how many AI assists the plan has left in a rolling 30 days.",
|
|
2352
|
+
{
|
|
2353
|
+
slug: import_zod.z.string().describe("The endpoint's slug")
|
|
2354
|
+
},
|
|
2355
|
+
withErrorHandling(async ({ slug }) => jsonContent(await client.ai.status(slug)))
|
|
2356
|
+
);
|
|
2357
|
+
server.tool(
|
|
2358
|
+
"ai_setup",
|
|
2359
|
+
"Have AI propose email fields (or a layout, or a repaired field) from 1 to 5 of an endpoint's captured emails. It sends those emails (subject, sender, recipients, text, headers; never attachments) to Anthropic's model, so the account's owner must approve it: this returns a link and a code to show them, and the page lists the emails. Then call wait_for_approval for the proposals, each with the value it found in every email. Nothing is saved: apply the fields with update_endpoint. Uses one AI assist.",
|
|
2360
|
+
{
|
|
2361
|
+
slug: import_zod.z.string().describe("The endpoint's slug"),
|
|
2362
|
+
requestIds: import_zod.z.array(import_zod.z.string()).min(1).max(5).describe("1 to 5 of the endpoint's email request ids, from list_emails"),
|
|
2363
|
+
ask: import_zod.z.union([
|
|
2364
|
+
import_zod.z.object({
|
|
2365
|
+
kind: import_zod.z.literal("field"),
|
|
2366
|
+
name: import_zod.z.string().describe("The field's name: letters, digits and _"),
|
|
2367
|
+
description: import_zod.z.string().describe('What the field is, such as "the order number"')
|
|
2368
|
+
}),
|
|
2369
|
+
import_zod.z.object({
|
|
2370
|
+
kind: import_zod.z.literal("layout"),
|
|
2371
|
+
description: import_zod.z.string().optional().describe("What these emails are")
|
|
2372
|
+
}),
|
|
2373
|
+
import_zod.z.object({
|
|
2374
|
+
kind: import_zod.z.literal("repair"),
|
|
2375
|
+
field: import_zod.z.object({
|
|
2376
|
+
name: import_zod.z.string(),
|
|
2377
|
+
from: import_zod.z.string(),
|
|
2378
|
+
header: import_zod.z.string().optional(),
|
|
2379
|
+
pattern: import_zod.z.string()
|
|
2380
|
+
}).describe("The field to repair, as the endpoint has it")
|
|
2381
|
+
})
|
|
2382
|
+
]).describe("What to propose")
|
|
2383
|
+
},
|
|
2384
|
+
withErrorHandling(
|
|
2385
|
+
async ({ slug, requestIds, ask }) => textContent(
|
|
2386
|
+
approvalAskText(
|
|
2387
|
+
await client.ai.setup(slug, {
|
|
2388
|
+
requestIds,
|
|
2389
|
+
ask
|
|
2390
|
+
})
|
|
2391
|
+
)
|
|
2392
|
+
)
|
|
2393
|
+
)
|
|
2394
|
+
);
|
|
2281
2395
|
server.tool(
|
|
2282
2396
|
"stop_share",
|
|
2283
2397
|
"Stop a public preview or live tunnel by its id (from list_shares). The CLI running it is told why and exits.",
|
package/dist/tools.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webhooks-cc/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.23.0",
|
|
4
4
|
"mcpName": "io.github.kroqdotdev/webhooks-cc",
|
|
5
5
|
"description": "MCP server for webhooks.cc — AI agent integration for webhook testing",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"dependencies": {
|
|
45
45
|
"@modelcontextprotocol/sdk": "^1.32.2",
|
|
46
46
|
"zod": "^4.6.7",
|
|
47
|
-
"@webhooks-cc/sdk": "1.
|
|
47
|
+
"@webhooks-cc/sdk": "1.27.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^26.6.6",
|