npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@canopy-finance/rwa-mcp

v0.5.1

Published

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

Downloads

243

Readme

Canopy RWA MCP

Turn any AI into an RWA agent.

Canopy RWA MCP gives AI agents safe, structured access to tokenized real-world assets on Robinhood Chain.

It is a Model Context Protocol server that exposes a curated asset registry, live Pyth Hermes prices (multiplier- and market-hours-adjusted), portfolio valuation and analytics, policy-gated transfer intents with read-only simulation, and (optionally) x402 payments — all over stdio.

Why this exists: correct prices for permissioned assets

Robinhood's own Chainlink feeds for these tokens are permissioned — the addresses page says "contact us", so there is no open on-chain feed to read. Canopy prices these assets correctly anyway: Pyth Hermes share prices over HTTPS, adjusted by each token's on-chain uiMultiplier() (a Robinhood Stock Token is not one share — reinvested dividends move the multiplier), market-hours aware (equity feeds are 24/5), corporate-action aware, and fail-closed (a Hermes outage is a structured PRICE_UNAVAILABLE, never a silent zero). This is not an on-chain Chainlink read. See PRICES.md.

MARKET_CLOSED is a valid price state, not an error: outside 09:30–16:00 ET the last price is old by design and is still returned (with a MARKET_CLOSED warning). Only STALE (market open but too old), PAUSED, and INVALID fail hard.


Install

Run directly with npx (no install needed):

npx -y @canopy-finance/rwa-mcp

Or install globally:

npm install -g @canopy-finance/rwa-mcp
canopy-rwa-mcp doctor   # check your environment before wiring it up

Requires Node.js >= 20.

Configure your MCP client

Add this to your MCP client config (e.g. Claude Desktop's claude_desktop_config.json, Cursor's mcp.json, etc.):

{
  "mcpServers": {
    "canopy-rwa": {
      "command": "npx",
      "args": ["-y", "@canopy-finance/rwa-mcp"],
      "env": {
        "ROBINHOOD_RPC_URL": "https://your-robinhood-rpc.example",
        "ROBINHOOD_CHAIN_ID": "4663",
        "RWA_POLICY_PATH": "/absolute/path/to/policy.json"
      }
    }
  }
}

The MCP client passes env directly (the stdio server reads only that env, never a .env file). Prices default to Pyth Hermes (PYTH_HERMES_URL); the registry ships with real Robinhood Chain addresses built in. See .env.example for every supported variable, and run canopy-rwa-mcp doctor to validate your setup before going live.

First run

The CLI (unlike the server) reads a local .env, so a quick local setup is:

cp .env.example .env
# edit .env: set ROBINHOOD_RPC_URL (everything else has a safe default)

cp policy.example.json policy.json
# edit policy.json: add your allowed recipient address(es) to allowedRecipients
# (it ships empty, which conservatively blocks every transfer until you fill it in)

# point the server at your policy, then diagnose:
export RWA_POLICY_PATH="$PWD/policy.json"
canopy-rwa-mcp doctor

doctor loads .env for you (real environment variables always win over the file) and prints a PASS/WARN/FAIL report. RWA_POLICY_PATH turns check 8 from WARN to PASS.

Tools

| Tool | What it does | Needs signing? | | ------------------------- | ------------------------------------------------------------------------ | -------------- | | list_supported_assets | List the RWA assets known to the server. | No | | resolve_asset | Resolve an asset by symbol (case-insensitive), name, or token address. | No | | get_asset_metadata | Registry metadata for a supported token address (allowlist enforced). | No | | get_asset_price | Current Pyth price; stale/negative prices are hard errors, never faked. | No | | get_rwa_balance | A wallet's balance of one asset (atomic + formatted). | No | | get_rwa_portfolio | Whole-wallet scan (one balance multicall) + Pyth valuation & allocation. | No | | analyze_rwa_portfolio | Deterministic concentration / stable-allocation / risk-flag analytics. | No | | create_transfer_intent | Build a canonical erc20_transfer intent (integrity hash + expiry). | No | | validate_intent | Check an intent against the operator policy; fails closed on valuation. | No | | simulate_transaction | Read-only estimateGas simulation. Never broadcasts; not approval. | No | | purchase_x402_resource | Pay for an x402-gated resource (SSRF-guarded, idempotent, capped). | Yes |

purchase_x402_resource is only present when ENABLE_SIGNING=true and a signer is configured — otherwise it is absent from tools/list (10 tools vs 11). Everything else is read-only.

Example prompts

  • "What RWA assets can I access, and which are stablecoins?"
  • "What's the current price of NVDA?"
  • "Show me the portfolio for 0xabc…def and its allocation breakdown."
  • "Analyze that wallet's concentration risk and flag anything over 35% in one asset."
  • "Draft a transfer of 2 NVDA from my wallet to 0x123…, then validate it against policy."
  • "Simulate that transfer and tell me the gas estimate and whether it would revert."

The agent turns these into structured tool calls; the deterministic code enforces the rules.

Read-only by default. AI proposes, deterministic code disposes.

The AI never gets to decide what is allowed. It can propose actions, but every limit is enforced by deterministic, operator-owned code that the agent cannot reach or change:

  • Ten of the eleven tools are read-only. The one that can move value (purchase_x402_resource) is absent unless the operator explicitly enables signing.
  • Transfers are only ever intents — signed typed data at most, never broadcast. This server has no sendTransaction / writeContract / broadcast path anywhere.
  • What a transfer may do is bounded by an operator-owned policy loaded at startup and immutable at runtime. The agent cannot set, replace, or read it. Overrides may only tighten it. See POLICY.md.
  • x402 payments are bounded by an absolute env payment ceiling the agent cannot raise, guarded by an SSRF wall and deterministic idempotency. See X402.md.

The threat model is spelled out in SECURITY.md: the agent is untrusted and may be prompt-injected. The guardrails assume that.

CLI

canopy-rwa-mcp                 # start the stdio MCP server (default)
canopy-rwa-mcp doctor          # environment & readiness checks (exit non-zero on FAIL)
canopy-rwa-mcp assets          # list registry assets (placeholders flagged loudly)
canopy-rwa-mcp inspect-config  # print resolved config with secrets redacted

Subcommands write to stderr only; stdout is reserved for the MCP transport.

Assets

The built-in registry ships 26 Robinhood Chain assets with real on-chain addresses: 21 enabled — USDG + 17 stocks + 3 ETFs — of which 20 have live Pyth price feeds (USDG is pinned to $1.00, no feed needed). 5 are disabled:

  • SPCX, CUSO — no Pyth feed exists.
  • BE, USAR, SLV — a feed id is registered but not currently publishing.

This is a curated set, not "all Robinhood stock tokens". You can override the registry with your own via RWA_REGISTRY_PATH.

Limitations

  • No swaps, no execution, no custody in V1. The server builds and validates intents and simulates them; it never signs a transfer broadcast, and never holds assets.
  • purchase_x402_resource requires a one-time on-chain Permit2 approval that this server cannot perform. A human must approve the Permit2 contract to spend the settlement token once, out of band, before payments can settle. See X402.md.

Documentation

  • PRICES.md — Pyth Hermes source, the on-chain uiMultiplier(), and price states.
  • SECURITY.md — threat model and trust boundaries.
  • POLICY.md — operator policy and tighten-only overrides.
  • X402.md — payment flow, SSRF wall, idempotency, the required approval.
  • RELEASE.md — the release checklist.

License

MIT.