Bloomberg MCP Server
Bloomberg MCP Server
An MCP server that exposes Bloomberg data over streamable HTTP at /mcp, ready to sit
behind the WSO2 AI Gateway (or any other MCP-aware proxy).
It wraps Bloomberg's own SDK — BLPAPI, the Bloomberg Open API — so the same entitlements and data you get from the Terminal, SAPI or B-PIPE are what the tools return. No scraping, no unofficial endpoints.
MCP client ──▶ WSO2 AI Gateway ──▶ http://bloomberg-mcp:8000/mcp ──▶ BLPAPI ──▶ BloombergTools
Tool | BLPAPI request | What it does |
| – | Which backend is live (real vs mock), connection details |
|
| Current/static fields — the Excel |
|
| End-of-period time series — |
|
| Intraday OHLCV bars (~140 days of history) |
|
| Tick-by-tick trades/quotes |
|
| Name / ISIN → Bloomberg ticker |
|
| Keyword → field mnemonic |
|
| Run a saved EQS screen |
Plus a bloomberg://cheatsheet resource listing common yellow keys and field mnemonics.
Streaming subscriptions (//blp/mktdata) are intentionally out of scope — MCP tool calls are
request/response, and refdata snapshots cover the same ground.
Quick start
uv venv --python 3.13
uv pip install -e .
cp .env.example .env
uv run python -m bloomberg_mcp # http://0.0.0.0:8000/mcp
uv run python scripts/smoke_client.py # exercise every tool
curl -s localhost:8000/healthz | jqWith no Bloomberg reachable, the server logs a warning and serves deterministic mock data
(every payload carries "mock": true), so the gateway wiring can be built and tested first.
Connecting to real Bloomberg
Install Bloomberg's SDK — it lives on Bloomberg's own package index, not PyPI:
uv pip install blpapi # the index is preconfigured in pyproject.toml
# or, with plain pip:
pip install --index-url https://blpapi.bloomberg.com/repository/releases/python/simple/ blpapiThen pick a transport in .env:
Desktop API (DAPI) — free with a Terminal licence, one user, Terminal must be running and logged in on the same machine:
BLOOMBERG_MODE=blpapi
BLOOMBERG_HOST=localhost
BLOOMBERG_PORT=8194Server API (SAPI) / B-PIPE — the licensed server-side feeds; this is what you want if the MCP server runs in a container or in the cloud:
BLOOMBERG_MODE=blpapi
BLOOMBERG_HOST=bpipe-host.internal
BLOOMBERG_PORT=8194
BLOOMBERG_AUTH_OPTIONS=AuthenticationMode=APPLICATION_ONLY;ApplicationAuthenticationType=APPNAME_AND_KEY;ApplicationName=my-app
BLOOMBERG_TLS_CLIENT_CERT=/certs/client.pk12
BLOOMBERG_TLS_CLIENT_CERT_PASSWORD=...
BLOOMBERG_TLS_TRUST_MATERIAL=/certs/rootCertificate.pk7BLOOMBERG_MODE=blpapi fails fast if Bloomberg is unreachable — use it in production so a
misconfiguration can't silently serve mock data. auto (the default) falls back to mock.
Note that Bloomberg's licence terms govern redistribution of this data; putting it behind a gateway for multiple consumers is exactly the case B-PIPE/SAPI entitlements exist for. Check your agreement before opening the gateway route up beyond entitled users.
Behind the WSO2 AI Gateway
Point the gateway's MCP backend at http://<host>:8000/mcp and let it own client-facing
authentication, rate limiting and observability. The defaults are already gateway-friendly:
MCP_STATELESS=true— no server-side session state, so any replica can serve any request and you need no session affinity. A single POST is a complete call; noinitializehandshake orMcp-Session-Idto carry:curl -X POST http://localhost:8000/mcp \ -H 'Content-Type: application/json' \ -H 'Accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{ "name":"get_reference_data", "arguments":{"securities":["IBM US Equity"],"fields":["PX_LAST"]}}}'MCP_JSON_RESPONSE=true— plainapplication/jsonresponses instead of SSE streams, which proxies handle far more predictably.MCP_API_KEY— optional shared secret between the gateway and this server, accepted asx-api-key: <key>orAuthorization: Bearer <key>; anything else gets 401./healthzstays open for probes.DNS-rebinding protection is explicitly disabled unless you set
MCP_ALLOWED_HOSTS, because behind a proxy theHostheader is the gateway's, not yours. Leaving it to the SDK default is not the same thing:streamable_http_appthen auto-enables a localhost-only allowlist and answers421 Invalid Host headerto every proxied request. SetMCP_ALLOWED_HOSTS=bloomberg-mcp:8000,localhost:*to turn it back on.
Container
docker build -t bloomberg-mcp .
docker run -p 8000:8000 --env-file .env bloomberg-mcpDeploying on Choreo
The repo carries everything Choreo needs — .choreo/component.yaml, openapi.yaml and the
Dockerfile — following the docker-rest-user-service
sample layout.
Push this directory to a Git repository Choreo can read.
Create a Service component, buildpack Docker, Docker context
/, Dockerfile/Dockerfile.Choreo reads
.choreo/component.yaml: a public REST endpoint on port 8000 withbasePath: /, its resources generated fromopenapi.yaml.Build, then set the environment variables on the Deploy page (all optional — a blank field falls back to the image default) and deploy.
The invoke URL ends in /mcp, which is what you hand to MCP clients:
https://<env>-<org>.<region>.choreoapis.dev/<project>/<component>/<version>/mcpSome things worth knowing before you deploy:
Only declared paths are routed. Choreo generates the managed API's resources from
openapi.yaml, soPOST /mcpandGET /healthzare declared there. Adding a route to the server without adding it to the spec gets you a 404 from the gateway.Stateless is what makes this work.
MCP_STATELESS=trueandMCP_JSON_RESPONSE=trueare baked into the image, so every call is one self-contained POST returning plain JSON — no session affinity across replicas, no SSE for the gateway to hold open.The managed API has its own auth. Choreo protects the endpoint with OAuth2 by default; your MCP client needs a token or a Choreo API key.
MCP_API_KEYis a second, optional secret checked by this server — useful as defence in depth, not a replacement.blpapi installs on Choreo but not on an Apple Silicon Mac. Bloomberg publishes no linux/arm64 wheel, so a local
docker buildfalls back to mock mode; Choreo builds amd64, where the real SDK installs.The Desktop API is unreachable from Choreo.
localhost:8194inside a container is the container. Real data means a SAPI or B-PIPE endpoint Choreo can route to; without one the server serves mock data and says so inbloomberg_status.The container runs as UID 10014, per Choreo's non-root requirement.
Configuration
Every setting is an environment variable; see .env.example for the full annotated list.
Variable | Default | Purpose |
|
|
|
|
| BLPAPI endpoint |
| – | B-PIPE/SAPI auth string |
| – | B-PIPE certificates |
|
| Per-request timeout |
|
| Request guardrails |
|
| Listen address |
|
| MCP endpoint path |
|
| Proxy-friendly transport |
| – | Enable DNS-rebinding protection |
| – / | Backend auth |
Local client (stdio)
For testing in Claude Code / Claude Desktop without the HTTP hop:
uv run python -m bloomberg_mcp --transport stdioLayout
src/bloomberg_mcp/
config.py settings from environment
backend.py backend protocol + BloombergError
blpapi_backend.py real BLPAPI session, request plumbing, response parsing
mock_backend.py deterministic synthetic data
server.py FastMCP tools, /healthz, API-key middleware, ASGI app
__main__.py CLI entry point
scripts/smoke_client.py exercises every tool over HTTP
.choreo/component.yaml Choreo endpoint + config-form definition
openapi.yaml API contract Choreo generates its routes from
DockerfileBuilt on mcp 2.x (MCPServer, formerly FastMCP).
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/madushankaf/mcp-bloomberg-mock'
If you have feedback or need assistance with the MCP directory API, please join our Discord server