A hosted Model Context Protocol (MCP) server that provides Claude and other MCP clients with access to your Granola meeting notes. Deploy once to Railway, and access your meeting notes from any Claude interface.
- OAuth Authentication - Secure authentication via your existing Granola/Google account with PKCE support
- 6 MCP Tools - Search, retrieve, and summarize your meeting notes
- Hosted Solution - Deploy to Railway and access from anywhere (no local server needed)
- Automatic Token Refresh - Tokens stay fresh with proactive refresh before expiry
- Optional Caching - PostgreSQL-based summary caching for improved performance
| Tool | Description |
|---|---|
get_all_meetings |
Get your most recent meetings with summaries (default: 20, max: 50) |
get_meeting_by_id |
Fetch a specific meeting by document ID |
get_recent_meetings |
Get meetings from the last N days |
search_meetings |
Search meetings by keyword (case-insensitive) |
get_document_summary |
Get the full rendered summary for a meeting |
get_todays_meetings |
Get all meetings scheduled for today (UTC) |
- Railway account (for hosting)
- Granola account with meeting notes
- Claude Pro/Teams subscription or Claude Desktop
Option A: One-Click Deploy
Option B: Manual Deploy
- Fork this repository to your GitHub account
- Create a new project in Railway
- Click "Deploy from GitHub repo" and select your fork
- Add a PostgreSQL database to your project:
- Click "+ New" → "Database" → "PostgreSQL"
- Railway will automatically:
- Detect the Dockerfile and
railway.tomlconfiguration - Set the
DATABASE_URLenvironment variable - Deploy and start the server
- Detect the Dockerfile and
In your Railway project, go to Variables and verify/add these environment variables:
# Required - WorkOS OAuth (from Granola app - defaults are included)
WORKOS_CLIENT_ID=client_01J8RYEJB3D8N2C3J9H5QB7SZ5
WORKOS_AUTH_URL=https://api.workos.com/user_management/authorize
WORKOS_TOKEN_URL=https://api.workos.com/user_management/authenticate
WORKOS_REFRESH_URL=https://api.workos.com/user_management/authenticate
# Required - Granola API endpoints (defaults included)
GRANOLA_REDIRECT_URI=granola://
GRANOLA_API_URL=https://api.granola.ai
GRANOLA_NOTES_URL=https://notes.granola.ai
# Optional - Performance
ENABLE_SUMMARY_CACHE=falseNote:
DATABASE_URLandPORTare automatically set by Railway. All other variables have sensible defaults.
After deployment completes, click on your service and find the public URL:
https://granola-mcp-production-xxxx.up.railway.app
Save this URL - you'll need it to configure Claude.
Claude Teams allows administrators to configure MCP integrations for the entire organization.
- Go to claude.ai and sign in with your Teams account
- Click your profile icon in the bottom-left corner
- Select "Settings"
- Navigate to "Team settings" (requires admin permissions)
- In Team settings, find "Integrations" in the sidebar
- Click "Add integration" or "Connect MCP server"
- Enter the following details:
| Field | Value |
|---|---|
| Name | Granola Meeting Notes |
| Server URL | https://your-railway-url.up.railway.app/mcp |
| Authentication | OAuth 2.0 |
- Click "Save" or "Add"
- Toggle the integration to "Enabled"
- Optionally configure which team members have access
- Team members will see the integration in their Claude interface
When a team member first uses the Granola integration:
- Claude will prompt them to "Connect to Granola Meeting Notes"
- Click the authentication link
- On the auth page, click "Sign in with Google"
- Complete the Google sign-in flow (use the same account as Granola)
- Important: After Google sign-in, you'll see a page that says "Open Granola?"
- Copy the URL from your browser's address bar (starts with
granola://) - Paste the URL into the form on the auth page
- Click "Complete Authentication"
- Return to Claude - you're now connected!
Individual Claude Pro users can add MCP servers to their personal account.
- Go to claude.ai and sign in
- Click your profile icon in the bottom-left corner
- Select "Settings"
- Navigate to "Integrations" or "Connected apps"
- Click "Add integration" or "Add MCP server"
- Enter the server details:
| Field | Value |
|---|---|
| Name | Granola Meeting Notes |
| URL | https://your-railway-url.up.railway.app/mcp |
- Click "Connect" or "Add"
- You'll be redirected to the authentication page
- Click "Sign in with Google"
- Complete the Google sign-in (use your Granola account)
- When you see "Open Granola?", copy the URL from your browser address bar
- Paste the URL into the form and click "Complete Authentication"
- Return to Claude - your integration should show as "Connected"
Try asking Claude:
"What meetings do I have today?"
or
"Show me my recent meetings"
For the Claude Desktop application:
- Open Claude Desktop
- Go to Settings (gear icon) → Developer → Edit Config
- Add the following to your
claude_desktop_config.json:
{
"mcpServers": {
"granola": {
"url": "https://your-railway-url.up.railway.app/mcp",
"transport": "http"
}
}
}- Save the file and restart Claude Desktop
- On first use, you'll be prompted to authenticate
| Platform | Path |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
For Claude Code users:
# Open Claude Code settings
claude mcp add granola --url https://your-railway-url.up.railway.app/mcpOr manually edit your settings file:
{
"mcpServers": {
"granola": {
"url": "https://your-railway-url.up.railway.app/mcp"
}
}
}Once connected, you can ask Claude questions like:
- "What meetings did I have today?"
- "Give me a summary of yesterday's meetings"
- "What's on my calendar this week?"
- "Search my meetings for discussions about the product roadmap"
- "Find all meetings where we discussed the Q4 budget"
- "Look for meetings with the engineering team"
- "What action items came out of my meeting with the design team?"
- "What did we decide in the last standup?"
- "Summarize the key decisions from my 1:1 with Sarah"
- "Get the full summary of meeting [document_id]"
- "What was discussed in my most recent meeting?"
- Bun runtime (v1.0+)
- PostgreSQL database (local or cloud)
# Clone the repository
git clone https://github.com/your-username/granola-hosted-mcp.git
cd granola-hosted-mcp
# Install dependencies
bun install
# Copy environment template
cp .env.example .env
# Edit .env with your DATABASE_URL
# Example: DATABASE_URL=postgresql://user:pass@localhost:5432/granola_mcp
# Initialize the database schema
bun run db:init
# Start development server with hot reload
bun run devThe server will start at http://localhost:3000.
| Script | Description |
|---|---|
bun run dev |
Start development server with watch mode |
bun run start |
Start production server |
bun run db:init |
Initialize database schema |
| Endpoint | Method | Description |
|---|---|---|
/health |
GET | Health check (database connectivity) |
/mcp |
POST | MCP JSON-RPC endpoint (requires Bearer token) |
/authorize |
GET | OAuth authorization UI |
/complete-auth |
POST | Handle OAuth callback |
/token |
POST | Token exchange endpoint (PKCE) |
/register |
POST | Dynamic client registration |
/.well-known/oauth-authorization-server |
GET | OAuth server metadata |
/.well-known/oauth-protected-resource |
GET | Protected resource metadata |
# Health check
curl https://your-app.up.railway.app/health
# Check token status (requires authentication)
curl -H "Authorization: Bearer SESSION_ID" \
https://your-app.up.railway.app/debug/test-refresh
# Force token refresh
curl -H "Authorization: Bearer SESSION_ID" \
"https://your-app.up.railway.app/debug/test-refresh?force=true""Authentication Failed" or "Invalid Credentials"
- Ensure you're signed into Granola in your browser before starting OAuth
- Use the same Google account that's linked to your Granola account
- Try clearing browser cookies and signing into Granola fresh
"Could not extract code from URL"
- Make sure you're copying the complete URL (should start with
granola://) - Don't copy just the page content - copy from the browser's address bar
- The URL should contain a
code=parameter
"Token Expired" or "Unauthorized" errors
- The server auto-refreshes tokens, but if issues persist:
- Disconnect and reconnect the integration
- Check token status at
/debug/test-refresh - Review Railway logs for refresh errors
"Session not found"
- Your session may have been cleaned up
- Re-authenticate by reconnecting the integration
"No meetings found"
- Verify you have meetings in your Granola account
- Check the date range (default searches recent meetings)
- Try a broader search keyword
- Ensure meetings have been processed by Granola
Railway deployment fails
- Ensure PostgreSQL addon is provisioned
- Check that
DATABASE_URLis set in variables - Review deployment logs for specific errors
"Connection refused" or server unreachable
- Verify the Railway deployment is running (green status)
- Test the health endpoint:
https://your-url.up.railway.app/health - Make sure you're using the correct URL with
/mcpsuffix
Integration not appearing
- Refresh the Claude page
- Check that the server URL is correct (including
/mcp) - Verify the server is running (health check)
"Tool not found" errors
- Ensure the MCP server is properly connected
- Try disconnecting and reconnecting the integration
- OAuth 2.0 with PKCE - Secure authorization code flow for public clients
- PostgreSQL token storage - Credentials stored securely, not in memory
- Automatic token cleanup - Expired tokens removed every 5 minutes
- Read-only API access - Only reads meeting data, no write operations
- SSL/TLS encryption - All traffic encrypted in production (Railway)
┌─────────────────┐ ┌──────────────────────┐ ┌─────────────────┐
│ │ │ │ │ │
│ Claude │────▶│ Granola MCP Server │────▶│ Granola API │
│ (Web/Desktop/ │◀────│ (Railway) │◀────│ (WorkOS OAuth) │
│ Code) │ │ │ │ │
│ │ │ ┌────────────────┐ │ └─────────────────┘
└─────────────────┘ │ │ PostgreSQL │ │
│ │ - Sessions │ │
│ │ - Auth codes │ │
│ │ - Cache │ │
│ └────────────────┘ │
└──────────────────────┘
- User initiates connection in Claude
- OAuth flow authenticates user with their Granola/Google account
- Tokens stored securely in PostgreSQL
- MCP tools call Granola API on user's behalf
- Auto-refresh keeps tokens valid without re-authentication
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL |
Yes | (Railway auto) | PostgreSQL connection string |
PORT |
No | 3000 |
Server port |
NODE_ENV |
No | development |
Environment mode |
WORKOS_CLIENT_ID |
No | (included) | WorkOS OAuth client ID |
WORKOS_AUTH_URL |
No | (included) | WorkOS authorization URL |
WORKOS_TOKEN_URL |
No | (included) | WorkOS token endpoint |
WORKOS_REFRESH_URL |
No | (included) | WorkOS refresh endpoint |
GRANOLA_REDIRECT_URI |
No | granola:// |
OAuth redirect URI |
GRANOLA_API_URL |
No | https://api.granola.ai |
Granola API base URL |
GRANOLA_NOTES_URL |
No | https://notes.granola.ai |
Granola notes URL |
ENABLE_SUMMARY_CACHE |
No | false |
Enable PostgreSQL summary caching |
MIT License - See LICENSE for details.
This project is not affiliated with Granola. It uses reverse-engineered API endpoints from the Granola Electron app (v6.267.0). Use at your own discretion. The API may change without notice.