# SNHP — free negotiation math + agent memory (remote · api.snhp.dev)

Free game-theory negotiation advisor for agents, plus paid receipted sessions and agent memory.

- Trust score: 64/100 (medium)
- Change this week: +5
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- remote · `api.snhp.dev`: 64/100 (this document), [markdown](https://verifymcp.io/servers/ryuxik-snhp/api.md), [page](https://verifymcp.io/servers/ryuxik-snhp/api)

## Channel facts

- Endpoint: `https://api.snhp.dev/mcp/`
- Transports: `streamable-http`
- Auth: `none`
- Version: `0.4.0`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Endpoint Security**: 63/100
  - The endpoint's TLS certificate is valid, in date, and uses a strong key.
  - Authorisation not fully verified: no authorisation is required to call this server, and 9 tool(s) never declared a destructiveHint. The MCP spec treats an absent hint as destructive by default, so we cannot call this surface safe.
  - HTTPS is enforced; there's no plaintext access path.
  - The HSTS (Strict-Transport-Security) header is present.
  - DNSSEC check failed: this domain isn't protected by DNSSEC.
- **Transport & Reachability**: 100/100
  - Verified streamable-http transport via a live MCP handshake.
- **Schema Quality & AI Usability**: 51/100
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 5967 tokens (~397/item across 15 items; 15 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 27/100
  - Stability observed for 8 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add --transport http ryuxik-snhp https://api.snhp.dev/mcp/
```

### Codex

```toml
[mcp_servers.ryuxik-snhp]
url = "https://api.snhp.dev/mcp/"
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ryuxik-snhp": {
      "type": "remote",
      "url": "https://api.snhp.dev/mcp/",
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add ryuxik-snhp --url https://api.snhp.dev/mcp/ --transport streamable-http
```

### Hermes

```yaml
mcp_servers:
  ryuxik-snhp:
    url: "https://api.snhp.dev/mcp/"
```

### Other

```json
{
  "mcpServers": {
    "ryuxik-snhp": {
      "type": "http",
      "url": "https://api.snhp.dev/mcp/"
    }
  }
}
```

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-02 (score 64, +1)

No change was recorded against any check on this day. Stability & Change Management went from 20 to 23. That category is still filling its 30-day observation window: 6 days of observed history at the previous scan, 7 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-07-31 (score 63, +2)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-30 (score 61, 0)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-29 (score 61, +1)

No change was recorded against any check on this day. Stability & Change Management went from 7 to 10. That category is still filling its 30-day observation window: 2 days of observed history at the previous scan, 3 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-07-28 (score 60, +1)

No change was recorded against any check on this day. Stability & Change Management went from 3 to 7. That category is still filling its 30-day observation window: 1 days of observed history at the previous scan, 2 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-07-27 (score 59, 0)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-26 (score 59)

First indexed and scored.

## MCP tools (15)

### `negotiate` (~772 tokens)

Negotiate — your optimal next move

Your math-optimal next move in any price negotiation — free, no account or key needed.

USE THIS WHEN: you're haggling over a single PRICE across multiple back-and-
forth rounds and want a better outcome than winging it. Validated edge: ~12%
better head-to-head (measured on this recommender, n=20 paired LLM
negotiations, 95% CI +6.5-17.4%, p<0.0001). NOT FOR: one-shot or fixed prices
(it'll tell you to just negotiate directly); multi-issue bundles (use
negotiate_bundle — it logrolls across several linked issues); or non-price
decisions like accept-vs-decline a job offer (just reason it through).

You provide only what you already know — no game theory:
  side          "sell" or "buy"
  walk_away     your reservation in dollars (seller=floor/minimum, buyer=ceiling/max)
  target        your aspiration in dollars (seller=high, buyer=low)
  counterparty_offers  their offers so far, in dollars, oldest first
  rounds_left   (optional, default 8) roughly how many back-and-forths remain
  compute_ms    (optional, default 0; EXPERIMENTAL) milliseconds of Monte-Carlo
                rollouts to spend refining the move. 0 = instant closed form.
                Validated to show NO realized edge over the closed form (n=400,
                mc_validation.py) — kept off by default as a research mechanism,
                not a quality improvement. The reply carries a "compute" block

You get back, in dollars:
  {"action": "counter"|"accept"|"walk", "recommended_price": 5387.0,
   "message": "...the best I can do is $5,387.00", "fit": {...},
   "expected_settlement": 4943.5, "confidence": 0.62}

WORKED EXAMPLE — selling a contract, floor $4,000, hope $6,000, the buyer has
bid $4,200 then $4,500:
  negotiate(side="sell", walk_away=4000, target=6000,
            counterparty_offers=[4200, 4500], rounds_left=6)
  \-> counter ~$5,387 with a ready-to-send message; ACCEPT once their bid crosses
     the optimal target; WALK if they stay below your floor near the deadline.

Works against…

Input parameters:

- `compute_ms` (integer): EXPERIMENTAL. Milliseconds of Monte-Carlo rollouts to spend refining the move; 0 = instant closed form (validated to show no realized edge, off by default).
- `counterparty_offers`: The other side's offers so far, in dollars, oldest first. Omit if they haven't offered yet.
- `item` (string): Short label for what's being negotiated (used only in the drafted message).
- `my_previous_offers`: Your own offers so far, in dollars, oldest first (optional context).
- `rounds_left` (integer): Roughly how many back-and-forth rounds remain before the deadline (default 8).
- `side` (string, required): Which side you are: 'sell' or 'buy'.
- `target` (number, required): Your aspiration price in dollars (seller: high; buyer: low).
- `walk_away` (number, required): Your reservation price in dollars — the worst you'd accept (seller: your floor/minimum; buyer: your ceiling/maximum).

Output parameters:

- `action`
- `compute`
- `confidence`
- `error`
- `expected_settlement`
- `fit`
- `message`
- `rationale`
- `recommended_price`

### `negotiate_bundle` (~912 tokens)

Negotiate a bundle — logroll linked issues

Negotiate several linked issues at once by logrolling — free, no account or key needed.

USE THIS WHEN: a deal has more than one issue on the table and they trade off —
a job offer (base + equity + signing), a SaaS contract (price + seats + term +
SLA), any package deal. It concedes on the issues you care about LESS (and the
other side cares about MORE) to win the ones you care about most — a trade that
beats splitting every issue down the middle. For a single PRICE, use
negotiate instead.

Provide `issues`: a list of {"name", "options" (the choices), "my_utility" (how
good each option is to YOU — one number per option, any scale), "their_utility"
(how good each option is to THEM — their preference direction)}. Optionally
\`my_priorities` ({issue_name: weight}, how much each issue matters to you) and
\`their_offers` (their packages so far as {issue_name: option}, oldest first —
this is what lets it INFER their priorities). Returns {action, recommended_offer
(issue -> option), message, my_utility, their_expected_utility,
inferred_their_priorities, trade_logic, fit, confidence, acceptance_probability}.

Validated (separately from the single-issue +12%): returns a Pareto-efficient
package that beats naive "split-every-issue-down-the-middle" bargaining by ~40%
joint surplus (300 random 4-issue profiles). HONEST CAVEAT: the priority
INFERENCE layered on top is weak (recovery r≈0.3) and currently adds only ~1%
(and can be slightly NEGATIVE against some opponents) over the same engine run
with no inference — so the proven value today is the efficient-package search,
not (yet) the logrolling edge.

Optional timing refinement: pass `rounds_left` (bargaining rounds remaining)
with `compute_ms` > 0 to spend that many ms of Monte-Carlo rollouts choosing
WHICH package to hold for as the other side concedes over the rounds — a firmer
package closes later (discounted) than a generous one. 0 = the instant
closed-form package; the reply then carries a `compute` block. Modest by desig…

Input parameters:

- `compute_ms` (integer): EXPERIMENTAL. Milliseconds of rollouts to choose WHICH package to hold as they concede; 0 = instant closed-form package.
- `issues` (array, required): One dict per issue: {name, options (the choices), my_utility (value of each option to YOU), their_utility (value to THEM)} — utilities are one number per option, any scale.
- `my_batna` (number): Your best alternative to no deal, as a utility fraction in [0,1] (default 0.40); the returned package is guaranteed to beat it.
- `my_priorities`: {issue_name: weight} — how much each issue matters to you (any scale). Optional.
- `rounds_left` (integer): Bargaining rounds remaining (used with compute_ms for the timing tier; default 8).
- `their_batna_estimate` (number): Your estimate of the other side's BATNA, [0,1] (default 0.40).
- `their_offers`: Packages the other side has tabled, oldest first, each as {issue_name: chosen_option} — lets it infer their priorities.

Output parameters:

- `acceptance_probability`
- `action`
- `compute`
- `confidence`
- `error`
- `fit`
- `inferred_their_priorities`
- `message`
- `my_utility`
- `recommended_offer`
- `their_expected_utility`
- `trade_logic`

### `score_deal` (~334 tokens)

Score a deal against the Pareto frontier

Score how good a deal is against your floor/target — free, no account or key needed.

Score a settled package against the exact Pareto frontier — the SNHP
leaderboard metric ("dollars left on the table") for YOUR negotiation.

Args:
    issues: one dict per issue: {"name": str, "options": [labels],
        "my_utility": [per-option value to me], "their_utility":
        [per-option value to them]} — both sides' TRUE per-option values.
    my_weights: {issue_name: weight} — my true priorities (any scale).
    their_weights: {issue_name: weight} — their true priorities.
    package: the settled deal, {issue_name: option_label}.
    notional: deal size in dollars for the dollars-left framing.

Returns realized joint welfare, the frontier best, the naive middle-split
baseline, frontier capture, logroll capture, and dollars_left_on_table.

Input parameters:

- `issues` (array, required): One dict per issue: {name, options, my_utility, their_utility} — both sides' TRUE per-option values (one number per option).
- `my_weights` (object, required): {issue_name: weight} — your true priorities (any scale).
- `notional` (number): Deal size in dollars, used for the 'dollars left on the table' framing (default 10000).
- `package` (object, required): The settled deal as {issue_name: chosen_option_label}.
- `their_weights` (object, required): {issue_name: weight} — their true priorities (any scale).

Output parameters:

- `dollars_left_on_table`
- `error`
- `frontier_best`
- `frontier_capture`
- `joint_welfare`
- `logroll_capture`
- `my_utility`
- `naive_split`
- `their_utility`

### `auction_bid` (~485 tokens)

Optimal auction bid

The optimal bid when you're bidding in an auction — free, no account or key needed.

USE THIS WHEN: you're a bidder and want the bid that maximizes your expected
surplus without overpaying. NOT for running an auction (use
auction_reserve) or 1:1 haggling (use negotiate).

Provide: auction_format ("first_price" sealed bid, "second_price_vickrey",
or "english_ascending"); my_valuation (what the item is worth to YOU, in $);
n_competing_bidders (how many OTHER bidders, not counting you); and
competitor_value_prior — a rough model of what rivals will pay, e.g.
{"family":"uniform","params":{"low":0,"high":6000}} (or
{"family":"lognorm","params":{"mu":8.5,"sigma":0.4}}). Estimate it if unknown.
Returns {optimal_bid, expected_surplus, win_probability, dominant_strategy,
rationale} — bid and surplus in the SAME $ you passed in.

Example: a domain worth $5,000 to you, 4 rivals who'd pay up to ~$6,000, in a
sealed first-price auction -> auction_bid(auction_format="first_price",
my_valuation=5000, n_competing_bidders=4,
competitor_value_prior={"family":"uniform","params":{"low":0,"high":6000}})
\-> optimal_bid ~$4,000, win_probability ~0.48.

Input parameters:

- `auction_format` (string, required): 'first_price' (sealed), 'second_price_vickrey', or 'english_ascending'.
- `competitor_value_prior` (object, required): Rough model of what rivals will pay, e.g. {family:'uniform', params:{low:0, high:6000}} or {family:'lognorm', params:{mu:8.5, sigma:0.4}}.
- `my_valuation` (number, required): What the item is worth to YOU, in dollars.
- `n_competing_bidders` (integer, required): How many OTHER bidders there are (not counting you).
- `reserve_price`: The auction's reserve/minimum bid in dollars, if any (optional).
- `risk_aversion` (number): Your risk aversion; 1.0 = risk-neutral (default 1.0).

Output parameters:

- `dominant_strategy`
- `error`
- `expected_surplus`
- `optimal_bid`
- `rationale`
- `win_probability`

### `auction_reserve` (~292 tokens)

Revenue-optimal reserve price

The revenue-optimal reserve price when you're selling — free, no account or key needed.

USE THIS WHEN: you're running an auction or sale with multiple bidders and need
the floor price (minimum bid you'll accept) that maximizes your expected
revenue. NOT for one-on-one haggling (use negotiate for that).

Provide: n_bidders (how many bidders), seller_valuation (what the item is worth
to YOU, in $), and bidder_value_prior — a rough model of what bidders will pay,
e.g. {"family":"uniform","params":{"low":2000,"high":8000}}. Estimate it if
unknown. Returns the reserve price and expected revenue.

Example: a painting, ~5 bidders, worth $1,000 to you, bidders likely pay
$2,000–$8,000 -> auction_reserve(n_bidders=5, seller_valuation=1000,
bidder_value_prior={"family":"uniform","params":{"low":2000,"high":8000}}).

Input parameters:

- `bidder_value_prior` (object, required): Rough model of what bidders will pay, e.g. {family:'uniform', params:{low:2000, high:8000}}.
- `n_bidders` (integer, required): How many bidders you expect.
- `seller_valuation` (number, required): What the item is worth to YOU, in dollars (your floor).

Output parameters:

- `error`
- `expected_efficiency_loss`
- `expected_revenue`
- `expected_revenue_no_reserve`
- `rationale`
- `reserve_price`

### `clearance_price` (~451 tokens)

Clearance price & markdown schedule

Best price plus markdown schedule to clear stock by a deadline — free, no account or key needed.

USE THIS WHEN: you must sell a FIXED number of units before a cutoff and
demand arrives over time — event tickets, perishable inventory, end-of-life
stock. NOT for 1:1 haggling (negotiate) or auctions (auction_bid/reserve).

Provide: inventory (units to sell); horizon_seconds (selling window in
SECONDS — 14 days = 14*24*3600 = 1209600); arrival_rate_per_second (expected
shoppers per second = expected total shoppers / horizon_seconds); and
buyer_arrival_prior — a rough model of willingness-to-pay, e.g.
{"family":"uniform","params":{"low":40,"high":150}}. Returns {static_price
(one good fixed price), static_expected_revenue, dynamic_schedule (list of
{t_seconds, recommended_price} markdown waypoints), sellthrough_rate,
rationale} — all prices in the SAME $ as your prior.

Example: 200 tickets, 14-day window, ~600 shoppers willing to pay $40-$150 ->
clearance_price(inventory=200, horizon_seconds=1209600,
arrival_rate_per_second=600/1209600,
buyer_arrival_prior={"family":"uniform","params":{"low":40,"high":150}})
\-> static_price ~$112, schedule marks down $114 -> ~$76 as the deadline nears.

Input parameters:

- `arrival_rate_per_second` (number, required): Expected shoppers per SECOND (= expected total shoppers / horizon_seconds).
- `buyer_arrival_prior` (object, required): Rough model of buyer willingness-to-pay, e.g. {family:'uniform', params:{low:40, high:150}}.
- `horizon_seconds` (number, required): Selling window in SECONDS (14 days = 14*24*3600 = 1209600).
- `inventory` (integer, required): Number of units you must sell before the cutoff.
- `n_simulations` (integer): Monte-Carlo sample count for the estimate (default 2000).
- `seed` (integer): RNG seed for reproducibility (default 42).

Output parameters:

- `dynamic_schedule`
- `dynamic_value_estimate`
- `error`
- `rationale`
- `sellthrough_rate`
- `static_expected_revenue`
- `static_price`
- `static_simulated_revenue`

### `stable_match` (~340 tokens)

Stable matching (Gale–Shapley)

Match two groups by their rankings so no pair wants to swap — free, no account or key needed.

A STABLE matching: USE THIS WHEN you're assigning two sides to each other by
mutual preference — interns<->teams, students<->schools, mentors<->mentees —
and want a result with no "blocking pair" (no person+slot that both prefer
each other over what they got).

Provide proposers and receivers, each a list of {"id": name,
"preferences": [ids of the OTHER side, most-wanted first]}. Receivers may add
"capacity" (default 1) to accept several. Returns {matching (name -> name),
unmatched_proposers, blocking_pairs (empty list = provably stable),
n_proposals}. NOTE: the result is PROPOSER-optimal, so put the side you want
to favor in `proposers`.

Example: stable_match(
    proposers=[{"id":"Ana","preferences":["Growth","Core"]},
               {"id":"Ben","preferences":["Core","Growth"]}],
    receivers=[{"id":"Growth","preferences":["Ben","Ana"]},
               {"id":"Core","preferences":["Ana","Ben"]}])
\-> matching {"Ana":"Growth","Ben":"Core"}, blocking_pairs [].

Input parameters:

- `proposers` (array, required): List of {id, preferences:[ids of the OTHER side, most-wanted first]}. The result is PROPOSER-optimal — put the side you want to favor here.
- `receivers` (array, required): List of {id, preferences:[...], capacity (optional, default 1)}.

Output parameters:

- `blocking_pairs`
- `error`
- `matching`
- `n_proposals`
- `unmatched_proposers`

### `memory_save` (~279 tokens)

Save agent memory (blind locker)

Persistent memory for your agent across sessions — save now, load in any later session.

You encrypt before saving; the store holds only ciphertext (blind custody)
and signs a receipt over its hash — it cannot read your memory.

Saving uses your prepaid wallet; a new key's 50¢ starter credit covers
your first saves, and loading it back (memory_load) is free. `blob_b64`
is YOUR ciphertext as base64 — encrypt BEFORE saving; keys never transit,
contents are never logged, so a breach leaks only sealed boxes. Charged a
thin flat fee ONLY on durable store (empty/oversize/unencodable is
uncharged). ttl_seconds is clamped to [60s, 7d] and the effective
expires_at is returned. The receipt's content_hash is over YOUR
ciphertext, so you can prove what you stored without the store ever seeing
plaintext.

Input parameters:

- `api_key` (string, required): Your SNHP API key (a new key's 50c starter credit covers first saves).
- `blob_b64` (string, required): YOUR ciphertext as base64 — encrypt BEFORE saving; the store holds only the sealed box and cannot read it.
- `ttl_seconds`: How long to keep it, clamped to [60s, 7 days]; the effective expiry is returned (optional).

Output parameters:

- `charged`
- `code`
- `error`
- `expires_at`
- `ok`
- `price_millicents`
- `reason`
- `receipt`
- `size_bytes`
- `ticket`
- `ticket_hash`

### `memory_load` (~148 tokens)

Load agent memory

Load a memory you saved in an earlier session — retrieval is free.

Get back an encrypted blob you parked earlier (the blind locker) by its
claim `ticket`. Returns {ok, blob_b64, size_bytes, expires_at} — the
ciphertext you saved, which only YOU can decrypt. A wrong owner reads as a
missing ticket; an expired TTL is `expired`; a lost at-rest key is
\`at_rest_key_unavailable`. Free (the save settled it).

Input parameters:

- `api_key` (string, required): The same SNHP API key you saved under (a different owner reads as a missing ticket).
- `ticket` (string, required): The claim ticket returned by memory_save.

Output parameters:

- `blob_b64`
- `charged`
- `code`
- `error`
- `expires_at`
- `ok`
- `reason`
- `size_bytes`

### `session_open` (~364 tokens)

Open a $2 receipted session

Open a $2 receipted negotiation session: deterministic, replayable, every move signed.

PAID ($2 once, from your credit balance) — the $2 covers EVERY move of
this negotiation (up to 10 moves, 7 days), tuned to the category. A new
key's 50¢ starter credit is a taste, not enough for a session — top up
first. category: resale | supply | retail. side: buy | sell.
walk_away = your true floor (sell) / ceiling (buy) — private,
never crossed. Pass their_offers to get the first move back
immediately with the session. Subsequent moves: session_advise
with the session_id — no further charge.

Input parameters:

- `api_key` (string, required): Your SNHP API key; $2 is debited from its credit balance (covers every move of this one negotiation).
- `category` (string, required): Negotiation category for tuning: 'resale' | 'supply' | 'retail'.
- `my_offers`: Your own offers so far, in dollars, oldest first (optional).
- `rounds_left`: Bargaining rounds remaining for this move (optional; overrides the category default).
- `seed` (integer): RNG seed for the deterministic engine (default 0).
- `side` (string, required): Which side you're on: 'buy' or 'sell'.
- `target` (number, required): Your aspiration price in dollars.
- `their_offers`: The other side's offers so far, in dollars, oldest first — pass to get the first move back with the session (optional).
- `walk_away` (number, required): Your true reservation in dollars — floor (sell) / ceiling (buy); private, never crossed.

Output parameters:

- `balance_after`
- `category`
- `context_hash`
- `error`
- `expires_at`
- `first_move`
- `first_move_error`
- `funding`
- `how_to_pay`
- `max_moves`
- `price_cents`
- `price_millicents`
- `receipt`
- `session_id`
- `side`

### `session_advise` (~157 tokens)

Session move — next single-price offer

Your next move inside a receipted session (single-issue) — no additional charge (the $2 at session_open covered it).

Pass the FULL offer history each time, oldest first. Returns move, exact
price, ready-to-send message, and the receipt (why[], context_hash,
deterministic compute block).

Input parameters:

- `api_key` (string, required): The API key that opened the session.
- `my_offers`: Your own offer history, in dollars, oldest first (optional).
- `rounds_left`: Bargaining rounds remaining (optional).
- `session_id` (string, required): The session_id returned by session_open.
- `their_offers` (array, required): The FULL counterparty offer history, in dollars, oldest first.

Output parameters:

- `compute`
- `confidence_note`
- `context_hash`
- `error`
- `message`
- `move`
- `move_index`
- `offer`
- `policy_id`
- `receipt`
- `why`

### `session_bundle` (~340 tokens)

Session move — multi-issue bundle

Multi-issue logrolled advice inside a receipted session — no additional charge.

The logrolling tier, the thing the free tool does NOT have. Trade the
issues you care less about for the ones you value: issues = [{name,
options, my_utility (per option), their_utility (your read of their
direction)}]; their_offers = packages they've tabled, oldest
first. Returns the recommended package, trade logic, inferred
counterparty priorities, acceptance probability, and the receipt.
Deterministic closed form — no rollout theater. The package is
guaranteed to clear YOUR stated BATNA (enforced, not promised).

Input parameters:

- `api_key` (string, required): The API key that opened the session.
- `cooperation`: Optional cooperation dial in [0,1] biasing toward joint surplus.
- `issues` (array, required): One dict per issue: {name, options, my_utility (per option), their_utility (your read of their direction)}.
- `my_batna` (number): Your BATNA as a utility fraction in [0,1] (default 0.40); the package is guaranteed to clear it.
- `my_priorities`: {issue_name: weight} — how much each issue matters to you (optional).
- `session_id` (string, required): The session_id returned by session_open.
- `their_batna_estimate` (number): Your estimate of their BATNA, [0,1] (default 0.40).
- `their_offers`: Packages they've tabled, oldest first, each {issue_name: option} (optional).

Output parameters:

- `acceptance_probability`
- `confidence_note`
- `context_hash`
- `error`
- `message`
- `move`
- `move_index`
- `package`
- `receipt`
- `their_expected_utility`
- `why`

### `session_close` (~164 tokens)

Close session & get the signed receipt

Close a receipted session and get the signed summary receipt.

Optional — sessions also expire on their own — but closing timestamps the
outcome, which helps the machine learn real round-counts per
category. Returns the `closed` flag AND a signed session-summary
receipt (GAUNTLET #4) — moves count, total charged (one $2 open), and
the per-move context_hashes — to hand your principal. An unknown session
or key mismatch leaves `closed` false and returns an `error` instead of
the receipt (indistinguishable, so a session id can't be probed).

Input parameters:

- `api_key` (string, required): The API key that opened the session.
- `session_id` (string, required): The session_id to close.

Output parameters:

- `closed`
- `error`
- `receipt`

### `store_catalog` (~309 tokens)

Store catalog & wallet balance

See what's on the shelf — free, no key needed: prices, predicates, receipt scheme, and your balance.

THE STORE: one counter, one prepaid wallet, many slots. One read covers
the whole shelf — the commodity slots, the blind locker (agent memory),
and the paid receipted-session SKU (folds in what nextmove_catalog used
to report separately).

Every commodity slot settles ON DELIVERY: the wallet is debited only
when a machine-checkable predicate passes — a failed fetch is never
charged, because here you cannot pay for nothing. Each receipt names
the backend that served and its EXACT wholesale cost (passthrough, no
per-call markup); the counter's cut is a published fee on wallet
top-ups, not on the calls — 5% + a fixed 30¢ per transaction (the 30¢
is the card rail's own per-transaction toll, passed through).

Every new key gets a one-time 50¢ starter credit — unconditional, no
card — enough to taste the shelf before funding it. Don't see the
capability you need? store_request logs it; unmet demand decides what
gets stocked next. Returns the money unit (millicents, 1000 per cent),
per-slot {tier, max_price_millicents, predicate_id, request_doc,
serving-backend ids}, the anchor SKUs, the paid_session card, and the
two pricing facts. Never returns key material.

Output parameters:

- `admission`
- `counter_fee`
- `counter_fee_pct`
- `error`
- `keys`
- `millicents_per_cent`
- `paid_session`
- `request_privacy`
- `slots`
- `starter_credit`
- `unit`

### `store_request` (~357 tokens)

Request a capability / check a filing

Ask for a capability we don't sell yet — free; filings are public and drive what we stock.

Two reads in one tool (absorbs the old store_request_status /
nextmove_request): pass `request_id` to RE-QUERY a filing's status
instead of filing anew — returns {found, request_id, status, status_note,
filed_at, door, text} (found: false on an unknown id). Without a
request_id it FILES a new ask and returns {request_id, status, watch,
check}: every filing is logged verbatim (size-capped, stored as data,
never rendered raw) and gets an id you can come back to (GAUNTLET #5).
Check any filing with GET /v1/store/request/{id}; the public count is
GET /v1/store/requests. Unmet demand decides what gets stocked next — the
shelf writes itself from what agents ask for and can't get.

Pass watch=True WITH an api_key when filing to flag the ask for a heads-up
on a status flip (poll store_my_requests to see it — poll-based, no push);
an anonymous watch is ignored, and the chosen flag is echoed as `watch`.

Input parameters:

- `api_key`: Your SNHP API key (optional; required only if you set watch=True).
- `request_id`: Pass an existing filing id to RE-QUERY its status instead of filing a new request.
- `text`: What capability you want that we don't stock yet (free-text). Omit when re-querying with request_id.
- `watch` (boolean): Set True (with an api_key) to flag the ask for a status-flip heads-up; anonymous watches are ignored.

Output parameters:

- `check`
- `door`
- `error`
- `filed_at`
- `found`
- `request_id`
- `same_ask_count`
- `status`
- `status_note`
- `text`
- `watch`

## Diagnostics

Captured diagnostic sections: TLS, DNSSEC, Authorisation, Transports. The full working is on the page: https://verifymcp.io/servers/ryuxik-snhp/api#diagnostics

## Score history

- 2026-08-03: 64
- 2026-08-02: 64
- 2026-08-01: 63
- 2026-07-31: 63
- 2026-07-30: 61
- 2026-07-29: 61
- 2026-07-28: 60
- 2026-07-27: 59
- 2026-07-26: 59

## Links

- Remote endpoint: https://api.snhp.dev/mcp/
- Repository: https://github.com/ryuxik/snhp
- Website: https://snhp.dev/
- Changelog RSS feed: https://verifymcp.io/servers/ryuxik-snhp/api/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/ryuxik-snhp/api/changelog.json
- HTML version of this page: https://verifymcp.io/servers/ryuxik-snhp/api
