使用说明
Dexter API · Dexter FE · Dexter MCP · Dexter Vault · Dexter Facilitator
This repository contains one codebase for two independently deployed OAuth MCP
services and the shared @dexterai/x402-core package:
| Product | Endpoint | Auth | Payment |
|---|---|---|---|
| Dexter MCP (full platform) | mcp.dexter.cash/mcp |
Dexter OAuth | Managed wallet, automatic |
| OpenDexter MCP | open.dexter.cash/mcp |
OAuth scope=vault before discovery or use |
Session-bound passkey wallet; explicit user or policy authority |
The npm packages (@dexterai/opendexter, @dexterai/x402-discovery) live in Dexter-DAO/opendexter-ide.
This OpenDexter source candidate requires the coordinated internal package
train recorded in
release/opendexter-dependency-train.json.
Its release runtime is Node ^20.19.0 || >=22.12.0, matching the pinned Vite
toolchain; npm run verify:release:runtime checks that boundary before install
or build.
The exact internal versions are published and this candidate carries a
registry-resolved lock. Release construction fails closed if either the lock or
installed graph drifts from the recorded train. An isolated local source train
and its installed dependency graph can be checked without deploying:
OPENDXTER_IDE_SOURCE=/absolute/path/to/opendexter-ide-candidate \
DEXTER_VAULT_SDK_SOURCE=/absolute/path/to/dexter-vault-sdk-candidate \
OPENDEXTER_API_SOURCE_ROOT=/absolute/path/to/dexter-api-candidate \
OPENDEXTER_FACILITATOR_SOURCE_ROOT=/absolute/path/to/dexter-facilitator-candidate \
OPENDXTER_RUNTIME_ROOT=/absolute/path/to/disposable-installed-graph \
npm run verify:release:source
The source gate verifies the current Node runtime, package Git provenance,
exact installed versions, source-link destinations, built entrypoints, and npm
peer closure. Before npm can run, it rejects dirty or unpinned external source
repositories and any pack lifecycle hook outside the exact reviewed contract.
Vault's declared prepack command is matched byte-for-byte but never executed:
the gate exports the reviewed SDK commit into a disposable directory, performs
an exact-lock scripts-disabled install and the explicit reviewed build with npm
10.9.3, then requires the packed bytes to match the registry artifact exactly.
It never uses or changes
the source checkout's ignored dist/ or node_modules/. Release construction
separately verifies the Node runtime and registry lock, performs the exact-lock
install and reviewed builds, and rejects any installed graph that differs from
the recorded train. Descriptor generation exports the exact Git commit into a
disposable directory, installs that archive from its lock, runs only the
reviewed workspace build, and executes the archived materializer. Mutable
checkout files and ignored node_modules are never descriptor evidence.
Use npm run build:apps-sdk:local for a non-deploying widget build.
build:apps-sdk retains its release behavior and copies served assets.
After the API and facilitator releases have been accepted in production, freeze
their advertised immutable identities and regenerate the hosted derivatives in
one step:
npm run prepare:open-accepted-production
Preparation reads https://api.dexter.cash/health and
https://x402.dexter.cash/version exactly once each. It writes the generated
release/opendexter-accepted-production.json receipt, derives the existing
public sourceContracts/v3 projection from that receipt, and regenerates the
hosted descriptor. Release verification, construction, and activation read
only those frozen files; they never resolve mutable production endpoints.
Construct a sealed candidate from the current clean, canonical Git commit into
an explicit trusted release root without activating it:
npm run build:mcp-release -- --output-root /absolute/protected/release-root
The builder refuses a dirty checkout, hidden index flags, replacement refs, a
noncanonical or unreachable origin, a commit the canonical origin does not
advertise, an existing destination, or an unreviewed Node/npm/lock identity.
deploy:mcp accepts only a sealed immutable OpenDexter release containing
deterministic provenance, the exact descriptor, and a complete file manifest
that also authenticates the provenance bytes. It replaces only
dexter-open-mcp, while proving the separate full dexter-mcp PID, path,
configuration, and restart counters remain unchanged. It verifies the new
public process's PM2 and kernel paths, protected environment, health-reported
release identity and 17-tool server roster, and public asset bytes and MIME
types before pm2 save. Any mismatch independently restores and re-verifies
the prior public OpenDexter process without restarting the private service. It
never reloads or updates an existing process in place. The OAuth challenge,
authenticated tools/list, 16-model-visible plus one app-only visibility split
for the Primary (15 plus one for other clients),
and real-user experience remain separate post-deploy proof gates. This is still
activation, not authorization to deploy.
OpenDexter: the hosted x402 buyer
OpenDexter is the hosted MCP server behind the OpenDexter connector. The
canonical https://open.dexter.cash/mcp resource requires OAuth scope=vault
before MCP initialization, tool discovery, or invocation. One successful
authorization covers discovery and search, exact request checks, wallet and
portfolio reads, identity-gated access, payment, and governed actions on the
same connection. Consequential calls still require the exact user instruction
or bounded policy authority described below.
The authorized server roster is 17 registered tools:
indexter_discoverindexter_searchx402_mcp_toolsx402_checkx402_fetchx402_statusx402_accessdexter_walletdexter_wallet_portfoliodexter_prepare_asset_actiondexter_execute_asset_actiondexter_asset_action_statusdexter_reconcile_asset_actiondexter_wallet_historydexter_report_workdexter_find_assetsdexter_trade(Primary-only)
dexter_trade buys or sells the confirmed investment and amount in one call.
Only the admitted Primary runtime can discover or call it; the public manifest
and other connected clients retain sixteen tools. Its answer and refusal bodies
pass through unchanged. A failed call can have an uncertain outcome.
dexter_find_assets searches stock products and token candidates beyond the connected wallet holdings. It accepts a company name, ticker or exact mint. Stock results preserve issuer identity and expose catalog pagination. Token results cover the provider search batch. Prepare checks whether the connected wallet can trade the selected asset.
dexter_report_work records the connected agent's current work statement with
server observation and expiry times. Reporting uses the existing connection
identity without requiring funds or spending permission. Keep the acknowledged
revision for the next update, and reuse the exact operation and content after
an uncertain response. A revision conflict returns the current report so the
agent can decide whether a new update is still appropriate. Reported completion
is separate from transaction finality; expired reports show the age of the
statement. The owner roster displays these reports through its existing API.
Every tool in this roster carries the OAuth security scheme and requires the current vault Bearer on each invocation. Compatibility aliases, composed-skill, passkey-probe, and card tools stay outside this hosted roster.
The hosted server revalidates the session's current authorization with the API
before handling each request. OPEN_MCP_OAUTH_SEED_TIMEOUT_MS sets the request
budget at startup, including response-body reading: the default is 5000 ms,
and overrides must be integers from 1 through 10000 ms. Invalid values prevent
startup. The budget bounds MCP's wait; the API may complete after it expires.
A timeout returns the existing temporary authorization error before tool
dispatch. Each attempt logs
its elapsed time, stage and outcome with a generated request ID and a hashed
session reference. X-Dexter-Seed-Request-Id carries that generated ID to the
API for log correlation. These diagnostics exclude credentials and response
bodies. Recovery keeps the original session and operation identifiers.
The MCP Apps visibility metadata exposes 16 of these tools to the model in
the Primary runtime and 15 in other clients that honor it. The remaining registered tool, indexter_discover, is
reserved for app browsing. Text-only clients use indexter_search and its
structured result; MCP Apps clients render the widget, with additional
ChatGPT display controls where supported.
indexter_search is the only model-visible Indexter entry. It accepts the
user's natural-language request and selects a curated overview, one provider,
or task search on the server. Broad and ambiguous requests use the overview;
named-provider questions use the provider view; concrete requests use task
search. Ambiguous provider names are resolved against the current catalog,
including lowercase names. An explicit catalog miss falls back to task search;
an unavailable catalog returns an error. Task search returns at most twelve results. indexter_discover remains
registered for widget browsing and is hidden from the model. Endpoint and Actor
cursors are separate opaque values and must be copied unchanged. Neither tool
requires a wallet read.
x402_mcp_tools lists tools at a public HTTPS MCP server. Copy the selected
tool's schema string into the mcp target for x402_check, along with its
arguments. A tool check can change provider state. See the
native MCP purchase guide.
x402_check accepts one target: mcp, a public endpoint URL, or a stable
resourceId from the current Indexter result. Dexter resolves managed
resources server-side without exposing their private routes. The tool also
accepts a method and optional exact raw request-body string. A check asks
Dexter to custody the request and seller
terms. A purchasable result carries quoteOnly=false and one opaque
intentId; quoteOnly=true carries no executable intent. x402_fetch accepts
that intentId plus an explicit user- or policy-approved maxAmountAtomic
ceiling. It never accepts URL, body, route, tab, seller, or caller-carried
prepared-purchase JSON.
x402_status accepts only the same intentId and reads state without
redispatching.
For supported USDC payments, Fetch and Status already return readable amounts in
outcome.amount.displayAmount, with symbol, decimals, and the original
amountAtomic. Read outcome.amount.basis to distinguish a requested payment
from a confirmed payment. The existing continuation supplies the next action,
message, and any returned same-intent status arguments. These fields describe
payment and delivery separately.
If execution authority is missing, the hosted consent handoff must preserve
the same intent. Only a returned dispatch.boundary: "crossed" permits the
agent to say the merchant request was dispatched. A missing result or
host-disabled invocation never does. After a returned pending, ambiguous, or
post-dispatch result, OpenDexter does not retry the purchase; it checks status
on that same intent.
Internal settlement-rail choice remains API-owned and is not a public tool or
mode menu.
Governed Buy and Sell, plus the preserved fail-closed Send contract, use one
API-owned intent through five hosted tools. dexter_prepare_asset_action
accepts one stable operationId plus the
exact action fields and persists/evaluates the request without signing or
submitting it. Send and non-stock Buy/Sell use the canonical assetId returned
by dexter_wallet_portfolio from an approved holding or an approvedActionTarget
whose matching action is available, never a symbol or mint. Natural-language
stock Buy/Sell instead use the exact human companyQuery; the API normalizes
that query and selects and pins the current catalog product. A caller must
never replace a stock query with a remembered static assetId, symbol, or
mint. Stock Buy supports either an amountAtomic USDC budget (6 decimals) or
a human decimal shareQuantity minimum-receive target, optionally bounded by
maximumSpendAtomic. Stock Sell supports companyQuery plus direct token
amountAtomic; it does not accept shareQuantity. For non-stock Sell and
Send, amountAtomic is the selected asset amount using the server-certified
decimals. Send does not expose a memo.
A prepared stock result exposes the immutable release in top-level
stockRuntime and its frozen catalog pin in preview.stockSelection.
Execute exposes top-level tradeSummary; Status exposes top-level
stockSelection, tradeSummary, and stockV2Identity; History carries the
same Status shape in items; Reconcile carries it in statusAfter. Stock
success requires a canonical 64-byte Solana signature, confirmed or finalized
commitment, executionSucceeded: true, and exact public-identity binding.
Governed tool responses declare the existing human presentation in
structuredContent.presentation. Action results expose summary, status,
and nextActions; History pages expose those fields per entry in
presentation.items, alongside presentation.nextCursor. The existing JSON
text presentation remains available to historical consumers. Clients that
validate against a cached tools/list schema must refresh that schema when
adopting this output contract.
presentation.preview.basis: "estimated_quote" identifies preparation terms.
presentation.actual contains recorded receipt amounts or an explicit reason
they are unavailable. A saved quote remains an estimate after execution.
Successful responses and landed program errors retain detailed backend fields
at their original structuredContent paths. Ordinary normalized governed
errors carry { presentation } there and preserve the validated error body in
_meta["dexter/governedWidgetResult"] for widgets. Existing IDs, evidence,
recovery restrictions, and history records remain intact. Use each
nextActions entry's returned arguments and conditions. Authentication and
SDK input-validation errors keep their existing protocol responses.
dexter_execute_asset_action accepts only operationId and the prepared
intentId; the API request body is exactly {} and the operation ID becomes
its Idempotency-Key. It accepts no action, attempt, plan, plan hash, approval,
wallet, agent, or grant selector. dexter_asset_action_status reads durable
receipt and finality evidence, dexter_reconcile_asset_action asks for the
same-intent reconciliation result without automatic retry, and
dexter_wallet_history reads cursor-paginated canonical status records.
Tool/schema presence is not runtime capability: the exact Prepare response is
authoritative. A covered Buy or Sell may execute autonomously under the
reusable bounded mandate. In the current integrated release, Send is preserved
in the public contract but Prepare refuses it with
protected_agent_send_sdk_required before capacity reservation or intent
creation. Do not call Execute or Reconcile for that refusal. No mandate,
insufficient scope, or an unavailable signer otherwise fails closed for
enrollment, extension, or owner escalation. Those ceremonies remain separately
authenticated and are not model-callable OpenDexter tools.
The MCP-to-API governed-action bridge uses
GOVERNED_AGENT_ACTIONS_HMAC_SECRET (32 bytes or longer), configured to the
same value in Dexter API and this MCP service, and signs the timestamp,
authenticated MCP session, method, exact mounted URL including query,
Idempotency-Key (or empty), and canonical request-body hash. It does not use
the Dextercard/session or x402 service secrets and has no legacy fallback.
The hosted check/fetch/status adapter also requires
NATIVE_EXACT_MCP_SERVICE_HMAC_SECRET (32 bytes or longer), configured to the
same value in Dexter API and this MCP service. Every internal request signs its
timestamp, method, exact route, and exact serialized body. Missing or weak
configuration fails closed before the request leaves MCP; the secret is never
part of a tool argument or result.
This release's production activation runs only dexter-open-mcp from
ecosystem.production.cjs and leaves the distinct full dexter-mcp process
untouched. Set
DEXTER_MCP_ENV_FILE to one absolute, service-owned mode-0600 regular file
before asking PM2 to load that config. The launcher rejects symlinks, hard
links, foreign ownership, permissive modes, and inherited Node loader controls;
the immutable release itself contains no credential file.
How wallet identity works. OAuth authorizes the canonical
https://open.dexter.cash/mcp resource before tool discovery. The same
authorized MCP session resolves the durable wallet binding and stored
passkey-vault identity for every product tool. Wallet and portfolio calls use
that binding. They do not accept a caller-supplied
wallet address or user handle. dexter_wallet reads the bound passkey wallet;
dexter_wallet_portfolio starts with a compact Solana portfolio summary. Use
view: "detail" with a mint or name/symbol query for one holding's available
market and quantity details, view: "holdings" for additional rows, and
view: "targets" for approved assets the wallet does not hold. Targets never create
a holding, quantity, balance, or portfolio value. Their matching action must be
available and the exact Prepare response remains authoritative.
Pass the returned snapshotId to read another view of the same observation;
pass nextCursor to continue a page. sourceSummary describes the whole observed
portfolio, while selection reports the response's scope. An expired snapshot
requires a fresh summary. The portfolio card uses the same read-only tool and
shows selected details from widget metadata. Historical v1 results, including
approvedActionTargets, remain supported. See
portfolio read contract.
How the npm package differs. @dexterai/opendexter is an independently
versioned local stdio package for Codex, Claude Code, and other agents. It uses
a user-controlled local signer instead of the hosted connector's OAuth and
session binding. This hosted source contract does not assert that a published
npm version has adopted the hosted tool boundary. Its package,
install guidance, and seller-side opendexter audition <url> command live in
Dexter-DAO/opendexter-ide.
| OpenDexter MCP | @dexterai/opendexter |
|
|---|---|---|
| Transport | Hosted HTTP MCP | Local stdio MCP |
| Authorization | OAuth required before discovery and use | Local process and signer |
| Wallet identity | Durable passkey wallet bound to the authenticated MCP session | User-controlled local signer |
| Executable roster | Sixteen tools on one authorized connection | Independently versioned; verify the installed package |
| Seller onboarding | Not exposed as a hosted tool | opendexter audition <url> |
| Best for | ChatGPT, Claude, hosted agents | Codex, Claude Code, CLI agents |
Source: open-mcp-server.mjs (hosted server). npm package source is in opendexter-ide/packages/mcp.
The opaque-intent boundary and its unverified backend dependencies are
documented in
docs/contracts/OPENDXTER-OPAQUE-INTENT-V1.md.
It is a source candidate, not proof of deployment or end-to-end settlement.
Dexter MCP: the authenticated server
The authenticated server at mcp.dexter.cash/mcp exposes the broader Dexter platform surface over OAuth-authenticated HTTPS, reusing the managed Dexter wallet infrastructure for automatic payment. It's what the Dexter brand connector on Claude and ChatGPT talks to.
Source: http-server-oauth.mjs.
Access Tiers
| Label | Who can call | Examples |
|---|---|---|
guest |
Shared demo bearer, no login required | general/search, wallet/resolve_wallet |
member |
Authenticated Supabase session / dexter_mcp_jwt |
wallet/list_my_wallets, wallet/set_session_wallet_override |
pro |
Role-gated (Pro or Super Admin) | hyperliquid_markets, hyperliquid_perp_trade |
dev |
Super Admins only | codex_start, codex_exec |
internal |
Diagnostic tooling, not exposed to end users | wallet/auth_info |
Every new Dexter account ships with a managed wallet, so resolver-backed tools immediately report source:"resolver".
Quick Start
git clone https://github.com/Dexter-DAO/dexter-mcp.git
cd dexter-mcp
npm install
cp .env.example .env
# populate .env with required Supabase/OAuth settings
# HTTPS transport (port 3930)
npm start
# or stdio transport for local tools
node server.mjs --tools=wallet
Verify the HTTP transport:
curl -sS http://localhost:3930/mcp/health | jq
With the public proxy in place:
curl -H "Authorization: Bearer <TOKEN_AI_MCP_TOKEN>" \
https://mcp.dexter.cash/mcp/health
Authentication
| Mode | When to use | How |
|---|---|---|
| OAuth2 / OIDC | Claude, ChatGPT, hosted connectors | Set TOKEN_AI_MCP_OAUTH=true and supply TOKEN_AI_OIDC_* (or Supabase) endpoints. Users sign in via the Dexter IdP; credentials are checked on every HTTP request, including existing sessions. |
| Bearer token | Service-to-service calls, Codex, Cursor | Define TOKEN_AI_MCP_TOKEN and send the matching Authorization: Bearer <token> header on every request. Tool permissions still apply. |
Session IDs identify transport state. Each request must carry valid credentials for the session owner. Refreshed tokens for that owner can continue the session. The private server refuses MCP requests when no authentication method is configured.
Provider validation may be cached for up to five minutes, shortened by token expiry when present. Revocation is subject to that cache and the provider's validation behavior.
Metadata endpoints (for connector discovery):
/.well-known/oauth-authorization-server/.well-known/oauth-protected-resource/.well-known/openid-configuration
These routes are proxied on both dexter.cash and mcp.dexter.cash, so connectors can follow the same issuer regardless of which hostname they use.
Toolsets
Tool bundles live under toolsets/<name>/index.mjs and register themselves through the manifest in toolsets/index.mjs. Bundles currently shipped:
| Bundle | What it does |
|---|---|
x402 |
Auto-registered paid resources from dexter-api (slippage sentinel, Jupiter quote, Twitter topic analysis, Solscan trending, Sora/meme jobs, GMGN snapshot, etc). Updates itself whenever /api/x402/resources changes. |
wallet |
Session-aware helpers (resolve_wallet, list_my_wallets, set_session_wallet_override, auth_info) backed by the Supabase resolver. |
solana |
Managed Solana trading utilities (solana_resolve_token, balance listings, swap preview/execute) proxied through dexter-api with entitlement checks. |
markets |
markets_fetch_ohlcv over Birdeye v3 pair data, auto-selecting the top-liquidity pair when only a mint is supplied. |
onchain |
onchain_activity_overview and onchain_entity_insight for wallet/token analytics. |
general |
Tavily-backed web search with depth + answer summaries plus a fetch helper for realtime research. |
hyperliquid |
hyperliquid_markets, hyperliquid_opt_in, hyperliquid_perp_trade for Hyperliquid copy-trading. |
codex |
Bridges MCP clients to the Codex CLI via codex_start, codex_reply, codex_exec. |
pumpstream |
pumpstream_live_summary view of https://pump.dexter.cash/api/live with filters, sort, viewer/USD floors. |
stream |
DexterVision shout utilities (stream_public_shout, stream_shout_feed). |
Each tool exposes an _meta block so downstream clients can group or gate consistently:
{
"name": "solana_swap_execute",
"title": "Execute Solana Swap",
"_meta": {
"category": "solana.trading",
"access": "member",
"tags": ["swap", "execution"]
}
}
category: high-level grouping for UX (e.g.wallets,analytics,solana.trading)access: entitlement level (guest,member,pro,dev,internal)tags: free-form labels for filtering/badging
Selection options:
| Where | How |
|---|---|
| Environment default | Leave TOKEN_AI_MCP_TOOLSETS unset to load every bundle. Set it (comma-separated) to restrict, e.g. TOKEN_AI_MCP_TOOLSETS=wallet. |
| Launch profile shortcut | TOKEN_AI_MCP_PROFILE=opendexter loads only the x402 surface on the authenticated server. |
| CLI / stdio | node server.mjs --tools=wallet or --profile=opendexter. |
| HTTP query | POST /mcp?tools=wallet or POST /mcp?profile=opendexter. |
Legacy Token-AI bundles in legacy-tools/ remain for reference; they are not registered by default.
Architecture Notes
common.mjs: builds the MCP server, normalizes Zod schemas, wraps tool registration with logging.toolsets/: declarative manifest of tool bundles plus the wallet toolset implementation. Authoring guide attoolsets/ADDING_TOOLSETS.md.server.mjs: stdio entrypoint (used by local agents and Codex); respects--tools=flags.dexter-mcp-stdio-bridge.mjs: bridges stdio clients to the hosted OAuth HTTP transport (for Codex/Cursor when they only support stdio).http-server-oauth.mjs: HTTPS transport with OAuth/OIDC, session caching, metadata routes.legacy-tools/: archived Token-AI tools kept for reference during migration.
Supabase interactions flow through Dexter API helpers for consistent auth enforcement.
Development
For local dev, PM2, harness operations, and Supabase session maintenance, see docs/dev/HARNESS.md.
Dexter Studio uses Claude Agent SDK and Zod 4 in an isolated, non-workspace
tooling profile so it cannot change the hosted MCP's Zod 3 runtime. Run
npm run studio:setup once before npm run studio.
Dexter Stack
| Repo | Role |
|---|---|
dexter-api |
OAuth issuer, wallet resolver, OTS buyer-side implementation, x402 billing |
dexter-fe |
Web frontend (Claude/ChatGPT connector auth, /wallet dashboard, admin) |
dexter-vault |
Open Tabs Standard reference implementation (Anchor program on Solana) |
dexter-facilitator |
x402 v2 payment facilitator (Solana + EVM) |
License
All rights reserved. This source is public for transparency and reference, not for reuse. You may not copy, modify, redistribute, or use this code in your own projects without written permission from Dexter. The Dexter and OpenDexter names and marks are not licensed for any use.
For licensing inquiries: branch@dexter.cash.