{"_id":"@canopy-finance/rwa-mcp","_rev":"2-38d12c9ad0975011b05b11700e4e71aa","name":"@canopy-finance/rwa-mcp","dist-tags":{"latest":"0.5.1"},"versions":{"0.5.0":{"name":"@canopy-finance/rwa-mcp","version":"0.5.0","keywords":["mcp","model-context-protocol","rwa","real-world-assets","robinhood-chain","pyth","x402","ai-agents","defi"],"license":"MIT","_id":"@canopy-finance/rwa-mcp@0.5.0","maintainers":[{"name":"canopy-finance","email":"heyagentsol@gmail.com"}],"homepage":"https://github.com/canopyfinance/canopy-rwa-mcp#readme","bugs":{"url":"https://github.com/canopyfinance/canopy-rwa-mcp/issues"},"bin":{"canopy-rwa-mcp":"dist/index.js"},"dist":{"shasum":"53af84e66dc7abd6d59a0f451c05de7f4ad2a6de","tarball":"https://registry.npmjs.org/@canopy-finance/rwa-mcp/-/rwa-mcp-0.5.0.tgz","fileCount":100,"integrity":"sha512-eUjOVv11jdZPIp63iViOGnfEMWj8VGchdaJKx+brFL4//qlQwWnlWwA2bXP8E3cwgasG7iKWd1Hxt+QZbU7zKg==","signatures":[{"sig":"MEYCIQCJwdGa4aomlt9jDSUS60n54jg0+gGhbn3bWpypcbtvOgIhAJPGrdRDG6r6fIGl2EeO2VSFNbHWg63zlhl3KBbY/cVW","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":272600},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"dev":"tsx src/index.ts","lint":"eslint . --ext .ts","test":"vitest run","build":"tsc -p tsconfig.json","start":"node dist/index.js","doctor":"node dist/index.js doctor","format":"prettier --write .","typecheck":"tsc -p tsconfig.json --noEmit","test:watch":"vitest","format:check":"prettier --check .","prepublishOnly":"npm run typecheck && npm run lint && npm run test && npm run build","verify:registry":"tsx scripts/verify-registry.ts"},"_npmUser":{"name":"canopy-finance","email":"heyagentsol@gmail.com"},"repository":{"url":"git+https://github.com/canopyfinance/canopy-rwa-mcp.git","type":"git"},"_npmVersion":"11.9.0","description":"Turn any AI into an RWA agent. MCP server for safe, structured access to tokenized real-world assets on Robinhood Chain: registry, Pyth Hermes prices (multiplier-adjusted, market-hours aware), portfolio analytics, policy-gated transfer intents + simulatio","directories":{},"_nodeVersion":"25.6.1","dependencies":{"zod":"^3.23.8","viem":"^2.21.0","dotenv":"^17.4.2","@modelcontextprotocol/sdk":"^1.0.0","@canopy-finance/x402-client":"0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.16.0","eslint":"^9.0.0","vitest":"^2.0.0","prettier":"^3.3.0","@eslint/js":"^9.39.5","typescript":"^5.5.0","@types/node":"^20.14.0","@typescript-eslint/parser":"^8.0.0","@typescript-eslint/eslint-plugin":"^8.0.0"},"_npmOperationalInternal":{"tmp":"tmp/rwa-mcp_0.5.0_1783948932295_0.07638793601931204","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"@canopy-finance/rwa-mcp","version":"0.5.1","description":"Turn any AI into an RWA agent. MCP server for safe, structured access to tokenized real-world assets on Robinhood Chain: registry, Pyth Hermes prices (multiplier-adjusted, market-hours aware), portfolio analytics, policy-gated transfer intents + simulatio","type":"module","engines":{"node":">=20"},"bin":{"canopy-rwa-mcp":"dist/index.js"},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"build":"tsc -p tsconfig.json","postbuild":"node -e \"require('fs').chmodSync('dist/index.js', 0o755)\"","dev":"tsx src/index.ts","start":"node dist/index.js","doctor":"node dist/index.js doctor","verify:registry":"tsx scripts/verify-registry.ts","test":"vitest run","test:watch":"vitest","typecheck":"tsc -p tsconfig.json --noEmit","lint":"eslint . --ext .ts","format":"prettier --write .","format:check":"prettier --check .","prepublishOnly":"npm run typecheck && npm run lint && npm run test && npm run build"},"dependencies":{"@canopy-finance/x402-client":"0.1.0","@modelcontextprotocol/sdk":"^1.0.0","dotenv":"^17.4.2","viem":"^2.21.0","zod":"^3.23.8"},"devDependencies":{"@eslint/js":"^9.39.5","@types/node":"^20.14.0","@typescript-eslint/eslint-plugin":"^8.0.0","@typescript-eslint/parser":"^8.0.0","eslint":"^9.0.0","prettier":"^3.3.0","tsx":"^4.16.0","typescript":"^5.5.0","vitest":"^2.0.0"},"keywords":["mcp","model-context-protocol","rwa","real-world-assets","robinhood-chain","pyth","x402","ai-agents","defi"],"repository":{"type":"git","url":"git+https://github.com/canopyfinance/canopy-rwa-mcp.git"},"homepage":"https://github.com/canopyfinance/canopy-rwa-mcp#readme","bugs":{"url":"https://github.com/canopyfinance/canopy-rwa-mcp/issues"},"license":"MIT","publishConfig":{"access":"public"},"_id":"@canopy-finance/rwa-mcp@0.5.1","_nodeVersion":"25.6.1","_npmVersion":"11.9.0","dist":{"integrity":"sha512-wjuJWPB3P4TVmd1lFN7CooESEBd/+BbkwQlXaGtrJeVsbktbQ+RIP8cBN4z2w3Ar6Sy8X4Pj358PrkH9pQoHlg==","shasum":"d8c1b16b4350f2f9eb101fc32fae374ae77b910b","tarball":"https://registry.npmjs.org/@canopy-finance/rwa-mcp/-/rwa-mcp-0.5.1.tgz","fileCount":100,"unpackedSize":272678,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIEZvkNXnASY78LJFA2rkM5dfVzLJh3Z+9c3CtvGB43fTAiEAz8161CsqfV/y1jC8/q1r96XY8pDMTH+t93UxrX5Sn5Q="}]},"_npmUser":{"name":"canopy-finance","email":"heyagentsol@gmail.com"},"directories":{},"maintainers":[{"name":"canopy-finance","email":"heyagentsol@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/rwa-mcp_0.5.1_1783949528624_0.3753434445364705"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-13T13:22:12.200Z","modified":"2026-07-13T13:32:08.929Z","0.5.0":"2026-07-13T13:22:12.426Z","0.5.1":"2026-07-13T13:32:08.812Z"},"bugs":{"url":"https://github.com/canopyfinance/canopy-rwa-mcp/issues"},"license":"MIT","homepage":"https://github.com/canopyfinance/canopy-rwa-mcp#readme","keywords":["mcp","model-context-protocol","rwa","real-world-assets","robinhood-chain","pyth","x402","ai-agents","defi"],"repository":{"type":"git","url":"git+https://github.com/canopyfinance/canopy-rwa-mcp.git"},"description":"Turn any AI into an RWA agent. MCP server for safe, structured access to tokenized real-world assets on Robinhood Chain: registry, Pyth Hermes prices (multiplier-adjusted, market-hours aware), portfolio analytics, policy-gated transfer intents + simulatio","maintainers":[{"name":"canopy-finance","email":"heyagentsol@gmail.com"}],"readme":"# Canopy RWA MCP\n\n**Turn any AI into an RWA agent.**\n\nCanopy RWA MCP gives AI agents safe, structured access to tokenized real-world assets on\nRobinhood Chain.\n\nIt is a [Model Context Protocol](https://modelcontextprotocol.io) server that exposes a\ncurated asset registry, live [Pyth](https://pyth.network) Hermes prices (multiplier- and\nmarket-hours-adjusted), portfolio valuation and analytics, policy-gated transfer intents\nwith read-only simulation, and (optionally) [x402](https://x402.org) payments — all over\nstdio.\n\n### Why this exists: correct prices for permissioned assets\n\nRobinhood's own Chainlink feeds for these tokens are **permissioned** — the addresses page\nsays \"contact us\", so there is no open on-chain feed to read. Canopy prices these assets\ncorrectly anyway: **Pyth Hermes** share prices over HTTPS, adjusted by each token's\non-chain `uiMultiplier()` (a Robinhood Stock Token is not one share — reinvested dividends\nmove the multiplier), **market-hours aware** (equity feeds are 24/5), corporate-action\naware, and **fail-closed** (a Hermes outage is a structured `PRICE_UNAVAILABLE`, never a\nsilent zero). This is **not** an on-chain Chainlink read. See [PRICES.md](./PRICES.md).\n\n`MARKET_CLOSED` is a valid price state, not an error: outside 09:30–16:00 ET the last\nprice is old by design and is still returned (with a `MARKET_CLOSED` warning). Only `STALE`\n(market open but too old), `PAUSED`, and `INVALID` fail hard.\n\n---\n\n## Install\n\nRun directly with `npx` (no install needed):\n\n```bash\nnpx -y @canopy-finance/rwa-mcp\n```\n\nOr install globally:\n\n```bash\nnpm install -g @canopy-finance/rwa-mcp\ncanopy-rwa-mcp doctor   # check your environment before wiring it up\n```\n\nRequires Node.js >= 20.\n\n## Configure your MCP client\n\nAdd this to your MCP client config (e.g. Claude Desktop's `claude_desktop_config.json`,\nCursor's `mcp.json`, etc.):\n\n```json\n{\n  \"mcpServers\": {\n    \"canopy-rwa\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@canopy-finance/rwa-mcp\"],\n      \"env\": {\n        \"ROBINHOOD_RPC_URL\": \"https://your-robinhood-rpc.example\",\n        \"ROBINHOOD_CHAIN_ID\": \"4663\",\n        \"RWA_POLICY_PATH\": \"/absolute/path/to/policy.json\"\n      }\n    }\n  }\n}\n```\n\nThe MCP client passes `env` directly (the stdio server reads only that env, never a\n`.env` file). Prices default to Pyth Hermes (`PYTH_HERMES_URL`); the registry ships with\nreal Robinhood Chain addresses built in. See [`.env.example`](./.env.example) for every\nsupported variable, and run `canopy-rwa-mcp doctor` to validate your setup before going\nlive.\n\n## First run\n\nThe CLI (unlike the server) reads a local `.env`, so a quick local setup is:\n\n```bash\ncp .env.example .env\n# edit .env: set ROBINHOOD_RPC_URL (everything else has a safe default)\n\ncp policy.example.json policy.json\n# edit policy.json: add your allowed recipient address(es) to allowedRecipients\n# (it ships empty, which conservatively blocks every transfer until you fill it in)\n\n# point the server at your policy, then diagnose:\nexport RWA_POLICY_PATH=\"$PWD/policy.json\"\ncanopy-rwa-mcp doctor\n```\n\n`doctor` loads `.env` for you (real environment variables always win over the file) and\nprints a PASS/WARN/FAIL report. `RWA_POLICY_PATH` turns check 8 from WARN to PASS.\n\n## Tools\n\n| Tool                      | What it does                                                              | Needs signing? |\n| ------------------------- | ------------------------------------------------------------------------ | -------------- |\n| `list_supported_assets`   | List the RWA assets known to the server.                                  | No             |\n| `resolve_asset`           | Resolve an asset by symbol (case-insensitive), name, or token address.   | No             |\n| `get_asset_metadata`      | Registry metadata for a supported token address (allowlist enforced).    | No             |\n| `get_asset_price`         | Current Pyth price; stale/negative prices are hard errors, never faked.  | No             |\n| `get_rwa_balance`         | A wallet's balance of one asset (atomic + formatted).                    | No             |\n| `get_rwa_portfolio`       | Whole-wallet scan (one balance multicall) + Pyth valuation & allocation. | No             |\n| `analyze_rwa_portfolio`   | Deterministic concentration / stable-allocation / risk-flag analytics.   | No             |\n| `create_transfer_intent`  | Build a canonical `erc20_transfer` intent (integrity hash + expiry).     | No             |\n| `validate_intent`         | Check an intent against the operator policy; fails closed on valuation.  | No             |\n| `simulate_transaction`    | Read-only `estimateGas` simulation. Never broadcasts; not approval.      | No             |\n| `purchase_x402_resource`  | Pay for an x402-gated resource (SSRF-guarded, idempotent, capped).       | **Yes**        |\n\n`purchase_x402_resource` is only present when `ENABLE_SIGNING=true` and a signer is\nconfigured — otherwise it is absent from `tools/list` (10 tools vs 11). Everything else is\nread-only.\n\n## Example prompts\n\n- \"What RWA assets can I access, and which are stablecoins?\"\n- \"What's the current price of NVDA?\"\n- \"Show me the portfolio for 0xabc…def and its allocation breakdown.\"\n- \"Analyze that wallet's concentration risk and flag anything over 35% in one asset.\"\n- \"Draft a transfer of 2 NVDA from my wallet to 0x123…, then validate it against policy.\"\n- \"Simulate that transfer and tell me the gas estimate and whether it would revert.\"\n\nThe agent turns these into structured tool calls; the deterministic code enforces the\nrules.\n\n## Read-only by default. AI proposes, deterministic code disposes.\n\nThe AI never gets to decide what is allowed. It can propose actions, but every limit is\nenforced by deterministic, operator-owned code that the agent cannot reach or change:\n\n- Ten of the eleven tools are **read-only**. The one that can move value\n  (`purchase_x402_resource`) is **absent** unless the operator explicitly enables signing.\n- Transfers are only ever **intents** — signed typed data at most, never broadcast. This\n  server has **no** `sendTransaction` / `writeContract` / broadcast path anywhere.\n- What a transfer may do is bounded by an **operator-owned policy** loaded at startup and\n  immutable at runtime. The agent cannot set, replace, or read it. Overrides may only\n  **tighten** it. See [POLICY.md](./POLICY.md).\n- x402 payments are bounded by an **absolute env payment ceiling** the agent cannot raise,\n  guarded by an SSRF wall and deterministic idempotency. See [X402.md](./X402.md).\n\nThe threat model is spelled out in [SECURITY.md](./SECURITY.md): **the agent is untrusted\nand may be prompt-injected.** The guardrails assume that.\n\n## CLI\n\n```bash\ncanopy-rwa-mcp                 # start the stdio MCP server (default)\ncanopy-rwa-mcp doctor          # environment & readiness checks (exit non-zero on FAIL)\ncanopy-rwa-mcp assets          # list registry assets (placeholders flagged loudly)\ncanopy-rwa-mcp inspect-config  # print resolved config with secrets redacted\n```\n\nSubcommands write to stderr only; stdout is reserved for the MCP transport.\n\n## Assets\n\nThe built-in registry ships **26** Robinhood Chain assets with real on-chain addresses:\n**21 enabled** — USDG + 17 stocks + 3 ETFs — of which **20 have live Pyth price feeds**\n(USDG is pinned to `$1.00`, no feed needed). **5 are disabled**:\n\n- `SPCX`, `CUSO` — no Pyth feed exists.\n- `BE`, `USAR`, `SLV` — a feed id is registered but not currently publishing.\n\nThis is a curated set, **not** \"all Robinhood stock tokens\". You can override the registry\nwith your own via `RWA_REGISTRY_PATH`.\n\n## Limitations\n\n- **No swaps, no execution, no custody in V1.** The server builds and validates intents\n  and simulates them; it never signs a transfer broadcast, and never holds assets.\n- **`purchase_x402_resource` requires a one-time on-chain Permit2 approval** that this\n  server cannot perform. A human must approve the Permit2 contract to spend the settlement\n  token once, out of band, before payments can settle. See [X402.md](./X402.md).\n\n## Documentation\n\n- [PRICES.md](./PRICES.md) — Pyth Hermes source, the on-chain `uiMultiplier()`, and price states.\n- [SECURITY.md](./SECURITY.md) — threat model and trust boundaries.\n- [POLICY.md](./POLICY.md) — operator policy and tighten-only overrides.\n- [X402.md](./X402.md) — payment flow, SSRF wall, idempotency, the required approval.\n- [RELEASE.md](./RELEASE.md) — the release checklist.\n\n## License\n\n[MIT](./LICENSE).\n","readmeFilename":"README.md"}