The Granola MCP connector routes your AI agent's tool calls to Granola's own MCP server through Scalekit. Each user signs in to Granola once, and Scalekit stores and refreshes their tokens, so your agent never handles credentials. It comes with 12 tools.
- Tools
- 12
- What they doRead · write · destructive
- 7 · 4 · 17 read4 write1 destructive
- Users sign in with
- OAuth
- OAuth app
- Scalekit's or your own
What you can do
- Ask about meetings: answer plain-language questions on discussions, decisions, and action items, with links to source notes
- List meetings: find meeting notes by time range, folder, or whether the user took part
- Read meeting notes: fetch private notes, AI summaries, attendees, and details for specific meetings
- Get transcripts: retrieve the verbatim transcript of a meeting for exact quotes and wording
- Browse folders: list meeting folders with their descriptions and note counts
Setup
Install the SDK
Terminal window npm install @scalekit-sdk/node dotenvTerminal window pip install scalekit-sdk-python python-dotenvSet your credentials
Add your Scalekit credentials to your
.envfile. Find values in app.scalekit.com > Developers > API Credentials..env SCALEKIT_ENVIRONMENT_URL=<your-environment-url>SCALEKIT_CLIENT_ID=<your-client-id>SCALEKIT_CLIENT_SECRET=<your-client-secret>Create the Granola MCP connection
In AgentKit > Connections, create a Granola MCP connection. The name you give it is the
connection_nameyour code passes. See Configure connections.Scalekit credentials are available for Granola MCP server, so you don't need to register an OAuth app.
Authorize a user and make your first call
quickstart.mts import { ScalekitClient } from '@scalekit-sdk/node'import 'dotenv/config'import { createInterface } from 'node:readline/promises'const scalekit = new ScalekitClient(process.env.SCALEKIT_ENVIRONMENT_URL,process.env.SCALEKIT_CLIENT_ID,process.env.SCALEKIT_CLIENT_SECRET,)const actions = scalekit.actionsconst connector = 'granolamcp'const identifier = 'user_123'// Generate an authorization link for the userconst { link } = await actions.getAuthorizationLink({ connectionName: connector, identifier })console.log('Authorize Granola MCP:', link)const rl = createInterface({ input: process.stdin, output: process.stdout })await rl.question('Press Enter after authorizing...')rl.close()// Make your first callconst result = await actions.executeTool({connector,identifier,toolName: 'granolamcp_get_account_info',toolInput: {},})console.log(result)Terminal window npx tsx quickstart.mtsquickstart.py import osfrom scalekit import ScalekitClientfrom dotenv import load_dotenvload_dotenv()scalekit_client = ScalekitClient(env_url=os.getenv("SCALEKIT_ENVIRONMENT_URL"),client_id=os.getenv("SCALEKIT_CLIENT_ID"),client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"),)actions = scalekit_client.actionsconnection_name = "granolamcp"identifier = "user_123"# Generate an authorization link for the userlink_response = actions.get_authorization_link(connection_name=connection_name,identifier=identifier,)print("Authorize Granola MCP:", link_response.link)input("Press Enter after authorizing...")# Make your first callresult = actions.execute_tool(tool_input={},tool_name="granolamcp_get_account_info",connection_name=connection_name,identifier=identifier,)print(result)Terminal window python quickstart.pyEach user signs in once. See Authorize a user for the full flow and statuses.
Tools
Pass the exact name toexecute_toolgranolamcp_get_account_infoGet the email, active workspace, and effective note-access scopes for the Granola account currently connected to this MCP session.Read-onlyGranola: Get Account Info
Get the email, active workspace, and effective note-access scopes for the Granola account currently connected to this MCP session. When to use: - User asks 'who am I signed in as?', 'which Granola account is this?', or 'what's my email?' - User suspects they connected the wrong Granola account - Meeting results may be incomplete or empty because of the user's Granola plan or workspace MCP access controls - Before performing actions, to confirm identity if the user references a specific account When scope-based access controls are active, mcp_note_access.scopes contains the note categories this connection can search: - personal: notes the connected user owns, notes shared directly with them, and notes accessible through private folders - public: notes accessible through workspace-visible Team Space folders - Both scopes means both categories can be searched. These scopes describe access, not who captured or participated in a meeting.
Inputs
This tool takes no inputs.
granolamcp_get_meeting_attachmentGet up to 5 meeting attachments, such as screenshots of shared screens, as images in request order.Read-onlyGet Meeting Attachment
Get up to 5 meeting attachments, such as screenshots of shared screens, as images in request order. Provide attachment_ids for a batch or attachment_id for one image. Each image is followed by its metadata; failed attachments return an error with their ID without discarding successful images. A response holds about 6 MB of images, so a batch of large screenshots may leave some out; each one left out returns an error with its ID, so request it again in a separate call. Attachment IDs come from the <attachments> section of get_meetings results. Use this when the description alone does not answer the user's question, for example to read a slide, chart, or code on screen.
Inputs
attachment_idstring- Single attachment ID. Provide exactly one of attachment_id or attachment_ids.
attachment_idsarray- Attachment IDs from the <attachment id="..."> tags in get_meetings results. Provide exactly one of attachment_id or attachment_ids.
meeting_idstring- Meeting UUID or public note ID (not_â¦).
note_idstring- Alias for meeting_id. If both are provided, they must refer to the same note (UUID and public note ID may differ).
granolamcp_get_meeting_transcriptGet the full transcript for a specific Granola meeting by ID.Read-onlyGranola: Get Meeting Transcript
Get the full transcript for a specific Granola meeting by ID. Returns only the verbatim transcript content, not summaries or notes. Use this when the user needs exact quotes, specific wording, or wants to review what was literally said in a meeting. For summarized content or action items, use query_granola_meetings or list_meetings/get_meetings instead.
Inputs
meeting_idstringrequired- Meeting UUID or public note ID (not_â¦).
max_charsinteger- Maximum transcript characters to return, cut at the last utterance that fits. Defaults to 40000, up to 80000. Lower it if responses exceed your output limit.
note_idstring- Alias for meeting_id. If both are provided, they must refer to the same note (UUID and public note ID may differ).
offsetinteger- Character offset to start reading from. Use next_offset from a previous truncated response. Defaults to 0.
granolamcp_get_meetingsGet detailed meeting information for one or more Granola meetings by ID.Read-onlyGranola: Get Meetings
Get detailed meeting information for one or more Granola meetings by ID. Returns private notes, AI-generated summary, attendees, and metadata. Use this when you already have specific meeting IDs (e.g. from list_meetings results). For open-ended questions about meeting content, use query_granola_meetings instead.
Inputs
meeting_idsarrayrequired- Meeting UUIDs or public note IDs (max 10).
note_idsarray- Alias for meeting_ids. If both are provided, they must refer to the same set of notes; order, duplicates, and UUID/public ID format may differ.
granolamcp_list_meeting_foldersList the user's Granola meeting folders.Read-onlyGranola: List Meeting Folders
List the user's Granola meeting folders. Returns folder ID, title, description, and note count including nested folders. When to use: - User asks about their folders or wants to browse meetings by folder - User wants to narrow down meeting searches to a specific folder Use the returned folder IDs with list_meetings (folder_id parameter) to list meetings within a specific folder.
Inputs
limitinteger- Maximum folders to return. Defaults to 100.
offsetinteger- Number of folders to skip. Use next_offset from a previous truncated response. Defaults to 0.
granolamcp_list_meetingsList the user's Granola meeting notes within a time range.Read-onlyGranola: List Meetings
List the user's Granola meeting notes within a time range. Returns meeting titles and metadata. IMPORTANT: For short-term questions about recent meeting details, prefer using query_granola_meetings instead. When to use: - User asks to list their meetings - User asks about action items, decisions, or summaries from meetings over a longer or specific date range - User asks about content from their meeting transcripts - User references 'Granola notes' or 'meeting notes' or 'transcripts' When NOT to use: - User is asking about upcoming calendar events or scheduling - User wants to create/modify calendar invites Filtering: - Omit workspace_only and involvement to return every meeting the user is allowed to access - For 'my meetings' or meetings the user was involved in, set both involvement conditions to true; true conditions combine using OR - Set captured_by_me to true for meetings whose Granola notes the user captured, or false to exclude them - Set listed_as_participant to true for meetings where the user is a known participant, or false to exclude them - False involvement conditions are exclusions and combine with the positive conditions using AND; omit a condition to ignore it - For Team Space or public workspace meetings, set workspace_only to true - workspace_only and involvement combine using AND Use get_meetings to retrieve detailed meeting content after identifying relevant meetings. Use list_meeting_folders to discover folder IDs, then pass a folder_id to list meetings within a specific folder.
Inputs
custom_endstring- ISO date for custom range end (required if time_range is 'custom'). Prefer YYYY-MM-DD to include the whole final day in the user's stored timezone (UTC if unavailable). Times without an offset use that timezone; an explicit Z means UTC and explicit offsets are respected. Do not append Z to a local time.
custom_startstring- ISO date for custom range start (required if time_range is 'custom'). Prefer YYYY-MM-DD for whole-day requests; dates and times without an offset use the user's stored timezone (UTC if unavailable). An explicit Z means UTC; explicit offsets are respected. Do not append Z to a local time.
folder_idstring- Optional folder ID to list meetings from a specific folder. Requires a paid Granola plan. Use list_meeting_folders to discover folder IDs.
involvementobject- Optional involvement filter. Conditions set to true form an OR inclusion group. Conditions set to false are exclusions applied using AND. Omitted conditions are ignored.
time_rangestring- Time range to query meetings from. Custom bounds imply 'custom' when time_range is omitted; otherwise defaults to the last 7 days, starting at midnight in the user's timezone. Free plans include only the last 30 days of meeting history; ranges extending beyond that return available meetings with an upgrade notice.one of
last_7_daysthis_weeklast_weeklast_30_dayscustom workspace_onlyboolean- Set to true only when the user explicitly asks for Team Space, public workspace, or workspace-visible meetings. Omit to search every meeting the user is allowed to access.
granolamcp_query_granola_meetingsQuery Granola about the user's meetings using natural language.Read-onlyGranola: Query Meetings
Query Granola about the user's meetings using natural language. Returns a tailored response with inline citation links in mark (e.g. [[0]](url)) that reference source meeting notes. IMPORTANT: The response includes numbered citation links to specific Granola meeting notes. These citations MUST be preserved in your response to the user — they provide transparency and allow the user to verify information by clicking through to the original notes. When to use: - User asks about what was discussed, decided, or action-items from meetings - User asks about follow-ups, todos, or commitments from recent meetings - User references 'Granola notes' or 'meeting notes' When NOT to use: - User is asking about calendar scheduling or upcoming events - User explicitly asks for a specific meeting by ID (use get_meetings instead) Prioritize using query_granola_meetings over list_meetings/get_meetings for open-ended or natural language queries about meeting content.
Inputs
querystringrequired- The query to run on Granola meeting notes
document_idsarray- Optional meeting UUIDs or public note IDs to limit context to (max 10).
note_idsarray- Alias for document_ids (max 10). If both are provided, they must refer to the same set of notes; order, duplicates, and UUID/public ID format may differ.
granolamcp_add_note_to_folderAdd a Granola note to a folder.WriteAdd Note To Folder
Add a Granola note to a folder. Use list_meeting_folders to find the destination folder ID and list_meetings to find the note ID; list_meetings shows which folders each note is already in. This operation is additive and idempotent. IMPORTANT: Adding a note grants everyone who can access the folder access to the note. A folder with visibility "workspace" shares the note with everyone in the workspace; check the folder's visibility and audience in list_meeting_folders first. Use only when the user has clearly requested that destination. The response confirms the write with an outcome (added or already_in_folder) and the destination folder's visibility and audience.
Inputs
folder_idstringrequired- Destination folder UUID
note_idstringrequired- Meeting UUID or public note ID (not_â¦)
granolamcp_create_folderCreate a top-level Granola folder.WriteCreate Folder
Create a top-level Granola folder. Use only when the user explicitly asks for a new folder; to file notes into an existing folder, find it with list_meeting_folders and use add_note_to_folder. visibility "private" (the default) creates a folder only the user can see. visibility "workspace" creates it in the workspace's Shared space, where everyone in the workspace can see every note added to it: use it only when the user asks for a team or shared folder. Sub-folders can't be created. If a top-level folder with the same title and visibility already exists, it is returned with outcome already_exists instead of creating a duplicate. The response has outcome created or already_exists and the folder with its id, visibility and audience; pass the id to add_note_to_folder.
Inputs
titlestringrequired- Folder name.
descriptionstring- What the folder is for.
visibilitystring- Who can see the folder: "private" (only the user) or "workspace" (everyone in the workspace).one of
privateworkspacedefaultprivate
granolamcp_sign_outRevoke the connected Granola account's consent and refresh tokens for this MCP client.WriteSign Out
Revoke the connected Granola account's consent and refresh tokens for this MCP client. Only use when the user asks to sign out, disconnect, or switch Granola accounts. This affects all connections for this account using the same client authorization. New MCP requests using this authorization will be rejected immediately after sign-out. No browser action is needed to complete MCP sign-out. If the user wants to switch accounts, tell them to reconnect Granola in this client. Only if the browser automatically selects their previous account, open the returned sign_out_url in that browser before reconnecting again.
Inputs
This tool takes no inputs.
granolamcp_update_folderRename a Granola folder or change its description.WriteUpdate Folder
Rename a Granola folder or change its description. Use only when the user asks to rename or describe a folder. Get the folder ID from list_meeting_folders. Pass title, description or both; anything omitted stays the same. An empty description clears it. Requires owner or collaborator access to the folder (its role in list_meeting_folders). The response returns the updated folder, including its stored title and description.
Inputs
folder_idstringrequired- Folder UUID
descriptionstring- New description. An empty string clears it.
titlestring- New folder name.
granolamcp_remove_note_from_folderRemove a Granola note from a folder.DestructiveRemove Note From Folder
Remove a Granola note from a folder. Use list_meeting_folders to find the folder ID and list_meetings to find the note ID; list_meetings shows which folders each note is in. Removing the note may revoke folder-derived access for other people. The response confirms the write with an outcome (removed or not_in_folder) and the folder's visibility and audience.
Inputs
folder_idstringrequired- Folder UUID
note_idstringrequired- Meeting UUID or public note ID (not_â¦)
No tools match.
Workflows
Tool calling
Use this connector when you want an agent to work with Granola meeting content, including summaries, notes, attendees, and transcripts.
- Use
granolamcp_query_granola_meetingsfor natural-language questions such as decisions, action items, or follow-ups from past meetings. - Use
granolamcp_list_meetingsto find meetings in a time window before drilling into specific meeting IDs. - Use
granolamcp_get_meetingswhen you already know the Granola meeting IDs and need richer metadata or notes. - Use
granolamcp_get_meeting_transcriptwhen exact wording matters and you need the verbatim transcript instead of summarized notes.
tool_response = actions.execute_tool( connection_name='granolamcp', identifier='user_123', tool_name="granolamcp_query_granola_meetings", tool_input={ "query": "What decisions and follow-ups came out of last week's customer calls?" },)print("Granola response:", tool_response)const toolResponse = await actions.executeTool({ connector: 'granolamcp', identifier: 'user_123', toolName: 'granolamcp_query_granola_meetings', toolInput: { query: "What decisions and follow-ups came out of last week's customer calls?", },});console.log('Granola response:', toolResponse.data);