AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Deskclaw

mcp-lelevinson-deskclaw · by Lelevinson

An AI customer-service agent that runs a real (mock) shop over WhatsApp — with hard safety rails. Skills → typed MCP tools → shared data, on OpenClaw.

No reviews yet
0 installs
14 views
0.0% view→install

Install

$ agentstack add mcp-lelevinson-deskclaw

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-lelevinson-deskclaw)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
3mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Deskclaw? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

DeskClaw

An AI customer-service agent that runs a real (mock) shop — with hard safety rails.

Skills → typed tools → shared data. The agent can sell, support, and escalate — but it can't touch money, and it never acts without your "yes".

[](https://github.com/Lelevinson/deskclaw/actions/workflows/ci.yml)


DeskClaw is a personal project exploring a question I find more interesting than "can an LLM chat?": **how do you let an AI agent act on a business — carts, orders, escalations, email — without ever having to trust it blindly?**

The answer built here: a conversational commerce agent for a small skincare brand (Amelya's, the demo store) that customers reach over real WhatsApp or a terminal chat. It recommends products, builds skincare routines, edits carts, places mock orders, intakes returns, and escalates angry or medical conversations to a human — every action flowing through typed MCP tools with preview → confirm → audit consent gates, identity checks bound to the messaging channel, and a hard no-go zone around money. A Next.js storefront and admin panel share the same backend, so what the agent does in chat is instantly visible (and fixable) in the browser.

See it

The storefront — Next.js 15 over the same backend the agent uses

The admin panel — a human works the queues the agent surfaces but never acts on

/routines — deterministic web routine builder, faithful to the brand's compatibility data

Product detail — live stock straight from the shared store

And the agent side — a real exchange over WhatsApp (the routine concierge chaining catalog search → compatibility rules → stock → budget in one ask):

> Customer: Can you put together a simple skincare routine for dry skin, under NT$2000? > > Agent: Here's a simple dry-skin routine under NT$2000 — AM: Cloud Cleanser NT$420, Calm Barrier Cream NT$680, Sunny Shield SPF50 NT$520 (last step) · PM: Cloud Cleanser, Calm Barrier Cream. Total NT$1,620, within your budget. I skipped the Night Repair Oil because it's currently out of stock. > > Customer: Yes, add the whole routine to my cart. > > Agent: I can add the full bundle: 1 × Cloud Cleanser NT$420, 1 × Calm Barrier Cream NT$680, 1 × Sunny Shield SPF50 NT$520 — NT$1,620. Please confirm: should I add all 3 items to your cart? > > Customer: Yes, confirm. > > Agent: Done — all three are in your cart. (three previews staged, three confirms committed, six audit-log entries written)

Every line of that is grounded: the prices come from the catalog, the AM/PM ordering from the brand's compatibility file, the out-of-stock honesty from live stock — and nothing entered the cart until the explicit "yes".

What the agent can do

10 skills drive the behavior, each a markdown contract over 29 typed MCP tools:

| | Skill | What it does | |---|---|---| | 🛍️ | search-products | Recommends from the catalog by need, budget, skin type — only real products | | 🧴 | routine-concierge | One ask → full AM/PM regimen → offers the bundle to cart (multi-tool chaining) | | 📋 | policy-oracle | Shipping/returns/FAQ + product-compatibility answers, strictly from brand data | | 🛒 | cart-actions | Add / remove / change quantity — every mutation preview → confirm → audit | | 💳 | checkout | Cart → mock order (stock decremented, cart cleared, no payment exists) | | 📦 | order-status | "Where's my order?" — identity-gated, own orders only | | ↩️ | returns-actions | Return requests + refund status reads — never issues the refund itself | | 🙋 | account-registration | Self-service signup / account linking from chat, bound to the channel identity | | 🚨 | sentiment-router | Classifies frustration & safety language, files durable escalation records | | 📨 | ops-digest | Proactive: a schedule wakes the agent with no human prompt; it inspects the store and emails the owner a morning ops digest it composes itself |

Plus the human side: when the agent escalates or an order is placed, the owner gets a real email (Resend), opens the admin panel, and resolves the handoff / advances the order / restocks — closing the loop the agent opened.

The interesting part: the safety model

Anyone can wire an LLM to tools. The design work here is in what the agent can't do:

sequenceDiagram
    participant C as Customer (WhatsApp)
    participant A as Agent (LLM + skills)
    participant T as Typed MCP tools
    participant S as Shared store

    C->>A: "add the cream to my cart"
    A->>T: shop_cart_preview_add_item
    T->>S: stage pending action (TTL'd) + audit log
    T-->>A: quoted preview — product, qty, price
    A->>C: "1 × Calm Barrier Cream, NT$680 — confirm?"
    C->>A: "yes"
    A->>T: shop_cart_confirm_add_item
    T->>S: re-validate stock → commit + audit log
    T-->>A: cart state (from the tool, never invented)
  • Preview → confirm → audit, structurally. Mutations are two separate tools. The preview stages a server-side pending action; the confirm re-validates (ownership, expiry, stock) and writes an audit log either way. The agent cannot skip the gate, because no single tool both decides and acts.
  • Identity comes from the channel, never the customer's words. Your WhatsApp number resolves through an account-links table; typing someone's account id proves nothing. Unlinked senders get routed to registration, not served.
  • A hard no-go zone. No refunds, no cancellations, no address changes, no payment — researched as the top agent-abuse surfaces and excluded by construction (the tools don't exist). The agent intakes and hands off; humans move money.
  • Answer only from data. Products, prices, policies, and ingredient-compatibility all come from versioned data files. The skills treat "not in the data" as "say it's not covered", and the medical/allergy/pregnancy boundary escalates to a human instead of answering — every escalation a durable, queryable record.
  • Owner-only outbound. The email tool has no recipient parameterto is always the owner from env. A prompt-injected "email this customer" is structurally impossible.
  • Proactive ≠ more authority. The scheduled ops digest reads ops data and notifies the owner. Same rails, zero new write paths.

Architecture

flowchart LR
    WA[WhatsApp] --> GW
    TUI[OpenClaw TUI] --> GW
    CRON[cron / manual trigger] -->|no human prompt| GW

    GW[OpenClaw Gateway] --> AG["LLM agent10 skills (markdown contracts)"]
    AG -->|29 typed MCP tools| SVC["src/shop service layer(identity · preview/confirm · audit)"]
    SVC --> DB[("shared JSON storecatalog · carts · orders · returnshandoffs · notifications · audit logs")]
    SVC -->|owner-only| MAIL[Resend → owner's inbox]

    WEB["Next.js storefront + /admin(server-side reuse layer)"] --> SVC
    DB -. same state, two surfaces .- WEB

Three layers keep new capabilities cheap: a skill (what to do, in markdown) calls typed tools (how it's allowed to happen, in TypeScript) over shared data (what's true, in versioned files). The storefront doesn't reimplement shop logic — it imports the same service layer server-side, so chat and web literally cannot disagree about state.

How it's tested

Two eval layers, because an agent has two failure modes — wrong code and wrong judgment:

  • npm run shop:eval — 97 deterministic assertions over the service layer: identity gating, ownership isolation (no existence leaks), preview/confirm contracts, double-confirm and expiry refusals, stock re-validation, audit-log writes, bundle-add invariants, cross-channel account linking, owner-only email with dedupe. Runs in CI on every push.
  • npm run agent:eval — 14 model-in-the-loop cases driving the real LLM through the gateway: does it route to the right skill, answer only from data, refuse to invent carriers, create the handoff record on a pregnancy question, preview-then-confirm a bundle, and stay quiet about upsells when the customer is angry? Rule-based assertions (tool calls made, store deltas, reply regexes) — no LLM judge.

This split caught real bugs: a race where parallel bundle previews clobbered each other in the JSON store (fixed by serializing tool execution in the MCP server), and a persona tweak that made the agent verbally promise escalation without filing the record.

Run it yourself

The project is devcontainer-first — Docker + VS Code is the whole setup story.

# 1. Clone, copy .env.example → .env, open in VS Code → "Reopen in Container"
# 2. One-time OpenClaw config (models, skills dir, shop MCP server):
#    follow docs/openclaw/setup.md §2–§4
npm install && npm run build
npm run shop:reset       # seed the demo shop
openclaw gateway         # start the agent gateway (one terminal)
openclaw tui             # chat with the agent (another terminal)

cd web && npm install && npm run dev   # storefront on :3000

Demo logins: customer lin / amelya-demo · admin admin / amelya-admin. Model options (local Ollama or gpt-5.5 via the Codex provider), WhatsApp connection, and troubleshooting all live in [docs/openclaw/setup.md](docs/openclaw/setup.md). Scenario scripts to try every skill: [skills-lab/scenarios/](skills-lab/scenarios/).

Repository map

README.md                 # you are here
ARCHITECTURE.md           # scope, stack, status, resolved decisions — the source of truth
AGENTS.md                 # contributor rules + topic→file map
skills/                   # the 10 agent skills (markdown contracts) — canonical
src/shop/                 # service layer: identity, preview/confirm, audit, notify
src/mcp/shop-server.ts    # the 29 typed MCP tools (serialized execution)
src/cli/                  # shop-eval, agent-eval, ops-digest trigger
data/                     # catalog, policies, compatibility, customers, shop state
web/                      # Next.js storefront + /admin (server-side reuse of src/shop)
skills-lab/               # per-skill demo scenarios with pass/fail criteria
docs/                     # setup, planning history, assets

| You want to know… | Open | |---|---| | What's in scope, the stack, what's done | [ARCHITECTURE.md](ARCHITECTURE.md) | | How the storefront reuses the backend | [web/README.md](web/README.md) | | What each skill does | [skills/README.md](skills/README.md) | | OpenClaw install / config / commands / fixes | [docs/openclaw/setup.md](docs/openclaw/setup.md) | | How to demo every skill | [skills-lab/README.md](skills-lab/README.md) | | How to work in this repo | [AGENTS.md](AGENTS.md) |

Stack

TypeScript (strict, ESM) · OpenClaw (agent runtime, gateway, WhatsApp channel) · MCP (@modelcontextprotocol/sdk) · Next.js 15 + Tailwind + shadcn/ui · Resend (owner email) · a deliberately boring JSON file store · Puppeteer (visual review tooling) · GitHub Actions CI. Models: gpt-5.5 via the Codex provider, or local Ollama.

Honest limitations

This is a prototype that takes its boundaries seriously, not a production system:

  • Account linking is demo-grade. Linking an existing account uses a per-account code as an OTP stand-in; there's no real out-of-band verification.
  • "Proactive" is local-first. The scheduled digest fires while the machine and gateway are up — there is no always-on server.
  • The JSON store is single-machine. Tool execution is serialized in-process; it's not a database and doesn't pretend to be.
  • Model-in-the-loop evals are not deterministic. A case can flake; the deterministic layer is the gate, the agent layer is the smoke alarm.
  • The agent's voice is machine-local. Conduct rules ship in skills/; the persona (a warm, dash-averse "Amelya's customer care" tone) lives in OpenClaw's workspace files (SOUL.md / IDENTITY.md). The canonical copy is in [docs/persona.md](docs/persona.md) so the voice is reproducible from the repo.

Credits

Built by @Lelevinson, @carleneamelya, and @fkilr50 as a hands-on study of AI-agent design. Developed with Claude Code and run on OpenClaw. Product photography and the DeskClaw mascot are AI-generated for this demo; Amelya's is a fictional brand.

Licensed under the [MIT License](LICENSE).

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.