merch-store-mcp
Allows agents to shop the Twilio Merch Store demo by exposing the store's own tools for page state, product search, cart management, checkout, credential presentation, purchase attempts, and drops.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@merch-store-mcpsearch for hoodies and add a large to my cart"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
merch-store-mcp
A local MCP server that lets any agent shop the Twilio Merch Store demo — an ecommerce store that publishes its capabilities to agents over WebMCP, gated by an agent credential the account holder grants and revokes in Authy.
your MCP client ──stdio──▶ merch-store-mcp ──CDP──▶ Chrome ──▶ the store's own toolsWhy this exists
The store's tools are registered by the page, in a browser tab. That is the whole point of WebMCP — capabilities travel with the site, not with a separate server — and it is also why you cannot just point an MCP client at a URL. There is no server to point at, and as of August 2026 no mainstream agent speaks WebMCP anyway.
So this attaches to Chrome over the DevTools Protocol, reads the tools the page registered, and republishes them over stdio MCP under their real names.
It never reimplements a tool. Every call is dispatched to the page's own implementation, so an agent and a person clicking the UI take the same code path and cannot drift apart. You can watch it happen: the store logs every call in its own console panel while your agent works.
Related MCP server: kilogent-browser
Setup
Needs Node 20+ and Google Chrome. Nothing else — no clone, and you do not need the store's source.
Claude Code
claude mcp add merch-store -- npx -y github:kmorope/merch-store-mcpClaude Desktop, Cursor, and anything else reading a JSON config
{
"mcpServers": {
"merch-store": {
"command": "npx",
"args": ["-y", "github:kmorope/merch-store-mcp"]
}
}
}Then ask your agent for store_status. It reports the connected page, the tool
count, and which WebMCP path is in use.
Chrome is started for you on first use, in a profile of its own at
~/.merch-store-chrome, with the store already open. If a Chrome is already
listening on the DevTools port, the bridge attaches to that instead.
From a clone, if you want to change it
git clone https://github.com/kmorope/merch-store-mcp
cd merch-store-mcp && npm install
npm run smoke # end-to-end check over real stdio MCP, ~15sPoint your client at node /absolute/path/to/merch-store-mcp/server.mjs. Use an
absolute path — these clients do not run servers from your project
directory, so a relative one resolves against something you did not choose.
Serving it over HTTP, for a tunnel
There is also an HTTP mode, for clients that cannot spawn a process — which in practice means putting this behind a tunnel so nobody installs anything at all.
node server.mjs --http --port 7331 # prints a bearer token
ngrok http 7331 # in another terminalclaude mcp add --transport http merch-store https://<your-host>/mcp \
--header "Authorization: Bearer <token>"npm run smoke:http covers this path: token refused when absent or wrong, the
full tool surface over Streamable HTTP, a real call reaching the page, and two
clients getting two sessions.
Read this before you expose it. The bridge drives a browser, so one instance
behind a tunnel means everyone drives the same Chrome on the host machine:
one shared cart, one shared page, interleaved tool calls — one client's
set_filters changes what another's get_page_state returns. There is a test
asserting exactly that, because it is behaviour to know about, not a bug to fix.
It is right for a demo one person drives while others watch, and wrong for
people exploring in parallel. For that, each person runs their own copy over
stdio — the npx line above.
A bearer token is generated when you do not pass one, because anyone who can
reach the endpoint can drive a real browser on your machine. --no-auth exists
for localhost and should never meet a tunnel. Sessions are capped at 32 and
reaped after 30 minutes idle, since a client that vanishes without saying
goodbye would otherwise leave its session behind forever.
What your agent gets
Every tool the page registers — currently 19, including get_page_state,
search_products, add_to_cart, checkout, present_credential,
get_purchase_attempts and join_drop — plus three of the bridge's own:
Tool | Purpose |
| Connected page, tool count, and whether native WebMCP is live |
| Navigate the connected page to a store path |
| Read the store's live call log, to confirm what really happened |
The authoritative list, with schemas and the error contract, is published by the
store itself at
/.well-known/mcp.json,
and the store's own /docs page
documents the flows.
How the store expects an agent to behave
Call
get_page_statebefore deciding anything.Treat structured errors as instructions, not failures — each one names the next move.
402 identity_requiredmeans callpresent_credential.Stop on
approval_required,credential_revoked,rate_limited,ai_disabledandbackend_unreachable. Retrying is wrong in all five.Never report a purchase as complete while it is waiting on a human. Read
get_purchase_attemptsand say what is pending.
There is deliberately no tool to approve a purchase. That decision belongs to the account holder's phone, and an agent that could answer its own request would make the demo meaningless.
Options
Flag | Environment | Default |
|
|
|
|
|
|
|
| launching enabled |
Point it at a store running on your own machine with
--url http://localhost:5173.
Real WebMCP, optionally
The bridge works whether or not the browser API exists, because it calls the
page's tool functions either way. To exercise the genuine standard, open
chrome://flags/#enable-webmcp-testing in the ~/.merch-store-chrome profile,
set it to Enabled, and restart Chrome. store_status then reports
nativeWebMcp: true.
Two things worth knowing
The debug profile is separate on purpose. --remote-debugging-port lets any
local process read and drive every tab in that browser. Pointing it at your
everyday Chrome would hand your logged-in sessions to anything running on your
machine. This profile only ever has the demo in it — keep it that way.
Writes need a moment to land. A tool call schedules a UI update that has not committed the instant the call resolves. The page waits two animation frames before returning, so back-to-back calls through this bridge are safe; if you drive the page by other means, wait yourself.
Troubleshooting
"never published a tool registry" — the store is not up at that URL, or you
are pointed at a different site on that host. Open the URL in a browser first. A
production build of the store only exposes its registry with ?agent=1, which
the bridge adds for you.
"Chrome was started but never answered" — an already-running Chrome from your
normal profile can swallow the launch. Quit it, or start the debug profile by
hand and use --no-launch.
The backend is unreachable — you will see a red banner in the store itself. Spending limits, purchase attempts and approvals live on the Authy backend and nothing is cached, so the store would rather say nothing than show a stale answer. That is the demo's backend, not this bridge; ask whoever is running it.
License
MIT
Available Tools
3 toolsstore_openA
Navigate the connected page to a store path, e.g. '/', '/checkout', '/drop', '/docs'. Most journeys do not need this — the page's own navigate_to tool is usually the right one.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path beginning with / |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the burden of describing the effect. 'Navigate the connected page' clearly communicates that this tool changes current page state or location. It also adds caveat about typical usage, which is useful behavioral context, though it does not detail error cases or side effects beyond navigation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core action and examples, and a clear alternative in the second sentence. No wasted words and the guidance is easy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a simple one-parameter tool with full schema coverage and no output schema requirements. The description covers what it does, gives path examples, and flags when it should be avoided, making it complete for the agent's needs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents the only parameter 'path' with 'Path beginning with /', so schema coverage is 100%. The description adds examples, which are helpful, but it does not add substantial semantic meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action: navigating the connected page to a store path, with concrete examples like '/checkout'. It is specific about the verb and resource, but it does not directly differentiate itself from the sibling tools store_status and store_read_log, instead distinguishing from a different page-level navigate_to tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly tells the agent when not to use the tool ('Most journeys do not need this') and names the preferred alternative ('the page's own navigate_to tool is usually the right one'). This gives clear routing guidance with little ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
store_read_logA
Read the store's live tool-call log — the same entries the page shows in its console panel. Use it to confirm what the store actually did before reporting success.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description takes on the transparency burden. It adds meaningful behavior beyond the name by calling the log 'live' and noting it mirrors the console panel entries, which signals freshness and fidelity. It does not enumerate return structure, but that is reasonably inferred from the 'same entries' phrasing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences deliver a definition, a behavioral anchor, and a use-case recommendation with no filler. The core purpose is front-loaded and every phrase earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is sufficient for a zero-parameter read-only tool: it identifies what is returned, the freshness of the data, and the intended workflow. The only minor gap is the absence of explicit return-format details, but the console-panel reference covers this adequately.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4 under the rubric. The description correctly avoids inventing parameter details and instead focuses on what the log contains and when it should be consulted.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Read the store's live tool-call log.' It further clarifies the object by referencing the same entries shown in the console panel, which distinguishes it from sibling tools like store_status and store_open.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use the tool: 'Use it to confirm what the store actually did before reporting success.' It provides clear context for invocation, though it does not name alternatives or exclusion conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
store_statusA
Check the bridge: which page is connected, whether native WebMCP is live in this Chrome, and which store tools are registered. Call this first if anything looks wrong.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It frames the tool as a read-only 'Check' and lists the diagnostic information it surfaces, implying side-effect-free behavior. It stops short of explicitly stating that no state changes or permissions are involved.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two dense sentences with no filler. The first sentence lists exact checks, and the second gives a clear usage directive. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter status tool with no output schema, the description adequately covers what it reports and when to call it. The only minor gap is that it does not describe the format or shape of the returned status result, but this is not essential for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is no parameter semantics for the description to add. Per the rubric, a zero-parameter tool receives a baseline of 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a concrete diagnostic action ('Check the bridge') and enumerates the specific facts it reports: which page is connected, whether native WebMCP is live, and which store tools are registered. This clearly distinguishes it from siblings like store_open and store_read_log.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit trigger condition: 'Call this first if anything looks wrong.' This tells the agent when to use the tool as a triage step, though it does not explicitly discuss when not to use it or name alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v1.0.0- First observed
store_open - First observed
store_read_log - First observed
store_status
TDQS
Scored across 3 tools
Each tool targets a distinct concern: store_status checks connection/bridge health, store_open handles navigation, and store_read_log inspects the execution log. There is no overlap in purpose or ambiguous boundaries between them.
All tools share the store_ prefix and use snake_case, creating a predictable pattern. Minor variation exists between noun-style (store_status) and verb-style (store_open, store_read_log), but the convention is uniform enough for an agent to infer behavior.
Three tools is on the lower end but well-scoped for a lightweight bridge/debugging server. Each tool serves a clear and necessary role, and the count aligns with the server's narrow purpose.
The server covers the core diagnostic workflow: check connection, navigate if needed, and verify via logs. It lacks direct control or configuration tools, but those appear intentionally delegated to the page's own tools, so no significant gaps for its intended use.
Maintenance
Related MCP Connectors
Browser MCP for logged-in tasks. Uses your Chrome — credentials stay local. Zero-token replay.
Host your MCP tool over streamable HTTP in one command.
Hosted real Google Chrome MCP with per-user persistent state. Navigate, click, type, screenshot.
MCP server to assist with JxBrowser development.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceLets any MCP-capable coding agent drive your real, logged-in Chrome through a local MCP server and MV3 extension.5-
- AlicenseNot gradedqualityBmaintenanceMCP server that lets agents drive your real Chrome browser with existing logins and sessions via an outbound-only WebSocket extension. It exposes Playwright-compatible browser tools for navigation, clicking, typing, and snapshots.1Apache 2.0
- AlicenseNot gradedqualityBmaintenanceConnects local stdio MCP servers to an existing Chrome 144+ session, preserving the user's signed-in sessions, cookies, tabs, and extension environment without launching a second browser. It provides tab control, semantic snapshots, screenshots, pointer, keyboard, form selection, scrolling, navigation, and waiting tools.MIT
- FlicenseNot gradedqualityBmaintenanceEnables MCP clients to drive individually named Chrome profiles, providing tools for tabs, navigation, page interaction, screenshots, JavaScript evaluation, console logs, and network inspection over stdio without a TCP port.-