@webhooks-cc/mcp 1.19.0 → 1.21.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 +87 -1
- package/dist/{chunk-GREHE3PB.mjs → chunk-BAGCOSXG.mjs} +89 -0
- package/dist/index.js +87 -1
- package/dist/index.mjs +2 -2
- package/dist/tools.d.mts +6 -2
- package/dist/tools.d.ts +6 -2
- package/dist/tools.js +88 -0
- package/dist/tools.mjs +3 -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.21.0" : "0.0.0-dev";
|
|
460
460
|
var MCP_USER_AGENT = `webhooks-cc-mcp/${VERSION}`;
|
|
461
461
|
|
|
462
462
|
// src/tools.ts
|
|
@@ -698,6 +698,13 @@ function payloadSchemaResult(requests, args2) {
|
|
|
698
698
|
}
|
|
699
699
|
return jsonContent(output);
|
|
700
700
|
}
|
|
701
|
+
function keyText(key) {
|
|
702
|
+
return [
|
|
703
|
+
`Approved. The API key ${key.name ? `"${key.name}" ` : ""}is: ${key.key ?? "(not returned)"}`,
|
|
704
|
+
`It is shown only this once: store it now (for example as a CI secret), never in code.`,
|
|
705
|
+
key.expiresAt ? `It works until ${key.expiresAt}.` : ""
|
|
706
|
+
].filter(Boolean).join("\n");
|
|
707
|
+
}
|
|
701
708
|
function textContent(text) {
|
|
702
709
|
return { content: [{ type: "text", text }] };
|
|
703
710
|
}
|
|
@@ -1797,6 +1804,15 @@ function registerTools(target, client, options = {}) {
|
|
|
1797
1804
|
);
|
|
1798
1805
|
})
|
|
1799
1806
|
);
|
|
1807
|
+
server.tool(
|
|
1808
|
+
"get_billing",
|
|
1809
|
+
"What the account pays for: the plan and its subscription (status, monthly or annual, when it renews, a pending change, whether it cancels at the period's end), the add-ons (extra requests, parsed pages, domains), and every team's subscription and add-ons. Read only: changing a plan, seats or add-ons takes the person in a browser.",
|
|
1810
|
+
{},
|
|
1811
|
+
withErrorHandling(async () => {
|
|
1812
|
+
const billing = await client.billing.get();
|
|
1813
|
+
return jsonContent(fitArrayField(billing, "teams"));
|
|
1814
|
+
})
|
|
1815
|
+
);
|
|
1800
1816
|
server.tool(
|
|
1801
1817
|
"get_usage",
|
|
1802
1818
|
"Check current request usage, remaining quota, plan, and period end; parsed pages, preview data (whk share) and AI assists, each with when it resets; and the pooled quota of every subscribed team you belong to.",
|
|
@@ -2258,6 +2274,76 @@ function registerTools(target, client, options = {}) {
|
|
|
2258
2274
|
return jsonContent(withShareHints(await client.shares.list(state ? { state } : {}), remote));
|
|
2259
2275
|
})
|
|
2260
2276
|
);
|
|
2277
|
+
server.tool(
|
|
2278
|
+
"list_api_keys",
|
|
2279
|
+
"List the account's API keys: id, name, prefix, when they were made, when they expire and when they were last used. The keys themselves are never listed.",
|
|
2280
|
+
{},
|
|
2281
|
+
withErrorHandling(async () => jsonContent(await client.apiKeys.list()))
|
|
2282
|
+
);
|
|
2283
|
+
server.tool(
|
|
2284
|
+
"create_api_key",
|
|
2285
|
+
"Ask for a new API key for the account, for CI or another tool. The account's owner must approve it: this returns at once with a link and a code. Show the person the link and tell them to check that the page shows the same code, then call wait_for_approval with the approval id to get the key (shown once).",
|
|
2286
|
+
{
|
|
2287
|
+
name: import_zod2.z.string().min(1).max(64).describe('A name that says where the key is used, such as "GitHub Actions"'),
|
|
2288
|
+
expiresInDays: import_zod2.z.number().int().min(1).max(365).optional().describe("How many days the key works, 1 to 365 (default 90)")
|
|
2289
|
+
},
|
|
2290
|
+
withErrorHandling(async ({ name, expiresInDays }) => {
|
|
2291
|
+
const pending = await client.apiKeys.create({ name, expiresInDays });
|
|
2292
|
+
if (!pending.id) {
|
|
2293
|
+
const key = await pending.wait();
|
|
2294
|
+
return textContent(keyText(key));
|
|
2295
|
+
}
|
|
2296
|
+
return textContent(
|
|
2297
|
+
[
|
|
2298
|
+
`Asked for approval: ${pending.summary}`,
|
|
2299
|
+
`Show the person this link: ${pending.url}`,
|
|
2300
|
+
`The page shows the code ${pending.code}; ask them to approve only if it matches.`,
|
|
2301
|
+
`Then call wait_for_approval with id ${pending.id}. The request expires at ${pending.expiresAt}.`
|
|
2302
|
+
].join("\n")
|
|
2303
|
+
);
|
|
2304
|
+
})
|
|
2305
|
+
);
|
|
2306
|
+
server.tool(
|
|
2307
|
+
"wait_for_approval",
|
|
2308
|
+
"Wait for the account's owner to answer an approval (from create_api_key) and collect what it grants, such as the new API key. If they have not answered yet, call it again.",
|
|
2309
|
+
{
|
|
2310
|
+
id: import_zod2.z.string().describe("The approval id"),
|
|
2311
|
+
timeout: durationOrTimestampSchema.default("45s").describe('How long to wait for the person, for example "45s"')
|
|
2312
|
+
},
|
|
2313
|
+
withErrorHandling(async ({ id, timeout }) => {
|
|
2314
|
+
const ms = durationMs(timeout) ?? 45e3;
|
|
2315
|
+
try {
|
|
2316
|
+
const result = await client.approvals.wait(id, { timeout: ms });
|
|
2317
|
+
return textContent(keyText(result));
|
|
2318
|
+
} catch (error) {
|
|
2319
|
+
if (error instanceof import_sdk.ApprovalDeniedError) {
|
|
2320
|
+
return textContent(
|
|
2321
|
+
"The person refused it on the approval page. Do not ask again unless they tell you to."
|
|
2322
|
+
);
|
|
2323
|
+
}
|
|
2324
|
+
if (error instanceof import_sdk.ApprovalExpiredError) {
|
|
2325
|
+
return textContent("The approval expired. Ask again if the person still wants it.");
|
|
2326
|
+
}
|
|
2327
|
+
if (error instanceof import_sdk.TimeoutError) {
|
|
2328
|
+
return textContent(
|
|
2329
|
+
`Not answered yet. Remind the person of the link if needed, and call wait_for_approval with id ${id} again.`
|
|
2330
|
+
);
|
|
2331
|
+
}
|
|
2332
|
+
throw error;
|
|
2333
|
+
}
|
|
2334
|
+
})
|
|
2335
|
+
);
|
|
2336
|
+
server.tool(
|
|
2337
|
+
"revoke_api_key",
|
|
2338
|
+
"Revoke one of the account's API keys by its id (from list_api_keys). Anything using it stops working at once.",
|
|
2339
|
+
{
|
|
2340
|
+
id: import_zod2.z.string().describe("The key's id, from list_api_keys")
|
|
2341
|
+
},
|
|
2342
|
+
withErrorHandling(async ({ id }) => {
|
|
2343
|
+
await client.apiKeys.revoke(id);
|
|
2344
|
+
return textContent(`Revoked the API key ${id}, if the account had it.`);
|
|
2345
|
+
})
|
|
2346
|
+
);
|
|
2261
2347
|
server.tool(
|
|
2262
2348
|
"stop_share",
|
|
2263
2349
|
"Stop a public preview or live tunnel by its id (from list_shares). The CLI running it is told why and exits.",
|
|
@@ -12,6 +12,8 @@ import {
|
|
|
12
12
|
MAX_CONDITION_NAME_LEN,
|
|
13
13
|
MAX_CONDITION_PATH_LEN,
|
|
14
14
|
MAX_RULE_NAME_LEN,
|
|
15
|
+
ApprovalDeniedError,
|
|
16
|
+
ApprovalExpiredError,
|
|
15
17
|
NotFoundError,
|
|
16
18
|
RateLimitError,
|
|
17
19
|
TEMPLATE_METADATA,
|
|
@@ -476,6 +478,13 @@ function payloadSchemaResult(requests, args) {
|
|
|
476
478
|
}
|
|
477
479
|
return jsonContent(output);
|
|
478
480
|
}
|
|
481
|
+
function keyText(key) {
|
|
482
|
+
return [
|
|
483
|
+
`Approved. The API key ${key.name ? `"${key.name}" ` : ""}is: ${key.key ?? "(not returned)"}`,
|
|
484
|
+
`It is shown only this once: store it now (for example as a CI secret), never in code.`,
|
|
485
|
+
key.expiresAt ? `It works until ${key.expiresAt}.` : ""
|
|
486
|
+
].filter(Boolean).join("\n");
|
|
487
|
+
}
|
|
479
488
|
function textContent(text) {
|
|
480
489
|
return { content: [{ type: "text", text }] };
|
|
481
490
|
}
|
|
@@ -1575,6 +1584,15 @@ function registerTools(target, client, options = {}) {
|
|
|
1575
1584
|
);
|
|
1576
1585
|
})
|
|
1577
1586
|
);
|
|
1587
|
+
server.tool(
|
|
1588
|
+
"get_billing",
|
|
1589
|
+
"What the account pays for: the plan and its subscription (status, monthly or annual, when it renews, a pending change, whether it cancels at the period's end), the add-ons (extra requests, parsed pages, domains), and every team's subscription and add-ons. Read only: changing a plan, seats or add-ons takes the person in a browser.",
|
|
1590
|
+
{},
|
|
1591
|
+
withErrorHandling(async () => {
|
|
1592
|
+
const billing = await client.billing.get();
|
|
1593
|
+
return jsonContent(fitArrayField(billing, "teams"));
|
|
1594
|
+
})
|
|
1595
|
+
);
|
|
1578
1596
|
server.tool(
|
|
1579
1597
|
"get_usage",
|
|
1580
1598
|
"Check current request usage, remaining quota, plan, and period end; parsed pages, preview data (whk share) and AI assists, each with when it resets; and the pooled quota of every subscribed team you belong to.",
|
|
@@ -2036,6 +2054,76 @@ function registerTools(target, client, options = {}) {
|
|
|
2036
2054
|
return jsonContent(withShareHints(await client.shares.list(state ? { state } : {}), remote));
|
|
2037
2055
|
})
|
|
2038
2056
|
);
|
|
2057
|
+
server.tool(
|
|
2058
|
+
"list_api_keys",
|
|
2059
|
+
"List the account's API keys: id, name, prefix, when they were made, when they expire and when they were last used. The keys themselves are never listed.",
|
|
2060
|
+
{},
|
|
2061
|
+
withErrorHandling(async () => jsonContent(await client.apiKeys.list()))
|
|
2062
|
+
);
|
|
2063
|
+
server.tool(
|
|
2064
|
+
"create_api_key",
|
|
2065
|
+
"Ask for a new API key for the account, for CI or another tool. The account's owner must approve it: this returns at once with a link and a code. Show the person the link and tell them to check that the page shows the same code, then call wait_for_approval with the approval id to get the key (shown once).",
|
|
2066
|
+
{
|
|
2067
|
+
name: z.string().min(1).max(64).describe('A name that says where the key is used, such as "GitHub Actions"'),
|
|
2068
|
+
expiresInDays: z.number().int().min(1).max(365).optional().describe("How many days the key works, 1 to 365 (default 90)")
|
|
2069
|
+
},
|
|
2070
|
+
withErrorHandling(async ({ name, expiresInDays }) => {
|
|
2071
|
+
const pending = await client.apiKeys.create({ name, expiresInDays });
|
|
2072
|
+
if (!pending.id) {
|
|
2073
|
+
const key = await pending.wait();
|
|
2074
|
+
return textContent(keyText(key));
|
|
2075
|
+
}
|
|
2076
|
+
return textContent(
|
|
2077
|
+
[
|
|
2078
|
+
`Asked for approval: ${pending.summary}`,
|
|
2079
|
+
`Show the person this link: ${pending.url}`,
|
|
2080
|
+
`The page shows the code ${pending.code}; ask them to approve only if it matches.`,
|
|
2081
|
+
`Then call wait_for_approval with id ${pending.id}. The request expires at ${pending.expiresAt}.`
|
|
2082
|
+
].join("\n")
|
|
2083
|
+
);
|
|
2084
|
+
})
|
|
2085
|
+
);
|
|
2086
|
+
server.tool(
|
|
2087
|
+
"wait_for_approval",
|
|
2088
|
+
"Wait for the account's owner to answer an approval (from create_api_key) and collect what it grants, such as the new API key. If they have not answered yet, call it again.",
|
|
2089
|
+
{
|
|
2090
|
+
id: z.string().describe("The approval id"),
|
|
2091
|
+
timeout: durationOrTimestampSchema.default("45s").describe('How long to wait for the person, for example "45s"')
|
|
2092
|
+
},
|
|
2093
|
+
withErrorHandling(async ({ id, timeout }) => {
|
|
2094
|
+
const ms = durationMs(timeout) ?? 45e3;
|
|
2095
|
+
try {
|
|
2096
|
+
const result = await client.approvals.wait(id, { timeout: ms });
|
|
2097
|
+
return textContent(keyText(result));
|
|
2098
|
+
} catch (error) {
|
|
2099
|
+
if (error instanceof ApprovalDeniedError) {
|
|
2100
|
+
return textContent(
|
|
2101
|
+
"The person refused it on the approval page. Do not ask again unless they tell you to."
|
|
2102
|
+
);
|
|
2103
|
+
}
|
|
2104
|
+
if (error instanceof ApprovalExpiredError) {
|
|
2105
|
+
return textContent("The approval expired. Ask again if the person still wants it.");
|
|
2106
|
+
}
|
|
2107
|
+
if (error instanceof TimeoutError) {
|
|
2108
|
+
return textContent(
|
|
2109
|
+
`Not answered yet. Remind the person of the link if needed, and call wait_for_approval with id ${id} again.`
|
|
2110
|
+
);
|
|
2111
|
+
}
|
|
2112
|
+
throw error;
|
|
2113
|
+
}
|
|
2114
|
+
})
|
|
2115
|
+
);
|
|
2116
|
+
server.tool(
|
|
2117
|
+
"revoke_api_key",
|
|
2118
|
+
"Revoke one of the account's API keys by its id (from list_api_keys). Anything using it stops working at once.",
|
|
2119
|
+
{
|
|
2120
|
+
id: z.string().describe("The key's id, from list_api_keys")
|
|
2121
|
+
},
|
|
2122
|
+
withErrorHandling(async ({ id }) => {
|
|
2123
|
+
await client.apiKeys.revoke(id);
|
|
2124
|
+
return textContent(`Revoked the API key ${id}, if the account had it.`);
|
|
2125
|
+
})
|
|
2126
|
+
);
|
|
2039
2127
|
server.tool(
|
|
2040
2128
|
"stop_share",
|
|
2041
2129
|
"Stop a public preview or live tunnel by its id (from list_shares). The CLI running it is told why and exits.",
|
|
@@ -2141,6 +2229,7 @@ export {
|
|
|
2141
2229
|
textContent,
|
|
2142
2230
|
jsonContent,
|
|
2143
2231
|
withErrorHandling,
|
|
2232
|
+
LOCAL_ONLY_TOOLS,
|
|
2144
2233
|
REMOTE_MAX_WAIT_MS,
|
|
2145
2234
|
REMOTE_MIN_POLL_MS,
|
|
2146
2235
|
shareHints,
|
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.21.0" : "0.0.0-dev";
|
|
484
484
|
var MCP_USER_AGENT = `webhooks-cc-mcp/${VERSION}`;
|
|
485
485
|
|
|
486
486
|
// src/tools.ts
|
|
@@ -722,6 +722,13 @@ function payloadSchemaResult(requests, args) {
|
|
|
722
722
|
}
|
|
723
723
|
return jsonContent(output);
|
|
724
724
|
}
|
|
725
|
+
function keyText(key) {
|
|
726
|
+
return [
|
|
727
|
+
`Approved. The API key ${key.name ? `"${key.name}" ` : ""}is: ${key.key ?? "(not returned)"}`,
|
|
728
|
+
`It is shown only this once: store it now (for example as a CI secret), never in code.`,
|
|
729
|
+
key.expiresAt ? `It works until ${key.expiresAt}.` : ""
|
|
730
|
+
].filter(Boolean).join("\n");
|
|
731
|
+
}
|
|
725
732
|
function textContent(text) {
|
|
726
733
|
return { content: [{ type: "text", text }] };
|
|
727
734
|
}
|
|
@@ -1821,6 +1828,15 @@ function registerTools(target, client, options = {}) {
|
|
|
1821
1828
|
);
|
|
1822
1829
|
})
|
|
1823
1830
|
);
|
|
1831
|
+
server.tool(
|
|
1832
|
+
"get_billing",
|
|
1833
|
+
"What the account pays for: the plan and its subscription (status, monthly or annual, when it renews, a pending change, whether it cancels at the period's end), the add-ons (extra requests, parsed pages, domains), and every team's subscription and add-ons. Read only: changing a plan, seats or add-ons takes the person in a browser.",
|
|
1834
|
+
{},
|
|
1835
|
+
withErrorHandling(async () => {
|
|
1836
|
+
const billing = await client.billing.get();
|
|
1837
|
+
return jsonContent(fitArrayField(billing, "teams"));
|
|
1838
|
+
})
|
|
1839
|
+
);
|
|
1824
1840
|
server.tool(
|
|
1825
1841
|
"get_usage",
|
|
1826
1842
|
"Check current request usage, remaining quota, plan, and period end; parsed pages, preview data (whk share) and AI assists, each with when it resets; and the pooled quota of every subscribed team you belong to.",
|
|
@@ -2282,6 +2298,76 @@ function registerTools(target, client, options = {}) {
|
|
|
2282
2298
|
return jsonContent(withShareHints(await client.shares.list(state ? { state } : {}), remote));
|
|
2283
2299
|
})
|
|
2284
2300
|
);
|
|
2301
|
+
server.tool(
|
|
2302
|
+
"list_api_keys",
|
|
2303
|
+
"List the account's API keys: id, name, prefix, when they were made, when they expire and when they were last used. The keys themselves are never listed.",
|
|
2304
|
+
{},
|
|
2305
|
+
withErrorHandling(async () => jsonContent(await client.apiKeys.list()))
|
|
2306
|
+
);
|
|
2307
|
+
server.tool(
|
|
2308
|
+
"create_api_key",
|
|
2309
|
+
"Ask for a new API key for the account, for CI or another tool. The account's owner must approve it: this returns at once with a link and a code. Show the person the link and tell them to check that the page shows the same code, then call wait_for_approval with the approval id to get the key (shown once).",
|
|
2310
|
+
{
|
|
2311
|
+
name: import_zod2.z.string().min(1).max(64).describe('A name that says where the key is used, such as "GitHub Actions"'),
|
|
2312
|
+
expiresInDays: import_zod2.z.number().int().min(1).max(365).optional().describe("How many days the key works, 1 to 365 (default 90)")
|
|
2313
|
+
},
|
|
2314
|
+
withErrorHandling(async ({ name, expiresInDays }) => {
|
|
2315
|
+
const pending = await client.apiKeys.create({ name, expiresInDays });
|
|
2316
|
+
if (!pending.id) {
|
|
2317
|
+
const key = await pending.wait();
|
|
2318
|
+
return textContent(keyText(key));
|
|
2319
|
+
}
|
|
2320
|
+
return textContent(
|
|
2321
|
+
[
|
|
2322
|
+
`Asked for approval: ${pending.summary}`,
|
|
2323
|
+
`Show the person this link: ${pending.url}`,
|
|
2324
|
+
`The page shows the code ${pending.code}; ask them to approve only if it matches.`,
|
|
2325
|
+
`Then call wait_for_approval with id ${pending.id}. The request expires at ${pending.expiresAt}.`
|
|
2326
|
+
].join("\n")
|
|
2327
|
+
);
|
|
2328
|
+
})
|
|
2329
|
+
);
|
|
2330
|
+
server.tool(
|
|
2331
|
+
"wait_for_approval",
|
|
2332
|
+
"Wait for the account's owner to answer an approval (from create_api_key) and collect what it grants, such as the new API key. If they have not answered yet, call it again.",
|
|
2333
|
+
{
|
|
2334
|
+
id: import_zod2.z.string().describe("The approval id"),
|
|
2335
|
+
timeout: durationOrTimestampSchema.default("45s").describe('How long to wait for the person, for example "45s"')
|
|
2336
|
+
},
|
|
2337
|
+
withErrorHandling(async ({ id, timeout }) => {
|
|
2338
|
+
const ms = durationMs(timeout) ?? 45e3;
|
|
2339
|
+
try {
|
|
2340
|
+
const result = await client.approvals.wait(id, { timeout: ms });
|
|
2341
|
+
return textContent(keyText(result));
|
|
2342
|
+
} catch (error) {
|
|
2343
|
+
if (error instanceof import_sdk.ApprovalDeniedError) {
|
|
2344
|
+
return textContent(
|
|
2345
|
+
"The person refused it on the approval page. Do not ask again unless they tell you to."
|
|
2346
|
+
);
|
|
2347
|
+
}
|
|
2348
|
+
if (error instanceof import_sdk.ApprovalExpiredError) {
|
|
2349
|
+
return textContent("The approval expired. Ask again if the person still wants it.");
|
|
2350
|
+
}
|
|
2351
|
+
if (error instanceof import_sdk.TimeoutError) {
|
|
2352
|
+
return textContent(
|
|
2353
|
+
`Not answered yet. Remind the person of the link if needed, and call wait_for_approval with id ${id} again.`
|
|
2354
|
+
);
|
|
2355
|
+
}
|
|
2356
|
+
throw error;
|
|
2357
|
+
}
|
|
2358
|
+
})
|
|
2359
|
+
);
|
|
2360
|
+
server.tool(
|
|
2361
|
+
"revoke_api_key",
|
|
2362
|
+
"Revoke one of the account's API keys by its id (from list_api_keys). Anything using it stops working at once.",
|
|
2363
|
+
{
|
|
2364
|
+
id: import_zod2.z.string().describe("The key's id, from list_api_keys")
|
|
2365
|
+
},
|
|
2366
|
+
withErrorHandling(async ({ id }) => {
|
|
2367
|
+
await client.apiKeys.revoke(id);
|
|
2368
|
+
return textContent(`Revoked the API key ${id}, if the account had it.`);
|
|
2369
|
+
})
|
|
2370
|
+
);
|
|
2285
2371
|
server.tool(
|
|
2286
2372
|
"stop_share",
|
|
2287
2373
|
"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-BAGCOSXG.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.21.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.d.mts
CHANGED
|
@@ -135,7 +135,6 @@ type ToolResult = {
|
|
|
135
135
|
content: TextContent[];
|
|
136
136
|
isError?: boolean;
|
|
137
137
|
};
|
|
138
|
-
/** Create a text content response for MCP tools. */
|
|
139
138
|
declare function textContent(text: string): ToolResult;
|
|
140
139
|
declare function jsonContent(value: unknown): ToolResult;
|
|
141
140
|
/** Wrap a tool handler with error handling that returns structured MCP errors. */
|
|
@@ -162,6 +161,11 @@ interface RegisterToolsOptions {
|
|
|
162
161
|
*/
|
|
163
162
|
remote?: boolean;
|
|
164
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Tools that only make sense next to the caller: they post to a URL of the
|
|
166
|
+
* caller's choosing, or (share_port) run the whk CLI on the caller's machine.
|
|
167
|
+
*/
|
|
168
|
+
declare const LOCAL_ONLY_TOOLS: Set<string>;
|
|
165
169
|
/** Longest wait on the hosted server; Cloudflare ends a request after 100 seconds. */
|
|
166
170
|
declare const REMOTE_MAX_WAIT_MS = 50000;
|
|
167
171
|
/** Shortest poll interval on the hosted server: each poll is an API request. */
|
|
@@ -192,5 +196,5 @@ declare function withShareHints(list: TunnelShareList, remote?: boolean): Record
|
|
|
192
196
|
*/
|
|
193
197
|
declare function registerTools(target: ToolServer, client: WebhooksCC, options?: RegisterToolsOptions): RegisteredToolHandle[];
|
|
194
198
|
|
|
195
|
-
export { REMOTE_MAX_WAIT_MS, REMOTE_MIN_POLL_MS, createEndpointShape, deleteEndpointShape, getEndpointShape, getRequestShape, jsonContent, listEndpointsShape, listRequestsShape, payloadSchemaResult, payloadSchemaShape, registerTools, shareHints, textContent, toolWords, waitForRequestShape, withErrorHandling, withShareHints };
|
|
199
|
+
export { LOCAL_ONLY_TOOLS, REMOTE_MAX_WAIT_MS, REMOTE_MIN_POLL_MS, createEndpointShape, deleteEndpointShape, getEndpointShape, getRequestShape, jsonContent, listEndpointsShape, listRequestsShape, payloadSchemaResult, payloadSchemaShape, registerTools, shareHints, textContent, toolWords, waitForRequestShape, withErrorHandling, withShareHints };
|
|
196
200
|
export type { RegisterToolsOptions, RegisteredToolHandle, ToolResult, ToolServer };
|
package/dist/tools.d.ts
CHANGED
|
@@ -135,7 +135,6 @@ type ToolResult = {
|
|
|
135
135
|
content: TextContent[];
|
|
136
136
|
isError?: boolean;
|
|
137
137
|
};
|
|
138
|
-
/** Create a text content response for MCP tools. */
|
|
139
138
|
declare function textContent(text: string): ToolResult;
|
|
140
139
|
declare function jsonContent(value: unknown): ToolResult;
|
|
141
140
|
/** Wrap a tool handler with error handling that returns structured MCP errors. */
|
|
@@ -162,6 +161,11 @@ interface RegisterToolsOptions {
|
|
|
162
161
|
*/
|
|
163
162
|
remote?: boolean;
|
|
164
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Tools that only make sense next to the caller: they post to a URL of the
|
|
166
|
+
* caller's choosing, or (share_port) run the whk CLI on the caller's machine.
|
|
167
|
+
*/
|
|
168
|
+
declare const LOCAL_ONLY_TOOLS: Set<string>;
|
|
165
169
|
/** Longest wait on the hosted server; Cloudflare ends a request after 100 seconds. */
|
|
166
170
|
declare const REMOTE_MAX_WAIT_MS = 50000;
|
|
167
171
|
/** Shortest poll interval on the hosted server: each poll is an API request. */
|
|
@@ -192,5 +196,5 @@ declare function withShareHints(list: TunnelShareList, remote?: boolean): Record
|
|
|
192
196
|
*/
|
|
193
197
|
declare function registerTools(target: ToolServer, client: WebhooksCC, options?: RegisterToolsOptions): RegisteredToolHandle[];
|
|
194
198
|
|
|
195
|
-
export { REMOTE_MAX_WAIT_MS, REMOTE_MIN_POLL_MS, createEndpointShape, deleteEndpointShape, getEndpointShape, getRequestShape, jsonContent, listEndpointsShape, listRequestsShape, payloadSchemaResult, payloadSchemaShape, registerTools, shareHints, textContent, toolWords, waitForRequestShape, withErrorHandling, withShareHints };
|
|
199
|
+
export { LOCAL_ONLY_TOOLS, REMOTE_MAX_WAIT_MS, REMOTE_MIN_POLL_MS, createEndpointShape, deleteEndpointShape, getEndpointShape, getRequestShape, jsonContent, listEndpointsShape, listRequestsShape, payloadSchemaResult, payloadSchemaShape, registerTools, shareHints, textContent, toolWords, waitForRequestShape, withErrorHandling, withShareHints };
|
|
196
200
|
export type { RegisterToolsOptions, RegisteredToolHandle, ToolResult, ToolServer };
|
package/dist/tools.js
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/tools.ts
|
|
21
21
|
var tools_exports = {};
|
|
22
22
|
__export(tools_exports, {
|
|
23
|
+
LOCAL_ONLY_TOOLS: () => LOCAL_ONLY_TOOLS,
|
|
23
24
|
REMOTE_MAX_WAIT_MS: () => REMOTE_MAX_WAIT_MS,
|
|
24
25
|
REMOTE_MIN_POLL_MS: () => REMOTE_MIN_POLL_MS,
|
|
25
26
|
createEndpointShape: () => createEndpointShape,
|
|
@@ -488,6 +489,13 @@ function payloadSchemaResult(requests, args) {
|
|
|
488
489
|
}
|
|
489
490
|
return jsonContent(output);
|
|
490
491
|
}
|
|
492
|
+
function keyText(key) {
|
|
493
|
+
return [
|
|
494
|
+
`Approved. The API key ${key.name ? `"${key.name}" ` : ""}is: ${key.key ?? "(not returned)"}`,
|
|
495
|
+
`It is shown only this once: store it now (for example as a CI secret), never in code.`,
|
|
496
|
+
key.expiresAt ? `It works until ${key.expiresAt}.` : ""
|
|
497
|
+
].filter(Boolean).join("\n");
|
|
498
|
+
}
|
|
491
499
|
function textContent(text) {
|
|
492
500
|
return { content: [{ type: "text", text }] };
|
|
493
501
|
}
|
|
@@ -1587,6 +1595,15 @@ function registerTools(target, client, options = {}) {
|
|
|
1587
1595
|
);
|
|
1588
1596
|
})
|
|
1589
1597
|
);
|
|
1598
|
+
server.tool(
|
|
1599
|
+
"get_billing",
|
|
1600
|
+
"What the account pays for: the plan and its subscription (status, monthly or annual, when it renews, a pending change, whether it cancels at the period's end), the add-ons (extra requests, parsed pages, domains), and every team's subscription and add-ons. Read only: changing a plan, seats or add-ons takes the person in a browser.",
|
|
1601
|
+
{},
|
|
1602
|
+
withErrorHandling(async () => {
|
|
1603
|
+
const billing = await client.billing.get();
|
|
1604
|
+
return jsonContent(fitArrayField(billing, "teams"));
|
|
1605
|
+
})
|
|
1606
|
+
);
|
|
1590
1607
|
server.tool(
|
|
1591
1608
|
"get_usage",
|
|
1592
1609
|
"Check current request usage, remaining quota, plan, and period end; parsed pages, preview data (whk share) and AI assists, each with when it resets; and the pooled quota of every subscribed team you belong to.",
|
|
@@ -2048,6 +2065,76 @@ function registerTools(target, client, options = {}) {
|
|
|
2048
2065
|
return jsonContent(withShareHints(await client.shares.list(state ? { state } : {}), remote));
|
|
2049
2066
|
})
|
|
2050
2067
|
);
|
|
2068
|
+
server.tool(
|
|
2069
|
+
"list_api_keys",
|
|
2070
|
+
"List the account's API keys: id, name, prefix, when they were made, when they expire and when they were last used. The keys themselves are never listed.",
|
|
2071
|
+
{},
|
|
2072
|
+
withErrorHandling(async () => jsonContent(await client.apiKeys.list()))
|
|
2073
|
+
);
|
|
2074
|
+
server.tool(
|
|
2075
|
+
"create_api_key",
|
|
2076
|
+
"Ask for a new API key for the account, for CI or another tool. The account's owner must approve it: this returns at once with a link and a code. Show the person the link and tell them to check that the page shows the same code, then call wait_for_approval with the approval id to get the key (shown once).",
|
|
2077
|
+
{
|
|
2078
|
+
name: import_zod.z.string().min(1).max(64).describe('A name that says where the key is used, such as "GitHub Actions"'),
|
|
2079
|
+
expiresInDays: import_zod.z.number().int().min(1).max(365).optional().describe("How many days the key works, 1 to 365 (default 90)")
|
|
2080
|
+
},
|
|
2081
|
+
withErrorHandling(async ({ name, expiresInDays }) => {
|
|
2082
|
+
const pending = await client.apiKeys.create({ name, expiresInDays });
|
|
2083
|
+
if (!pending.id) {
|
|
2084
|
+
const key = await pending.wait();
|
|
2085
|
+
return textContent(keyText(key));
|
|
2086
|
+
}
|
|
2087
|
+
return textContent(
|
|
2088
|
+
[
|
|
2089
|
+
`Asked for approval: ${pending.summary}`,
|
|
2090
|
+
`Show the person this link: ${pending.url}`,
|
|
2091
|
+
`The page shows the code ${pending.code}; ask them to approve only if it matches.`,
|
|
2092
|
+
`Then call wait_for_approval with id ${pending.id}. The request expires at ${pending.expiresAt}.`
|
|
2093
|
+
].join("\n")
|
|
2094
|
+
);
|
|
2095
|
+
})
|
|
2096
|
+
);
|
|
2097
|
+
server.tool(
|
|
2098
|
+
"wait_for_approval",
|
|
2099
|
+
"Wait for the account's owner to answer an approval (from create_api_key) and collect what it grants, such as the new API key. If they have not answered yet, call it again.",
|
|
2100
|
+
{
|
|
2101
|
+
id: import_zod.z.string().describe("The approval id"),
|
|
2102
|
+
timeout: durationOrTimestampSchema.default("45s").describe('How long to wait for the person, for example "45s"')
|
|
2103
|
+
},
|
|
2104
|
+
withErrorHandling(async ({ id, timeout }) => {
|
|
2105
|
+
const ms = durationMs(timeout) ?? 45e3;
|
|
2106
|
+
try {
|
|
2107
|
+
const result = await client.approvals.wait(id, { timeout: ms });
|
|
2108
|
+
return textContent(keyText(result));
|
|
2109
|
+
} catch (error) {
|
|
2110
|
+
if (error instanceof import_sdk.ApprovalDeniedError) {
|
|
2111
|
+
return textContent(
|
|
2112
|
+
"The person refused it on the approval page. Do not ask again unless they tell you to."
|
|
2113
|
+
);
|
|
2114
|
+
}
|
|
2115
|
+
if (error instanceof import_sdk.ApprovalExpiredError) {
|
|
2116
|
+
return textContent("The approval expired. Ask again if the person still wants it.");
|
|
2117
|
+
}
|
|
2118
|
+
if (error instanceof import_sdk.TimeoutError) {
|
|
2119
|
+
return textContent(
|
|
2120
|
+
`Not answered yet. Remind the person of the link if needed, and call wait_for_approval with id ${id} again.`
|
|
2121
|
+
);
|
|
2122
|
+
}
|
|
2123
|
+
throw error;
|
|
2124
|
+
}
|
|
2125
|
+
})
|
|
2126
|
+
);
|
|
2127
|
+
server.tool(
|
|
2128
|
+
"revoke_api_key",
|
|
2129
|
+
"Revoke one of the account's API keys by its id (from list_api_keys). Anything using it stops working at once.",
|
|
2130
|
+
{
|
|
2131
|
+
id: import_zod.z.string().describe("The key's id, from list_api_keys")
|
|
2132
|
+
},
|
|
2133
|
+
withErrorHandling(async ({ id }) => {
|
|
2134
|
+
await client.apiKeys.revoke(id);
|
|
2135
|
+
return textContent(`Revoked the API key ${id}, if the account had it.`);
|
|
2136
|
+
})
|
|
2137
|
+
);
|
|
2051
2138
|
server.tool(
|
|
2052
2139
|
"stop_share",
|
|
2053
2140
|
"Stop a public preview or live tunnel by its id (from list_shares). The CLI running it is told why and exits.",
|
|
@@ -2140,6 +2227,7 @@ function registerTools(target, client, options = {}) {
|
|
|
2140
2227
|
}
|
|
2141
2228
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2142
2229
|
0 && (module.exports = {
|
|
2230
|
+
LOCAL_ONLY_TOOLS,
|
|
2143
2231
|
REMOTE_MAX_WAIT_MS,
|
|
2144
2232
|
REMOTE_MIN_POLL_MS,
|
|
2145
2233
|
createEndpointShape,
|
package/dist/tools.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
LOCAL_ONLY_TOOLS,
|
|
2
3
|
REMOTE_MAX_WAIT_MS,
|
|
3
4
|
REMOTE_MIN_POLL_MS,
|
|
4
5
|
createEndpointShape,
|
|
@@ -17,8 +18,9 @@ import {
|
|
|
17
18
|
waitForRequestShape,
|
|
18
19
|
withErrorHandling,
|
|
19
20
|
withShareHints
|
|
20
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-BAGCOSXG.mjs";
|
|
21
22
|
export {
|
|
23
|
+
LOCAL_ONLY_TOOLS,
|
|
22
24
|
REMOTE_MAX_WAIT_MS,
|
|
23
25
|
REMOTE_MIN_POLL_MS,
|
|
24
26
|
createEndpointShape,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webhooks-cc/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.21.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.25.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^26.6.6",
|