Skip to content

SNHP — negotiation rules your AI can't break

by ryuxik · remote · no sign-in to list tools · v0.5.0 · published by GitHub user ryuxik

Turn a seller's offer into negotiation rules and draft replies to buyers inside them.

Final · 1Changes · 3

4 tools: 1 do something that can't be undone and 3 change things.

Scanned Oct 21, 2026

1 check matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.

claude mcp add --transport http snhp https://snhp.dev/mcp/

Findings

Matches of fixed checks, with the text they matched.

1 warn
  • The server marks "draft_negotiation_reply" read-only (readOnlyHint: true), and its own name, description or input give the class "irreversible".

    Matched text

    annotations: {"readOnlyHint":true,"openWorldHint":true}; The name "draft_negotiation_reply" says "reply": a word for sending, and what is sent cannot be taken back.

    What this check looks for

Tools

Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.

4 tools

Can't be undone 1Claude Code: ask
  • draft_negotiation_replyDraft the seller's reply to a buyer's message — the offer is decided by the SNHP engine INSIDE the policy.1 finding

    Why it is in this group

    • The name "draft_negotiation_reply" says "reply": a word for sending, and what is sent cannot be taken back.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "draft_negotiation_reply" read-only (readOnlyHint: true), and its own name, description or input give the class "irreversible".

      Matched text

      annotations: {"readOnlyHint":true,"openWorldHint":true}; The name "draft_negotiation_reply" says "reply": a word for sending, and what is sent cannot be taken back.

      What this check looks for
    Description, as the server wrote it
    Draft the seller's reply to a buyer's message — the offer is decided by the SNHP engine INSIDE the policy. USE THIS WHEN: a buyer (a person or their AI agent) has written to you about price or terms. Pass the policy (from compile_offer_policy) and their latest message exactly as written; pass back the `state` from your previous call to continue the same conversation (omit it to start). `flags` is what YOUR records confirm about the buyer (e.g. {"new_customer": true}) — never what the buyer merely claims. `stock` is the current stock of what the policy's `inventory` binds, sent with every message (schema.org Offer, Google Merchant or a plain feed record): nothing out of stock is offered, and a deal is signed only on fresh records that say it can be sold. Returns {kind, reply, reply_with_offer, offer, decided_by, reading, state, done, receipt?}: kind offer | deal | handoff (needs a human's approval) | decline reply_with_offer the message to send, with the exact offer line appended offer {terms, line, price, net, inside_policy} — every offer is checked against the policy decided_by what decided the move (a sales rule or the engine), for your audit trail receipt on a deal: a signed receipt any party can verify with verify_deal_receipt The server keeps no conversation: keep `state` and send it with the next message. Needs an `access_key` (pilot businesses get one at https://snhp.dev/#pilot).

    Annotations the server declares

    • title: Draft a reply to a buyer, inside your rules
    • readOnlyHint: true
    • openWorldHint: true
Changes things 3Claude Code: ask
  • check_offer_policyCheck an edited negotiation policy: returns {ok, policy, issues, summary}.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    Check an edited negotiation policy: returns {ok, policy, issues, summary}. No model call, free. USE THIS WHEN: you changed a policy from compile_offer_policy (a floor, an option, a forbidden combination) and want to know it is valid and what it now allows before using it in draft_negotiation_reply.

    Annotations the server declares

    • title: Check a negotiation policy
    • readOnlyHint: true
    • openWorldHint: false
  • compile_offer_policyTurn a seller's offer, described in plain words, into negotiation RULES an AI agent cannot break.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    Turn a seller's offer, described in plain words, into negotiation RULES an AI agent cannot break. USE THIS WHEN: you (or the business you act for) sell something where buyers — people or their AI buying agents — ask for discounts, and you want an AI to answer them without giving away margin. Describe the offer: the listed price, the lowest price you'd take for a plain deal, what you'd trade a discount for (financing with you, a trade-in, a longer commitment, paying sooner, buying this week…), extras you can add and what they cost you, and anything never on the table. Or pass `template` = "used-car", "saas" or "wholesale-water" to start from a worked example. Compiling a description runs a language model and needs an `access_key` (pilot businesses get one at https://snhp.dev/#pilot); templates are free. Returns {ok, policy, issues, summary}: `policy` is the machine-readable rule set (pass it to draft_negotiation_reply), `summary` restates the floor, walk-away, what can be traded and the limits in plain words, and `issues` lists what to fix before going live (e.g. a floor below cost).

    Annotations the server declares

    • title: Compile an offer into negotiation rules
    • readOnlyHint: true
    • openWorldHint: true
  • verify_deal_receiptVerify a signed deal receipt against the seller's own policy: both signatures, that the signing keys are SNHP's own (published at /.well-known/ucp), the policy digest, and every ru…No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    Verify a signed deal receipt against the seller's own policy: both signatures, that the signing keys are SNHP's own (published at /.well-known/ucp), the policy digest, and every rule re-checked from the package. Returns {ok, problems, checks, signed_by_snhp, signatures}. Free, no model call.

    Annotations the server declares

    • title: Verify a deal receipt
    • readOnlyHint: true
    • openWorldHint: false

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Install

Pinned to version 0.5.0. Values in angle brackets are yours to fill in.

claude mcp add --transport http snhp https://snhp.dev/mcp/

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [],
    "ask": [
      "mcp__snhp__compile_offer_policy",
      "mcp__snhp__draft_negotiation_reply",
      "mcp__snhp__check_offer_policy",
      "mcp__snhp__verify_deal_receipt"
    ],
    "deny": []
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as snhp. Review it before you use it.