@webhooks-cc/mcp 1.5.0 → 1.7.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 +5 -1
- package/dist/bin/mcp.js +128 -14
- package/dist/index.d.mts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +130 -14
- package/dist/index.mjs +133 -16
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -149,10 +149,14 @@ Provider template and signing support includes:
|
|
|
149
149
|
- `mux`
|
|
150
150
|
- `sentry`
|
|
151
151
|
- `bitbucket`
|
|
152
|
+
- `docusign`
|
|
153
|
+
- `adyen`
|
|
154
|
+
- `paypal`
|
|
155
|
+
- `plaid`
|
|
152
156
|
|
|
153
157
|
Signature verification also supports:
|
|
154
158
|
|
|
155
|
-
- all template providers except `sendgrid
|
|
159
|
+
- all template providers except `sendgrid` (IP allowlisting) and `plaid` (JWT/JWK verification requires Plaid API credentials)
|
|
156
160
|
|
|
157
161
|
Use `list_provider_templates` to inspect templates, default events, signature headers, and signing requirements from the agent.
|
|
158
162
|
|
package/dist/bin/mcp.js
CHANGED
|
@@ -687,15 +687,17 @@ function registerTools(server, client) {
|
|
|
687
687
|
provider: import_zod2.z.enum(import_sdk.TEMPLATE_PROVIDERS).optional().describe("Optional provider template to send with signed headers"),
|
|
688
688
|
template: import_zod2.z.string().optional().describe("Provider-specific template preset"),
|
|
689
689
|
event: import_zod2.z.string().optional().describe("Provider event or topic name"),
|
|
690
|
-
secret: import_zod2.z.string().optional().describe(
|
|
690
|
+
secret: import_zod2.z.string().optional().describe(
|
|
691
|
+
"Signing secret. Required for signed provider templates; omit for secretless providers (sendgrid, discord, plaid)."
|
|
692
|
+
)
|
|
691
693
|
},
|
|
692
694
|
withErrorHandling(
|
|
693
695
|
async ({ slug, method, headers, body, provider, template, event, secret }) => {
|
|
694
696
|
let response;
|
|
695
697
|
if (provider) {
|
|
696
698
|
const templateSecret = secret?.trim();
|
|
697
|
-
if (!templateSecret) {
|
|
698
|
-
throw new Error(
|
|
699
|
+
if (!templateSecret && import_sdk.TEMPLATE_METADATA[provider]?.secretRequired !== false) {
|
|
700
|
+
throw new Error(`send_webhook with provider "${provider}" requires a non-empty secret`);
|
|
699
701
|
}
|
|
700
702
|
response = await client.endpoints.sendTemplate(slug, {
|
|
701
703
|
provider,
|
|
@@ -871,7 +873,7 @@ function registerTools(server, client) {
|
|
|
871
873
|
requestId: import_zod2.z.string().describe("The captured request ID"),
|
|
872
874
|
provider: import_zod2.z.enum(import_sdk.VERIFY_PROVIDERS).optional().describe("Provider whose signature scheme should be verified. Omit to use stored result."),
|
|
873
875
|
secret: import_zod2.z.string().optional().describe(
|
|
874
|
-
"
|
|
876
|
+
"Provider credential for client-side verification (for example a shared signing secret, Adyen hex HMAC key, or PayPal webhook ID). Required for non-Discord providers."
|
|
875
877
|
),
|
|
876
878
|
publicKey: import_zod2.z.string().optional().describe("Discord application public key. Required for provider=discord."),
|
|
877
879
|
url: httpUrlSchema.optional().describe("Original signed URL. Required for Twilio, Square, and HubSpot verification."),
|
|
@@ -943,7 +945,9 @@ function registerTools(server, client) {
|
|
|
943
945
|
provider: import_zod2.z.enum(import_sdk.TEMPLATE_PROVIDERS).optional().describe("Optional provider template for signing"),
|
|
944
946
|
template: import_zod2.z.string().optional().describe("Provider-specific template preset"),
|
|
945
947
|
event: import_zod2.z.string().optional().describe("Provider event or topic name"),
|
|
946
|
-
secret: import_zod2.z.string().optional().describe(
|
|
948
|
+
secret: import_zod2.z.string().optional().describe(
|
|
949
|
+
"Signing secret. Required for signed provider templates; omit for secretless providers (sendgrid, discord, plaid)."
|
|
950
|
+
)
|
|
947
951
|
},
|
|
948
952
|
withErrorHandling(async ({ url, method, headers, body, provider, template, event, secret }) => {
|
|
949
953
|
const response = await client.sendTo(url, {
|
|
@@ -974,7 +978,9 @@ function registerTools(server, client) {
|
|
|
974
978
|
provider: import_zod2.z.enum(import_sdk.TEMPLATE_PROVIDERS).optional().describe("Optional provider template for signing"),
|
|
975
979
|
template: import_zod2.z.string().optional().describe("Provider-specific template preset"),
|
|
976
980
|
event: import_zod2.z.string().optional().describe("Provider event or topic name"),
|
|
977
|
-
secret: import_zod2.z.string().optional().describe(
|
|
981
|
+
secret: import_zod2.z.string().optional().describe(
|
|
982
|
+
"Signing secret. Required for signed provider templates; omit for secretless providers (sendgrid, discord, plaid)."
|
|
983
|
+
)
|
|
978
984
|
},
|
|
979
985
|
withErrorHandling(async ({ url, method, headers, body, provider, template, event, secret }) => {
|
|
980
986
|
const preview = await client.buildRequest(url, {
|
|
@@ -1050,9 +1056,9 @@ function registerTools(server, client) {
|
|
|
1050
1056
|
}
|
|
1051
1057
|
if (provider) {
|
|
1052
1058
|
const templateSecret = secret?.trim();
|
|
1053
|
-
if (!templateSecret) {
|
|
1059
|
+
if (!templateSecret && import_sdk.TEMPLATE_METADATA[provider]?.secretRequired !== false) {
|
|
1054
1060
|
throw new Error(
|
|
1055
|
-
|
|
1061
|
+
`test_webhook_flow with provider "${provider}" requires a non-empty secret`
|
|
1056
1062
|
);
|
|
1057
1063
|
}
|
|
1058
1064
|
flow.sendTemplate({
|
|
@@ -1066,6 +1072,11 @@ function registerTools(server, client) {
|
|
|
1066
1072
|
"test_webhook_flow cannot verify Discord signatures (Ed25519 requires a public key, not a secret)"
|
|
1067
1073
|
);
|
|
1068
1074
|
}
|
|
1075
|
+
if (!templateSecret) {
|
|
1076
|
+
throw new Error(
|
|
1077
|
+
`test_webhook_flow cannot verify "${provider}" signatures \u2014 this provider's templates are unsigned`
|
|
1078
|
+
);
|
|
1079
|
+
}
|
|
1069
1080
|
flow.verifySignature({
|
|
1070
1081
|
provider,
|
|
1071
1082
|
secret: templateSecret
|
|
@@ -1103,24 +1114,127 @@ function registerTools(server, client) {
|
|
|
1103
1114
|
return jsonContent(description);
|
|
1104
1115
|
})
|
|
1105
1116
|
);
|
|
1117
|
+
registerAgentRegistrationTools(server);
|
|
1118
|
+
}
|
|
1119
|
+
function resolveBaseUrl() {
|
|
1120
|
+
return process.env.WHK_BASE_URL ?? "https://webhooks.cc";
|
|
1121
|
+
}
|
|
1122
|
+
function registerAgentRegistrationTools(server) {
|
|
1123
|
+
const baseUrl = resolveBaseUrl();
|
|
1124
|
+
server.tool(
|
|
1125
|
+
"how_to_register",
|
|
1126
|
+
"Explain how an agent self-registers for a webhooks.cc API credential (auth.md). Call this FIRST when you have no API key. Returns the three registration flows and the auth.md documentation URL. No authentication required.",
|
|
1127
|
+
{},
|
|
1128
|
+
withErrorHandling(async () => {
|
|
1129
|
+
return jsonContent({
|
|
1130
|
+
...import_sdk.WebhooksCC.describeRegistration(baseUrl),
|
|
1131
|
+
next_steps: [
|
|
1132
|
+
"Easiest: call register_agent (anonymous) to get a key immediately, then have a human run claim_agent with the returned userCode while logged in to webhooks.cc.",
|
|
1133
|
+
"Or set WHK_API_KEY to an existing whcc_ key and use the authenticated tools."
|
|
1134
|
+
]
|
|
1135
|
+
});
|
|
1136
|
+
})
|
|
1137
|
+
);
|
|
1138
|
+
server.tool(
|
|
1139
|
+
"register_agent",
|
|
1140
|
+
"Self-register for a webhooks.cc API credential via the anonymous auth.md flow. Returns a whcc_ API key that works immediately in a bounded sandbox, plus a short userCode and claimUrl a human uses to bind the key to their account. No authentication required. After registering, set WHK_API_KEY to the returned credential.",
|
|
1141
|
+
{
|
|
1142
|
+
clientName: import_zod2.z.string().optional().describe("A human-readable name for this agent, recorded on the issued key")
|
|
1143
|
+
},
|
|
1144
|
+
withErrorHandling(async ({ clientName }) => {
|
|
1145
|
+
const reg = await import_sdk.WebhooksCC.register.anonymous({ baseUrl, clientName });
|
|
1146
|
+
return jsonContent({
|
|
1147
|
+
credential: reg.credential,
|
|
1148
|
+
scopes: reg.scopes,
|
|
1149
|
+
claim: {
|
|
1150
|
+
userCode: reg.userCode,
|
|
1151
|
+
claimUrl: reg.claimUrl,
|
|
1152
|
+
claimToken: reg.claimToken,
|
|
1153
|
+
expiresAt: reg.claimTokenExpires,
|
|
1154
|
+
instructions: `Ask a human to open ${reg.claimUrl} while logged in to webhooks.cc and either enter the code ${reg.userCode} or open ${reg.claimUrl}?token=${reg.claimToken}. Then call check_claim with the claimToken.`
|
|
1155
|
+
},
|
|
1156
|
+
usage: "Set WHK_API_KEY to `credential` to use the authenticated tools. Before it is claimed the key can create ephemeral endpoints and read its own captured requests in the sandbox."
|
|
1157
|
+
});
|
|
1158
|
+
})
|
|
1159
|
+
);
|
|
1160
|
+
server.tool(
|
|
1161
|
+
"check_claim",
|
|
1162
|
+
"Check whether an anonymous registration's API key has been claimed by a human yet. Poll this after register_agent until status is 'claimed'. No authentication required.",
|
|
1163
|
+
{
|
|
1164
|
+
claimToken: import_zod2.z.string().describe("The claimToken returned by register_agent")
|
|
1165
|
+
},
|
|
1166
|
+
withErrorHandling(async ({ claimToken }) => {
|
|
1167
|
+
const poll = await import_sdk.WebhooksCC.register.pollClaim(claimToken, { baseUrl });
|
|
1168
|
+
return jsonContent(poll);
|
|
1169
|
+
})
|
|
1170
|
+
);
|
|
1171
|
+
server.tool(
|
|
1172
|
+
"register_agent_with_email",
|
|
1173
|
+
"Self-register via the verified_email auth.md flow: webhooks.cc emails a one-time code to the address. The credential is WITHHELD until the code is confirmed with verify_agent_otp. Returns a claimToken to pass to verify_agent_otp. No authentication required.",
|
|
1174
|
+
{
|
|
1175
|
+
email: import_zod2.z.string().email({ message: "Invalid email address" }).describe("The email address to verify and bind the credential to"),
|
|
1176
|
+
clientName: import_zod2.z.string().optional().describe("A human-readable name for this agent, recorded on the issued key")
|
|
1177
|
+
},
|
|
1178
|
+
withErrorHandling(async ({ email, clientName }) => {
|
|
1179
|
+
const challenge = await import_sdk.WebhooksCC.register.withEmail(email, { baseUrl, clientName });
|
|
1180
|
+
return jsonContent({
|
|
1181
|
+
claimToken: challenge.claimToken,
|
|
1182
|
+
expiresAt: challenge.claimTokenExpires,
|
|
1183
|
+
postClaimScopes: challenge.postClaimScopes,
|
|
1184
|
+
next_step: `A one-time code was emailed to ${email}. Ask the human for it, then call verify_agent_otp with this claimToken and the code.`
|
|
1185
|
+
});
|
|
1186
|
+
})
|
|
1187
|
+
);
|
|
1188
|
+
server.tool(
|
|
1189
|
+
"verify_agent_otp",
|
|
1190
|
+
"Complete the verified_email flow: submit the emailed OTP with the claimToken from register_agent_with_email. On success returns the whcc_ API key (bound to the verified email). Set WHK_API_KEY to it. No authentication required.",
|
|
1191
|
+
{
|
|
1192
|
+
claimToken: import_zod2.z.string().describe("The claimToken returned by register_agent_with_email"),
|
|
1193
|
+
otp: import_zod2.z.string().describe("The one-time code the human received by email")
|
|
1194
|
+
},
|
|
1195
|
+
withErrorHandling(async ({ claimToken, otp }) => {
|
|
1196
|
+
const issued = await import_sdk.WebhooksCC.register.confirmEmailOtp({ claimToken, otp }, { baseUrl });
|
|
1197
|
+
return jsonContent({
|
|
1198
|
+
credential: issued.credential,
|
|
1199
|
+
scopes: issued.scopes,
|
|
1200
|
+
usage: "Set WHK_API_KEY to `credential` to use the authenticated tools."
|
|
1201
|
+
});
|
|
1202
|
+
})
|
|
1203
|
+
);
|
|
1204
|
+
server.tool(
|
|
1205
|
+
"register_agent_with_idjag",
|
|
1206
|
+
"Self-register via the identity_assertion (ID-JAG) auth.md flow: present a verified identity-assertion JWT (urn:ietf:params:oauth:token-type:id-jag) from a trusted provider. The credential is returned synchronously \u2014 no human claim step. No webhooks.cc authentication required, but only works if webhooks.cc trusts your provider.",
|
|
1207
|
+
{
|
|
1208
|
+
assertion: import_zod2.z.string().describe("The ID-JAG assertion JWT (typ oauth-id-jag+jwt) from a trusted provider")
|
|
1209
|
+
},
|
|
1210
|
+
withErrorHandling(async ({ assertion }) => {
|
|
1211
|
+
const issued = await import_sdk.WebhooksCC.register.withIdJag(assertion, { baseUrl });
|
|
1212
|
+
return jsonContent({
|
|
1213
|
+
credential: issued.credential,
|
|
1214
|
+
scopes: issued.scopes,
|
|
1215
|
+
usage: "Set WHK_API_KEY to `credential` to use the authenticated tools."
|
|
1216
|
+
});
|
|
1217
|
+
})
|
|
1218
|
+
);
|
|
1106
1219
|
}
|
|
1107
1220
|
|
|
1108
1221
|
// src/index.ts
|
|
1109
|
-
var VERSION = true ? "1.
|
|
1222
|
+
var VERSION = true ? "1.7.0" : "0.0.0-dev";
|
|
1110
1223
|
function createServer(options = {}) {
|
|
1111
1224
|
const apiKey = options.apiKey ?? process.env.WHK_API_KEY;
|
|
1225
|
+
const server = new import_mcp2.McpServer({
|
|
1226
|
+
name: "webhooks-cc",
|
|
1227
|
+
version: VERSION
|
|
1228
|
+
});
|
|
1112
1229
|
if (!apiKey) {
|
|
1113
|
-
|
|
1230
|
+
registerAgentRegistrationTools(server);
|
|
1231
|
+
return server;
|
|
1114
1232
|
}
|
|
1115
1233
|
const client = new import_sdk2.WebhooksCC({
|
|
1116
1234
|
apiKey,
|
|
1117
1235
|
webhookUrl: options.webhookUrl ?? process.env.WHK_WEBHOOK_URL,
|
|
1118
1236
|
baseUrl: options.baseUrl ?? process.env.WHK_BASE_URL
|
|
1119
1237
|
});
|
|
1120
|
-
const server = new import_mcp2.McpServer({
|
|
1121
|
-
name: "webhooks-cc",
|
|
1122
|
-
version: VERSION
|
|
1123
|
-
});
|
|
1124
1238
|
registerTools(server, client);
|
|
1125
1239
|
registerPrompts(server);
|
|
1126
1240
|
registerResources(server, client);
|
package/dist/index.d.mts
CHANGED
|
@@ -3,6 +3,14 @@ import { WebhooksCC } from '@webhooks-cc/sdk';
|
|
|
3
3
|
|
|
4
4
|
/** Register all webhook tools on an MCP server instance. */
|
|
5
5
|
declare function registerTools(server: McpServer, client: WebhooksCC): void;
|
|
6
|
+
/**
|
|
7
|
+
* Agent self-registration tools (auth.md). These are UNAUTHENTICATED — they let
|
|
8
|
+
* an agent that does NOT yet have a webhooks.cc credential obtain one, then
|
|
9
|
+
* configure the MCP server with the returned key (WHK_API_KEY). Registered on
|
|
10
|
+
* every server so a probing agent can always discover the on-ramp via
|
|
11
|
+
* `describe` / `how_to_register`.
|
|
12
|
+
*/
|
|
13
|
+
declare function registerAgentRegistrationTools(server: McpServer): void;
|
|
6
14
|
|
|
7
15
|
declare function registerPrompts(server: McpServer): void;
|
|
8
16
|
|
|
@@ -30,4 +38,4 @@ interface CreateServerOptions {
|
|
|
30
38
|
*/
|
|
31
39
|
declare function createServer(options?: CreateServerOptions): McpServer;
|
|
32
40
|
|
|
33
|
-
export { type CreateServerOptions, createServer, registerPrompts, registerResources, registerTools };
|
|
41
|
+
export { type CreateServerOptions, createServer, registerAgentRegistrationTools, registerPrompts, registerResources, registerTools };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,14 @@ import { WebhooksCC } from '@webhooks-cc/sdk';
|
|
|
3
3
|
|
|
4
4
|
/** Register all webhook tools on an MCP server instance. */
|
|
5
5
|
declare function registerTools(server: McpServer, client: WebhooksCC): void;
|
|
6
|
+
/**
|
|
7
|
+
* Agent self-registration tools (auth.md). These are UNAUTHENTICATED — they let
|
|
8
|
+
* an agent that does NOT yet have a webhooks.cc credential obtain one, then
|
|
9
|
+
* configure the MCP server with the returned key (WHK_API_KEY). Registered on
|
|
10
|
+
* every server so a probing agent can always discover the on-ramp via
|
|
11
|
+
* `describe` / `how_to_register`.
|
|
12
|
+
*/
|
|
13
|
+
declare function registerAgentRegistrationTools(server: McpServer): void;
|
|
6
14
|
|
|
7
15
|
declare function registerPrompts(server: McpServer): void;
|
|
8
16
|
|
|
@@ -30,4 +38,4 @@ interface CreateServerOptions {
|
|
|
30
38
|
*/
|
|
31
39
|
declare function createServer(options?: CreateServerOptions): McpServer;
|
|
32
40
|
|
|
33
|
-
export { type CreateServerOptions, createServer, registerPrompts, registerResources, registerTools };
|
|
41
|
+
export { type CreateServerOptions, createServer, registerAgentRegistrationTools, registerPrompts, registerResources, registerTools };
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
createServer: () => createServer,
|
|
24
|
+
registerAgentRegistrationTools: () => registerAgentRegistrationTools,
|
|
24
25
|
registerPrompts: () => registerPrompts,
|
|
25
26
|
registerResources: () => registerResources,
|
|
26
27
|
registerTools: () => registerTools
|
|
@@ -708,15 +709,17 @@ function registerTools(server, client) {
|
|
|
708
709
|
provider: import_zod2.z.enum(import_sdk.TEMPLATE_PROVIDERS).optional().describe("Optional provider template to send with signed headers"),
|
|
709
710
|
template: import_zod2.z.string().optional().describe("Provider-specific template preset"),
|
|
710
711
|
event: import_zod2.z.string().optional().describe("Provider event or topic name"),
|
|
711
|
-
secret: import_zod2.z.string().optional().describe(
|
|
712
|
+
secret: import_zod2.z.string().optional().describe(
|
|
713
|
+
"Signing secret. Required for signed provider templates; omit for secretless providers (sendgrid, discord, plaid)."
|
|
714
|
+
)
|
|
712
715
|
},
|
|
713
716
|
withErrorHandling(
|
|
714
717
|
async ({ slug, method, headers, body, provider, template, event, secret }) => {
|
|
715
718
|
let response;
|
|
716
719
|
if (provider) {
|
|
717
720
|
const templateSecret = secret?.trim();
|
|
718
|
-
if (!templateSecret) {
|
|
719
|
-
throw new Error(
|
|
721
|
+
if (!templateSecret && import_sdk.TEMPLATE_METADATA[provider]?.secretRequired !== false) {
|
|
722
|
+
throw new Error(`send_webhook with provider "${provider}" requires a non-empty secret`);
|
|
720
723
|
}
|
|
721
724
|
response = await client.endpoints.sendTemplate(slug, {
|
|
722
725
|
provider,
|
|
@@ -892,7 +895,7 @@ function registerTools(server, client) {
|
|
|
892
895
|
requestId: import_zod2.z.string().describe("The captured request ID"),
|
|
893
896
|
provider: import_zod2.z.enum(import_sdk.VERIFY_PROVIDERS).optional().describe("Provider whose signature scheme should be verified. Omit to use stored result."),
|
|
894
897
|
secret: import_zod2.z.string().optional().describe(
|
|
895
|
-
"
|
|
898
|
+
"Provider credential for client-side verification (for example a shared signing secret, Adyen hex HMAC key, or PayPal webhook ID). Required for non-Discord providers."
|
|
896
899
|
),
|
|
897
900
|
publicKey: import_zod2.z.string().optional().describe("Discord application public key. Required for provider=discord."),
|
|
898
901
|
url: httpUrlSchema.optional().describe("Original signed URL. Required for Twilio, Square, and HubSpot verification."),
|
|
@@ -964,7 +967,9 @@ function registerTools(server, client) {
|
|
|
964
967
|
provider: import_zod2.z.enum(import_sdk.TEMPLATE_PROVIDERS).optional().describe("Optional provider template for signing"),
|
|
965
968
|
template: import_zod2.z.string().optional().describe("Provider-specific template preset"),
|
|
966
969
|
event: import_zod2.z.string().optional().describe("Provider event or topic name"),
|
|
967
|
-
secret: import_zod2.z.string().optional().describe(
|
|
970
|
+
secret: import_zod2.z.string().optional().describe(
|
|
971
|
+
"Signing secret. Required for signed provider templates; omit for secretless providers (sendgrid, discord, plaid)."
|
|
972
|
+
)
|
|
968
973
|
},
|
|
969
974
|
withErrorHandling(async ({ url, method, headers, body, provider, template, event, secret }) => {
|
|
970
975
|
const response = await client.sendTo(url, {
|
|
@@ -995,7 +1000,9 @@ function registerTools(server, client) {
|
|
|
995
1000
|
provider: import_zod2.z.enum(import_sdk.TEMPLATE_PROVIDERS).optional().describe("Optional provider template for signing"),
|
|
996
1001
|
template: import_zod2.z.string().optional().describe("Provider-specific template preset"),
|
|
997
1002
|
event: import_zod2.z.string().optional().describe("Provider event or topic name"),
|
|
998
|
-
secret: import_zod2.z.string().optional().describe(
|
|
1003
|
+
secret: import_zod2.z.string().optional().describe(
|
|
1004
|
+
"Signing secret. Required for signed provider templates; omit for secretless providers (sendgrid, discord, plaid)."
|
|
1005
|
+
)
|
|
999
1006
|
},
|
|
1000
1007
|
withErrorHandling(async ({ url, method, headers, body, provider, template, event, secret }) => {
|
|
1001
1008
|
const preview = await client.buildRequest(url, {
|
|
@@ -1071,9 +1078,9 @@ function registerTools(server, client) {
|
|
|
1071
1078
|
}
|
|
1072
1079
|
if (provider) {
|
|
1073
1080
|
const templateSecret = secret?.trim();
|
|
1074
|
-
if (!templateSecret) {
|
|
1081
|
+
if (!templateSecret && import_sdk.TEMPLATE_METADATA[provider]?.secretRequired !== false) {
|
|
1075
1082
|
throw new Error(
|
|
1076
|
-
|
|
1083
|
+
`test_webhook_flow with provider "${provider}" requires a non-empty secret`
|
|
1077
1084
|
);
|
|
1078
1085
|
}
|
|
1079
1086
|
flow.sendTemplate({
|
|
@@ -1087,6 +1094,11 @@ function registerTools(server, client) {
|
|
|
1087
1094
|
"test_webhook_flow cannot verify Discord signatures (Ed25519 requires a public key, not a secret)"
|
|
1088
1095
|
);
|
|
1089
1096
|
}
|
|
1097
|
+
if (!templateSecret) {
|
|
1098
|
+
throw new Error(
|
|
1099
|
+
`test_webhook_flow cannot verify "${provider}" signatures \u2014 this provider's templates are unsigned`
|
|
1100
|
+
);
|
|
1101
|
+
}
|
|
1090
1102
|
flow.verifySignature({
|
|
1091
1103
|
provider,
|
|
1092
1104
|
secret: templateSecret
|
|
@@ -1124,24 +1136,127 @@ function registerTools(server, client) {
|
|
|
1124
1136
|
return jsonContent(description);
|
|
1125
1137
|
})
|
|
1126
1138
|
);
|
|
1139
|
+
registerAgentRegistrationTools(server);
|
|
1140
|
+
}
|
|
1141
|
+
function resolveBaseUrl() {
|
|
1142
|
+
return process.env.WHK_BASE_URL ?? "https://webhooks.cc";
|
|
1143
|
+
}
|
|
1144
|
+
function registerAgentRegistrationTools(server) {
|
|
1145
|
+
const baseUrl = resolveBaseUrl();
|
|
1146
|
+
server.tool(
|
|
1147
|
+
"how_to_register",
|
|
1148
|
+
"Explain how an agent self-registers for a webhooks.cc API credential (auth.md). Call this FIRST when you have no API key. Returns the three registration flows and the auth.md documentation URL. No authentication required.",
|
|
1149
|
+
{},
|
|
1150
|
+
withErrorHandling(async () => {
|
|
1151
|
+
return jsonContent({
|
|
1152
|
+
...import_sdk.WebhooksCC.describeRegistration(baseUrl),
|
|
1153
|
+
next_steps: [
|
|
1154
|
+
"Easiest: call register_agent (anonymous) to get a key immediately, then have a human run claim_agent with the returned userCode while logged in to webhooks.cc.",
|
|
1155
|
+
"Or set WHK_API_KEY to an existing whcc_ key and use the authenticated tools."
|
|
1156
|
+
]
|
|
1157
|
+
});
|
|
1158
|
+
})
|
|
1159
|
+
);
|
|
1160
|
+
server.tool(
|
|
1161
|
+
"register_agent",
|
|
1162
|
+
"Self-register for a webhooks.cc API credential via the anonymous auth.md flow. Returns a whcc_ API key that works immediately in a bounded sandbox, plus a short userCode and claimUrl a human uses to bind the key to their account. No authentication required. After registering, set WHK_API_KEY to the returned credential.",
|
|
1163
|
+
{
|
|
1164
|
+
clientName: import_zod2.z.string().optional().describe("A human-readable name for this agent, recorded on the issued key")
|
|
1165
|
+
},
|
|
1166
|
+
withErrorHandling(async ({ clientName }) => {
|
|
1167
|
+
const reg = await import_sdk.WebhooksCC.register.anonymous({ baseUrl, clientName });
|
|
1168
|
+
return jsonContent({
|
|
1169
|
+
credential: reg.credential,
|
|
1170
|
+
scopes: reg.scopes,
|
|
1171
|
+
claim: {
|
|
1172
|
+
userCode: reg.userCode,
|
|
1173
|
+
claimUrl: reg.claimUrl,
|
|
1174
|
+
claimToken: reg.claimToken,
|
|
1175
|
+
expiresAt: reg.claimTokenExpires,
|
|
1176
|
+
instructions: `Ask a human to open ${reg.claimUrl} while logged in to webhooks.cc and either enter the code ${reg.userCode} or open ${reg.claimUrl}?token=${reg.claimToken}. Then call check_claim with the claimToken.`
|
|
1177
|
+
},
|
|
1178
|
+
usage: "Set WHK_API_KEY to `credential` to use the authenticated tools. Before it is claimed the key can create ephemeral endpoints and read its own captured requests in the sandbox."
|
|
1179
|
+
});
|
|
1180
|
+
})
|
|
1181
|
+
);
|
|
1182
|
+
server.tool(
|
|
1183
|
+
"check_claim",
|
|
1184
|
+
"Check whether an anonymous registration's API key has been claimed by a human yet. Poll this after register_agent until status is 'claimed'. No authentication required.",
|
|
1185
|
+
{
|
|
1186
|
+
claimToken: import_zod2.z.string().describe("The claimToken returned by register_agent")
|
|
1187
|
+
},
|
|
1188
|
+
withErrorHandling(async ({ claimToken }) => {
|
|
1189
|
+
const poll = await import_sdk.WebhooksCC.register.pollClaim(claimToken, { baseUrl });
|
|
1190
|
+
return jsonContent(poll);
|
|
1191
|
+
})
|
|
1192
|
+
);
|
|
1193
|
+
server.tool(
|
|
1194
|
+
"register_agent_with_email",
|
|
1195
|
+
"Self-register via the verified_email auth.md flow: webhooks.cc emails a one-time code to the address. The credential is WITHHELD until the code is confirmed with verify_agent_otp. Returns a claimToken to pass to verify_agent_otp. No authentication required.",
|
|
1196
|
+
{
|
|
1197
|
+
email: import_zod2.z.string().email({ message: "Invalid email address" }).describe("The email address to verify and bind the credential to"),
|
|
1198
|
+
clientName: import_zod2.z.string().optional().describe("A human-readable name for this agent, recorded on the issued key")
|
|
1199
|
+
},
|
|
1200
|
+
withErrorHandling(async ({ email, clientName }) => {
|
|
1201
|
+
const challenge = await import_sdk.WebhooksCC.register.withEmail(email, { baseUrl, clientName });
|
|
1202
|
+
return jsonContent({
|
|
1203
|
+
claimToken: challenge.claimToken,
|
|
1204
|
+
expiresAt: challenge.claimTokenExpires,
|
|
1205
|
+
postClaimScopes: challenge.postClaimScopes,
|
|
1206
|
+
next_step: `A one-time code was emailed to ${email}. Ask the human for it, then call verify_agent_otp with this claimToken and the code.`
|
|
1207
|
+
});
|
|
1208
|
+
})
|
|
1209
|
+
);
|
|
1210
|
+
server.tool(
|
|
1211
|
+
"verify_agent_otp",
|
|
1212
|
+
"Complete the verified_email flow: submit the emailed OTP with the claimToken from register_agent_with_email. On success returns the whcc_ API key (bound to the verified email). Set WHK_API_KEY to it. No authentication required.",
|
|
1213
|
+
{
|
|
1214
|
+
claimToken: import_zod2.z.string().describe("The claimToken returned by register_agent_with_email"),
|
|
1215
|
+
otp: import_zod2.z.string().describe("The one-time code the human received by email")
|
|
1216
|
+
},
|
|
1217
|
+
withErrorHandling(async ({ claimToken, otp }) => {
|
|
1218
|
+
const issued = await import_sdk.WebhooksCC.register.confirmEmailOtp({ claimToken, otp }, { baseUrl });
|
|
1219
|
+
return jsonContent({
|
|
1220
|
+
credential: issued.credential,
|
|
1221
|
+
scopes: issued.scopes,
|
|
1222
|
+
usage: "Set WHK_API_KEY to `credential` to use the authenticated tools."
|
|
1223
|
+
});
|
|
1224
|
+
})
|
|
1225
|
+
);
|
|
1226
|
+
server.tool(
|
|
1227
|
+
"register_agent_with_idjag",
|
|
1228
|
+
"Self-register via the identity_assertion (ID-JAG) auth.md flow: present a verified identity-assertion JWT (urn:ietf:params:oauth:token-type:id-jag) from a trusted provider. The credential is returned synchronously \u2014 no human claim step. No webhooks.cc authentication required, but only works if webhooks.cc trusts your provider.",
|
|
1229
|
+
{
|
|
1230
|
+
assertion: import_zod2.z.string().describe("The ID-JAG assertion JWT (typ oauth-id-jag+jwt) from a trusted provider")
|
|
1231
|
+
},
|
|
1232
|
+
withErrorHandling(async ({ assertion }) => {
|
|
1233
|
+
const issued = await import_sdk.WebhooksCC.register.withIdJag(assertion, { baseUrl });
|
|
1234
|
+
return jsonContent({
|
|
1235
|
+
credential: issued.credential,
|
|
1236
|
+
scopes: issued.scopes,
|
|
1237
|
+
usage: "Set WHK_API_KEY to `credential` to use the authenticated tools."
|
|
1238
|
+
});
|
|
1239
|
+
})
|
|
1240
|
+
);
|
|
1127
1241
|
}
|
|
1128
1242
|
|
|
1129
1243
|
// src/index.ts
|
|
1130
|
-
var VERSION = true ? "1.
|
|
1244
|
+
var VERSION = true ? "1.7.0" : "0.0.0-dev";
|
|
1131
1245
|
function createServer(options = {}) {
|
|
1132
1246
|
const apiKey = options.apiKey ?? process.env.WHK_API_KEY;
|
|
1247
|
+
const server = new import_mcp2.McpServer({
|
|
1248
|
+
name: "webhooks-cc",
|
|
1249
|
+
version: VERSION
|
|
1250
|
+
});
|
|
1133
1251
|
if (!apiKey) {
|
|
1134
|
-
|
|
1252
|
+
registerAgentRegistrationTools(server);
|
|
1253
|
+
return server;
|
|
1135
1254
|
}
|
|
1136
1255
|
const client = new import_sdk2.WebhooksCC({
|
|
1137
1256
|
apiKey,
|
|
1138
1257
|
webhookUrl: options.webhookUrl ?? process.env.WHK_WEBHOOK_URL,
|
|
1139
1258
|
baseUrl: options.baseUrl ?? process.env.WHK_BASE_URL
|
|
1140
1259
|
});
|
|
1141
|
-
const server = new import_mcp2.McpServer({
|
|
1142
|
-
name: "webhooks-cc",
|
|
1143
|
-
version: VERSION
|
|
1144
|
-
});
|
|
1145
1260
|
registerTools(server, client);
|
|
1146
1261
|
registerPrompts(server);
|
|
1147
1262
|
registerResources(server, client);
|
|
@@ -1150,6 +1265,7 @@ function createServer(options = {}) {
|
|
|
1150
1265
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1151
1266
|
0 && (module.exports = {
|
|
1152
1267
|
createServer,
|
|
1268
|
+
registerAgentRegistrationTools,
|
|
1153
1269
|
registerPrompts,
|
|
1154
1270
|
registerResources,
|
|
1155
1271
|
registerTools
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
-
import { WebhooksCC } from "@webhooks-cc/sdk";
|
|
3
|
+
import { WebhooksCC as WebhooksCC2 } from "@webhooks-cc/sdk";
|
|
4
4
|
|
|
5
5
|
// src/prompts.ts
|
|
6
6
|
import { z } from "zod";
|
|
@@ -250,11 +250,13 @@ import {
|
|
|
250
250
|
MAX_GLOB_PATTERN_LEN,
|
|
251
251
|
NotFoundError,
|
|
252
252
|
RateLimitError,
|
|
253
|
+
TEMPLATE_METADATA,
|
|
253
254
|
TEMPLATE_PROVIDERS,
|
|
254
255
|
TimeoutError,
|
|
255
256
|
UnauthorizedError,
|
|
256
257
|
VERIFY_PROVIDERS,
|
|
257
258
|
verifySignature,
|
|
259
|
+
WebhooksCC,
|
|
258
260
|
WebhooksCCError
|
|
259
261
|
} from "@webhooks-cc/sdk";
|
|
260
262
|
var MAX_BODY_SIZE = 32768;
|
|
@@ -701,15 +703,17 @@ function registerTools(server, client) {
|
|
|
701
703
|
provider: z2.enum(TEMPLATE_PROVIDERS).optional().describe("Optional provider template to send with signed headers"),
|
|
702
704
|
template: z2.string().optional().describe("Provider-specific template preset"),
|
|
703
705
|
event: z2.string().optional().describe("Provider event or topic name"),
|
|
704
|
-
secret: z2.string().optional().describe(
|
|
706
|
+
secret: z2.string().optional().describe(
|
|
707
|
+
"Signing secret. Required for signed provider templates; omit for secretless providers (sendgrid, discord, plaid)."
|
|
708
|
+
)
|
|
705
709
|
},
|
|
706
710
|
withErrorHandling(
|
|
707
711
|
async ({ slug, method, headers, body, provider, template, event, secret }) => {
|
|
708
712
|
let response;
|
|
709
713
|
if (provider) {
|
|
710
714
|
const templateSecret = secret?.trim();
|
|
711
|
-
if (!templateSecret) {
|
|
712
|
-
throw new Error(
|
|
715
|
+
if (!templateSecret && TEMPLATE_METADATA[provider]?.secretRequired !== false) {
|
|
716
|
+
throw new Error(`send_webhook with provider "${provider}" requires a non-empty secret`);
|
|
713
717
|
}
|
|
714
718
|
response = await client.endpoints.sendTemplate(slug, {
|
|
715
719
|
provider,
|
|
@@ -885,7 +889,7 @@ function registerTools(server, client) {
|
|
|
885
889
|
requestId: z2.string().describe("The captured request ID"),
|
|
886
890
|
provider: z2.enum(VERIFY_PROVIDERS).optional().describe("Provider whose signature scheme should be verified. Omit to use stored result."),
|
|
887
891
|
secret: z2.string().optional().describe(
|
|
888
|
-
"
|
|
892
|
+
"Provider credential for client-side verification (for example a shared signing secret, Adyen hex HMAC key, or PayPal webhook ID). Required for non-Discord providers."
|
|
889
893
|
),
|
|
890
894
|
publicKey: z2.string().optional().describe("Discord application public key. Required for provider=discord."),
|
|
891
895
|
url: httpUrlSchema.optional().describe("Original signed URL. Required for Twilio, Square, and HubSpot verification."),
|
|
@@ -957,7 +961,9 @@ function registerTools(server, client) {
|
|
|
957
961
|
provider: z2.enum(TEMPLATE_PROVIDERS).optional().describe("Optional provider template for signing"),
|
|
958
962
|
template: z2.string().optional().describe("Provider-specific template preset"),
|
|
959
963
|
event: z2.string().optional().describe("Provider event or topic name"),
|
|
960
|
-
secret: z2.string().optional().describe(
|
|
964
|
+
secret: z2.string().optional().describe(
|
|
965
|
+
"Signing secret. Required for signed provider templates; omit for secretless providers (sendgrid, discord, plaid)."
|
|
966
|
+
)
|
|
961
967
|
},
|
|
962
968
|
withErrorHandling(async ({ url, method, headers, body, provider, template, event, secret }) => {
|
|
963
969
|
const response = await client.sendTo(url, {
|
|
@@ -988,7 +994,9 @@ function registerTools(server, client) {
|
|
|
988
994
|
provider: z2.enum(TEMPLATE_PROVIDERS).optional().describe("Optional provider template for signing"),
|
|
989
995
|
template: z2.string().optional().describe("Provider-specific template preset"),
|
|
990
996
|
event: z2.string().optional().describe("Provider event or topic name"),
|
|
991
|
-
secret: z2.string().optional().describe(
|
|
997
|
+
secret: z2.string().optional().describe(
|
|
998
|
+
"Signing secret. Required for signed provider templates; omit for secretless providers (sendgrid, discord, plaid)."
|
|
999
|
+
)
|
|
992
1000
|
},
|
|
993
1001
|
withErrorHandling(async ({ url, method, headers, body, provider, template, event, secret }) => {
|
|
994
1002
|
const preview = await client.buildRequest(url, {
|
|
@@ -1064,9 +1072,9 @@ function registerTools(server, client) {
|
|
|
1064
1072
|
}
|
|
1065
1073
|
if (provider) {
|
|
1066
1074
|
const templateSecret = secret?.trim();
|
|
1067
|
-
if (!templateSecret) {
|
|
1075
|
+
if (!templateSecret && TEMPLATE_METADATA[provider]?.secretRequired !== false) {
|
|
1068
1076
|
throw new Error(
|
|
1069
|
-
|
|
1077
|
+
`test_webhook_flow with provider "${provider}" requires a non-empty secret`
|
|
1070
1078
|
);
|
|
1071
1079
|
}
|
|
1072
1080
|
flow.sendTemplate({
|
|
@@ -1080,6 +1088,11 @@ function registerTools(server, client) {
|
|
|
1080
1088
|
"test_webhook_flow cannot verify Discord signatures (Ed25519 requires a public key, not a secret)"
|
|
1081
1089
|
);
|
|
1082
1090
|
}
|
|
1091
|
+
if (!templateSecret) {
|
|
1092
|
+
throw new Error(
|
|
1093
|
+
`test_webhook_flow cannot verify "${provider}" signatures \u2014 this provider's templates are unsigned`
|
|
1094
|
+
);
|
|
1095
|
+
}
|
|
1083
1096
|
flow.verifySignature({
|
|
1084
1097
|
provider,
|
|
1085
1098
|
secret: templateSecret
|
|
@@ -1117,24 +1130,127 @@ function registerTools(server, client) {
|
|
|
1117
1130
|
return jsonContent(description);
|
|
1118
1131
|
})
|
|
1119
1132
|
);
|
|
1133
|
+
registerAgentRegistrationTools(server);
|
|
1134
|
+
}
|
|
1135
|
+
function resolveBaseUrl() {
|
|
1136
|
+
return process.env.WHK_BASE_URL ?? "https://webhooks.cc";
|
|
1137
|
+
}
|
|
1138
|
+
function registerAgentRegistrationTools(server) {
|
|
1139
|
+
const baseUrl = resolveBaseUrl();
|
|
1140
|
+
server.tool(
|
|
1141
|
+
"how_to_register",
|
|
1142
|
+
"Explain how an agent self-registers for a webhooks.cc API credential (auth.md). Call this FIRST when you have no API key. Returns the three registration flows and the auth.md documentation URL. No authentication required.",
|
|
1143
|
+
{},
|
|
1144
|
+
withErrorHandling(async () => {
|
|
1145
|
+
return jsonContent({
|
|
1146
|
+
...WebhooksCC.describeRegistration(baseUrl),
|
|
1147
|
+
next_steps: [
|
|
1148
|
+
"Easiest: call register_agent (anonymous) to get a key immediately, then have a human run claim_agent with the returned userCode while logged in to webhooks.cc.",
|
|
1149
|
+
"Or set WHK_API_KEY to an existing whcc_ key and use the authenticated tools."
|
|
1150
|
+
]
|
|
1151
|
+
});
|
|
1152
|
+
})
|
|
1153
|
+
);
|
|
1154
|
+
server.tool(
|
|
1155
|
+
"register_agent",
|
|
1156
|
+
"Self-register for a webhooks.cc API credential via the anonymous auth.md flow. Returns a whcc_ API key that works immediately in a bounded sandbox, plus a short userCode and claimUrl a human uses to bind the key to their account. No authentication required. After registering, set WHK_API_KEY to the returned credential.",
|
|
1157
|
+
{
|
|
1158
|
+
clientName: z2.string().optional().describe("A human-readable name for this agent, recorded on the issued key")
|
|
1159
|
+
},
|
|
1160
|
+
withErrorHandling(async ({ clientName }) => {
|
|
1161
|
+
const reg = await WebhooksCC.register.anonymous({ baseUrl, clientName });
|
|
1162
|
+
return jsonContent({
|
|
1163
|
+
credential: reg.credential,
|
|
1164
|
+
scopes: reg.scopes,
|
|
1165
|
+
claim: {
|
|
1166
|
+
userCode: reg.userCode,
|
|
1167
|
+
claimUrl: reg.claimUrl,
|
|
1168
|
+
claimToken: reg.claimToken,
|
|
1169
|
+
expiresAt: reg.claimTokenExpires,
|
|
1170
|
+
instructions: `Ask a human to open ${reg.claimUrl} while logged in to webhooks.cc and either enter the code ${reg.userCode} or open ${reg.claimUrl}?token=${reg.claimToken}. Then call check_claim with the claimToken.`
|
|
1171
|
+
},
|
|
1172
|
+
usage: "Set WHK_API_KEY to `credential` to use the authenticated tools. Before it is claimed the key can create ephemeral endpoints and read its own captured requests in the sandbox."
|
|
1173
|
+
});
|
|
1174
|
+
})
|
|
1175
|
+
);
|
|
1176
|
+
server.tool(
|
|
1177
|
+
"check_claim",
|
|
1178
|
+
"Check whether an anonymous registration's API key has been claimed by a human yet. Poll this after register_agent until status is 'claimed'. No authentication required.",
|
|
1179
|
+
{
|
|
1180
|
+
claimToken: z2.string().describe("The claimToken returned by register_agent")
|
|
1181
|
+
},
|
|
1182
|
+
withErrorHandling(async ({ claimToken }) => {
|
|
1183
|
+
const poll = await WebhooksCC.register.pollClaim(claimToken, { baseUrl });
|
|
1184
|
+
return jsonContent(poll);
|
|
1185
|
+
})
|
|
1186
|
+
);
|
|
1187
|
+
server.tool(
|
|
1188
|
+
"register_agent_with_email",
|
|
1189
|
+
"Self-register via the verified_email auth.md flow: webhooks.cc emails a one-time code to the address. The credential is WITHHELD until the code is confirmed with verify_agent_otp. Returns a claimToken to pass to verify_agent_otp. No authentication required.",
|
|
1190
|
+
{
|
|
1191
|
+
email: z2.string().email({ message: "Invalid email address" }).describe("The email address to verify and bind the credential to"),
|
|
1192
|
+
clientName: z2.string().optional().describe("A human-readable name for this agent, recorded on the issued key")
|
|
1193
|
+
},
|
|
1194
|
+
withErrorHandling(async ({ email, clientName }) => {
|
|
1195
|
+
const challenge = await WebhooksCC.register.withEmail(email, { baseUrl, clientName });
|
|
1196
|
+
return jsonContent({
|
|
1197
|
+
claimToken: challenge.claimToken,
|
|
1198
|
+
expiresAt: challenge.claimTokenExpires,
|
|
1199
|
+
postClaimScopes: challenge.postClaimScopes,
|
|
1200
|
+
next_step: `A one-time code was emailed to ${email}. Ask the human for it, then call verify_agent_otp with this claimToken and the code.`
|
|
1201
|
+
});
|
|
1202
|
+
})
|
|
1203
|
+
);
|
|
1204
|
+
server.tool(
|
|
1205
|
+
"verify_agent_otp",
|
|
1206
|
+
"Complete the verified_email flow: submit the emailed OTP with the claimToken from register_agent_with_email. On success returns the whcc_ API key (bound to the verified email). Set WHK_API_KEY to it. No authentication required.",
|
|
1207
|
+
{
|
|
1208
|
+
claimToken: z2.string().describe("The claimToken returned by register_agent_with_email"),
|
|
1209
|
+
otp: z2.string().describe("The one-time code the human received by email")
|
|
1210
|
+
},
|
|
1211
|
+
withErrorHandling(async ({ claimToken, otp }) => {
|
|
1212
|
+
const issued = await WebhooksCC.register.confirmEmailOtp({ claimToken, otp }, { baseUrl });
|
|
1213
|
+
return jsonContent({
|
|
1214
|
+
credential: issued.credential,
|
|
1215
|
+
scopes: issued.scopes,
|
|
1216
|
+
usage: "Set WHK_API_KEY to `credential` to use the authenticated tools."
|
|
1217
|
+
});
|
|
1218
|
+
})
|
|
1219
|
+
);
|
|
1220
|
+
server.tool(
|
|
1221
|
+
"register_agent_with_idjag",
|
|
1222
|
+
"Self-register via the identity_assertion (ID-JAG) auth.md flow: present a verified identity-assertion JWT (urn:ietf:params:oauth:token-type:id-jag) from a trusted provider. The credential is returned synchronously \u2014 no human claim step. No webhooks.cc authentication required, but only works if webhooks.cc trusts your provider.",
|
|
1223
|
+
{
|
|
1224
|
+
assertion: z2.string().describe("The ID-JAG assertion JWT (typ oauth-id-jag+jwt) from a trusted provider")
|
|
1225
|
+
},
|
|
1226
|
+
withErrorHandling(async ({ assertion }) => {
|
|
1227
|
+
const issued = await WebhooksCC.register.withIdJag(assertion, { baseUrl });
|
|
1228
|
+
return jsonContent({
|
|
1229
|
+
credential: issued.credential,
|
|
1230
|
+
scopes: issued.scopes,
|
|
1231
|
+
usage: "Set WHK_API_KEY to `credential` to use the authenticated tools."
|
|
1232
|
+
});
|
|
1233
|
+
})
|
|
1234
|
+
);
|
|
1120
1235
|
}
|
|
1121
1236
|
|
|
1122
1237
|
// src/index.ts
|
|
1123
|
-
var VERSION = true ? "1.
|
|
1238
|
+
var VERSION = true ? "1.7.0" : "0.0.0-dev";
|
|
1124
1239
|
function createServer(options = {}) {
|
|
1125
1240
|
const apiKey = options.apiKey ?? process.env.WHK_API_KEY;
|
|
1241
|
+
const server = new McpServer2({
|
|
1242
|
+
name: "webhooks-cc",
|
|
1243
|
+
version: VERSION
|
|
1244
|
+
});
|
|
1126
1245
|
if (!apiKey) {
|
|
1127
|
-
|
|
1246
|
+
registerAgentRegistrationTools(server);
|
|
1247
|
+
return server;
|
|
1128
1248
|
}
|
|
1129
|
-
const client = new
|
|
1249
|
+
const client = new WebhooksCC2({
|
|
1130
1250
|
apiKey,
|
|
1131
1251
|
webhookUrl: options.webhookUrl ?? process.env.WHK_WEBHOOK_URL,
|
|
1132
1252
|
baseUrl: options.baseUrl ?? process.env.WHK_BASE_URL
|
|
1133
1253
|
});
|
|
1134
|
-
const server = new McpServer2({
|
|
1135
|
-
name: "webhooks-cc",
|
|
1136
|
-
version: VERSION
|
|
1137
|
-
});
|
|
1138
1254
|
registerTools(server, client);
|
|
1139
1255
|
registerPrompts(server);
|
|
1140
1256
|
registerResources(server, client);
|
|
@@ -1142,6 +1258,7 @@ function createServer(options = {}) {
|
|
|
1142
1258
|
}
|
|
1143
1259
|
export {
|
|
1144
1260
|
createServer,
|
|
1261
|
+
registerAgentRegistrationTools,
|
|
1145
1262
|
registerPrompts,
|
|
1146
1263
|
registerResources,
|
|
1147
1264
|
registerTools
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webhooks-cc/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "MCP server for webhooks.cc — AI agent integration for webhook testing",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -36,15 +36,15 @@
|
|
|
36
36
|
},
|
|
37
37
|
"homepage": "https://webhooks.cc",
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
39
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
40
40
|
"zod": "^4.4.3",
|
|
41
|
-
"@webhooks-cc/sdk": "1.
|
|
41
|
+
"@webhooks-cc/sdk": "1.9.1"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
|
-
"@types/node": "^
|
|
44
|
+
"@types/node": "^26.2.0",
|
|
45
45
|
"tsup": "^8.5.1",
|
|
46
46
|
"typescript": "^6.0.3",
|
|
47
|
-
"vitest": "^4.1.
|
|
47
|
+
"vitest": "^4.1.10"
|
|
48
48
|
},
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "tsup",
|