Skip to main content

OpenWealth MCP

CI PyPI Python License

Three FastMCP servers that expose the OpenWealth APIs as MCP tools, so an AI assistant (Claude, Cursor, any MCP client) can read custody data, manage orders, and onboard customers through a typed, audited interface instead of raw HTTP.

Server API Console script Tools
Custody Custody Services v3.2.0 — customers, accounts, positions, transactions openwealth-custody-mcp 10 (read-only)
Trading Order Placement v3.0.1 — orders, executions, quotes, subscriptions openwealth-trading-mcp 18 (full lifecycle)
Customer Customer Management v2.0.6 — customers, persons, contacts, addresses, documents, KYC openwealth-customer-mcp 26 (full lifecycle)

All three ship in one Python package and speak MCP over stdio. OpenAPI specs are vendored from OpenWealth and served as sanitized MCP resources (server URLs and auth schemes are stripped before the spec is exposed to the LLM).

⚠️ Trading places real orders. create_order is a financially consequential tool. Read Safety model before pointing it at anything other than the sandbox.


Install

pip install openwealth-mcp

Requires Python ≥ 3.11 and a bearer token for an OpenWealth endpoint (sandbox or custodian).

To install from source for development:

git clone https://github.com/OpenWealth/OpenWealth-MCP.git
cd OpenWealth-MCP
pip install -e ".[dev]"    # or: uv sync --extra dev

Quickstart

Configure each server separately — each needs its own base URL and token.

Claude Desktop / Claude Code (claude_desktop_config.json):

{
  "mcpServers": {
    "openwealth-custody": {
      "command": "openwealth-custody-mcp",
      "env": {
        "OPENWEALTH_CUSTODY_BASE_URL": "https://api.openwealth.synpulse8.com/api/custody-services/v3",
        "OPENWEALTH_BEARER_TOKEN": "<jwt>"
      }
    },
    "openwealth-trading": {
      "command": "openwealth-trading-mcp",
      "env": {
        "OPENWEALTH_TRADING_BASE_URL": "https://<host>/api/trading-services/v1",
        "OPENWEALTH_BEARER_TOKEN": "<jwt>"
      }
    },
    "openwealth-customer": {
      "command": "openwealth-customer-mcp",
      "env": {
        "OPENWEALTH_CUSTOMER_MANAGEMENT_BASE_URL": "https://api.openwealth.synpulse8.com/api/customer-management/v2",
        "OPENWEALTH_BEARER_TOKEN": "<jwt>"
      }
    }
  }
}

Cursor (.cursor/mcp.json, or Settings → MCP for a global server):

{
  "mcpServers": {
    "openwealth-custody": {
      "command": "openwealth-custody-mcp",
      "env": {
        "OPENWEALTH_CUSTODY_BASE_URL": "https://api.openwealth.synpulse8.com/api/custody-services/v3",
        "OPENWEALTH_BEARER_TOKEN": "<jwt>"
      }
    },
    "openwealth-trading": {
      "command": "openwealth-trading-mcp",
      "env": {
        "OPENWEALTH_TRADING_BASE_URL": "https://<host>/api/trading-services/v1",
        "OPENWEALTH_BEARER_TOKEN": "<jwt>"
      }
    },
    "openwealth-customer": {
      "command": "openwealth-customer-mcp",
      "env": {
        "OPENWEALTH_CUSTOMER_MANAGEMENT_BASE_URL": "https://api.openwealth.synpulse8.com/api/customer-management/v2",
        "OPENWEALTH_BEARER_TOKEN": "<jwt>"
      }
    }
  }
}

Then run MCP: Restart Servers from the command palette and check that the server shows as connected. Configure only the domain you have access to.

Sandbox JWTs often expire in about 60 seconds — refresh from the portal and restart the server. Supply the token without the Bearer prefix; the client adds it.

Full client wiring, WSL specifics and troubleshooting live in docs/mcp-clients.md and docs/local-dev.md.


Configuration

All settings are environment variables prefixed OPENWEALTH_. A .env file in the working directory is loaded automatically (and is gitignored — never commit one). Host and credentials are never hard-coded.

Variable Default Description
OPENWEALTH_CUSTODY_BASE_URL Custody API base URL including the path prefix, no trailing slash. Required when running the Custody server. https:// is added if the scheme is missing.
OPENWEALTH_TRADING_BASE_URL Trading API base URL including the path prefix, no trailing slash. Required when running the Trading server.
OPENWEALTH_CUSTOMER_MANAGEMENT_BASE_URL Customer Management API base URL including the path prefix, no trailing slash. Required when running the Customer Management server.
OPENWEALTH_BEARER_TOKEN Access token without the Bearer prefix. Required unless OPENWEALTH_AUTH_HEADER is set.
OPENWEALTH_AUTH_HEADER Full Authorization header value; overrides OPENWEALTH_BEARER_TOKEN.
OPENWEALTH_CORRELATION_ID generated Fixed correlation id; otherwise a UUID per request.
OPENWEALTH_TIMEOUT_SECONDS 120 Read/write timeout in seconds (max 300).
OPENWEALTH_CONNECT_TIMEOUT_SECONDS 10 Connect timeout in seconds (max 120).
OPENWEALTH_MAX_RETRIES 2 Retries for transient failures (0–5). See Safety model.
OPENWEALTH_VERIFY_TLS true Set to false only against a sandbox with a self-signed certificate.
OPENWEALTH_LOG_LEVEL INFO DEBUG, INFO, WARNING, or ERROR. JSON logs on stderr.
OPENWEALTH_LOG_FILE Optional log file path (logs to both file and stderr).

Startup fails fast if neither OPENWEALTH_BEARER_TOKEN nor OPENWEALTH_AUTH_HEADER is set. The URL for each server is validated at startup — a missing URL prints a clear error and exits.

Transport is stdio only. HTTP transport and JWKS ingress are out of scope in favour of a smaller surface.


Tools

Every response is JSON with status_code, correlation_id and data (plus next_cursor on paginated GETs). Errors return {"error": true, "error_code": "...", "message": "...", "retryable": bool} — never a stack trace.

Custody — openwealth-custody-mcp

Tool operationId Endpoint
get_customers getCustomers GET /customers
get_customers_by_customer_id getCustomersByCustomerId GET /customers/{customerId}
get_customer_accounts_by_customer_id getCustomerAccountsByCustomerId GET /customers/{customerId}/accounts
get_customer_account_by_id getCustomerAccountById GET /customers/{customerId}/accounts/{accountId}
get_customer_position_by_customer_id getCustomerPositionByCustomerId GET /customers/{customerId}/positions
get_customer_position_by_id getCustomerPositionById GET /customers/{customerId}/positions/{positionId}
get_account_position_by_account_id getAccountPositionByAccountId GET /accounts/{accountId}/positions
get_account_position_by_id getAccountPositionById GET /accounts/{accountId}/positions/{positionId}
get_transaction_by_customer_id getTransactionByCustomerId GET /customers/{customerId}/transactions
get_transaction_by_transaction_id getTransactionByTransactionId GET /customers/{customerId}/transactions/{transactionId}

Listing positions and transactions requires a date (YYYY-MM-DD) — the OpenAPI spec makes it mandatory.

Trading — openwealth-trading-mcp

Tool operationId Endpoint
list_customers listCustomers GET /customers
get_customer getCustomer GET /customers/{customerId}
list_accounts listAccounts GET /accounts
get_account getAccount GET /accounts/{accountId}
list_orders listOrders GET /orders
get_order getOrder GET /orders/{orderId}
create_order ⚠️ createOrder POST /orders
cancel_order actionCancelOrder POST /orders/{orderId}/actions/cancel
list_order_executions listOrderExecutions GET /orders/{orderId}/executions
get_order_execution getOrderExecution GET /orders/{orderId}/executions/{executionId}
list_order_states listOrderStates GET /orders/{orderId}/states
create_quote createQuote POST /quotes
list_event_subscriptions listEventSubscriptions GET /event-subscriptions
get_event_subscription getEventSubscription GET /event-subscriptions/{eventSubscriptionId}
create_event_subscription createEventSubscription POST /event-subscriptions
update_event_subscription updateEventSubscription PUT /event-subscriptions/{eventSubscriptionId}
delete_event_subscription deleteEventSubscription DELETE /event-subscriptions/{eventSubscriptionId}
list_event_subscription_notifications listEventSubscriptionEventNotifications GET /event-subscriptions/{eventSubscriptionId}/event-notifications

Customer Management — openwealth-customer-mcp

Tool operationId Endpoint
get_customers getCustomers GET /customers
create_customer ⚠️ postCustomer POST /customer-details
get_customer getCustomerByCustomerId GET /customers/{customerId}
get_customer_details getCustomerDetailsByCustomerId GET /customers/{customerId}/customer-details
get_persons getPersons GET /customers/{customerId}/persons
create_person ⚠️ postPerson POST /customers/{customerId}/person-details
get_person getPersonByPersonId GET /customers/{customerId}/persons/{personId}
get_person_details getPersonDetailsByPersonId GET /customers/{customerId}/person-details/{personId}
get_contacts getContactDetailsByCustomerId GET /customers/{customerId}/persons/{personId}/contacts
create_contact postContactDetailsByCustomerId POST /customers/{customerId}/persons/{personId}/contacts
get_contact getContactDetailsByContactDetailID GET /customers/{customerId}/persons/{personId}/contacts/{contactId}
update_contact putContactDetailByContactDetailId PUT /customers/{customerId}/persons/{personId}/contacts/{contactId}
delete_contact deleteContactDetailsByContactDetailID DELETE /customers/{customerId}/persons/{personId}/contacts/{contactId}
get_addresses getAddressByCustomerId GET /customers/{customerId}/persons/{personId}/addresses
create_address postAddressByCustomerId POST /customers/{customerId}/persons/{personId}/addresses
get_address getAddressByAddressId GET /customers/{customerId}/persons/{personId}/addresses/{addressId}
update_address putAddressByCustomerId PUT /customers/{customerId}/persons/{personId}/addresses/{addressId}
get_documents getDocumentsByCustomerId GET /customers/{customerId}/documents
create_document ⚠️ postDocumentByCustomerId POST /customers/{customerId}/document-details
get_document getDocumentByDocumentId GET /customers/{customerId}/documents/{documentId}
get_document_details getDocumentDetailsByDocumentId GET /customers/{customerId}/documents/{documentId}/document-details
get_kyc getKycByCustomerId GET /customers/{customerId}/persons/{personId}/kyc
create_kyc ⚠️ postKyc POST /customers/{customerId}/persons/{personId}/kyc
create_prospect_precheck postProspect POST /prospect-precheck
get_prospect_precheck getPreCheck GET /prospect-precheck/{temporaryId}
get_status getStatusByTemporaryId GET /status/{temporaryId}

⚠️ marks tools that create regulatory or compliance-significant entities (customer, person, document, kyc) — records that are hard to reverse and carry KYC/AML implications. Write tools on softer, mutable data (contact, address, prospect_precheck) are not marked because they can be freely updated or deleted without compliance impact. All Customer Management write tools are still never retried regardless of the ⚠️ marker — see Safety model.

MCP resources

URI Content
openwealth://specs/custody Custody tool/endpoint table (Markdown)
openwealth://specs/custody.yaml Custody OpenAPI schema reference (server URLs and auth stripped)
openwealth://specs/trading Trading tool/endpoint table with financial-impact notes
openwealth://specs/trading.yaml Trading OpenAPI schema reference (server URLs and auth stripped)
openwealth://specs/customer Customer Management tool/endpoint table with write-impact notes
openwealth://specs/customer.yaml Customer Management OpenAPI schema reference (server URLs and auth stripped)

Safety model

  • create_order is never retried. A duplicate order is a financial error, so a failed POST fails loudly rather than silently placing a second one.
  • Customer Management write tools are never retried. create_customer, create_person, create_contact, create_address, create_document, create_kyc and create_prospect_precheck are not retried to avoid duplicate records at the custody bank.
  • Idempotent writes are retried on 5xx: cancel_order, create_quote, update_contact, update_address, PUT and DELETE. GETs retry on 408, 429 and 5xx with exponential backoff and ±20% jitter. The Retry-After header is honoured.
  • Tool annotations (readOnlyHint, destructiveHint, idempotentHint) are set per tool, so MCP clients can require confirmation for writes.
  • Tokens are never tool arguments. They come from the environment only, and are never echoed in tool results or logs.
  • Custody is read-only by design. Only the Trading and Customer servers can mutate state.

Always confirm order details with a human before calling create_order.


Development

With uv (recommended):

uv sync --extra dev

uv run ruff check src tests
uv run ruff format --check src tests
uv run mypy
uv run pytest -q

With pip:

pip install -e ".[dev]"

ruff check src tests
ruff format --check src tests
mypy
pytest -q

The same four gates run in CI on every push and pull request across Python 3.11, 3.12 and 3.13. pre-commit install wires ruff and mypy into your commits.

See CONTRIBUTING.md for full contribution guidelines.


Documentation

Where What
CHANGELOG.md Release history
CONTRIBUTING.md Dev setup and contribution guidelines
docs/mcp-clients.md MCP client configuration (Claude, Cursor, WSL)
docs/local-dev.md Local development setup
docs/release.md Release and publishing process
specs/ Vendored OpenAPI definitions
SECURITY.md Vulnerability reporting and secret handling

Scope

Custody is read-only (GET). Trading covers the full order lifecycle (GET, POST, PUT, DELETE). Customer Management covers the full customer onboarding and lifecycle (GET, POST, PUT, DELETE). HTTP transport, JWKS ingress and a central MCP gateway are out of scope.


License

Apache-2.0

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openwealth_mcp-0.3.7.tar.gz (210.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openwealth_mcp-0.3.7-py3-none-any.whl (89.5 kB view details)

Uploaded Python 3

File details

Details for the file openwealth_mcp-0.3.7.tar.gz.

File metadata

  • Download URL: openwealth_mcp-0.3.7.tar.gz
  • Upload date:
  • Size: 210.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for openwealth_mcp-0.3.7.tar.gz
Algorithm Hash digest
SHA256 ad14f2dc37b01ccbcc64e1bc66c434f3d217f57dae212d811ff4de407411927b
MD5 3e4c17da3301c222a63c634882107273
BLAKE2b-256 12a4697bde3da5edce791f94059e3ab4774e16938c3e973532bb82708bb3a34f

See more details on using hashes here.

Provenance

The following attestation bundles were made for openwealth_mcp-0.3.7.tar.gz:

Publisher: publish.yml on OpenWealth/OpenWealth-MCP

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openwealth_mcp-0.3.7-py3-none-any.whl.

File metadata

  • Download URL: openwealth_mcp-0.3.7-py3-none-any.whl
  • Upload date:
  • Size: 89.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for openwealth_mcp-0.3.7-py3-none-any.whl
Algorithm Hash digest
SHA256 2e43425b9314223b210b13408e6aff99b0180f3563faac83494e3b3a30d87f76
MD5 7fdf35c5579d7abc10d24dec17498e01
BLAKE2b-256 28c8757c30b90e5924c1299c376630d4a35606294e0a9f5a9e49a3a620146585

See more details on using hashes here.

Provenance

The following attestation bundles were made for openwealth_mcp-0.3.7-py3-none-any.whl:

Publisher: publish.yml on OpenWealth/OpenWealth-MCP

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.3.7 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page