Skip to content

nc_calendar_find_availability returns nothing but reports success #1394

Description

@IchbinkeinReh

nc_calendar_find_availability always returns an empty result while reporting success, so a caller cannot distinguish "no free slot exists" from "this tool does nothing".

Reproduction

await session.call_tool("nc_calendar_find_availability", {"duration_minutes": 60})

Result:

meta=None content=[] structured_content=None is_error=False result_type='complete'

Same for every parameter combination I tried — with and without date_range_start/date_range_end, business_hours_only=False, exclude_weekends=False.

Cause

The server says so itself:

WARNING nextcloud_mcp_server.client.calendar - find_availability is not fully implemented with AsyncDavClient
INFO    nextcloud_mcp_server.observability.metrics - tool call nc_calendar_find_availability success in 30ms

The call is then recorded as a success, so the gap is invisible in metrics and to any caller that trusts is_error.

Why it matters

The tool is advertised in the tool list with a detailed docstring ("intelligently analyzes existing calendar events to find free time slots…") and a full parameter set. A model will pick it for exactly the task it names, get nothing back, and either report that the calendar is fully booked or fall back to guessing.

That is the awkward failure mode: it does not look like an error, it looks like an answer.

Suggestions

Whichever fits your plans best:

  1. Fail loudly until it is implemented — raise a ToolError saying the tool is not available, so callers can react.
  2. Hide it — drop it from the advertised tool list while unimplemented (the capability filter in errors.py already does this kind of gating).
  3. Implement itnc_calendar_get_upcoming_events already returns everything needed; the rest is interval arithmetic over the busy spans.

I ended up doing (3) in my own client. Two things I ran into that may be worth knowing if you implement it server-side:

  • All-day events must not blanket the day. Real calendars keep birthdays, name days and subscribed school-holiday feeds as all-day entries; treating them as busy erased whole working days for me.
  • Both transparency levels matter — the calendar's schedule-calendar-transp and the event's TRANSP. Neither is currently exposed; I opened feat(calendar): surface free/busy transparency for calendars and events #1390 for that.

Happy to contribute an implementation if you would like it, though I would rather agree on the shape of the response first.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GomNRo5jTc6rDNNLYrRVRX

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions