@webhooks-cc/mcp 1.18.0 → 1.20.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 +79 -2
- package/dist/{chunk-GTEE7L2Y.mjs → chunk-KLP2TU7I.mjs} +81 -1
- package/dist/index.js +79 -2
- package/dist/index.mjs +2 -2
- package/dist/tools.d.mts +6 -2
- package/dist/tools.d.ts +6 -2
- package/dist/tools.js +80 -1
- 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.20.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
|
}
|
|
@@ -1799,7 +1806,7 @@ function registerTools(target, client, options = {}) {
|
|
|
1799
1806
|
);
|
|
1800
1807
|
server.tool(
|
|
1801
1808
|
"get_usage",
|
|
1802
|
-
"Check current request usage, remaining quota, plan, and period end,
|
|
1809
|
+
"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.",
|
|
1803
1810
|
{},
|
|
1804
1811
|
withErrorHandling(async () => {
|
|
1805
1812
|
const [usageResult, teamsResult] = await Promise.allSettled([
|
|
@@ -2258,6 +2265,76 @@ function registerTools(target, client, options = {}) {
|
|
|
2258
2265
|
return jsonContent(withShareHints(await client.shares.list(state ? { state } : {}), remote));
|
|
2259
2266
|
})
|
|
2260
2267
|
);
|
|
2268
|
+
server.tool(
|
|
2269
|
+
"list_api_keys",
|
|
2270
|
+
"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.",
|
|
2271
|
+
{},
|
|
2272
|
+
withErrorHandling(async () => jsonContent(await client.apiKeys.list()))
|
|
2273
|
+
);
|
|
2274
|
+
server.tool(
|
|
2275
|
+
"create_api_key",
|
|
2276
|
+
"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).",
|
|
2277
|
+
{
|
|
2278
|
+
name: import_zod2.z.string().min(1).max(64).describe('A name that says where the key is used, such as "GitHub Actions"'),
|
|
2279
|
+
expiresInDays: import_zod2.z.number().int().min(1).max(365).optional().describe("How many days the key works, 1 to 365 (default 90)")
|
|
2280
|
+
},
|
|
2281
|
+
withErrorHandling(async ({ name, expiresInDays }) => {
|
|
2282
|
+
const pending = await client.apiKeys.create({ name, expiresInDays });
|
|
2283
|
+
if (!pending.id) {
|
|
2284
|
+
const key = await pending.wait();
|
|
2285
|
+
return textContent(keyText(key));
|
|
2286
|
+
}
|
|
2287
|
+
return textContent(
|
|
2288
|
+
[
|
|
2289
|
+
`Asked for approval: ${pending.summary}`,
|
|
2290
|
+
`Show the person this link: ${pending.url}`,
|
|
2291
|
+
`The page shows the code ${pending.code}; ask them to approve only if it matches.`,
|
|
2292
|
+
`Then call wait_for_approval with id ${pending.id}. The request expires at ${pending.expiresAt}.`
|
|
2293
|
+
].join("\n")
|
|
2294
|
+
);
|
|
2295
|
+
})
|
|
2296
|
+
);
|
|
2297
|
+
server.tool(
|
|
2298
|
+
"wait_for_approval",
|
|
2299
|
+
"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.",
|
|
2300
|
+
{
|
|
2301
|
+
id: import_zod2.z.string().describe("The approval id"),
|
|
2302
|
+
timeout: durationOrTimestampSchema.default("45s").describe('How long to wait for the person, for example "45s"')
|
|
2303
|
+
},
|
|
2304
|
+
withErrorHandling(async ({ id, timeout }) => {
|
|
2305
|
+
const ms = durationMs(timeout) ?? 45e3;
|
|
2306
|
+
try {
|
|
2307
|
+
const result = await client.approvals.wait(id, { timeout: ms });
|
|
2308
|
+
return textContent(keyText(result));
|
|
2309
|
+
} catch (error) {
|
|
2310
|
+
if (error instanceof import_sdk.ApprovalDeniedError) {
|
|
2311
|
+
return textContent(
|
|
2312
|
+
"The person refused it on the approval page. Do not ask again unless they tell you to."
|
|
2313
|
+
);
|
|
2314
|
+
}
|
|
2315
|
+
if (error instanceof import_sdk.ApprovalExpiredError) {
|
|
2316
|
+
return textContent("The approval expired. Ask again if the person still wants it.");
|
|
2317
|
+
}
|
|
2318
|
+
if (error instanceof import_sdk.TimeoutError) {
|
|
2319
|
+
return textContent(
|
|
2320
|
+
`Not answered yet. Remind the person of the link if needed, and call wait_for_approval with id ${id} again.`
|
|
2321
|
+
);
|
|
2322
|
+
}
|
|
2323
|
+
throw error;
|
|
2324
|
+
}
|
|
2325
|
+
})
|
|
2326
|
+
);
|
|
2327
|
+
server.tool(
|
|
2328
|
+
"revoke_api_key",
|
|
2329
|
+
"Revoke one of the account's API keys by its id (from list_api_keys). Anything using it stops working at once.",
|
|
2330
|
+
{
|
|
2331
|
+
id: import_zod2.z.string().describe("The key's id, from list_api_keys")
|
|
2332
|
+
},
|
|
2333
|
+
withErrorHandling(async ({ id }) => {
|
|
2334
|
+
await client.apiKeys.revoke(id);
|
|
2335
|
+
return textContent(`Revoked the API key ${id}, if the account had it.`);
|
|
2336
|
+
})
|
|
2337
|
+
);
|
|
2261
2338
|
server.tool(
|
|
2262
2339
|
"stop_share",
|
|
2263
2340
|
"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
|
}
|
|
@@ -1577,7 +1586,7 @@ function registerTools(target, client, options = {}) {
|
|
|
1577
1586
|
);
|
|
1578
1587
|
server.tool(
|
|
1579
1588
|
"get_usage",
|
|
1580
|
-
"Check current request usage, remaining quota, plan, and period end,
|
|
1589
|
+
"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.",
|
|
1581
1590
|
{},
|
|
1582
1591
|
withErrorHandling(async () => {
|
|
1583
1592
|
const [usageResult, teamsResult] = await Promise.allSettled([
|
|
@@ -2036,6 +2045,76 @@ function registerTools(target, client, options = {}) {
|
|
|
2036
2045
|
return jsonContent(withShareHints(await client.shares.list(state ? { state } : {}), remote));
|
|
2037
2046
|
})
|
|
2038
2047
|
);
|
|
2048
|
+
server.tool(
|
|
2049
|
+
"list_api_keys",
|
|
2050
|
+
"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.",
|
|
2051
|
+
{},
|
|
2052
|
+
withErrorHandling(async () => jsonContent(await client.apiKeys.list()))
|
|
2053
|
+
);
|
|
2054
|
+
server.tool(
|
|
2055
|
+
"create_api_key",
|
|
2056
|
+
"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).",
|
|
2057
|
+
{
|
|
2058
|
+
name: z.string().min(1).max(64).describe('A name that says where the key is used, such as "GitHub Actions"'),
|
|
2059
|
+
expiresInDays: z.number().int().min(1).max(365).optional().describe("How many days the key works, 1 to 365 (default 90)")
|
|
2060
|
+
},
|
|
2061
|
+
withErrorHandling(async ({ name, expiresInDays }) => {
|
|
2062
|
+
const pending = await client.apiKeys.create({ name, expiresInDays });
|
|
2063
|
+
if (!pending.id) {
|
|
2064
|
+
const key = await pending.wait();
|
|
2065
|
+
return textContent(keyText(key));
|
|
2066
|
+
}
|
|
2067
|
+
return textContent(
|
|
2068
|
+
[
|
|
2069
|
+
`Asked for approval: ${pending.summary}`,
|
|
2070
|
+
`Show the person this link: ${pending.url}`,
|
|
2071
|
+
`The page shows the code ${pending.code}; ask them to approve only if it matches.`,
|
|
2072
|
+
`Then call wait_for_approval with id ${pending.id}. The request expires at ${pending.expiresAt}.`
|
|
2073
|
+
].join("\n")
|
|
2074
|
+
);
|
|
2075
|
+
})
|
|
2076
|
+
);
|
|
2077
|
+
server.tool(
|
|
2078
|
+
"wait_for_approval",
|
|
2079
|
+
"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.",
|
|
2080
|
+
{
|
|
2081
|
+
id: z.string().describe("The approval id"),
|
|
2082
|
+
timeout: durationOrTimestampSchema.default("45s").describe('How long to wait for the person, for example "45s"')
|
|
2083
|
+
},
|
|
2084
|
+
withErrorHandling(async ({ id, timeout }) => {
|
|
2085
|
+
const ms = durationMs(timeout) ?? 45e3;
|
|
2086
|
+
try {
|
|
2087
|
+
const result = await client.approvals.wait(id, { timeout: ms });
|
|
2088
|
+
return textContent(keyText(result));
|
|
2089
|
+
} catch (error) {
|
|
2090
|
+
if (error instanceof ApprovalDeniedError) {
|
|
2091
|
+
return textContent(
|
|
2092
|
+
"The person refused it on the approval page. Do not ask again unless they tell you to."
|
|
2093
|
+
);
|
|
2094
|
+
}
|
|
2095
|
+
if (error instanceof ApprovalExpiredError) {
|
|
2096
|
+
return textContent("The approval expired. Ask again if the person still wants it.");
|
|
2097
|
+
}
|
|
2098
|
+
if (error instanceof TimeoutError) {
|
|
2099
|
+
return textContent(
|
|
2100
|
+
`Not answered yet. Remind the person of the link if needed, and call wait_for_approval with id ${id} again.`
|
|
2101
|
+
);
|
|
2102
|
+
}
|
|
2103
|
+
throw error;
|
|
2104
|
+
}
|
|
2105
|
+
})
|
|
2106
|
+
);
|
|
2107
|
+
server.tool(
|
|
2108
|
+
"revoke_api_key",
|
|
2109
|
+
"Revoke one of the account's API keys by its id (from list_api_keys). Anything using it stops working at once.",
|
|
2110
|
+
{
|
|
2111
|
+
id: z.string().describe("The key's id, from list_api_keys")
|
|
2112
|
+
},
|
|
2113
|
+
withErrorHandling(async ({ id }) => {
|
|
2114
|
+
await client.apiKeys.revoke(id);
|
|
2115
|
+
return textContent(`Revoked the API key ${id}, if the account had it.`);
|
|
2116
|
+
})
|
|
2117
|
+
);
|
|
2039
2118
|
server.tool(
|
|
2040
2119
|
"stop_share",
|
|
2041
2120
|
"Stop a public preview or live tunnel by its id (from list_shares). The CLI running it is told why and exits.",
|
|
@@ -2141,6 +2220,7 @@ export {
|
|
|
2141
2220
|
textContent,
|
|
2142
2221
|
jsonContent,
|
|
2143
2222
|
withErrorHandling,
|
|
2223
|
+
LOCAL_ONLY_TOOLS,
|
|
2144
2224
|
REMOTE_MAX_WAIT_MS,
|
|
2145
2225
|
REMOTE_MIN_POLL_MS,
|
|
2146
2226
|
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.20.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
|
}
|
|
@@ -1823,7 +1830,7 @@ function registerTools(target, client, options = {}) {
|
|
|
1823
1830
|
);
|
|
1824
1831
|
server.tool(
|
|
1825
1832
|
"get_usage",
|
|
1826
|
-
"Check current request usage, remaining quota, plan, and period end,
|
|
1833
|
+
"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.",
|
|
1827
1834
|
{},
|
|
1828
1835
|
withErrorHandling(async () => {
|
|
1829
1836
|
const [usageResult, teamsResult] = await Promise.allSettled([
|
|
@@ -2282,6 +2289,76 @@ function registerTools(target, client, options = {}) {
|
|
|
2282
2289
|
return jsonContent(withShareHints(await client.shares.list(state ? { state } : {}), remote));
|
|
2283
2290
|
})
|
|
2284
2291
|
);
|
|
2292
|
+
server.tool(
|
|
2293
|
+
"list_api_keys",
|
|
2294
|
+
"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.",
|
|
2295
|
+
{},
|
|
2296
|
+
withErrorHandling(async () => jsonContent(await client.apiKeys.list()))
|
|
2297
|
+
);
|
|
2298
|
+
server.tool(
|
|
2299
|
+
"create_api_key",
|
|
2300
|
+
"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).",
|
|
2301
|
+
{
|
|
2302
|
+
name: import_zod2.z.string().min(1).max(64).describe('A name that says where the key is used, such as "GitHub Actions"'),
|
|
2303
|
+
expiresInDays: import_zod2.z.number().int().min(1).max(365).optional().describe("How many days the key works, 1 to 365 (default 90)")
|
|
2304
|
+
},
|
|
2305
|
+
withErrorHandling(async ({ name, expiresInDays }) => {
|
|
2306
|
+
const pending = await client.apiKeys.create({ name, expiresInDays });
|
|
2307
|
+
if (!pending.id) {
|
|
2308
|
+
const key = await pending.wait();
|
|
2309
|
+
return textContent(keyText(key));
|
|
2310
|
+
}
|
|
2311
|
+
return textContent(
|
|
2312
|
+
[
|
|
2313
|
+
`Asked for approval: ${pending.summary}`,
|
|
2314
|
+
`Show the person this link: ${pending.url}`,
|
|
2315
|
+
`The page shows the code ${pending.code}; ask them to approve only if it matches.`,
|
|
2316
|
+
`Then call wait_for_approval with id ${pending.id}. The request expires at ${pending.expiresAt}.`
|
|
2317
|
+
].join("\n")
|
|
2318
|
+
);
|
|
2319
|
+
})
|
|
2320
|
+
);
|
|
2321
|
+
server.tool(
|
|
2322
|
+
"wait_for_approval",
|
|
2323
|
+
"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.",
|
|
2324
|
+
{
|
|
2325
|
+
id: import_zod2.z.string().describe("The approval id"),
|
|
2326
|
+
timeout: durationOrTimestampSchema.default("45s").describe('How long to wait for the person, for example "45s"')
|
|
2327
|
+
},
|
|
2328
|
+
withErrorHandling(async ({ id, timeout }) => {
|
|
2329
|
+
const ms = durationMs(timeout) ?? 45e3;
|
|
2330
|
+
try {
|
|
2331
|
+
const result = await client.approvals.wait(id, { timeout: ms });
|
|
2332
|
+
return textContent(keyText(result));
|
|
2333
|
+
} catch (error) {
|
|
2334
|
+
if (error instanceof import_sdk.ApprovalDeniedError) {
|
|
2335
|
+
return textContent(
|
|
2336
|
+
"The person refused it on the approval page. Do not ask again unless they tell you to."
|
|
2337
|
+
);
|
|
2338
|
+
}
|
|
2339
|
+
if (error instanceof import_sdk.ApprovalExpiredError) {
|
|
2340
|
+
return textContent("The approval expired. Ask again if the person still wants it.");
|
|
2341
|
+
}
|
|
2342
|
+
if (error instanceof import_sdk.TimeoutError) {
|
|
2343
|
+
return textContent(
|
|
2344
|
+
`Not answered yet. Remind the person of the link if needed, and call wait_for_approval with id ${id} again.`
|
|
2345
|
+
);
|
|
2346
|
+
}
|
|
2347
|
+
throw error;
|
|
2348
|
+
}
|
|
2349
|
+
})
|
|
2350
|
+
);
|
|
2351
|
+
server.tool(
|
|
2352
|
+
"revoke_api_key",
|
|
2353
|
+
"Revoke one of the account's API keys by its id (from list_api_keys). Anything using it stops working at once.",
|
|
2354
|
+
{
|
|
2355
|
+
id: import_zod2.z.string().describe("The key's id, from list_api_keys")
|
|
2356
|
+
},
|
|
2357
|
+
withErrorHandling(async ({ id }) => {
|
|
2358
|
+
await client.apiKeys.revoke(id);
|
|
2359
|
+
return textContent(`Revoked the API key ${id}, if the account had it.`);
|
|
2360
|
+
})
|
|
2361
|
+
);
|
|
2285
2362
|
server.tool(
|
|
2286
2363
|
"stop_share",
|
|
2287
2364
|
"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-KLP2TU7I.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.20.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
|
}
|
|
@@ -1589,7 +1597,7 @@ function registerTools(target, client, options = {}) {
|
|
|
1589
1597
|
);
|
|
1590
1598
|
server.tool(
|
|
1591
1599
|
"get_usage",
|
|
1592
|
-
"Check current request usage, remaining quota, plan, and period end,
|
|
1600
|
+
"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.",
|
|
1593
1601
|
{},
|
|
1594
1602
|
withErrorHandling(async () => {
|
|
1595
1603
|
const [usageResult, teamsResult] = await Promise.allSettled([
|
|
@@ -2048,6 +2056,76 @@ function registerTools(target, client, options = {}) {
|
|
|
2048
2056
|
return jsonContent(withShareHints(await client.shares.list(state ? { state } : {}), remote));
|
|
2049
2057
|
})
|
|
2050
2058
|
);
|
|
2059
|
+
server.tool(
|
|
2060
|
+
"list_api_keys",
|
|
2061
|
+
"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.",
|
|
2062
|
+
{},
|
|
2063
|
+
withErrorHandling(async () => jsonContent(await client.apiKeys.list()))
|
|
2064
|
+
);
|
|
2065
|
+
server.tool(
|
|
2066
|
+
"create_api_key",
|
|
2067
|
+
"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).",
|
|
2068
|
+
{
|
|
2069
|
+
name: import_zod.z.string().min(1).max(64).describe('A name that says where the key is used, such as "GitHub Actions"'),
|
|
2070
|
+
expiresInDays: import_zod.z.number().int().min(1).max(365).optional().describe("How many days the key works, 1 to 365 (default 90)")
|
|
2071
|
+
},
|
|
2072
|
+
withErrorHandling(async ({ name, expiresInDays }) => {
|
|
2073
|
+
const pending = await client.apiKeys.create({ name, expiresInDays });
|
|
2074
|
+
if (!pending.id) {
|
|
2075
|
+
const key = await pending.wait();
|
|
2076
|
+
return textContent(keyText(key));
|
|
2077
|
+
}
|
|
2078
|
+
return textContent(
|
|
2079
|
+
[
|
|
2080
|
+
`Asked for approval: ${pending.summary}`,
|
|
2081
|
+
`Show the person this link: ${pending.url}`,
|
|
2082
|
+
`The page shows the code ${pending.code}; ask them to approve only if it matches.`,
|
|
2083
|
+
`Then call wait_for_approval with id ${pending.id}. The request expires at ${pending.expiresAt}.`
|
|
2084
|
+
].join("\n")
|
|
2085
|
+
);
|
|
2086
|
+
})
|
|
2087
|
+
);
|
|
2088
|
+
server.tool(
|
|
2089
|
+
"wait_for_approval",
|
|
2090
|
+
"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.",
|
|
2091
|
+
{
|
|
2092
|
+
id: import_zod.z.string().describe("The approval id"),
|
|
2093
|
+
timeout: durationOrTimestampSchema.default("45s").describe('How long to wait for the person, for example "45s"')
|
|
2094
|
+
},
|
|
2095
|
+
withErrorHandling(async ({ id, timeout }) => {
|
|
2096
|
+
const ms = durationMs(timeout) ?? 45e3;
|
|
2097
|
+
try {
|
|
2098
|
+
const result = await client.approvals.wait(id, { timeout: ms });
|
|
2099
|
+
return textContent(keyText(result));
|
|
2100
|
+
} catch (error) {
|
|
2101
|
+
if (error instanceof import_sdk.ApprovalDeniedError) {
|
|
2102
|
+
return textContent(
|
|
2103
|
+
"The person refused it on the approval page. Do not ask again unless they tell you to."
|
|
2104
|
+
);
|
|
2105
|
+
}
|
|
2106
|
+
if (error instanceof import_sdk.ApprovalExpiredError) {
|
|
2107
|
+
return textContent("The approval expired. Ask again if the person still wants it.");
|
|
2108
|
+
}
|
|
2109
|
+
if (error instanceof import_sdk.TimeoutError) {
|
|
2110
|
+
return textContent(
|
|
2111
|
+
`Not answered yet. Remind the person of the link if needed, and call wait_for_approval with id ${id} again.`
|
|
2112
|
+
);
|
|
2113
|
+
}
|
|
2114
|
+
throw error;
|
|
2115
|
+
}
|
|
2116
|
+
})
|
|
2117
|
+
);
|
|
2118
|
+
server.tool(
|
|
2119
|
+
"revoke_api_key",
|
|
2120
|
+
"Revoke one of the account's API keys by its id (from list_api_keys). Anything using it stops working at once.",
|
|
2121
|
+
{
|
|
2122
|
+
id: import_zod.z.string().describe("The key's id, from list_api_keys")
|
|
2123
|
+
},
|
|
2124
|
+
withErrorHandling(async ({ id }) => {
|
|
2125
|
+
await client.apiKeys.revoke(id);
|
|
2126
|
+
return textContent(`Revoked the API key ${id}, if the account had it.`);
|
|
2127
|
+
})
|
|
2128
|
+
);
|
|
2051
2129
|
server.tool(
|
|
2052
2130
|
"stop_share",
|
|
2053
2131
|
"Stop a public preview or live tunnel by its id (from list_shares). The CLI running it is told why and exits.",
|
|
@@ -2140,6 +2218,7 @@ function registerTools(target, client, options = {}) {
|
|
|
2140
2218
|
}
|
|
2141
2219
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2142
2220
|
0 && (module.exports = {
|
|
2221
|
+
LOCAL_ONLY_TOOLS,
|
|
2143
2222
|
REMOTE_MAX_WAIT_MS,
|
|
2144
2223
|
REMOTE_MIN_POLL_MS,
|
|
2145
2224
|
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-KLP2TU7I.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.20.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.24.0"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^26.6.6",
|