Machine layer
An AI agent can find dollar yield trivially. There is no machine-readable source of truth for currency-denominated yield, which means an agent holding a non-dollar liability cannot make a currency-aware allocation at all. That gap is wider than the human one. This is the read API and the MCP server that close it.
Static JSON, no key, no rate limit, CORS open. Every response carries the same source URLs and confidence labels the site shows, because an agent needs the provenance more than a human does, not less.
GET /v1/instruments.json all 40 instruments
GET /v1/currencies.json all 24 currencies, covered and empty
GET /v1/rates.json policy rates, spot FX, 3M forward carry
GET /v1/coverage.json gaps, empty shelves, dead ends
GET /v1/currency/{CCY}.json one currency and its instruments
GET /v1/instrument/{id}.json one instrument
Every instrument carries an access block giving its tier, what the tier means in a
sentence, and a verified_holdable boolean. Every currency carries
best_reachable alongside best_published_yield_pct. Read the first of each
pair. The second is kept because removing a field breaks consumers, and it is the misleading one
wherever the two differ: it says 3.00% for the yen and 2.50% for the Hong Kong dollar, and neither
is an instrument anyone reading this can own.
$ curl -s protean.finance/v1/currency/CAD.json | jq '{status, n: (.instruments|length)}'
{
"status": "empty_shelf",
"n": 0
}
That is the honest answer for Canadian dollars today, and an agent that gets it can stop looking instead of allocating into something that is not what it says it is.
The same dataset over Model Context Protocol, so an agent can ask the question in its own terms rather than parsing a table.
{
"mcpServers": {
"protean": {
"command": "node",
"args": ["/path/to/protean/mcp/server.js"]
}
}
}
Tools exposed: list_currencies, get_currency,
list_instruments, get_instrument, best_yield,
compare_currency, get_rates, coverage_report. The four
documents above are also attachable as MCP resources.
best_yield takes a currency and an eligibility profile and returns what that holder
can actually reach, which is a different answer from the highest number in the table. Most of the
top of this index is permissioned, and an agent that ignores eligibility will confidently recommend
an instrument its principal is not allowed to own. The three profiles are
permissionless_only, which is the only correct setting for a contract that cannot
complete onboarding, will_onboard, which is the default and adds allowlisted
instruments, and include_unverified, which adds the rows whose transfer terms no issuer
publishes. Every profile returns the figures it excluded and why, so a rate quoted at you elsewhere
is accounted for rather than missing.
The server does no reasoning of its own. It reads the JSON above, which already carries the access tier for every instrument, computed once in the site build. Reimplementing the reachability rules in the machine layer would have been thirty lines and would eventually have disagreed with these pages, and a data layer whose two faces give different answers is worse than no data layer.
Free. Attribution appreciated, not required. This data is published, not warranted: read the method page for what is verified and what is not, and do not put an unverified row into a production allocation decision without checking it yourself.