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/tools.ts

38 lines · 2.0 KB · TypeScript
Raw
import { parseInput } from '../lib/validate.ts'
import { DEFAULT_MCP_SERVER, findMcpServer, GRANOLA_MCP_TOOLS, GRANOLA_MCP_URL, KODY_MCP_PAGE, MCP_SERVER_PATTERN, toolNamesOf } from '../lib/mcp.ts'

/**
 * Status of the optional MCP lane: whether Granola's official MCP server (https://mcp.granola.ai/mcp)
 * is connected to this Kody account, its OAuth state, and the tools it exposes. Read-only; no
 * Granola request. The MCP lane works on every Granola plan (Basic: last 30 days of notes) and
 * adds `query_granola_meetings` (ask questions across meetings), which the REST API does not have.
 *
 * @param input.server - Kody MCP server name (default `granola`).
 * @returns `{ server, connected, state, authUrl, tools, documentedTools, next }`
 *
 * @example
 * import mcpTools from 'kody:@charlesmatte/granola/mcp/tools'
 *
 * const status = await mcpTools({})
 */
export default async function granolaMcpTools(input: unknown) {
	const p = parseInput<{ server?: string }>(input, { server: { type: 'string', pattern: MCP_SERVER_PATTERN } }, 'mcp/tools')
	const server = p.server ?? DEFAULT_MCP_SERVER
	const info = await findMcpServer(server)
	if (!info) {
		return { server, connected: false, documentedTools: GRANOLA_MCP_TOOLS, next: `Not connected. One-time setup: open ${KODY_MCP_PAGE}, add a server named "${server}" with URL ${GRANOLA_MCP_URL}, then open the authorization link and sign in to Granola. Or run ./mcp/connect({ confirm: true }) and open the returned authUrl.` }
	}
	const tools = toolNamesOf(info)
	const state = String(info.state ?? info.status ?? 'unknown')
	return {
		server,
		connected: tools.length > 0,
		url: info.url,
		state,
		authUrl: info.authUrl ?? null,
		error: info.error ?? null,
		tools,
		documentedTools: GRANOLA_MCP_TOOLS,
		next: tools.length ? 'Ready: ask questions with ./mcp/query({ question }), or call a tool with ./mcp/call({ tool, args }).' : info.authUrl ? `Open authUrl to finish the Granola sign-in: ${info.authUrl}` : 'Server saved but no tools discovered yet; reconnect with ./mcp/connect.',
	}
}