Skip to main content
Glama
index-v1.ts12.5 kB
#!/usr/bin/env node import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js"; import open from "open"; const BEAR_URL_SCHEME = "bear://x-callback-url"; interface BearParams { [key: string]: string | undefined; } async function openBearURL(action: string, params: BearParams): Promise<void> { const url = new URL(`${BEAR_URL_SCHEME}/${action}`); Object.entries(params).forEach(([key, value]) => { if (value !== undefined) { url.searchParams.append(key, value); } }); await open(url.toString()); } const server = new Server( { name: "bear-mcp", version: "1.0.0", }, { capabilities: { tools: {}, }, } ); server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: "create_note", description: "Create a new note in Bear", inputSchema: { type: "object", properties: { title: { type: "string", description: "Note title", }, text: { type: "string", description: "Note content", }, tags: { type: "string", description: "Comma separated tags (e.g., 'work,ideas')", }, clipboard: { type: "boolean", description: "Append clipboard content", }, timestamp: { type: "boolean", description: "Prepend timestamp", }, }, required: [], }, }, { name: "open_note", description: "Open a specific note in Bear", inputSchema: { type: "object", properties: { id: { type: "string", description: "Note unique identifier", }, title: { type: "string", description: "Note title (ignored if id is provided)", }, header: { type: "string", description: "Header inside the note to jump to", }, exclude_trashed: { type: "boolean", description: "Exclude trashed notes", }, new_window: { type: "boolean", description: "Open in new window", }, edit: { type: "boolean", description: "Open note in edit mode", }, }, required: [], }, }, { name: "add_text", description: "Append or prepend text to an existing note", inputSchema: { type: "object", properties: { id: { type: "string", description: "Note unique identifier", }, title: { type: "string", description: "Note title (ignored if id is provided)", }, text: { type: "string", description: "Text to add", }, mode: { type: "string", enum: ["append", "prepend", "replace", "replace_all"], description: "How to add the text (default: append)", }, new_line: { type: "boolean", description: "Add newline before text when appending", }, tags: { type: "string", description: "Comma separated tags to add", }, }, required: ["text"], }, }, { name: "search_notes", description: "Search for notes in Bear", inputSchema: { type: "object", properties: { term: { type: "string", description: "Search term", }, tag: { type: "string", description: "Tag to search within", }, }, required: ["term"], }, }, { name: "get_tags", description: "Get all tags in Bear", inputSchema: { type: "object", properties: {}, required: [], }, }, { name: "open_tag", description: "Show notes with specific tag(s)", inputSchema: { type: "object", properties: { name: { type: "string", description: "Tag name(s), comma separated for multiple", }, }, required: ["name"], }, }, { name: "rename_tag", description: "Rename an existing tag", inputSchema: { type: "object", properties: { name: { type: "string", description: "Current tag name", }, new_name: { type: "string", description: "New tag name", }, }, required: ["name", "new_name"], }, }, { name: "delete_tag", description: "Delete a tag from all notes", inputSchema: { type: "object", properties: { name: { type: "string", description: "Tag name to delete", }, }, required: ["name"], }, }, { name: "trash_note", description: "Move a note to trash", inputSchema: { type: "object", properties: { id: { type: "string", description: "Note unique identifier", }, title: { type: "string", description: "Note title (ignored if id is provided)", }, }, required: [], }, }, { name: "archive_note", description: "Archive a note", inputSchema: { type: "object", properties: { id: { type: "string", description: "Note unique identifier", }, title: { type: "string", description: "Note title (ignored if id is provided)", }, }, required: [], }, }, { name: "grab_url", description: "Create a note from a webpage", inputSchema: { type: "object", properties: { url: { type: "string", description: "Webpage URL to grab", }, tags: { type: "string", description: "Comma separated tags", }, }, required: ["url"], }, }, ], }; }); server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; if (!args) { throw new Error("No arguments provided"); } try { switch (name) { case "create_note": { const params: BearParams = {}; if (args.title) params.title = String(args.title); if (args.text) params.text = String(args.text); if (args.tags) params.tags = String(args.tags); if (args.clipboard) params.clipboard = "yes"; if (args.timestamp) params.timestamp = "yes"; await openBearURL("create", params); return { content: [ { type: "text", text: "Note created successfully", }, ], }; } case "open_note": { const params: BearParams = {}; if (args.id) params.id = String(args.id); if (args.title) params.title = String(args.title); if (args.header) params.header = String(args.header); if (args.exclude_trashed) params.exclude_trashed = "yes"; if (args.new_window) params.new_window = "yes"; if (args.edit) params.edit = "yes"; await openBearURL("open-note", params); return { content: [ { type: "text", text: "Note opened successfully", }, ], }; } case "add_text": { const params: BearParams = { text: String(args.text), }; if (args.id) params.id = String(args.id); if (args.title) params.title = String(args.title); if (args.mode) params.mode = String(args.mode); if (args.new_line) params.new_line = "yes"; if (args.tags) params.tags = String(args.tags); await openBearURL("add-text", params); return { content: [ { type: "text", text: "Text added successfully", }, ], }; } case "search_notes": { const params: BearParams = { term: String(args.term), }; if (args.tag) params.tag = String(args.tag); await openBearURL("search", params); return { content: [ { type: "text", text: "Search opened in Bear", }, ], }; } case "get_tags": { await openBearURL("tags", {}); return { content: [ { type: "text", text: "Tags list opened in Bear", }, ], }; } case "open_tag": { const params: BearParams = { name: String(args.name), }; await openBearURL("open-tag", params); return { content: [ { type: "text", text: "Tag notes opened successfully", }, ], }; } case "rename_tag": { const params: BearParams = { name: String(args.name), new_name: String(args.new_name), }; await openBearURL("rename-tag", params); return { content: [ { type: "text", text: "Tag renamed successfully", }, ], }; } case "delete_tag": { const params: BearParams = { name: String(args.name), }; await openBearURL("delete-tag", params); return { content: [ { type: "text", text: "Tag deleted successfully", }, ], }; } case "trash_note": { const params: BearParams = {}; if (args.id) params.id = String(args.id); if (args.title) params.title = String(args.title); await openBearURL("trash", params); return { content: [ { type: "text", text: "Note moved to trash", }, ], }; } case "archive_note": { const params: BearParams = {}; if (args.id) params.id = String(args.id); if (args.title) params.title = String(args.title); await openBearURL("archive", params); return { content: [ { type: "text", text: "Note archived successfully", }, ], }; } case "grab_url": { const params: BearParams = { url: String(args.url), }; if (args.tags) params.tags = String(args.tags); await openBearURL("grab-url", params); return { content: [ { type: "text", text: "URL content grabbed successfully", }, ], }; } default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } }); async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("Bear MCP server running on stdio"); } main().catch((error) => { console.error("Server error:", error); process.exit(1); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/philgetzen/bear-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server