This repository has been archived on 2026-07-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
shira-hermes/mcp_server/tools/legal_tools.py
T
chaim 6f7b94d6f8 feat: initial shira-hermes service
Shira AI backend using OpenAI-compatible agent with tool-calling loop,
replacing the smart-assistant route in ai-gateway.

Components:
- FastAPI adapter (same HTTP contract as ai-gateway)
- Agent runner with agentic tool-calling loop via ai-gateway /v1/chat/completions
- EspoCRM REST API client
- 20 MCP tools (CRM, documents, legal assistance)
- Prompt builder ported from ai-gateway JS to Python
- SOUL.md personality definition
- Dockerfile for Coolify deployment

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 17:29:35 +00:00

150 lines
7.4 KiB
Python

"""Legal Assistance tools: Direct Access initial report generation."""
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from mcp_server.espocrm_client import EspoCrmClient
from mcp_server.tools._helpers import normalize_date, ok, fail
def register_legal_tools(
tools: dict,
crm: "EspoCrmClient",
case_id: str | None,
context: dict,
):
"""Register legal assistance tools."""
async def generate_initial_report(**kwargs) -> str:
if not case_id:
return fail("צריך להיות בתוך תיק כדי ליצור דוח גישה ישירה")
try:
# Normalize date fields
for f in ("appointmentDate", "filingDeadline", "firstContactDate", "meetingDate"):
if kwargs.get(f):
normalized = normalize_date(kwargs[f])
kwargs[f] = normalized.split(" ")[0] if normalized else kwargs[f]
# Extract legalAnalysis sub-object from flat args
legal_analysis = {}
legal_keys = [
"q1DocsReviewed", "q1DocsDetail", "q2Reasoned", "q2ReasonDetail",
"q3PanelMatch", "q4PanelComposition", "q5ComplaintsAddressed", "q6ComplaintsDetail",
"q7ClinicalExam", "q8ClinicalGap", "q9MoharaApplied", "q9MoharaDetail",
"q10RehabGap", "q10RehabDetail", "q11ScoreGap", "q11ScoreDetail",
"q12UniqueAspects", "q12UniqueDetail",
]
for k in legal_keys:
if k in kwargs:
legal_analysis[k] = kwargs.pop(k)
if legal_analysis:
kwargs["legalAnalysis"] = legal_analysis
result = await crm.post("SmartAssistant/action/executeTool", {
"tool": "generate_direct_access_report",
"params": kwargs,
"caseId": case_id,
})
# Update case fields if not already set
case_info = context.get("case", {})
updates = {}
if kwargs.get("appointmentDate") and not case_info.get("cAppointmentDate"):
updates["cAppointmentDate"] = kwargs["appointmentDate"]
if kwargs.get("aidType") and not case_info.get("cAidType"):
updates["cAidType"] = kwargs["aidType"]
if kwargs.get("urgencyLevel") and not case_info.get("cUrgencyLevel"):
updates["cUrgencyLevel"] = kwargs["urgencyLevel"]
if kwargs.get("filingDeadline") and not case_info.get("cFilingDeadline"):
updates["cFilingDeadline"] = kwargs["filingDeadline"]
if updates:
await crm.put(f"Case/{case_id}", updates)
return ok(result.get("message", "✅ דוח גישה ישירה נוצר בהצלחה!"))
except Exception as e:
return fail(f"שגיאה ביצירת דוח גישה ישירה: {e}")
courts = [
"בית הדין האזורי לעבודה ירושלים",
"בית הדין האזורי לעבודה תל אביב",
"בית הדין האזורי לעבודה חיפה",
"בית הדין האזורי לעבודה באר שבע",
"בית הדין האזורי לעבודה נצרת",
"בית הדין הארצי לעבודה",
]
subjects = [
"נכות כללית", "נכות מעבודה", "נכות איבה", "ניידות",
"אי כושר", "שירותים מיוחדים", "סיעוד",
"גמלת הבטחת הכנסה", "דמי אבטלה", "אחר",
]
aid_types = [
"הגשת ערעור", "יעוץ והדרכה", "סיוע נוסף ביטוח לאומי",
"סיוע נוסף תחום אחר", "אי מתן סיוע",
]
recommendations = [
"המשך ייצוג", "ייעוץ והדרכה חלף ייצוג", "ויתור הלקוח",
"החלפת ייצוג", "לא נוצר קשר", "לא התקיימה פגישה",
"עדיין לא ניתן להחליט", "נדרשים מסמכים נוספים", "המלצה לסירוב",
]
tools["generate_initial_report"] = {
"description": "Generate Direct Access initial report (דוח דיווח ראשוני — גישה ישירה). Call ONLY after collecting ALL required data through conversation.",
"parameters": {
"type": "object",
"properties": {
"aidType": {"type": "string", "enum": aid_types, "description": "מהות הסיוע"},
"urgencyLevel": {"type": "string", "enum": ["רגיל", "דחוף", "בהול"]},
"filingDeadline": {"type": "string", "description": "מועד אחרון להגשה (YYYY-MM-DD)"},
"appointmentDate": {"type": "string", "description": "מועד קבלת המינוי (YYYY-MM-DD)"},
"firstContactDate": {"type": "string"},
"contactDelayReason": {"type": "string"},
"meetingDate": {"type": "string"},
"meetingDelayReason": {"type": "string"},
"meetingAttendees": {"type": "string"},
"contactStatus": {"type": "string", "enum": ["תקין", "לא תקין"]},
"contactStatusDetail": {"type": "string"},
"proceedingNumber": {"type": "string"},
"courtName": {"type": "string", "enum": courts},
"proceedingSubject": {"type": "string", "enum": subjects},
"claimSummary": {"type": "string"},
"defenseClaims": {"type": "string"},
# Legal analysis (flat)
"q1DocsReviewed": {"type": "boolean"},
"q1DocsDetail": {"type": "string"},
"q2Reasoned": {"type": "boolean"},
"q2ReasonDetail": {"type": "string"},
"q3PanelMatch": {"type": "boolean"},
"q4PanelComposition": {"type": "string"},
"q5ComplaintsAddressed": {"type": "boolean"},
"q6ComplaintsDetail": {"type": "string"},
"q7ClinicalExam": {"type": "boolean"},
"q8ClinicalGap": {"type": "string"},
"q9MoharaApplied": {"type": "boolean"},
"q9MoharaDetail": {"type": "string"},
"q10RehabGap": {"type": "boolean"},
"q10RehabDetail": {"type": "string"},
"q11ScoreGap": {"type": "boolean"},
"q11ScoreDetail": {"type": "string"},
"q12UniqueAspects": {"type": "boolean"},
"q12UniqueDetail": {"type": "string"},
# Recommendation
"recommendationType": {"type": "string", "enum": recommendations},
"recommendationDetail": {"type": "string"},
# Additional rights
"additionalAidNeeded": {"type": "string", "enum": ["לא נחוץ", "נחוץ בתחום ביטוח לאומי", "נחוץ בתחום אחר"]},
"additionalAidNIDetail": {"type": "string"},
"additionalAidOtherDetail": {"type": "string"},
"additionalAidUrgency": {"type": "string", "enum": ["רגיל", "דחוף", "בהול"]},
"additionalAidDeadlines": {"type": "string"},
"willingToRepresent": {"type": "boolean"},
"notes": {"type": "string"},
},
"required": ["aidType", "proceedingSubject", "recommendationType"],
},
"handler": generate_initial_report,
}