CoolFace
Apppublic

JosefPilter/appointments-chatbot

sourceHugging Faceupdated 4mo agoView on Hugging Face
0likes
server.py194 linesDownload Raw Back to mcp_server
1"""2server.py — FastMCP server wiring layer.3 4Exposes the tools from tools.py over the MCP stdio transport.5All business logic lives in tools.py; this file is purely declaration.6 7Run directly:8    python -m mcp_server.server9 10Or via MCP inspector:11    mcp dev mcp_server/server.py12"""13 14from mcp.server.fastmcp import FastMCP15 16import mcp_server.tools as _tools17 18mcp = FastMCP("appointment-scheduler")19 20 21@mcp.tool()22def get_current_datetime() -> dict:23    """Return the current date and time in the Europe/Zurich timezone.24 25    Call this before checking availability whenever the user provides a relative26    time expression (e.g., 'next Wednesday', 'in three days', 'tomorrow morning').27    Use the returned date as the anchor for all date arithmetic.28 29    Returns a dict with:30      - datetime: ISO 8601 string with TZ offset (e.g. "2026-05-25T14:30:00+02:00")31      - date:     ISO 8601 date string (e.g. "2026-05-25")32      - weekday:  day name (e.g. "Monday")33      - week_number: ISO week number (int)34    """35    return _tools.get_current_datetime()36 37 38@mcp.tool()39def get_appointment_topics() -> list[dict]:40    """Return all available appointment topics.41 42    Use the returned topic_id values when calling get_appointment_contact_medium43    or check_availability.44 45    Returns a list of objects with topic_id and topic_name.46    """47    return _tools.get_appointment_topics()48 49 50@mcp.tool()51def get_appointment_contact_medium(topic_id: str) -> list[dict] | dict:52    """Return the contact media available for a given topic.53 54    Not all media are available for all topics:55    - Mortgage has no phone option (requires document review).56    - Pension has no branch option (handled remotely).57 58    Args:59        topic_id: A topic_id returned by get_appointment_topics.60 61    Returns a list of objects with contact_medium_id and contact_medium_name,62    or an error dict if topic_id is invalid.63    """64    return _tools.get_appointment_contact_medium(topic_id)65 66 67@mcp.tool()68def check_availability(69    topic_id: str,70    contact_medium_id: str,71    start_datetime: str,72    end_datetime: str,73) -> list[dict] | dict:74    """Return available 60-minute appointment slots within the requested window.75 76    Slots are generated dynamically relative to today. Weekends, fully-booked77    days, and slots within the next 24 hours are excluded automatically.78 79    If the requested range exceeds 3 days, only the first 3 days are checked.80 81    Args:82        topic_id: A topic_id from get_appointment_topics.83        contact_medium_id: A contact_medium_id from get_appointment_contact_medium.84        start_datetime: ISO 8601 string. Timezone defaults to Europe/Zurich if omitted.85        end_datetime:   ISO 8601 string. Timezone defaults to Europe/Zurich if omitted.86 87    Returns a list of {datetime_start, datetime_end} dicts (ISO 8601 strings),88    or an error dict on invalid input.89    """90    return _tools.check_availability(91        topic_id, contact_medium_id, start_datetime, end_datetime92    )93 94 95@mcp.tool()96def book_appointment(97    topic_id: str,98    contact_medium_id: str,99    datetime_start: str,100    datetime_end: str,101) -> dict:102    """Book an appointment slot returned by check_availability.103 104    The slot must exist in the generated availability and must not already be105    taken. Use the exact datetime_start / datetime_end values from106    check_availability to guarantee a match.107 108    Args:109        topic_id:           A topic_id from get_appointment_topics.110        contact_medium_id:  A contact_medium_id from get_appointment_contact_medium.111        datetime_start:     ISO 8601 string matching a slot from check_availability.112        datetime_end:       ISO 8601 string matching a slot from check_availability.113 114    Returns {"status": "success", "booking_id": "BK-XXXXXX", "details": {...}}115    or {"status": "error", "message": "..."}.116    """117    return _tools.book_appointment(118        topic_id, contact_medium_id, datetime_start, datetime_end119    )120 121 122@mcp.tool()123def reset_bookings() -> dict:124    """Clear all bookings from the in-memory store.125 126    Intended for testing and evaluation resets. Has no effect on slot127    generation (availability patterns are date-seeded and remain stable).128 129    Returns {"status": "reset"}.130    """131    return _tools.reset_bookings()132 133 134@mcp.tool()135def admin_set_availability_override(override_json: str) -> dict:136    """Set a fixed availability profile for the current evaluation scenario run.137 138    Parses override_json (a JSON object mapping ISO date strings to lists of139    "HH:MM-HH:MM" slot strings, all times in Europe/Zurich) and activates the140    override. While active, check_availability returns only the overridden slots;141    dates absent from the dict return empty.142 143    Intended for the evaluation runner only — not for production use.144 145    Args:146        override_json: JSON string, e.g. '{"2026-05-26": ["09:00-10:00"]}'147 148    Returns {"status": "ok", "dates_set": N} or an error dict.149    """150    return _tools.admin_set_availability_override(override_json)151 152 153@mcp.tool()154def admin_clear_availability_override() -> dict:155    """Deactivate the availability override and revert to seeded slot generation.156 157    Call this between evaluation scenario runs to ensure isolation.158 159    Returns {"status": "cleared"}.160    """161    return _tools.admin_clear_availability_override()162 163 164@mcp.tool()165def admin_set_clock_override(reference_date: str) -> dict:166    """Pin get_current_datetime() to the scenario's reference_date.167 168    Call this per evaluation scenario run (alongside the availability override) so169    the agent's get_current_datetime() shares the scenario's pinned clock170    (EVALUATION_FRAMEWORK §3a) — making scenario execution date-independent even171    when the run day differs from the suite anchor.172 173    Args:174        reference_date: ISO date string, e.g. "2026-06-01".175 176    Returns {"status": "ok", "clock": "<iso>"} or an error dict.177    """178    return _tools.admin_set_clock_override(reference_date)179 180 181@mcp.tool()182def admin_clear_clock_override() -> dict:183    """Revert get_current_datetime() to the real wall clock.184 185    Call this between evaluation scenario runs to ensure isolation.186 187    Returns {"status": "cleared"}.188    """189    return _tools.admin_clear_clock_override()190 191 192if __name__ == "__main__":193    mcp.run()194