Skip to content

Commit b3d4132

Browse files
fix(client): align webhook/schedule MCP calls with current api shape
Six contract mismatches discovered while running every advertised tool against a live local api. After this commit the MCP exercises all webhook + schedule CRUD endpoints without errors: - createWebhook now sends {events: [event], url, signingSecret} so the API-Platform-exposed POST /api/v1/webhooks accepts it. The single user-facing event arg is expanded internally. - updateWebhook expands {event} → {events: [event]} the same way. - toggleWebhook switched POST → PATCH (API-Platform exposes only PATCH on /webhooks/{uuid}/toggle). - testWebhook now hits /zapier/webhooks/{uuid}/test — the main webhook bundle has no /test endpoint; the Zapier-integration controller accepts the same UUID. - updateSchedule switched PATCH → PUT (API-Platform default for the schedules resource). - runSchedule path /schedules/{uuid}/run → /schedules/{uuid}/run-now. Also: respect EXPORTCOMMENTS_API_BASE env var so the same client can be pointed at a local api during development (defaults unchanged to https://exportcomments.com). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 287778d commit b3d4132

1 file changed

Lines changed: 24 additions & 9 deletions

File tree

src/client.ts

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import type {
77
CLIOutput,
88
} from './types.js';
99

10-
const BASE_URL = 'https://exportcomments.com/api/v3';
11-
const V1_BASE_URL = 'https://exportcomments.com/api/v1';
10+
const API_BASE = process.env.EXPORTCOMMENTS_API_BASE?.replace(/\/+$/, '') ?? 'https://exportcomments.com';
11+
const BASE_URL = `${API_BASE}/api/v3`;
12+
const V1_BASE_URL = `${API_BASE}/api/v1`;
1213
const USER_AGENT = 'exportcomments-cli/1.0.0';
1314

1415
/** A JWT has three base64url-encoded segments separated by dots (header.payload.signature). */
@@ -280,26 +281,40 @@ export class ExportCommentsClient {
280281
/**
281282
* @param event subscription event name (e.g. "export.completed")
282283
* @param url POST target — must respond 2xx within 10s
284+
*
285+
* The API-Platform webhook resource expects `events: string[]` and a
286+
* `signingSecret` for HMAC verification. We accept a single event in the
287+
* MCP-facing shape and expand it here so the MCP tool stays single-arg.
283288
*/
284289
async createWebhook(event: string, url: string): Promise<CLIOutput<unknown>> {
285-
return this.v1Request('POST', '/webhooks', { event, url });
290+
const { randomBytes } = await import('node:crypto');
291+
return this.v1Request('POST', '/webhooks', {
292+
events: [event],
293+
url,
294+
signingSecret: randomBytes(32).toString('hex'),
295+
});
286296
}
287297

288298
async updateWebhook(uuid: string, fields: { event?: string; url?: string }): Promise<CLIOutput<unknown>> {
289-
return this.v1Request('PATCH', `/webhooks/${uuid}`, fields);
299+
const payload: { events?: string[]; url?: string } = {};
300+
if (fields.event) payload.events = [fields.event];
301+
if (fields.url) payload.url = fields.url;
302+
return this.v1Request('PATCH', `/webhooks/${uuid}`, payload);
290303
}
291304

292305
async deleteWebhook(uuid: string): Promise<CLIOutput<unknown>> {
293306
return this.v1Request('DELETE', `/webhooks/${uuid}`);
294307
}
295308

309+
/** Toggle uses PATCH (API-Platform exposes it that way). */
296310
async toggleWebhook(uuid: string): Promise<CLIOutput<unknown>> {
297-
return this.v1Request('POST', `/webhooks/${uuid}/toggle`);
311+
return this.v1Request('PATCH', `/webhooks/${uuid}/toggle`);
298312
}
299313

300-
/** Sends a test event payload to a webhook URL for connectivity verification. */
314+
/** Sends a test event payload. The main /webhooks bundle has no test
315+
* endpoint; the Zapier-integration route does, and accepts the same UUID. */
301316
async testWebhook(uuid: string): Promise<CLIOutput<unknown>> {
302-
return this.v1Request('POST', `/webhooks/${uuid}/test`);
317+
return this.v1Request('POST', `/zapier/webhooks/${uuid}/test`);
303318
}
304319

305320
// ── Scheduled exports ──
@@ -318,15 +333,15 @@ export class ExportCommentsClient {
318333
}
319334

320335
async updateSchedule(uuid: string, fields: Record<string, unknown>): Promise<CLIOutput<unknown>> {
321-
return this.v1Request('PATCH', `/schedules/${uuid}`, fields);
336+
return this.v1Request('PUT', `/schedules/${uuid}`, fields);
322337
}
323338

324339
async deleteSchedule(uuid: string): Promise<CLIOutput<unknown>> {
325340
return this.v1Request('DELETE', `/schedules/${uuid}`);
326341
}
327342

328343
async runSchedule(uuid: string): Promise<CLIOutput<unknown>> {
329-
return this.v1Request('POST', `/schedules/${uuid}/run`);
344+
return this.v1Request('POST', `/schedules/${uuid}/run-now`);
330345
}
331346

332347
async pauseSchedule(uuid: string): Promise<CLIOutput<unknown>> {

0 commit comments

Comments
 (0)