Skip to main content
    Back to Changelog
    Improvement
    May 28, 20262 min read

    MCP server: cleaner errors, smarter schemas, faster previews

    API & MCP
    Governance

    ✨ What's Improved

    The MCP server now treats agents like they don't have access to your DB schema — because they don't. Write tools auto-wrap legacy payload shapes, return structured errors with recovery hints, and trim multi-KB scrape blobs out of previews so context windows stay clean.

    The Problem

    An external Claude session populating a brand kit hit nine separate rough edges across ~30 MCP calls: ~12 needed retries. writing_constraints had an undocumented DB shape that rejected every obvious payload. create_brand_kit_competitor returned a bare "Error occurred during tool execution" with no code. Two-step dry_run/confirm flow had silent contradictions. Dry-run previews dumped every CSS custom property from the scraped competitor site into the response, blowing past context limits.

    The Fix

    • Auto-wrap on write. upsert_brand_kit_governance accepts writing_constraints as a bare array, a {rules: [...]} object, a flat key/value object, or a single string — and reshapes it into the canonical {constraints: [...], preferences?: {...}} form before write. Read paths still return a bare array for downstream consumers.
    • Structured errors everywhere. Competitor handlers now wrap in try/catch and return error_code, retryable, and recovery_hint on every failure path. Non-Error throws are serialized properly. DB error messages flow through to the agent.
    • dry_run + confirm clarified. Passing both is now a validation_error with a mutually exclusive recovery message. Dry-run previews embed next_call: { confirm: true } so the follow-up shape is unambiguous.
    • Smaller previews. raw_scrape_data.css_tokens (often hundreds of entries) is stripped from MCP responses — only extraction_confidence, scraped_at, css_token_count, and scrape_status come over the wire. Full data stays in the DB for the web UI.
    • Scrape status. Every competitor response now carries scrape_status: success | partial | blocked | timeout | no_api_key | no_data plus an optional reason — no more guessing why a scrape returned empty fields.
    • No more accidental primary personas. generate_audience_persona checks for an existing primary before insert and forces is_primary: false if one exists.
    • No more duplicate keys. get_brand_kit_personality and upsert_brand_kit_personality no longer return both traits + personality_traits. Only the DB-native long names.
    • Tool discovery in one call. New list_brand_kit_tools meta-tool returns the canonical mapping from each brand-kit section to its read, preview, write, and generate tools. Replaces multi-step tool_search queries.

    How to Verify

    No user action needed — these are server-side changes deployed automatically. If you're integrating against the MCP server, structured errors now carry _meta.error_code and _meta.recovery_hint you can surface to your end users. The list_brand_kit_tools tool is the new starting point for section-aware agents.