An MCP (Model Context Protocol) server that wraps the Granola API, providing tools to search and retrieve meeting notes and documents.
- Unified Search: Search meeting notes by participant, time range, or topic in a single tool
- Full Document Retrieval: Fetch complete meeting notes in Markdown format
- List Document Collections: View all document lists and their metadata
- Ruby 3.0 or higher
- A Granola account with API access
- Your Granola Bearer token
- Clone this repository:
git clone <repository-url>
cd granola-mcp- Install dependencies:
bundle install- Copy the example environment file:
cp .env.example .env- Edit
.envand add your Granola Bearer token:
GRANOLA_BEARER_TOKEN=your-bearer-token-here
Alternatively, you can export it as an environment variable:
export GRANOLA_BEARER_TOKEN="your-bearer-token-here"ruby granola_mcp_server.rbOr make it executable:
chmod +x granola_mcp_server.rb
./granola_mcp_server.rbSearch for meeting notes using multiple criteria. You can search by participant, date range, topic, or any combination of these.
Parameters:
participant(optional): Name or email of participant to search forstart_date(optional): Start date in ISO format (YYYY-MM-DD)end_date(optional): End date in ISO format (YYYY-MM-DD)topic(optional): Topic or keywords to search forsearch_content(optional): Whether to search in document content (slower) or just titles (default: false)limit(optional): Maximum number of results to return (default: 20)
Note: At least one search criterion must be provided. If using date range, both start_date and end_date are required.
Example searches:
- Find all meetings with a specific person
- Find meetings within a date range
- Find meetings about a specific topic
- Combine criteria to narrow results
Retrieve the full content of a specific meeting note in Markdown format.
Parameters:
document_id(required): The ID of the document to fetch
Returns a complete Markdown representation including:
- Meeting title and date
- Participants list
- Meeting summary
- Full notes content with proper formatting
Retrieve all document collections/lists.
No parameters required.
Returns metadata for each list including:
- List ID and title
- Document count
- Visibility settings
- Member information
- Timestamps
All tools return responses in this format:
{
"success": true,
"count": 5,
"documents": [
{
"id": "document-uuid",
"title": "Meeting Title",
"date": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T11:30:00Z",
"participants": [
{
"name": "John Doe",
"email": "[email protected]",
"role": "creator"
}
],
"preview": "Meeting notes preview..."
}
]
}{
"success": true,
"document": {
"id": "document-uuid",
"title": "Meeting Title",
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-01-15T11:30:00Z",
"content_markdown": "# Meeting Title\n\n**Date:** January 15, 2025...\n\n## Participants\n\n..."
}
}To use this server with an MCP client, add it to your MCP settings:
{
"mcpServers": {
"granola": {
"command": "ruby",
"args": ["/path/to/granola_mcp_server.rb"],
"env": {
"GRANOLA_BEARER_TOKEN": "your-bearer-token"
}
}
}
}The server handles common errors:
- Missing bearer token
- API request failures
- Invalid date formats
- Document not found errors
- Rate limiting
Errors are returned in this format:
{
"success": false,
"error": "Error message"
}To add a new tool, create a new class inheriting from FastMcp::Tool:
class MyNewTool < FastMcp::Tool
description "Tool description"
arguments do
required(:param_name).filled(:string).description("Parameter description")
optional(:optional_param).filled(:integer).description("Optional parameter")
end
def call(param_name:, optional_param: nil)
# Tool implementation
end
end
# Register it in the server setup
server.register_tool(MyNewTool)MIT License