stateset-nsr-mcp
v0.7.4
Published
MCP server exposing the StateSet NSR neuro-symbolic reasoning API — verified decisions with machine-checkable proofs, as agent-native tools.
Downloads
458
Maintainers
Readme
NSR MCP Server — verified reasoning for agents
nsr-mcp-server.mjs exposes a running StateSet NSR API to any MCP host
(Claude Code, Claude Desktop, the Agent SDK) as agent-native tools and prompts.
Why this exists
An LLM agent is a fallible neural reasoner. NSR's value is turning a
consequential call — issue this refund, grant this access, cancel this
subscription — from "trust the model" into "the model proposes, NSR proves."
The intended pattern is NSR as a verification oracle: before acting, the
agent routes the decision through nsr_decide and only proceeds on an
approved verdict backed by cited rules. A refused outcome is the correct,
safe result — the agent asks for missing facts or escalates instead of
guessing. The verify_before_acting prompt (below) hands the host exactly
this guardrail.
This is distinct from the in-process Rust nsr-mcp binary
(src/bin/nsr_mcp.rs), which embeds an engine and stubs the reasoning
tools. Use this server for the full, live reasoning surface.
Self-contained
No npm dependencies — Node ≥ 18 (global fetch) and a hand-rolled JSON-RPC
loop implementing initialize / tools / prompts. Nothing to install.
Configure
| Env | Default | Meaning |
|---|---|---|
| NSR_API_URL | http://127.0.0.1:8080 | Base URL of the NSR server |
| NSR_API_KEY | — | Sent as x-api-key on every request (required) |
| NSR_ORG_ID | — | Optional X-Org-ID override |
The server exits at startup with a clear error when NSR_API_KEY is unset —
a missing key can never work, so it fails fast instead of 401ing on the first
tool call. Point NSR_API_URL at either:
- Hosted:
https://api.nsr.stateset.com(get an API key from the console at https://nsr.stateset.com → API setup), or - Local: your own
nsr-server(see Run locally below).
Connect your agent
Every MCP host below launches the same stdio command. The server is published
on npm as stateset-nsr-mcp,
so npx -y stateset-nsr-mcp needs no clone and no install step. Pin a version
with [email protected] if you prefer; the package version tracks the
engine crate version.
To run from a checkout instead (development, or an air-gapped host), swap the
command for node /path/to/stateset-nsr/mcp/nsr-mcp-server.mjs — it is a
single dependency-free file and behaves identically.
Claude Code
One command:
claude mcp add nsr \
--env NSR_API_URL=https://api.nsr.stateset.com \
--env NSR_API_KEY=nsr_your_key \
-- npx -y stateset-nsr-mcpOr check a project-scoped .mcp.json into your repo so every teammate gets it
(this repo ships one registering the server as nsr-mcp):
{
"mcpServers": {
"nsr": {
"command": "npx",
"args": ["-y", "stateset-nsr-mcp"],
"env": {
"NSR_API_URL": "https://api.nsr.stateset.com",
"NSR_API_KEY": "nsr_your_key"
}
}
}
}Verify with /mcp inside Claude Code — you should see 14 nsr_* tools.
Claude Desktop
Add the same mcpServers block to claude_desktop_config.json
(Settings → Developer → Edit Config; macOS:
~/Library/Application Support/Claude/claude_desktop_config.json,
Windows: %APPDATA%\Claude\claude_desktop_config.json), then restart the app.
Cursor
Create .cursor/mcp.json in your project (or ~/.cursor/mcp.json globally)
with the same mcpServers JSON as above, then enable the server under
Settings → MCP.
Windsurf
Same JSON in ~/.codeium/windsurf/mcp_config.json.
Codex CLI
~/.codex/config.toml:
[mcp_servers.nsr]
command = "npx"
args = ["-y", "stateset-nsr-mcp"]
env = { NSR_API_URL = "https://api.nsr.stateset.com", NSR_API_KEY = "nsr_your_key" }VS Code (Copilot agent mode)
.vscode/mcp.json in your workspace:
{
"servers": {
"nsr": {
"type": "stdio",
"command": "npx",
"args": ["-y", "stateset-nsr-mcp"],
"env": {
"NSR_API_URL": "https://api.nsr.stateset.com",
"NSR_API_KEY": "nsr_your_key"
}
}
}
}Claude Agent SDK (programmatic)
import { query } from '@anthropic-ai/claude-agent-sdk'
for await (const message of query({
prompt: 'Can order 9412 be refunded? Verify before acting.',
options: {
mcpServers: {
nsr: {
command: 'npx',
args: ['-y', 'stateset-nsr-mcp'],
env: { NSR_API_URL: 'https://api.nsr.stateset.com', NSR_API_KEY: 'nsr_your_key' },
},
},
allowedTools: ['mcp__nsr__nsr_decide', 'mcp__nsr__nsr_verify_plan'],
},
})) { /* … */ }Anything else
Any MCP host that can spawn a stdio server works: command node, single arg
npx -y stateset-nsr-mcp (or the checkout path), env NSR_API_URL +
NSR_API_KEY (+ optional NSR_ORG_ID, NSR_TIMEOUT_MS). The server speaks
MCP protocol revisions 2024-11-05 through 2025-06-18 and negotiates on
initialize.
First session: prove it works
Ask your agent:
Use nsr_decide: "Can order 9412 be refunded?" with action
issue_refund, the factfinal_sale(9412), and the ruleno_refund_final_sale: IFfinal_sale(?o)THENrefund_not_approved(?o)with effectdeny.
A correct setup returns a denied verdict citing no_refund_final_sale —
a proof, not a guess. Then try dropping the fact: the engine refuses and
refusal.missing_facts names exactly what evidence would unblock it. That
refuse-then-supply loop is the intended agent workflow (see Prompts below).
Run locally
# 1. A local NSR API. NSR_NEURAL_BACKEND=mock is REQUIRED offline — the default
# backend calls an external embeddings API, so entity creation 500s without it.
NSR_API_KEYS="mcp-demo-key" NSR_NEURAL_BACKEND=mock \
./target-local/release/nsr-server serve -p 8787
# 2. Point the MCP server at it (registered as `nsr-mcp` in the repo .mcp.json)
NSR_API_URL=http://127.0.0.1:8787 NSR_API_KEY=mcp-demo-key node nsr-mcp-server.mjsVerify it
npm test— protocol-surface tests (initialize / tools / prompts / errors), no live API needed.node smoke.mjs— every tool end-to-end against a live API.node scenario.mjs— a full teach-then-prove reasoning session.
Tools (14)
nsr_decide, nsr_verify_plan, nsr_get_decision, nsr_backward_chain,
nsr_forward_chain, nsr_chat, nsr_add_entity, nsr_add_fact,
nsr_add_rule, nsr_query_kb, nsr_list_templates, nsr_apply_template,
nsr_gss_seed_info, nsr_flywheel_curve.
nsr_verify_plan is the agent-safety flagship (v0.4.0): submit a multi-step
plan, get one verified decision per step plus a plan_verdict — execute only
on approved; a single denied/refused step blocks the plan, and refused
steps carry missing_facts naming exactly what evidence would unblock them.
Agent-friendly semantics (v0.3.0):
nsr_add_factaccepts entity ids or exact names — non-UUID refs are resolved via entity search and must match exactly one entity; missing or ambiguous names return actionable errors instead of a bare 400.nsr_decideis retry-safe: every call carries anIdempotency-Key(auto-generated, reused across transient-failure retries — 5xx/429/408 and network errors; permanent 4xx never retried) so a retried decide cannot double-execute or double-bill. Passidempotency_keyto pin agent-level replays too.
Prompts
verify_before_acting(action, context?)— the guardrail: prove a consequential action viansr_decidebefore executing; refuse rather than guess.teach_a_policy(policy)— encode a business policy as entities + facts + a rule, then verify it proves (and correctly fails on the negative case).
See the stateset-nsr skill for the ground-then-decide / teach-then-prove
workflows.
