# @getplexa/mcp — Plexa MCP server ![license: MIT](https://img.shields.io/badge/license-MIT-6ee7a8) ![chains: Base · Polygon · Arbitrum](https://img.shields.io/badge/chains-Base%20%C2%B7%20Polygon%20%C2%B7%20Arbitrum-9aa8f0) ![x402](https://img.shields.io/badge/payments-x402-aab4f0) ![MCP](https://img.shields.io/badge/protocol-MCP-c4b5fd) A [Model Context Protocol](https://modelcontextprotocol.io) server that gives any MCP client (Claude Desktop, Cursor, your own agent) two economic-safety tools from **[Plexa](https://getplexa.com)** — the x402-native **economic-safety layer for trading agents** — paid per call in USDC, no accounts: | Tool | Wraps | Price | Returns | |---|---|---|---| | `plexa_quote` | `POST /v1/quote` | $0.02 | **Executable** fill price under size (not mid/spot), price impact (bps), realizable depth, per-leg route, worst-case slippage, confidence — from canonical on-chain quoters on Base, Polygon & Arbitrum. | | `plexa_pretrade_check` | `POST /v1/pretrade/check` | $0.05 | Two levels. **`verdict`**: `avoid` only when a listed trap is *proven* on-chain at that block (no pool to exit into · the counter-asset pot is under 5% of your size, and the pot is a hard upper bound on what a sale can return · the token's own trading gate is off), `clear` otherwise — `clear` means *no provable trap*, **not** "safe". **`risk_profile`**: age, holder concentration, liquidity depth incl. `exitLiquidityUsd`, oracle availability, transfer limits — as data you weigh, not as a rating. Plus reasons, confidence and an executable quote. (Base-only today.) | It is a **thin client of the public API** (`https://api.getplexa.com`) — it pays a `402` automatically, signs the USDC authorization **locally** with your wallet, and never sees your key. The liquidity engine stays behind the API. --- ## Why A generic wallet guard answers *"can I sign this transaction?"*. It can't answer the **economic** question an automated trader actually needs: *what price will this swap really fill at under my size, and is this token a trap (rug / honeypot / thin liquidity)?* Plexa answers both. This package puts those answers one tool-call away inside any MCP-speaking agent. --- ## Install Nothing to install — point your MCP client at the package via `npx`. It is fetched and run on demand. ### Claude Desktop Add to `claude_desktop_config.json` (**Settings → Developer → Edit Config**): ```json { "mcpServers": { "plexa": { "command": "npx", "args": ["-y", "@getplexa/mcp"], "env": { "PLEXA_BASE_URL": "https://api.getplexa.com", "AGENT_WALLET_KEY": "0x", "CHAIN": "base" } } } } ``` ### Cursor Add to `~/.cursor/mcp.json` (or **Settings → MCP → Add**) — the same `mcpServers` block as above. Restart the client. You should see the `plexa_quote` and `plexa_pretrade_check` tools available. --- ## Configuration All configuration is via environment variables (set in the `env` block of your MCP config): | Variable | Default | Notes | |---|---|---| | `PLEXA_BASE_URL` | `https://api.getplexa.com` | The public API. The real URL — not a secret. | | `AGENT_WALLET_KEY` | *(none)* | **Required to pay.** Funded wallet private key — pays per call and signs locally. Plexa never receives it. Without it, tools return a clear `402`. | | `CHAIN` | `base` | `base` \| `polygon` \| `arbitrum` (aliases `matic`, `arb`, `arbitrum-one` and CAIP-2 `eip155:8453`/`137`/`42161` also work; case is normalized). The chain your wallet is funded on; quotes and payment default to it. `plexa_pretrade_check` is Base-only today — other chains answer 422. | **Funding.** Use a **dedicated, low-balance wallet** with a little USDC on `CHAIN` to pay per call (quotes $0.02, checks $0.05). The wallet signs an EIP-3009 USDC authorization per request; Plexa returns the result only after the payment settles on-chain (**settle-before-serve**). > Your key is a secret. Prefer your MCP client's secret storage if it has one. Never commit it. --- ## How payment works (x402 in MCP) MCP has no native payment. This server acts as an **x402 client**: it wraps `fetch`, so when Plexa replies `402 Payment Required` it reads the payment requirements, signs a USDC authorization with your wallet (locally), and retries. The signed authorization is the only thing that leaves your machine — **never the key**. Payment is made on `CHAIN`, so you fund **one wallet on one chain**. If no `AGENT_WALLET_KEY` is set, the tools return an honest `402` error explaining a funded wallet is needed — they never fabricate a result. --- ## Example Once configured, just ask your agent naturally — it will call the tools: > *"Before I buy this token `0x…` on Base, check it with Plexa and get me an executable quote for $500."* The agent calls `plexa_pretrade_check` (verdict + reasons) and `plexa_quote` (executable price under $500), pays $0.05 + $0.02 in USDC automatically, and answers with real on-chain economics. ## What comes back Beyond `verdict` / `triggers` / `risk_profile` / `liquidityCoverage`, every pre-trade response carries six blocks of context. Live capture, WETH, **2026-08-20T14:46:29Z**, Base block **50223921** — the `note` string each block carries is long and is cut here, nothing else is: ```json { "identity": { "name": "Wrapped Ether", "symbol": "WETH", "decimals": 18, "totalSupplyRaw": "239296586519181917702210", "totalSupply": 239296.58651918193 }, "valuation": { "fdvExecutableUsd": 543916397.6557496, "basis": "totalSupply(this chain) x executablePrice(at sizeUSD)" }, "ownership": { "ownerAddress": null, "ownerRenounced": null, "isMintable": false, "creatorAddress": "0xe8a3ecea7d6a688ee903173024225357ddf29e93", "creatorBalance": 0.000289172466091074, "creatorSharePct": 1.208427041511075e-07 }, "dormancy": { "topHolderIdleDays": null, "lastTopHolderMoveBlock": null, "headBlock": null }, "market": { "priceUsdSpot": 2277.76, "volume24hUsd": 551324354.8699999, "marketCapUsd": 542587444, "holderCount": 5223863 }, "sources": { "*": "measured", "risk_profile.concentration": "unavailable:holder-axis-produced-nothing", "flags.F_CONC": "unavailable:holder-axis-produced-nothing", "valuation": "derived:identity.totalSupply*quote.executablePrice", "dormancy": "unavailable:holder-axis-produced-no-block", "ownership.creatorAddress": "derived:sender-of-first-transfer", "ownership.isMintable": "derived:mint-selector-in-bytecode", "market": "vendor:dexscreener+goplus", "market.priceUsdSpot": "vendor:dexscreener", "market.volume24hUsd": "vendor:dexscreener", "market.marketCapUsd": "vendor:dexscreener", "market.holderCount": "vendor:goplus" } } ``` 🔴 **`sources` is the map of who said what.** `measured` — ours, read off the chain on this call. `derived:` — ours, computed from other fields of this same response. `vendor:` — somebody else's number, republished and signed as theirs. `unavailable:` — no value, **and the reason why**. That last one is the point: a missing number that names its own gap cannot be mistaken for a clean result. Two numbers that look like duplicates and are not: `valuation.fdvExecutableUsd` is THIS chain's supply at the price your size executes at; `market.marketCapUsd` is the vendor's global figure. For a bridged token ours is legitimately smaller. --- ## Notes - **Client-only.** Talks to the public Plexa API over HTTPS. No service internals ship in this package. - **Honest failures.** A non-2xx response or a network error becomes a loud tool error — never a clean-looking empty result. An agent can always tell a failure from a pass. - Built on the official [`@modelcontextprotocol/sdk`](https://github.com/modelcontextprotocol) + [x402](https://x402.org). ## License MIT — see [LICENSE](./LICENSE). Questions: **[support@getplexa.com](mailto:support@getplexa.com)** · **[getplexa.com](https://getplexa.com)** > Informational on-chain data and heuristic economic signals, **not financial advice**. Absence of flags > is not a guarantee of safety. Verify independently before trading.