Repository navigation
Magnet Integration
Let an AI agent use your MachFive Magnet the way a visitor would.
A Magnet is an interactive widget that automates
conversational lead generation. machvive-m5t-magnet bridges one to
WebMCP, so an
agent can discover what the widget collects and fill it in — instead of guessing
at the DOM, or ignoring it entirely.
<machvive-m5t-magnet app-guid="your-app-guid"></machvive-m5t-magnet>import '@machfivetechchicago/machvive-webmcp-ai/m5t-magnet';That is the whole integration. The element loads the magnet snippet, waits for the runtime, and registers tools. It renders nothing — your magnet already draws its own launcher, and a second visible surface would compete with it.
Nothing here is hardcoded. A magnet already declares what it collects — each step's field, type, prompt, and options — and that declaration is an agent interface. The component reads it and generates the tools.
Configure a step in your magnet admin and it appears to agents. No code change.
Against a magnet asking product interest, name, and email:
| Tool | What it does |
|---|---|
magnet_describe |
What the form asks, and whether it can schedule |
magnet_options |
Allowed choices for a multiple-choice field |
magnet_start |
Open the form with answers filled in |
magnet_status |
Has the visitor submitted yet |
magnet_options only appears if something actually has choices. This matters more
than it sounds: an agent shown a tool that returns nothing useful wastes a turn
discovering that, and may distrust the rest of the surface.
Here is magnet_describe against a real booking-enabled magnet:
Book time with Nicholas — Thirty minutes with me, booked in one step.
It asks:
- product_interest (single_select): "What do you want to talk about?"
choices: Mach Five Group | Mach Five Tech | Mach Five Marketing | ...
- first_name (text): "What's your name?"
- email (email): "What's the best email to reach you?"
It can schedule "30-min meeting" via ms_bookings. The visitor books it from the
widget — you cannot book on their behalf, and the times come from a live calendar.
magnet_start prefills the widget and opens it. It does not submit.
This is deliberate, and it is the most important line in the integration. An agent
posting a person's email address without that person seeing it is a consent
problem, and lead capture is precisely where it matters. The magnet's own
open({ prefill }) API reads as designed for this handoff: the agent gathers what
it can from the conversation, the widget shows the visitor what will be sent, and
the visitor confirms.
What the agent gets back says so plainly:
Opened the enquiry form for the visitor with product_interest, email filled in.
They will be asked for: first_name. They must review and submit it themselves.
A magnet can schedule in either of two ways, and the component reads both:
-
A
bookingstep inmag_macro_steps— the calendar is part of the flow. -
A
bookaction inmag_actions— the magnet hands off to an external calendar such as Microsoft Bookings, while its steps collect something else.
The second shape is easy to miss. A magnet whose entire purpose is booking may
have no booking step at all — its steps collect a name and an email, and the
booking lives in mag_actions with config.source: "ms_bookings". Reading only
the steps reports "cannot schedule" on exactly the magnets that can.
Prefillable step types are an allowlist: text, email, phone, number,
single_select, multi_select. Everything else is described to the agent and left
for the visitor.
A booking step is the clearest case — its slots come from a live calendar and change by the minute, so a pre-filled time would be stale or invalid by the time anyone saw it. But the same rule covers step types released after this component was written. An unrecognised type degrades to "the visitor completes this", which is the honest default for something we do not understand:
The visitor completes these in the widget — you cannot pre-answer them:
- meeting_time (booking) — a live calendar; they pick a real slot
An invalid value does not throw. It returns a result the agent can act on, naming what would have worked:
"Nope" is not a choice for product_interest.
Options: Evaluating MachVive | Building with it and need help | ...
An unknown field name gets the same treatment. Agents self-correct from this in a single turn; an exception would end the run.
An empty value means "I do not know this" — a legitimate thing for an agent to say — and is dropped rather than rejected.
magnet-ready |
tools registered; detail carries the magnet id and tool names |
magnet-capture |
the visitor submitted |
magnet-error |
the runtime never loaded |
.config |
the magnet definition this element bound to |
.captures |
captures observed this session |
document.querySelector('machvive-m5t-magnet')
.addEventListener('magnet-capture', (e) => console.log('lead captured', e.detail));app-guid |
required unless you load the magnet snippet yourself |
magnet-id |
pick a specific magnet when the app defines several; defaults to the home magnet |
src |
override the snippet origin |
If the page already carries a coreSnippet script, the component uses it rather
than loading a second copy.
A secure context. WebMCP is [SecureContext], so this needs https:// or
localhost. Over plain HTTP there is no navigator.modelContext and no tools.
Your magnet must allow the origin. The instance is configured with permitted origins; localhost needs to be among them for local development.
Browser only. Like every component in this package, importing it during a server render throws — use a client-only import in Next.js, Nuxt, Astro, SvelteKit, or Remix.
Stated plainly, because some of this was learned by reading the magnet runtime rather than from a specification:
- The prefillable allowlist is conservative by choice. It covers the types seen in real magnets. A type outside it is described but not pre-answered, which is safe but may be stricter than necessary.
-
open({ prefill })appears to cap at 40 keys and coerce values to strings. That was inferred from the runtime, not documented. -
Only the
captureevent is observed. If the runtime emits others, richer status reporting is possible. - There is no agent-side submit, by design. If a programmatic submit exists, exposing it would be a product decision about consent, not a technical one.
Verified against two real magnets: one that collects details for email follow-up, and one that books through Microsoft Bookings.
- Project wiki home
- webmcp-playground — a live agent-callable page
- webmcp-browser-use — drive a magnet with a real agent