Skip to content

Conversation

@JonasJesus42
Copy link
Contributor

@JonasJesus42 JonasJesus42 commented Jan 5, 2026

  • Add calendar management tools (list, get, create, delete)
  • Add event management tools (list, get, create, update, delete, quick_add)
  • Add availability tool (get_freebusy)
  • Add advanced tools (move_event, find_available_slots, duplicate_event)
  • Implement OAuth 2.0 with PKCE for Google authentication
  • Add Google Calendar API client with full TypeScript types
  • Add google-calendar to monorepo workspaces

Total: 14 tools for complete calendar management


Summary by cubic

Adds a Google Calendar MCP server with OAuth 2.0 (PKCE) and 14 tools for full calendar and event management, availability checks, and advanced operations. Also fixes Google OAuth state/redirect_uri handling and preserves event duration when duplicating with only a new start time.

  • New Features

    • OAuth 2.0 with PKCE for Google authentication.
    • 14 tools: calendars (list/get/create/delete), events (list/get/create/update/delete/quick_add), availability (get_freebusy), advanced (move_event/find_available_slots/duplicate_event).
    • Typed Google Calendar API client and server integration.
    • New workspace with app.json, README, and env setup.
  • Migration

Written for commit ac1272d. Summary will update on new commits.

- Add calendar management tools (list, get, create, delete)
- Add event management tools (list, get, create, update, delete, quick_add)
- Add availability tool (get_freebusy)
- Add advanced tools (move_event, find_available_slots, duplicate_event)
- Implement OAuth 2.0 with PKCE for Google authentication
- Add Google Calendar API client with full TypeScript types
- Add google-calendar to monorepo workspaces

Total: 14 tools for complete calendar management
@github-actions
Copy link

github-actions bot commented Jan 5, 2026

🚀 Preview Deployments Ready!

Your changes have been deployed to preview environments:

📦 google-calendar

🔗 View Preview

These previews will be automatically updated with new commits to this PR.


Deployed from commit: 5464eb0

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 16 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="google-calendar/server/lib/types.ts">

<violation number="1" location="google-calendar/server/lib/types.ts:148">
P2: Inconsistent typing for `accessRole`. This field uses a specific union type in `CalendarListEntry` but a generic `string` here. Consider using the same union type for consistency and better type safety.</violation>
</file>

<file name="google-calendar/server/main.ts">

<violation number="1" location="google-calendar/server/main.ts:42">
P1: Missing `redirect_uri` parameter in token exchange request. Google OAuth requires this to match the authorization request&#39;s redirect_uri. The token exchange will fail without it.</violation>
</file>

<file name="google-calendar/server/tools/advanced.ts">

<violation number="1" location="google-calendar/server/tools/advanced.ts:257">
P1: When `newStart` is provided without `newEnd`, using the original event&#39;s end time directly can create invalid events (end before start) or events with incorrect duration. Consider calculating the new end time by preserving the original event&#39;s duration when only `newStart` is specified.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Google OAuth doesn't allow 'state' inside redirect_uri.
Extract state from callbackUrl and pass it as separate OAuth param.
- Add CalendarAccessRole type for better type safety
- Fix redirect_uri handling in exchangeCode
- Fix getAccessToken type compatibility with Env
Tools need to receive the env parameter to access the authenticated user's access token.
- Add shared/deco.gen.ts with typed Env and MeshRequestContext
- Add server/lib/env.ts with getGoogleAccessToken helper
- Update main.ts to use typed Env from shared/deco.gen.ts
- Update google-client.ts to use env.ts helper
- Fix all numeric schema fields to use z.coerce.number() for string-to-number conversion
When only newStart is provided without newEnd, calculate the new end time
by preserving the original event's duration instead of using the original
end time directly, which could create invalid events.
@JonasJesus42 JonasJesus42 merged commit a63eca1 into main Jan 5, 2026
6 of 10 checks passed
Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 9 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="google-calendar/server/main.ts">

<violation number="1" location="google-calendar/server/main.ts:21">
P0: Critical race condition: `lastRedirectUri` is shared global state that will be overwritten by concurrent OAuth flows. If User A starts auth, then User B starts auth before A finishes, User A&#39;s token exchange will fail because it uses B&#39;s redirect_uri.

Consider using a `Map&lt;string, string&gt;` keyed by the state parameter or code_verifier to store redirect URIs per-flow, or pass the redirect_uri through the OAuth state parameter.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

].join(" ");

// Store the last used redirect_uri for token exchange
let lastRedirectUri: string | null = null;
Copy link

@cubic-dev-ai cubic-dev-ai bot Jan 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0: Critical race condition: lastRedirectUri is shared global state that will be overwritten by concurrent OAuth flows. If User A starts auth, then User B starts auth before A finishes, User A's token exchange will fail because it uses B's redirect_uri.

Consider using a Map<string, string> keyed by the state parameter or code_verifier to store redirect URIs per-flow, or pass the redirect_uri through the OAuth state parameter.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At google-calendar/server/main.ts, line 21:

<comment>Critical race condition: `lastRedirectUri` is shared global state that will be overwritten by concurrent OAuth flows. If User A starts auth, then User B starts auth before A finishes, User A&#39;s token exchange will fail because it uses B&#39;s redirect_uri.

Consider using a `Map&lt;string, string&gt;` keyed by the state parameter or code_verifier to store redirect URIs per-flow, or pass the redirect_uri through the OAuth state parameter.</comment>

<file context>
@@ -4,46 +4,80 @@
 ].join(&quot; &quot;);
 
+// Store the last used redirect_uri for token exchange
+let lastRedirectUri: string | null = null;
+
 const runtime = withRuntime&lt;Env&gt;({
</file context>
Fix with Cubic

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants