iol-mcp
by ejgonzalez90
README.md
# iol-mcp
An unofficial [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for the
[InvertirOnline (IOL)](https://www.invertironline.com/) REST API, the Argentine retail broker.
It lets AI agents such as Claude Code read your portfolio and account statement, fetch quotes and
historical series, check MEP dollar rates, browse mutual funds (FCIs), and, only if you explicitly
enable it, place and cancel orders.
> ## Disclaimer
>
> - This project is **not affiliated with, endorsed by, or supported by InvertirOnline** or any of
> its companies. "InvertirOnline" is a trademark of its owner.
> - **Use at your own risk.** Software that can place orders with real money can lose real money.
> The authors accept no liability for any loss, including losses caused by bugs, API changes, or
> mistakes made by an AI agent. Nothing here is financial advice.
> - **Trading is disabled by default.** Tools that buy, sell, cancel, subscribe or redeem are not
> even registered unless you set `ENABLE_TRADING=true`. Leave it off unless you understand what
> you are enabling, and consider using it only with an agent that asks you to confirm each action.
> - Your IOL credentials are used to log in to the IOL API from the machine running this server.
> The server has no authentication of its own, so keep it on a machine and network you trust.
## Quick start
You need an InvertirOnline account with API access and either Docker or Node.js 24+.
### 1. Configure credentials
```bash
cp .env.example .env
# edit .env and set IOL_USERNAME and IOL_PASSWORD
```
See [Configuration](#configuration) for all variables.
### 2. Run the server
**Docker, prebuilt image** (published by CI to GitHub Container Registry):
```bash
docker run -d --name iol-mcp --restart unless-stopped \
--env-file .env -p 127.0.0.1:7577:7577 \
ghcr.io/ejgonzalez90/iol-mcp:latest
```
**Docker Compose, built locally:**
```bash
docker compose up -d
```
**Node.js, from source (no build step):**
```bash
npm ci
npm run dev
```
The Node.js options read credentials from the process environment, not from `.env`; for example
`node --env-file=.env dist/index.js` after `npm run build`, or export the variables in your shell.
The server listens on `http://0.0.0.0:7577/mcp` using the MCP Streamable HTTP transport. The
examples publish it on `127.0.0.1` only, because the server has no authentication of its own;
drop the `127.0.0.1:` prefix only if you put it behind something that does.
### 3. Connect a client
**Claude Code:**
```bash
claude mcp add --transport http iol-mcp http://localhost:7577/mcp
```
**Any other MCP client that supports Streamable HTTP** (check your client's documentation for the
exact config file and key names):
```json
{
"mcpServers": {
"iol-mcp": {
"type": "http",
"url": "http://localhost:7577/mcp"
}
}
}
```
## Configuration
| Variable | Required | Default | Description |
|------------------|----------|----------------------------------|-------------|
| `IOL_USERNAME` | Yes* | | IOL account username (email). |
| `IOL_PASSWORD` | Yes* | | IOL account password. |
| `IOL_BASE_URL` | No | `https://api.invertironline.com` | Override the API base URL (for a mock or sandbox). |
| `ENABLE_TRADING` | No | `false` | Set to exactly `true` to register the trading tools listed below. Any other value (including `TRUE` or `1`) keeps them off. |
| `PORT` | No | `7577` | HTTP port. |
\* The server logs in lazily on the first API call using these variables and renews the short-lived
bearer token automatically. If they are unset you can instead call the `authenticate` tool with
explicit credentials.
On startup the server logs one line stating whether trading is enabled and how many trading tools
were registered or skipped. Credentials are never logged; only `set`/`MISSING` is shown.
## Tools
34 tools in total: 26 read-only and 8 that require `ENABLE_TRADING=true`.
### Authentication
| Tool | Description |
|------|-------------|
| `authenticate` | Authenticate with InvertirOnline (defaults to the `IOL_USERNAME`/`IOL_PASSWORD` env vars). |
### Account (read-only)
| Tool | Description |
|------|-------------|
| `get_portfolio` | Investment portfolio for a country (`argentina` or `estados_Unidos`). |
| `get_account_statement` | Account statement showing available cash and positions. |
| `get_profile` | Authenticated client's profile data. |
| `get_operations` | List operations with optional filters. |
| `get_operation` | Details of a specific operation by number. |
| `get_notifications` | Pending notifications for the authenticated user. |
### Quotations (read-only)
| Tool | Description |
|------|-------------|
| `get_quotation` | Current price quotation for a security. |
| `get_quotation_detail` | Detailed quotation (order book, last trades) for a security. |
| `get_historical_series` | Historical price series for a security between two dates. |
| `get_all_quotations` | All current quotations for an instrument type and country. |
| `get_panel_quotations` | Quotations for a specific panel (e.g. a market index panel). |
### Securities (read-only)
| Tool | Description |
|------|-------------|
| `get_instruments` | Available instrument types for a country. |
| `get_panels` | Available panels for an instrument type and country. |
| `get_security` | General information about a listed security. |
| `get_security_options` | Options chain for a security. |
### Mutual funds, FCI (read-only)
| Tool | Description |
|------|-------------|
| `list_fci` | All available mutual funds. |
| `get_fci` | Details and current NAV for a specific fund. |
| `get_fci_types` | Available fund types. |
| `get_fci_administrators` | Fund management companies (administradoras). |
| `get_fci_by_administrator` | Funds offered by an administrator, optionally filtered by type. |
### MEP dollar rates (read-only)
| Tool | Description |
|------|-------------|
| `get_mep_rate` | Current MEP (dollar) reference rate. |
| `get_mep_rate_by_symbol` | MEP reference rate for a specific underlying bond symbol (e.g. `AL30`). |
### Simplified operations (read-only)
| Tool | Description |
|------|-------------|
| `get_simplified_estimated_amounts` | Estimated buy amounts for a simplified (one-click) operation. |
| `get_simplified_parameters` | Parameters for a simplified operation type. |
| `validate_simplified_operation` | Validate a simplified operation before submitting. |
### Trading (requires `ENABLE_TRADING=true`)
These tools are **not registered** unless `ENABLE_TRADING=true`.
| Tool | Description |
|------|-------------|
| `buy` | Place a buy order for a security on an Argentine or US market. |
| `sell` | Place a sell order for a security on an Argentine or US market. |
| `buy_foreign` | Buy a foreign (D) security (EspecieD, MEP/CCL dollar-linked). |
| `sell_foreign` | Sell a foreign (D) security (EspecieD, MEP/CCL dollar-linked). |
| `subscribe_fci` | Subscribe (invest) in a mutual fund. |
| `redeem_fci` | Redeem (withdraw) from a mutual fund. |
| `cancel_operation` | Cancel a pending operation by its number. |
| `simplified_buy` | Place a simplified (one-click) buy order. |
## Development
```bash
npm ci
npm run dev # run from source with tsx (no build)
npm run lint # eslint
npm run build # tsc -> dist/
npm test # vitest; all tests mock fetch and never touch the network
```
Hot reload in Docker (mounts `src/`, restarts on save):
```bash
docker compose -f docker-compose.dev.yml up --build
```
Build the production image locally:
```bash
docker build --target runtime -t iol-mcp:latest .
```
When `NODE_ENV` is not `production`, `GET /debug` returns server health, uptime, and the active
session count (credentials are reported only as `set`/`MISSING`). The production image sets
`NODE_ENV=production`, which disables it.
To add a tool, register it with `server.registerTool(...)` in `src/tools/` and make all HTTP calls
through `apiRequest()` in `src/client.ts`. A tool that moves money or changes broker state must go
in `src/tools/trading.ts` and be added to `TRADING_TOOL_NAMES` so the `ENABLE_TRADING` guard covers
it.
## License
[MIT](LICENSE) © 2026 ejgonzalez90
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo recent community issues