bear_create_note
Creates a Bear note with title, markdown body, tags, and YAML front matter. Hashtags written inline are automatically registered as real tags. Returns the note ID.
Instructions
Create a new Bear note with a title, optional body text, tags, and YAML front matter. Hashtags written inline in the body (e.g. '#my_tag' or '#parent/child') are extracted and registered as real tags on the note, matching Bear's desktop-app behaviour. Tags from the 'tags' array are indexed regardless of whether they appear in the body. Hierarchical tags like '#parent/child' also index every ancestor (so they show up under #parent in Bear's sidebar). Front matter is stored as a collapsed metadata block at the top of the note. Returns the new note's ID.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes | Note title | |
| body | No | Note body text (markdown) | |
| tags | No | Tags to assign to the note | |
| frontmatter | No | YAML front matter fields as key-value pairs (e.g. {status: 'draft', project: 'alpha'}) |
Implementation Reference
- mcp-server/src/index.ts:29-31 (registration)Registration: All tools (including bear_create_note) are registered via ListToolsRequestSchema handler, which maps over `tools` object values and exposes their .tool definitions.
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: Object.values(tools).map((t) => t.tool), })); - mcp-server/src/tools.ts:147-197 (handler)Handler & Schema: The complete definition of bear_create_note. Contains both the tool schema (name, description, inputSchema with title/body/tags/frontmatter properties, and annotations) and the buildArgs function that constructs the bcli command-line arguments.
bear_create_note: { tool: { name: "bear_create_note", description: "Create a new Bear note with a title, optional body text, tags, and YAML front matter. Hashtags written inline in the body (e.g. '#my_tag' or '#parent/child') are extracted and registered as real tags on the note, matching Bear's desktop-app behaviour. Tags from the 'tags' array are indexed regardless of whether they appear in the body. Hierarchical tags like '#parent/child' also index every ancestor (so they show up under #parent in Bear's sidebar). Front matter is stored as a collapsed metadata block at the top of the note. Returns the new note's ID.", inputSchema: { type: "object" as const, properties: { title: { type: "string", description: "Note title", }, body: { type: "string", description: "Note body text (markdown)", }, tags: { type: "array", items: { type: "string" }, description: "Tags to assign to the note", }, frontmatter: { type: "object", description: "YAML front matter fields as key-value pairs (e.g. {status: 'draft', project: 'alpha'})", additionalProperties: { type: "string" }, }, }, required: ["title"], }, annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, }, }, buildArgs: (input) => { const args = ["create", String(input.title), "--json"]; if (input.body) args.push("--body", String(input.body)); if (Array.isArray(input.tags) && input.tags.length > 0) { args.push("--tags", input.tags.join(",")); } if (input.frontmatter && typeof input.frontmatter === "object") { const fm = input.frontmatter as Record<string, string>; args.push( "--fm", ...Object.entries(fm).map(([k, v]) => `${k}=${v}`), ); } return args; }, - mcp-server/src/tools.ts:3-8 (helper)Type definition for ToolHandler interface that bear_create_note implements.
export interface ToolHandler { tool: Tool; buildArgs: (input: Record<string, unknown>) => string[]; usesStdin?: (input: Record<string, unknown>) => string | null; } - mcp-server/src/index.ts:33-121 (helper)Dispatch: The CallToolRequestSchema handler looks up the tool by name in the `tools` map (which contains bear_create_note), calls buildArgs to get CLI args, then executes bcli via execBcliWithReauth.
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, }; }