Skip to content

CarterMcAlister/granola-hosted-mcp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Granola MCP Server

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.

Features

  • 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

Available Tools

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)

Prerequisites

  • Railway account (for hosting)
  • Granola account with meeting notes
  • Claude Pro/Teams subscription or Claude Desktop

Deployment

1. Deploy to Railway

Option A: One-Click Deploy

Deploy on Railway

Option B: Manual Deploy

  1. Fork this repository to your GitHub account
  2. Create a new project in Railway
  3. Click "Deploy from GitHub repo" and select your fork
  4. Add a PostgreSQL database to your project:
    • Click "+ New""Database""PostgreSQL"
  5. Railway will automatically:
    • Detect the Dockerfile and railway.toml configuration
    • Set the DATABASE_URL environment variable
    • Deploy and start the server

2. Configure Environment Variables

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=false

Note: DATABASE_URL and PORT are automatically set by Railway. All other variables have sensible defaults.

3. Get Your Server URL

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.


Setup with Claude Teams

Claude Teams allows administrators to configure MCP integrations for the entire organization.

Step 1: Access Team Settings

  1. Go to claude.ai and sign in with your Teams account
  2. Click your profile icon in the bottom-left corner
  3. Select "Settings"
  4. Navigate to "Team settings" (requires admin permissions)

Step 2: Add the MCP Integration

  1. In Team settings, find "Integrations" in the sidebar
  2. Click "Add integration" or "Connect MCP server"
  3. Enter the following details:
Field Value
Name Granola Meeting Notes
Server URL https://your-railway-url.up.railway.app/mcp
Authentication OAuth 2.0
  1. Click "Save" or "Add"

Step 3: Enable for Team Members

  1. Toggle the integration to "Enabled"
  2. Optionally configure which team members have access
  3. Team members will see the integration in their Claude interface

Step 4: Authenticate (Each Team Member)

When a team member first uses the Granola integration:

  1. Claude will prompt them to "Connect to Granola Meeting Notes"
  2. Click the authentication link
  3. On the auth page, click "Sign in with Google"
  4. Complete the Google sign-in flow (use the same account as Granola)
  5. Important: After Google sign-in, you'll see a page that says "Open Granola?"
  6. Copy the URL from your browser's address bar (starts with granola://)
  7. Paste the URL into the form on the auth page
  8. Click "Complete Authentication"
  9. Return to Claude - you're now connected!

Setup with Claude Individual (Pro)

Individual Claude Pro users can add MCP servers to their personal account.

Step 1: Access Settings

  1. Go to claude.ai and sign in
  2. Click your profile icon in the bottom-left corner
  3. Select "Settings"

Step 2: Add MCP Integration

  1. Navigate to "Integrations" or "Connected apps"
  2. Click "Add integration" or "Add MCP server"
  3. Enter the server details:
Field Value
Name Granola Meeting Notes
URL https://your-railway-url.up.railway.app/mcp
  1. Click "Connect" or "Add"

Step 3: Authenticate

  1. You'll be redirected to the authentication page
  2. Click "Sign in with Google"
  3. Complete the Google sign-in (use your Granola account)
  4. When you see "Open Granola?", copy the URL from your browser address bar
  5. Paste the URL into the form and click "Complete Authentication"
  6. Return to Claude - your integration should show as "Connected"

Step 4: Verify Connection

Try asking Claude:

"What meetings do I have today?"

or

"Show me my recent meetings"


Setup with Claude Desktop

For the Claude Desktop application:

macOS / Windows

  1. Open Claude Desktop
  2. Go to Settings (gear icon) → DeveloperEdit Config
  3. Add the following to your claude_desktop_config.json:
{
  "mcpServers": {
    "granola": {
      "url": "https://your-railway-url.up.railway.app/mcp",
      "transport": "http"
    }
  }
}
  1. Save the file and restart Claude Desktop
  2. On first use, you'll be prompted to authenticate

Config File Locations

Platform Path
macOS ~/Library/Application Support/Claude/claude_desktop_config.json
Windows %APPDATA%\Claude\claude_desktop_config.json

Setup with Claude Code (CLI)

For Claude Code users:

Add to MCP Settings

# Open Claude Code settings
claude mcp add granola --url https://your-railway-url.up.railway.app/mcp

Or manually edit your settings file:

{
  "mcpServers": {
    "granola": {
      "url": "https://your-railway-url.up.railway.app/mcp"
    }
  }
}

Usage Examples

Once connected, you can ask Claude questions like:

Daily Summaries

  • "What meetings did I have today?"
  • "Give me a summary of yesterday's meetings"
  • "What's on my calendar this week?"

Searching Meetings

  • "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"

Action Items & Follow-ups

  • "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"

Specific Meetings

  • "Get the full summary of meeting [document_id]"
  • "What was discussed in my most recent meeting?"

Local Development

Prerequisites

  • Bun runtime (v1.0+)
  • PostgreSQL database (local or cloud)

Setup

# 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 dev

The server will start at http://localhost:3000.

Available Scripts

Script Description
bun run dev Start development server with watch mode
bun run start Start production server
bun run db:init Initialize database schema

API Endpoints

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

Debug Endpoints

# 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"

Troubleshooting

Authentication Issues

"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 Issues

"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 Results

"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

Deployment Issues

Railway deployment fails

  • Ensure PostgreSQL addon is provisioned
  • Check that DATABASE_URL is 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 /mcp suffix

Claude Integration Issues

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

Security

  • 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)

Architecture

┌─────────────────┐     ┌──────────────────────┐     ┌─────────────────┐
│                 │     │                      │     │                 │
│  Claude         │────▶│  Granola MCP Server  │────▶│  Granola API    │
│  (Web/Desktop/  │◀────│  (Railway)           │◀────│  (WorkOS OAuth) │
│   Code)         │     │                      │     │                 │
│                 │     │  ┌────────────────┐  │     └─────────────────┘
└─────────────────┘     │  │  PostgreSQL    │  │
                        │  │  - Sessions    │  │
                        │  │  - Auth codes  │  │
                        │  │  - Cache       │  │
                        │  └────────────────┘  │
                        └──────────────────────┘

How It Works

  1. User initiates connection in Claude
  2. OAuth flow authenticates user with their Granola/Google account
  3. Tokens stored securely in PostgreSQL
  4. MCP tools call Granola API on user's behalf
  5. Auto-refresh keeps tokens valid without re-authentication

Environment Variables Reference

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

License

MIT License - See LICENSE for details.


Disclaimer

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.

About

A hosted MCP server that provides Claude and other MCP clients with access to your Granola meeting notes

Topics

Resources

License

Stars

Watchers

Forks

Contributors