movmint-fx-mcp
by nziacbdc
README.md
# movmint-fx-mcp
MCP server for the Movmint FX quoting and capture service. Exposes two tools (`get_fx_quote`, `capture_fx_quote`) that LLM clients can call to get live FX rates and execute trades.
---
## Architecture
### How it fits together
```
┌─────────────────────────────────────────────────────────────────┐
│ LLM Client (Claude Desktop / Open WebUI + Ollama) │
└───────────────────────┬─────────────────────────────────────────┘
│
┌─────────────▼──────────────┐
│ Transport layer │
│ │
│ Option A: stdio │ ← Claude Desktop spawns
│ (no port, no proxy) │ the process directly
│ │
│ Option B: HTTP via mcpo │ ← Open WebUI / Ollama
│ localhost:8008 │ connects as tool server
└─────────────┬──────────────┘
│
┌─────────────▼──────────────┐
│ MCP Server (Node.js) │
│ src/index.ts │
│ │
│ Tools: │
│ • get_fx_quote │
│ • capture_fx_quote │
└─────────────┬──────────────┘
│ OAuth2 client_credentials
│ Bearer token (cached, auto-refreshed)
┌─────────────▼──────────────┐
│ Movmint API │
│ api.nextgen.digitalfiat.app│
│ │
│ POST /fx/quote │
│ POST /fx/quote/capture/:id│
└────────────────────────────┘
```
### MCP Server (`src/index.ts`)
Written in TypeScript using the `@modelcontextprotocol/sdk`. Key behaviours:
- **Transport:** `StdioServerTransport` — communicates over stdin/stdout. Does not bind to a network port by itself.
- **Auth:** OAuth2 `client_credentials` flow. Tokens are cached in memory and refreshed 30 seconds before expiry.
- **Validation:** Tool inputs are validated with `zod` schemas before the API is called.
#### Tool: `get_fx_quote`
Calls `POST /fx/quote` on the Movmint API.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `from_currency` | string | Yes | Source currency code (e.g. `BSD`, `USD`) |
| `to_currency` | string | Yes | Target currency code (e.g. `USDC`, `EUR`) |
| `amount` | number | Yes | Amount in `from_currency` |
| `funding_method` | `IMMEDIATE` \| `DEFERRED` | No | Defaults to `IMMEDIATE` |
| `tx_configuration` | object | Yes | Client reference ID + source/target payment config |
| `participants` | array | No | KYC participants (ULTIMATE_ORIGINATOR, ULTIMATE_BENEFICIARY, etc.) |
Returns a `quote_id` valid for approximately 30 seconds.
#### Tool: `capture_fx_quote`
Calls `POST /fx/quote/capture/{quote_id}` on the Movmint API.
| Parameter | Type | Required | Description |
|-----------|------|----------|-------------|
| `quote_id` | string | Yes | The `quote_id` returned from `get_fx_quote` |
Returns transaction details including the deposit address for funding.
#### Payment configuration schemas
`tx_configuration` accepts `source_configuration` and `target_configuration`, each with a `source_type` and an `account_configuration` that is one of:
| Type | Fields |
|------|--------|
| `BANK_ACCOUNT` | `account_number`, `routing_number`, `account_type` (`CHECKING`/`SAVINGS`) |
| `DLT_WALLET` | `wallet_address`, `network` (`ethereum`/`solana`/`base`/`sanddollar`) |
| `CARD` | `card_number`, `expiry_date`, `cvv`, `cardholder_name`, `card_type` (`CreditCard`/`DebitCard`) |
---
## Environment variables
| Variable | Default | Required |
|----------|---------|----------|
| `CLIENT_ID` | — | **Yes** |
| `CLIENT_SECRET` | — | **Yes** |
| `MOVMINT_BASE_URL` | `https://api.nextgen.digitalfiat.app` | No |
| `MOVMINT_TOKEN_URL` | `https://api.nextgen.digitalfiat.app/oauth2/token` | No |
| `MOVMINT_TOKEN_AUDIENCE` | `fx-service` | No |
Store these in a `.env` file at the project root (never commit it — it is gitignored).
```
CLIENT_ID=your-client-id
CLIENT_SECRET=your-client-secret
MOVMINT_BASE_URL=https://api.nextgen.digitalfiat.app
MOVMINT_TOKEN_URL=https://api.nextgen.digitalfiat.app/oauth2/token
MOVMINT_TOKEN_AUDIENCE=fx-service
```
---
## Bootstrap: running locally
### Prerequisites
- Node.js 20+
- `uvx` (ships with `uv`) — for running `mcpo` without a permanent install
### 1. Install dependencies and build
```bash
cd /path/to/movmint-fx-mcp
npm install
npm run build # compiles src/ → dist/
```
### 2. Option A — Claude Desktop (stdio, no proxy needed)
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
```json
{
"mcpServers": {
"movmint-fx": {
"command": "node",
"args": ["/absolute/path/to/movmint-fx-mcp/dist/index.js"],
"env": {
"CLIENT_ID": "your-client-id",
"CLIENT_SECRET": "your-client-secret"
}
}
}
}
```
Restart Claude Desktop. The tools appear automatically in the tool picker.
### 2. Option B — Open WebUI + Ollama (HTTP via mcpo)
`mcpo` is a proxy that wraps any stdio MCP server and exposes it as an OpenAI-compatible HTTP tool server. Open WebUI can then connect to it as a tool source for any hosted model including Ollama models.
#### Port map (confirmed on this machine)
| Service | Port |
|---------|------|
| Ollama | 11434 |
| Open WebUI | 8080 |
| mcpo (this server) | **8008** |
#### Step 1 — Create `mcpo-config.json`
Create `mcpo-config.json` at the project root (it is gitignored):
```json
{
"mcpServers": {
"movmint-fx": {
"command": "node",
"args": ["/absolute/path/to/movmint-fx-mcp/dist/index.js"],
"env": {
"CLIENT_ID": "your-client-id",
"CLIENT_SECRET": "your-client-secret",
"MOVMINT_BASE_URL": "https://api.nextgen.digitalfiat.app",
"MOVMINT_TOKEN_URL": "https://api.nextgen.digitalfiat.app/oauth2/token",
"MOVMINT_TOKEN_AUDIENCE": "fx-service"
}
}
}
}
```
#### Step 2 — Start mcpo
```bash
uvx mcpo --port 8008 --config /absolute/path/to/movmint-fx-mcp/mcpo-config.json
```
Verify it is running:
```bash
curl http://localhost:8008/docs # OpenAPI/Swagger UI
curl http://localhost:8008/openapi.json
```
#### Step 3 — Connect Open WebUI
1. Open WebUI → **Admin Panel → Settings → Tools**
2. Add tool server URL: `http://localhost:8008`
3. Open WebUI discovers `get_fx_quote` and `capture_fx_quote` automatically via the OpenAPI spec
4. Enable the tools when starting a chat with any Ollama model
### 3. Development mode (watch + rebuild)
```bash
npm run dev # tsc --watch, rebuilds dist/ on every save
```
Run mcpo in a separate terminal; it will pick up the rebuilt `dist/index.js` on the next tool invocation (the Node process is spawned fresh per mcpo request).
---
## Project structure
```
movmint-fx-mcp/
├── src/
│ └── index.ts # MCP server — tools, auth, API client
├── dist/ # Compiled output (gitignored)
├── interactions/
│ └── SD-CAD_SD-USD Collection.postman_collection.json
├── mcpo-config.json # mcpo proxy config with credentials (gitignored)
├── package.json
├── tsconfig.json
├── .env # Local credentials (gitignored)
└── .gitignore
```
---
## Security notes
- `mcpo-config.json` and `.env` both contain credentials and are gitignored. Do not commit either file.
- The MCP server logs the token request URL and body to `stderr` for debugging. Avoid piping stderr to shared log aggregators in production.
- The `quote_id` returned by `get_fx_quote` expires in ~30 seconds. Do not store or reuse stale quote IDs.
TDQS
A4.1/5.0
Scored across 2 tools
Disambiguation5/5
The two tools have clearly distinct purposes: one generates a quote, the other executes it. No overlap or ambiguity.
Naming Consistency5/5
Both tools follow a consistent verb_noun pattern with snake_case: get_fx_quote and capture_fx_quote.
Tool Count4/5
With only 2 tools, the set is minimal but appropriate for a focused FX quote-capture workflow. Slightly thin but not unreasonable.
Completeness3/5
The core flow of getting and capturing a quote is covered, but missing operations like quote status, history, or cancellation create notable gaps.
Maintenance
ActivityStale
ResponsivenessNo issues