🎁 Free: The MCP Growth Kit — the 9-tactic playbook + skills your agent can run to grow your MCP →
← All posts

Make your MCP look native in Claude: result widgets in one afternoon

Tal

Tal — Founder at Lulu

July 29, 2026

Text is a wall. Cards get chosen.

In an agent surface, your tool's output is your product's UI. There's no homepage, no onboarding screen, no brand moment — there's the instant your result lands in the conversation. If that instant is a JSON blob or a paragraph of prose, your tool is a commodity the user scrolls past. If it's a designed card that looks like the host built it, two things happen: the user trusts the answer, and — this is the part that compounds — the tool gets re-invoked. Hosts and users both reach again for tools whose answers they can read at a glance.

We didn't theorize this; we shipped it. Our weather MCP runs live in Claude today, and when you ask it about Bangkok, the answer isn't text — it's an atmospheric card: rain-slate gradient background keyed to the actual conditions, the temperature at 58 pixels, humidity and wind as chips, attribution in the corner. It looks like a native Claude surface. It's a FastMCP server with one registration call.

As of lulu-ads 0.8.1, that machinery is in the SDK for every publisher. Here's the whole system.

Four templates, zero design skill

Most developers shouldn't design UI, and with templates they don't have to. You pick the shape that matches your answer, map your fields, and the SDK renders it inside a fixed frame:

stat-card — one primary value is the answer: a temperature, a price, a score, a balance. Big value, muted eyebrow above it for context, secondary data as chips, optional condition-driven atmosphere behind it.

table-card — rows to compare: search results, rankings, forecasts. Column headers, monospace numbers that align, and at most one row highlighted as "best" with an orange rail.

notice-card — a verdict: domain available, payment succeeded, scan passed. A check/warning glyph, one sentence of title, detail rows underneath.

carousel-card — three to eight rich alternatives to browse: hotels, flights, listings. Swipeable cards with dots, one optionally marked as recommended.

Registration is one call per tool, with an explicit mapping from your result fields to the template's slots. This is the real code from our weather server, verbatim:

from lulu_ads.widgets import register_result_widget

register_result_widget(
    mcp, "get_weather",
    template="stat-card",
    mapping={
        "eyebrow": "location.name",
        "value": {"path": "temperature_c", "suffix": "°"},
        "sublabel": {"path": "feels_like_c", "prefix": "Feels like ", "suffix": "°C"},
        "condition": "conditions",
        "chips": [
            {"path": "humidity_pct", "prefix": "💧 ", "suffix": "%"},
            {"path": "wind_kmh", "prefix": "💨 ", "suffix": " km/h"},
        ],
        "atmosphere": "weather_code",
    },
    endpoint_url="https://your-host.dev/your/mcp",
)

The mapping is deliberately dumb and predictable — paths into your structuredContent, optional prefixes and suffixes, nothing clever. The clever part belongs to your agent, and we'll get there.

The frame you don't have to build

Every template shares one frame, and the frame is where the unglamorous hard parts live — the parts you'd otherwise discover one production bug at a time:

The host bridge. The widget speaks the MCP Apps contract with the host — the same postMessage plumbing our weather card proved in production Claude before it ever became a template.

A truly transparent canvas. Here's an honest one: we shipped a widget whose corners rendered as white boxes on Claude's dark theme, and the bug wasn't the background at all — it was a missing color-scheme declaration, because Chromium only keeps an iframe transparent when the embedded page's color scheme matches the host's. The frame carries the fix; you never think about it.

Dark and light, both real. Tokens flip with the host theme. Your card is legible in both without you designing either.

Mobile that reflows instead of truncating. The iframe's viewport is the card, so below 440px the frame restructures: values scale down one step, rows stack, and text wraps instead of dying in an ellipsis. The sponsored strip transforms too — on phones it becomes a full-width orange band with SPONSORED on the left and "via Lulu Ads" on the right, then the advertiser logo and the full ad text in columns beneath. Nothing gets cut on a phone. Ever.

The disclosed sponsored strip. When a response carries a sponsored field, the frame renders it at the bottom: a small orange-gradient SPONSORED chip, the advertiser's logo tile (with an automatic letter-tile fallback), the offer text, a CTA, and "via Lulu Ads." The philosophy is fixed and non-negotiable: your data is the hero, the disclosure is always legible, and the strip is calm — one soft sheen when the card first renders, then stillness. No tickers, no rotation, no blinking. And when there's no sponsored payload, there's no strip at all — no gap, no ghost. It's the same data-never-directives contract the whole SDK runs on, now with a consistent face.

The design rules that matter

The full craft guide is longer, but these five carry most of the weight:

  • One hero element per card. The value or the verdict. Never two things shouting.
  • Chips, not sentences. Secondary data reads faster as labeled chips than as prose.
  • Monospace the numbers that will be compared, and right-align them.
  • Atmosphere only when it means something. A rain gradient behind a rain forecast carries information; a decorative gradient behind a currency rate is noise.
  • Native, not spammy: generous padding, one accent moment, no emoji walls, no looping motion, nothing that resembles a banner ad.

If it feels like the host designed it, you did it right. If it feels like an ad unit, delete something.

Let your agent do it

Choosing templates and writing mappings is exactly the kind of work a coding agent does well — so we packaged it. The MCP Growth Kit ships a build-result-widget skill: your agent reads your tool's output schema, picks the fitting template, writes the mapping, renders dark and light screenshots, and shows you the result before committing anything. It follows a machine-readable design system published at getlulu.dev/widget-design.md — point Claude at that file in your repo and say "build my widget." The design guide wins arguments with the agent's instincts by construction; the screenshots-before-done rule is an Iron Law, not a suggestion.

Widgets are one tactic in a bigger stack — the same one we documented in How to grow your MCP server, aggregated on Lulu MCPs, and measured in our numbers post. A tool that looks native gets tried; a tool that answers beautifully gets re-invoked; a tool that's re-invoked has traffic worth something.

Get the pieces

The complete visual guide — every template rendered, the full craft rules, both strip layouts — is The MCP Widget Design Guide (PDF), companion to the Growth Playbook. The skills and the machine-readable design system come with the free MCP Growth Kit. And the sponsored strip only earns you money if you're a publisher — setup takes about a minute. We timed it.

Your tools already have the traffic.

One line of code makes them earn — 70% goes to you.

Join the publisher beta ->