I'd been looking at MCP implementations for accessing my personal Google data in the various AI tools I've been using. Zapier have an MCP offering that leverages their existing tooling to make bundling and authenticating remote services easy and convenient. However, Zapier looked to prove expensive in two ways.
Firstly, Zapier requires a £24/month subscription to use their service beyond 100 requests per month. That's fine for testing but not for daily integration into the tools I actually use.
The second cost is subtler: context bloat. Zapier's MCP implementation exposes a broad set of generic endpoints, which may not map cleanly to the parameters you actually need to query your data efficiently. When an LLM or agent has to reason over a larger, noisier tool surface to accomplish something as simple as checking today's calendar or retrieving tasks from a specific list, it burns more tokens than necessary. At scale, that adds up.
So I experimented with building a small, purpose-built MCP server. This is less convenient than Zapier in that it requires your own Google OAuth client set up in Google Cloud Console - Zapier abstracts that away with their own client. But once past that hurdle, the implementation is straightforward and you get precise control over what tools are exposed and how they behave.
You can review the implementation here:
Connect MCP Demo
https://github.com/appsoftwareltd/connect-mcp-demo
The server is a Node.js/TypeScript application built on Express. It uses the MCP TypeScript SDK to register tools and handle the MCP protocol, and Kysely as a type-safe query builder against a PostgreSQL database for OAuth token persistence.
Features
- Google Calendar (read-only) - list calendars, list/get/search events
- Google Tasks (read-only) - list task lists, list/get tasks
- Weather - current conditions for any location via the Google Weather and Geocoding APIs
- API key authentication - ID + secret pair protects all endpoints
- OAuth token management - automatic access token refresh, persisted to PostgreSQL
- Idempotent migrations - SQL migration scripts run automatically on startup
Google OAuth
The Google Cloud project requires the Calendar API, Tasks API, Weather API, and Geocoding API enabled. You need two credential types: an OAuth 2.0 client ID and secret (for Calendar and Tasks) and an API key (for Weather and Geocoding).
After configuring those credentials in config.json, authenticate by opening the following URL in a browser:
http://localhost:3000/auth/google?apiKeyId=your-api-key-id&apiKeySecret=your-api-key-secret
You'll be redirected to Google's OAuth consent screen to approve the requested scopes (read-only Calendar and Tasks). Google then redirects back to the configured callback URL on the MCP server, which stores the access and refresh tokens in the database, keyed to the API key ID used to initiate the flow. From that point on, the server handles token refresh automatically - no credential handling required in the LLM client.
Connecting an MCP Client
The server exposes two MCP transport endpoints:
/mcp- Streamable HTTP transport (current standard, recommended)/sse- Legacy SSE transport (for older clients that don't support Streamable HTTP)
For VS Code, add the following to your settings:
{
"mcp": {
"servers": {
"connect-mcp": {
"type": "http",
"url": "http://localhost:3000/mcp?apiKeyId=your-api-key-id&apiKeySecret=your-api-key-secret"
}
}
}
}
Once connected, the MCP client discovers available tools via the standard MCP protocol. The server exposes eight tools:
| Tool | Description | Key Parameters |
|---|---|---|
list_calendars |
List all Google Calendars | - |
list_calendar_events |
List events from a calendar within a time range | calendarId, timeMin, timeMax, maxResults |
get_calendar_event |
Get a single calendar event by ID | calendarId, eventId |
search_calendar_events |
Search calendar events by query string | calendarId, query, timeMin, timeMax |
list_task_lists |
List all Google Task Lists | - |
list_tasks |
List tasks in a task list | taskListId, showCompleted, dueMin, dueMax, maxResults |
get_task |
Get a single task by ID | taskListId, taskId |
get_weather |
Get current weather for a location | location |
The tool set is intentionally minimal - each tool maps directly to a Google API call with only the parameters you actually need. That narrow surface is the whole point: less noise for the LLM means fewer unnecessary tokens spent on reasoning about what to call and how.
Visit the repository at https://github.com/appsoftwareltd/connect-mcp-demo for full setup documentation, Docker deployment notes, and pre-built REST Client request files for testing.