Naragate MCP Server
One portable tool layer so the same Naragate experience works on the custom web UI and on any MCP-capable agent surface — Claude Code, Claude Desktop, Cursor, Windsurf, Zed, VS Code, opencode, Codex, or your own harness.
┌─ custom web UI (Angular)
Naragate backend ├─ MCP server ──► any MCP harness (desktop / CLI / IDE)
(FastAPI+cache) └─ Pi agent harness
The three layers (what a user actually needs)
| Layer | Path | Required? | Role |
|---|---|---|---|
| MCP server | mcp/ (this package) |
Yes for non-web | The tools: analyze, history, trend, precheck, usage |
| Skills | skills/ |
Yes | Domain instructions: how to parse, challenge and score a claim |
| Agents | agents/ |
No | Optional orchestration for harnesses with subagents |
Skills alone can't fetch data (they declare tools but don't ship them); agents+skills add orchestration but still have no data. The MCP bundle is the data layer — with it, skills run anywhere.
Credit safety (hard requirement)
This server never talks to Sectors directly. Every tool is a thin client over the Naragate backend, so evidence gathering, the Evidence Graph cache and credit accounting live in exactly one place. A warm re-run costs 0 additional Sectors calls, identical to the web UI. There is a test asserting the MCP package never references the Sectors API.
Install
uvx naragate-mcp # run without installing (recommended)
pip install naragate-mcp # or install into your environment
pipx install naragate-mcp
From a checkout: pip install -e mcp.
Point it at your backend (default http://127.0.0.1:5678):
export NARAGATE_BACKEND_URL="http://127.0.0.1:5678"
export NARAGATE_TOKEN="nrg_..." # optional: act as your own account
naragate-mcp
Transport is stdio.
Acting as your own account (NARAGATE_TOKEN)
The backend owns the Sectors key and LLM configuration; this server never sees them. To use your own key, cache and credits, mint a token in the web UI (Settings → MCP & API Access) and set NARAGATE_TOKEN. Every request then carries Authorization: Bearer <token>, which the backend resolves to your email — the same identity the web session uses.
- Without a token the server falls back to the backend's deployment key (fine for single-user self-hosts; all callers share one key/ledger).
whoamiconfirms the resolved account;get_setup_statusreports missing config;bind_sectors_keysets your key off-web.- Tokens are stored hashed server-side and revocable from the same settings page.
No backend? Start one in one command
This server depends on an engine, not on any particular hosted deployment. The engine runs standalone with no Redis (SQLite + in-process cache):
pip install naragate-engine && SECTORS_API_KEY=... naragate-engine
# or
docker run --rm -p 5678:5678 -e SECTORS_API_KEY=... ghcr.io/masdevid/naragate-engine
If no engine answers, tools fail with an actionable hint on how to start one. Set NARAGATE_BACKEND_URL to wherever the engine runs.
Tools
30 tools total — 15 high-level + 15 low-level (every primitive declared in skills/*/tools.yaml).
| Tool | What it does |
|---|---|
analyze_narrative(narrative) |
Verify a narrative end-to-end → Reality Gap score, verdict, evidence sections, policy signal, skeptic summary |
analyze_template(template_id) |
Run one of the 12 curated dashboard templates by id |
list_templates() |
The 12 curated narratives (same tiles as the web dashboard) |
get_claim(claim_id) |
Full stored record (claim, evidence, skeptic, score, policy) |
get_reality_gap(claim_id) |
Compact report for a stored claim |
list_history(limit) |
Recent analyses, most recent first |
get_trend_summary() |
Totals, average score, verdict distribution, per-ticker history |
get_policy_precheck(sector) |
Policy→price pre-check, scoped to the claim's sector |
get_usage() |
Sectors/LLM credit usage, cache hits, remaining budget |
whoami() |
Which account this session acts as (email + whether a Sectors key is bound) |
get_setup_status() |
Missing backend config (sectors_api_key, llm_model) |
bind_sectors_key(api_key) |
Bind a Sectors v2 key to this session's user (requires NARAGATE_TOKEN) |
ask_followup(claim_id, question) |
Ask a follow-up about a completed analysis, grounded in its evidence |
get_followup_suggestions(claim_id) |
3-5 contextual follow-up templates (the web suggestion chips) |
next_followup_suggestion(claim_id, exclude) |
One fresh template, avoiding exclude |
Low-level tools — full tools.yaml parity
Every primitive declared in skills/*/tools.yaml is also exposed, for harnesses that want to compose
per-agent exactly like the Pi pipeline (check the cache, then fetch on a miss and merge back):
| Tool | What it does |
|---|---|
sectors_company_report(ticker, sections) |
Sectors v2 company report (valuation/overview/financials) |
sectors_subsector_report(sub_sector, sections) |
Sectors v2 subsector report |
sectors_quarterly_financials(ticker, n_quarters) |
Sectors v2 quarterly financials |
sectors_daily_transaction(ticker, start, end) |
Sectors v2 daily price/volume (Sectors caps a call at 90 days) |
sectors_news(ticker, limit) |
Sectors v2 news headlines |
sectors_corporate_actions(ticker) |
Sectors v2 corporate actions |
sectors_filings(ticker, filing_type) |
Sectors v2 insider-trade filings |
sectors_foreign_flow(ticker, start, end) |
Sectors v2 foreign investor flow (net inflow/outflow) |
sectors_broker_summary(ticker, start, end) |
Sectors v2 broker accumulation/distribution summary |
sectors_top_changes(classifications, periods, n_stock) |
Sectors v2 top gainers/losers across the IDX universe |
sectors_segments(ticker, financial_year) |
Sectors v2 revenue-segment breakdown |
sectors_index_daily(index_code, start, end) |
Sectors v2 daily closing prices for an IDX index (e.g. ihsg) |
evidence_cache_get(ticker) |
Read the Evidence Graph (null on miss) |
evidence_cache_merge(ticker, key, value, ttl?) |
Merge one section into the cache |
llm_complete(prompt, system?, response_format?, role?) |
One-shot completion on Naragate's configured LLM |
A test (tests/test_parity.py) asserts that every tool declared in any skills/*/tools.yaml
exists on the server, so this can't drift.
Resources
naragate://templatesnaragate://usagenaragate://historynaragate://claim/{claim_id}
Harness configuration
Claude Code
claude mcp add naragate \
-e NARAGATE_BACKEND_URL=http://127.0.0.1:5678 \
-e NARAGATE_TOKEN=nrg_... \
-- uvx naragate-mcp
Claude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"naragate": {
"command": "uvx",
"args": ["naragate-mcp"],
"env": { "NARAGATE_BACKEND_URL": "http://127.0.0.1:5678", "NARAGATE_TOKEN": "nrg_..." }
}
}
}
opencode (opencode.json)
{
"mcp": {
"naragate": {
"type": "local",
"command": ["uvx", "naragate-mcp"],
"enabled": true,
"environment": { "NARAGATE_BACKEND_URL": "http://127.0.0.1:5678", "NARAGATE_TOKEN": "nrg_..." }
}
}
}
Cursor (.cursor/mcp.json) / Windsurf / Zed / VS Code
{
"mcpServers": {
"naragate": {
"command": "uvx",
"args": ["naragate-mcp"],
"env": { "NARAGATE_BACKEND_URL": "http://127.0.0.1:5678", "NARAGATE_TOKEN": "nrg_..." }
}
}
}
Codex (~/.codex/config.toml)
[mcp_servers.naragate]
command = "uvx"
args = ["naragate-mcp"]
env = { NARAGATE_BACKEND_URL = "http://127.0.0.1:5678", NARAGATE_TOKEN = "nrg_..." }
Example prompts
- "Use naragate to verify: PE BBCA mahal di 25x."
- "List the naragate templates and run the nickel policy one."
- "Show my last 10 naragate analyses and the trend summary."
- "What's my Sectors credit usage?"
Tests
cd mcp
python -m pytest -q
Covers the REST client (mock transport), the tool surface, compact-report shaping, and the credit-safety guarantee. No live backend or Sectors access required.
Publishing
CI publishes via .github/workflows/publish-mcp.yml
when a GitHub release is published (or gh workflow run publish-mcp.yml). It authenticates with
PyPI Trusted Publishing (OIDC) — no API token secret. One-time setup on PyPI
(project → Publishing → Add a new publisher):
| Field | Value |
|---|---|
| Owner | masdevid |
| Repository | naragate |
| Workflow name | publish-mcp.yml |
| Environment name | pypi |
→ https://pypi.org/manage/project/naragate-mcp/settings/publishing/
For local/manual publishing, publish.sh uses an API token instead:
mcp/publish.sh # PyPI
mcp/publish.sh testpypi # TestPyPI
mcp/publish.sh check # dry run: build + twine check (no token, no upload)
publish.sh reads PYPI_TOKEN from the environment or the repo-root .env, builds with
python -m build, validates with twine check, and uploads — the token is never echoed. Manual
equivalent:
python -m build
python -m twine check dist/*
TWINE_USERNAME=__token__ TWINE_PASSWORD="$PYPI_TOKEN" python -m twine upload dist/*
Related
- Naragate README — project overview and the "Use Naragate from any MCP agent" section
- Skills — the 13 skills whose
tools.yamlthis server satisfies - Agents — optional subagent topology for harnesses that support it
- Parity test — enforces that every
skills/*/tools.yamltool is exposed here
Release files for naragate-mcp 0.5.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| naragate_mcp-0.5.0.tar.gz | 20.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| naragate_mcp-0.5.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 34.1 kB
Release files / naragate_mcp-0.5.0.tar.gz
| Download URL | naragate_mcp-0.5.0.tar.gz |
|---|---|
| Size | 20.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1ab47f0a96e94d1844fe694309f31f54e3103ecdddde213464614b19d05c3e26
|
|
BLAKE2b-256 checksum How to use checksums |
4271168faa1f181258374b09d90f8ea9cfb8ddc5764fd2472132720f010f2998
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.
Transparency logRelease files / naragate_mcp-0.5.0-py3-none-any.whl
| Download URL | naragate_mcp-0.5.0-py3-none-any.whl |
|---|---|
| Size | 14.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2b4411f1cb7d3ea5f1b65b89c44c690ef91198bf1e9623dbb174158a0f036f77
|
|
BLAKE2b-256 checksum How to use checksums |
e1e1850ab8c29bc43275c93cb62107fc02eddc8a0d47fa20838350a2fe0f500b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.
Transparency log