Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 31744d01a1 | |||
| 6ee26f1ad8 |
11
CHANGELOG.md
11
CHANGELOG.md
@@ -73,6 +73,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Comprehensive input schema definitions
|
||||
- Security audit of parameter handling
|
||||
|
||||
## [1.1.8] - 2026-04-30
|
||||
|
||||
### Fixed
|
||||
- **Binary files returned as MCP embedded resource**: Updated issue #9 fix to use the proper MCP `EmbeddedResource` format instead of a `BASE64:` text prefix
|
||||
- Binary files are now returned as `{ type: "resource", resource: { uri, mimeType, blob } }`
|
||||
- `uri` is constructed as `obsidian://<vault>/<path>`
|
||||
- `mimeType` is detected from the file extension (PDF, ZIP, images, Office formats, audio/video; defaults to `application/octet-stream`)
|
||||
- `blob` contains the base64-encoded raw bytes
|
||||
|
||||
## [1.1.7] - 2026-04-30
|
||||
|
||||
### Fixed
|
||||
@@ -160,6 +169,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## Version History
|
||||
|
||||
- **1.1.8** - Bug fix release: Binary files returned as MCP embedded resource (fixes #9)
|
||||
- **1.1.7** - Bug fix release: Binary files returned as base64 in `obsidian_read_note` (fixes #9)
|
||||
- **1.1.6** - Bug fix release: Clarify `name` vs `path` semantics in `obsidian_create_note` (fixes #8)
|
||||
- **1.1.5** - Bug fix release: Preserve `<` and `>` in note content for Mermaid/HTML (fixes #7)
|
||||
@@ -173,6 +183,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Search & Discovery (12 tools)
|
||||
- Task & Property Management (8 tools)
|
||||
|
||||
[1.1.8]: https://git.mortons.site/Peter.Morton/obsidian-mcp/releases/tag/v1.1.8
|
||||
[1.1.7]: https://git.mortons.site/Peter.Morton/obsidian-mcp/releases/tag/v1.1.7
|
||||
[1.1.6]: https://git.mortons.site/Peter.Morton/obsidian-mcp/releases/tag/v1.1.6
|
||||
[1.1.5]: https://git.mortons.site/Peter.Morton/obsidian-mcp/releases/tag/v1.1.5
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": "0.3",
|
||||
"name": "obsidian-mcp",
|
||||
"version": "1.1.7",
|
||||
"version": "1.1.8",
|
||||
"display_name": "Obsidian CLI Bundle",
|
||||
"description": "MCP Bundle for Obsidian CLI - Enable AI assistants to manage Obsidian vaults through conversational interface",
|
||||
"long_description": "This MCP bundle provides a comprehensive set of tools for AI assistants to interact with and manage Obsidian vaults. It includes capabilities for creating, reading, updating, and deleting notes, managing links and tags, handling tasks, and more. With this bundle, AI assistants can seamlessly integrate with Obsidian to help users organize their knowledge and workflows.",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "obsidian-mcp",
|
||||
"version": "1.1.7",
|
||||
"version": "1.1.8",
|
||||
"description": "MCP Bundle for Obsidian CLI - Enable AI assistants to manage Obsidian vaults through Model Context Protocol",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
|
||||
@@ -40,6 +40,30 @@ function isBinaryContent(buf: Buffer): boolean {
|
||||
return nonPrintable / sample.length > 0.1;
|
||||
}
|
||||
|
||||
/** Map common file extensions to MIME types */
|
||||
const MIME_TYPES: Record<string, string> = {
|
||||
pdf: 'application/pdf',
|
||||
zip: 'application/zip',
|
||||
gz: 'application/gzip',
|
||||
tar: 'application/x-tar',
|
||||
png: 'image/png',
|
||||
jpg: 'image/jpeg',
|
||||
jpeg: 'image/jpeg',
|
||||
gif: 'image/gif',
|
||||
webp: 'image/webp',
|
||||
svg: 'image/svg+xml',
|
||||
mp3: 'audio/mpeg',
|
||||
mp4: 'video/mp4',
|
||||
docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
};
|
||||
|
||||
function getMimeType(filePath: string): string {
|
||||
const ext = filePath.split('.').pop()?.toLowerCase() ?? '';
|
||||
return MIME_TYPES[ext] ?? 'application/octet-stream';
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all file operation tools
|
||||
*/
|
||||
@@ -151,7 +175,7 @@ export async function registerFileOperationTools(server: ObsidianMCPServer): Pro
|
||||
// T031: Read note tool
|
||||
server.registerTool(
|
||||
'obsidian_read_note',
|
||||
'Read the content of a note from the Obsidian vault. Specify either the note name (file) or full path (path). For large files (e.g. PDFs), use max_chars and offset to read in chunks and avoid exceeding context limits. Binary files (ZIP, images, compiled files, etc.) are automatically detected and returned as a base64-encoded string prefixed with "BASE64:" — the client must base64-decode the value to recover the original binary content.',
|
||||
'Read the content of a note from the Obsidian vault. Specify either the note name (file) or full path (path). For large files (e.g. PDFs), use max_chars and offset to read in chunks and avoid exceeding context limits. Binary files (ZIP, images, PDFs, etc.) are automatically detected and returned as an MCP embedded resource with a uri, mimeType, and base64-encoded blob field instead of plain text.',
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -174,7 +198,7 @@ export async function registerFileOperationTools(server: ObsidianMCPServer): Pro
|
||||
},
|
||||
},
|
||||
createToolHandler(
|
||||
'Read the content of a note. Binary files are returned as a base64-encoded string prefixed with "BASE64:" — decode it to recover the original binary content.',
|
||||
'Read the content of a note. Binary files are returned as an MCP embedded resource (type: "resource") with uri, mimeType, and a base64-encoded blob field.',
|
||||
{
|
||||
type: 'object',
|
||||
properties: {
|
||||
@@ -209,13 +233,21 @@ export async function registerFileOperationTools(server: ObsidianMCPServer): Pro
|
||||
const result = await executeObsidianCommandBinary('read', cmdArgs);
|
||||
handleCLIResult(result, { operation: 'read_note', identifier: sanitized.file || sanitized.path });
|
||||
|
||||
// Detect binary content from the raw buffer and return as base64
|
||||
// Detect binary content from the raw buffer and return as MCP resource
|
||||
if (result.stdoutBuffer && isBinaryContent(result.stdoutBuffer)) {
|
||||
const identifier = sanitized.file || sanitized.path as string;
|
||||
const vaultName = process.env.OBSIDIAN_VAULT ?? 'vault';
|
||||
const uri = `obsidian://${encodeURIComponent(vaultName)}/${encodeURIComponent(identifier)}`;
|
||||
const mimeType = getMimeType(identifier);
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: `BASE64:${result.stdoutBuffer.toString('base64')}`,
|
||||
type: 'resource' as const,
|
||||
resource: {
|
||||
uri,
|
||||
mimeType,
|
||||
blob: result.stdoutBuffer.toString('base64'),
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -16,10 +16,10 @@ export interface ToolInput {
|
||||
* Successful tool output
|
||||
*/
|
||||
export interface ToolOutput {
|
||||
content: Array<{
|
||||
type: 'text';
|
||||
text: string;
|
||||
}>;
|
||||
content: Array<
|
||||
| { type: 'text'; text: string }
|
||||
| { type: 'resource'; resource: { uri: string; mimeType?: string; blob: string } }
|
||||
>;
|
||||
isError?: false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user