FastAPI-based Model Context Protocol (MCP) server that exposes Bitrix24 CRM data and actions to LLM agents. The server translates MCP resource and tool calls into Bitrix24 REST API requests.
- MCP resources for listing deals, leads, contacts, users, tasks, currencies, and Bitrix24 dictionaries (lead stages/sources, deal categories/stages, task statuses/priorities)
- MCP tools for retrieving CRM entities (deals, leads, contacts, users, tasks) and companies (list/detail via
getCompanies/getCompany) - Localized MCP prompts (Russian), including structuredContent and warnings for missing arguments
- Tool responses conform to CallToolResult (fields
content,structuredContent,isError) compatible with fastmcp - Uniform warnings and recommended date filters for all tools, allowing clients to automatically retry requests with adjustments
- Resource responses include
_metablocks with human-readable labels (responsible user, stage, source, priority, etc.) - Tool responses for
getLeadsnow reuse the cachedcrm/leadsdictionary so they ship the same_metadata (responsible, creator, modifier, status, source, currency), exposestructuredContent.aggregateswith counts, includestructuredContent.hints.copyableFilter(примеры недельного фильтра/iter) so агент может копировать фильтр для следующего запроса, а предупреждения поtoolWarnings.getLeadsбольше не приводят только к диапазону «сегодня» — теперь пример показывает последнюю неделю с>=DATE_CREATE/<=DATE_CREATE. - Date-range hints, warnings, and weekly samples respect a configurable timezone (
SERVER_TIMEZONE, defaultUTC), so the generatedYYYY-MM-DDTHH:MM:SS±HH:MMboundaries match your portal’s local day. - Configurable via environment variables (
.env) - HTTPX-based Bitrix24 client with retry/backoff
- Async FastAPI application ready for Docker or local execution
- Pytest suite with in-memory Bitrix24 client stubs
- Claude Desktop stdio proxy (
mcp_stdio_proxy.py) with configurable base URL/timeout via environment versions/releasesresource exposes structured release metadata (version, status, title, notes) derived fromCHANGELOG.mdso agents can fetch the latest release history through MCP.- Configure
GITHUB_RELEASES_REPO(and optionalGITHUB_TOKEN,GITHUB_TIMEOUT_SECONDS,GITHUB_CACHE_TTL_SECONDS) to keepversions/releasesin sync with GitHub Releases instead of the static changelog snapshot.
- All prompt texts, tool descriptions, and ready-made payloads are stored in
mcp_server/app/docs/prompts_ru.md. When the file is changed, the server automatically picks up new instructions without code modifications. - The
initializeresponse containsstructuredInstructionsandinstructionNoteswith examples: how to get fresh leads (order = {"DATE_MODIFY": "DESC"}) and how to set date ranges via>=DATE_CREATE,<=DATE_CREATE. - MCP tools return
structuredContentwith the full Bitrix24 response and warnings. If no date range is provided, any list tool (getDeals,getLeads,getContacts,getUsers,getTasks,getCompanies) adds a message, recommended filters, andsuggestedFix, allowing fastmcp/SGR to automatically retry the request. - The
bitrix24_leads_guideresource provides a cheat sheet with typical scenarios (fresh leads, today's selection, status filter) and rules for combining filters. - The
prompts_ru.mdstructure provides for localization: for a new locale, it is enough to add aprompts_<locale>.mdfile and update the settings.
- MCP tools (
/mcp/tool/call, JSON-RPCtools/call, WebSocket/SSE) return a dictionary in the format:
{
"content": [
{"type": "text", "text": "crm/leads: 42 records received. Full response in structuredContent.result."},
{"type": "text", "text": "Warning: Add range filters ..."} // optional
],
"structuredContent": {
"metadata": {"provider": "bitrix24", "tool": "getLeads", "resource": "crm/leads"},
"request": {"order": {"DATE_MODIFY": "DESC"}, "filter": {...}},
"result": {...}, // original Bitrix24 response
"warnings": [...] // optional
},
"isError": false
}
mcp_server/
app/
main.py # FastAPI application factory and lifespan management
settings.py # Pydantic settings loaded from environment
bitrix_client.py # Async HTTP client wrapper for Bitrix24 REST API
exceptions.py # Shared exception types for MCP responses
dependencies.py # FastAPI dependencies for resource/tool registries
mcp/
schemas.py # Pydantic models for MCP requests/responses
resources.py # Resource registry (crm/deals, crm/leads, ...)
tools.py # Tool registry (getDeals, getLeads, ...)
routes.py # MCP endpoints (`/mcp/index`, `/mcp/resource/query`, `/mcp/tool/call`)
tests/
test_resources.py # Resource query tests
test_tools.py # Tool call tests
conftest.py # Shared fixtures and settings overrides
mmp@m copypaste? Wait patch wants to change line 105 from ` ``` ` to ` ```text `. Need patch near that line. We'll produce patch.
- The `structuredContent` field stores the original REST payload, so clients can continue to use `metadata` and `result`.
- Warnings about missing dates and other critical arguments are added to `structuredContent.warnings`, and specific filters and sorts to apply are available in `structuredContent.suggestedFix.filters`.
- SSE/WebSocket transmissions use the same CallToolResult, which eliminates fastmcp validator errors.
- For list tools the server additionally exposes `structuredContent.pagination` (`limit`, `start`, `next`, `total`, `fetched`), so you can immediately report the total count or use `next` to page through the full selection.
- For dictionaries like `crm/lead_statuses` and `crm/deal_stages` we now include each stage’s `group`/`groupName` derived from its semantics (`process` → «В работе», `success` → «Заключена», `failure` → «Провалена»), so agents can filter or aggregate by status groups directly.
- `getLeads` now supports `statusSemantics` (or alias `groupSemantics`) — a list of semantic groups (`process`, `success`, `failure`). The server resolves them into the corresponding `STATUS_ID` values before handing the filter to Bitrix, so you can request “лиды в работе” without managing the ID list yourself.
- Added `callBitrixMethod` so you can proxy arbitrary REST calls (for example, `crm.activity.list` to fetch calls by `OWNER_TYPE_ID`/`TYPE_ID`). This keeps MCP flexible while reusing the same logging/warnings/pagination wrappers.
- Added `getLeadCalls`, which combines `crm.activity.list` + `crm.activity.get` + `voximplant.statistic.get` to produce a detailed call log for a lead (`date`, `CALL_ID`, `duration`, and recording info).
## Release History Resource
Use the MCP resource `versions/releases` (alias `releases`) to get structured release notes directly from `CHANGELOG.md`. It returns a list of entries with `version`, `status`, `title`, and `notes`, so agents can inspect what changed without leaving the MCP context:
```bash
curl -sS http://localhost:8000/mcp/resource/query -H "Content-Type: application/json" \
-d '{"resource": "versions/releases", "params": {}}' | jq .Set GITHUB_RELEASES_REPO=owner/repo to pull releases from GitHub instead of the built-in changelog. An optional GITHUB_TOKEN lets you read private repos or avoid rate limiting, GITHUB_TIMEOUT_SECONDS controls the fetch timeout, and GITHUB_CACHE_TTL_SECONDS determines how long results stay cached before another GitHub call. When GitHub is unreachable, the resource falls back to the static entries derived from CHANGELOG.md.
- Every entity returned via
crm/deals,crm/leads, andcrm/tasksis enriched with a_metasection that contains human-readable descriptors resolved through cached Bitrix24 dictionaries:
{
"ID": "123",
"ASSIGNED_BY_ID": "42",
"STATUS_ID": "NEW",
"_meta": {
"responsible": {
"id": "42",
"name": "Анна Иванова",
"email": "anna@example.com"
},
"status": {
"id": "NEW",
"name": "Новый"
},
"source": {
"id": "CALL",
"name": "Звонок"
}
}
}- Available enrichments today:
- Deals:
responsible,category,stage - Leads:
responsible,creator,modifier,status,source,currency - Tasks:
responsible,creator,status,priority
- Deals:
- Each
_meta.<key>entry exposes anid, aname, andraw(original Bitrix24 dictionary entry) so MCP clients can keep working with the underlying IDs when needed. - Cached dictionaries (
crm/currencies,crm/lead_statuses,crm/lead_sources,crm/deal_categories,crm/deal_stages,tasks/statuses,tasks/priorities) are also exposed as standalone MCP resources for direct lookups.
mcp_server/
app/
main.py # FastAPI application factory and lifespan management
settings.py # Pydantic settings loaded from environment
bitrix_client.py # Async HTTP client wrapper for Bitrix24 REST API
exceptions.py # Shared exception types for MCP responses
dependencies.py # FastAPI dependencies for resource/tool registries
mcp/
schemas.py # Pydantic models for MCP requests/responses
resources.py # Resource registry (crm/deals, crm/leads, ...)
tools.py # Tool registry (getDeals, getLeads, ...)
routes.py # MCP endpoints (`/mcp/index`, `/mcp/resource/query`, `/mcp/tool/call`)
tests/
test_resources.py # Resource query tests
test_tools.py # Tool call tests
conftest.py # Shared fixtures and settings overrides
Create .env based on .env.example:
cp .env.example .envUpdate the following values:
BITRIX_BASE_URL: your Bitrix24 REST endpoint (usually<portal>/rest)BITRIX_TOKEN: webhook key or OAuth access tokenBITRIX_INSTANCE_NAME(optional): identifier used in MCP metadataSERVER_*: customize local server host/port/log level if requiredSERVER_TIMEZONE(optional): IANA timezone (defaultUTC) used when building date-range warnings/hints so agents always see consistent local boundaries.
python -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'uvicorn mcp_server.app.main:app --reloadHealth check:
curl http://localhost:8000/healthzMCP discovery:
curl http://localhost:8000/mcp/indexpytestdocker build -t b24-mcp .
docker run --rm -p 8000:8000 --env-file .env b24-mcpNote: The provided
.envfile is mounted as environment variables inside the container. Ensure it contains valid Bitrix24 credentials before starting the container.
Use the included mcp_stdio_proxy.py script to bridge Claude Desktop (stdio-based MCP client) with the HTTP server:
-
Ensure the MCP server is running locally (defaults to
http://127.0.0.1:8000). -
Optional environment variables for the proxy:
MCP_PROXY_BASE_URL– override the target server URL (defaults tohttp://127.0.0.1:8000).MCP_PROXY_TIMEOUT– request timeout in seconds (defaults to30).
-
Update Claude Desktop settings (
~/Library/Application Support/Claude/Settings/settings.json):{ "mcpServers": { "b24-mcp": { "command": "/Users/gregkisel/Documents/GitHub/b24-mcp/.venv/bin/python", "args": [ "/Users/gregkisel/Documents/GitHub/b24-mcp/mcp_stdio_proxy.py" ], "cwd": "/Users/gregkisel/Documents/GitHub/b24-mcp", "env": { "MCP_PROXY_BASE_URL": "http://127.0.0.1:8000", "MCP_PROXY_TIMEOUT": "30" }, "autoStart": false } } }Adjust the paths if your checkout lives elsewhere or you use a different Python interpreter.
-
Restart Claude Desktop and select the
b24-mcpMCP server. The proxy skips JSON-RPC notifications (noid) to avoid spurious errors while forwarding responses untouched.
- The server authenticates requests to Bitrix24 via the
BITRIX_TOKENenvironment variable. - You can supply either:
- Inbound webhook key (recommended for service integrations) — create in Bitrix24 and ensure it has access to CRM entities (deals, leads, contacts) and tasks.
- OAuth access token — ensure the application scopes cover at least
crm,task, and user directory access.
- Token must remain secret. Store it only in
.env, CI secrets, or secure secret stores; never commit to source control. - When rotating tokens, simply update the value in
.envor provided secret source and restart the MCP server.
| Endpoint | Method | Description |
|---|---|---|
/mcp/index |
GET | Lists available resources and tools |
/mcp/resource/query |
POST | Queries a resource (crm/deals, crm/leads, crm/contacts, crm/users, crm/tasks) |
/mcp/tool/call |
POST | Executes a tool (getDeals, getLeads, getContacts, getUsers, getTasks, getCompanies, getCompany) |
Resource queries for crm/deals, crm/leads, crm/contacts, and crm/tasks default to returning at most five records when no filters are provided so that an empty request does not stream the entire CRM list.
- To inspect incoming MCP payloads and outgoing tool responses directly in the server logs, set
SERVER_LOG_LEVEL=debugbefore starting the app (FastAPI reads this from.envor the environment). WithDEBUGenabled you will see JSON-RPC requests,tool/resourceparameters, and pagination metadata in the logs, which helps when tuning filters for Open WebUI or other agents.
curl -X POST http://localhost:8000/mcp/resource/query \
-H "Content-Type: application/json" \
-d '{"resource": "crm/deals", "params": {"select": ["ID", "TITLE"], "filter": {">OPPORTUNITY": 10000}}}'curl -X POST http://localhost:8000/mcp/tool/call \
-H "Content-Type: application/json" \
-d '{"tool": "getDeals", "params": {"select": ["ID", "TITLE"], "filter": {">OPPORTUNITY": 10000}}}'- Use Docker or a process manager (systemd, supervisord) to host the FastAPI app.
- Ensure
.envis stored securely and not committed to source control. - For production, configure HTTPS termination and add authentication in front of the MCP server if required.
- During local development the MCP server accepts WebSocket connections at
ws://<host>:<port>/mcp. - By default the application is configured to accept origins from
http://localhostandhttp://127.0.0.1. - If you see
403 Forbiddenwhen attempting to open a WebSocket, try supplying an explicitOriginheader with your client (for exampleOrigin: http://localhost) or update theallow_originssetting inmcp_server/app/main.py.
Testing examples:
# quick HTTP index check
curl -sS http://127.0.0.1:8000/mcp/index | jq .
# JSON-RPC handshake over HTTP GET
curl -sS http://127.0.0.1:8000/mcp | jq .
# websocat with explicit Origin header (recommended when debugging CORS)
websocat -H 'Origin: http://localhost' ws://127.0.0.1:8000/mcp
# FastMCP CLI (if installed) to test MCP handshake
python -m fastmcp.cli connect ws://127.0.0.1:8000/mcpNote: For production deployments, restrict allow_origins to trusted domains and enable TLS (wss://).
This MCP server exposes a simple Server-Sent Events endpoint at /mcp/sse.
Use SSE when you want a streaming transport from server → client. The server
will send an initial handshake payload on connect and will broadcast tool and
resource results to connected SSE clients.
How it works:
- Connect a client to
GET /mcp/sseto receive events (Content-Typetext/event-stream). - Send JSON-RPC requests via
POST /mcp(the server will reply to the POST and also broadcast results to SSE subscribers). - For local testing use the following commands:
# Tail the HTTP index
curl -sS http://127.0.0.1:8000/mcp/index | jq .
# Connect to SSE (example using curl) — note: curl will not nicely render continuous SSE output
# but can be used to test the handshake
curl -v http://127.0.0.1:8000/mcp/sse
# Send initialize over HTTP JSON-RPC (you should also see this payload on the SSE connection)
curl -sS -X POST http://127.0.0.1:8000/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | jq .
# Health endpoint
curl -sS http://127.0.0.1:8000/mcp/health | jq . For production, replace curl with a proper SSE client (browser EventSource or an SSE-capable client library) and secure the connection with TLS (https/wss).
The server can be used by any MCP-capable client. Below are quick-start examples for the most common desktop clients. Adjust paths for your operating system and restart the client after editing its config.
- Ensure the MCP server is running locally (
uvicorn mcp_server.app.main:app --reload). - Edit
~/Library/Application Support/Claude/claude_desktop_config.json(macOS) or%AppData%\Claude\claude_desktop_config.json(Windows). - Add an entry under
mcpServers:
Restart Claude Desktop and the Bitrix24 MCP server will appear in the MCP servers menu.
- Run the MCP server (
uvicorn mcp_server.app.main:app --reload). - Update
~/.codex/config.tomland add an entry beneath[mcp_servers]:
[mcp_servers.bitrix24]
url = "http://127.0.0.1:8000/mcp"- Restart the Codex CLI; run
codex mcp listto verify the connection.
- Start the MCP server locally.
- Edit
~/.cursor/mcp.json(Cursor creates the file automatically after the first launch) and add a new server definition:
{
"mcpServers": {
"bitrix24": {
"url": "http://127.0.0.1:8000/mcp",
"timeout": 30000,
"name": "Bitrix24 MCP"
}
}
}After saving the file, reopen Cursor. The Bitrix24 MCP server will be available in the MCP panel and can be enabled per project.
MIT License. See LICENSE for details.
{ "mcpServers": { "b24-mcp": { "command": "/Users/gregkisel/Documents/GitHub/b24-mcp/.venv/bin/python", "args": [ "/Users/gregkisel/Documents/GitHub/b24-mcp/mcp_stdio_proxy.py" ], "cwd": "/Users/gregkisel/Documents/GitHub/b24-mcp", "env": { "MCP_PROXY_BASE_URL": "http://127.0.0.1:8000", "MCP_PROXY_TIMEOUT": "30" }, "autoStart": false } } }