/install granola-api
Granola MCP
Access Granola via MCP (Model Context Protocol) with managed authentication.
Quick Start
python \x3C\x3C'EOF'
import urllib.request, os, json
data = json.dumps({'query': 'What action items came from my last meeting?'}).encode()
req = urllib.request.Request('https://gateway.maton.ai/granola/query_granola_meetings', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Base URL
https://gateway.maton.ai/granola/{tool-name}
Replace {tool-name} with the MCP tool name (e.g., query_granola_meetings). The gateway proxies requests to mcp.granola.ai and automatically injects your credentials.
Authentication
All requests require the Maton API key:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Getting Your API Key
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
Connection Management
Manage your Granola MCP connections at https://ctrl.maton.ai.
List Connections
python \x3C\x3C'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections?app=granola&method=MCP&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Create Connection
python \x3C\x3C'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'granola', 'method': 'MCP'}).encode()
req = urllib.request.Request('https://ctrl.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Get Connection
python \x3C\x3C'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "8a413c45-6427-45d9-b69d-8118ce62ffce",
"status": "PENDING",
"creation_time": "2026-02-24T11:34:46.204677Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "granola",
"method": "MCP",
"metadata": {}
}
}
Open the returned url in a browser to complete OAuth authorization.
Delete Connection
python \x3C\x3C'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Specifying Connection
If you have multiple Granola connections, you must specify which MCP connection to use with the Maton-Connection header:
python \x3C\x3C'EOF'
import urllib.request, os, json
data = json.dumps({'query': 'What were my action items?'}).encode()
req = urllib.request.Request('https://gateway.maton.ai/granola/query_granola_meetings', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('Maton-Connection', '8a413c45-6427-45d9-b69d-8118ce62ffce')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
IMPORTANT: If omitted, the gateway uses the default (oldest) active connection, which may fail if it's not an MCP connection.
MCP Reference
All MCP tools use POST method:
| Tool | Description | Schema |
|---|---|---|
query_granola_meetings |
Chat with meeting notes using natural language | schema |
list_meetings |
List meetings with metadata and attendees | schema |
get_meetings |
Retrieve detailed content for specific meetings | schema |
get_meeting_transcript |
Get raw transcript (paid tiers only) | schema |
Query Meetings
Chat with your meeting notes using natural language queries:
POST /granola/query_granola_meetings
Content-Type: application/json
{
"query": "What action items came from my meetings this week?"
}
Response:
{
"content": [
{
"type": "text",
"text": "You had 2 recent meetings:\
**Feb 4, 2026 at 7:30 PM** - \"Team sync\" [[0]](https://notes.granola.ai/d/abc123)\
- Action item: Review Q1 roadmap\
- Action item: Schedule follow-up with engineering\
**Jan 27, 2026 at 1:04 AM** - \"Finance integration\" [[1]](https://notes.granola.ai/d/def456)\
- Discussed workflow automation platforms\
- Action item: Evaluate n8n vs Zapier"
}
],
"isError": false
}
Use cases:
- "What action items were assigned to me?"
- "Summarize my meetings from last week"
- "What did we discuss about the product launch?"
- "Find all mentions of budget in my meetings"
List Meetings
List your meetings with metadata including IDs, titles, dates, and attendees:
POST /granola/list_meetings
Content-Type: application/json
{}
Response:
{
"content": [
{
"type": "text",
"text": "\x3Cmeetings_data from=\"Jan 27, 2026\" to=\"Feb 4, 2026\" count=\"2\">\
\x3Cmeeting id=\"0dba4400-50f1-4262-9ac7-89cd27b79371\" title=\"Team sync\" date=\"Feb 4, 2026 7:30 PM\">\
\x3Cknown_participants>\
John Doe (note creator) from Acme \[email protected]>\
Jane Smith from Acme \[email protected]>\
\x3C/known_participants>\
\x3C/meeting>\
\
\x3Cmeeting id=\"4ebc086f-ba8d-49e8-8cd1-ed81ac8f2e3b\" title=\"Finance integration\" date=\"Jan 27, 2026 1:04 AM\">\
\x3Cknown_participants>\
John Doe (note creator) from Acme \[email protected]>\
\x3C/known_participants>\
\x3C/meeting>\
\x3C/meetings_data>"
}
],
"isError": false
}
Response fields in XML format:
meetings_data: Container withfrom,todate range andcountmeeting: Individual meeting withid,title, anddateattributesknown_participants: List of attendees with name, role, company, and email
Get Meetings
Retrieve detailed content for specific meetings by ID:
POST /granola/get_meetings
Content-Type: application/json
{
"meeting_ids": ["0dba4400-50f1-4262-9ac7-89cd27b79371"]
}
Response:
{
"content": [
{
"type": "text",
"text": "\x3Cmeetings_data from=\"Feb 4, 2026\" to=\"Feb 4, 2026\" count=\"1\">\
\x3Cmeeting id=\"0dba4400-50f1-4262-9ac7-89cd27b79371\" title=\"Team sync\" date=\"Feb 4, 2026 7:30 PM\">\
\x3Cknown_participants>\
John Doe (note creator) from Acme \[email protected]>\
\x3C/known_participants>\
\
\x3Csummary>\
## Key Decisions\
- Approved Q1 roadmap\
- Budget increased by 15%\
\
## Action Items\
- @john: Review design specs by Friday\
- @jane: Schedule engineering sync\
\x3C/summary>\
\x3C/meeting>\
\x3C/meetings_data>"
}
],
"isError": false
}
Response includes:
- Meeting metadata (id, title, date, participants)
summary: AI-generated meeting summary with key decisions and action items- Enhanced notes and private notes (when available)
Get Meeting Transcript
Retrieve the raw transcript for a specific meeting (paid tiers only):
POST /granola/get_meeting_transcript
Content-Type: application/json
{
"meeting_id": "0dba4400-50f1-4262-9ac7-89cd27b79371"
}
Response (paid tier):
{
"content": [
{
"type": "text",
"text": "\x3Ctranscript meeting_id=\"0dba4400-50f1-4262-9ac7-89cd27b79371\">\
[00:00:15] John: Let's get started with the Q1 planning...\
[00:01:23] Jane: I've prepared the budget breakdown...\
[00:03:45] John: That looks good. What about the timeline?\
\x3C/transcript>"
}
],
"isError": false
}
Response (free tier):
{
"content": [
{
"type": "text",
"text": "Transcripts are only available to paid Granola tiers"
}
],
"isError": true
}
Code Examples
JavaScript
const response = await fetch('https://gateway.maton.ai/granola/query_granola_meetings', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
},
body: JSON.stringify({
query: 'What were the action items from my last meeting?'
})
});
const data = await response.json();
console.log(data.content[0].text);
Python
import os
import requests
# Query meeting notes
response = requests.post(
'https://gateway.maton.ai/granola/query_granola_meetings',
headers={
'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
'Content-Type': 'application/json'
},
json={
'query': 'What were the action items from my last meeting?'
}
)
print(response.json())
Error Handling
| Status | Meaning |
|---|---|
| 400 | Missing Granola connection |
| 401 | Invalid or missing Maton API key |
| 429 | Rate limited (approx 100 req/min) |
Troubleshooting: API Key Issues
- Check that the
MATON_API_KEYenvironment variable is set:
echo $MATON_API_KEY
- Verify the API key is valid by listing connections:
python \x3C\x3C'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://ctrl.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Troubleshooting: Invalid App Name
- Ensure your URL path starts with
granola. For example:
- Correct:
https://gateway.maton.ai/granola/query_granola_meetings - Incorrect:
https://gateway.maton.ai/query_granola_meetings
Troubleshooting: MCP Parameter Errors
MCP tools return validation errors when required parameters are missing:
{
"content": [
{
"type": "text",
"text": "MCP error -32602: Input validation error: Invalid arguments for tool get_meetings: [\
{\
\"code\": \"invalid_type\",\
\"expected\": \"array\",\
\"received\": \"undefined\",\
\"path\": [\"meeting_ids\"],\
\"message\": \"Required\"\
}\
]"
}
],
"isError": true
}
Notes
- All IDs are UUIDs (with or without hyphens)
- MCP tool responses wrap content in
{"content": [{"type": "text", "text": "..."}], "isError": false}format - Users can only query their own meeting notes; shared notes from others are not accessible
- Basic (free) plan users are limited to notes from the last 30 days
- The
get_meeting_transcripttool is only available on paid Granola tiers
Resources
- 确保已安装 OpenClaw(本地或 Docker 部署)
- 在对话框中输入安装命令:
/install granola-api - 安装完成后,直接呼叫该 Skill 的名称或使用
/granola-api触发 - 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
Granola 是什么?
Granola MCP integration with managed authentication. Use this skill when users want to search meeting content, get meeting summaries, find action items, or r... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 467 次。
如何安装 Granola?
在 OpenClaw 或 Claude Code 对话框中运行命令「/install granola-api」即可一键安装,无需额外配置。
Granola 是免费的吗?
是的,Granola 完全免费(开源免费),可自由下载、安装和使用。
Granola 支持哪些平台?
Granola 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。
谁开发了 Granola?
由 byungkyu(@byungkyu)开发并维护,当前版本 v1.0.1。