IBKR TWS MCP Server
Enables AI agents to interact with Interactive Brokers through 48 tools for market data, orders, account management, and more, via the MCP protocol.
README
IBKR TWS MCP Server
基于 ib_async + fastmcp 的可扩展 Interactive Brokers MCP Server。
48 个工具,8 个插件分类,与现有 8 个 IB skills 平滑融合。
目录
架构概览
┌─────────────────────────────────────────────┐
│ 用户 / AI Agent │
└──────────────┬──────────────────────────────┘
│ MCP 协议 (stdio / HTTP)
┌──────────▼──────────┐
│ MCP Server │ ← 48 个工具,8 个插件分类
│ ┌────────────────┐ │
│ │ 插件注册中心 │ │ ← 新增工具只需 1 个装饰器
│ └────────────────┘ │
│ ┌────────────────┐ │
│ │ 中间件层 │ │ ← 只读模式 / 风控 / 限流
│ └────────────────┘ │
│ ┌────────────────┐ │
│ │ 连接管理器 │ │ ← 单例 + 自动重连
│ └────────────────┘ │
└──────────┬──────────┘
│ Socket (TCP)
┌──────────▼──────────┐
│ IB Gateway / TWS │ ← 必须运行
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ IBKR 服务器 │
└─────────────────────┘
前置条件
必须
| 项目 | 版本 | 说明 |
|---|---|---|
| Python | 3.12+ | 需要较新版本以支持类型提示语法 |
| uv | latest | 包管理工具,替代 pip/poetry |
| IB 账户 | 任意类型 | 模拟盘或实盘均可 |
| IB Gateway 或 TWS | 稳定版或最新版 | 必须运行并接受 API 连接 |
安装 IB Gateway
配置 IB Gateway API
在 IB Gateway / TWS 中:
- 进入
Configure → Settings → API → Settings - 勾选 Enable ActiveX and Socket Clients
- 勾选 Allow connections from localhost only
- 勾选 Download open orders on connection
- 记下端口号:
| 平台 | 模拟盘 | 实盘 |
|---|---|---|
| IB Gateway | 4002 | 4001 |
| TWS | 7497 | 7496 |
- 建议:
Configure → Settings → Memory Allocation设为 4096 MB 以上
安装
# 克隆或进入项目目录
cd /Users/x/ibkr-tws-mcp
# 安装依赖
uv sync
配置
环境变量
cp .env.example .env
编辑 .env:
# IB 连接
IB_HOST=127.0.0.1
IB_PORT=7497 # 根据上表修改
IB_CLIENT_ID=1
IB_ACCOUNT_ID= # 留空自动检测
IB_READ_ONLY=true # 生产环境建议 true
IB_REALTIME_DATA=false # 无实时数据订阅时设 false(使用延迟免费数据)
# 风控
RISK_MAX_ORDER_QTY=1000
RISK_MAX_ORDER_NOTIONAL=100000
RISK_DAILY_LOSS_LIMIT=10000
RISK_SYMBOL_DENYLIST= # 逗号分隔,如 "GME,AMC"
RISK_SYMBOL_ALLOWLIST= # 留空=不限制
# MCP 服务
MCP_TRANSPORT=stdio # stdio 或 http
MCP_HOST=0.0.0.0
MCP_PORT=8765
# 日志
LOG_LEVEL=info # debug / info / warn / error
插件配置
编辑 config/plugins.yaml:
plugins:
enabled:
- market_data # 行情 (10 工具)
- contracts # 合约 (7 工具)
- account # 账户 (8 工具)
- orders # 订单 (9 工具)
- risk # 风控 (5 工具)
- scanner # 扫描器 (3 工具)
- news # 新闻 (3 工具)
optional:
strategies: # 策略 (3 工具,融合现有 skills)
enabled: false # 按需开启
requires: [pandas, numpy]
disabled: [] # 填入要禁用的插件名
启动
stdio 模式(推荐,用于 AI Agent 接入)
uv run ibkr-mcp
HTTP 模式(用于调试或远程接入)
uv run ibkr-mcp --transport http --host 0.0.0.0 --port 8765
启动后访问 http://localhost:8765 查看工具列表。
接入 AI Agent
OpenCode / Claude Code
在项目或全局配置中添加 MCP Server:
{
"mcpServers": {
"ibkr-tws": {
"command": "uv",
"args": ["run", "--directory", "/Users/x/ibkr-tws-mcp", "ibkr-mcp"],
"env": {
"IB_HOST": "127.0.0.1",
"IB_PORT": "7497",
"IB_READ_ONLY": "true"
}
}
}
}
Claude Desktop
编辑 ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"ibkr-tws": {
"command": "uv",
"args": ["run", "--directory", "/Users/x/ibkr-tws-mcp", "ibkr-mcp"],
"env": {
"IB_PORT": "7497",
"IB_READ_ONLY": "true"
}
}
}
}
Cursor
编辑 .cursor/mcp.json:
{
"mcpServers": {
"ibkr-tws": {
"command": "uv",
"args": ["run", "--directory", "/Users/x/ibkr-tws-mcp", "ibkr-mcp"]
}
}
}
工具参考
所有工具返回统一格式:
{
"success": true,
"data": { ... },
"error": null,
"meta": { "conId": 265598 }
}
📊 Market Data (10 工具)
get_quote
获取实时报价快照。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
exchange |
string | SMART |
交易所 |
currency |
string | USD |
货币 |
返回:{ symbol, bid, ask, last, close, high, low, volume, marketCap }
get_quotes_bulk
批量获取多个标的报价。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbols |
list[str] | 必填 | 股票代码列表 |
exchange |
string | SMART |
交易所 |
currency |
string | USD |
货币 |
返回:报价列表
get_history
获取历史 K 线数据。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
duration |
string | 1 D |
时间跨度,如 1 D, 30 D, 1 Y |
bar_size |
string | 1 min |
K 线周期,如 1 min, 5 mins, 1 hour, 1 day |
what_to_show |
string | TRADES |
数据类型:TRADES / MIDPOINT / BID / ASK |
exchange |
string | SMART |
交易所 |
currency |
string | USD |
货币 |
use_rth |
bool | true |
仅交易时段数据 |
返回:[{ date, open, high, low, close, volume, average, barCount }]
get_ticks
获取历史逐笔成交数据。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
start_datetime |
string | "" |
起始时间,格式 YYYYMMDD-HH:mm:ss |
number_of_ticks |
int | 100 |
返回笔数 |
返回:[{ time, price, size, tickAttribLast }]
get_depth
获取 Level 2 盘口数据。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
num_rows |
int | 5 |
盘口深度 |
返回:{ bids: [{ price, size, side, position }], asks: [...] }
subscribe_stream
订阅实时行情流。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
返回:{ subscription_id, symbol, status }
unsubscribe_stream
取消实时行情订阅。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
subscription_id |
string | 必填 | 订阅 ID |
list_subscriptions
查看当前所有活跃订阅。
subscribe_pnl
订阅实时盈亏推送。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
account |
string | "" |
账户号 |
返回:{ subscription_id, account, dailyPnL, unrealizedPnL, realizedPnL, status }
subscribe_account
订阅账户更新推送(余额、持仓变化等)。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
account |
string | "" |
账户号 |
📝 Contracts (7 工具)
search_contract
搜索并解析合约信息。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
sec_type |
string | STK |
类型:STK / OPT / FUT / CASH / IND |
exchange |
string | SMART |
交易所 |
currency |
string | USD |
货币 |
返回:{ conId, symbol, secType, exchange, currency, primaryExchange }
contract_details
通过 conId 获取合约详情。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
conid |
int | 必填 | 合约 ID |
get_option_chain
获取期权链(到期日、行权价)。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 标的代码 |
exchange |
string | SMART |
交易所 |
currency |
string | USD |
货币 |
返回:[{ exchange, underlyingConId, tradingClass, multiplier, expirations, strikes }]
get_futures_chain
获取期货合约链。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 品种代码 |
exchange |
string | GLOBEX |
交易所 |
symbol_to_conid
股票代码转 conId。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
sec_type |
string | STK |
类型 |
返回:{ conId, symbol, secType }
get_trading_hours
获取标的交易时段信息。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
exchange |
string | SMART |
交易所 |
currency |
string | USD |
货币 |
返回:{ conId, symbol, timeZone, tradingHours, liquidHours, marketName }
get_option_expirations
获取标的可用期权到期日列表。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 标的代码 |
exchange |
string | SMART |
交易所 |
currency |
string | USD |
货币 |
返回:{ symbol, conId, expirations: [...], count }
👤 Account (8 工具)
get_account_summary
获取账户摘要(净值、购买力等)。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
account |
string | "" |
账户号(留空自动检测) |
tags |
string | "" |
指定标签(留空返回全部) |
返回:{ NetLiquidation: "...", TotalCashValue: "...", ... }
get_positions
获取持仓列表。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
account |
string | "" |
账户号 |
返回:[{ symbol, secType, position, avgCost, marketValue, unrealizedPNL, realizedPNL }]
get_portfolio
获取投资组合(含 P&L)。
参数同 get_positions。
get_buying_power
获取购买力详情。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
account |
string | "" |
账户号 |
返回:{ BuyingPower: "...", CashBalance: "...", NetLiquidation: "..." }
get_pnl
获取实时盈亏。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
account |
string | "" |
账户号 |
返回:{ dailyPnL, unrealizedPnL, realizedPnL, value }
get_cash_balances
获取多币种现金余额。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
account |
string | "" |
账户号 |
get_watchlist
获取自选股实时行情。不传 symbols 时默认返回当前持仓。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbols |
list[str] | None |
股票代码列表 |
exchange |
string | SMART |
交易所 |
currency |
string | USD |
货币 |
返回:[{ symbol, conId, last, bid, ask, volume, high, low, close }]
calculate_rebalance
计算调仓建议。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
target_allocations |
dict | 必填 | 目标配置比例,如 {"AAPL": 0.3, "NVDA": 0.2} |
account |
string | "" |
账户号 |
返回:{ netLiquidation, currentAllocations, targetAllocations, rebalanceActions }
💰 Orders (9 工具)
⚠️ 交易类工具受
IB_READ_ONLY环境变量控制,默认只读模式下会被阻止。
place_order
下单。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
action |
string | 必填 | BUY / SELL |
quantity |
int | 必填 | 数量 |
order_type |
string | MKT |
MKT / LMT |
price |
float | 0.0 |
限价(LMT 必填) |
exchange |
string | SMART |
交易所 |
currency |
string | USD |
货币 |
返回:{ orderId, status, filledQty, avgFillPrice }
cancel_order
撤单。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
order_id |
int | 必填 | 订单 ID |
cancel_all
撤销所有未成交订单。
get_open_orders
获取未成交订单列表。
返回:[{ orderId, symbol, action, type, quantity, price, status, filled, remaining, avgFillPrice }]
get_executions
获取已成交记录。
返回:[{ execId, symbol, side, shares, price, time, cumQty }]
place_bracket
下括号单(入场 + 止损 + 止盈)。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
action |
string | 必填 | BUY / SELL |
quantity |
int | 必填 | 数量 |
entry_price |
float | 必填 | 入场价 |
stop_loss |
float | 必填 | 止损价 |
take_profit |
float | 必填 | 止盈价 |
返回:3 个订单 ID(entry / stop_loss / take_profit)
modify_order
修改未成交订单。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
order_id |
int | 必填 | 订单 ID |
quantity |
int | 0 |
新数量(0=不变) |
price |
float | 0.0 |
新价格(0=不变) |
stop_price |
float | 0.0 |
新止损价(0=不变) |
place_conditional
条件单(价格触发)。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
action |
string | 必填 | BUY / SELL |
quantity |
int | 必填 | 数量 |
order_type |
string | LMT |
MKT / LMT |
price |
float | 0.0 |
限价 |
trigger_price |
float | 0.0 |
触发价格 |
place_algo_order
算法订单(VWAP / TWAP 等)。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
action |
string | 必填 | BUY / SELL |
quantity |
int | 必填 | 数量 |
algo_strategy |
string | Vwap |
Vwap / Twap / ArrivalPx / DarkIce |
algo_params |
dict | None |
算法参数,如 {"maxPctVol": "0.1"} |
🛡️ Risk (5 工具)
get_delta_exposure
获取按标的分类的 Delta 敞口。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
account |
string | "" |
账户号 |
返回:{ by_symbol: { AAPL: 100, ... }, total_delta: 150 }
get_greeks
获取期权希腊值。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 标的代码 |
expiry |
string | 必填 | 到期日,格式 YYYYMMDD |
strike |
float | 必填 | 行权价 |
right |
string | 必填 | C / P |
exchange |
string | SMART |
交易所 |
currency |
string | USD |
货币 |
返回:{ delta, gamma, theta, vega, rho, impliedVol, optPrice, pvDividend }
get_margin
获取保证金使用情况。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
account |
string | "" |
账户号 |
simulate_trade
模拟交易,预估保证金/购买力影响。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
action |
string | 必填 | BUY / SELL |
quantity |
int | 必填 | 数量 |
price |
float | 0.0 |
价格(留空取当前价) |
返回:{ estimatedPrice, estimatedNotional, marginImpactPct, netLiquidation, riskFlags }
get_corporate_actions
获取分红/拆股历史。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
返回:[{ payDate, dividend, annualDividend, yield }]
🔍 Scanner (3 工具)
run_scanner
运行市场扫描。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
scan_type |
string | TOP_PERC_GAIN |
扫描类型 |
location |
string | STK.US.MAJOR |
扫描范围 |
instrument |
string | STK |
品种类型 |
max_results |
int | 50 |
最大结果数 |
可用 scanType:TOP_PERC_GAIN, TOP_PERC_LOSE, MOST_ACTIVE, TOP_VOLUME, TOP_PRICE_RANGE, HOT_BY_PRICE, HOT_BY_VOLUME
scanner_presets
获取可用扫描预设列表。
scan_options_volume
扫描期权异动(高成交量)。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
min_volume |
int | 100 |
最小成交量 |
min_open_interest |
int | 50 |
最小持仓量 |
max_results |
int | 50 |
最大结果数 |
📰 News (3 工具)
get_news
获取标的相关新闻。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
exchange |
string | SMART |
交易所 |
currency |
string | USD |
货币 |
limit |
int | 10 |
返回条数 |
get_earnings_calendar
获取财报日历。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbols |
list[str] | None |
股票代码列表(默认蓝筹股) |
days_ahead |
int | 30 |
未来天数 |
get_dividend_calendar
获取分红日历。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbols |
list[str] | None |
股票代码列表(默认高息股) |
🧠 Strategies (3 工具)
融合现有 IB skills 的策略分析工具。需在
config/plugins.yaml中开启strategies插件。
get_short_roll_candidates
寻找滚动空头/备兑开仓机会。
分析当前持仓中的空头股票,返回可滚动或备兑的候选列表。
analyze_collar
Collar 保护策略分析。
| 参数 | 类型 | 默认 | 说明 |
|---|---|---|---|
symbol |
string | 必填 | 股票代码 |
quantity |
int | 必填 | 持仓数量 |
put_strike_offset |
float | 0.05 |
Put 行权价偏移(下行保护比例) |
call_strike_offset |
float | 0.10 |
Call 行权价偏移(上行封顶比例) |
expiry |
string | "" |
到期日 |
返回:{ currentPrice, putStrike, callStrike, maxLoss, maxProfit, putProtection, callCap }
get_portfolio_actions
持仓行动建议(财报风险、盈亏review)。
分析持仓盈亏百分比,对亏损超过 10% 或盈利超过 30% 的标的给出 review 建议。
插件扩展
新增工具(3 步)
Step 1: 在 src/ibkr_mcp/plugins/ 下新建或编辑文件
Step 2: 使用装饰器注册
# src/ibkr_mcp/plugins/news.py
from ibkr_mcp.core.registry import ToolRegistry
from ibkr_mcp.core.connection import IBConnection
from ibkr_mcp.core.response import MCPResponse
@ToolRegistry.register("news")
async def get_news(conid: int, limit: int = 10) -> dict:
"""获取标的新闻"""
ib = await IBConnection.get()
# ... 实现逻辑
return MCPResponse.ok(data=news)
Step 3: 在 config/plugins.yaml 中启用(如果是新分类)
plugins:
enabled:
- news # 新增
重启即可。零核心代码修改。
与现有 Skills 融合
融合策略
| 现有 Skill | 融合方式 | 状态 |
|---|---|---|
ib-account |
→ MCP get_account_summary |
可替代 |
ib-portfolio |
→ MCP get_positions |
可替代 |
ib-option-chain |
→ MCP get_option_chain |
可替代 |
ib-find-short-roll |
保留 skill,数据源改 MCP | 策略逻辑保留 |
ib-collar |
保留 skill,数据源改 MCP | 策略逻辑保留 |
ib-portfolio-action-report |
→ MCP get_portfolio_actions |
可替代 |
ib-report-delta-exposure |
→ MCP get_delta_exposure |
可替代 |
ib-create-consolidated-report |
保留(不依赖 IB 连接) | 不受影响 |
迁移建议
- 数据类 skills(
ib-account,ib-portfolio,ib-option-chain)→ 直接用 MCP 工具替代 - 策略类 skills(
ib-find-short-roll,ib-collar)→ 保留策略逻辑,底层数据改为调用 MCP - 分析类 skills(
ib-report-delta-exposure)→ 已迁入 MCPget_delta_exposure
常见问题
连接失败
Q: Connection refused
确保 IB Gateway / TWS 正在运行,且 API 端口匹配:
# TWS 模拟盘
IB_PORT=7497
# IB Gateway 模拟盘
IB_PORT=4002
Q: Client ID conflict
每个连接需要唯一的 Client ID。修改 .env 中的 IB_CLIENT_ID。
市场数据
Q: 返回延迟数据而非实时数据
设置 IB_REALTIME_DATA=false(默认),系统自动使用延迟免费数据(type 3)。
如需实时数据,需订阅 IB 市场数据包并设置 IB_REALTIME_DATA=true。
Q: 某些标的数据为空
确保合约代码正确。先用 search_contract 或 symbol_to_conid 验证。
交易
Q: 下单被拒绝
检查 IB_READ_ONLY=true。生产环境默认只读,如需交易设为 false。
Q: 订单一直未成交
检查价格是否合理。限价单价格偏离市场价太远不会成交。
性能
Q: Gateway 崩溃
增加 Java 内存:Configure → Settings → Memory Allocation → 4096 MB。
Q: 请求超时
增加 API timeout:在 IB Gateway 设置中调大超时时间。
项目结构
ibkr-tws-mcp/
├── pyproject.toml # 项目配置
├── .env.example # 环境变量模板
├── config/plugins.yaml # 插件配置
├── README.md # 本文档
├── src/ibkr_mcp/
│ ├── config.py # 配置管理
│ ├── main.py # MCP Server 入口
│ ├── core/
│ │ ├── connection.py # 连接管理(单例 + 自动重连)
│ │ ├── registry.py # 插件注册中心
│ │ ├── middleware.py # 中间件(只读/风控/限流)
│ │ └── response.py # 统一响应信封
│ ├── plugins/
│ │ ├── market_data.py # 行情 (10 工具)
│ │ ├── contracts.py # 合约 (7 工具)
│ │ ├── account.py # 账户 (8 工具)
│ │ ├── orders.py # 订单 (9 工具)
│ │ ├── risk.py # 风控 (5 工具)
│ │ ├── scanner.py # 扫描器 (3 工具)
│ │ ├── strategies.py # 策略 (3 工具)
│ │ └── news.py # 新闻 (3 工具)
│ └── shared/
│ ├── formatters.py # 数据格式化
│ └── validators.py # 参数验证
└── tests/
许可证
MIT
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.