mcp-bitrix24 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
mcp_bitrix24/client.py ADDED
@@ -0,0 +1,130 @@
1
+ import httpx
2
+ import os
3
+ from datetime import date, timedelta
4
+ from typing import Any
5
+
6
+
7
+ class BitrixClient:
8
+ def __init__(self, webhook_url: str | None = None):
9
+ self.webhook_url = (webhook_url or os.getenv("BITRIX24_WEBHOOK_URL", "")).rstrip("/")
10
+ if not self.webhook_url:
11
+ raise ValueError("BITRIX24_WEBHOOK_URL não configurado")
12
+
13
+ def _call(self, method: str, params: dict[str, Any] | None = None) -> Any:
14
+ url = f"{self.webhook_url}/{method}"
15
+ response = httpx.post(url, json=params or {}, timeout=30)
16
+ response.raise_for_status()
17
+ data = response.json()
18
+ if "error" in data:
19
+ raise RuntimeError(f"Bitrix24 error: {data.get('error_description', data['error'])}")
20
+ return data.get("result")
21
+
22
+ def list_deals(
23
+ self,
24
+ filter: dict | None = None,
25
+ select: list[str] | None = None,
26
+ order: dict | None = None,
27
+ start: int = 0,
28
+ ) -> list[dict]:
29
+ params: dict[str, Any] = {"start": start}
30
+ if filter:
31
+ params["filter"] = filter
32
+ if select:
33
+ params["select"] = select
34
+ if order:
35
+ params["order"] = order
36
+ result = self._call("crm.deal.list", params)
37
+ return result if isinstance(result, list) else []
38
+
39
+ def get_deal(self, deal_id: int) -> dict:
40
+ return self._call("crm.deal.get", {"id": deal_id})
41
+
42
+ def create_deal(self, fields: dict) -> int:
43
+ return self._call("crm.deal.add", {"fields": fields})
44
+
45
+ def update_deal(self, deal_id: int, fields: dict) -> bool:
46
+ return self._call("crm.deal.update", {"id": deal_id, "fields": fields})
47
+
48
+ def get_stages(self, pipeline_id: int | None = None) -> list[dict]:
49
+ params: dict[str, Any] = {}
50
+ if pipeline_id is not None:
51
+ params["filter"] = {"CATEGORY_ID": pipeline_id}
52
+ return self._call("crm.dealcategory.stage.list", params) or []
53
+
54
+ def add_comment(self, deal_id: int, comment: str) -> int:
55
+ fields = {
56
+ "OWNER_TYPE_ID": 2,
57
+ "OWNER_ID": deal_id,
58
+ "TYPE_ID": 12,
59
+ "SUBJECT": "Nota",
60
+ "DESCRIPTION": comment,
61
+ "DESCRIPTION_TYPE": 1,
62
+ "COMPLETED": "Y",
63
+ "DIRECTION": 0,
64
+ }
65
+ return self._call("crm.activity.add", {"fields": fields})
66
+
67
+ def add_task(self, deal_id: int, subject: str, description: str = "", deadline: str = "") -> int:
68
+ fields: dict[str, Any] = {
69
+ "OWNER_TYPE_ID": 2,
70
+ "OWNER_ID": deal_id,
71
+ "TYPE_ID": 6,
72
+ "SUBJECT": subject,
73
+ "DESCRIPTION": description,
74
+ "COMPLETED": "N",
75
+ "DIRECTION": 0,
76
+ }
77
+ if deadline:
78
+ fields["DEADLINE"] = deadline
79
+ return self._call("crm.activity.add", {"fields": fields})
80
+
81
+ def list_pipelines(self) -> list[dict]:
82
+ return self._call("crm.dealcategory.list") or []
83
+
84
+ def list_tasks(
85
+ self,
86
+ responsible_id: int | None = None,
87
+ overdue_only: bool = False,
88
+ due_today: bool = False,
89
+ due_this_week: bool = False,
90
+ start: int = 0,
91
+ ) -> list[dict]:
92
+ filter: dict[str, Any] = {"!STATUS": 5}
93
+ if responsible_id:
94
+ filter["RESPONSIBLE_ID"] = responsible_id
95
+ if overdue_only:
96
+ filter["<=DEADLINE"] = date.today().isoformat()
97
+ if due_today:
98
+ filter[">=DEADLINE"] = date.today().isoformat()
99
+ filter["<=DEADLINE"] = date.today().isoformat()
100
+ if due_this_week:
101
+ filter[">=DEADLINE"] = date.today().isoformat()
102
+ filter["<=DEADLINE"] = (date.today() + timedelta(days=7)).isoformat()
103
+
104
+ params: dict[str, Any] = {
105
+ "filter": filter,
106
+ "select": ["ID", "TITLE", "DEADLINE", "RESPONSIBLE_ID", "STATUS", "UF_CRM_TASK"],
107
+ "order": {"ID": "desc"},
108
+ "start": start,
109
+ }
110
+ result = self._call("tasks.task.list", params)
111
+ if isinstance(result, dict):
112
+ return result.get("tasks", [])
113
+ return []
114
+
115
+ def list_dormant_deals(self, days: int = 20) -> list[dict]:
116
+ cutoff = (date.today() - timedelta(days=days)).isoformat()
117
+ return self.list_deals(
118
+ filter={"<=DATE_MODIFY": cutoff, "CLOSED": "N"},
119
+ select=["ID", "TITLE", "STAGE_ID", "DATE_MODIFY", "ASSIGNED_BY_ID", "OPPORTUNITY", "CURRENCY_ID"],
120
+ order={"DATE_MODIFY": "ASC"},
121
+ )
122
+
123
+ def list_closing_this_week(self) -> list[dict]:
124
+ today = date.today().isoformat()
125
+ next_week = (date.today() + timedelta(days=7)).isoformat()
126
+ return self.list_deals(
127
+ filter={">=CLOSEDATE": today, "<=CLOSEDATE": next_week, "CLOSED": "N"},
128
+ select=["ID", "TITLE", "STAGE_ID", "CLOSEDATE", "OPPORTUNITY", "CURRENCY_ID", "ASSIGNED_BY_ID"],
129
+ order={"CLOSEDATE": "ASC"},
130
+ )
mcp_bitrix24/server.py ADDED
@@ -0,0 +1,259 @@
1
+ import json
2
+ import os
3
+ from dotenv import load_dotenv
4
+ from mcp.server.fastmcp import FastMCP
5
+ from mcp_bitrix24.client import BitrixClient
6
+
7
+ load_dotenv()
8
+
9
+ mcp = FastMCP("Bitrix24 CRM")
10
+ client = BitrixClient()
11
+
12
+
13
+ @mcp.tool()
14
+ def list_deals(
15
+ stage: str = "",
16
+ responsible_id: int = 0,
17
+ title_contains: str = "",
18
+ limit: int = 20,
19
+ ) -> str:
20
+ """Lista deals do Bitrix24. Filtre por estágio, responsável ou texto no título."""
21
+ filter: dict = {}
22
+ if stage:
23
+ filter["STAGE_ID"] = stage
24
+ if responsible_id:
25
+ filter["ASSIGNED_BY_ID"] = responsible_id
26
+ if title_contains:
27
+ filter["%TITLE"] = title_contains
28
+
29
+ select = ["ID", "TITLE", "STAGE_ID", "OPPORTUNITY", "CURRENCY_ID",
30
+ "ASSIGNED_BY_ID", "DATE_CREATE", "CLOSEDATE", "COMMENTS"]
31
+
32
+ deals = client.list_deals(filter=filter or None, select=select)
33
+ deals = deals[:limit]
34
+
35
+ if not deals:
36
+ return "Nenhum deal encontrado com os filtros fornecidos."
37
+
38
+ lines = [f"Encontrados {len(deals)} deals:\n"]
39
+ for d in deals:
40
+ valor = f"{d.get('OPPORTUNITY', '0')} {d.get('CURRENCY_ID', '')}"
41
+ lines.append(
42
+ f"• [{d['ID']}] {d['TITLE']}\n"
43
+ f" Estágio: {d.get('STAGE_ID')} | Valor: {valor}\n"
44
+ f" Responsável ID: {d.get('ASSIGNED_BY_ID')} | Fechamento: {d.get('CLOSEDATE', 'N/A')}"
45
+ )
46
+ return "\n".join(lines)
47
+
48
+
49
+ @mcp.tool()
50
+ def get_deal(deal_id: int) -> str:
51
+ """Retorna todos os detalhes de um deal específico pelo ID."""
52
+ deal = client.get_deal(deal_id)
53
+ if not deal:
54
+ return f"Deal {deal_id} não encontrado."
55
+ return json.dumps(deal, ensure_ascii=False, indent=2)
56
+
57
+
58
+ @mcp.tool()
59
+ def create_deal(
60
+ title: str,
61
+ stage_id: str = "",
62
+ value: float = 0.0,
63
+ currency: str = "BRL",
64
+ contact_id: int = 0,
65
+ company_id: int = 0,
66
+ responsible_id: int = 0,
67
+ comments: str = "",
68
+ close_date: str = "",
69
+ ) -> str:
70
+ """
71
+ Cria um novo deal no Bitrix24.
72
+ close_date deve estar no formato YYYY-MM-DD.
73
+ """
74
+ fields: dict = {"TITLE": title, "CURRENCY_ID": currency}
75
+ if stage_id:
76
+ fields["STAGE_ID"] = stage_id
77
+ if value:
78
+ fields["OPPORTUNITY"] = value
79
+ if contact_id:
80
+ fields["CONTACT_ID"] = contact_id
81
+ if company_id:
82
+ fields["COMPANY_ID"] = company_id
83
+ if responsible_id:
84
+ fields["ASSIGNED_BY_ID"] = responsible_id
85
+ if comments:
86
+ fields["COMMENTS"] = comments
87
+ if close_date:
88
+ fields["CLOSEDATE"] = f"{close_date}T00:00:00+03:00"
89
+
90
+ new_id = client.create_deal(fields)
91
+ return f"Deal criado com sucesso! ID: {new_id}"
92
+
93
+
94
+ @mcp.tool()
95
+ def update_deal(deal_id: int, fields_json: str) -> str:
96
+ """
97
+ Atualiza campos de um deal existente.
98
+ fields_json deve ser um JSON com os campos a atualizar.
99
+ Exemplo: {"TITLE": "Novo nome", "OPPORTUNITY": 5000}
100
+ """
101
+ try:
102
+ fields = json.loads(fields_json)
103
+ except json.JSONDecodeError as e:
104
+ return f"Erro: fields_json inválido — {e}"
105
+
106
+ client.update_deal(deal_id, fields)
107
+ return f"Deal {deal_id} atualizado com sucesso."
108
+
109
+
110
+ @mcp.tool()
111
+ def move_deal_stage(deal_id: int, stage_id: str) -> str:
112
+ """
113
+ Move um deal para um estágio do funil.
114
+ Use list_stages para ver os estágios disponíveis.
115
+ """
116
+ client.update_deal(deal_id, {"STAGE_ID": stage_id})
117
+ return f"Deal {deal_id} movido para o estágio '{stage_id}'."
118
+
119
+
120
+ @mcp.tool()
121
+ def list_stages(pipeline_id: int = 0) -> str:
122
+ """Lista os estágios disponíveis no funil. pipeline_id=0 lista o funil padrão."""
123
+ stages = client.get_stages(pipeline_id if pipeline_id else None)
124
+ if not stages:
125
+ return "Nenhum estágio encontrado."
126
+ lines = ["Estágios disponíveis:"]
127
+ for s in stages:
128
+ lines.append(f"• {s.get('STATUS_ID')} — {s.get('NAME')}")
129
+ return "\n".join(lines)
130
+
131
+
132
+ @mcp.tool()
133
+ def add_comment(deal_id: int, comment: str) -> str:
134
+ """Adiciona uma nota/comentário a um deal."""
135
+ activity_id = client.add_comment(deal_id, comment)
136
+ return f"Comentário adicionado ao deal {deal_id}. Atividade ID: {activity_id}"
137
+
138
+
139
+ @mcp.tool()
140
+ def add_task(deal_id: int, subject: str, description: str = "", deadline: str = "") -> str:
141
+ """
142
+ Adiciona uma tarefa a um deal.
143
+ deadline deve estar no formato YYYY-MM-DDTHH:MM:SS+HH:MM.
144
+ """
145
+ activity_id = client.add_task(deal_id, subject, description, deadline)
146
+ return f"Tarefa '{subject}' adicionada ao deal {deal_id}. Atividade ID: {activity_id}"
147
+
148
+
149
+ @mcp.tool()
150
+ def list_pipelines() -> str:
151
+ """Lista todos os funis (pipelines) de deals disponíveis."""
152
+ pipelines = client.list_pipelines()
153
+ if not pipelines:
154
+ return "Apenas o funil padrão (ID: 0) está disponível."
155
+ lines = ["Funis disponíveis:"]
156
+ for p in pipelines:
157
+ lines.append(f"• ID: {p.get('ID')} — {p.get('NAME')}")
158
+ return "\n".join(lines)
159
+
160
+
161
+ @mcp.tool()
162
+ def list_tasks(
163
+ responsible_id: int = 0,
164
+ overdue_only: bool = False,
165
+ due_this_week: bool = False,
166
+ limit: int = 20,
167
+ ) -> str:
168
+ """Lista tarefas pendentes do Bitrix24. overdue_only=true retorna só as atrasadas. due_this_week=true retorna tarefas com prazo nos próximos 7 dias."""
169
+ tasks = client.list_tasks(
170
+ responsible_id=responsible_id or None,
171
+ overdue_only=overdue_only,
172
+ due_this_week=due_this_week,
173
+ )
174
+ tasks = tasks[:limit]
175
+
176
+ if not tasks:
177
+ return "Nenhuma tarefa encontrada."
178
+
179
+ lines = [f"Encontradas {len(tasks)} tarefas:\n"]
180
+ for t in tasks:
181
+ deadline = t.get("deadline") or t.get("DEADLINE") or "sem prazo"
182
+ crm_link = t.get("ufCrmTask") or t.get("UF_CRM_TASK") or ""
183
+ lines.append(
184
+ f"• [{t.get('id') or t.get('ID')}] {t.get('title') or t.get('TITLE')}\n"
185
+ f" Prazo: {deadline} | Status: {t.get('status') or t.get('STATUS')}\n"
186
+ f" Responsável ID: {t.get('responsibleId') or t.get('RESPONSIBLE_ID')} | CRM: {crm_link}"
187
+ )
188
+ return "\n".join(lines)
189
+
190
+
191
+ @mcp.tool()
192
+ def daily_briefing(dormant_days: int = 20) -> str:
193
+ """
194
+ Gera um briefing consolidado do dia: tarefas atrasadas, tarefas para hoje,
195
+ deals dormentes e deals com fechamento previsto para esta semana.
196
+ dormant_days: quantos dias sem atividade para considerar um deal dormente (padrão: 20).
197
+ """
198
+ from datetime import date
199
+ today = date.today().strftime("%d/%m/%Y")
200
+ sections = [f"BRIEFING DO DIA — {today}\n"]
201
+
202
+ # Tarefas atrasadas
203
+ overdue = client.list_tasks(overdue_only=True)
204
+ if overdue:
205
+ sections.append(f"TAREFAS ATRASADAS ({len(overdue)})")
206
+ for t in overdue[:10]:
207
+ deal = (t.get("ufCrmTask") or [""])[0]
208
+ deadline = (t.get("deadline") or "sem prazo")[:10]
209
+ sections.append(f" • [{t.get('id')}] {t.get('title')} | prazo: {deadline} | deal: {deal}")
210
+ else:
211
+ sections.append("TAREFAS ATRASADAS\n Nenhuma.")
212
+
213
+ sections.append("")
214
+
215
+ # Tarefas para hoje
216
+ today_tasks = client.list_tasks(due_today=True)
217
+ if today_tasks:
218
+ sections.append(f"TAREFAS PARA HOJE ({len(today_tasks)})")
219
+ for t in today_tasks[:10]:
220
+ deal = (t.get("ufCrmTask") or [""])[0]
221
+ sections.append(f" • [{t.get('id')}] {t.get('title')} | deal: {deal}")
222
+ else:
223
+ sections.append("TAREFAS PARA HOJE\n Nenhuma.")
224
+
225
+ sections.append("")
226
+
227
+ # Deals dormentes
228
+ dormant = client.list_dormant_deals(days=dormant_days)
229
+ if dormant:
230
+ sections.append(f"DEALS DORMENTES — sem atividade há +{dormant_days} dias ({len(dormant)})")
231
+ for d in dormant[:10]:
232
+ modified = (d.get("DATE_MODIFY") or "")[:10]
233
+ valor = f"{d.get('OPPORTUNITY', '0')} {d.get('CURRENCY_ID', '')}"
234
+ sections.append(f" • [{d['ID']}] {d['TITLE']} | estágio: {d.get('STAGE_ID')} | último update: {modified} | valor: {valor}")
235
+ else:
236
+ sections.append(f"DEALS DORMENTES\n Nenhum deal parado há mais de {dormant_days} dias.")
237
+
238
+ sections.append("")
239
+
240
+ # Forecast da semana
241
+ closing = client.list_closing_this_week()
242
+ if closing:
243
+ sections.append(f"FECHAMENTO PREVISTO ESTA SEMANA ({len(closing)})")
244
+ for d in closing[:10]:
245
+ closedate = (d.get("CLOSEDATE") or "")[:10]
246
+ valor = f"{d.get('OPPORTUNITY', '0')} {d.get('CURRENCY_ID', '')}"
247
+ sections.append(f" • [{d['ID']}] {d['TITLE']} | fechamento: {closedate} | valor: {valor}")
248
+ else:
249
+ sections.append("FECHAMENTO PREVISTO ESTA SEMANA\n Nenhum deal.")
250
+
251
+ return "\n".join(sections)
252
+
253
+
254
+ def main():
255
+ mcp.run(transport="stdio")
256
+
257
+
258
+ if __name__ == "__main__":
259
+ main()
@@ -0,0 +1,134 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-bitrix24
3
+ Version: 0.1.0
4
+ Summary: MCP Server for Bitrix24 CRM — manage deals via Claude
5
+ Project-URL: Homepage, https://github.com/lucbrito88-boop/mcp-bitrix24
6
+ Project-URL: Repository, https://github.com/lucbrito88-boop/mcp-bitrix24
7
+ License: MIT
8
+ Keywords: ai,bitrix24,claude,crm,mcp
9
+ Requires-Python: >=3.10
10
+ Requires-Dist: httpx>=0.27.0
11
+ Requires-Dist: mcp[cli]>=1.0.0
12
+ Requires-Dist: python-dotenv>=1.0.0
13
+ Description-Content-Type: text/markdown
14
+
15
+ # Bitrix24 MCP Server
16
+
17
+ MCP Server que integra o CRM Bitrix24 ao Claude, permitindo gerenciar deals diretamente via linguagem natural.
18
+
19
+ ## O que você pode fazer
20
+
21
+ Após configurar, você pode pedir ao Claude coisas como:
22
+
23
+ - *"Liste meus deals em aberto"*
24
+ - *"Mostre os detalhes do deal 123"*
25
+ - *"Crie um deal chamado 'Proposta NTSec' no valor de R$ 50.000"*
26
+ - *"Mova o deal 456 para a etapa de negociação"*
27
+ - *"Adicione uma nota no deal 789: reunião realizada com sucesso"*
28
+ - *"Quais são os estágios do meu funil?"*
29
+ - *"Liste minhas tarefas atrasadas"*
30
+ - *"Quais tarefas estão pendentes para o responsável 42?"*
31
+
32
+ ## Ferramentas disponíveis
33
+
34
+ | Ferramenta | Descrição |
35
+ |---|---|
36
+ | `list_deals` | Lista deals com filtros por estágio, responsável ou título |
37
+ | `get_deal` | Retorna todos os detalhes de um deal pelo ID |
38
+ | `create_deal` | Cria um novo deal no CRM |
39
+ | `update_deal` | Atualiza campos de um deal existente |
40
+ | `move_deal_stage` | Move um deal para outro estágio do funil |
41
+ | `list_stages` | Lista os estágios disponíveis no funil |
42
+ | `add_comment` | Adiciona nota/comentário a um deal |
43
+ | `add_task` | Cria uma tarefa vinculada a um deal |
44
+ | `list_tasks` | Lista tarefas pendentes; filtra por responsável ou só atrasadas |
45
+ | `list_pipelines` | Lista os funis de deals disponíveis |
46
+
47
+ ## Pré-requisitos
48
+
49
+ - Python 3.10+
50
+ - [uv](https://docs.astral.sh/uv/) (gerenciador de pacotes)
51
+ - Claude Code CLI
52
+ - Conta no Bitrix24 com acesso à API (webhook configurado)
53
+
54
+ ## Instalação
55
+
56
+ ### 1. Clone o repositório
57
+
58
+ ```bash
59
+ git clone https://github.com/seu-usuario/bitrix24-mcp.git
60
+ cd bitrix24-mcp
61
+ ```
62
+
63
+ ### 2. Crie o ambiente virtual e instale as dependências
64
+
65
+ ```bash
66
+ uv venv .venv
67
+ uv pip install -r requirements.txt
68
+ ```
69
+
70
+ ### 3. Configure o webhook do Bitrix24
71
+
72
+ Copie o arquivo de exemplo e adicione sua URL:
73
+
74
+ ```bash
75
+ cp .env.example .env
76
+ ```
77
+
78
+ Edite o `.env`:
79
+
80
+ ```env
81
+ BITRIX24_WEBHOOK_URL=https://seudominio.bitrix24.com.br/rest/USER_ID/WEBHOOK_TOKEN/
82
+ ```
83
+
84
+ **Como obter o webhook no Bitrix24:**
85
+ 1. Acesse seu Bitrix24 → Configurações → Integrações → Webhooks de entrada
86
+ 2. Crie um webhook com permissões de CRM (leitura e escrita)
87
+ 3. Copie a URL gerada
88
+
89
+ ### 4. Configure o MCP Server no Claude Code
90
+
91
+ Adicione ao seu `.claude/settings.json` (ou `~/.claude/settings.json` para uso global):
92
+
93
+ ```json
94
+ {
95
+ "mcpServers": {
96
+ "bitrix24": {
97
+ "command": "/caminho/para/bitrix24-mcp/.venv/Scripts/python.exe",
98
+ "args": ["/caminho/para/bitrix24-mcp/server.py"]
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ > **Windows:** use `.venv\Scripts\python.exe`
105
+ > **Mac/Linux:** use `.venv/bin/python`
106
+
107
+ ### 5. Reinicie o Claude Code
108
+
109
+ Feche e reabra o Claude Code. O MCP server `bitrix24` deve aparecer disponível.
110
+
111
+ ## Estrutura do projeto
112
+
113
+ ```
114
+ bitrix24-mcp/
115
+ ├── src/mcp_bitrix24/
116
+ │ ├── server.py # MCP server — define as ferramentas expostas ao Claude
117
+ │ └── client.py # Wrapper da API REST do Bitrix24
118
+ ├── pyproject.toml # Configuração do pacote (PyPI)
119
+ ├── requirements.txt # Dependências Python
120
+ ├── .env.example # Template de configuração
121
+ └── .gitignore
122
+ ```
123
+
124
+ ## Dependências
125
+
126
+ - [`mcp`](https://github.com/anthropics/mcp) — SDK do Model Context Protocol
127
+ - [`httpx`](https://www.python-httpx.org/) — cliente HTTP assíncrono
128
+ - [`python-dotenv`](https://github.com/theskumar/python-dotenv) — carregamento do `.env`
129
+
130
+ ## Segurança
131
+
132
+ - O arquivo `.env` está no `.gitignore` — nunca commite suas credenciais
133
+ - O webhook do Bitrix24 deve ter permissões de CRM e Tarefas (task)
134
+ - Recomenda-se criar um usuário de serviço dedicado no Bitrix24 para o webhook
@@ -0,0 +1,7 @@
1
+ mcp_bitrix24/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ mcp_bitrix24/client.py,sha256=VJnYNDM2SOOS8wzwCW-bOVytz7BRSYejYB5uzvLsol0,4909
3
+ mcp_bitrix24/server.py,sha256=fPFP411ieQF_h7lHR9977hdNniCL-Z66X4fZKBScPRM,8651
4
+ mcp_bitrix24-0.1.0.dist-info/METADATA,sha256=P1R8iBaypVtTMkYR6ls76JwyPzfLHBmNZhpPj4aZBvw,4124
5
+ mcp_bitrix24-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
6
+ mcp_bitrix24-0.1.0.dist-info/entry_points.txt,sha256=MyLb0Z8DmN_V00LsrmrA6l8IZ7LIHGzgkACS_RLn1PY,58
7
+ mcp_bitrix24-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ mcp-bitrix24 = mcp_bitrix24.server:main