bear_list_notes
List Bear notes, optionally filtered by tag, returning ID, title, tags (hierarchical and leaf), pin status, and modification date.
Instructions
List Bear notes with optional tag filtering. Returns an array of notes with IDs, titles, tags, pin status, and modification dates. Each note includes two tag fields: 'tags' mirrors Bear's CloudKit index verbatim (includes ancestor expansions — a note tagged #parent/child will show both 'parent' and 'parent/child'); 'attached_tags' shows only leaf tags (the most-specific tag on each branch). Notes with 'locked: true' are private/encrypted in Bear and their body content is not searchable — if a search returns no results, check whether the relevant note is locked. Use bear_get_note to read the full content of a specific note.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| tag | No | Filter notes by tag (partial match) | |
| include_archived | No | Include archived notes in results | |
| include_trashed | No | Include trashed notes in results | |
| limit | No | Maximum number of notes to return (default 30) |
Implementation Reference
- mcp-server/src/tools.ts:9-51 (handler)The 'bear_list_notes' tool handler entry in the tools registry. Contains the Tool definition (name, description, inputSchema, annotations), and the buildArgs function that converts user input into CLI arguments for the bcli 'ls --json' command. The key execution path: index.ts calls handler.buildArgs(params) then execBcliWithReauth(args).
export const tools: Record<string, ToolHandler> = { bear_list_notes: { tool: { name: "bear_list_notes", description: "List Bear notes with optional tag filtering. Returns an array of notes with IDs, titles, tags, pin status, and modification dates. Each note includes two tag fields: 'tags' mirrors Bear's CloudKit index verbatim (includes ancestor expansions — a note tagged #parent/child will show both 'parent' and 'parent/child'); 'attached_tags' shows only leaf tags (the most-specific tag on each branch). Notes with 'locked: true' are private/encrypted in Bear and their body content is not searchable — if a search returns no results, check whether the relevant note is locked. Use bear_get_note to read the full content of a specific note.", inputSchema: { type: "object" as const, properties: { tag: { type: "string", description: "Filter notes by tag (partial match)", }, include_archived: { type: "boolean", description: "Include archived notes in results", }, include_trashed: { type: "boolean", description: "Include trashed notes in results", }, limit: { type: "number", description: "Maximum number of notes to return (default 30)", }, }, }, annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, }, }, buildArgs: (input) => { const args = ["ls", "--json"]; if (input.tag) args.push("--tag", String(input.tag)); if (input.include_archived) args.push("--archived"); if (input.include_trashed) args.push("--trashed"); if (input.limit) args.push("--limit", String(input.limit)); return args; }, }, - mcp-server/src/index.ts:29-31 (registration)Tool registration via the ListToolsRequestSchema handler. The tools from tools.ts are listed by mapping over Object.values(tools) and exposing their .tool property to the MCP client. This makes bear_list_notes discoverable.
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: Object.values(tools).map((t) => t.tool), })); - mcp-server/src/index.ts:33-122 (registration)Tool execution dispatcher (CallToolRequestSchema handler). When 'bear_list_notes' is called, it's looked up by name, buildArgs constructs the CLI args, then execBcliWithReauth executes the bcli binary. The JSON output is parsed and returned.
server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: input } = request.params; const handler = tools[name]; if (!handler) { return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true, }; } const params = (input ?? {}) as Record<string, unknown>; // Validate bear_edit_note: need at least one edit operation if (name === "bear_edit_note") { const hasAppend = params.append_text !== undefined; const hasBody = params.body !== undefined; const hasSetFm = params.set_frontmatter !== undefined && Object.keys(params.set_frontmatter as object).length > 0; const hasRemoveFm = Array.isArray(params.remove_frontmatter) && (params.remove_frontmatter as unknown[]).length > 0; const hasFm = hasSetFm || hasRemoveFm; if (!hasAppend && !hasBody && !hasFm) { return { content: [ { type: "text", text: "Provide 'append_text', 'body', 'set_frontmatter', or 'remove_frontmatter'.", }, ], isError: true, }; } if (hasAppend && hasBody) { return { content: [ { type: "text", text: "Provide either 'append_text' or 'body', not both.", }, ], isError: true, }; } } try { const args = handler.buildArgs(params); let result: { stdout: string; stderr: string }; // Check if this tool needs stdin piping const stdinData = handler.usesStdin?.(params) ?? null; if (stdinData !== null) { result = await execBcliWithStdinAndReauth(args, stdinData); } else { result = await execBcliWithReauth(args); } // Parse JSON output from bcli const stdout = result.stdout.trim(); if (!stdout) { return { content: [{ type: "text", text: "Command completed successfully." }], }; } // Validate it's JSON and pretty-print try { const parsed = JSON.parse(stdout); return { content: [ { type: "text", text: JSON.stringify(parsed, null, 2) }, ], }; } catch { // If bcli returned non-JSON, pass it through return { content: [{ type: "text", text: stdout }], }; } } catch (error) { const message = error instanceof BcliError ? error.message : String(error); return { content: [{ type: "text", text: message }], isError: true, }; } }); - mcp-server/src/tools.ts:15-36 (schema)Input schema for bear_list_notes: accepts optional 'tag' (string), 'include_archived' (boolean), 'include_trashed' (boolean), and 'limit' (number) parameters.
inputSchema: { type: "object" as const, properties: { tag: { type: "string", description: "Filter notes by tag (partial match)", }, include_archived: { type: "boolean", description: "Include archived notes in results", }, include_trashed: { type: "boolean", description: "Include trashed notes in results", }, limit: { type: "number", description: "Maximum number of notes to return (default 30)", }, }, },