Bit2Me MCP Server
# Bit2Me MCP Server
[](https://github.com/bit2me-devs/bit2me-mcp/actions/workflows/ci.yml)
[](https://github.com/bit2me-devs/bit2me-mcp/actions/workflows/deploy.yml)
[](https://www.npmjs.com/package/@bit2me/mcp-server)
[](https://opensource.org/licenses/MIT)
[](https://scorecard.dev/viewer/?uri=github.com/bit2me-devs/bit2me-mcp)
[](https://www.bestpractices.dev/projects/11511)
[](https://www.typescriptlang.org/)
[](https://nodejs.org/)
An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server to interact with the [Bit2Me](https://bit2me.com/) ecosystem. This server allows AI assistants like Claude to access real-time market data, manage wallets, execute trading operations, and query products like Earn and Loans.
For more information, visit: **[https://mcp.bit2me.com](https://mcp.bit2me.com)**
**Bit2Me** is a leading cryptocurrency exchange based in Spain, offering a wide range of services including trading, staking (Earn), and loans. This MCP server acts as a bridge, enabling LLMs to perform actions and retrieve data securely from your Bit2Me account.
## ๐ Features
- **General**: Asset information, account details, portfolio valuation, and self-introspection (`general_describe_tool` returns description, schema, and examples for an **enabled** tool โ useful for LLMs encountering a tool for the first time).
- **Wallet Management**: Query balances, transactions, and wallet (Pockets) details.
- **Pro Trading**: Manage orders (Limit, Market, Stop), query open orders, and transfer funds between Wallet and Pro.
- **Earn & Loans**: Manage Earn (Staking) strategies and collateralized loans.
- **Operations**: Execute trades, transfers, and withdrawals securely.
- **Write safeguards**: Irreversible writes (Pro / Earn / Loan / `broker_confirm_quote`) first return a `needs_confirmation` preview unless `confirm` is the boolean `true`. Broker quote tools (`broker_quote_*`) do not require confirm. The preview includes the stamped `idempotency_key` so a retry reuses it. Failed POST/DELETE calls retry with exponential backoff + jitter when that key is present.
- **Category allow-list**: Optional `BIT2ME_ENABLED_CATEGORIES` (comma-separated: `general`, `broker`, `wallet`, `pro`, `earn`, `loan`) filters `tools/list` and dispatch. Unset = all. An unknown id is a startup/parse error.
- **MCP tool annotations**: `tools/list` exposes hints from `type` in `data/tools.json` โ `readOnlyHint` on READ/META, `destructiveHint` on irreversible WRITE (not `broker_quote_*`), `idempotentHint` on cancel-order tools.
- **structuredContent**: Tool results include a `structuredContent` object alongside the existing text JSON (the text payload is unchanged).
- **Resources**: `bit2me://health`, `bit2me://server`, and `bit2me://catalog` (enabled tools; no Bit2Me I/O). Same catalogue on stdio and HTTP `resources/list` / `resources/read`.
- **Decimal Precision**: Portfolio valuation uses `decimal.js` โ no floating-point drift on large balances or high-precision assets.
- **Expanded PII Redaction**: Logs automatically scrub email addresses, IBANs, phone numbers, KYC fields, JWT-shaped tokens, and long base64 blobs, in addition to API keys and signatures.
- **Monotonic Nonces**: API-key signing uses a strictly-increasing nonce counter, preventing replay attacks even under high concurrency.
- **Audit Log**: Every write tool (order creation, withdrawals, earn deposits, loan operations, โฆ) appends a tamper-evident JSON line on both success and failure. Set `AUDIT_LOG_PATH` to write to a dedicated file; otherwise audit lines are emitted via the logger with `audit: true`.
- **Parametrized Prompts**: `analyze_portfolio` and `market_summary` accept arguments. Extra prompts: `tax_report`, `dca_plan`, `loan_health_check`, and `confirm_write` (optional `tool` argument) for irreversible writes.
## ๐ ๏ธ Available Tools & API Endpoints
The server currently exposes **48 tools** grouped as follows:
- 4 General tools (including `general_describe_tool` for self-introspection)
- 8 Broker (Simple Trading) tools โ includes `wallet_get_cards` (Bit2Me Teller). It stays in `broker` so the allow-list id does not change.
- 4 Wallet tools
- 14 Pro Trading tools
- 11 Earn (Staking) tools
- 7 Loan tools
Full descriptions, response schemas, Bit2Me REST endpoints and usage notes live in [`TOOLS_DOCUMENTATION.md`](./TOOLS_DOCUMENTATION.md).
## ๐ Documentation & Schemas
All tool responses are normalised for LLM consumption (consistent naming, flattened payloads, concise metadata). Use the following references when developing new tooling:
- **[`docs/README.md`](./docs/README.md)** โ Map of every canonical doc (what to edit vs what is generated).
- **[`TOOLS_DOCUMENTATION.md`](./TOOLS_DOCUMENTATION.md)** โ Auto-generated catalogue (`pnpm build:docs` from `data/tools.json`).
- **[`data/tools.json`](./data/tools.json)** โ Source of truth for tool metadata, schemas and examples.
## โ๏ธ Installation and Configuration
### Prerequisites
- **Node.js**: v20 or higher.
- **Bit2Me Account**: You need a verified Bit2Me account.
### ๐ Authentication Methods
#### API Keys (Recommended)
The recommended way to authenticate is using API Keys. This method is secure, granular, and designed for programmatic access.
1. Go to your **[Bit2Me API Dashboard](https://app.bit2me.com/profile/api)**.
2. Click on **"New Key"**.
3. Select the permissions you need (e.g., Wallets, Trading, Earn, Loans).
> **โ ๏ธ Security Note:** This MCP server does **NOT** support crypto withdrawals to external blockchain addresses or transfers to other users. For security best practices, please **DO NOT** enable "Withdrawal" permissions on your API Key. Internal transfers between your own Bit2Me wallets (Wallet โ Pro โ Earn) are fully supported.
#### JWT Session Token (Alternative)
All tools accept an optional `jwt` argument (session cookie toward Bit2Me). Typical local use does **not** need it.
- **stdio / Claude Desktop**: prefer API keys in `.env`. `jwt` is only for a one-off session token.
- **HTTP binary**: send `Authorization: Bearer <jwt>` (or API-key headers) per request โ see ADR 0001.
When `jwt` is provided on a **stdio** call (and HTTP has not already authenticated the request), the server uses session-cookie auth toward Bit2Me instead of the process API keys.
```typescript
// Example: optional session token on a tool call
const result = await mcpClient.callTool("wallet_get_pockets", {
symbol: "BTC",
jwt: "user_session_token_here", // omitted โ API keys from the environment
});
```
> **Note:** For local Claude Desktop / Cursor, API keys in `.env` are enough. Per-request JWT or API-key headers belong to the **HTTP** binary (`bit2me-mcp-http`). See [docs/adr/0001-valet-key-http-credentials.md](./docs/adr/0001-valet-key-http-credentials.md) and the [documentation map](./docs/README.md).
### Steps
1. **Clone the repository:**
```bash
git clone https://github.com/bit2me-devs/bit2me-mcp.git
cd bit2me-mcp
```
2. **Install dependencies:**
```bash
pnpm install
```
3. **Configure environment variables:**
Create a `.env` file in the root directory:
```bash
cp .env.example .env
```
Edit `.env` and add your keys:
```env
BIT2ME_API_KEY=YOUR_BIT2ME_ACCOUNT_API_KEY
BIT2ME_API_SECRET=YOUR_BIT2ME_ACCOUNT_API_SECRET
# Optional Configuration
BIT2ME_GATEWAY_URL=https://gateway.bit2me.com # Must be HTTPS (localhost/127.x are exempt)
BIT2ME_REQUEST_TIMEOUT=30000 # Request timeout in ms (default: 30000)
BIT2ME_MAX_RETRIES=3 # Max retries for rate limits (default: 3)
BIT2ME_RETRY_BASE_DELAY=1000 # Base delay for backoff in ms (default: 1000)
BIT2ME_LOG_LEVEL=info # Log level: debug, info, warn, error (default: info)
LOG_FORMAT=json # Optional: "json" for log aggregators; default is human-readable
# AUDIT_LOG_PATH=/var/log/bit2me-mcp/audit.log # Append-only write-tool audit log
# BIT2ME_ENABLED_CATEGORIES=wallet,broker,general # Optional allow-list; unset = all
```
> **๐ก QA/Staging:** Use `BIT2ME_GATEWAY_URL` to point to different environments (e.g., `https://qa-gateway.bit2me.com` for QA testing).
> **๐ File permissions:** The `.env` file holds API credentials. Restrict it to the owner only:
>
> ```bash
> chmod 600 .env
> ```
>
> A pre-commit hook (`.husky/check-env-perms.sh`) prints a warning when the local `.env` mode is more permissive than `600`.
4. **Build the project:**
```bash
pnpm run build
```
## ๐ฅ๏ธ Usage with Claude Desktop
To use this server with the Claude Desktop application, add the following configuration to your `claude_desktop_config.json` file:
### MacOS
`~/Library/Application Support/Claude/claude_desktop_config.json`
### Windows
`%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"bit2me": {
"command": "node",
"args": ["/absolute/path/to/bit2me-mcp/build/index.js"],
"env": {
"BIT2ME_API_KEY": "YOUR_BIT2ME_ACCOUNT_API_KEY",
"BIT2ME_API_SECRET": "YOUR_BIT2ME_ACCOUNT_API_SECRET"
}
}
}
}
```
> **Note:** Replace `/absolute/path/to/...` with the actual full path to your project.
#### Using a Custom Gateway (QA/Staging)
For testing against different environments, add the `BIT2ME_GATEWAY_URL` variable:
```json
{
"mcpServers": {
"bit2me": {
"command": "node",
"args": ["/absolute/path/to/bit2me-mcp/build/index.js"],
"env": {
"BIT2ME_API_KEY": "YOUR_BIT2ME_ACCOUNT_API_KEY",
"BIT2ME_API_SECRET": "YOUR_BIT2ME_ACCOUNT_API_SECRET",
"BIT2ME_GATEWAY_URL": "https://qa-gateway.bit2me.com"
}
}
}
}
```
## ๐ก๏ธ Security
### Security Policy
For detailed information about reporting vulnerabilities and our security policy, please see [SECURITY.md](./SECURITY.md).
### Best Practices
- **API Keys**: Never commit API keys to version control. The pre-commit hook runs `gitleaks` (if installed) to block accidental secret commits.
- **Permissions**: Use minimal permissions. Avoid "Withdrawal" permissions for MCP usage.
- **HTTPS Gateway**: `BIT2ME_GATEWAY_URL` is validated at startup โ only `https://` URLs are accepted. Plain `http://` is rejected except for `localhost` / `127.x` addresses (local development only).
- **Monotonic Nonces**: API-key signing uses a strictly-increasing nonce counter so concurrent requests cannot generate replay-vulnerable signatures.
- **Expanded PII Redaction**: The logger scrubs API keys, signatures, JWTs, emails, IBANs, phone numbers, KYC fields, and long base64 blobs before writing any line to stderr.
- **Audit Log**: Every write tool appends an append-only JSON entry (tool name, sanitised args, outcome, correlation ID, SHA-256 fingerprint of the session token โ never the token itself). Set `AUDIT_LOG_PATH` to persist to a file.
## โ ๏ธ Rate Limits & Error Handling
The Bit2Me API enforces rate limits to ensure stability.
- **429 Too Many Requests**: The client retries with exponential backoff and **full jitter** (`BIT2ME_RETRY_BASE_DELAY`, default 1000 ms, up to `BIT2ME_MAX_RETRIES`).
- **Console Warnings**: You may see warnings in the logs if rate limits are hit.
- **Best Practice**: Avoid asking for massive amounts of data in a very short loop.
## ๐ Logging
The server implements a structured logging system that automatically sanitizes sensitive data (API keys, signatures, JWTs, emails, IBANs, and other PII).
You can control the verbosity using the `BIT2ME_LOG_LEVEL` environment variable:
- `debug`: Detailed request/response logs (useful for development)
- `info`: Startup and operational events (default)
- `warn`: Rate limits and non-critical issues
- `error`: API errors and failures
Set `LOG_FORMAT=json` to switch the logger to a single-JSON-object-per-line format suitable for log aggregators (Loki, Datadog, CloudWatch, etc.). The default is human-readable.
All logs are written to **stderr**; stdout is reserved for the MCP JSON-RPC frame.
## ๐งต Concurrency Model
Each incoming tool call runs inside its own [`AsyncLocalStorage`](https://nodejs.org/api/async_context.html#class-asynclocalstorage) boundary. The store carries:
- `correlationId`: a UUID generated per request, included in every log line
- `sessionToken` (`jwt`): the optional per-call session token, never logged in the clear
- `toolName`, `startTime`: useful for metrics / audit
Two concurrent HTTP requests (for example two JWTs in flight on the same local process) never share ALS state. That is request isolation, not a multi-user product โ see [ADR 0003](./docs/adr/0003-local-single-user-threat-model.md). Tests outside `runWithContext` fall back to a safe default. See `tests/concurrency.test.ts` and `tests/http-transport-*.test.ts`.
Per-request state stored via `memoizePerRequest()` (e.g. wallet pockets fetched multiple times during a single broker quote) is keyed by `correlationId` and cleared in the `finally` block of `executeTool()` so the cache cannot grow unbounded.
## ๐ข Operating in Production
Two binaries ship with this package:
- `bit2me-mcp-server` โ the original stdio transport, designed to be spawned by a single LLM client (Claude Desktop, Cursor, โฆ).
- `bit2me-mcp-http` โ HTTP JSON-RPC (`src/index-http.ts`). Each request may send its own credentials (`X-Bit2Me-Api-Key` + `X-Bit2Me-Api-Secret` or `Authorization: Bearer <jwt>`). `POST /mcp` handles `initialize`, `tools/*`, `prompts/*`, `resources/*`. A notification (no `id`) returns `202` with an empty body. `GET /mcp` (SSE) is reserved, not implemented. Default bind is loopback (`127.0.0.1`). This is not a hosted multi-tenant SaaS; see [ADR 0003](./docs/adr/0003-local-single-user-threat-model.md). Put TLS in front of any non-loopback bind.
Recommended environment variables for the HTTP binary:
- `MCP_HTTP_HOST` / `MCP_HTTP_PORT` (default `127.0.0.1:3000`)
- `MCP_HTTP_AUTH_MODE`: `api_key` (default), `jwt`, or `both`
- `LOG_FORMAT=json` for structured logs
- `AUDIT_LOG_PATH=/var/log/bit2me-mcp/audit.log` to ship audit lines to a file
### Choosing an auth mode (HTTP transport)
The HTTP transport accepts API-key credentials and Bit2Me session JWTs. Both
modes are first-class โ the right choice depends on **where the server is
bound and who is calling it**, not on a one-size-fits-all rule. The full
threat model and rationale live in [`docs/adr/0001-valet-key-http-credentials.md`](./docs/adr/0001-valet-key-http-credentials.md).
| Topology | Recommended `MCP_HTTP_AUTH_MODE` | Why |
| ---------------------------------------------------------------------- | ---------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| stdio (Cursor, Claude Desktop, local CLI) | n/a โ use `BIT2ME_API_KEY` / `BIT2ME_API_SECRET` in `.env` | Single-process, no network hop; scopes are enforced by the Bit2Me dashboard. |
| HTTP bound to loopback (`127.0.0.1`, `::1`, `localhost`) | `api_key` | Credentials never leave the host. |
| HTTP on a private network / VPN behind a TLS-terminating reverse proxy | `api_key` | Encrypted hop; scopes enforced by the Bit2Me dashboard; operator owns the proxy chain. |
| HTTP exposed on the public internet for a single operator | `jwt` | Bit2Me JWTs auto-expire (~15 min); the leak window is shorter. |
| HTTP shared by multiple third-party integrators | `jwt` | Independent revocation per integrator without rotating the master credentials. |
Hard rules that apply regardless of the mode you pick:
- **Mint API keys with the smallest scope** that satisfies the caller's use
case. Read-only when possible. **Never enable Withdrawal scopes for MCP
usage** โ the MCP server intentionally does not support external withdrawals,
so granting that permission only widens the blast radius of a leak.
- **Always put the HTTP transport behind TLS** on any non-loopback bind.
Plain HTTP on `0.0.0.0` is a misconfiguration regardless of the auth mode.
- The server emits a startup `WARN` log if `api_key`/`both` is active on a
non-loopback host so operators are nudged toward a TLS-terminating proxy or
the JWT mode.
- Credential headers (`X-Bit2Me-Api-Key`, `X-Bit2Me-Api-Secret`,
`Authorization`) are scrubbed from every structured log line before it
reaches stderr.
Built-in observability endpoints (HTTP transport only):
- `GET /health` โ liveness + Bit2Me reachability + cache/circuit-breaker/rate-limiter snapshot. Cached for 30s.
- `GET /metrics` โ Prometheus text-format counters (`bit2me_mcp_tool_calls_total`, `bit2me_mcp_tool_errors_total`, `bit2me_mcp_tool_duration_avg_ms`).
Reliability features active by default:
- Circuit breaker on the upstream Bit2Me API (`src/utils/circuit-breaker.ts`).
- Per-endpoint rate limiter with exponential backoff + jitter.
- Idempotency keys on every write tool (`pro_create_order`, `loan_create`, `earn_deposit`, โฆ) โ the wrapper stamps a stable key if the caller omits `idempotency_key`.
- Irreversible writes (Pro / Earn / Loan / `broker_confirm_quote`; not `broker_quote_*`) return a `needs_confirmation` preview unless `confirm` is the boolean `true`. The preview repeats the stamped `idempotency_key`.
- Monotonic request nonces for API-key signing (replay-safe even under high concurrency).
- Append-only audit log for every successful **and** failed write operation.
## โ Troubleshooting
### Error: "Connection refused"
- Ensure the MCP server is running.
- Check that the path in `claude_desktop_config.json` points correctly to the `build/index.js` file.
### Error: "API Key invalid" or "Unauthorized"
- Verify your keys in `.env` or the Claude config.
- Ensure your API keys have the necessary permissions (Wallet, Trade, Earn, etc.) enabled in the Bit2Me dashboard.
- Check that there are no extra spaces or quotes around the API key values.
### Error: "Rate limit exceeded" or 429 responses
- The Bit2Me API has rate limits. The server automatically retries with exponential backoff.
- If you're hitting rate limits frequently, reduce the number of concurrent requests.
- Consider adding delays between operations in your workflows.
### Tools not showing up in Claude
- Restart Claude Desktop completely (quit and reopen).
- Check the Claude Desktop logs for initialization errors.
- Verify the configuration file syntax is valid JSON.
### Error: "Request timeout"
- Check your internet connection.
- Increase `BIT2ME_REQUEST_TIMEOUT` in your environment variables (default: 30000ms).
- Some Bit2Me API endpoints may be temporarily slow.
### Environment variables not loading
- When using `npx`, environment variables must be set in the config file's `env` section.
- For local development, ensure the `.env` file is in the project root.
- The server prioritizes config-provided credentials over `.env` file values.
### Error: "Network error" or CORS issues
- The MCP server runs server-side and doesn't have CORS restrictions.
- Network errors usually indicate connectivity problems or API downtime.
- Check the Bit2Me status page or try again later.
### Debugging
- Run the server manually to see logs:
```bash
pnpm dev
```
- Set `BIT2ME_LOG_LEVEL=debug` for detailed logging.
- Check Claude Desktop logs:
- macOS: `~/Library/Logs/Claude/mcp*.log`
- Windows: `%APPDATA%\Claude\logs\mcp*.log`
## ๐ Testing with MCP Inspector
[MCP Inspector](https://github.com/modelcontextprotocol/inspector) is the official debugging tool for MCP servers. It provides a web interface to test your tools, view responses, and debug issues.
### Installation
This repo uses `pnpm dlx` (see `pnpm dev` / `make dev`). Consumers of the published package can use `npx`.
### Running the Inspector
#### Option A: Published package (no clone)
```bash
export BIT2ME_API_KEY=YOUR_BIT2ME_ACCOUNT_API_KEY
export BIT2ME_API_SECRET=YOUR_BIT2ME_ACCOUNT_API_SECRET
npx -y @modelcontextprotocol/inspector npx @bit2me/mcp-server
```
#### Option B: Local repository
```bash
git clone https://github.com/bit2me-devs/bit2me-mcp.git
cd bit2me-mcp
pnpm install
pnpm run build
export BIT2ME_API_KEY=YOUR_BIT2ME_ACCOUNT_API_KEY
export BIT2ME_API_SECRET=YOUR_BIT2ME_ACCOUNT_API_SECRET
pnpm dlx @modelcontextprotocol/inspector node build/index.js
```
Or after install: `pnpm dev` (same inspector against `build/index.js`).
CLI (no browser) โ list tools against the local build:
```bash
pnpm dlx @modelcontextprotocol/inspector --cli node build/index.js --method tools/list
```
**Note:** The web inspector opens at `http://localhost:5173`.
### Using the Inspector
The web interface provides:
1. **Tools Tab:**
- View all 48 available tools
- See input schemas for each tool
- Test tools with custom parameters
- View formatted responses
2. **Resources Tab:**
- Explore `bit2me://health`, `bit2me://server`, and `bit2me://catalog`
3. **Prompts Tab:**
- Test prompt templates (if configured)
4. **Request/Response Logs:**
- See all MCP protocol messages
- Debug communication issues
- View timing information
### Example: Testing a Tool
1. Navigate to the **Tools** tab
2. Select a tool (e.g., `pro_get_ticker`)
3. Fill in the required parameters:
```json
{
"pair": "BTC-EUR"
}
```
4. Click **Run** to execute the tool
5. View the formatted response in the output panel
## ๐ Landing Page Deployment
The project's landing page is located in the `/landing` directory.
Deployment is automated using GitHub Actions.
**How to update the website:**
1. Tool catalogue: edit `data/tools.json` (Python/shell), then `pnpm build:docs` and commit `TOOLS_DOCUMENTATION.md`. `landing/tools-data.js` is gitignored (Pages / `pnpm build:docs` for local preview).
2. Page chrome: edit HTML/CSS/`CNAME` in `/landing` if needed.
3. Push to `main`. Pages deploy on push; after a SemVer release the `landing` job in `release.yml` runs again so the catalogue snapshot can see the new git tag.
4. The hero **Stable** badge reads **live npm**, not `package.json` on `main`. Same source as the shields.io npm badge. See [docs/stack/release.md](./docs/stack/release.md).
**Domain:**
The `/landing/CNAME` file manages the custom domain configuration.
## ๐ค Contributing
We welcome contributions to improve this MCP server! Whether it's fixing bugs, adding new tools, or improving documentation, your help is appreciated.
Please read our **[Contributing Guidelines](./CONTRIBUTING.md)** for details on:
- Setting up your development environment
- Running tests
- Commit conventions (Conventional Commits)
- Pull Request process
### Quick Start
1. **Fork and Clone**:
```bash
git clone https://github.com/bit2me-devs/bit2me-mcp.git
```
2. **Install Dependencies**:
```bash
pnpm install
```
3. **Create a Branch**:
```bash
git checkout -b feat/amazing-feature
```
For full details, check the [CONTRIBUTING.md](./CONTRIBUTING.md) file.
### Code of Conduct
Be respectful, inclusive, and constructive. Full text:
[CODE_OF_CONDUCT.md](./CODE_OF_CONDUCT.md).
## ๐ License
[MIT License](./LICENSE)
TDQS
Scored across 48 tools
Domain prefixes (earn_, pro_, wallet_, loan_, broker_) help separate major areas, but there are several similar-sounding clusters: earn_get_summary versus earn_get_movements_summary, broker_get_asset_price versus broker_get_asset_data versus broker_get_asset_chart, and pro_get_trades versus pro_get_public_trades versus pro_get_order_trades. The descriptions are detailed enough to resolve ambiguity, but an agent could easily select the wrong tool without careful reading.
All tools consistently follow a domain_verb_noun snake_case pattern (e.g., wallet_get_pockets, pro_create_order, loan_payback). Action verbs and resource nouns are clear, and even multi-word resources are formatted consistently. No camelCase or mixed conventions appear.
48 tools is well above the 25+ threshold and feels heavy even though the server covers multiple product areas (Wallet, Pro, Earn, Loans, and meta tools). Several tools could potentially be consolidated, especially the overlapping Earn summary/config getters and multiple market-data tools.
The main product lifecycles are well covered: broker quotes confirm into buy/sell/swap, Pro orders can be created and cancelled, Earn supports deposit/withdraw and detailed position/reward queries, and Loans support simulate/create/payback/guarantee increase. Notable minor gaps include no external send/withdrawal from Simple Wallet, no Pro order modification, and no card management beyond listing.