Server data from the Official MCP Registry
Read-only crypto research skills that check a price, RSI and ATR against independent sources.
About
Read-only crypto research skills that check a price, RSI and ATR against independent sources.
Remote endpoints: streamable-http: https://nota-ryo.vercel.app/mcp
Security Report
Remote MCP endpoint verified (121ms response). Server: nota. 4 tools available. 3 trust signals: valid MCP protocol, known domain (vercel.app), registry import. 1 security issue detected.
4 tools verified · Open access · 2 issues found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
Remote servers are capped at 8.0 because source code is not available for review. The score reflects endpoint verification only.
Permissions Required
This plugin requests these system permissions. Most are normal for its category.
How to Connect
Remote Plugin
No local installation needed. Your AI client connects to the remote endpoint directly.
Add this to your MCP configuration to connect:
{
"mcpServers": {
"io-github-pugarhuda-nota": {
"url": "https://nota-ryo.vercel.app/mcp"
}
}
}Documentation
View on GitHubFrom the project's GitHub README.
Nota
An AI trading opinion you can audit. A council of specialised agents debates live RYO market
evidence and records the practice trade it would make as a replayable decision receipt:
nota replay <id> rebuilds it from the stored evidence and prints identical: true, every cited
number is read back out of the evidence rather than retyped by the model, and independent sources
audit RYO's own price and indicators before anything is sized. Built for the RYO-CHAN Hackathon 2026.
Tracks entered: 1 Autonomous Agents (council, receipts, watch loop), 2 Dashboards
(diff-first receipt dashboard), 3 New Skills (narrative_convergence, news_verify,
price_crosscheck, technicals_crosscheck, all in RYO's envelope).


Screenshots are generated from the shipped demo ledger by scripts/screenshots.py.
Watch it instead: nota-ryo.vercel.app/demo — a narrated
2:18 walkthrough with a clickable transcript, or the bare file at /demo.mp4.
How a decision is made
gather ──────────► council ──► judge ──► risk (pure ATR math) ──► receipt ──► ledger ──► notify
5 RYO tools macro weighs entry / stop / target id = hash(evidence, Telegram
+ own skills technician opinions or Blocked when price model, prompts) Discord
(price_check, narrative by Brier or ATR is missing
voices, news) weights
- Evidence pack:
market_overview,monitor_market_sentiment_shift,deep_analysis,analyze_token,compare_tokens(the token against BTC/ETH peers).scan_marketdrivesnota scan, RYO's recommended funnel. A failed tool becomes a section with statuserror; the pack still exists. Own skills are added as further sections (price_checkby default,narrative_signalwith--voices,news_checkwith--news). - Council: three agents (macro, technician, narrative) each return a stance, a
probability, and citations as dotted paths into the evidence. Citations that point at
a missing or null value are dropped in code (after normalising
x[0].ytox.0.y) and the opinion is downgraded. - Judge: weighs opinions by each agent's historical Brier score and decides long / short / no_trade.
- RYO's own plan is evidence, not an instruction:
deep_analysis.data.trade_plancarries RYO's ATR preview (entry, stop, targets, multiplier, method). Nota sizes independently and then reports the gap on the receipt: on the shipped ETH call, RYO stops at 2357.83 on a 1.5× ATR while this sizing uses 2.0×, so the stop sits 1.8% of entry lower and the first target 5.4% further, both in the same direction. - Risk: a pure function. Stop = 2×ATR(14), target = 3×ATR, size from 1% account risk, capped at 20% of the account. No price or no ATR means Blocked, never a guessed number, and so does an ATR big enough to put the stop or target at or below zero: on an instrument that volatile the fixed-multiple rule does not apply, and a receipt must not print a negative price.
- Replay: LLM outputs are cached by
(evidence hash, role, prompt version, model).nota replay <id>reproduces the receipt exactly;--freshre-asks the model and prints the drift honestly. The dashboard's "Verify replay" button does the cached check only. - Calibration:
nota resolve --allscores every decision whose seven-day horizon has passed (Brier per agent) against a fresh RYO price read, falling back to the exchange median fromprice_crosscheckwhen RYO cannot give a price; the outcome records which source was used. - Autonomy:
nota watch SOL,BTC --every 3600 --notifydecides on a schedule, resolves matured decisions, and posts each new receipt to Telegram / Discord.--scan-top 3lets the loop pick its own candidates fromscan_marketevery cycle. - Simulated data never trades: when RYO marks the primary evidence
data_mode: simulated, sizing is blocked and the receipt says so. - Transport: REST (
/tools/{tool}/call) by default, or MCP JSON-RPC (tools/list,tools/callon the same base URL) withRYO_TRANSPORT=mcp;nota healthlists the live tool catalog over MCP when a key is set.
The public surface is treated as public
/api/skills/<name>/invoke and POST /mcp are unauthenticated on purpose, so they are written for
strangers:
- A voice id goes into an outbound URL, so it is validated first.
../../evilused to resolve tohttps://t.me/evil, which handed a caller the path on the target host; with redirects followed that is a step towards making this server fetch somewhere of their choosing. Handles are letters, digits, underscore, dot and hyphen, up to 64 characters, and anything else is refused before a request is built. tools/callover MCP is metered per address exactly like the REST route, 60 an hour, because it reaches third-party APIs.initialize,tools/listandresources/*stay free: they touch nothing outside the process.- A JSON-RPC batch is capped at 25 messages, and
Originis validated on every MCP request as the transport spec's security section requires. - Backing is capped at 30 an hour per address. It used to answer 503 on the hosted deployment, which
meant the one place anyone could try it was the one place it did not work: a serverless filesystem
cannot be written, and the ledger there is a snapshot. Backings now go to Postgres when
DATABASE_URLis set (nota/backings.py) and to the ledger's own table otherwise, so nothing local needs a database to run or to test. The write is a singleINSERT ... ON CONFLICT (decision_id, handle) DO UPDATE: reading a map of handles, changing one and writing it back would drop a stance whenever two people backed at the same moment, and a public record that silently loses someone's vote is worse than no public record. The 503 is still there for the case it was written for - nowhere to write at all.
Honesty rules this code enforces
- Every number in a receipt carries its source path, RYO
as_of,data_modeand trace id. null/unavailableis never converted to 0 (Envelope.get,first_present, risk, every skill).- Recorded fixtures keep RYO's original
as_ofanddata_modeand are labelledsource: recorded. Synthetic test fixtures live only undertests/fixtures/and are labelledsource: fixture; receipts print the label. There is no fake-LLM mode in the CLI. - The RYO surface is read-only; practice trades exist only in
nota.db. - A receipt says what it cost: model calls, cache hits, prompt and completion tokens, the provider's
own billed figure, and wall time. Every one of those is what the provider reported, never derived
from a price table this repository would have to keep correct - a figure that was not reported
reads "not reported", and one silent call makes the whole total unknown rather than smaller.
spendis deliberately outside the replay comparison: a cached rebuild spends nothing, so the field is a measurement, not a reproducibility claim. - External sources say what they cannot do: Venice web search carries no dates, the X mirror is unofficial, RSS feeds that fail are listed, exchange prices never replace RYO's value.
Run
uv sync
cp .env.example .env # RYO_MCP_KEY + an LLM key (Anthropic, or NOTA_LLM=openai for Venice/OpenRouter)
uv run nota health # MCP health (no key) + whoami/quota (with key)
uv run nota decide SOL # live evidence + price cross-check, council, receipt
uv run nota decide SOL --voices tg:WatcherGuru,bs:decrypt.co,bs:unusualwhales.bsky.social --news --notify
uv run nota scan --top-n 5 --decide-top 2 # scan_market -> analyze_token -> council
uv run nota watch SOL,BTC --every 3600 --notify
uv run nota replay <id> # identical: True
uv run nota replay <id> --fresh
uv run nota resolve --all # after 7 days: Brier scores per agent
uv run nota scores
uv run nota record SOL # capture all six live tools into fixtures/recorded
uv run nota decide SOL --source recorded # replay those recordings without a key (after `record`)
uv run nota positions # open practice positions vs the latest independent price
uv run nota serve # http://127.0.0.1:8000 overview, /app dashboard, /mcp
uv run nota skill spec # Track 3 definitions
uv run nota skill run price_crosscheck '{"symbol":"SOL","reference_price":150}'
uv run pytest -q
Skills (Track 3)
All four return RYO's public envelope field for field (docs/skills/SKILL-SPEC.md) and are
served on RYO's own skill paths, so plugging them into RYO is a route registration, not a port:
GET /api/skills/ (SkillDefinition list), GET /api/skills/{name}, and
POST /api/skills/{name}/invoke taking SkillCallRequest {name, args, conversation_id} and
returning SkillCallResponse {name, status: success|error, result, latency_ms, xp, guard_decision}.
The dashboard's "Run a skill" panel builds its form from those definitions and shows the envelope.
narrative_convergence: up to 20 voices (tg:public Telegram previews,bs:Bluesky public API,x:through X's own public syndication endpoint, the one that serves embedded timelines, with a Tavily fallback), VADER sentiment plus a crypto lexicon, conviction, urgency, and convergence detection. Silence isnull, not 0. Nitter, whichx:used to go through, was served cease-and-desist letters in August 2026 and its public mirrors went dark, so that reader was advertising a source that could not answer; syndication is keyless, dated and still open, and every failure is reported asunavailablerather than guessed. One measured limit worth knowing before you try it: syndication throttles hard, and it has tightened. It hit data-centre addresses first, sox:came backunavailablefrom the hosted demo while reading fine from an ordinary connection; as of 2026-09-10 an ordinary connection getssyndication HTTP 429too. Treatx:as best effort andtg:/bs:as the dependable readers - those two answer from both. SettingTAVILY_API_KEYturns the throttle into a search-backed fallback, which the envelope then labels as undated; without that key the warning says so in as many words.news_verify: dated headlines from CoinDesk, Cointelegraph, The Block and Decrypt RSS, plus Tavily or Venice web search for breadth; counts independent domains and attaches RYOanalyze_tokencontext.price_crosscheck: keyless CoinGecko, Coinbase and Kraken spot prices, median, spread, and deviation of a reference price (RYO's) from the exchanges, plus the alternative.me Fear & Greed index against RYO's reading.technicals_crosscheck: RSI(14), ATR(14) and 1d/7d/30d performance recomputed with Wilder's method from CoinGecko public OHLC (4-hour candles aggregated to UTC days), with the deviation of reference values (RYO'stechnicals.rsi_14/atr_14) from the independent calculation. The Technician sees it astechnicals_checkon every decision.
Nota is also an MCP server (Track 3)
Nota is an MCP client of RYO. It is also an MCP server, so RYO, Claude Desktop, Cursor or any other MCP host can call the four skills directly with no wrapper:
// claude_desktop_config.json, or any MCP client that speaks Streamable HTTP
{ "mcpServers": { "nota": { "url": "https://nota-ryo.vercel.app/mcp" } } }
curl -s https://nota-ryo.vercel.app/mcp -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | jq '.result.tools[].name'
curl -s https://nota-ryo.vercel.app/mcp -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"technicals_crosscheck","arguments":{"symbol":"SOL"}}}'
It serves all four MCP primitives, not just the easy one:
- tools:
tools/listandtools/callfor the four skills, eachinputSchemagenerated from the same definition the REST route and the dashboard form use. - resources:
resources/list,resources/templates/list(nota://receipt/{id}) andresources/read, which returns a receipt as markdown plus its own JSON. A client that never touches this project's HTTP API can still list its decisions and read one. - prompts:
prompts/listandprompts/get.audit_a_tokentells the caller's model to cross-check RYO against the independent sources and carries the honesty rules with it, including that a null stays null.read_a_receiptwalks a stored decision. - completions:
completion/completeoffers the receipt ids and symbols this deployment actually holds, so a client never has to guess one.
Nota is published in the official MCP registry as io.github.PugarHuda/nota (version 0.1.0,
2026-09-10), so a client can find it without being handed the URL:
curl "https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.PugarHuda/nota".
server.json at the repository root is this server's entry for the official MCP registry, and the
deployment serves it at /.well-known/mcp/server.json and /server.json, so the description and the
endpoint it names cannot drift apart. Two rules the registry enforces and a test here mirrors: the
description is capped at 100 characters, and a published version is immutable - every republish
needs a new version, so changing anything in that file means bumping it. Publish with
mcp-publisher login github && mcp-publisher publish from the repository root; mcp-publisher validate checks the file against the live registry without publishing.
GET /llms.txt follows the llms.txt convention: one generated page telling an agent what is here,
how to call the MCP endpoint, which skills exist and which receipts the ledger holds. It is built
from the routes and the ledger, so it cannot drift from them.
One endpoint, POST only, stateless. It negotiates the protocol version the client asks for
(2026-07-28, 2025-06-18, 2025-03-26 or RYO's own 2024-11-05), validates the Origin header
against DNS rebinding as the transport spec requires, answers a batch with one response per request,
returns 202 Accepted with no body when the body holds only notifications, and answers 405 to GET
and DELETE because there is no stream to open and no session to delete. Each tool's inputSchema is
generated from the same skill definition the REST route and the dashboard form use, so the three can
never drift apart. tools/call returns the RYO envelope twice: as text for clients that only read
text, and as structuredContent for clients that parse.
Dashboard (Track 2)
nota serve exposes a read-only API over the ledger (/api/decisions, /api/decisions/{id},
/api/decisions/{id}/replay, /api/positions, /api/scores, /api/health, exports
/r/{id}.json and /r/{id}.md, OpenAPI at /docs) and a single-page dashboard:
- Thirty-second summary at the top of every receipt: what to do now (trade or block reason), the single biggest change and why it matters, whether the open practice position would be stopped out or at target at the latest independent price, and what happens next (when it is scored, or the score).
- What changed: every receipt is diffed against the previous receipt for the same symbol
and the rows are ranked by impact. Verdict flips, trade unlock/block, availability and model
changes come first, then the numbers the risk engine reads (price, ATR, RSI) by % move, then
every other evidence leaf. A value that became
nullis shown asnull, never as 0. - Degraded mode: a banner names each evidence section that is not
ok; provenance showsas_of,data_modeand trace id per section. - Open practice positions against the latest evidence price, with distance-to-stop.
- Agent leaderboard by Brier score with the judge weights currently in force, and a judge
calibration table (stated
p_up_7dbucket vs realised hit rate) once decisions resolve. - Two languages, one page:
/and/jasharelanding.cssandlanding.js, so only the prose is translated and the behaviour is the same object rather than a copy of it. Tests bind the two: identical section ids, both loading the one script, and neither allowed to write a receipt id or an evidence hash into the file. - Which sources helped (
sourcesin/api/scores): for every evidence section, the judge's mean Brier on decisions where that section answered against decisions where it did not, and the difference between them. It answers a question the agent leaderboard cannot - not "which agent is right" but "does having this feed make the call better". An empty bucket scoresnull, and the table carriesenough_to_read, false until 20 decisions are scored: the gap between two three-sample means is noise, and printing it as a finding would be the same offence as turning a null into a zero. - Verify replay from the page (cached outputs only, never spends), share to X, exports.
- Works for everyone: skip link, real buttons, visible focus,
aria-liveupdates, keyboardj/kmove,Enteropen,pprevious receipt,/filter,?help. - Polls the ledger every 30 s so a running
watchloop shows up without a reload.
The dashboard reads receipts only. It cannot show a number that has no receipt behind it.
SocialFi layer
- Receipt cards:
/r/<id>.pngrenders a 1200×630 card from the receipt (Pillow, bundled font);/r/<id>carries Open Graph and X card tags pointing at it, so a shared permalink previews as the receipt. Discord notifications embed the same image. - Backing: anyone can back or disagree with a call under a handle (
POST /api/decisions/<id>/back, one stance per handle per receipt, latest wins). When the call resolves, backers are scored against the outcome (/api/backers): agreeing with a long that went up is right, disagreeing with it is wrong,no_tradecalls are never scored. It is public and unauthenticated on purpose; the ledger keeps every stance with its timestamp.
Evaluate with zero keys
The repository ships a ledger snapshot that starts with four receipts made on live RYO evidence
(2026-09-07, SOL / BTC / ETH, each labelled with its own source) and grows: a daily cycle
(.github/workflows/ledger.yml) scores whatever reached its seven-day horizon and commits the
snapshot back. Every receipt in it verifies, and a test says so:
uv sync # on PowerShell, set the variable first: $env:NOTA_DB = "data/demo.db"
NOTA_DB=data/demo.db uv run nota replay b80b42835b01 # identical: True - verified with no key at all
NOTA_DB=data/demo.db uv run nota serve # then open http://127.0.0.1:8000/app for the dashboard
NOTA_DB=data/demo.db uv run nota positions
uv run nota skill run price_crosscheck '{"symbol":"SOL"}' # live exchanges, no key
uv run pytest -q # 176 tests
The first line is the point of the project: a cached replay rebuilds the receipt from the ledger's
own evidence and the model outputs stored beside it, keyed by the model that produced them, so it
touches no API and cannot drift. Every shipped receipt verifies this way, the recorded-source one
included, because a cached replay is keyed by the model that produced the output rather than by
whatever model is configured today. --fresh is the opposite: it calls today's model on the
same evidence and prints the differences as drift.
A council decision needs one LLM key (Anthropic, or any OpenAI-compatible provider such as Venice) and live RYO evidence needs the builder key; everything else, verification included, runs without either.
The walkthrough, and how it is made
/demo serves a narrated video and, beside it, the transcript as chapters: clicking a line seeks
to it. Three steps build it, and each one hands the next its timing rather than a guess:
uv run --with edge-tts python scripts/narration.py # the voice, and it sets the pace
uv run python scripts/demo_video.py # Playwright records the real pages
cd video && npx remotion render # the two are composed
scripts/narration.pyholds the spoken script as beats, each one a sentence paired with the selector it is about. Microsoft'sen-US-AndrewNeuralreads them throughedge-tts, which needs no key, andffprobemeasures what came back. Nothing is timed by ear.scripts/demo_video.pydrives the app with Playwright againstdata/demo.dband holds every beat for exactly the length of its own audio. It draws two things a raw screen capture lacks: a cursor that travels to whatever is being described, and a frame around that element, so it is never ambiguous which part the voice means. It writes down the second each beat actually began — a page load takes time the narration does not — and that file is what both the composition and/demo's transcript read.video/is a Remotion composition that places each line at its recorded offset and renders the MP4.
Nothing in it is staged. The verify button is pressed on camera and its answer is whatever the API returns; every figure spoken is one this deployment produces on demand.
Hosted demo
A read-only copy of the dashboard runs at https://nota-ryo.vercel.app (Vercel, framework-detected
FastAPI via main.py). It serves the committed ledger snapshot data/demo.db (receipts on live
RYO evidence, each carrying its trace ids) with NOTA_READONLY=1: reads, replay verification, cards and exports
work; backing answers 503 because a serverless filesystem cannot be written. The full system,
including live RYO evidence, the watch loop, notifications and backing, runs with
uv run nota serve on any machine with a writable disk.
Failure handling
- RYO client: exponential backoff with jitter on 429/503/network, honours
Retry-After, never retries 4xx argument errors, recordsX-RateLimit-*headers. - Evidence gathering continues past failed tools and skills; the judge is told which sections
are missing and is instructed to prefer
no_tradewhen primary evidence is gone. - SQLite ledger in WAL mode; every write is idempotent by content hash, so a restart resumes.
watchsurvives a failing symbol, a failing notifier and a failing resolution.- RSS is parsed with
defusedxml(no entity expansion from untrusted feeds). - Some ISPs DNS-block exchange domains (seen from Indonesia: Coinbase and Kraken resolve to a
block page with a bad certificate).
price_crosscheckthen reports those sourcesunavailableand works from whatever remains; the hosted demo on Vercel reaches all three.
Layout
nota/
envelope.py RYO public response contract + REST/MCP parsers
ryo_client.py RyoClient (httpx) + RecordedRyoClient + record()
ledger.py SQLite: evidence, llm_cache, decisions, outcomes
evidence.py EvidencePack, ryo_args(), gather(), candidate_symbols(), path lookups
paths.py candidate paths for price / ATR (one place to fix when the live schema is recorded)
llm.py LLM protocol, AnthropicLLM (messages.parse), OpenAICompatLLM (Venice/OpenRouter)
council.py role prompts, Opinion/Verdict, citation validation, cached run_council()
risk.py size_trade(): PracticeTrade | Blocked
receipt.py Receipt + markdown rendering
notify.py Telegram Bot API + Discord webhook publishing
api.py FastAPI read API + static/index.html dashboard
skills/ contract, sources (Telegram, Bluesky, X syndication, RSS, Tavily, Venice), narrative, news, price_check
decide.py / replay.py / calibration.py / cli.py
static/ landing.html + landing.ja.html (same page, `/` and `/ja`), index.html (dashboard),
demo.html (walkthrough + transcript), landing.css + landing.js shared by both languages
scripts/ screenshots.py, narration.py, demo_video.py
video/ Remotion composition that puts the narration onto the recording
docs/ hackathon analysis, MCP builder guide copy, design spec, skill spec, submission draft
tests/ pytest, no network (respx + FakeLLM test double)
Disclosed third-party libraries
httpx, pydantic, anthropic, typer, python-dotenv, fastapi, uvicorn, vaderSentiment (MIT),
defusedxml, pillow; dev: pytest, respx, playwright (browser end-to-end tests in
tests/test_dashboard_e2e.py and QA in tests/test_qa_browser.py, run after
uv run playwright install chromium), edge-tts and Remotion (walkthrough only, see below). Data sources:
RYO MCP, t.me/s previews, Bluesky public AppView, X public syndication, CoinDesk /
Cointelegraph / The Block / Decrypt RSS, CoinGecko, Coinbase, Kraken and alternative.me public
APIs, Tavily or Venice web search.
No starter template was used: the repository began empty and every line of application code was
written during the hackathon. Two external things touched the work without entering it, and are
named here for completeness: the taste-skill design ruleset (Leon Lin, MIT) was installed with
npx skills add and read while reshaping the interface, and it is gitignored rather than vendored,
so no file of it ships here; and the demo assets under docs/img and docs/demo are generated by
scripts/screenshots.py and scripts/demo_video.py from this project's own dashboard, not sourced
from anywhere.
Three tools build the walkthrough and none of them ships inside the application: edge-tts
(GPL-3.0, Microsoft's public neural voices, no key) reads the narration, Playwright records the
pages, and Remotion (Remotion License — free for individuals and for companies of three people
or fewer, paid above that; see https://remotion.dev/license) composes the result. They are
development dependencies of video/, invoked from scripts/, and no Remotion or edge-tts code is
served to a visitor or imported by nota. The narration is written here, not generated: the voice
is synthetic, the script is not. Fixtures under tests/fixtures/ are hand-built and labelled source: fixture;
fixtures/recorded/ holds real RYO responses captured with nota record and labelled
source: recorded; tests/fixtures/x/ holds one real payload captured from X's public syndication
endpoint on 2026-09-07.
No secret has ever been committed. Verified across the whole history, not just the working tree:
49 commits, 448 blobs, twelve credential patterns (RYO builder keys, Anthropic, OpenAI, OpenRouter,
Venice, Tavily, Telegram bot tokens, Discord webhooks, AWS, GitHub and Vercel tokens, PEM private
keys). The single match is ryo_mcp_your_private_key, the placeholder inside RYO's own builder
guide quoted at docs/MCP-Builder-Guide.md. No .env or credential file was added in any commit.
Reviews
No reviews yet
Be the first to review this server!
More Developer Tools MCP Servers
Paperclip
Freeby Paperclipai · Developer Tools
Trending hip-hop artist momentum scores across four cultural dimensions.
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-creator-python
Freeby mcp-marketplace · Developer Tools
Create, build, and publish Python MCP servers to PyPI — conversationally.
MCP Marketplace
Freeby mcp-marketplace · Developer Tools
Search and install MCP servers from inside your AI client.
MarkItDown
Freeby Microsoft · Content & Media
Convert files (PDF, Word, Excel, images, audio) to Markdown for LLM consumption
