AI tools
Read these docs as Markdown from an AI assistant, and query coverage records with the oracle's two MCP tools.
An AI assistant reads these docs as Markdown. The oracle, an MCP server, answers an assistant's questions about an institution's record.
These docs as Markdown
Every page is available as plain Markdown, built from the same source as the HTML page.
| URL | What it returns |
|---|---|
https://docs.joinsolva.xyz/llms.txt | An index of every page, with its title, description and a link to its Markdown version. |
https://docs.joinsolva.xyz/llms-full.txt | Every page in one Markdown file. |
https://docs.joinsolva.xyz/docs/<page>.md | One page. Add .md to any page URL, for example /docs/build/quickstart.md. The docs home is /docs.md. |
Each Markdown page starts with the page title and description. Each HTML page also points to its Markdown version with a text/markdown alternate link in its head.
Give an assistant llms.txt when it should find the right page itself, and llms-full.txt when it should read everything at once.
Page actions
Under every page title:
- Copy Markdown copies the page's Markdown to your clipboard.
- Open shows a menu: Open in GitHub, View as Markdown, Open in Scira AI, Open in ChatGPT, Open in Claude and Open in Cursor. The assistant links open with the prompt "Read
<page URL>, I want to ask questions about it."
The oracle
The oracle is an MCP server in services/oracle. MCP, the Model Context Protocol, is how an AI assistant calls tools that a server exposes. The oracle exposes two tools about an institution's coverage: get_solvency and get_anomalies. It runs over stdio.
Answers from a live orchestrator Coming soon depend on the SDK's orchestrator calls, which the oracle reads through. The tools, their inputs and their outputs are described below as they work once those calls match the orchestrator.
Run it
From the repository root, build it and point your MCP client at the built server:
pnpm exec turbo run build --filter=@solva/oracle{
"mcpServers": {
"solva-oracle": {
"command": "node",
"args": ["/path/to/solva/services/oracle/dist/server.js"],
"env": {
"SOLVA_NETWORK": "testnet",
"SOLVA_ORCHESTRATOR_URL": "http://localhost:8080",
"SOLVA_CONTRACT_ID": "CAFUK25F56VW442VAOHDKGMPYF2BZ3ERVLVAM4H6JTN2WGZPDUQLRTPN"
}
}
}
}| Variable | Default | Meaning |
|---|---|---|
SOLVA_NETWORK | testnet | testnet, mainnet or local. Picks the SDK's default endpoints. |
SOLVA_ORCHESTRATOR_URL | the SDK default | Orchestrator the oracle reads stored proofs from. |
SOLVA_RPC_URL | the SDK default | Soroban RPC for the on-chain read. |
SOLVA_CONTRACT_ID | none | A registry to read. When unset, the SDK asks the orchestrator for the institution's registry. |
SOLVA_API_TOKEN | none | Sent as a bearer token on orchestrator calls. |
get_solvency
Returns whether an institution's reserves cover its liabilities, confirmed by a read of its own registry on Stellar.
Input
| Field | Type | Meaning |
|---|---|---|
institution_id | string, at least 1 character | The institution's tenant UUID. |
How it answers. It reads the institution's latest stored proof through the SDK's getLatestProof. It then reads the latest proof from the institution's registry on chain with getOnChainLatestProof and checks that R >= L there. If the on-chain read fails, it reports verifiedOnChain: false instead of an error.
Output. One text item holding this JSON:
{
"status": "solvent",
"solvent": true,
"reservesTotal": "16000000",
"liabilitiesTotal": "9000000",
"proofId": "1",
"verifiedOnChain": true,
"asOf": 1793685990
}| Field | Type | Meaning |
|---|---|---|
status | string | solvent when covered and confirmed on chain, otherwise breach. |
solvent | boolean | true only when the on-chain read succeeded and reserves cover liabilities. |
reservesTotal | string | R, minor units. |
liabilitiesTotal | string | L, minor units. |
proofId | string | The proof's id. |
verifiedOnChain | boolean | true when the on-chain read succeeded and showed R >= L. |
asOf | number | When the proof was published, Unix seconds. |
The field and value names are the tool's API. In these docs the same idea is called coverage: solvent: true means the record shows reserves covering liabilities.
get_anomalies
Returns flags raised by comparing each of an institution's proofs with the one before it. It uses only the public totals and timestamps, so it needs no private data.
Input
| Field | Type | Meaning |
|---|---|---|
institution_id | string, at least 1 character | The institution's tenant UUID. |
Output. One text item holding a JSON array of flags:
[
{
"kind": "reserve_drift",
"severity": "critical",
"proofId": "2",
"value": -40.62,
"threshold": -10,
"message": "Reserves fell 40.62% from the previous cycle.",
"detectedAt": 1793772390
}
]| Field | Type | Meaning |
|---|---|---|
kind | string | reserve_drift, liability_spike or cycle_timing_gap. |
severity | string | warning at or past the threshold, critical at twice the threshold or more. |
proofId | string | The later proof of the two compared. |
value | number | The measured change in percent, or the gap in seconds. |
threshold | number | The threshold crossed. Negative for reserve drift. |
message | string | A plain sentence describing the flag. |
detectedAt | number | Publish time of the later proof, Unix seconds. |
The thresholds are DEFAULT_THRESHOLDS in packages/shared-types/src/anomaly.ts:
| Flag | Raised when | Default |
|---|---|---|
reserve_drift | Reserves fall by at least this percent from the previous proof. A rise never raises it. | 10% |
liability_spike | Liabilities rise by at least this percent from the previous proof. | 15% |
cycle_timing_gap | More than this many seconds pass between two proofs. | 93,600 s (26 hours: a daily cycle plus 2 hours) |
Percent changes are computed on the integer totals with BigInt and truncated to two decimal places.
A flag needs two proofs to compare. Today the oracle passes only the latest proof, so get_anomalies raises no flag yet. Reading the full proof history comes with answers from a live orchestrator. The example above shows the shape a flag takes. A move from solvent (16,000,000) to near-breach (9,500,000) is a 40.62% fall, more than twice the 10% threshold, so it is critical.
Next: Changelog.