# AssetFare — precomputed cross-chain route intelligence for AI agents AssetFare saves agent time and tokens by exploring multi-amount candidate curves every 30 minutes. On six Solana-origin Base/Arbitrum pilot corridors, those observations only shortlist three candidates; the caller's request then quotes all three at the actual requested amount and returns at most two choices inside the time profile. Balanced defaults to 60 seconds, fast to 30 seconds, and economy is an explicit slower mode. Candidates over the time limit remain reference-only. Selection reuses the exact request-time quote while valid; after expiry it refreshes only the chosen candidate at the same amount and never silently switches routes. Selection itself is never transaction authority. Caller approves and signs; the server never signs or submits. Core 2.17.0 quotes also include strict `continuation_v3`. MCP 1.21.3 verifies the canonical full-quote hash, route-summary hash and fingerprint claim, exact path/providers, caller wallet-chain and event-signer requirements, base-unit bounds, allowed mode and TTL. Every quote remains `unranked_candidate`; no adapter selects it automatically, and `caller_approved:true` alone is not human-approval proof. The portable quote hash removes `continuation_v3`, replaces duplicated raw base-unit numbers with the exact decimal strings in `direct_route_summary`, then hashes AssetFare `typed-canonical-v1` bytes. That encoding preserves JSON type, uses exact IEEE-754 binary64 bytes for finite numbers, UTF-8 byte lengths and byte-sorted object keys, distinguishes `-0` from `0`, and rejects every non-substituted integral number outside JavaScript's safe-integer range. The required literal `quote_payload_sha256_spec` appears both on `continuation_v3` and in its fingerprint claim, preventing numeric-string collisions and cross-language precision ambiguity. [![Public safety checks](https://github.com/assetfare/assetfare-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/assetfare/assetfare-mcp/actions/workflows/ci.yml) [![npm version](https://img.shields.io/npm/v/assetfare-mcp.svg)](https://www.npmjs.com/package/assetfare-mcp) [![AssetFare MCP connector](https://glama.ai/mcp/connectors/io.github.odaiin/assetfare/badges/score.svg)](https://glama.ai/mcp/connectors/io.github.odaiin/assetfare) [![Listed on mcpservers.org](https://mcpservers.org/badge.svg)](https://mcpservers.org/servers/assetfare/assetfare-mcp) AssetFare is an agent-native, non-custodial native-USDC bridge and cross-chain route service. **Solana native USDC → Base native USDC** is the canonical route: an agent gets a fresh quote and, only after explicit caller approval, a bounded unsigned transaction plan the caller verifies and signs. AssetFare also provides bridge and cross-chain swap routes across nineteen chains, twenty-four available endpoints, and 100 directed routes. AssetFare service fee 1bp; Circle/provider/network fees additional; quote exposes total token-path cost and live availability; server never signs/submits. Solana SOL → Base USDC and Optimism USDC → Base USDC are also supported. AssetFare never receives private keys, signs, or submits. For economic evaluation, read `economic_guidance` and the complete 100-route catalog at `https://assetfare.dev/route-economics.json`. `price_recommended_for_amount` is advisory; when it is false, compare a fresh all-in quote if price matters. It does not add an acknowledgement field or block prepare/session creation. The API accepts USD 1 as a shared technical minimum. For agent-wallet funding, use AssetFare for aggregate refills or material transfers rather than reacting to each failed x402 micropayment. Use the route-specific best-from amount and confirm the fresh quote. A wallet that is empty on every supported source chain is not an AssetFare use case. Verify before trusting: [public source](https://github.com/assetfare/assetfare-mcp), [Ed25519-signed manifest](https://api.assetfare.dev/.well-known/assetfare-manifest.json), [public key](https://assetfare.dev/.well-known/assetfare-manifest.pub), [security.txt](https://assetfare.dev/.well-known/security.txt), and [on-chain execution evidence](https://assetfare.dev/evidence/). Best-from calls are not 100% guarantees; confirm the fresh AssetFare quote. Every v2 quote includes `direct_route_summary`, an intent-bound ordered provider path with normalized `chain:asset` endpoints, exact base-unit amount bounds as decimal strings, the single AssetFare 1bp fee step, and server-signing/server-submission=false. `direct_protocol_only` means every step uses a disclosed direct protocol. All current routes use that classification; `external_intent` remains only as a compatibility enum. `route_aggregator_used=false` describes AssetFare's own engine and does not claim every provider avoids internal aggregation. Circle/provider costs remain in `cost_summary.provider_fee_components`. Contract 2.6.1 also exposes known LayerZero native fees and bounded source-gas estimates in `separately_paid_costs`, provides `expected_all_in_cost_usd_estimate`, and names the native balance the caller must retain. Costs that still cannot be priced remain explicit in `unpriced_costs`. `continuation_v3` binds the entire quote (excluding the continuation object itself) to a process-local, maximum-60-second Core cache. A later exact `approval_v3` selects `one_shot` or `session`, may only strengthen the quote's maximum-input/minimum-output bounds, and fails closed after expiry, restart, path/provider drift, wallet/signer requirement drift, mode conflict or replay. Multi-step routes are session-only. Omitting `approval_v3` is explicitly `legacy_advisory`; the boolean gate remains required but is not human proof. ### Independent agent verifier The dependency-free `assetfare-verify` CLI verifies evidence instead of accepting an AssetFare `pass`, `safe`, score, or verdict field. From this checkout, live verification is explicit: ```bash node scripts/assetfare-verify.mjs --live ``` A package release that contains the `assetfare-verify` bin entry can be invoked with `npx --yes --package=assetfare-mcp assetfare-verify --live`. Do not pin an older package version that predates this command. Live mode uses the public Ed25519 key and key id embedded in the verifier. It fetches only the pinned manifest and its hash-bound safety bundle, rejects redirects, unexpected MIME types, non-canonical JSON, unknown/missing schema keys, oversized responses, expired manifests, and subjective safety claims. It then obtains `eth_chainId` and exact `eth_getCode` bytes from two independently pinned public RPC providers on every supported EVM chain. The raw bytes must agree with one another and with both the bundle's SHA-256 and Ethereum Keccak-256 evidence. These are read-only calls; the command has no signing or transaction-submission path. For deterministic or air-gapped checking, pass all three trust-material files explicitly: ```bash node scripts/assetfare-verify.mjs --offline \ --manifest ./fixtures/manifest.json \ --bundle ./fixtures/safety-bundle.json \ --pubkey ./fixtures/assetfare-manifest.pub ``` Offline mode makes no network requests. It verifies the supplied manifest signature, the signed bundle hash, exact schemas and claims, release/build/ deployment provenance, all seven EVM chains, and every embedded raw runtime-code hash. Its successful status is `offline_evidence_verified`, not a live RPC quorum result. `npm run verify-selftest` creates deterministic local fixtures and exercises bad signatures, bad bundle hashes and schemas, redirects, MIME confusion, chain/code disagreements, incomplete RPC evidence, and forbidden subjective claims. AssetFare is maintained by a distributed project team using one public release namespace during the pilot. Roles, release controls, and the current public owner are documented in [GOVERNANCE.md](GOVERNANCE.md) and [MAINTAINERS.md](MAINTAINERS.md); this is not a claim of incorporation or independent third-party audit. Interfaces: MCP + A2A + REST/OpenAPI. This repository contains an optional MCP adapter. The primary remote endpoint exposes eleven current v2 tools: signed manifest, capabilities, route selection, selected-candidate quoting, direct AssetFare quote, one-shot caller-approved prepare, and the five session-lifecycle operations. The 13 unversioned legacy tools remain available at the separate `/mcp/legacy` compatibility endpoint for the original Solana SOL → Base/Arbitrum ETH workflow. The two profiles never appear together on a remote endpoint. Agents can also evaluate any current v2 route without installing or connecting MCP: - APIs.json: `https://assetfare.dev/apis.json` - Capabilities: `https://api.assetfare.dev/v2/capabilities` - OpenAPI v2: `https://api.assetfare.dev/v2/openapi.json` - Provider status: `https://api.assetfare.dev/v2/status` - Read-only Arazzo workflow: `https://assetfare.dev/arazzo.yaml` - Independent agent pilot: `https://assetfare.dev/pilot/` ## Safety model - AssetFare MCP never accepts a private key and never signs or submits a transaction. - Every available route models and collects an AssetFare service fee of exactly 1bp at one eligible successful atomic action; no route is fee-free. The 1bp is not the total cost: Circle (including any fixed CCTP forwarding fee), provider, and network fees are additional and appear in the quote's total token-path cost. - `assetfare_v2_capabilities` and `assetfare_v2_quote` expose all 100 technically available routes. Availability is live: check capabilities/quote before preparing. Forty-four routes publish a numeric threshold; 56 have no current price recommendation. Below a published threshold, the quoted amount is also not price-recommended. The shared USD 1 technical minimum applies. - Economic guidance is advisory across REST, MCP, A2A and CLI. It never adds a separate acknowledgement step or blocks prepare/session creation. - Remote MCP/A2A clients must send strict `approval_v3` to prepare and session create. Its selected mode is schema-bound (`one_shot` versus `session`), and session approval must use the same idempotency key. The lower-level REST compatibility surface still labels omission `legacy_advisory`; it is not action authority for a new flow. Each call also requires literal `caller_approved:true`; the adapters never insert it and never describe it as human proof. Private key/seed/signed-transaction inputs are refused. - A session capability is a sensitive bearer credential, never a private key. Remote clients generate 32 random bytes locally, encode them as base64url without padding, and supply it only in `X-AssetFare-Session-Token`. The server stores only its hash. The remote MCP/A2A service never generates the secret; `assetfare-plan` keeps it in memory by default and writes it only to an explicit new mode-0600 file. The optional local stdio helper remains offline-only. - Remote MCP session create/get/observe/refresh calls must also retain the strict caller-side `verification_context` from the selected quote, approval and public wallet map. A2A v1 uses the same object as required `verificationContext`. Both adapters validate it before any upstream call, keep it out of the upstream request, apply the complete semantic verifier to every returned `current_action`, and emit a fresh self-verifying wallet handoff. If context is missing after a restart or any target/program/bounds/binding drifts, the adapter fails before creating state or exposing an action. - Remote MCP/A2A one-shot prepare likewise requires a separately typed one-shot verification context. The adapter validates it before prepare, keeps it caller-side, verifies the first EVM, Solana or Aptos action and approval bounds, and returns the untouched Core bundle inside a verified wrapper with a fresh wallet handoff. The nested bundle retains its original `payload_sha256`; wrapper fields are not part of that Core hash. - The unversioned MCP quote/status and all MCP authentication/session/action tools are isolated at `/mcp/legacy` for original-corridor compatibility only. - MCP state-changing tools only create authentication/session records or prepare/verify unsigned legacy workflow actions. MCP clients should require user approval for those calls. - The caller independently verifies every returned unsigned action and signs/submits with its own wallets. ## Remote endpoint `https://api.assetfare.dev/mcp` Official MCP Registry servers: `io.github.assetfare/assetfare` and `io.github.assetfare/assetfare-bridge`. The historical `io.github.odaiin/*` records were retired during the ownership-preserving GitHub organization migration tracked in [registry issue #1666](https://github.com/modelcontextprotocol/registry/issues/1666). npm, the public source, the hosted endpoint, and Registry metadata target `1.21.3` for this proof-carrying six-pilot execution-handoff release. Primary MCP quote scope: 100 available directed routes across twenty-four endpoints; 44 are threshold-recommended and 56 have no current price recommendation. The only technical quote minimum is $1; no route has a separate economic floor or adapter-enforced maximum. The route-specific guidance is non-enforcing and changes as observations accumulate. Live upstream availability and liquidity still apply. Each route charges an AssetFare service fee of exactly 1bp; Circle/provider/network fees are additional, and each quote exposes total token-path cost and live availability. Canonical examples are `solana:SOL → base:USDC`, `solana:USDC → base:USDC`, and `ethereum:USDC → solana:USDC`. X Layer, Sei, Sonic, Monad, Avalanche, Cronos, Injective, Linea and Aptos contribute eighteen source-only routes to Base/Solana. The unversioned legacy workflow remains limited to `solana:SOL → base:ETH` and `solana:SOL → arbitrum:ETH`; it does not limit the v2 route matrix. The USD 1 API minimum is technical only. Price-verified quotes include a best-from amount; availability-only quotes include null. Confirm every fresh quote before choosing. The six pilots are `solana:USDC->base:USDC`, `solana:USDC->base:ETH`, `solana:SOL->base:USDC`, `solana:SOL->base:ETH`, `solana:USDC->arbitrum:USDC`, and `solana:SOL->arbitrum:ETH`. Their applicable verified components form 2, 8, 8, 32, 2, and 32 complete internal graphs respectively (84 total), explored at USD 50, 100, 500, 1,000, 5,000, and 10,000 every 30 minutes. For a new evaluation, call `assetfare_v2_capabilities`, then `assetfare_v2_route_selection` with the actual intended amount. On a pilot corridor it uses precomputed curves to identify the recent top two plus the best AssetFare direct graph, fetches those three exact request-time quotes, and returns the top two. Every response also reports AssetFare's current exact cost, ETA, cost rank, and—only when supported by at least two higher tested buckets—a non-guaranteed recent amount range. A conflicting exact quote removes that range. After the caller explicitly chooses one, call `assetfare_v2_quote_selected_candidate`; it returns the already-fetched quote while valid and refreshes only the chosen candidate after expiry. An AssetFare choice contains the normal `continuation_v3` quote; an external choice contains normalized quote facts and its handoff without an executable payload. `assetfare_v2_quote` remains available for direct AssetFare-only quoting and compatibility. The primary endpoint has no legacy tools to misselect. Existing unversioned clients can connect to `https://api.assetfare.dev/mcp/legacy`; new clients must not use it. ## REST/OpenAPI first call Use the public v2 quote endpoint when an agent has not explicitly connected MCP. No API key, wallet authentication, session, signature, or transaction is required for this read-only evaluation call: ```bash curl -sS https://api.assetfare.dev/v2/quote \ -H 'content-type: application/json' \ -d '{"from_chain":"solana","from_token":"USDC","to_chain":"base","to_token":"USDC","amount_usd":1000}' ``` From a cloned repository, the dependency-free examples are: ```bash node examples/rest-quote.mjs 1000 solana USDC base USDC python3 examples/rest_quote.py 1000 solana USDC base USDC ``` For a one-command, agent-readable evaluation that verifies the signed release manifest and remains strictly quote-only: ```bash npx --yes --package=assetfare-mcp@1.21.3 assetfare-route-eval \ --amount 1000 --from-chain solana --from-token USDC \ --to-chain base --to-token USDC --quote-output quote.json ``` From a cloned repository, the equivalent command is `npm run route-eval -- ...`. The evaluator writes the exact validated quote only when `--quote-output` is explicitly supplied. The path must not exist and is created mode 0600. The evaluation remains read-only and unranked; compare it with fresh executable alternatives before selection. After that comparison and explicit caller approval, the shortest server-enforced path to one verified unsigned plan is: ```bash npx --yes --package=assetfare-mcp@1.21.3 assetfare-plan \ --caller-approved --mode session \ --quote quote.json --select-exact-quote-bounds \ --wallet solana= \ --wallet base= \ --event-signer-public \ --session-token-output ./session-capability.json \ --wallet-handoff-output ./caller-wallet-handoff.json ``` `--select-exact-quote-bounds` is an explicit local selection of the quote's maximum-input and minimum-output bounds. It generates strict `approval_v3` in memory and does not claim that `--caller-approved` proves human approval. For custom stricter bounds or an independently reviewable approval artifact, keep the three-step path: run `assetfare-select` with explicit bounds and pass its mode-0600 `approval.json` to `assetfare-plan --approval approval.json`. Economic guidance remains advisory in the CLI. Compare a fresh all-in quote when price matters; no additional acknowledgement flag is required. `assetfare-plan` validates the quote and approval binding, makes only the selected prepare/session POST, checks the returned path/provider/bounds and ActionSafetyReceiptV1/raw/action/bundle hashes, and stops unsigned and unsubmitted. Session tokens never appear in stdout or structured results. The optional token output path must not exist and is created mode 0600; omit it only if loss of recovery after process exit is acceptable. The optional caller-wallet handoff file removes the next-action ambiguity without crossing the custody boundary. For EVM actions it contains ordered, verified EIP-1193 `eth_sendTransaction` request templates; for Solana it contains the exact verified instructions, fee payer, required signers, and explicit fresh-blockhash construction requirements for a Solana Wallet Standard client. It is self-contained: the exact verified bundle, ActionSafetyReceiptV1, plan verification results, raw/action/bundle bindings, and a canonical handoff hash travel with the wallet request data so a receiving process can recompute them. Handoff v3 separates two different authorities. AssetFare itself is always forbidden from invoking a wallet. A human may confirm each request manually, or an external agent may execute it automatically only under a separate, caller-owned local policy with explicit amount, receive, fee and transaction caps. AssetFare does not choose that policy, invoke the wallet, hold a key, sign, or submit. For session mode, keep that capability file until the workflow is terminal. If the session-create response is lost, repeat the same plan command with `--session-capability-input ./session-capability.json`; it reuses the exact token and idempotency key. Once the file contains a session ID, resume without recreating the session: ```bash npx --yes --package=assetfare-mcp@1.21.3 assetfare-session \ --operation get --capability-file ./session-capability.json npx --yes --package=assetfare-mcp@1.21.3 assetfare-session \ --operation observe-source --capability-file ./session-capability.json \ --idempotency-key source-0001 \ --transaction-hash ``` `assetfare-session` accepts only transaction hashes from actions the caller has already verified, signed, and submitted. It sends the bearer token only in the session header and never prints it. The mode-0600 capability also preserves the strict approval, exact intent, public wallet map and direct-route summary needed to apply the full first-action semantic verifier to every later `current_action`. Each later EVM or Solana action receives a fresh self-verifying caller-wallet handoff; use `--wallet-handoff-output ` to persist it. Legacy v1 capability files may read an action-free session but fail closed before exposing an unverified action. Structured 409 recovery flags are preserved in CLI errors. Immediately before opening the caller wallet, request a just-in-time handoff: ```bash npx --yes --package=assetfare-mcp@1.21.3 assetfare-session \ --operation wallet-ready \ --capability-file ./session-capability.json \ --idempotency-key wallet-ready-0001 \ --wallet-handoff-output ./wallet-ready-handoff.json ``` The quote binding stays at 60 seconds. A selected unsigned action bundle is valid for 180 seconds and its EVM on-chain deadline is 240 seconds. `wallet-ready` accepts a current action only when at least 120 seconds remain; if the unsubmitted action has expired, it refreshes that exact session step, deeply verifies the replacement, and writes a new mode-0600 handoff. It never replaces a still-live action early, invokes a wallet, signs, or submits. ### Caller-owned autonomous execution `assetfare-agent-runner` connects the verified session handoff to an external agent's existing wallet without making AssetFare a custodian. It runs in the caller's process. The caller supplies two local files: Every AssetFare unsigned action is now a proof-carrying handoff. Remote MCP semantic verification is useful transport evidence, but is deliberately not signing authority. The local package recomputes the bundle and handoff hashes, intent, wallets, path/providers, amount bounds, decoded targets/programs, selectors/instructions, and signer set. It first returns the compact `assetfare-local-verification-verdict-1.0.0` status `verified_for_simulation`. Only after the caller-owned wallet adapter simulates the exact bound payload successfully and the delegated policy still authorizes it does the runner produce `verified_for_signing` and invoke that local adapter. Agents therefore consume one small verdict instead of reasoning over the raw transaction. An external-provider recommendation is only a provider handoff; AssetFare does not build or claim to verify that provider's transaction. The packaged delegated runner supports EVM and Solana handoffs. Aptos routes return a verified Aptos Wallet Standard unsigned-BCS handoff with delegated runner execution disabled; the caller confirms, simulates, signs and submits that handoff in its own Aptos wallet. - a mode-0600 policy matching [`caller-owned-execution-policy-v2`](./schemas/caller-owned-execution-policy-v2.json), containing only public wallets and explicit execution caps; and - a local wallet adapter. The packaged [`standard-wallet-adapter`](./src/standard-wallet-adapter.js) already implements the AssetFare contract for a standard EIP-1193 provider and a Solana Wallet Standard wallet; the caller only wires its existing provider clients as shown in [`examples/caller-wallet-adapter.mjs`](./examples/caller-wallet-adapter.mjs). Before funding it, validate the local adapter contract without invoking any wallet, signer, RPC submit, or network request: ```bash npx --yes --package=assetfare-mcp@1.21.3 assetfare-adapter-conformance \ --wallet-adapter ./my-local-wallet-adapter.mjs ``` The CLI deliberately has no private-key, seed, mnemonic, keystore, raw signed transaction, remote signer, or hosted-wallet option: ```bash npx --yes --package=assetfare-mcp@1.21.3 assetfare-agent-runner \ --capability-file ./session-capability.json \ --policy-file ./caller-execution-policy.json \ --state-file ./caller-runner-state.json \ --wallet-adapter ./my-local-wallet-adapter.mjs ``` For every current action the runner revalidates the self-verifying handoff, requires the configured remaining lifetime, reserves worst-case EVM native spend before the first approval, checks gas/fee/rent and transaction-count caps before each submission, and checks the policy, total runtime, and action expiry again after simulation and immediately before every normal or recovery submit. The v2 adapter must echo the exact execution-window hash and performs its own final check before using the caller wallet. The runner invokes only the caller adapter, persists only public hashes and cost summaries, observes the submitted hashes through the session, and repeats until the bound final minimum is confirmed. Approval-only failure can invoke the caller adapter's exact-zero revocation recovery. Adapter calls are idempotently bound to a public operation ID for crash recovery. The local adapter signs and submits through the caller's wallet/RPC. The packaged reference adapter accepts standard provider objects, never key strings, and stores only mode-0600 public operation metadata for idempotent retries. It returns only simulations, public confirmations, and transaction hashes. The remote MCP and A2A services still expose no wallet, key, signing, submission, or runner tool. In every result: ```text key_location: caller_wallet_adapter_only signed_by: caller_wallet_adapter submitted_by: caller_wallet_adapter assetfare_server_key_access: false assetfare_server_signing: false assetfare_server_submission: false ``` For a wallet that controls several EVM chains, `evmProvider` may be either one EIP-1193 provider or an async `(chainId) => provider` resolver. The reference adapter resolves the exact request chain before simulation, signing, submission and confirmation, rejects a mismatched chain/account, and requires two EVM confirmations by default. Solana confirmation remains finalized. The session CLI and AssetFare server have no signing or submission path. Quote selection and plan creation also require at least 15 seconds of quote TTL remaining; otherwise obtain and confirm a fresh quote instead of racing expiry. The evaluator defaults to the representative USD 1,000 `solana:USDC -> base:USDC` request. That USDC result is one AssetFare candidate, not a cross-provider market comparison; apply its route-specific best-from rule and confirm the fresh quote. The former `solana:SOL -> base:ETH` comparison route is currently inactive on economics, so the public API rejects it instead of returning an AssetFare offer or triggering competitor requests. Use the 100-route catalog and live capabilities before evaluating any route. Read-only framework integrations are available for [Coinbase AgentKit](./integrations/coinbase-agentkit/) and [GOAT](./integrations/goat-sdk/), plus project-reviewed (a project-authored repository review, not independent third-party assurance) [SendAI Solana Agent Kit plugin](./integrations/solana-agent-kit/) and [elizaOS plugin](./integrations/elizaos/), plus quote tools for [Agenti](./integrations/agenti/). None of these integrations exposes preparation, signing, submission, funding, swap, or bridge execution. Dify agents can install the reviewed [AssetFare Marketplace plugin](https://marketplace.dify.ai/plugin/odaiin/assetfare). It exposes two native REST tools—live capabilities and one route quote—with no credentials, wallet, authentication, session, preparation, signing, submission, swap, or bridge execution tool. Hugging Face smolagents users can load the reviewed [quote tool](https://huggingface.co/spaces/odaiin/assetfare-quote) or [capabilities tool](https://huggingface.co/spaces/odaiin/assetfare-capabilities) from free Static Spaces. Hub tools execute remote code locally: inspect `tool.py`, set `trust_remote_code=True`, and pin the documented immutable revision. The complete source and tests are in [`assetfare/smolagents-assetfare`](https://github.com/assetfare/smolagents-assetfare). ## A2A v1 quote adapter AssetFare also exposes A2A Agent Card version 1.7.0 for agents that discover quote and caller-approved unsigned workflows without MCP: - canonical Agent Card: `https://api.assetfare.dev/.well-known/agent-card.json` - legacy discovery alias returning the identical card: `https://api.assetfare.dev/.well-known/agent.json` - JSON-RPC v1 endpoint: `https://api.assetfare.dev/a2a` - protocol: official `@a2a-js/sdk` v1, `A2A-Version: 1.0`, `Content-Type: application/json` The read-only quote skill accepts one structured DataPart containing `fromChain`, `fromToken`, `toChain`, `toToken`, and `amountUsd`. It calls the public v2 capabilities, status, and quote endpoints and returns one quote with its passed-through `caller_action_plan_handoff`. `amountUsd` must be finite and at least 1; the adapter imposes no maximum, while live upstream availability and liquidity still apply. Two additional caller-approved A2A skills mirror the MCP execution tools: a deeply verified one-shot `prepare` operation with a self-verifying wallet handoff and the full `session` lifecycle (`session_create`, `session_get`, `observe_source`, `observe_output`, `refresh_action`). Before calling `session_create`, the A2A client generates its session token locally; the remote A2A endpoint deliberately exposes no token-generation operation. Every session operation also requires the same hash-bound `verificationContext` copied from the exact selected quote, strict approval and public-wallet map. The adapter validates that context before the upstream request, verifies every EVM, Solana or Aptos `current_action`, and emits a fresh self-verifying caller-wallet handoff. Each execution operation requires an explicit `callerApproved:true` and the caller's public wallet addresses; AssetFare never signs or submits, and only the caller's own submitted transaction hashes are observed. A safe 409 response is preserved as structured reapproval/recovery guidance; it never authorizes automatic requoting, replay, or a replacement session. A card fetch, registry health check, TCK request, or registry-generated `SendMessage` probe is discovery/conformance traffic, not customer demand. The public endpoint was checked with official `a2aproject/a2a-tck` commit `263b9cfa`: all 55 applicable MUST checks passed. Five generic TCK SUT fixture tests send fixed TextPart payloads with magic messageId prefixes and require unrelated text/file/data artifacts. They are deliberately not implemented by this structured non-custodial agent; the exception is disclosed rather than presented as a full 100% pass. Connect a remote MCP client directly—no package installation or AssetFare API key is required: ```bash claude mcp add --transport http assetfare https://api.assetfare.dev/mcp ``` ```json { "mcpServers": { "assetfare": { "url": "https://api.assetfare.dev/mcp" } } } ``` ### Codex CLI and app Add the remote server from the CLI: ```bash codex mcp add assetfare --url https://api.assetfare.dev/mcp ``` Or add it to `~/.codex/config.toml` or a project `.codex/config.toml`. The `writes` approval mode prompts for tools that are not annotated read-only: ```toml [mcp_servers.assetfare] url = "https://api.assetfare.dev/mcp" default_tools_approval_mode = "writes" ``` ### Gemini CLI ```bash gemini mcp add --transport http assetfare https://api.assetfare.dev/mcp ``` Equivalent `~/.gemini/settings.json` entry: ```json { "mcpServers": { "assetfare": { "url": "https://api.assetfare.dev/mcp", "type": "http", "trust": false } } } ``` ### Cursor Add the following server to a project `.cursor/mcp.json` or the global `~/.cursor/mcp.json`: ```json { "mcpServers": { "assetfare": { "url": "https://api.assetfare.dev/mcp" } } } ``` Connecting is unauthenticated. The primary endpoint uses caller-owned public wallets and, for session mode, a client-generated capability. Only the separate legacy endpoint uses the wallet-bound token produced by the old signMessage flow; never place either capability in an MCP configuration file. ## Agent skill The portable Agent Skill is [`skills/assetfare-route/SKILL.md`](./skills/assetfare-route/SKILL.md). Skills.lc-compatible clients can install it directly from this public GitHub repository. ```bash npx --yes skills add assetfare/assetfare-mcp --skill assetfare-route -g -y ``` ## Portable Agent Plugin Clients that support the published vendor-neutral Agent Plugins 1.0 format can install this repository from its Git URL. The current `plugins` CLI can install the same MCP connection and AssetFare route-evaluation skill through the included compatibility metadata: ```bash npx plugins add assetfare/assetfare-mcp ``` The primary MCP endpoint is v2-only. Legacy wallet-auth/session tools are isolated at `/mcp/legacy`. AssetFare never receives private keys, signs, or submits, and the skill keeps REST/OpenAPI v2 as the primary evaluation path. Circle Agent Stack and other shell-capable agents can use the same skill and public REST/OpenAPI flow; see [`integrations/circle-agent-stack`](./integrations/circle-agent-stack/README.md). ## First-call evaluation Run `npm run first-call-eval` to verify a fresh MCP client can discover the primary v2 quote-only tools, validate current capabilities, and obtain a representative USD 1,000 Solana-native-USDC to Base-native-USDC quote without creating a wallet login, session, action, signature, or transaction. Legacy tools are absent from the primary endpoint. Use USD 1 only for a deliberate reachability/schema smoke test. Use Streamable HTTP. The endpoint has no server-side API key. Read-only v2 tools never authenticate a wallet; prepare/session tools require explicit caller approval and public wallets. Legacy wallet authentication is a separate endpoint. ## Local stdio The repository also contains a stdio-compatible all-tools wrapper for self-hosting, including the local-only session-capability helper. The public Registry entry uses the lean v2-only Streamable HTTP endpoint. Package and Registry releases remain separately reviewed from remote deployment. ## npm release publishing npm releases use GitHub Actions OIDC trusted publishing through `.github/workflows/publish-npm.yml`. The workflow is manually dispatched with an existing immutable `v` GitHub release tag, verifies that the exact tag is on `main` and matches `package.json`, runs the complete package checks and production audit, refuses an already-published version, and publishes with short-lived OIDC credentials. No npm write token is stored in GitHub or this repository. The npm trusted-publisher record is pinned to GitHub organization `assetfare`, repository `assetfare-mcp`, and workflow filename `publish-npm.yml`. Direct `npm publish` is allowed only for that workflow. Package settings should require 2FA and disallow traditional tokens after the OIDC connection is verified. ### Integration npm releases The five stable integration packages use a separate, package-allowlisted release path. Their immutable tags are pinned exactly as follows: - `assetfare-agenti-route-tools-v1.3.0` (`@assetfare/agenti-route-tools`) - `assetfare-agentkit-action-provider-v1.3.0` - `assetfare-elizaos-route-plugin-v1.3.0` - `assetfare-goat-plugin-v1.3.0` (`@assetfare/goat-plugin`) - `assetfare-solana-agent-kit-plugin-v1.3.0` Current stable packages and direct installation commands: | Framework | npm package | Install | | --- | --- | --- | | Agenti | [`@assetfare/agenti-route-tools`](https://www.npmjs.com/package/@assetfare/agenti-route-tools) | `npm install @assetfare/agenti-route-tools ai zod` | | Coinbase AgentKit | [`assetfare-agentkit-action-provider`](https://www.npmjs.com/package/assetfare-agentkit-action-provider) | `npm install assetfare-agentkit-action-provider @coinbase/agentkit zod` | | elizaOS | [`assetfare-elizaos-route-plugin`](https://www.npmjs.com/package/assetfare-elizaos-route-plugin) | `npm install assetfare-elizaos-route-plugin @elizaos/core zod` | | GOAT | [`@assetfare/goat-plugin`](https://www.npmjs.com/package/@assetfare/goat-plugin) | `npm install @assetfare/goat-plugin @goat-sdk/core zod` | | Solana Agent Kit | [`assetfare-solana-agent-kit-plugin`](https://www.npmjs.com/package/assetfare-solana-agent-kit-plugin) | `npm install assetfare-solana-agent-kit-plugin solana-agent-kit zod` | `release-integration-provenance.yml` accepts only those five package choices. It requires the corresponding lightweight tag to resolve to a commit signed by the pinned AssetFare release key and contained in `main`, requires an already published non-draft GitHub release, runs the package's locked checks, tests, build, production audit, and pack verification, then uploads exactly the npm tarball and its SHA-256 file and records GitHub build provenance. It never publishes to npm. Both workflows must be dispatched with `--ref` set to that package's exact tag, never `main` or another branch/tag. They require `GITHUB_REF` to equal `refs/tags/` and `GITHUB_SHA` to equal the signed tag commit; the tag itself must contain the same two workflow files and pinned signer data. For example, after the trusted-publisher prerequisite below is complete, the provenance phase for AgentKit is selected with `gh workflow run release-integration-provenance.yml --ref assetfare-agentkit-action-provider-v1.0.0 -f package=assetfare-agentkit-action-provider`. The publish phase uses the same `--ref` and package choice with `publish-integration-npm.yml` only after provenance succeeds. `publish-integration-npm.yml` accepts the same allowlist and the exact version mapped to each immutable tag above. It repeats the signed-tag, release, manifest, lockfile, test, build, audit, and pack checks; downloads only the two exact release assets; verifies GitHub's asset digest, SHA-256 file, GitHub attestation, package identity, and byte-for-byte reproducibility; then publishes that downloaded tarball with short-lived OIDC credentials. An existing registry version is accepted only when its shasum matches exactly; a conflict fails closed. The final gate requires the expected `latest` tag, shasum, and npm SLSA provenance. **Do not dispatch either integration release workflow until the target npm package's Settings → Trusted Publisher entry is configured and independently checked with organization `assetfare`, repository `assetfare-mcp`, exact workflow filename `publish-integration-npm.yml`, no environment, and direct `npm publish` permission.** Configure that exact entry separately for all five packages. Do not substitute `publish-npm.yml`, a fork, a differently named workflow, or an npm write token. The existing root v1.x provenance and publish workflows remain separate and unchanged. ## Trust material - Security contact: `security@assetfare.dev` - Security policy and private reporting: `https://github.com/assetfare/assetfare-mcp/security/policy` - Signed manifest: `https://api.assetfare.dev/.well-known/assetfare-manifest.json` - Public signing key: `https://assetfare.dev/.well-known/assetfare-manifest.pub` - Continuously revalidated operator ownership: `https://api.assetfare.dev/.well-known/owners.json` - Active-route source status: `https://api.assetfare.dev/v2/status` - Active-route capabilities: `https://api.assetfare.dev/v2/capabilities` - Primary OpenAPI v2: `https://api.assetfare.dev/v2/openapi.json` - Legacy MCP-backed v1 OpenAPI: `https://api.assetfare.dev/openapi.json` - APIs.json: `https://assetfare.dev/apis.json` - Arazzo: `https://assetfare.dev/arazzo.yaml` - Server card: `https://api.assetfare.dev/.well-known/mcp/server-card.json` - A2A Agent Card: `https://api.assetfare.dev/.well-known/agent-card.json` - A2A endpoint: `https://api.assetfare.dev/a2a` - Agent guide: `https://assetfare.dev/llms-full.txt` - Mainnet evidence: `https://assetfare.dev/evidence/` - Paired route evidence: [`evidence/solana-base-paired-quotes-20260916.md`](./evidence/solana-base-paired-quotes-20260916.md) - Agent-payment route evidence: [`evidence/solana-base-usdc-paired-quotes-20260916.md`](./evidence/solana-base-usdc-paired-quotes-20260916.md) - Historical same-input comparison for an inactive corridor: `https://assetfare.dev/compare/solana-to-base/` - Dated Solana USDC → Base USDC comparison ($250, 2026-09-23; explicit non-all-in and non-identical-lane caveats): `https://assetfare.dev/compare/solana-usdc-to-base-usdc/` ## Discovery - Official MCP Registry: `io.github.assetfare/assetfare` and `io.github.assetfare/assetfare-bridge` - MCP Servers: `https://mcpservers.org/servers/assetfare/assetfare-mcp` - Smithery: `https://smithery.ai/servers/twotw55/assetfare` - Glama: `https://glama.ai/mcp/connectors/io.github.odaiin/assetfare` - Agent Skill: `https://www.skills.sh/assetfare/assetfare-mcp/assetfare-route` - Dify Marketplace: `https://marketplace.dify.ai/plugin/odaiin/assetfare` - Hugging Face quote tool: `https://huggingface.co/spaces/odaiin/assetfare-quote` (canonical reviewed revision `a2895876d7adec645e93d7092e63b2ed4be17ef5`) - Hugging Face capabilities tool: `https://huggingface.co/spaces/odaiin/assetfare-capabilities` (canonical reviewed revision `bdbe1e82be617c77283dd44e67cc9bda2d220ec7`) - Hugging Face prepare tool: `https://huggingface.co/spaces/odaiin/assetfare-prepare` (canonical reviewed revision `bc4619ea3d5443ed24e0e0892994530dea259188`) - Hugging Face session-create tool: `https://huggingface.co/spaces/odaiin/assetfare-session-create` (canonical reviewed revision `f4af546056d1ac3f3cf44af428b66766f8beef15`) - A2A Registry: `https://a2aregistry.org/agents/d4f9ab1a-904c-4227-8fc6-548e45749de1` - ARD: `https://assetfare.dev/.well-known/ard.json` The wrapper deliberately contains no AssetFare route engine, wallets, RPC credentials, or internal operations data. ## Agent use case For any supported v2 request, an agent first reads v2 capabilities and requests a fresh quote through REST/OpenAPI or the read-only `assetfare_v2_quote` MCP tool. Only an existing original-corridor client should connect separately to `/mcp/legacy`. The caller independently signs and submits every on-chain action; this MCP server never does. See the first-call evaluation script, the public mainnet evidence at https://assetfare.dev/evidence/, and the end-to-end case study at https://assetfare.dev/case-studies/solana-to-base-mainnet-canary/.