mirror of
https://github.com/hoshikawa2/compass_backoffice.git
synced 2026-07-09 22:04:20 +00:00
first commit
This commit is contained in:
176
mcp_servers/backoffice_mcp_server/main.py
Normal file
176
mcp_servers/backoffice_mcp_server/main.py
Normal file
@@ -0,0 +1,176 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Callable, Dict
|
||||
|
||||
from fastapi import FastAPI, HTTPException
|
||||
|
||||
from .models import ToolCallRequest, ToolCallResponse, ToolDefinition, ToolListResponse
|
||||
from .settings import get_settings
|
||||
from .store import (
|
||||
consultar_cliente_backoffice,
|
||||
consultar_reclamacao,
|
||||
registrar_acao_backoffice,
|
||||
consultar_siebel_caso,
|
||||
registrar_acao_siebel,
|
||||
consultar_imdb_cliente,
|
||||
consultar_speech_analytics,
|
||||
consultar_tais_kb,
|
||||
consultar_abrt,
|
||||
consultar_portabilidade,
|
||||
buscar_templates_emulador,
|
||||
gerar_rascunho_emulador,
|
||||
)
|
||||
|
||||
app = FastAPI(title="Backoffice MCP HTTP Server", version="1.0.0")
|
||||
|
||||
TOOLS: Dict[str, Dict[str, Any]] = {
|
||||
"consultar_reclamacao": {
|
||||
"description": "Consulta reclamação/protocolo de backoffice/ANATEL.",
|
||||
"handler": consultar_reclamacao,
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"protocol_id": {"type": "string"},
|
||||
"customer_key": {"type": "string"},
|
||||
"interaction_key": {"type": "string"},
|
||||
},
|
||||
"required": ["protocol_id"],
|
||||
},
|
||||
},
|
||||
"consultar_cliente_backoffice": {
|
||||
"description": "Consulta contexto operacional do cliente para backoffice.",
|
||||
"handler": consultar_cliente_backoffice,
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"customer_key": {"type": "string"},
|
||||
"contract_key": {"type": "string"},
|
||||
"session_key": {"type": "string"},
|
||||
"cpf": {"type": "string"},
|
||||
"cnpj": {"type": "string"},
|
||||
"document": {"type": "string"},
|
||||
"document_type": {"type": "string"},
|
||||
},
|
||||
"required": ["customer_key"],
|
||||
},
|
||||
},
|
||||
"registrar_acao_backoffice": {
|
||||
"description": "Registra ação operacional, parecer ou encaminhamento no sistema de backoffice.",
|
||||
"handler": registrar_acao_backoffice,
|
||||
"input_schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"protocol_id": {"type": "string"},
|
||||
"action_text": {"type": "string"},
|
||||
"operator_session": {"type": "string"},
|
||||
},
|
||||
"required": ["protocol_id", "action_text"],
|
||||
},
|
||||
},
|
||||
"consultar_siebel_caso": {
|
||||
"description": "Consulta caso/SR no Siebel para reclamação ANATEL/backoffice.",
|
||||
"handler": consultar_siebel_caso,
|
||||
"input_schema": {"type": "object", "properties": {"protocol_id": {"type": "string"}, "interaction_key": {"type": "string"}, "customer_key": {"type": "string"}}},
|
||||
},
|
||||
"registrar_acao_siebel": {
|
||||
"description": "Registra ação, reclassificação, fechamento ou atualização no Siebel.",
|
||||
"handler": registrar_acao_siebel,
|
||||
"input_schema": {"type": "object", "properties": {"protocol_id": {"type": "string"}, "action_text": {"type": "string"}, "operator_session": {"type": "string"}}, "required": ["action_text"]},
|
||||
},
|
||||
"consultar_imdb_cliente": {
|
||||
"description": "Consulta enriquecimento IMDB/PMID do cliente.",
|
||||
"handler": consultar_imdb_cliente,
|
||||
"input_schema": {"type": "object", "properties": {"customer_key": {"type": "string"}, "contract_key": {"type": "string"}, "session_key": {"type": "string"}, "cpf": {"type": "string"}, "cnpj": {"type": "string"}, "document": {"type": "string"}, "document_type": {"type": "string"}}},
|
||||
},
|
||||
"consultar_speech_analytics": {
|
||||
"description": "Consulta histórico/resumo do Speech Analytics.",
|
||||
"handler": consultar_speech_analytics,
|
||||
"input_schema": {"type": "object", "properties": {"protocol_id": {"type": "string"}, "customer_key": {"type": "string"}, "interaction_key": {"type": "string"}, "cpf": {"type": "string"}, "cnpj": {"type": "string"}, "document": {"type": "string"}, "document_type": {"type": "string"}}},
|
||||
},
|
||||
"consultar_tais_kb": {
|
||||
"description": "Consulta base TAIS KB/RAG e templates de resposta.",
|
||||
"handler": consultar_tais_kb,
|
||||
"input_schema": {"type": "object", "properties": {"query": {"type": "string"}, "protocol_id": {"type": "string"}, "customer_key": {"type": "string"}}},
|
||||
},
|
||||
"consultar_abrt": {
|
||||
"description": "Consulta suporte ABRT associado ao cliente/caso.",
|
||||
"handler": consultar_abrt,
|
||||
"input_schema": {"type": "object", "properties": {"customer_key": {"type": "string"}, "protocol_id": {"type": "string"}, "cpf": {"type": "string"}, "cnpj": {"type": "string"}, "document": {"type": "string"}, "document_type": {"type": "string"}}},
|
||||
},
|
||||
"consultar_portabilidade": {
|
||||
"description": "Consulta status de portabilidade.",
|
||||
"handler": consultar_portabilidade,
|
||||
"input_schema": {"type": "object", "properties": {"customer_key": {"type": "string"}, "contract_key": {"type": "string"}, "cpf": {"type": "string"}, "cnpj": {"type": "string"}, "document": {"type": "string"}, "document_type": {"type": "string"}}},
|
||||
},
|
||||
"buscar_templates_emulador": {
|
||||
"description": "Busca templates/documentos para Response Emulator.",
|
||||
"handler": buscar_templates_emulador,
|
||||
"input_schema": {"type": "object", "properties": {"protocol_id": {"type": "string"}, "query": {"type": "string"}}},
|
||||
},
|
||||
"gerar_rascunho_emulador": {
|
||||
"description": "Gera rascunho de resposta do Response Emulator.",
|
||||
"handler": gerar_rascunho_emulador,
|
||||
"input_schema": {"type": "object", "properties": {"protocol_id": {"type": "string"}, "selected_actions": {"type": "array"}, "operator_instructions": {"type": "string"}}},
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
def health() -> Dict[str, Any]:
|
||||
settings = get_settings()
|
||||
return {
|
||||
"status": "ok",
|
||||
"service": "backoffice_mcp_server",
|
||||
"use_mock": settings.use_mock,
|
||||
"backend_type": settings.backend_type,
|
||||
"rest_configured": bool(settings.rest_base_url),
|
||||
"oracle_configured": bool(settings.oracle_dsn and settings.oracle_user),
|
||||
"tim_clients_configured": settings.tim_clients_configured(),
|
||||
"tim_env": {
|
||||
"PMID_API_HOST": bool(settings.pmid_api_host),
|
||||
"SIEBEL_API_HOST": bool(settings.siebel_api_host),
|
||||
"SPEECH_PREDICTION_BASE_URL": bool(settings.speech_prediction_base_url),
|
||||
"SPEECH_HISTORY_BASE_URL": bool(settings.speech_history_base_url),
|
||||
"TAIS_DB_DSN": bool(settings.tais_db_dsn),
|
||||
"TAIS_GENAI_ENDPOINT": bool(settings.tais_genai_endpoint),
|
||||
},
|
||||
"tools": list(TOOLS.keys()),
|
||||
}
|
||||
|
||||
|
||||
@app.get("/tools/list", response_model=ToolListResponse)
|
||||
def list_tools() -> ToolListResponse:
|
||||
return ToolListResponse(
|
||||
tools=[
|
||||
ToolDefinition(
|
||||
name=name,
|
||||
description=cfg["description"],
|
||||
input_schema=cfg["input_schema"],
|
||||
)
|
||||
for name, cfg in TOOLS.items()
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
@app.post("/tools/call", response_model=ToolCallResponse)
|
||||
def call_tool(req: ToolCallRequest) -> ToolCallResponse:
|
||||
cfg = TOOLS.get(req.name)
|
||||
if not cfg:
|
||||
raise HTTPException(status_code=404, detail=f"Ferramenta não encontrada: {req.name}")
|
||||
|
||||
handler: Callable[..., Dict[str, Any]] = cfg["handler"]
|
||||
try:
|
||||
schema_props = ((cfg.get("input_schema") or {}).get("properties") or {})
|
||||
allowed = set(schema_props.keys())
|
||||
# O MCPToolRouter do framework preserva original_context/extra_args por
|
||||
# design. O servidor de domínio deve aceitar somente os parâmetros da
|
||||
# tool, senão handlers Python falham com unexpected keyword argument.
|
||||
arguments = dict(req.arguments or {})
|
||||
filtered_arguments = {k: v for k, v in arguments.items() if not allowed or k in allowed}
|
||||
result = handler(**filtered_arguments)
|
||||
return ToolCallResponse(ok=True, tool=req.name, result=result)
|
||||
except TypeError as exc:
|
||||
return ToolCallResponse(ok=False, tool=req.name, error=f"Parâmetros inválidos: {exc}")
|
||||
except Exception as exc: # pragma: no cover
|
||||
return ToolCallResponse(ok=False, tool=req.name, error=str(exc))
|
||||
Reference in New Issue
Block a user