Skip to content

fix(ai-tools): validate MCP billing/contract/catalog payloads with shared Zod schemas; fix void delete_draft return - #3098

Open
ToddHebebrand wants to merge 1 commit into
mainfrom
ToddHebebrand/invoice-contract-MCP
Open

fix(ai-tools): validate MCP billing/contract/catalog payloads with shared Zod schemas; fix void delete_draft return#3098
ToddHebebrand wants to merge 1 commit into
mainfrom
ToddHebebrand/invoice-contract-MCP

Conversation

@ToddHebebrand

Copy link
Copy Markdown
Collaborator

Summary

Two defects found by live MCP testing of the billing/contract/catalog AI tools:

  1. Unvalidated object payloads on the MCP path. manage_contracts, manage_invoices, and manage_catalog type-cast their object payloads (input/patch/line/payment/item/override/components) straight into the service layer with no Zod parse. The HTTP routes validate these payloads, but the MCP path skipped it entirely, so a malformed payload died as an opaque HTTP 500 DB constraint violation instead of a structured VALIDATION_ERROR the model could act on. Payloads now parse with the same shared schemas the routes use (createContractSchema, manualLineSchema, createCatalogItemSchema, recordPaymentSchema, etc.), wrapped under their param name so ZodError paths are self-describing (line.quantity: ..., payment.receivedAt: ...).

  2. manage_invoices delete_draft returned "undefined". It stringified the result of a Promise<void> call, so the MCP layer rejected the result as a generic tool failure after the delete had already committed. Now returns {ok: true}, matching the manage_contracts/manage_quotes pattern.

Tests

Regression tests cover invalid create/update/add_line/payment payloads (structured VALIDATION_ERROR, service never called) and the delete_draft return shape:

  • aiToolsBilling.manageInvoices.test.ts
  • aiToolsCatalog.manageCatalog.test.ts
  • aiToolsContracts.manageContracts.test.ts

🤖 Generated with Claude Code

…ared Zod schemas; fix void delete_draft return

Two defects found by live MCP testing:

1. manage_contracts, manage_invoices, and manage_catalog type-cast their
   object payloads (input/patch/line/payment/item/override/components)
   straight into the service layer with no Zod parse — the HTTP routes
   validate these payloads but the MCP path skipped it, so a malformed
   payload died as an opaque HTTP 500 DB constraint violation instead of
   a structured VALIDATION_ERROR. Payloads now parse with the same shared
   schemas the routes use (createContractSchema, manualLineSchema,
   createCatalogItemSchema, recordPaymentSchema, etc.), wrapped under
   their param name so ZodError paths are self-describing.

2. manage_invoices delete_draft returned JSON.stringify of a void call,
   i.e. undefined — the MCP layer rejected the result as a generic tool
   failure AFTER the delete had already committed. Now returns {ok:true},
   matching manage_contracts/manage_quotes.

Regression tests cover invalid create/update/add_line/payment payloads
(structured VALIDATION_ERROR, service never called) and the delete_draft
return shape.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying breeze with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4e6c34b
Status: ✅  Deploy successful!
Preview URL: https://d95b7da1.breeze-9te.pages.dev
Branch Preview URL: https://toddhebebrand-invoice-contra.breeze-9te.pages.dev

View logs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant