Server data from the Official MCP Registry
Read-only decision record: query decisions, drain decision changes, verify token.
About
Read-only decision record: query decisions, drain decision changes, verify token.
Security Report
decisionscope is a read-only forwarding client that sends each tool call to a hosted endpoint with a Bearer service token read from RITHMO_MCP_TOKEN. The code shows no malicious patterns, hardcoded secrets, shell execution, or data exfiltration beyond the documented query forwarding. Remaining concerns are low: the token will be sent to any URL set in RITHMO_MCP_URL without an HTTPS requirement, and upstream answer text is passed to the assistant unfiltered. Supply chain analysis found 3 known vulnerabilities in dependencies (0 critical, 2 high severity). Package verification found 1 issue.
8 files analyzed · 8 issues found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
Permissions Required
This plugin requests these system permissions. Most are normal for its category.
How to Install
Add this to your MCP configuration file:
{
"mcpServers": {
"io-github-cloudcorprecords-decisionscope": {
"args": [
"-y",
"@reneturcios/decisionscope"
],
"command": "npx"
}
}
}Documentation
View on GitHubFrom the project's GitHub README.
decisionscope
decisionscope gives a tool read-only access to a hosted decision record: a system of record for what was actually decided. Before acting, a tool can ask the record a natural-language question — "Are we still shipping the new onboarding flow?" — and get back the current authoritative answer, or an explicit hold when the record has no confident answer. A polling caller can also drain decisions whose state changed since a cursor. The record only answers; it never takes actions in your systems.
decisionscope is a forwarding client. It runs locally as a CLI
and a stdio MCP server, and forwards each call to the hosted
endpoint as a JSON-RPC tools/call request. The endpoint is named
by RITHMO_MCP_URL and defaults to the hosted service at
https://app.rithmo.ai/api/mcp; a self-hosted deployment exposes
the same tools and contract at its own address.
Setup
Every request carries a per-organization service token as a
Bearer token. The token resolves to exactly one organization,
must carry the mcp:read scope, and every result is scoped to
that organization. There is no anonymous access.
export RITHMO_MCP_TOKEN="<your service token>"
# Optional; only needed for a self-hosted endpoint:
export RITHMO_MCP_URL="https://app.rithmo.ai/api/mcp"
Keep the token in a secret store, never in code. With no token
set, every call fails before any request is sent, with an error
naming RITHMO_MCP_TOKEN.
Install
npx @reneturcios/decisionscope whoami
Or run the container image:
docker run -i ghcr.io/cloudcorprecords/decisionscope
The container defaults to the MCP server (see below). Pass CLI
arguments to use it as a CLI instead, and pass the two environment
variables above with -e so the container can reach your record.
CLI
decisionscope query_decision "Are we still shipping the new onboarding flow?"
decisionscope query_decision "What did we decide about GitHub integration?" --type decision
decisionscope query_decision "Who owns the pricing change?" --owner "Priya" --surface jira
decisionscope list_decision_changes
decisionscope list_decision_changes --since "0_" --limit 200
decisionscope whoami
decisionscope --version
Results print as JSON. Exit codes: 0 on success, 1 on an
operation error (including a missing token), 2 for usage
errors. Arguments are validated before the token is checked, so a
malformed call is always a usage error.
MCP server
One bin serves both faces. The mcp subcommand starts a stdio
MCP server:
npx -y @reneturcios/decisionscope mcp
MCP client configuration:
{
"mcpServers": {
"decisionscope": {
"command": "npx",
"args": ["-y", "@reneturcios/decisionscope", "mcp"],
"env": {
"RITHMO_MCP_TOKEN": "<your service token>"
}
}
}
}
Object results are returned as a JSON text block and as
structuredContent, so clients can read
res.structuredContent directly.
Tools
| Tool | Input | What it returns |
|---|---|---|
query_decision | question (required); optional type (action_item | follow_up | decision), owner, area, surface | A result discriminated on result: found, found_record, or no_record — see below. |
list_decision_changes | optional since (opaque cursor), optional limit (integer 1–200, default 50) | { changes, cursor, has_more } — the changes since the cursor, in (changed_at, decision_id) order. |
whoami | (none) | { org_id, scopes } for the configured token. |
Reading a query_decision result
The result field has three variants, and the distinction
matters:
found— a live answer from the commitment ledger. The answer text is atanswer, alongsidestatus,lifecycle_state,ownerandsource(both discriminated states, never bare nulls),decided_at,due_at,rationale,conditions,director,context, asupersedeschain (newest-first, cycle-guarded, capped at 12 hops), an optionalspine, and aconfidencescore. Apart fromconfidence, afoundresult for the same decision is byte-identical on every call.found_record— a live answer from the subject record. This is an answer, not a refusal. The answer text is atsubject.currentAnswer, notanswer— and it may benull, meaning the subject is on record but there is no answer text to act on.no_record— no confident answer. The bare form is just{ "result": "no_record" }; a typed form adds arecordexplaining why the answer is held (closed,no_record, ornot_observedwhen the asked-about surface is one the record does not observe). Apremise_check, when present, always hassafe_to_proceed: false. Never proceed on ano_record.
Gate on a usable answer, not on the variant name:
const r = res.structuredContent;
const answer =
r.result === 'found' ? r.answer :
r.result === 'found_record' ? r.subject.currentAnswer :
null;
if (answer != null && String(answer).trim() !== '') { /* act */ }
else { /* hold — no answer to act on */ }
One special case: a no_record whose record.reason starts
with record_unavailable: means the record itself could not be
read (a transient failure). That is not "we decided no" — hold
and retry.
Draining changes
list_decision_changes is built for a polling trigger:
- First call (no
since): returns no changes and the current head cursor. You start from now; history is not replayed. Passsince: "0_"to backfill from the start instead. has_moremeans the page was full (changes.length === limit). It can be true on an exactly-full final page, so the next call may legitimately return zero changes — that is how the drain terminates, not an error.- When a page returns no rows, the cursor is echoed back unchanged, so re-polling with it is safe and idempotent.
- Each change carries the same record core as a
foundresult, pluschanged_at— but neversupersedes,spine, orconfidence. Itsstatusis wider: reversals appear asdroppedorsuperseded, values afoundresult never returns.
Development
npm install
npm run build # tsc -> dist/
npm test # node test runner over test/*.test.ts, no network (fake fetch only)
npm run dev # run the CLI from source via tsx
License
MIT — see LICENSE.
Reviews
No reviews yet
Be the first to review this server!
More Developer Tools MCP Servers
Rea
Freeby Morluto · Developer Tools
Reverse engineer anything from your terminal or agent with one CLI and MCP server.
Paperclip
Freeby Paperclipai · Developer Tools
Trending hip-hop artist momentum scores across four cultural dimensions.
Fetch
Freeby Modelcontextprotocol · Developer Tools
Web content fetching and conversion for efficient LLM usage
Git
Freeby Modelcontextprotocol · Developer Tools
Read, search, and manipulate Git repositories programmatically
Toleno
Freeby Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
MCP Marketplace
Freeby mcp-marketplace · Developer Tools
Search and install MCP servers from inside your AI client.
