Skip to content

feat(mcp): landing-pages AI toolset, async image uploads, and platform-aligned tool metadata - #113

Merged
bighadj22 merged 6 commits into
mainfrom
feat/mcp-landing-pages-ai-tools
Sep 12, 2026
Merged

feat(mcp): landing-pages AI toolset, async image uploads, and platform-aligned tool metadata#113
bighadj22 merged 6 commits into
mainfrom
feat/mcp-landing-pages-ai-tools

Conversation

@bighadj22

Copy link
Copy Markdown
Owner

Summary

Extends the MCP surface so an AI client (ChatGPT, Claude, etc.) can build a complete landing page end-to-end — create the page, pass generated images into the image stack through a durable background workflow, poll until stored, arrange the stack, and publish — and aligns every tool's advertised metadata with the current MCP + OpenAI plugin requirements.

What's included

Landing pages toolset (7 new tools)

  • uploadLandingPageImage — accepts conversation images via the OpenAI file-object contract (openai/fileParams), a public http(s) URL, or base64 from programmatic clients; validates content by magic-byte sniffing, enforces an 8 MB cap, and enqueues a background workflow
  • getLandingPageImageUploadStatus — polls the upload workflow and maps every instance state to a model-readable status view
  • removeLandingPageImage (shared-R2-object last-reference guard), reorderLandingPageImages, duplicateLandingPage, unpublishLandingPage, archiveLandingPage

Durable upload workflow

  • CodLandingPageImageUploadWorkflow (Cloudflare Workflows): retried URL fetch with capped streaming read, content-type verification against served bytes, fail-open intrinsic-dimension parsing, idempotent record insert, audited landing_page_images row with source: "ai"
  • Dependency-free image sniffing + dimension parsing for png/jpeg/gif/webp

Output contracts on all 96 tools

  • Every domain exports an output-schema map from a shared success/failure envelope; outputSchema is advertised on every tool and every result carries validated structuredContent (drift logs loudly and degrades to the text result)

Platform-aligned tool metadata

  • ToolAnnotations derived from the platform's own classifications (read-scope gating → readOnlyHint, dangerous-tool set → destructiveHint) with machine-checked consistency tests
  • Human-readable titles on all tools; openai/fileParams and openai/toolInvocation status text on the upload tool
  • Per-subject tool-call rate limit (fixed window in RATE_LIMIT KV, fail-open) keyed by the client's openai/subject hint; client hints join the audit trail as correlation-only fields

Confirmation model

  • Removed the server-side two-round confirmation gate: per platform docs, write-action approval is the MCP client's responsibility, framed by the destructiveHint annotations; the server gates by OAuth scope, validates inputs, rate-limits, and writes the audit trail (confirm-tool and MCP_REQUEST_STATE_KEY removed)

Tooling fixes

  • MCP tools: strict layer-2 validation (unknown fields rejected, never silently stripped), existence checks on publish/unpublish/archive paths (no more false success), publish warns on an empty image stack, STOREFRONT_URL fallback parity with REST, bounded default pagination on list
  • Dashboard: landing-page Studio uploads now presign into the landing/ R2 namespace; removed the BETA badge from the AI agents nav item
  • OAuth consent page: real brand wordmark (light/dark variants), permissions grouped by domain with compact localized chips (ar/fr/en), account identity line, dark mode, RTL support — all client-controlled values HTML-escaped

Test plan

  • cod-server: 140 files / 2054 tests passing (tsc clean)
  • cod-client-astro: 33 files / 147 tests passing (astro check clean)
  • Schema-drift guards extended in both directions for inputs, outputs, annotations, and titles
  • Rate-limit tests: block at limit, fail-open on KV errors, per-subject isolation
  • Workflow tests: URL/bytes paths, size caps, content mismatch, idempotent insert, dimension fallbacks
  • Verified end-to-end against the deployed worker with a live ChatGPT connector (image upload via file object, polling, publish)

Notes

  • No D1 migrations — landing_page_images.source already anticipated "ai"; no new production dependencies
  • DANGEROUS_TOOLS is retained as the risk classification feeding annotations; it no longer gates execution
  • Wrangler config gains the LP_IMAGE_UPLOAD_WORKFLOW binding (example template updated; deploy-time config is gitignored per repo policy)

- CodLandingPageImageUploadWorkflow: background upload for MCP agents —
  URL-fetch (retried, size-capped, magic-byte-verified) and direct-R2-bytes
  entry paths, idempotent record insert, fail-open dimension parsing,
  audited landing_page_images row with source "ai"
- dependency-free image sniffing/dimension parsing (png/jpeg/gif/webp)
- shared minting rules for upload ids and R2 keys (landing-image-upload lib)
- addLandingPageImage gains optional provenance (upload | ai)
- getLandingPageById batched to two D1 round trips; opt-in list pagination
  (limit/offset) surfaced on the REST route; wrangler binding + env wiring
- uploadLandingPageImage: chat clients pass conversation images via the
  OpenAI file-object contract (openai/fileParams) or a public URL;
  programmatic clients via base64 — enqueues the background workflow and
  returns a polling job id
- getLandingPageImageUploadStatus: polls the workflow instance and maps
  every state to a model-readable status view
- stack + lifecycle tools: remove (R2 last-reference guard), reorder,
  duplicate, unpublish, archive
- strict layer-2 validation on every tool (unknown fields rejected, never
  stripped); publish warns on an empty image stack; existence checks fix
  false-success on publish/update paths; STOREFRONT_URL fallback parity
  with REST; tool descriptions written for model consumption
- REST list route gains validated limit/offset
Every ai-tools domain exports an output-schema map built from a shared
success/failure envelope; the MCP surface advertises outputSchema on every
registered tool and validates each result's structuredContent against it
(drift logs loudly and falls back to the text result, never failing a
working tool). Payload fields documented for model consumption; DB-row
passthroughs declare guaranteed identity fields only.
- ToolAnnotations derived from the platform's own classifications (read
  scopes => readOnlyHint, DANGEROUS_TOOLS => destructiveHint) with
  consistency tests; human-readable titles on all 96 tools
- per-subject tool-call rate limit (fixed window in RATE_LIMIT KV,
  fail-open) keyed by the client's openai/subject hint; client hints
  (subject/session) join the audit trail — correlation only, never
  authorization
- removed the server-side two-round confirmation gate: per the platform
  docs, write-action approval is the client's job, framed by our
  destructiveHint annotations; the server gates by scope, validates,
  rate-limits, and audits (confirm-tool + MCP_REQUEST_STATE_KEY removed)
- consent page redesign: real brand wordmark (light/dark), grouped
  permission chips with localized domain/action labels (ar/fr/en),
  account identity line, dark mode, RTL — all client-controlled values
  escaped
- audit redaction for oversized string arguments
… BETA badge

Landing page Studio uploads now request folder=landing on presign (they
were landing in products/); the AI agents MCP nav item is no longer marked
beta.
@bighadj22
bighadj22 merged commit 492c313 into main Sep 12, 2026
3 checks passed
@bighadj22
bighadj22 deleted the feat/mcp-landing-pages-ai-tools branch September 12, 2026 20:06
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