Skip to content

Commit 8087325

Browse files
committed
Merge remote-tracking branch 'origin/main' into feat/add-org-booking-tools
# Conflicts: # apps/mcp-server/README.md # apps/mcp-server/src/server-instructions.ts
2 parents acc828b + b82e264 commit 8087325

20 files changed

Lines changed: 1318 additions & 148 deletions

.agents/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Companion Agent Documentation Index
2+
3+
- **[../AGENTS.md](../AGENTS.md)** — main agent guide (repo areas, tooling, scope).
4+
- **[rules/](rules/)** — modular engineering rules.
5+
- **[skills/](skills/)** — agent skills (e.g. `chat-sdk`, synced via `skills-lock.json`).
6+
7+
## Rules Index
8+
9+
### API
10+
11+
- [api-mcp-openapi-contract](rules/api-mcp-openapi-contract.md) — align `apps/mcp-server` tools with the Cal.com API v2 OpenAPI contract.
12+
13+
### Reference
14+
15+
- [reference-local-cal-api](rules/reference-local-cal-api.md) — how to locate the local `/cal` API v2 OpenAPI spec.
16+
17+
See [rules/_sections.md](rules/_sections.md) for section definitions and [rules/README.md](rules/README.md) for the rule format.

.agents/rules/README.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Companion Engineering Rules
2+
3+
This directory contains modular, machine-readable engineering rules for the
4+
Companion monorepo. The scaffold mirrors the format used in
5+
[`calcom/cal`](https://github.com/calcom/cal), kept intentionally lean — rules are
6+
added as needs arise rather than copied wholesale.
7+
8+
## Structure
9+
10+
Rules are grouped by a section prefix, defined in `_sections.md`:
11+
12+
| Prefix | Section | Impact |
13+
|--------|---------|--------|
14+
| `api-` | API / Contract | HIGH |
15+
| `testing-` | Testing | MEDIUM-HIGH |
16+
| `quality-` | Code Quality | MEDIUM |
17+
| `reference-` | Reference | LOW |
18+
19+
## Files
20+
21+
- `_sections.md` — defines sections, ordering, and impact levels.
22+
- `_template.md` — template for creating new rules.
23+
- `{section}-{rule-name}.md` — individual rule files.
24+
25+
## Rule Format
26+
27+
Each rule file uses YAML frontmatter followed by a clear explanation:
28+
29+
```markdown
30+
---
31+
title: Rule Title Here
32+
impact: CRITICAL | HIGH | MEDIUM | LOW
33+
impactDescription: Optional description
34+
tags: tag1, tag2
35+
---
36+
37+
## Rule Title Here
38+
39+
**Impact: LEVEL (optional description)**
40+
41+
Brief explanation of the rule and why it matters, with concrete examples.
42+
```
43+
44+
## Adding New Rules
45+
46+
1. Copy `_template.md` to `{section}-{rule-name}.md`.
47+
2. Fill in the frontmatter (title, impact, tags).
48+
3. Write a clear explanation with incorrect/correct examples where useful.
49+
4. Add the rule to [`../README.md`](../README.md) under the right section.
50+
51+
## Scope
52+
53+
Keep rules narrowly scoped. The MCP/OpenAPI rules apply only to `apps/mcp-server`
54+
and other code that wraps Cal.com API v2 — they do not apply to `apps/chat`,
55+
`apps/mobile`, `apps/extension`, or `packages/cli`.

.agents/rules/_sections.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Sections
2+
3+
This file defines all sections, their ordering, impact levels, and descriptions.
4+
The section ID (in parentheses) is the filename prefix used to group rules.
5+
6+
---
7+
8+
## 1. API / Contract (api)
9+
10+
**Impact:** HIGH
11+
**Description:** Rules that keep MCP server tools and other API-v2-wrapping code
12+
aligned with the Cal.com Platform API v2 contract (OpenAPI).
13+
14+
## 2. Testing (testing)
15+
16+
**Impact:** MEDIUM-HIGH
17+
**Description:** Test coverage and validation strategies, especially for request
18+
shapes and schema boundaries.
19+
20+
## 3. Code Quality (quality)
21+
22+
**Impact:** MEDIUM
23+
**Description:** Standards for maintainable, consistent code.
24+
25+
## 4. Reference (reference)
26+
27+
**Impact:** LOW
28+
**Description:** Reference guides for locating shared resources and local setup.

.agents/rules/_template.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
title: Rule Title Here
3+
impact: MEDIUM
4+
impactDescription: Optional description of impact (e.g., "prevents API drift")
5+
tags: tag1, tag2
6+
---
7+
8+
## Rule Title Here
9+
10+
**Impact: MEDIUM (optional impact description)**
11+
12+
Brief explanation of the rule and why it matters. This should be clear and concise, explaining the implications.
13+
14+
**Incorrect (description of what's wrong):**
15+
16+
```typescript
17+
// Bad code example here
18+
const bad = example();
19+
```
20+
21+
**Correct (description of what's right):**
22+
23+
```typescript
24+
// Good code example here
25+
const good = example();
26+
```
27+
28+
Reference: [Link to documentation or resource](https://example.com)
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
---
2+
title: Align MCP Server Tools with the Cal.com API v2 OpenAPI Contract
3+
impact: HIGH
4+
impactDescription: Prevents MCP tool schemas from drifting away from the API they wrap
5+
tags: api, openapi, mcp, mcp-server, zod, api-v2
6+
---
7+
8+
# Align MCP Server Tools with the Cal.com API v2 OpenAPI Contract
9+
10+
**Impact: HIGH (prevents MCP tool schemas from drifting away from the API they wrap)**
11+
12+
`apps/mcp-server` is a Model Context Protocol server that wraps the
13+
[Cal.com Platform API v2](https://cal.com/docs/api-reference/v2). Every tool's
14+
Zod input schema is effectively a re-declaration of part of the API v2 contract.
15+
If the schema drifts from the real endpoint, the LLM sends requests the API
16+
rejects (or, worse, silently malformed ones). Keep the two in sync.
17+
18+
**This rule applies only to `apps/mcp-server`** (and any other code that wraps
19+
API v2). It does not apply to `apps/chat`, `apps/mobile`, `apps/extension`, or
20+
`packages/cli`.
21+
22+
## Before adding or changing a tool
23+
24+
1. **Locate the OpenAPI spec.** Find `docs/api-reference/v2/openapi.json` from a
25+
local `calcom/cal` checkout — see
26+
[reference-local-cal-api](reference-local-cal-api.md) for the lookup order.
27+
2. **Read the exact contract** for the endpoint you wrap:
28+
- HTTP path and method.
29+
- Path params and query params.
30+
- Request body schema (follow `$ref`s).
31+
- Response schema (follow `$ref`s).
32+
- Enums, `minimum`/`maximum`, `default`, and `required` fields.
33+
3. **Mirror those constraints in the Zod schema**, unless you intentionally
34+
choose a stricter bound for safety (document why in a comment if non-obvious).
35+
36+
## Mirror constraints in Zod
37+
38+
Schemas live next to each tool in `apps/mcp-server/src/tools/**` and are exported
39+
as `<tool>Schema` objects. Encode the documented bounds directly:
40+
41+
**Incorrect (loose schema that ignores the documented bounds):**
42+
43+
```typescript
44+
export const getOrgMembershipsSchema = {
45+
orgId: z.number().describe("Organization ID"),
46+
take: z.number().optional(),
47+
skip: z.number().optional(),
48+
};
49+
```
50+
51+
**Correct (mirrors path/param types and the OpenAPI min/max + integer bounds):**
52+
53+
```typescript
54+
export const getOrgMembershipsSchema = {
55+
orgId: z.number().int().describe("Organization ID. Use get_me — never guess."),
56+
take: z.number().int().min(1).max(250).optional().describe("Max results (1-250)"),
57+
skip: z.number().int().min(0).optional().describe("Results to skip (offset, min 0)"),
58+
};
59+
```
60+
61+
Match documented enums exactly (e.g. `z.enum(["MEMBER", "OWNER", "ADMIN"])`) and
62+
keep `.describe()` text accurate — the descriptions become the tool's parameter
63+
docs that the LLM reads.
64+
65+
## Update discovery + metadata when behavior changes
66+
67+
When a change affects what a tool can do or how it is discovered, update all of:
68+
69+
- Tool annotations (`title`, `readOnlyHint`, `destructiveHint`, `idempotentHint`,
70+
`openWorldHint`) so they still reflect the operation.
71+
- The tool tables in `apps/mcp-server/README.md`.
72+
- Server instructions in `apps/mcp-server/src/server-instructions.ts`.
73+
74+
## Add tests for request shape and validation boundaries
75+
76+
Co-located `*.test.ts` files already assert OpenAPI bounds — extend them. Cover
77+
the schema edges so future edits can't silently loosen them:
78+
79+
```typescript
80+
it("enforces OpenAPI pagination bounds", () => {
81+
expect(getOrgMembershipsSchema.take.safeParse(0).success).toBe(false);
82+
expect(getOrgMembershipsSchema.take.safeParse(250).success).toBe(true);
83+
expect(getOrgMembershipsSchema.take.safeParse(251).success).toBe(false);
84+
expect(getOrgMembershipsSchema.skip.safeParse(-1).success).toBe(false);
85+
});
86+
```
87+
88+
Run them with `bun --filter @calcom/mcp-server test` (or `vitest run` inside
89+
`apps/mcp-server`).
90+
91+
## Optional: local stdio smoke
92+
93+
For high-confidence MCP PRs, run a local stdio smoke against API v2 when a local
94+
API key/DB is available (see `apps/mcp-server/README.md` for stdio + `CAL_API_KEY`
95+
setup) to confirm the tool actually round-trips against the live contract.
96+
97+
## Do not hand-edit the spec
98+
99+
`docs/api-reference/v2/openapi.json` is generated in `calcom/cal`. If the spec is
100+
wrong, fix/regenerate it in `/cal` separately — never hand-edit that JSON from
101+
Companion.
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
title: Locating the Cal.com API v2 OpenAPI Spec
3+
impact: LOW
4+
impactDescription: Reference guide for finding the source-of-truth API v2 contract
5+
tags: reference, api, openapi, mcp
6+
---
7+
8+
# Locating the Cal.com API v2 OpenAPI Spec
9+
10+
`apps/mcp-server` wraps the Cal.com Platform API v2. The source of truth for the
11+
API contract is the OpenAPI document that lives in the **`calcom/cal`** repo at:
12+
13+
```
14+
docs/api-reference/v2/openapi.json
15+
```
16+
17+
It is auto-generated from the API v2 NestJS decorators and is large (~1MB+).
18+
Companion does **not** vendor a copy of it, so agents resolve it from a local
19+
checkout of `calcom/cal`.
20+
21+
## How to find it
22+
23+
Look for the file in this order and use the first that exists:
24+
25+
1. `$CALCOM_CAL_REPO/docs/api-reference/v2/openapi.json`
26+
— set the `CALCOM_CAL_REPO` env var to your local `calcom/cal` checkout.
27+
2. `../cal/docs/api-reference/v2/openapi.json`
28+
— the common layout where `companion` and `cal` are sibling directories.
29+
30+
```bash
31+
# Resolve the spec path (first match wins)
32+
SPEC="${CALCOM_CAL_REPO:+$CALCOM_CAL_REPO/docs/api-reference/v2/openapi.json}"
33+
[ -f "$SPEC" ] || SPEC="../cal/docs/api-reference/v2/openapi.json"
34+
[ -f "$SPEC" ] && echo "Using $SPEC" || echo "openapi.json not found — clone calcom/cal"
35+
```
36+
37+
If neither path exists, ask for a `calcom/cal` checkout (or its location) rather
38+
than guessing the contract.
39+
40+
## Do not hand-edit the spec
41+
42+
`openapi.json` is generated. If the spec itself is wrong, fix or regenerate it in
43+
the `calcom/cal` repo (by changing the API v2 decorators and rebooting the API),
44+
**not** by editing the JSON. Never hand-edit `cal`'s `openapi.json` from Companion.

AGENTS.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Companion Development Guide for AI Agents
2+
3+
Companion is a Bun-based monorepo for Cal.com's mobile app, browser extension, and
4+
AI-driven interfaces (chat gateway, MCP server, CLI). This file is the main entry
5+
point for AI agents working in this repo.
6+
7+
## Repo Areas
8+
9+
| Path | What it is |
10+
|------|------------|
11+
| `apps/mobile` | Expo (React Native) mobile app for iOS/Android. |
12+
| `apps/extension` | WXT-based browser extension. |
13+
| `apps/chat` | Multi-protocol bot gateway (Slack/Telegram) with an AI agent. |
14+
| `apps/mcp-server` | Model Context Protocol server that wraps the Cal.com Platform API v2. |
15+
| `packages/cli` | Command-line interface for Cal.com API interactions. |
16+
17+
## Tooling
18+
19+
- **Runtime / package manager**: Bun (workspaces in `apps/*`, `packages/*`).
20+
- **Lint & format**: Biome (`bun run lint`, `bun run format`, `bun run check`).
21+
- **Type check**: `bun run typecheck`.
22+
- **Git hooks**: Husky + lint-staged run `biome format --write` on staged files.
23+
24+
Note: Biome's `files.includes` in `biome.json` only covers `js/jsx/ts/tsx/json`,
25+
so `bun run format` / `format:check` do **not** touch Markdown. Validate docs with
26+
`git diff --check` (whitespace) and a manual read.
27+
28+
## When Touching MCP Tools
29+
30+
Before adding or changing tools in `apps/mcp-server` that wrap Cal.com API v2,
31+
follow [.agents/rules/api-mcp-openapi-contract.md](.agents/rules/api-mcp-openapi-contract.md):
32+
mirror the API v2 OpenAPI contract (path/method, params, request/response shapes,
33+
enums, bounds, defaults, required fields) in the MCP Zod schemas, and update tool
34+
metadata, README tables, server instructions, and tests when behavior changes.
35+
36+
To locate the OpenAPI spec, see
37+
[.agents/rules/reference-local-cal-api.md](.agents/rules/reference-local-cal-api.md).
38+
39+
## Scope of These Rules
40+
41+
The `.agents/rules` here are intentionally narrow. The MCP/OpenAPI rules apply
42+
**only** to `apps/mcp-server` (and other API-v2-wrapping code). They do **not**
43+
apply to unrelated `apps/chat`, `apps/mobile`, `apps/extension`, or `packages/cli`
44+
work — don't burden those areas with MCP-specific constraints.
45+
46+
## Extended Documentation
47+
48+
- **[.agents/README.md](.agents/README.md)** — agent docs index and rules list.
49+
- **[.agents/rules/](.agents/rules/)** — modular engineering rules.

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
AGENTS.md

apps/mcp-server/README.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ A **Model Context Protocol (MCP)** server that wraps the [Cal.com Platform API v
44

55
## Features
66

7-
- **44 tools** covering Bookings, Event Types, Schedules, Availability, Calendars, Conferencing, Routing Forms, Organizations, and User Profile (each with MCP tool annotations: `title`, `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`)
7+
- **52 tools** covering Bookings, Event Types, Schedules, Availability, Calendars, Conferencing, Routing Forms, Organizations, Teams, and User Profile (each with MCP tool annotations: `title`, `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`)
88
- **Dual transport** — stdio for local dev tooling, StreamableHTTP for remote/production
99
- **Dual auth** — API key for stdio (local dev), OAuth 2.1 Authorization Code + PKCE for HTTP (production)
1010
- **Per-user token storage** — encrypted at rest with AES-256-GCM in SQLite
@@ -179,7 +179,7 @@ The server acts as an intermediary: it issues its own access tokens to MCP clien
179179
- Expired tokens are cleaned up automatically every 5 minutes
180180
- In-process rate limiting on all OAuth endpoints (token bucket per IP, configurable via `RATE_LIMIT_WINDOW_MS` / `RATE_LIMIT_MAX`)
181181

182-
## Tools (44)
182+
## Tools (52)
183183

184184
Each tool exposes MCP [tool annotations](https://modelcontextprotocol.io/specification/draft/server/tools#tool-annotations) — a human-readable `title` plus behaviour hints (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) so MCP clients can render them appropriately and apply safety policies.
185185

@@ -272,18 +272,34 @@ Each tool exposes MCP [tool annotations](https://modelcontextprotocol.io/specifi
272272
### Organizations: Memberships (5)
273273
| Tool | Title | Hint | Description |
274274
|---|---|---|---|
275-
| `get_org_memberships` | List Org Memberships | Read | Get all organization memberships |
275+
| `get_org_memberships` | List Org Memberships | Read | Get all organization memberships; supports `take`/`skip` pagination (`take` max 250) |
276276
| `create_org_membership` | Create Org Membership | Create | Create an organization membership |
277277
| `get_org_membership` | Get Org Membership | Read | Get an organization membership |
278278
| `update_org_membership` | Update Org Membership | Update | Update an organization membership (role, accepted, impersonation) |
279279
| `delete_org_membership` | Delete Org Membership | Destructive | Delete an organization membership |
280280

281+
### Organizations: Teams (2)
282+
| Tool | Title | Hint | Description |
283+
|---|---|---|---|
284+
| `get_org_teams` | List All Org Teams | Read | List all teams in an organization; requires org admin access; supports `take`/`skip` pagination (`take` max 250) |
285+
| `get_my_teams` | List My Teams | Read | List teams the authenticated user belongs to; supports `take`/`skip` pagination (`take` max 250) |
286+
281287
### Organizations: Routing Forms (2)
282288
| Tool | Title | Hint | Description |
283289
|---|---|---|---|
284290
| `get_org_routing_forms` | List Org Routing Forms | Read | Get organization routing forms |
285291
| `get_org_routing_form_responses` | List Org Routing Form Responses | Read | Get routing form responses |
286292

293+
### Teams: Memberships (6)
294+
| Tool | Title | Hint | Description |
295+
|---|---|---|---|
296+
| `get_team_memberships` | List Team Memberships | Read | Get all team memberships; supports `take`/`skip` pagination (`take` max 250) and email filtering |
297+
| `get_team_membership` | Get Team Membership | Read | Get a team membership |
298+
| `create_team_membership` | Create Team Membership | Create | Create a team membership (role defaults to `MEMBER`) |
299+
| `update_team_membership` | Update Team Membership | Update | Update a team membership (accepted, role, impersonation) |
300+
| `delete_team_membership` | Delete Team Membership | Destructive | Delete a team membership |
301+
| `create_team_invite` | Create Team Invite | Create | Generate a team invite link |
302+
287303
### API Version Notes
288304

289305
- Default API version: `2024-08-13`

0 commit comments

Comments
 (0)