@webhooks-cc/mcp 1.13.0 → 1.14.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/README.md +15 -9
- package/dist/bin/mcp.js +252 -42
- package/dist/index.js +252 -42
- package/dist/index.mjs +256 -44
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -441,28 +441,75 @@ var methodSchema = import_zod2.z.enum(HTTP_METHODS).default("POST").describe("HT
|
|
|
441
441
|
var kindSchema = import_zod2.z.enum(["http", "email"]).optional().describe('Only HTTP requests ("http") or only captured emails ("email")');
|
|
442
442
|
var EMAIL_SCAN_LIMIT = 100;
|
|
443
443
|
var durationOrTimestampSchema = import_zod2.z.union([import_zod2.z.string(), import_zod2.z.number()]);
|
|
444
|
-
var
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
444
|
+
var CONDITION_FIELD_NAMES = Object.keys(import_sdk.CONDITION_FIELDS);
|
|
445
|
+
var CONDITION_OP_NAMES = import_sdk.CONDITION_OPS;
|
|
446
|
+
function conditionSchema(use) {
|
|
447
|
+
const fields = use === "response" ? CONDITION_FIELD_NAMES.filter((field) => import_sdk.CONDITION_FIELDS[field].response) : CONDITION_FIELD_NAMES;
|
|
448
|
+
return import_zod2.z.object({
|
|
449
|
+
field: import_zod2.z.enum(fields).describe(
|
|
450
|
+
use === "response" ? "What to read: method, path, header (name), query (name), body (text), body_path (path into a JSON or form body), content_type, size" : "What to read: method, path, header (name), query (name), body, body_path (path), content_type, size, kind (http or email), email (name: subject, from, to, text or tag), spam_score, email_auth (name: spf, dkim or dmarc), signature (verified, failed or missing)"
|
|
451
|
+
),
|
|
452
|
+
op: import_zod2.z.enum(CONDITION_OP_NAMES).describe(
|
|
453
|
+
"eq, neq, contains, not_contains, starts_with, ends_with, matches (glob: * one path segment, ** any, ? one character), regex (RE2, searched anywhere; (?i) ignores case), exists, not_exists, gt, gte, lt, lte (numbers)"
|
|
454
|
+
),
|
|
455
|
+
value: import_zod2.z.string().max(import_sdk.MAX_CONDITION_VALUE_LEN).optional().describe(`What to compare with (not for exists and not_exists)`),
|
|
456
|
+
name: import_zod2.z.string().max(import_sdk.MAX_CONDITION_NAME_LEN).optional().describe("Header or query parameter name; the email part; spf, dkim or dmarc"),
|
|
457
|
+
path: import_zod2.z.string().max(import_sdk.MAX_CONDITION_PATH_LEN).optional().describe('Dot path for body_path, e.g. data.object.status or items.0.sku or a["odd.key"]')
|
|
458
|
+
}).superRefine((condition, ctx) => {
|
|
459
|
+
for (const issue of (0, import_sdk.conditionIssues)(condition, { use })) {
|
|
460
|
+
ctx.addIssue({ code: "custom", message: issue });
|
|
461
|
+
}
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
var ruleConditionSchema = conditionSchema("response");
|
|
465
|
+
var destinationFields = {
|
|
466
|
+
name: import_zod2.z.string().max(100).nullable().optional().describe("A name for the list and the log"),
|
|
467
|
+
enabled: import_zod2.z.boolean().optional().describe("Send to it (default true)"),
|
|
468
|
+
http: import_zod2.z.boolean().optional().describe("Takes HTTP requests (default true)"),
|
|
469
|
+
email: import_zod2.z.boolean().optional().describe("Takes emails (default true)"),
|
|
470
|
+
filter: import_zod2.z.object({
|
|
471
|
+
logic: import_zod2.z.enum(["and", "or"]).optional().describe("and (default): every condition; or: any"),
|
|
472
|
+
conditions: import_zod2.z.array(conditionSchema("filter")).max(10)
|
|
473
|
+
}).nullable().optional().describe(
|
|
474
|
+
"Send only captures that match (null: everything it takes). Conditions like response rules plus kind, email (name: subject, from, to, text, tag), spam_score, email_auth (name: spf, dkim, dmarc) and signature (verified, failed, missing)"
|
|
449
475
|
),
|
|
450
|
-
|
|
451
|
-
|
|
476
|
+
format: import_zod2.z.enum([
|
|
477
|
+
"auto",
|
|
478
|
+
"as_received",
|
|
479
|
+
"json",
|
|
480
|
+
"template",
|
|
481
|
+
"chat",
|
|
482
|
+
"postmark",
|
|
483
|
+
"sendgrid",
|
|
484
|
+
"mailgun",
|
|
485
|
+
"cloudmailin"
|
|
486
|
+
]).optional().describe(
|
|
487
|
+
"auto (pick from the URL), as_received (relay HTTP requests unchanged; emails as signed JSON), json (signed JSON envelope), template (your bodyTemplate, signed like json), chat (Slack or Discord message), or an inbound mail provider's shape for emails (postmark, sendgrid, mailgun, cloudmailin; HTTP requests then go as received), to test the inbound handler you wrote for that provider"
|
|
452
488
|
),
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
)
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
(
|
|
460
|
-
|
|
461
|
-
)
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
489
|
+
mailgunSigningKey: import_zod2.z.string().max(200).nullable().optional().describe(
|
|
490
|
+
"For format mailgun: your Mailgun HTTP webhook signing key, so the form's signature verifies; null removes it. Write-only."
|
|
491
|
+
),
|
|
492
|
+
bodyTemplate: import_zod2.z.unknown().optional().describe(
|
|
493
|
+
`For format template: any JSON value whose strings hold {{ placeholders }}, e.g. {"event": "{{ json.type }}", "amount": "{{ json.data.amount }}", "code": "{{ codes.0 }}"}. A string that is only a placeholder keeps the value's type; a missing field becomes null. HTTP requests read method, path, query.x, headers.x, body, json.path, id, receivedAt, signature; emails read the email.received fields (subject, from.address, to, text, codes, links, auth, spam, tag)`
|
|
494
|
+
),
|
|
495
|
+
messageTemplate: import_zod2.z.string().max(4e3).nullable().optional().describe(
|
|
496
|
+
"For format chat: the message text with {{ placeholders }}; null sends the standard message"
|
|
497
|
+
),
|
|
498
|
+
headers: import_zod2.z.array(
|
|
499
|
+
import_zod2.z.object({
|
|
500
|
+
name: import_zod2.z.string().describe("Header name, e.g. Authorization"),
|
|
501
|
+
value: import_zod2.z.string().nullable().describe("Value, or null to keep the stored one")
|
|
502
|
+
})
|
|
503
|
+
).max(10).optional().describe("Your own headers for every delivery (not chat). Replaces the whole list"),
|
|
504
|
+
appendPath: import_zod2.z.boolean().optional().describe("Append the captured path to the URL (as_received)"),
|
|
505
|
+
retrySeconds: import_zod2.z.union([import_zod2.z.literal(0), import_zod2.z.literal(3600), import_zod2.z.literal(86400)]).optional().describe("Retry failed deliveries for 86400 (default), 3600 or 0 seconds"),
|
|
506
|
+
keepOrder: import_zod2.z.boolean().optional().describe("One delivery at a time, in capture order"),
|
|
507
|
+
sentField: import_zod2.z.string().max(128).nullable().optional().describe("JSON body field with the sender's own timestamp"),
|
|
508
|
+
throttleSeconds: import_zod2.z.number().int().min(0).max(3600).optional().describe(
|
|
509
|
+
"At most one delivery every N seconds; the rest are not sent (1 makes a heads-up channel)"
|
|
510
|
+
),
|
|
511
|
+
delaySeconds: import_zod2.z.number().int().min(0).max(3600).optional().describe("Wait this long after the capture before sending, like a callback")
|
|
512
|
+
};
|
|
466
513
|
var responseRuleSchema = import_zod2.z.object({
|
|
467
514
|
name: import_zod2.z.string().max(import_sdk.MAX_RULE_NAME_LEN).optional().describe(`Human-readable rule name (max ${import_sdk.MAX_RULE_NAME_LEN} chars)`),
|
|
468
515
|
enabled: import_zod2.z.boolean().optional().default(true).describe("Whether this rule is active"),
|
|
@@ -473,8 +520,10 @@ var responseRuleSchema = import_zod2.z.object({
|
|
|
473
520
|
var responseRulesSchema = import_zod2.z.array(responseRuleSchema).max(50).describe("Ordered conditional response rules (first match wins, max 50)");
|
|
474
521
|
var mockResponseSchema = import_zod2.z.object({
|
|
475
522
|
status: import_zod2.z.number().int().min(import_sdk.MOCK_RESPONSE_STATUS_MIN).max(import_sdk.MOCK_RESPONSE_STATUS_MAX).describe(`HTTP status code (${import_sdk.MOCK_RESPONSE_STATUS_MIN}-${import_sdk.MOCK_RESPONSE_STATUS_MAX})`),
|
|
476
|
-
body: import_zod2.z.string().default("").describe(
|
|
477
|
-
|
|
523
|
+
body: import_zod2.z.string().default("").describe(
|
|
524
|
+
'Response body (default: empty). {{ placeholders }} are filled in from the request: {{ json.id }} (a JSON or form body field), {{ body }}, {{ headers.user-agent }}, {{ query.page }}, {{ method }}, {{ path }}, {{ id }}, {{ uuid }}, {{ now }}; filters: | default: "x", | json, | lower, | upper, | truncate: 80'
|
|
525
|
+
),
|
|
526
|
+
headers: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.string()).default({}).describe("Response headers (default: none); values may use {{ placeholders }} too"),
|
|
478
527
|
delay: import_zod2.z.number().int().min(import_sdk.MOCK_RESPONSE_DELAY_MIN).max(import_sdk.MOCK_RESPONSE_DELAY_MAX).optional().describe(
|
|
479
528
|
`Response delay in milliseconds (${import_sdk.MOCK_RESPONSE_DELAY_MIN}-${import_sdk.MOCK_RESPONSE_DELAY_MAX}, default: none)`
|
|
480
529
|
)
|
|
@@ -829,6 +878,8 @@ var ESSENTIAL_DETAIL_FIELDS = [
|
|
|
829
878
|
"tag",
|
|
830
879
|
"subject",
|
|
831
880
|
"from",
|
|
881
|
+
"fields",
|
|
882
|
+
"replyText",
|
|
832
883
|
"size",
|
|
833
884
|
"test",
|
|
834
885
|
"spam",
|
|
@@ -838,6 +889,11 @@ var ESSENTIAL_DETAIL_FIELDS = [
|
|
|
838
889
|
"html",
|
|
839
890
|
"htmlTruncated"
|
|
840
891
|
];
|
|
892
|
+
function shrinkRendered(rendered, max) {
|
|
893
|
+
const body = typeof rendered.body === "string" ? rendered.body : "";
|
|
894
|
+
if (body.length <= max - 1024) return rendered;
|
|
895
|
+
return { ...rendered, body: body.slice(0, max - 1024), bodyTruncated: true };
|
|
896
|
+
}
|
|
841
897
|
function emailDetail(client, email, view, includeHtml) {
|
|
842
898
|
const { data } = client.emails.toJson(email, {
|
|
843
899
|
endpoint: view.endpoint,
|
|
@@ -1000,7 +1056,7 @@ function registerTools(server, client) {
|
|
|
1000
1056
|
);
|
|
1001
1057
|
server.tool(
|
|
1002
1058
|
"update_endpoint",
|
|
1003
|
-
"Update an endpoint name, mock response, conditional response rules, signing configuration,
|
|
1059
|
+
"Update an endpoint name, mock response, conditional response rules, signing configuration, whether codes and links are picked out of its emails, or the named fields picked out of them.",
|
|
1004
1060
|
{
|
|
1005
1061
|
slug: import_zod2.z.string().describe("The endpoint slug to update"),
|
|
1006
1062
|
name: import_zod2.z.string().optional().describe("New display name"),
|
|
@@ -1014,7 +1070,17 @@ function registerTools(server, client) {
|
|
|
1014
1070
|
signingHeader: import_zod2.z.string().nullable().optional().describe(
|
|
1015
1071
|
"Custom signature header name (only for generic-hmac provider), or null to clear"
|
|
1016
1072
|
),
|
|
1017
|
-
showEmailExtracts: import_zod2.z.boolean().optional().describe("Pick codes and links out of emails (dashboard and forwarded JSON). Owner only.")
|
|
1073
|
+
showEmailExtracts: import_zod2.z.boolean().optional().describe("Pick codes and links out of emails (dashboard and forwarded JSON). Owner only."),
|
|
1074
|
+
emailFields: import_zod2.z.array(
|
|
1075
|
+
import_zod2.z.object({
|
|
1076
|
+
name: import_zod2.z.string().describe("Letters, digits and _, starting with a letter: {{ fields.name }}"),
|
|
1077
|
+
from: import_zod2.z.enum(["subject", "text", "html", "from", "to", "header"]).describe("What it reads; html is the HTML as text"),
|
|
1078
|
+
header: import_zod2.z.string().optional().describe('The header name, for from "header"'),
|
|
1079
|
+
pattern: import_zod2.z.string().describe("RE2 regular expression; the first group is the value (no lookarounds)")
|
|
1080
|
+
})
|
|
1081
|
+
).max(20).nullable().optional().describe(
|
|
1082
|
+
"Named fields picked out of every email: shown with it, `fields` in its JSON, read by forwarding templates and filters (email_field). Replaces the list; null or [] removes them. Owner only."
|
|
1083
|
+
)
|
|
1018
1084
|
},
|
|
1019
1085
|
withErrorHandling(
|
|
1020
1086
|
async ({
|
|
@@ -1026,7 +1092,8 @@ function registerTools(server, client) {
|
|
|
1026
1092
|
signingProvider,
|
|
1027
1093
|
signingSecret,
|
|
1028
1094
|
signingHeader,
|
|
1029
|
-
showEmailExtracts
|
|
1095
|
+
showEmailExtracts,
|
|
1096
|
+
emailFields
|
|
1030
1097
|
}) => {
|
|
1031
1098
|
const endpoint = await client.endpoints.update(slug, {
|
|
1032
1099
|
name,
|
|
@@ -1036,12 +1103,33 @@ function registerTools(server, client) {
|
|
|
1036
1103
|
signingProvider,
|
|
1037
1104
|
signingSecret,
|
|
1038
1105
|
signingHeader,
|
|
1039
|
-
showEmailExtracts
|
|
1106
|
+
showEmailExtracts,
|
|
1107
|
+
emailFields
|
|
1040
1108
|
});
|
|
1041
1109
|
return jsonContent(endpoint);
|
|
1042
1110
|
}
|
|
1043
1111
|
)
|
|
1044
1112
|
);
|
|
1113
|
+
server.tool(
|
|
1114
|
+
"preview_response",
|
|
1115
|
+
"Dry run of an endpoint's responses: which response rule answers a captured request, and the response with its {{ placeholders }} filled in, exactly as the receiver would send it. Nothing is sent. Pass mockResponse or responseRules to try settings before saving them with update_endpoint.",
|
|
1116
|
+
{
|
|
1117
|
+
slug: import_zod2.z.string().describe("The endpoint slug"),
|
|
1118
|
+
requestId: import_zod2.z.string().optional().describe(
|
|
1119
|
+
"A captured request on the endpoint (default: the newest HTTP request, or a sample)"
|
|
1120
|
+
),
|
|
1121
|
+
mockResponse: mockResponseSchema.nullable().optional().describe("Try this default response instead of the saved one (null: none)"),
|
|
1122
|
+
responseRules: responseRulesSchema.nullable().optional().describe("Try these rules instead of the saved ones (null: none)")
|
|
1123
|
+
},
|
|
1124
|
+
withErrorHandling(async ({ slug, requestId, mockResponse, responseRules }) => {
|
|
1125
|
+
const preview = await client.endpoints.previewResponse(slug, {
|
|
1126
|
+
...requestId ? { requestId } : {},
|
|
1127
|
+
...mockResponse !== void 0 ? { mockResponse } : {},
|
|
1128
|
+
...responseRules !== void 0 ? { responseRules } : {}
|
|
1129
|
+
});
|
|
1130
|
+
return jsonContent(preview);
|
|
1131
|
+
})
|
|
1132
|
+
);
|
|
1045
1133
|
server.tool(
|
|
1046
1134
|
"delete_endpoint",
|
|
1047
1135
|
"Delete a webhook endpoint and all its captured requests.",
|
|
@@ -1257,6 +1345,39 @@ function registerTools(server, client) {
|
|
|
1257
1345
|
});
|
|
1258
1346
|
})
|
|
1259
1347
|
);
|
|
1348
|
+
server.tool(
|
|
1349
|
+
"render_email",
|
|
1350
|
+
"A captured email in the shape an inbound mail provider posts it (postmark, sendgrid, mailgun, cloudmailin), to test the inbound handler you wrote for that provider against real mail. Returns the method, headers and body; with targetUrl (your local handler), posts it there and returns the answer. A Mailgun form is signed when you pass the signing key your handler checks.",
|
|
1351
|
+
{
|
|
1352
|
+
requestId: import_zod2.z.string().describe("The captured email's request ID"),
|
|
1353
|
+
format: import_zod2.z.enum(["postmark", "sendgrid", "mailgun", "cloudmailin", "json"]).describe("Whose shape; json is webhooks.cc's own email.received JSON (unsigned)"),
|
|
1354
|
+
mailgunSigningKey: import_zod2.z.string().optional().describe("For mailgun: the signing key your handler verifies with (a test key)"),
|
|
1355
|
+
targetUrl: httpUrlSchema.optional().describe("Post it here, e.g. http://localhost:3000/api/inbound/postmark")
|
|
1356
|
+
},
|
|
1357
|
+
withErrorHandling(async ({ requestId, format, mailgunSigningKey, targetUrl }) => {
|
|
1358
|
+
const rendered = await client.emails.render(requestId, {
|
|
1359
|
+
format,
|
|
1360
|
+
...mailgunSigningKey ? { mailgunSigningKey } : {}
|
|
1361
|
+
});
|
|
1362
|
+
if (!targetUrl) {
|
|
1363
|
+
return jsonContent(
|
|
1364
|
+
shrinkRendered(rendered, MAX_BODY_SIZE)
|
|
1365
|
+
);
|
|
1366
|
+
}
|
|
1367
|
+
const response = await fetch(targetUrl, {
|
|
1368
|
+
method: "POST",
|
|
1369
|
+
headers: { "content-type": rendered.headers["content-type"] },
|
|
1370
|
+
body: rendered.body,
|
|
1371
|
+
redirect: "manual"
|
|
1372
|
+
});
|
|
1373
|
+
return jsonContent({
|
|
1374
|
+
format,
|
|
1375
|
+
status: response.status,
|
|
1376
|
+
statusText: response.statusText,
|
|
1377
|
+
body: await readBodyTruncated(response)
|
|
1378
|
+
});
|
|
1379
|
+
})
|
|
1380
|
+
);
|
|
1260
1381
|
server.tool(
|
|
1261
1382
|
"compare_requests",
|
|
1262
1383
|
"Compare two captured requests and show the structured differences.",
|
|
@@ -1640,9 +1761,79 @@ function registerTools(server, client) {
|
|
|
1640
1761
|
return jsonContent({ ...result, address: client.emails.address(slug, tag) });
|
|
1641
1762
|
})
|
|
1642
1763
|
);
|
|
1764
|
+
server.tool(
|
|
1765
|
+
"list_destinations",
|
|
1766
|
+
"List where an endpoint's captures go: its destinations (up to 10) with their URL, kinds, filter, format, templates and timing, and with summary: true their last 24 hours. Owner only.",
|
|
1767
|
+
{
|
|
1768
|
+
slug: import_zod2.z.string().describe("The endpoint slug"),
|
|
1769
|
+
summary: import_zod2.z.boolean().default(true).describe("Add each destination's last 24 hours")
|
|
1770
|
+
},
|
|
1771
|
+
withErrorHandling(async ({ slug, summary }) => {
|
|
1772
|
+
return jsonContent(await client.destinations.list(slug, { summary }));
|
|
1773
|
+
})
|
|
1774
|
+
);
|
|
1775
|
+
server.tool(
|
|
1776
|
+
"add_destination",
|
|
1777
|
+
"Add a destination for an endpoint's captures: your server (as received or signed JSON), a Slack or Discord channel (chat, optionally your own messageTemplate, throttleSeconds 1 for a heads-up), or a JSON body you shape with bodyTemplate (for Zapier, n8n or your API). filter sends only matching captures; delaySeconds makes it a callback. Each destination gets its own signing secret. Check it with preview_destination before relying on it. Owner only.",
|
|
1778
|
+
{
|
|
1779
|
+
slug: import_zod2.z.string().describe("The endpoint slug"),
|
|
1780
|
+
url: httpUrlSchema.describe("https URL on a public host name, or a Slack or Discord webhook"),
|
|
1781
|
+
...destinationFields
|
|
1782
|
+
},
|
|
1783
|
+
withErrorHandling(async ({ slug, ...input }) => {
|
|
1784
|
+
return jsonContent(await client.destinations.create(slug, input));
|
|
1785
|
+
})
|
|
1786
|
+
);
|
|
1787
|
+
server.tool(
|
|
1788
|
+
"update_destination",
|
|
1789
|
+
"Change a destination: any of its fields; only the ones you pass change. Owner only.",
|
|
1790
|
+
{
|
|
1791
|
+
slug: import_zod2.z.string().describe("The endpoint slug"),
|
|
1792
|
+
destinationId: import_zod2.z.string().describe("The destination's id (from list_destinations)"),
|
|
1793
|
+
url: httpUrlSchema.optional().describe("A new URL"),
|
|
1794
|
+
...destinationFields
|
|
1795
|
+
},
|
|
1796
|
+
withErrorHandling(async ({ slug, destinationId, ...input }) => {
|
|
1797
|
+
return jsonContent(await client.destinations.update(slug, destinationId, input));
|
|
1798
|
+
})
|
|
1799
|
+
);
|
|
1800
|
+
server.tool(
|
|
1801
|
+
"remove_destination",
|
|
1802
|
+
"Remove a destination. Deliveries still waiting for it are marked failed; its log stays. Owner only.",
|
|
1803
|
+
{
|
|
1804
|
+
slug: import_zod2.z.string().describe("The endpoint slug"),
|
|
1805
|
+
destinationId: import_zod2.z.string().describe("The destination's id")
|
|
1806
|
+
},
|
|
1807
|
+
withErrorHandling(async ({ slug, destinationId }) => {
|
|
1808
|
+
await client.destinations.delete(slug, destinationId);
|
|
1809
|
+
return textContent(`Destination ${destinationId} removed.`);
|
|
1810
|
+
})
|
|
1811
|
+
);
|
|
1812
|
+
server.tool(
|
|
1813
|
+
"preview_destination",
|
|
1814
|
+
"Dry run of a destination against a captured request: whether its filter lets the request through and the exact request it would send (method, URL, headers, body with placeholders filled in). Nothing is sent. Use destinationId for a saved destination, destination for unsaved fields (on top of the saved ones, or with a url on their own), or both.",
|
|
1815
|
+
{
|
|
1816
|
+
slug: import_zod2.z.string().describe("The endpoint slug"),
|
|
1817
|
+
destinationId: import_zod2.z.string().optional().describe("A saved destination"),
|
|
1818
|
+
destination: import_zod2.z.object({ url: httpUrlSchema.optional(), ...destinationFields }).optional().describe("Unsaved fields to try"),
|
|
1819
|
+
requestId: import_zod2.z.string().optional().describe("A captured request (default: the newest of the kind it takes, or a sample)")
|
|
1820
|
+
},
|
|
1821
|
+
withErrorHandling(async ({ slug, destinationId, destination, requestId }) => {
|
|
1822
|
+
if (!destinationId && !destination?.url) {
|
|
1823
|
+
throw new Error("Pass destinationId, or a destination with a url");
|
|
1824
|
+
}
|
|
1825
|
+
return jsonContent(
|
|
1826
|
+
await client.destinations.preview(slug, {
|
|
1827
|
+
...destinationId ? { destinationId } : {},
|
|
1828
|
+
...destination ? { destination } : {},
|
|
1829
|
+
...requestId ? { requestId } : {}
|
|
1830
|
+
})
|
|
1831
|
+
);
|
|
1832
|
+
})
|
|
1833
|
+
);
|
|
1643
1834
|
server.tool(
|
|
1644
1835
|
"configure_forwarding",
|
|
1645
|
-
"Change an endpoint's forwarding: the URL, on or off, which kinds
|
|
1836
|
+
"Change an endpoint's primary forwarding destination (the one the endpoint's forward* fields stand for): the URL, on or off, which kinds, the format, your own headers, and the advanced options. Only the arguments you pass change. Owner only. For several destinations, filters, templates, throttling or delays, use add_destination and update_destination.",
|
|
1646
1837
|
{
|
|
1647
1838
|
slug: import_zod2.z.string().describe("The endpoint slug"),
|
|
1648
1839
|
url: httpUrlSchema.nullable().optional().describe("https URL on a public host name, or null to remove it (forwarding must be off)"),
|
|
@@ -1690,23 +1881,32 @@ function registerTools(server, client) {
|
|
|
1690
1881
|
"Read (or with rotate: true, replace) the whsec_ secret forwarded deliveries are signed with. Owner only. Treat the value as a credential: put it in the handler's environment, not in code.",
|
|
1691
1882
|
{
|
|
1692
1883
|
slug: import_zod2.z.string().describe("The endpoint slug"),
|
|
1884
|
+
destinationId: import_zod2.z.string().optional().describe("A destination (default: the endpoint's primary destination)"),
|
|
1693
1885
|
rotate: import_zod2.z.boolean().default(false).describe("Replace the secret; every delivery from now on uses the new one")
|
|
1694
1886
|
},
|
|
1695
|
-
withErrorHandling(async ({ slug, rotate }) => {
|
|
1696
|
-
const secret = rotate ? await client.forwarding.rotateSecret(slug) : await client.forwarding.secret(slug);
|
|
1887
|
+
withErrorHandling(async ({ slug, destinationId, rotate }) => {
|
|
1888
|
+
const secret = destinationId ? rotate ? await client.destinations.rotateSecret(slug, destinationId) : await client.destinations.secret(slug, destinationId) : rotate ? await client.forwarding.rotateSecret(slug) : await client.forwarding.secret(slug);
|
|
1697
1889
|
return jsonContent({ secret, rotated: rotate });
|
|
1698
1890
|
})
|
|
1699
1891
|
);
|
|
1700
1892
|
server.tool(
|
|
1701
1893
|
"test_forwarding",
|
|
1702
|
-
"Send the endpoint's newest captured request of a kind (or a sample) to
|
|
1894
|
+
"Send the endpoint's newest captured request of a kind (or a sample, or requestId) to a destination once, exactly as a delivery would go out, and report the answer. Works whether it is on or off, and whatever its filter says; nothing is retried or logged.",
|
|
1703
1895
|
{
|
|
1704
1896
|
slug: import_zod2.z.string().describe("The endpoint slug"),
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
)
|
|
1897
|
+
destinationId: import_zod2.z.string().optional().describe("A destination (default: the endpoint's primary destination)"),
|
|
1898
|
+
kind: import_zod2.z.enum(["http", "email"]).optional().describe("Which kind to send (default: http when the destination takes HTTP requests)"),
|
|
1899
|
+
requestId: import_zod2.z.string().optional().describe("With destinationId: a captured request to send")
|
|
1708
1900
|
},
|
|
1709
|
-
withErrorHandling(async ({ slug, kind }) => {
|
|
1901
|
+
withErrorHandling(async ({ slug, destinationId, kind, requestId }) => {
|
|
1902
|
+
if (destinationId) {
|
|
1903
|
+
return jsonContent(
|
|
1904
|
+
await client.destinations.test(slug, destinationId, {
|
|
1905
|
+
...kind ? { kind } : {},
|
|
1906
|
+
...requestId ? { requestId } : {}
|
|
1907
|
+
})
|
|
1908
|
+
);
|
|
1909
|
+
}
|
|
1710
1910
|
return jsonContent(await client.forwarding.test(slug, kind ? { kind } : {}));
|
|
1711
1911
|
})
|
|
1712
1912
|
);
|
|
@@ -1717,17 +1917,25 @@ function registerTools(server, client) {
|
|
|
1717
1917
|
endpointSlug: import_zod2.z.string().optional().describe("List the endpoint's delivery log"),
|
|
1718
1918
|
requestId: import_zod2.z.string().optional().describe("List every delivery and try of this request"),
|
|
1719
1919
|
limit: import_zod2.z.number().int().min(1).max(100).default(20).describe("With endpointSlug: max rows"),
|
|
1720
|
-
status: import_zod2.z.enum(["all", "pending", "failed"]).default("all").describe(
|
|
1920
|
+
status: import_zod2.z.enum(["all", "pending", "failed", "skipped"]).default("all").describe(
|
|
1921
|
+
"With endpointSlug: all, pending (queued or retrying), failed or skipped (filtered out)"
|
|
1922
|
+
),
|
|
1923
|
+
destinationId: import_zod2.z.string().optional().describe("With endpointSlug: only this destination"),
|
|
1721
1924
|
before: import_zod2.z.string().optional().describe("With endpointSlug: a row's cursor, to list older rows")
|
|
1722
1925
|
},
|
|
1723
|
-
withErrorHandling(async ({ endpointSlug, requestId, limit, status, before }) => {
|
|
1926
|
+
withErrorHandling(async ({ endpointSlug, requestId, limit, status, destinationId, before }) => {
|
|
1724
1927
|
if (requestId === void 0 === (endpointSlug === void 0)) {
|
|
1725
1928
|
throw new Error("Pass exactly one of endpointSlug or requestId");
|
|
1726
1929
|
}
|
|
1727
1930
|
if (requestId) return jsonContent(await client.forwarding.requestDeliveries(requestId));
|
|
1728
1931
|
const [summary, deliveries] = await Promise.all([
|
|
1729
1932
|
client.forwarding.summary(endpointSlug),
|
|
1730
|
-
client.forwarding.deliveries(endpointSlug, {
|
|
1933
|
+
client.forwarding.deliveries(endpointSlug, {
|
|
1934
|
+
limit,
|
|
1935
|
+
status,
|
|
1936
|
+
before,
|
|
1937
|
+
...destinationId ? { destinationId } : {}
|
|
1938
|
+
})
|
|
1731
1939
|
]);
|
|
1732
1940
|
return jsonContent({
|
|
1733
1941
|
summary,
|
|
@@ -1738,17 +1946,19 @@ function registerTools(server, client) {
|
|
|
1738
1946
|
);
|
|
1739
1947
|
server.tool(
|
|
1740
1948
|
"redeliver",
|
|
1741
|
-
"Forward again with the
|
|
1949
|
+
"Forward again with the current settings: one captured request or email (requestId; to every destination that takes it, or with destinationId to that one whatever its filter says), or every request whose latest delivery failed (endpointSlug, optionally only destinationId, oldest first, up to 1,000 at a time per destination). Owner only.",
|
|
1742
1950
|
{
|
|
1743
1951
|
requestId: import_zod2.z.string().optional().describe("The request or email to send again"),
|
|
1744
|
-
endpointSlug: import_zod2.z.string().optional().describe("Send every failed delivery of this endpoint again")
|
|
1952
|
+
endpointSlug: import_zod2.z.string().optional().describe("Send every failed delivery of this endpoint again"),
|
|
1953
|
+
destinationId: import_zod2.z.string().optional().describe("Only this destination")
|
|
1745
1954
|
},
|
|
1746
|
-
withErrorHandling(async ({ requestId, endpointSlug }) => {
|
|
1955
|
+
withErrorHandling(async ({ requestId, endpointSlug, destinationId }) => {
|
|
1747
1956
|
if (requestId === void 0 === (endpointSlug === void 0)) {
|
|
1748
1957
|
throw new Error("Pass exactly one of requestId or endpointSlug");
|
|
1749
1958
|
}
|
|
1959
|
+
const options = destinationId ? { destinationId } : {};
|
|
1750
1960
|
return jsonContent(
|
|
1751
|
-
requestId ? await client.forwarding.redeliver(requestId) : await client.forwarding.redeliverFailed(endpointSlug)
|
|
1961
|
+
requestId ? await client.forwarding.redeliver(requestId, options) : await client.forwarding.redeliverFailed(endpointSlug, options)
|
|
1752
1962
|
);
|
|
1753
1963
|
})
|
|
1754
1964
|
);
|
|
@@ -2143,7 +2353,7 @@ function registerAgentRegistrationTools(server) {
|
|
|
2143
2353
|
}
|
|
2144
2354
|
|
|
2145
2355
|
// src/index.ts
|
|
2146
|
-
var VERSION = true ? "1.
|
|
2356
|
+
var VERSION = true ? "1.14.0" : "0.0.0-dev";
|
|
2147
2357
|
function createServer(options = {}) {
|
|
2148
2358
|
const apiKey = options.apiKey ?? process.env.WHK_API_KEY;
|
|
2149
2359
|
const webhookUrl = options.webhookUrl ?? process.env.WHK_WEBHOOK_URL;
|