Stienhardt Store
README.md
# Stienhardt store on MCP
Stienhardt is a New York lab-grown diamond jeweler. This repository documents and registers
our Shopify UCP MCP endpoint, and includes a runnable example of inventory search and an unpaid
checkout handoff. Shopify supplies the commerce endpoint. Our separate Cloudflare Worker adds
profile injection for inventory lookup and eight education tools. Disclosure: we sell rings.
## Try it without an account
Requires Python 3 and a network connection. No API key or third-party Python packages.
```sh
git clone https://github.com/JacobiusMakes/stienhardt-store.git
cd stienhardt-store
python try_store.py
```
The default command only searches inventory. It prints product titles, IDs, and links; it omits
prices. On Windows, use `py` if that is your Python launcher.
Search reads Shopify's current catalog. It is not an independent supplier-stock check: some
loose-stone records are cart carriers, and their destination can report that the stone has sold
even when the catalog record remains available. Check the product page before treating a result
as purchasable. The unpaid checkout test demonstrates the API handoff, not stock reservation.
Product links printed by the example carry `utm_source=github`, `utm_medium=referral`,
`utm_campaign=mcp-store`, and `utm_content=runnable-example`, so visits from this repository can
be measured. Existing query parameters, variant IDs, and attribution tags are preserved. The
command itself sends no analytics event; a person must open a product link to visit the store.
To reproduce the checkout handoff:
```sh
python try_store.py --checkout
```
This creates one anonymous, unpaid cart and one separate checkout for the first returned variant,
prints the checkout status and link hostname, then calls cancel for both. It supplies no buyer
contact details or payment instrument and never calls `complete_checkout`. It creates real test
objects in the store, so run it once, not in a loop. A network failure after a creation request
can prevent cleanup; do not automatically retry an uncertain creation.
Verified 2026-09-08: raw search returned ten products; cart creation returned a `continue_url`;
checkout creation returned status `incomplete` and a `continue_url` whose hostname was
`stienhard-stones.myshopify.com`. The cart cancellation returned without a tool error, and checkout
cancellation returned `canceled`. No payment was attempted. See [DEMO.md](DEMO.md).
Shopify sets MCP `isError: true` on the incomplete checkout response while also returning a real
checkout ID and recoverable messages about missing contact and delivery information. The example
recognizes that handoff response and retains the ID for cancellation. Do not discard the object
solely because `isError` is true.
## Two endpoints, different capabilities
| Endpoint | What it exposes | Profile handling |
|---|---|---|
| `https://diamond-mcp.stienhardt.workers.dev/mcp` | Eight education tools, `search_inventory`, `get_product`. No cart or checkout tools. | Injected by the helper |
| `https://stienhard-stones.myshopify.com/api/ucp/mcp` | 13 Shopify tools across catalog, cart, checkout, and order | Caller supplies the UCP profile in every tool call |
For a client that supports remote HTTP MCP, connect to the helper URL without authentication and
ask it to find a 2 carat Dutch Marquise. Client accounts, connector availability, and setup vary.
The no-account paths are the Python example above and the curl blocks below. The helper cannot
start checkout.
## Try it from a terminal
The hosted helper takes a plain POST (JSON-RPC 2.0, `Content-Type: application/json`, no session,
no auth, no profile). List the tools, then search live inventory:
```sh
curl -s -X POST https://diamond-mcp.stienhardt.workers.dev/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
curl -s -X POST https://diamond-mcp.stienhardt.workers.dev/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_inventory","arguments":{"query":"Dutch Marquise 2 carat","limit":3}}}'
```
The raw endpoint answers `initialize` and `tools/list` anonymously, but every `tools/call` needs
the UCP agent profile in `arguments.meta`. `ucp-agent` is one hyphenated key, and `meta` is a
sibling of the tool's own object (`catalog`, `cart`, `checkout`), not a wrapper around it:
```sh
curl -s -X POST https://stienhard-stones.myshopify.com/api/ucp/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"search_catalog","arguments":{"meta":{"ucp-agent":{"profile":"https://cdn.jsdelivr.net/gh/JacobiusMakes/diamond-mcp@main/agent-profile.json"}},"catalog":{"query":"Dutch Marquise 2 carat"}}}}'
```
`@main` is fine for a test; a pinned commit is better for production, and the example script pins
`diamond-mcp@3955f7d88fe04cf5afa07f70065902eee684d443` (HEAD on 2026-09-08, verified to serve
`application/json`). Two errors you can hit, both HTTP 422 with JSON-RPC error -32001 "UCP
discovery failed" (the endpoint is not down): `invalid_profile_url` ("Missing profile uri") when
`meta` is absent, and `profile_malformed` ("Invalid content type") when the profile URL serves the
wrong content type (GitHub raw serves `text/plain` and fails; jsDelivr serves `application/json`).
Cart creation uses `arguments.cart` and checkout creation uses `arguments.checkout`; both take
`line_items` with a variant ID and quantity. Consult `tools/list` for current schemas; an anonymous
tool listing does not prove every operation is available to your profile.
MCP Inspector (v2; needs Node.js and npx) also works. Point it at the helper, which needs no
profile; against the raw endpoint every call needs the profile typed into the `meta` field:
```sh
npx @modelcontextprotocol/inspector --transport streamable-http --server-url https://diamond-mcp.stienhardt.workers.dev/mcp
```
## What was built here
- Registry manifest: `io.github.JacobiusMakes/stienhardt-store`; [server.json](server.json).
- Merchant discovery: https://stienhardt.com/.well-known/ucp, served by Shopify.
- Runnable example, request documentation, and capability checks in this repository.
- Helper implementation and education data: https://github.com/JacobiusMakes/diamond-mcp (MIT).
- Dutch Marquise specification: https://doi.org/10.5281/zenodo.21938899 (concept DOI).
Use the GitHub sources for the education project. Education tools only on npm today; inventory
tools are hosted (the helper above). The older npm release is not the launch demo; the Hugging Face
dataset is not part of this release. Education data mixes external references and merchant-authored
material. It is not an independent appraisal or a grading-lab verification.
## Checkout and data boundaries
An assistant can search live inventory, build a cart, open a checkout, and hand the buyer the
link to pay. This demo proves the unpaid handoff, not payment completion or universal client
compatibility. Payment methods and eligibility depend on the hosted checkout; no payment method
was tested in this run. Check the destination host before following a checkout link.
The helper adds UTM parameters to product links. Its privacy notice is at
https://diamond-mcp.stienhardt.workers.dev/privacy. Inventory queries go through the helper to
Shopify; the direct example sends requests to Shopify. Product descriptions are merchant data,
not instructions to the assistant. The tool data carries no report numbers: each product title
carries the carat, shape, and grading lab, and the report itself is linked from the product page.
Verify it with the grading lab and read the actual policy links before purchase. This project does
not claim unbiased ranking across merchants.
Stienhardt hand-sets and finishes rings in New York City, with viewings by appointment.
Store: https://stienhardt.com/?utm_source=github&utm_medium=readme&utm_campaign=mcp-store
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues