feat: add org booking tools#111
Conversation
Two new read-only tools for org-level booking queries: - get_org_team_bookings: list all bookings for a team within an org (TEAM_ADMIN). Endpoint: /v2/organizations/:orgId/teams/:teamId/bookings - get_org_user_bookings: list all bookings for a specific org member (ORG_ADMIN). Endpoint: /v2/organizations/:orgId/users/:userId/bookings Both support the full booking filter set (status, attendeeEmail, attendeeName, eventType, date ranges, sorting, pagination). Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
Co-Authored-By: joe@cal.com <j.auyeung419@gmail.com>
…tools # Conflicts: # apps/mcp-server/README.md # apps/mcp-server/src/server-instructions.ts
|
The latest updates on your projects. Learn more about Vercel for GitHub. 2 Skipped Deployments
|
| take: z.number().int().optional().describe("Max results to return (default 100, max 250)"), | ||
| skip: z.number().int().optional().describe("Results to skip (offset)"), |
There was a problem hiding this comment.
🟡 Missing OpenAPI pagination bounds on take and skip in new shared booking filters schema
The new bookingFiltersSchema defines take as z.number().int().optional() and skip as z.number().int().optional(), but the description for take says "max 250". Every other paginated schema in the codebase enforces .min(1).max(250) on take and .min(0) on skip — see apps/mcp-server/src/tools/organizations/memberships.ts:10-11, apps/mcp-server/src/tools/organizations/teams.ts:10-11, apps/mcp-server/src/tools/teams/memberships.ts:12-13. The AGENTS.md rule (api-mcp-openapi-contract.md) requires mirroring OpenAPI min/max bounds in Zod schemas and even provides take/skip as the canonical correct/incorrect example. This loose schema is inherited by the two new tools (getOrgTeamBookings, getOrgUserBookings), allowing an LLM to send out-of-bounds values the API will reject.
| take: z.number().int().optional().describe("Max results to return (default 100, max 250)"), | |
| skip: z.number().int().optional().describe("Results to skip (offset)"), | |
| take: z.number().int().min(1).max(250).optional().describe("Max results to return (1-250, default 100)"), | |
| skip: z.number().int().min(0).optional().describe("Results to skip (offset, min 0)"), |
Was this helpful? React with 👍 or 👎 to provide feedback.
| describe("getOrgTeamBookings", () => { | ||
| it("exports getOrgTeamBookingsSchema", () => { expect(getOrgTeamBookingsSchema).toBeDefined(); }); |
There was a problem hiding this comment.
🟡 Missing schema validation boundary tests for new org booking tools
The AGENTS.md rule (api-mcp-openapi-contract.md) requires: "Co-located *.test.ts files already assert OpenAPI bounds — extend them. Cover the schema edges so future edits can't silently loosen them." The new bookings.test.ts file has no schema boundary tests (e.g. verifying that take > 250 fails, skip < 0 fails, etc.), unlike the existing memberships.test.ts:30-39 which tests pagination bounds. Once the bounds from BUG-0001 are added, corresponding boundary tests should be added here.
Prompt for agents
The AGENTS.md rule (api-mcp-openapi-contract.md) requires schema boundary tests for new tools. The new bookings.test.ts only has basic existence checks but no boundary validation tests.
Look at apps/mcp-server/src/tools/organizations/memberships.test.ts lines 30-39 for the pattern. Add similar tests to apps/mcp-server/src/tools/organizations/bookings.test.ts that verify:
- getOrgTeamBookingsSchema.take rejects 0 and 251, accepts 250
- getOrgTeamBookingsSchema.skip rejects -1
- Same for getOrgUserBookingsSchema
This requires the bounds from BUG-0001 to be fixed first in booking-filters.ts.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
1 issue found across 10 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/mcp-server/src/tools/booking-filters.ts">
<violation number="1" location="apps/mcp-server/src/tools/booking-filters.ts:36">
P2: `skip` is missing `.min(0)` validation, allowing negative skip values that are semantically invalid for pagination offset</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| sortCreated: z.enum(["asc", "desc"]).optional().describe("Sort by creation time"), | ||
| sortUpdatedAt: z.enum(["asc", "desc"]).optional().describe("Sort by updated time"), | ||
| take: z.number().int().optional().describe("Max results to return (default 100, max 250)"), | ||
| skip: z.number().int().optional().describe("Results to skip (offset)"), |
There was a problem hiding this comment.
P2: skip is missing .min(0) validation, allowing negative skip values that are semantically invalid for pagination offset
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/mcp-server/src/tools/booking-filters.ts, line 36:
<comment>`skip` is missing `.min(0)` validation, allowing negative skip values that are semantically invalid for pagination offset</comment>
<file context>
@@ -0,0 +1,77 @@
+ sortCreated: z.enum(["asc", "desc"]).optional().describe("Sort by creation time"),
+ sortUpdatedAt: z.enum(["asc", "desc"]).optional().describe("Sort by updated time"),
+ take: z.number().int().optional().describe("Max results to return (default 100, max 250)"),
+ skip: z.number().int().optional().describe("Results to skip (offset)"),
+};
+
</file context>
Fixes: https://linear.app/calcom/issue/ENG-1698/add-mcp-tool-for-list-and-search-bookings
#103 had some issues and review comments like ORG_BOOKING_READ and TEAM_BOOKING_READ wasn't in the default scope string and Readme and
apps/mcp-server/src/server-instructions.tswasn't updated