AgentStack
MCP verified MIT Self-run

Sera Mcp

mcp-sera-cx-sera-mcp · by sera-cx

Multi-currency settlement MCP for AI agents. 32 tools over Sera Protocol's stablecoin FX rails. Open source.

No reviews yet
0 installs
7 views
0.0% view→install

Install

$ agentstack add mcp-sera-cx-sera-mcp

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Sera Mcp? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

sera-mcp

The core MCP server for Sera Protocol. Turns any agent into a multi-currency agent by exposing Sera Protocol — stablecoin FX settlement — as one standard tool layer. 32 tools, 5 resources, 4 slash-prompt templates. Works with Claude Code, Claude Desktop, Cursor, OpenAI Agents SDK, OpenClaw, Hermes, NanoClaw, and any other MCP-compatible host.

Who this is for: agent builders and ops engineers who need their agent to discover currencies, quote, route, and execute stablecoin FX swaps through one standard tool interface.

Companion repo: Josh-sera/sera-agents — templates, examples, x402 services, and host integrations built on top of this MCP. Site: agents.sera.cx.

For deeper reading, see [ARCHITECTURE.md](ARCHITECTURE.md), [SECURITY-MODEL.md](SECURITY-MODEL.md), and [CHANGELOG.md](CHANGELOG.md).

This package also ships a sera CLI for cron jobs, CI scripts, and ops debugging — see [CLI section](#cli) below.

What you get

32 tools across 9 categories:

| Category | Tools | |---|---| | Discovery | list_currencies, get_markets | | Pricing & analytics | get_fx_rate, compare_to_external_fx, multi_source_mid, spread_radar | | Liquidity probing | scan_markets, find_deals, probe_depth, round_trip_cost, infer_book | | Quote & execute | get_quote, prepare_swap, execute_swap, convert_and_send, quote_recipient_amount, find_cheapest_settlement_path, limit_watcher | | Maker | maker_quote_ladder | | Treasury | get_balances, treasury_value, exposure_report, rebalance_plan, pay_invoice | | Settlement | settlement_status | | History | fx_history, fx_volatility, corridor_pnl | | Admin | doctor |

5 resources (sera://currencies, sera://markets, sera://config, sera://help/tools, sera://help/quickstart) — hosts can browse without burning tool-call budget.

4 slash-prompt templates for common workflows: sera.deal_scan, sera.treasury_brief, sera.invoice_optimizer, sera.fx_integrity_check.

Install

git clone 
cd sera-mcp
npm install
npm run build

Requires Node 18.17+. Default install needs zero env vars — sensible defaults are baked in.

Wire it in

Claude Code (one line)

claude mcp add sera --scope user \
  --env SERA_NETWORK=mainnet \
  --env POLICY_PRESET=standard \
  -- node /absolute/path/to/sera-mcp/dist/index.js

Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "sera": {
      "command": "node",
      "args": ["/absolute/path/to/sera-mcp/dist/index.js"],
      "env": {
        "SERA_NETWORK": "mainnet",
        "POLICY_PRESET": "standard"
      }
    }
  }
}

Cursor

Settings → MCP → add a stdio server pointing at node /absolute/path/to/sera-mcp/dist/index.js with the same env.

Any MCP client over stdio

SERA_NETWORK=mainnet POLICY_PRESET=standard node dist/index.js

Speaks MCP over stdio. The server prints structured JSON status to stderr; stdout is reserved for the protocol.

Streamable HTTP (remote / web-served)

# Default: localhost only, DNS-rebinding protection auto-enabled, stateful sessions
node dist/index.js --transport http --port 3848

# Bind public with allowedHosts header validation
node dist/index.js --transport http --host 0.0.0.0 --port 3848 \
  --allowed-hosts mcp.mydomain.com,localhost

# Serverless / stateless mode
node dist/index.js --transport http --stateless

Endpoints:

  • POST /mcp — JSON-RPC requests
  • GET /mcp — SSE stream for notifications (stateful mode)
  • DELETE /mcp — session terminate
  • GET /health — liveness probe

> ⚠️ NO BUILT-IN AUTH ON STREAMABLE HTTP > > Anyone who can reach the bound port can call every registered Sera tool. The transport ships with DNS-rebinding protection for localhost binds and a public-bind startup guard that refuses to start when binding to a non-loopback host without --allowed-hosts or an explicit SERA_HTTP_ALLOW_UNAUTHENTICATED_PUBLIC=true acknowledgment. Do not set the ack env in production. > > Safe options: > - Localhost (default): --host 127.0.0.1 — DNS rebinding protection auto-enabled. > - Behind an auth-handling reverse proxy: --host 0.0.0.0 --allowed-hosts mcp.mydomain.com. The proxy is the trust boundary; it must handle auth (OAuth, JWT, mTLS, Cloudflare Access — your call). > - Future: OAuth 2.1 + RFC 8707 Resource Indicators per MCP spec v2025-06-18. Tracked in roadmap. > > See [SECURITY-MODEL.md](SECURITY-MODEL.md) for the full deployment matrix.

Verify install

In a new agent session, ask:

Call sera.doctor()

Returns a one-shot self-check: API health, network sanity, signer mode, policy summary, persistence state. If everything is green you're wired correctly.

Configure

Most installs need nothing. Override via env:

Network

| Variable | Default | Effect | |---|---|---| | SERA_NETWORK | mainnet | mainnethttps://api.sera.cx/api/v1. sepoliahttps://api-testnet.sera.cx/api/v1. URLs are hardcoded; you cannot redirect them via env. |

Signer

| Mode | What happens | |---|---| | external (default) | Server never signs. get_quote returns route_params; your wallet signs externally; execute_swap accepts the signature. Safe for distribution. | | local | Server holds SIGNER_PRIVATE_KEY and signs in-process. Enables convert_and_send. Only use on a trusted server with a wallet you've intentionally funded. | | readonly | All execution tools refuse. Discovery + analytics only. |

Policy presets

Pre-baked bundles. Pick one with POLICY_PRESET=:

| Preset | Symbols | Per-tx cap | Daily cap | Slippage | |---|---|---|---|---| | starter | USDC, USDT | $1,000 | $5,000 | 25 bps | | standard (recommended) | USDC, USDT, XSGD, JPYC, MYRT, TGBP, EURC | $5,000 | $50,000 | 10 bps | | sg-retail | USDC, USDT, XSGD | $2,000 | $10,000 | 15 bps | | open | (none) | (none) | (none) | 0 | Don't ship this. |

Override individual fields by setting the matching env (POLICY_MAX_NOTIONAL_USD, POLICY_DAILY_VOLUME_CAP_USD, POLICY_ALLOWED_SYMBOLS, etc.). Each override beats the preset.

Other

| Variable | Effect | |---|---| | POLICY_DRY_RUN=true | All execute_swap calls refuse, regardless of signer mode. Paper-trading mode. | | SERA_ENABLE_EXECUTION_TOOLS=false | Hide the execution tool category (execute_swap, convert_and_send) from the MCP host entirely. Default true. Set false for public / multi-tenant deployments. Other tools (discovery, pricing, liquidity, quote planning, treasury, history) keep working. | | SERA_HISTORY_DB=/path/to/file.db | Enables fx_history, fx_volatility, corridor_pnl. SQLite log of every fx_rate + quote call this MCP serves. | | LOG_LEVEL | trace \| debug \| info (default) \| warn \| error. Structured JSON to stderr. | | SERA_API_KEY + SERA_API_SECRET | Required for get_balances, treasury_value, exposure_report, rebalance_plan, pay_invoice, settlement_status. |

See .env.example for the full list with comments.

Security model

Built for distribution. Every layer assumes the install instructions might be hostile.

  • Hardcoded base URLs: SERA_BASE_URL is ignored by default. Overrides require a separately-named env (SERA_BASE_URL_ALLOW_CUSTOM=true) and emit a loud boot warning. A malicious install snippet can't redirect API traffic by setting one env var.
  • No redirects: undici maxRedirections: 0. Even a sera.cx subdomain can't 301 us elsewhere.
  • Quote registry: every get_quote registers {uuid → frozen route_params}. execute_swap refuses unknown uuids in local-signer mode (won't sign arbitrary intents) and refuses route_params mismatches in any mode.
  • Server-derived notional: daily volume cap is computed from route_params.maxInputAmount × token's USD value. Caller cannot lie about it.
  • Prompt arg sanitization: every prompt template arg is type-validated (address regex, fiat regex, numeric regex, symbol-list regex) before substitution into LLM context. Newline/SQL/instruction injections are rejected.
  • Policy gates: symbol whitelist, recipient whitelist, per-tx notional cap, rolling 24h volume cap, dry-run kill-switch.
  • Signer modes: server defaults to external and holds no key.
  • Caching: read-only endpoints have TTL caches with in-flight de-dupe. Quotes never cached.
  • Logging: structured JSON to stderr; never to stdout (which is reserved for MCP transport).

Run sera.doctor in any agent session for a live posture check.

Execution flow (external signer)

  1. Agent calls sera.get_quote with from, to, amount, owner_address (or simulate: true to probe with the burn address).
  2. MCP validates the request against policy and calls Sera POST /swap/quote.
  3. MCP returns uuid + route_params (the exact EIP-712 Intent struct) + caches the binding.
  4. Wallet signs route_params under the Sera EIP-712 domain:

``js const domain = { name: 'Sera', version: '1', chainId, verifyingContract: seraAddress }; const types = { Intent: [ { name: 'taker', type: 'address' }, { name: 'inputToken', type: 'address' }, { name: 'outputToken', type: 'address' }, { name: 'maxInputAmount', type: 'uint256' }, { name: 'minOutputAmount', type: 'uint256' }, { name: 'recipient', type: 'address' }, { name: 'initialDepositAmount', type: 'uint256' }, { name: 'uuid', type: 'uint256' }, { name: 'deadline', type: 'uint48' }, ]}; const sig = await signer.signTypedData(domain, types, route_params); ``

  1. Agent calls sera.execute_swap with { uuid, signature }.

Quotes are single-use. On QUOTE_STALE / 410, re-quote — do not retry the same uuid.

Architecture

┌────────┐    sera.get_quote        ┌───────────────┐     POST /swap/quote     ┌──────┐
│ Agent  │ ───────────────────────▶ │  sera-mcp     │ ───────────────────────▶ │ Sera │
│        │                          │ (cache+policy │                          │  API │
│        │ ◀── route_params + uuid  │  +registry)   │ ◀──── uuid + route       │      │
└────────┘                          └───────────────┘                          └──────┘
     │  sign route_params (EIP-712)
     ▼
 wallet / external signer
     │  signature
     ▼
sera.execute_swap (uuid + sig) ──▶ sera-mcp ──▶ POST /swap ──▶ Sera ──▶ on-chain settlement
                                       │
                                       └─ enforces uuid binding, daily cap, dry-run

Source layout:

src/
├── index.ts                    MCP server entrypoint, tool/resource/prompt registration
├── config.ts                   env loading, hardcoded URL allowlist, AppContext
├── resources.ts                MCP resources (sera://...)
├── prompts.ts                  slash-prompt templates with arg sanitization
├── sera/
│   ├── client.ts               REST client + TTL cache wrapper
│   ├── tokens.ts               token resolver, decimals math
│   └── types.ts
├── signer/signer.ts            EIP-712 signer (external | local | readonly)
├── policy/policy.ts            whitelist, caps, presets, dry-run, daily volume gate
├── tools/                      32 tool handlers
└── util/
    ├── cache.ts                TTL cache + in-flight de-dupe
    ├── limit.ts                bounded-concurrency runner
    ├── external_fx.ts          Frankfurter / open.er-api / exchangerate.host clients
    ├── persistence.ts          optional SQLite log
    ├── logger.ts               structured stderr JSON
    ├── quote_registry.ts       uuid → route_params binding
    └── sanitize.ts             prompt arg validators

Status

Honest read of what's hardened vs what's still moving:

| Surface | Status | Notes | |---|---|---| | stdio MCP transport | Stable | Used in production by Claude Code / Claude Desktop / Cursor / OpenAI Agents SDK | | Read tools (discovery, pricing, liquidity, history, treasury reads) | Stable | Cached, rate-limit-tolerant, no side effects | | Policy gates (whitelist, caps, dry-run, daily volume) | Stable | Server-derived notional; quote-registry binding | | Quote tools (get_quote, prepare_swap, quote_recipient_amount) | Stable | EIP-712 Intent surface stable | | External signer execution (execute_swap with caller signature) | Stable | Server holds no key | | Local signer execution (execute_swap server-signs, convert_and_send) | Operator-managed | Requires SERA_SIGNER_MODE=local + intentionally funded wallet on a trusted host | | API-key treasury tools (get_balances, treasury_value, pay_invoice, settlement_status) | Operator-managed | Require SERA_API_KEY / SERA_API_SECRET | | Tool annotations (readOnly / destructive / idempotent / openWorldHint) | Stable (v0.5.0) | Every tool carries annotations the host runtime can use for confirmation UX. | | Tool grouping + execution opt-in (SERA_ENABLE_EXECUTION_TOOLS) | Stable (v0.5.0) | Default true; set false to hide execute_swap + convert_and_send entirely. | | convert_and_send only registered when SERA_SIGNER_MODE=local | Stable (v0.5.0) | Tool no longer surfaces when it can't work. | | Streamable HTTP transport | Stable (v0.8.0) | Additive to stdio; --transport http opts in. Localhost-default with DNS-rebinding protection. No OAuth (bind to localhost or front with auth proxy). | | Per-tool outputSchema + structuredContent | Partial (v0.7.0) | Live on doctor, list_currencies, get_fx_rate, market_health. Remaining tools incremental. | | Read/exec endpoint split (/mcp/read, /mcp/exec) | Planned | When OAuth lands. | | OAuth 2.1 + RFC 8707 Resource Indicators for remote HTTP | Planned | Required before any public/multi-tenant deployment. |

Roadmap

  • Streamable HTTP transport — additive to stdio; for ChatGPT connectors and hosted/remote agents. SSE is not on the roadmap (deprecated upstream).
  • Tool grouping + SERA_ENABLE_EXECUTION_TOOLS flag — hides execution tools by default; opt-in for trusted hosts.
  • Subscriptions — push deal alerts instead of polling. MCP spec supports it; needs server-side subscriber state.
  • Multi-hop SOR explorer — for pairs with no direct corridor, plan via intermediate fiats.
  • Address risk screening — sanctions / OFAC hooks (needs an external provider).
  • Approval/allowance managersera.approval_status for ERC-20 approvals to the Sera vault.
  • Per-tool rate limits — defend against polling-loop DoS on the upstream quote engine.

CLI

This package ships a sera CLI alongside the MCP server. Same code, same Sera plumbing — just a different entry point for shell scripts and ops use.

# After build, either run directly:
node dist/cli.js doctor

# Or install globally for the `sera` command:
npm install -g .          # from this directory
# Or:
npm link                  # development convenience

sera doctor
sera fx USD SGD
sera quote USDC XSGD 100 --simulate
sera deals --min-bps 25 --json | jq
sera ladder USDT JPYC 30000
sera spread-radar USD,SGD,MYR,EUR,GBP,JPY

Run sera --help for the full command reference.

Built for:

  • Cron jobs / CI — automated FX dumps, daily deal summaries, alerting
  • Ops debugging — Sera engineering checking quote behavior without an agent
  • Power users — terminal-first people who don't want an LLM in the loop

The CLI uses the same handlers as the MCP server so anything an agent can do via sera.* tools, the CLI exposes as a command. See [src/cli.ts](src/cli.ts).

Add --json to any command to get raw JSON for piping into jq / scripts.

License

MIT

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.