Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ There are two ways to configure the environment with the Obsidian REST API Key.
],
"env": {
"OBSIDIAN_API_KEY": "<your_api_key_here>",
"OBSIDIAN_HOST": "<your_obsidian_host>"
"OBSIDIAN_HOST": "<your_obsidian_host>",
"OBSIDIAN_PORT": "<your_obsidian_port>",
"OBSIDIAN_PROTOCOL": "<your_obsidian_protocol>"
}
}
}
Expand All @@ -55,6 +57,8 @@ 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
OBSIDIAN_PORT=your_obsidian_port
OBSIDIAN_PROTOCOL=your_obsidian_protocol
```

Note: You can find the key in the Obsidian plugin config.
Expand Down
29 changes: 17 additions & 12 deletions src/mcp_obsidian/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@

api_key = os.getenv("OBSIDIAN_API_KEY", "")
obsidian_host = os.getenv("OBSIDIAN_HOST", "127.0.0.1")
obsidian_port = os.getenv("OBSIDIAN_PORT", "27124")
obsidian_protocol = os.getenv("OBSIDIAN_PROTOCOL", "https")

if api_key == "":
raise ValueError(f"OBSIDIAN_API_KEY environment variable required. Working directory: {os.getcwd()}")

if obsidian_protocol not in ["http", "https"]:
raise ValueError(f"OBSIDIAN_PROTOCOL must be either http or https. Working directory: {os.getcwd()}")

TOOL_LIST_FILES_IN_VAULT = "obsidian_list_files_in_vault"
TOOL_LIST_FILES_IN_DIR = "obsidian_list_files_in_dir"

Expand Down Expand Up @@ -44,7 +49,7 @@ def get_tool_description(self):
)

def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | EmbeddedResource]:
api = obsidian.Obsidian(api_key=api_key, host=obsidian_host)
api = obsidian.Obsidian(api_key=api_key, host=obsidian_host, port=obsidian_port, protocol=obsidian_protocol)

files = api.list_files_in_vault()

Expand Down Expand Up @@ -80,7 +85,7 @@ def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | Embedded
if "dirpath" not in args:
raise RuntimeError("dirpath argument missing in arguments")

api = obsidian.Obsidian(api_key=api_key, host=obsidian_host)
api = obsidian.Obsidian(api_key=api_key, host=obsidian_host, port=obsidian_port, protocol=obsidian_protocol)

files = api.list_files_in_dir(args["dirpath"])

Expand Down Expand Up @@ -116,7 +121,7 @@ def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | Embedded
if "filepath" not in args:
raise RuntimeError("filepath argument missing in arguments")

api = obsidian.Obsidian(api_key=api_key, host=obsidian_host)
api = obsidian.Obsidian(api_key=api_key, host=obsidian_host, port=obsidian_port, protocol=obsidian_protocol)

content = api.get_file_contents(args["filepath"])

Expand Down Expand Up @@ -159,7 +164,7 @@ def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | Embedded

context_length = args.get("context_length", 100)

api = obsidian.Obsidian(api_key=api_key, host=obsidian_host)
api = obsidian.Obsidian(api_key=api_key, host=obsidian_host, port=obsidian_port, protocol=obsidian_protocol)
results = api.search(args["query"], context_length)

formatted_results = []
Expand Down Expand Up @@ -218,7 +223,7 @@ def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | Embedded
if "filepath" not in args or "content" not in args:
raise RuntimeError("filepath and content arguments required")

api = obsidian.Obsidian(api_key=api_key, host=obsidian_host)
api = obsidian.Obsidian(api_key=api_key, host=obsidian_host, port=obsidian_port, protocol=obsidian_protocol)
api.append_content(args.get("filepath", ""), args["content"])

return [
Expand Down Expand Up @@ -271,7 +276,7 @@ def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | Embedded
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, host=obsidian_host)
api = obsidian.Obsidian(api_key=api_key, host=obsidian_host, port=obsidian_port, protocol=obsidian_protocol)
api.patch_content(
args.get("filepath", ""),
args.get("operation", ""),
Expand Down Expand Up @@ -320,7 +325,7 @@ def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | Embedded
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, host=obsidian_host)
api = obsidian.Obsidian(api_key=api_key, host=obsidian_host, port=obsidian_port, protocol=obsidian_protocol)
api.delete_file(args["filepath"])

return [
Expand Down Expand Up @@ -358,7 +363,7 @@ def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | Embedded
if "query" not in args:
raise RuntimeError("query argument missing in arguments")

api = obsidian.Obsidian(api_key=api_key, host=obsidian_host)
api = obsidian.Obsidian(api_key=api_key, host=obsidian_host, port=obsidian_port, protocol=obsidian_protocol)
results = api.search_json(args.get("query", ""))

return [
Expand Down Expand Up @@ -397,7 +402,7 @@ def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | Embedded
if "filepaths" not in args:
raise RuntimeError("filepaths argument missing in arguments")

api = obsidian.Obsidian(api_key=api_key, host=obsidian_host)
api = obsidian.Obsidian(api_key=api_key, host=obsidian_host, port=obsidian_port, protocol=obsidian_protocol)
content = api.get_batch_file_contents(args["filepaths"])

return [
Expand Down Expand Up @@ -437,7 +442,7 @@ def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | Embedded
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, host=obsidian_host)
api = obsidian.Obsidian(api_key=api_key, host=obsidian_host, port=obsidian_port, protocol=obsidian_protocol)
content = api.get_periodic_note(period)

return [
Expand Down Expand Up @@ -497,7 +502,7 @@ def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | Embedded
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, host=obsidian_host)
api = obsidian.Obsidian(api_key=api_key, host=obsidian_host, port=obsidian_port, protocol=obsidian_protocol)
results = api.get_recent_periodic_notes(period, limit, include_content)

return [
Expand Down Expand Up @@ -544,7 +549,7 @@ def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | Embedded
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, host=obsidian_host)
api = obsidian.Obsidian(api_key=api_key, host=obsidian_host, port=obsidian_port, protocol=obsidian_protocol)
results = api.get_recent_changes(limit, days)

return [
Expand Down