sienge-ecbiesek-mcp 1.0.0__py3-none-any.whl → 1.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.

Potentially problematic release.


This version of sienge-ecbiesek-mcp might be problematic. Click here for more details.

@@ -0,0 +1,34 @@
1
+ Metadata-Version: 2.4
2
+ Name: sienge-ecbiesek-mcp
3
+ Version: 1.1.0
4
+ Summary: Sienge ECBIESEK MCP Server - Model Context Protocol integration for Sienge API (ECBIESEK Company)
5
+ Author-email: ECBIESEK <ti@ecbiesek.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/Moizas951/Sienge-mcp
8
+ Project-URL: Documentation, https://github.com/Moizas951/Sienge-mcp#readme
9
+ Project-URL: Repository, https://github.com/Moizas951/Sienge-mcp.git
10
+ Project-URL: Issues, https://github.com/Moizas951/Sienge-mcp/issues
11
+ Keywords: sienge,mcp,claude,api,construction,ecbiesek
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Topic :: Office/Business :: Financial
23
+ Requires-Python: >=3.9
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: fastmcp>=0.1.0
27
+ Requires-Dist: httpx>=0.25.0
28
+ Requires-Dist: pydantic>=2.0.0
29
+ Requires-Dist: python-dotenv>=1.0.0
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
32
+ Requires-Dist: black>=23.0.0; extra == "dev"
33
+ Requires-Dist: flake8>=6.0.0; extra == "dev"
34
+ Dynamic: license-file
@@ -0,0 +1,9 @@
1
+ sienge_ecbiesek_mcp-1.1.0.dist-info/licenses/LICENSE,sha256=leWD46QLXsQ43M8fE_KgOo5Sf0YB9_X8EVqGdV0Dsc0,1101
2
+ sienge_mcp/__init__.py,sha256=Pjl4hgBCWhVJ_BBZXaP7SuZfH7Z1JWZbSs8MV5sUle8,287
3
+ sienge_mcp/server.py,sha256=-xMDp97XliIgJMii4X5Ws7gcHAT9Fwe3S2JViCd0tDs,43690
4
+ sienge_mcp/utils/logger.py,sha256=bqU0GDsQXE9TaKOq5_6S2L8bh_Nas-EuYNDE3fzlPWg,5880
5
+ sienge_ecbiesek_mcp-1.1.0.dist-info/METADATA,sha256=ayq0Ym2v-7Wik1FUnVvqflTNtz9TrccINRhAVPDpFT0,1534
6
+ sienge_ecbiesek_mcp-1.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
+ sienge_ecbiesek_mcp-1.1.0.dist-info/entry_points.txt,sha256=jxEu6gvTw3ci0mjDfqbi0rBLRpeuscwwRk9-H-UOnO8,63
8
+ sienge_ecbiesek_mcp-1.1.0.dist-info/top_level.txt,sha256=FCvuhB9JQPKGY0Q8aKoVc7akqG5htoJyfj-eJvVUmWM,11
9
+ sienge_ecbiesek_mcp-1.1.0.dist-info/RECORD,,
sienge_mcp/server.py CHANGED
@@ -33,7 +33,7 @@ class SiengeAPIError(Exception):
33
33
 
34
34
  async def make_sienge_request(method: str, endpoint: str, params: Optional[Dict] = None, json_data: Optional[Dict] = None) -> Dict:
35
35
  """
36
- Função auxiliar para fazer requisições à API do Sienge
36
+ Função auxiliar para fazer requisições à API do Sienge (v1)
37
37
  Suporta tanto Bearer Token quanto Basic Auth
38
38
  """
39
39
  try:
@@ -104,6 +104,79 @@ async def make_sienge_request(method: str, endpoint: str, params: Optional[Dict]
104
104
  "message": f"Erro na requisição: {str(e)}"
105
105
  }
106
106
 
107
+ async def make_sienge_bulk_request(method: str, endpoint: str, params: Optional[Dict] = None, json_data: Optional[Dict] = None) -> Dict:
108
+ """
109
+ Função auxiliar para fazer requisições à API bulk-data do Sienge
110
+ Suporta tanto Bearer Token quanto Basic Auth
111
+ """
112
+ try:
113
+ async with httpx.AsyncClient(timeout=REQUEST_TIMEOUT) as client:
114
+ headers = {
115
+ "Content-Type": "application/json",
116
+ "Accept": "application/json"
117
+ }
118
+
119
+ # Configurar autenticação e URL para bulk-data
120
+ auth = None
121
+
122
+ if SIENGE_API_KEY and SIENGE_API_KEY != "sua_api_key_aqui":
123
+ # Bearer Token (Recomendado)
124
+ headers["Authorization"] = f"Bearer {SIENGE_API_KEY}"
125
+ url = f"{SIENGE_BASE_URL}/{SIENGE_SUBDOMAIN}/public/api/bulk-data/v1{endpoint}"
126
+ elif SIENGE_USERNAME and SIENGE_PASSWORD:
127
+ # Basic Auth usando httpx.BasicAuth
128
+ auth = httpx.BasicAuth(SIENGE_USERNAME, SIENGE_PASSWORD)
129
+ url = f"{SIENGE_BASE_URL}/{SIENGE_SUBDOMAIN}/public/api/bulk-data/v1{endpoint}"
130
+ else:
131
+ return {
132
+ "success": False,
133
+ "error": "No Authentication",
134
+ "message": "Configure SIENGE_API_KEY ou SIENGE_USERNAME/PASSWORD no .env"
135
+ }
136
+
137
+ response = await client.request(
138
+ method=method,
139
+ url=url,
140
+ headers=headers,
141
+ params=params,
142
+ json=json_data,
143
+ auth=auth
144
+ )
145
+
146
+ if response.status_code in [200, 201]:
147
+ try:
148
+ return {
149
+ "success": True,
150
+ "data": response.json(),
151
+ "status_code": response.status_code
152
+ }
153
+ except:
154
+ return {
155
+ "success": True,
156
+ "data": {"message": "Success"},
157
+ "status_code": response.status_code
158
+ }
159
+ else:
160
+ return {
161
+ "success": False,
162
+ "error": f"HTTP {response.status_code}",
163
+ "message": response.text,
164
+ "status_code": response.status_code
165
+ }
166
+
167
+ except httpx.TimeoutException:
168
+ return {
169
+ "success": False,
170
+ "error": "Timeout",
171
+ "message": f"A requisição excedeu o tempo limite de {REQUEST_TIMEOUT}s"
172
+ }
173
+ except Exception as e:
174
+ return {
175
+ "success": False,
176
+ "error": str(e),
177
+ "message": f"Erro na requisição bulk-data: {str(e)}"
178
+ }
179
+
107
180
  # ============ CONEXÃO E TESTE ============
108
181
 
109
182
  @mcp.tool
@@ -272,46 +345,115 @@ async def get_sienge_creditor_bank_info(creditor_id: str) -> Dict:
272
345
  # ============ FINANCEIRO ============
273
346
 
274
347
  @mcp.tool
275
- async def get_sienge_accounts_receivable(customer_id: Optional[str] = None, due_date_from: Optional[str] = None,
276
- due_date_to: Optional[str] = None, status: Optional[str] = None, limit: Optional[int] = 50) -> Dict:
348
+ async def get_sienge_accounts_receivable(start_date: str, end_date: str, selection_type: str = "D",
349
+ company_id: Optional[int] = None, cost_centers_id: Optional[List[int]] = None,
350
+ correction_indexer_id: Optional[int] = None, correction_date: Optional[str] = None,
351
+ change_start_date: Optional[str] = None, completed_bills: Optional[str] = None,
352
+ origins_ids: Optional[List[str]] = None, bearers_id_in: Optional[List[int]] = None,
353
+ bearers_id_not_in: Optional[List[int]] = None) -> Dict:
277
354
  """
278
- Consulta títulos a receber
355
+ Consulta parcelas do contas a receber via API bulk-data
279
356
 
280
357
  Args:
281
- customer_id: ID do cliente
282
- due_date_from: Data inicial (YYYY-MM-DD)
283
- due_date_to: Data final (YYYY-MM-DD)
284
- status: Status (open, paid, overdue)
285
- limit: Máximo de registros
358
+ start_date: Data de início do período (YYYY-MM-DD) - OBRIGATÓRIO
359
+ end_date: Data do fim do período (YYYY-MM-DD) - OBRIGATÓRIO
360
+ selection_type: Seleção da data do período (I=emissão, D=vencimento, P=pagamento, B=competência) - padrão: D
361
+ company_id: Código da empresa
362
+ cost_centers_id: Lista de códigos de centro de custo
363
+ correction_indexer_id: Código do indexador de correção
364
+ correction_date: Data para correção do indexador (YYYY-MM-DD)
365
+ change_start_date: Data inicial de alteração do título/parcela (YYYY-MM-DD)
366
+ completed_bills: Filtrar por títulos completos (S)
367
+ origins_ids: Códigos dos módulos de origem (CR, CO, ME, CA, CI, AR, SC, LO, NE, NS, AC, NF)
368
+ bearers_id_in: Filtrar parcelas com códigos de portador específicos
369
+ bearers_id_not_in: Filtrar parcelas excluindo códigos de portador específicos
286
370
  """
287
- params = {"limit": min(limit or 50, 200)}
371
+ params = {
372
+ "startDate": start_date,
373
+ "endDate": end_date,
374
+ "selectionType": selection_type
375
+ }
288
376
 
289
- if customer_id:
290
- params["customer_id"] = customer_id
291
- if due_date_from:
292
- params["due_date_from"] = due_date_from
293
- if due_date_to:
294
- params["due_date_to"] = due_date_to
295
- if status:
296
- params["status"] = status
377
+ if company_id:
378
+ params["companyId"] = company_id
379
+ if cost_centers_id:
380
+ params["costCentersId"] = cost_centers_id
381
+ if correction_indexer_id:
382
+ params["correctionIndexerId"] = correction_indexer_id
383
+ if correction_date:
384
+ params["correctionDate"] = correction_date
385
+ if change_start_date:
386
+ params["changeStartDate"] = change_start_date
387
+ if completed_bills:
388
+ params["completedBills"] = completed_bills
389
+ if origins_ids:
390
+ params["originsIds"] = origins_ids
391
+ if bearers_id_in:
392
+ params["bearersIdIn"] = bearers_id_in
393
+ if bearers_id_not_in:
394
+ params["bearersIdNotIn"] = bearers_id_not_in
395
+
396
+ result = await make_sienge_bulk_request("GET", "/income", params=params)
297
397
 
298
- result = await make_sienge_request("GET", "/accounts-receivable", params=params)
398
+ if result["success"]:
399
+ data = result["data"]
400
+ income_data = data.get("data", []) if isinstance(data, dict) else data
401
+
402
+ return {
403
+ "success": True,
404
+ "message": f"✅ Encontradas {len(income_data)} parcelas a receber",
405
+ "income_data": income_data,
406
+ "count": len(income_data),
407
+ "period": f"{start_date} a {end_date}",
408
+ "selection_type": selection_type,
409
+ "filters": params
410
+ }
411
+
412
+ return {
413
+ "success": False,
414
+ "message": "❌ Erro ao buscar parcelas a receber",
415
+ "error": result.get("error"),
416
+ "details": result.get("message")
417
+ }
418
+
419
+ @mcp.tool
420
+ async def get_sienge_accounts_receivable_by_bills(bills_ids: List[int], correction_indexer_id: Optional[int] = None,
421
+ correction_date: Optional[str] = None) -> Dict:
422
+ """
423
+ Consulta parcelas dos títulos informados via API bulk-data
424
+
425
+ Args:
426
+ bills_ids: Lista de códigos dos títulos - OBRIGATÓRIO
427
+ correction_indexer_id: Código do indexador de correção
428
+ correction_date: Data para correção do indexador (YYYY-MM-DD)
429
+ """
430
+ params = {
431
+ "billsIds": bills_ids
432
+ }
433
+
434
+ if correction_indexer_id:
435
+ params["correctionIndexerId"] = correction_indexer_id
436
+ if correction_date:
437
+ params["correctionDate"] = correction_date
438
+
439
+ result = await make_sienge_bulk_request("GET", "/income/by-bills", params=params)
299
440
 
300
441
  if result["success"]:
301
442
  data = result["data"]
302
- receivables = data.get("results", []) if isinstance(data, dict) else data
443
+ income_data = data.get("data", []) if isinstance(data, dict) else data
303
444
 
304
445
  return {
305
446
  "success": True,
306
- "message": f"✅ Encontrados {len(receivables)} títulos a receber",
307
- "receivables": receivables,
308
- "count": len(receivables),
447
+ "message": f"✅ Encontradas {len(income_data)} parcelas dos títulos informados",
448
+ "income_data": income_data,
449
+ "count": len(income_data),
450
+ "bills_consulted": bills_ids,
309
451
  "filters": params
310
452
  }
311
453
 
312
454
  return {
313
455
  "success": False,
314
- "message": "❌ Erro ao buscar títulos a receber",
456
+ "message": "❌ Erro ao buscar parcelas dos títulos informados",
315
457
  "error": result.get("error"),
316
458
  "details": result.get("message")
317
459
  }
@@ -531,6 +673,206 @@ async def create_sienge_purchase_request(description: str, project_id: str, item
531
673
  "details": result.get("message")
532
674
  }
533
675
 
676
+ # ============ NOTAS FISCAIS DE COMPRA ============
677
+
678
+ @mcp.tool
679
+ async def get_sienge_purchase_invoice(sequential_number: int) -> Dict:
680
+ """
681
+ Consulta nota fiscal de compra por número sequencial
682
+
683
+ Args:
684
+ sequential_number: Número sequencial da nota fiscal
685
+ """
686
+ result = await make_sienge_request("GET", f"/purchase-invoices/{sequential_number}")
687
+
688
+ if result["success"]:
689
+ return {
690
+ "success": True,
691
+ "message": f"✅ Nota fiscal {sequential_number} encontrada",
692
+ "invoice": result["data"]
693
+ }
694
+
695
+ return {
696
+ "success": False,
697
+ "message": f"❌ Erro ao buscar nota fiscal {sequential_number}",
698
+ "error": result.get("error"),
699
+ "details": result.get("message")
700
+ }
701
+
702
+ @mcp.tool
703
+ async def get_sienge_purchase_invoice_items(sequential_number: int) -> Dict:
704
+ """
705
+ Consulta itens de uma nota fiscal de compra
706
+
707
+ Args:
708
+ sequential_number: Número sequencial da nota fiscal
709
+ """
710
+ result = await make_sienge_request("GET", f"/purchase-invoices/{sequential_number}/items")
711
+
712
+ if result["success"]:
713
+ data = result["data"]
714
+ items = data.get("results", []) if isinstance(data, dict) else data
715
+ metadata = data.get("resultSetMetadata", {}) if isinstance(data, dict) else {}
716
+
717
+ return {
718
+ "success": True,
719
+ "message": f"✅ Encontrados {len(items)} itens na nota fiscal {sequential_number}",
720
+ "items": items,
721
+ "count": len(items),
722
+ "metadata": metadata
723
+ }
724
+
725
+ return {
726
+ "success": False,
727
+ "message": f"❌ Erro ao buscar itens da nota fiscal {sequential_number}",
728
+ "error": result.get("error"),
729
+ "details": result.get("message")
730
+ }
731
+
732
+ @mcp.tool
733
+ async def create_sienge_purchase_invoice(document_id: str, number: str, supplier_id: int, company_id: int,
734
+ movement_type_id: int, movement_date: str, issue_date: str,
735
+ series: Optional[str] = None, notes: Optional[str] = None) -> Dict:
736
+ """
737
+ Cadastra uma nova nota fiscal de compra
738
+
739
+ Args:
740
+ document_id: ID do documento (ex: "NF")
741
+ number: Número da nota fiscal
742
+ supplier_id: ID do fornecedor
743
+ company_id: ID da empresa
744
+ movement_type_id: ID do tipo de movimento
745
+ movement_date: Data do movimento (YYYY-MM-DD)
746
+ issue_date: Data de emissão (YYYY-MM-DD)
747
+ series: Série da nota fiscal (opcional)
748
+ notes: Observações (opcional)
749
+ """
750
+ invoice_data = {
751
+ "documentId": document_id,
752
+ "number": number,
753
+ "supplierId": supplier_id,
754
+ "companyId": company_id,
755
+ "movementTypeId": movement_type_id,
756
+ "movementDate": movement_date,
757
+ "issueDate": issue_date
758
+ }
759
+
760
+ if series:
761
+ invoice_data["series"] = series
762
+ if notes:
763
+ invoice_data["notes"] = notes
764
+
765
+ result = await make_sienge_request("POST", "/purchase-invoices", json_data=invoice_data)
766
+
767
+ if result["success"]:
768
+ return {
769
+ "success": True,
770
+ "message": f"✅ Nota fiscal {number} criada com sucesso",
771
+ "invoice": result["data"]
772
+ }
773
+
774
+ return {
775
+ "success": False,
776
+ "message": f"❌ Erro ao criar nota fiscal {number}",
777
+ "error": result.get("error"),
778
+ "details": result.get("message")
779
+ }
780
+
781
+ @mcp.tool
782
+ async def add_items_to_purchase_invoice(sequential_number: int, deliveries_order: List[Dict[str, Any]],
783
+ copy_notes_purchase_orders: bool = True, copy_notes_resources: bool = False,
784
+ copy_attachments_purchase_orders: bool = True) -> Dict:
785
+ """
786
+ Insere itens em uma nota fiscal a partir de entregas de pedidos de compra
787
+
788
+ Args:
789
+ sequential_number: Número sequencial da nota fiscal
790
+ deliveries_order: Lista de entregas com estrutura:
791
+ - purchaseOrderId: ID do pedido de compra
792
+ - itemNumber: Número do item no pedido
793
+ - deliveryScheduleNumber: Número da programação de entrega
794
+ - deliveredQuantity: Quantidade entregue
795
+ - keepBalance: Manter saldo (true/false)
796
+ copy_notes_purchase_orders: Copiar observações dos pedidos de compra
797
+ copy_notes_resources: Copiar observações dos recursos
798
+ copy_attachments_purchase_orders: Copiar anexos dos pedidos de compra
799
+ """
800
+ item_data = {
801
+ "deliveriesOrder": deliveries_order,
802
+ "copyNotesPurchaseOrders": copy_notes_purchase_orders,
803
+ "copyNotesResources": copy_notes_resources,
804
+ "copyAttachmentsPurchaseOrders": copy_attachments_purchase_orders
805
+ }
806
+
807
+ result = await make_sienge_request("POST", f"/purchase-invoices/{sequential_number}/items/purchase-orders/delivery-schedules", json_data=item_data)
808
+
809
+ if result["success"]:
810
+ return {
811
+ "success": True,
812
+ "message": f"✅ Itens adicionados à nota fiscal {sequential_number} com sucesso",
813
+ "item": result["data"]
814
+ }
815
+
816
+ return {
817
+ "success": False,
818
+ "message": f"❌ Erro ao adicionar itens à nota fiscal {sequential_number}",
819
+ "error": result.get("error"),
820
+ "details": result.get("message")
821
+ }
822
+
823
+ @mcp.tool
824
+ async def get_sienge_purchase_invoices_deliveries_attended(bill_id: Optional[int] = None, sequential_number: Optional[int] = None,
825
+ purchase_order_id: Optional[int] = None, invoice_item_number: Optional[int] = None,
826
+ purchase_order_item_number: Optional[int] = None,
827
+ limit: Optional[int] = 100, offset: Optional[int] = 0) -> Dict:
828
+ """
829
+ Lista entregas atendidas entre pedidos de compra e notas fiscais
830
+
831
+ Args:
832
+ bill_id: ID do título da nota fiscal
833
+ sequential_number: Número sequencial da nota fiscal
834
+ purchase_order_id: ID do pedido de compra
835
+ invoice_item_number: Número do item da nota fiscal
836
+ purchase_order_item_number: Número do item do pedido de compra
837
+ limit: Máximo de registros (padrão: 100, máximo: 200)
838
+ offset: Deslocamento (padrão: 0)
839
+ """
840
+ params = {"limit": min(limit or 100, 200), "offset": offset or 0}
841
+
842
+ if bill_id:
843
+ params["billId"] = bill_id
844
+ if sequential_number:
845
+ params["sequentialNumber"] = sequential_number
846
+ if purchase_order_id:
847
+ params["purchaseOrderId"] = purchase_order_id
848
+ if invoice_item_number:
849
+ params["invoiceItemNumber"] = invoice_item_number
850
+ if purchase_order_item_number:
851
+ params["purchaseOrderItemNumber"] = purchase_order_item_number
852
+
853
+ result = await make_sienge_request("GET", "/purchase-invoices/deliveries-attended", params=params)
854
+
855
+ if result["success"]:
856
+ data = result["data"]
857
+ deliveries = data.get("results", []) if isinstance(data, dict) else data
858
+ metadata = data.get("resultSetMetadata", {}) if isinstance(data, dict) else {}
859
+
860
+ return {
861
+ "success": True,
862
+ "message": f"✅ Encontradas {len(deliveries)} entregas atendidas",
863
+ "deliveries": deliveries,
864
+ "count": len(deliveries),
865
+ "metadata": metadata,
866
+ "filters": params
867
+ }
868
+
869
+ return {
870
+ "success": False,
871
+ "message": "❌ Erro ao buscar entregas atendidas",
872
+ "error": result.get("error"),
873
+ "details": result.get("message")
874
+ }
875
+
534
876
  # ============ ESTOQUE ============
535
877
 
536
878
  @mcp.tool
@@ -601,39 +943,100 @@ async def get_sienge_stock_reservations(limit: Optional[int] = 50) -> Dict:
601
943
  # ============ PROJETOS/OBRAS ============
602
944
 
603
945
  @mcp.tool
604
- async def get_sienge_projects(limit: Optional[int] = 50, offset: Optional[int] = 0, status: Optional[str] = None, search: Optional[str] = None) -> Dict:
946
+ async def get_sienge_projects(limit: Optional[int] = 100, offset: Optional[int] = 0, company_id: Optional[int] = None,
947
+ enterprise_type: Optional[int] = None, receivable_register: Optional[str] = None,
948
+ only_buildings_enabled: Optional[bool] = False) -> Dict:
605
949
  """
606
- Busca projetos/obras no Sienge
950
+ Busca empreendimentos/obras no Sienge
607
951
 
608
952
  Args:
609
- limit: Máximo de registros (padrão: 50)
953
+ limit: Máximo de registros (padrão: 100, máximo: 200)
610
954
  offset: Pular registros (padrão: 0)
611
- status: Filtrar por status
612
- search: Buscar por nome
955
+ company_id: Código da empresa
956
+ enterprise_type: Tipo do empreendimento (1: Obra e Centro de custo, 2: Obra, 3: Centro de custo, 4: Centro de custo associado a obra)
957
+ receivable_register: Filtro de registro de recebíveis (B3, CERC)
958
+ only_buildings_enabled: Retornar apenas obras habilitadas para integração orçamentária
613
959
  """
614
- params = {"limit": min(limit or 50, 200), "offset": offset or 0}
960
+ params = {"limit": min(limit or 100, 200), "offset": offset or 0}
615
961
 
616
- if status:
617
- params["status"] = status
618
- if search:
619
- params["search"] = search
962
+ if company_id:
963
+ params["companyId"] = company_id
964
+ if enterprise_type:
965
+ params["type"] = enterprise_type
966
+ if receivable_register:
967
+ params["receivableRegister"] = receivable_register
968
+ if only_buildings_enabled:
969
+ params["onlyBuildingsEnabledForIntegration"] = only_buildings_enabled
620
970
 
621
- result = await make_sienge_request("GET", "/projects", params=params)
971
+ result = await make_sienge_request("GET", "/enterprises", params=params)
622
972
 
623
973
  if result["success"]:
624
974
  data = result["data"]
625
- projects = data.get("results", []) if isinstance(data, dict) else data
975
+ enterprises = data.get("results", []) if isinstance(data, dict) else data
976
+ metadata = data.get("resultSetMetadata", {}) if isinstance(data, dict) else {}
626
977
 
627
978
  return {
628
979
  "success": True,
629
- "message": f"✅ Encontrados {len(projects)} projetos",
630
- "projects": projects,
631
- "count": len(projects)
980
+ "message": f"✅ Encontrados {len(enterprises)} empreendimentos",
981
+ "enterprises": enterprises,
982
+ "count": len(enterprises),
983
+ "metadata": metadata,
984
+ "filters": params
985
+ }
986
+
987
+ return {
988
+ "success": False,
989
+ "message": "❌ Erro ao buscar empreendimentos",
990
+ "error": result.get("error"),
991
+ "details": result.get("message")
992
+ }
993
+
994
+ @mcp.tool
995
+ async def get_sienge_enterprise_by_id(enterprise_id: int) -> Dict:
996
+ """
997
+ Busca um empreendimento específico por ID no Sienge
998
+
999
+ Args:
1000
+ enterprise_id: ID do empreendimento
1001
+ """
1002
+ result = await make_sienge_request("GET", f"/enterprises/{enterprise_id}")
1003
+
1004
+ if result["success"]:
1005
+ return {
1006
+ "success": True,
1007
+ "message": f"✅ Empreendimento {enterprise_id} encontrado",
1008
+ "enterprise": result["data"]
1009
+ }
1010
+
1011
+ return {
1012
+ "success": False,
1013
+ "message": f"❌ Erro ao buscar empreendimento {enterprise_id}",
1014
+ "error": result.get("error"),
1015
+ "details": result.get("message")
1016
+ }
1017
+
1018
+ @mcp.tool
1019
+ async def get_sienge_enterprise_groupings(enterprise_id: int) -> Dict:
1020
+ """
1021
+ Busca agrupamentos de unidades de um empreendimento específico
1022
+
1023
+ Args:
1024
+ enterprise_id: ID do empreendimento
1025
+ """
1026
+ result = await make_sienge_request("GET", f"/enterprises/{enterprise_id}/groupings")
1027
+
1028
+ if result["success"]:
1029
+ groupings = result["data"]
1030
+ return {
1031
+ "success": True,
1032
+ "message": f"✅ Agrupamentos do empreendimento {enterprise_id} encontrados",
1033
+ "groupings": groupings,
1034
+ "count": len(groupings) if isinstance(groupings, list) else 0
632
1035
  }
633
1036
 
634
1037
  return {
635
1038
  "success": False,
636
- "message": "❌ Erro ao buscar projetos",
1039
+ "message": f"❌ Erro ao buscar agrupamentos do empreendimento {enterprise_id}",
637
1040
  "error": result.get("error"),
638
1041
  "details": result.get("message")
639
1042
  }
@@ -1,205 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: sienge-ecbiesek-mcp
3
- Version: 1.0.0
4
- Summary: Sienge ECBIESEK MCP Server - Model Context Protocol integration for Sienge API (ECBIESEK Company)
5
- Author-email: ECBIESEK <ti@ecbiesek.com>
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/Moizas951/Sienge-mcp
8
- Project-URL: Documentation, https://github.com/Moizas951/Sienge-mcp#readme
9
- Project-URL: Repository, https://github.com/Moizas951/Sienge-mcp.git
10
- Project-URL: Issues, https://github.com/Moizas951/Sienge-mcp/issues
11
- Keywords: sienge,mcp,claude,api,construction,ecbiesek
12
- Classifier: Development Status :: 4 - Beta
13
- Classifier: Intended Audience :: Developers
14
- Classifier: License :: OSI Approved :: MIT License
15
- Classifier: Operating System :: OS Independent
16
- Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.9
18
- Classifier: Programming Language :: Python :: 3.10
19
- Classifier: Programming Language :: Python :: 3.11
20
- Classifier: Programming Language :: Python :: 3.12
21
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
- Classifier: Topic :: Office/Business :: Financial
23
- Requires-Python: >=3.9
24
- Description-Content-Type: text/markdown
25
- License-File: LICENSE
26
- Requires-Dist: fastmcp>=0.1.0
27
- Requires-Dist: httpx>=0.25.0
28
- Requires-Dist: pydantic>=2.0.0
29
- Requires-Dist: python-dotenv>=1.0.0
30
- Provides-Extra: dev
31
- Requires-Dist: pytest>=7.0.0; extra == "dev"
32
- Requires-Dist: black>=23.0.0; extra == "dev"
33
- Requires-Dist: flake8>=6.0.0; extra == "dev"
34
- Dynamic: license-file
35
-
36
- # 🏗️ Sienge ECBIESEK MCP Server
37
-
38
- [![PyPI version](https://badge.fury.io/py/sienge-ecbiesek-mcp.svg)](https://badge.fury.io/py/sienge-ecbiesek-mcp)
39
- [![Python 3.9+](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/)
40
-
41
- **Sienge ECBIESEK MCP Server** - Servidor MCP personalizado para a empresa ECBIESEK integrar com a API do Sienge através do Claude Desktop.
42
-
43
- ## 🚀 Instalação Rápida (ECBIESEK)
44
-
45
- ### Usando pipx (Recomendado)
46
-
47
- ```bash
48
- # Executar diretamente sem instalação
49
- pipx run sienge-ecbiesek-mcp
50
-
51
- # Ou instalar permanentemente
52
- pipx install sienge-ecbiesek-mcp
53
- ```
54
-
55
- ### Usando pip
56
-
57
- ```bash
58
- pip install sienge-ecbiesek-mcp
59
- ```
60
-
61
- ## ⚙️ Configuração no Claude Desktop (ECBIESEK)
62
-
63
- Adicione a seguinte configuração ao seu arquivo `claude_desktop_config.json`:
64
-
65
- ### Para pipx (Recomendado):
66
- ```json
67
- {
68
- "mcpServers": {
69
- "SiengeECBIESEK": {
70
- "command": "pipx",
71
- "args": [
72
- "run",
73
- "sienge-ecbiesek-mcp@latest"
74
- ],
75
- "env": {
76
- "SIENGE_BASE_URL": "https://api.sienge.com.br",
77
- "SIENGE_SUBDOMAIN": "ecbiesek",
78
- "SIENGE_USERNAME": "seu-usuario-ecbiesek",
79
- "SIENGE_PASSWORD": "sua-senha-ecbiesek"
80
- }
81
- }
82
- }
83
- }
84
- ```
85
-
86
- ### Para pip (instalação global):
87
- ```json
88
- {
89
- "mcpServers": {
90
- "SiengeECBIESEK": {
91
- "command": "sienge-ecbiesek-mcp",
92
- "env": {
93
- "SIENGE_BASE_URL": "https://api.sienge.com.br",
94
- "SIENGE_SUBDOMAIN": "ecbiesek",
95
- "SIENGE_USERNAME": "seu-usuario-ecbiesek",
96
- "SIENGE_PASSWORD": "sua-senha-ecbiesek"
97
- }
98
- }
99
- }
100
- }
101
- ```
102
-
103
- ## 🔐 Variáveis de Ambiente (ECBIESEK)
104
-
105
- ### Autenticação Basic Auth (Configuração ECBIESEK)
106
- ```bash
107
- SIENGE_USERNAME=usuario_ecbiesek
108
- SIENGE_PASSWORD=senha_ecbiesek
109
- SIENGE_SUBDOMAIN=ecbiesek
110
- SIENGE_BASE_URL=https://api.sienge.com.br
111
- ```
112
-
113
- ### Autenticação Bearer Token (Alternativa)
114
- ```bash
115
- SIENGE_API_KEY=token_api_ecbiesek
116
- SIENGE_BASE_URL=https://api.sienge.com.br
117
- ```
118
-
119
- ## 🛠️ Ferramentas Disponíveis
120
-
121
- O servidor ECBIESEK fornece mais de 30 ferramentas para interagir com a API do Sienge:
122
-
123
- ### 📊 Relatórios e Listagens
124
- - `listar_projetos` - Lista todos os projetos ECBIESEK
125
- - `listar_contas` - Lista contas a pagar/receber
126
- - `listar_centros_custo` - Lista centros de custo
127
- - `listar_fornecedores` - Lista fornecedores
128
- - `listar_colaboradores` - Lista colaboradores ECBIESEK
129
-
130
- ### 🏗️ Gestão de Projetos
131
- - `obter_projeto` - Obtém detalhes de um projeto específico
132
- - `listar_etapas_projeto` - Lista etapas de um projeto
133
- - `listar_medicoes_projeto` - Lista medições de um projeto
134
-
135
- ### 💰 Financeiro
136
- - `criar_conta_pagar` - Cria conta a pagar
137
- - `atualizar_conta` - Atualiza conta existente
138
- - `obter_detalhes_conta` - Obtém detalhes de uma conta
139
-
140
- ### 👥 Recursos Humanos ECBIESEK
141
- - `obter_colaborador` - Obtém detalhes de um colaborador
142
- - `listar_departamentos` - Lista departamentos
143
- - `listar_cargos` - Lista cargos
144
-
145
- ### 📦 Estoque e Suprimentos
146
- - `listar_produtos` - Lista produtos
147
- - `obter_produto` - Obtém detalhes de um produto
148
- - `listar_grupos_produto` - Lista grupos de produtos
149
-
150
- ### ⚙️ Configurações
151
- - `obter_configuracoes_sistema` - Obtém configurações do sistema
152
- - `listar_moedas` - Lista moedas disponíveis
153
- - `obter_info_autenticacao` - Verifica status da autenticação
154
-
155
- ## 📝 Exemplos de Uso (ECBIESEK)
156
-
157
- ### Listar Projetos
158
- ```
159
- Claude: Liste todos os projetos ativos da ECBIESEK no Sienge.
160
- ```
161
-
162
- ### Criar Conta a Pagar
163
- ```
164
- Claude: Crie uma conta a pagar para o fornecedor XYZ no valor de R$ 1.500,00 com vencimento em 30 dias.
165
- ```
166
-
167
- ### Obter Relatório Financeiro
168
- ```
169
- Claude: Me mostre um resumo das contas a pagar em aberto dos projetos da ECBIESEK.
170
- ```
171
-
172
- ## 🏢 Sobre a ECBIESEK
173
-
174
- Este MCP Server foi desenvolvido especificamente para atender às necessidades da empresa ECBIESEK na integração com o sistema Sienge.
175
-
176
- ## 📋 Requisitos
177
-
178
- - Python 3.9 ou superior
179
- - Acesso à API do Sienge com credenciais ECBIESEK
180
- - Claude Desktop instalado
181
-
182
- ## 🐛 Resolução de Problemas
183
-
184
- ### Erro de Autenticação
185
- - Verifique se as credenciais ECBIESEK estão corretas
186
- - Confirme se o subdomínio "ecbiesek" está correto
187
- - Teste as credenciais diretamente na API do Sienge
188
-
189
- ### Timeout de Requisições
190
- - Aumente o valor de `REQUEST_TIMEOUT`
191
- - Verifique a conectividade com a API do Sienge
192
-
193
- ## 📄 Licença
194
-
195
- MIT License - Desenvolvido para ECBIESEK
196
-
197
- ## 📞 Suporte ECBIESEK
198
-
199
- - 📧 Email: ti@ecbiesek.com
200
- - 🏢 Empresa: ECBIESEK
201
- - 📖 Documentação interna
202
-
203
- ---
204
-
205
- **⭐ Sienge ECBIESEK MCP Server - Solução personalizada para integração Sienge + Claude Desktop**
@@ -1,9 +0,0 @@
1
- sienge_ecbiesek_mcp-1.0.0.dist-info/licenses/LICENSE,sha256=leWD46QLXsQ43M8fE_KgOo5Sf0YB9_X8EVqGdV0Dsc0,1101
2
- sienge_mcp/__init__.py,sha256=Pjl4hgBCWhVJ_BBZXaP7SuZfH7Z1JWZbSs8MV5sUle8,287
3
- sienge_mcp/server.py,sha256=-7JO_QGvI2Bsw2Fg3kcAmVoLLVoEsffZiHwjw3jLPzc,27107
4
- sienge_mcp/utils/logger.py,sha256=bqU0GDsQXE9TaKOq5_6S2L8bh_Nas-EuYNDE3fzlPWg,5880
5
- sienge_ecbiesek_mcp-1.0.0.dist-info/METADATA,sha256=kUMzLjwbt_ACAuUJI5M-n6PIuewJP6cwd4ZqX_WfFyI,6318
6
- sienge_ecbiesek_mcp-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
- sienge_ecbiesek_mcp-1.0.0.dist-info/entry_points.txt,sha256=jxEu6gvTw3ci0mjDfqbi0rBLRpeuscwwRk9-H-UOnO8,63
8
- sienge_ecbiesek_mcp-1.0.0.dist-info/top_level.txt,sha256=FCvuhB9JQPKGY0Q8aKoVc7akqG5htoJyfj-eJvVUmWM,11
9
- sienge_ecbiesek_mcp-1.0.0.dist-info/RECORD,,