Skip to content
← Public packages

@charlesmatte/granola

Search and read Granola meeting notes, summaries and transcripts from any agent; manage webhooks and legal holds safely.

src/mcp/call.ts

30 lines · 1.6 KB · TypeScript
Raw
import { callMcpTool, DEFAULT_MCP_SERVER, GRANOLA_MCP_TOOLS, MCP_SERVER_PATTERN } from '../lib/mcp.ts'
import { parseInput } from '../lib/validate.ts'

/**
 * Call one tool on Granola's official MCP server through Kody (optional lane; connect it first
 * with ./mcp/connect). Only Granola's documented, read-only tools are allowed:
 * `query_granola_meetings` (ask a question across meetings — not in the REST API), `list_meetings`,
 * `get_meetings`, `list_meeting_folders` (paid), `get_meeting_transcript` (paid), `get_account_info`.
 * `args` is passed through unchanged; the tool schemas are defined by Granola (see ./mcp/tools and
 * Kody's `search({ entity: "mcp-server:granola" })`). Rate limit ≈100 requests/minute.
 *
 * @param input.tool - One of the documented tool names. Required.
 * @param input.args - Tool arguments object (default `{}`).
 * @param input.server - Kody MCP server name (default `granola`).
 * @returns `{ server, tool, result }` — the MCP tool result as returned by Kody.
 *
 * @example
 * import mcpCall from 'kody:@charlesmatte/granola/mcp/call'
 *
 * const who = await mcpCall({ tool: 'get_account_info' })
 */
export default async function callGranolaMcp(input: unknown) {
	const p = parseInput<{ tool: string; args?: Record<string, unknown>; server?: string }>(
		input,
		{ tool: { type: 'enum', values: GRANOLA_MCP_TOOLS, required: true }, args: { type: 'object' }, server: { type: 'string', pattern: MCP_SERVER_PATTERN } },
		'mcp/call',
	)
	const server = p.server ?? DEFAULT_MCP_SERVER
	return { server, tool: p.tool, result: await callMcpTool(server, p.tool, p.args ?? {}) }
}