bear-notes-mcp 2.8.0 → 2.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  Search, read, create, and update your Bear Notes from any AI assistant.
4
4
 
5
- **Full documentation and source code: [claude-desktop-extension-bear-notes](https://github.com/vasylenko/claude-desktop-extension-bear-notes)**
5
+ **Full documentation and source code: [bear-notes-mcp](https://github.com/vasylenko/bear-notes-mcp)**
6
6
 
7
7
  ## Key Features
8
8
 
9
- - **10 MCP tools** for full Bear Notes integration
9
+ - **12 MCP tools** for full Bear Notes integration
10
10
  - **OCR search** across images and PDFs attached to notes
11
11
  - **Date-based search** with relative dates ("yesterday", "last week", etc.)
12
12
  - **Configurable new note convention** for tag placement (opt-in)
@@ -83,8 +83,8 @@ Example with configuration:
83
83
 
84
84
  **Step 1: Clone and build**
85
85
  ```bash
86
- git clone https://github.com/vasylenko/claude-desktop-extension-bear-notes.git
87
- cd claude-desktop-extension-bear-notes
86
+ git clone https://github.com/vasylenko/bear-notes-mcp.git
87
+ cd bear-notes-mcp
88
88
  npm install
89
89
  npm run build
90
90
  ```
package/dist/config.js CHANGED
@@ -1,4 +1,4 @@
1
- export const APP_VERSION = '2.8.0';
1
+ export const APP_VERSION = '2.8.2';
2
2
  export const BEAR_URL_SCHEME = 'bear://x-callback-url/';
3
3
  export const CORE_DATA_EPOCH_OFFSET = 978307200; // 2001-01-01 to Unix epoch
4
4
  export const DEFAULT_SEARCH_LIMIT = 50;
package/dist/main.js CHANGED
@@ -52,11 +52,27 @@ Use bear-search-notes to find the correct note identifier.`);
52
52
  `ID: ${noteWithContent.identifier}`,
53
53
  ];
54
54
  const noteText = noteWithContent.text || '*This note appears to be empty.*';
55
- return createToolResponse(`${noteInfo.join('\n')}
56
-
57
- ---
58
-
59
- ${noteText}`);
55
+ const annotations = { audience: ['user', 'assistant'] };
56
+ // Body and file metadata are separate content blocks so the synthetic
57
+ // file section can never leak back during write operations (#86)
58
+ const content = [
59
+ {
60
+ type: 'text',
61
+ text: `${noteInfo.join('\n')}\n\n---\n\n${noteText}`,
62
+ annotations,
63
+ },
64
+ ];
65
+ if (noteWithContent.files?.length) {
66
+ const fileEntries = noteWithContent.files
67
+ .map((f) => `## ${f.filename}\n\n${f.content}`)
68
+ .join('\n\n---\n\n');
69
+ content.push({
70
+ type: 'text',
71
+ text: `# Attached Files\n\n${fileEntries}`,
72
+ annotations,
73
+ });
74
+ }
75
+ return { content };
60
76
  }
61
77
  catch (error) {
62
78
  logger.error('bear-open-note failed:', error);
@@ -246,7 +262,7 @@ server.registerTool('bear-add-text', {
246
262
  });
247
263
  server.registerTool('bear-replace-text', {
248
264
  title: 'Replace Note Content',
249
- description: 'Replace content in an existing Bear note — either the full body or a specific section. Requires content replacement to be enabled in extension settings. Use bear-search-notes first to get the note ID. To add text without replacing existing content use bear-add-text instead.',
265
+ description: 'Replace content in an existing Bear note — either the full body or a specific section. Requires content replacement to be enabled in settings. Use bear-search-notes first to get the note ID. To add text without replacing existing content use bear-add-text instead.',
250
266
  inputSchema: {
251
267
  id: z
252
268
  .string()
@@ -277,7 +293,7 @@ server.registerTool('bear-replace-text', {
277
293
  if (!ENABLE_CONTENT_REPLACEMENT) {
278
294
  return createToolResponse(`Content replacement is not enabled.
279
295
 
280
- To use replace mode, enable "Content Replacement" in the Bear Notes extension settings.`);
296
+ To use replace mode, enable "Content Replacement" in the Bear Notes server settings.`);
281
297
  }
282
298
  if (scope === 'section' && !header) {
283
299
  return createToolResponse(`scope is "section" but no header was provided.
package/dist/notes.js CHANGED
@@ -91,8 +91,9 @@ export function getNoteContent(identifier) {
91
91
  // Process multiple rows (note + files) into single note object
92
92
  const firstRow = rows[0];
93
93
  const formattedNote = formatBearNote(firstRow);
94
- // Collect file content from all rows with clear source labeling
95
- const fileContents = [];
94
+ // Collect file content into a structured array kept separate from note text
95
+ // to prevent the synthetic file section from leaking into write operations (#86)
96
+ const files = [];
96
97
  for (const row of rows) {
97
98
  const rowData = row;
98
99
  const filename = rowData.filename;
@@ -102,21 +103,13 @@ export function getNoteContent(identifier) {
102
103
  const content = trimmed
103
104
  ? trimmed
104
105
  : '*[File content not available — Bear has not extracted text from this file type]*';
105
- fileContents.push(`##${filename}\n\n${content}`);
106
+ files.push({ filename, content });
106
107
  }
107
108
  }
108
- // Always append file content section, even if empty, to show structure
109
- const originalText = formattedNote.text || '';
110
- const filesSectionHeader = '\n\n---\n\n#Attached Files\n\n';
111
- if (fileContents.length > 0) {
112
- const fileSection = `${filesSectionHeader}${fileContents.join('\n\n---\n\n')}`;
113
- formattedNote.text = originalText + fileSection;
109
+ if (files.length > 0) {
110
+ formattedNote.files = files;
114
111
  }
115
- else {
116
- // Add a note that no files are attached for clarity
117
- formattedNote.text = originalText + `${filesSectionHeader}*No files attached to this note.*`;
118
- }
119
- logger.info(`Retrieved note content with ${fileContents.length} attached files for: ${formattedNote.title}`);
112
+ logger.info(`Retrieved note content with ${files.length} attached files for: ${formattedNote.title}`);
120
113
  return formattedNote;
121
114
  }
122
115
  catch (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bear-notes-mcp",
3
- "version": "2.8.0",
3
+ "version": "2.8.2",
4
4
  "description": "Bear Notes MCP server with TypeScript and native SQLite",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",
@@ -49,7 +49,9 @@
49
49
  "notes management",
50
50
  "productivity",
51
51
  "typescript",
52
- "mcp"
52
+ "mcp",
53
+ "mcp-server",
54
+ "ai-assistant"
53
55
  ],
54
56
  "author": {
55
57
  "name": "Serhii Vasylenko",
@@ -59,12 +61,12 @@
59
61
  "license": "MIT",
60
62
  "repository": {
61
63
  "type": "git",
62
- "url": "git+https://github.com/vasylenko/claude-desktop-extension-bear-notes.git"
64
+ "url": "git+https://github.com/vasylenko/bear-notes-mcp.git"
63
65
  },
64
66
  "bugs": {
65
- "url": "https://github.com/vasylenko/claude-desktop-extension-bear-notes/issues"
67
+ "url": "https://github.com/vasylenko/bear-notes-mcp/issues"
66
68
  },
67
- "homepage": "https://github.com/vasylenko/claude-desktop-extension-bear-notes#readme",
69
+ "homepage": "https://github.com/vasylenko/bear-notes-mcp#readme",
68
70
  "bin": {
69
71
  "bear-notes-mcp": "dist/main.js"
70
72
  },