From 44c8d1540fa1ed231fa8c9e12dd67d7a35ac1eef Mon Sep 17 00:00:00 2001 From: Felipe Meres Date: Thu, 10 Apr 2025 08:24:44 -0400 Subject: [PATCH] feat: add host environment variable support --- README.md | 4 +++- src/mcp_obsidian/tools.py | 32 ++++++++++++++++---------------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 91bf228..e55c9f6 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,8 @@ There are two ways to configure the environment with the Obsidian REST API Key. "mcp-obsidian" ], "env": { - "OBSIDIAN_API_KEY":"" + "OBSIDIAN_API_KEY": "", + "OBSIDIAN_HOST": "" } } } @@ -53,6 +54,7 @@ There are two ways to configure the environment with the Obsidian REST API Key. ``` OBSIDIAN_API_KEY=your_api_key_here +OBSIDIAN_HOST=your_obsidian_host ``` Note: You can find the key in the Obsidian plugin config. diff --git a/src/mcp_obsidian/tools.py b/src/mcp_obsidian/tools.py index b7cad84..04dcbec 100644 --- a/src/mcp_obsidian/tools.py +++ b/src/mcp_obsidian/tools.py @@ -10,6 +10,8 @@ import os from . import obsidian api_key = os.getenv("OBSIDIAN_API_KEY", "") +obsidian_host = os.getenv("OBSIDIAN_HOST", "127.0.0.1") + if api_key == "": raise ValueError(f"OBSIDIAN_API_KEY environment variable required. Working directory: {os.getcwd()}") @@ -42,8 +44,7 @@ class ListFilesInVaultToolHandler(ToolHandler): ) def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | EmbeddedResource]: - - api = obsidian.Obsidian(api_key=api_key) + api = obsidian.Obsidian(api_key=api_key, host=obsidian_host) files = api.list_files_in_vault() @@ -79,7 +80,7 @@ class ListFilesInDirToolHandler(ToolHandler): if "dirpath" not in args: raise RuntimeError("dirpath argument missing in arguments") - api = obsidian.Obsidian(api_key=api_key) + api = obsidian.Obsidian(api_key=api_key, host=obsidian_host) files = api.list_files_in_dir(args["dirpath"]) @@ -115,7 +116,7 @@ class GetFileContentsToolHandler(ToolHandler): if "filepath" not in args: raise RuntimeError("filepath argument missing in arguments") - api = obsidian.Obsidian(api_key=api_key) + api = obsidian.Obsidian(api_key=api_key, host=obsidian_host) content = api.get_file_contents(args["filepath"]) @@ -158,7 +159,7 @@ class SearchToolHandler(ToolHandler): context_length = args.get("context_length", 100) - api = obsidian.Obsidian(api_key=api_key) + api = obsidian.Obsidian(api_key=api_key, host=obsidian_host) results = api.search(args["query"], context_length) formatted_results = [] @@ -217,7 +218,7 @@ class AppendContentToolHandler(ToolHandler): if "filepath" not in args or "content" not in args: raise RuntimeError("filepath and content arguments required") - api = obsidian.Obsidian(api_key=api_key) + api = obsidian.Obsidian(api_key=api_key, host=obsidian_host) api.append_content(args.get("filepath", ""), args["content"]) return [ @@ -267,11 +268,10 @@ class PatchContentToolHandler(ToolHandler): ) def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | EmbeddedResource]: - required = ["filepath", "operation", "target_type", "target", "content"] - if not all(key in args for key in required): - raise RuntimeError(f"Missing required arguments: {', '.join(required)}") + if not all(k in args for k in ["filepath", "operation", "target_type", "target", "content"]): + raise RuntimeError("filepath, operation, target_type, target and content arguments required") - api = obsidian.Obsidian(api_key=api_key) + api = obsidian.Obsidian(api_key=api_key, host=obsidian_host) api.patch_content( args.get("filepath", ""), args.get("operation", ""), @@ -320,7 +320,7 @@ class DeleteFileToolHandler(ToolHandler): if not args.get("confirm", False): raise RuntimeError("confirm must be set to true to delete a file") - api = obsidian.Obsidian(api_key=api_key) + api = obsidian.Obsidian(api_key=api_key, host=obsidian_host) api.delete_file(args["filepath"]) return [ @@ -358,7 +358,7 @@ class ComplexSearchToolHandler(ToolHandler): if "query" not in args: raise RuntimeError("query argument missing in arguments") - api = obsidian.Obsidian(api_key=api_key) + api = obsidian.Obsidian(api_key=api_key, host=obsidian_host) results = api.search_json(args.get("query", "")) return [ @@ -397,7 +397,7 @@ class BatchGetFileContentsToolHandler(ToolHandler): if "filepaths" not in args: raise RuntimeError("filepaths argument missing in arguments") - api = obsidian.Obsidian(api_key=api_key) + api = obsidian.Obsidian(api_key=api_key, host=obsidian_host) content = api.get_batch_file_contents(args["filepaths"]) return [ @@ -437,7 +437,7 @@ class PeriodicNotesToolHandler(ToolHandler): if period not in valid_periods: raise RuntimeError(f"Invalid period: {period}. Must be one of: {', '.join(valid_periods)}") - api = obsidian.Obsidian(api_key=api_key) + api = obsidian.Obsidian(api_key=api_key, host=obsidian_host) content = api.get_periodic_note(period) return [ @@ -497,7 +497,7 @@ class RecentPeriodicNotesToolHandler(ToolHandler): if not isinstance(include_content, bool): raise RuntimeError(f"Invalid include_content: {include_content}. Must be a boolean") - api = obsidian.Obsidian(api_key=api_key) + api = obsidian.Obsidian(api_key=api_key, host=obsidian_host) results = api.get_recent_periodic_notes(period, limit, include_content) return [ @@ -544,7 +544,7 @@ class RecentChangesToolHandler(ToolHandler): if not isinstance(days, int) or days < 1: raise RuntimeError(f"Invalid days: {days}. Must be a positive integer") - api = obsidian.Obsidian(api_key=api_key) + api = obsidian.Obsidian(api_key=api_key, host=obsidian_host) results = api.get_recent_changes(limit, days) return [