Skip to main content
Glama
shaynemeyer

obsidian-mcp

by shaynemeyer

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
OBSIDIAN_VAULTSNoInline JSON string that defines the vaults.
OBSIDIAN_API_KEYNoLegacy: API key for the Local REST API.
OBSIDIAN_READ_ONLYNoSet to 'true' to disable all mutating tools. Default is 'false'.false
OBSIDIAN_HEALTH_TTLNoSeconds to cache each vault's REST health probe. Default is '20'.20
OBSIDIAN_VAULT_PATHNoLegacy: path to the default vault.
OBSIDIAN_PREFER_RESTNoSet to 'false' to always use the filesystem backend. Default is 'true'.true
OBSIDIAN_VAULTS_FILENoPath to a TOML file that defines the vaults.
OBSIDIAN_DEFAULT_VAULTNoName of the default vault.
OBSIDIAN_REST_BASE_URLNoLegacy: base URL for the Local REST API.
OBSIDIAN_MAX_FILE_BYTESNoMaximum file size in bytes that will be read. Default is '2000000'.2000000
OBSIDIAN_REQUEST_TIMEOUTNoPer-request timeout in seconds. Default is '15'.15

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{
  "listChanged": false
}
prompts
{
  "listChanged": false
}
resources
{
  "subscribe": false,
  "listChanged": false
}
experimental
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
obsidian_list_vaultsA

List every configured vault, showing which one unqualified calls will hit.

Reads configuration only — it does not contact Obsidian, so it is cheap and safe to call first when you are unsure which vaults exist. For live reachability, use obsidian_backend_status.

Returns: str: JSON of the shape {"current_vault": str, "count": int, "vaults": [{"name": str, "description": str|null, "path": str|null, "rest_base_url": str|null, "backends": ["rest"|"filesystem"], "is_current": bool, "is_default": bool}]} On failure: "Error: "

obsidian_switch_vaultA

Change which vault subsequent unqualified tool calls target.

Changes this server session only — nothing in any vault is modified, and Obsidian's own open vault is unaffected. Prefer passing vault directly on a tool call for one-off access; switch when a long stretch of work lives in one vault. A vault argument on an individual call always overrides this.

Args: params (SwitchVaultInput): - vault (str): Name of the vault to make current

Returns: str: JSON of the shape {"status": "ok", "current_vault": str, "previous_vault": str, "path": str|null, "rest_base_url": str|null, "backends": ["rest"|"filesystem"]} On failure: "Error: Unknown vault ''. Configured vaults: ..."

obsidian_list_notesA

List notes and folders in the vault, optionally scoped to one folder.

Use this to discover the vault's structure before reading or writing. For finding a note by its contents, obsidian_search_notes is faster.

Args: params (ListNotesInput): - folder (str): Vault-relative folder, empty for the root - recursive (bool): Walk nested folders too - response_format (str): 'markdown' or 'json'

Returns: str: Markdown list, or JSON of the shape {"folder": str, "count": int, "backend": "rest"|"filesystem", "entries": [{"path": str, "is_folder": bool, "size_bytes": int, "modified_at": str}]} On failure: "Error: "

obsidian_read_noteA

Read a note's content plus its tags, frontmatter, and links.

Backlinks are only populated when Obsidian is running, since they come from Obsidian's own link index.

Args: params (ReadNoteInput): - path (str): Vault-relative path, '.md' optional - include_content (bool): False for metadata only - response_format (str): 'markdown' or 'json'

Returns: str: Markdown rendering, or JSON of the shape {"path": str, "content": str, "frontmatter": object, "tags": [str], "links": [str], "backlinks": [str], "size_bytes": int, "modified_at": str, "source": "rest"|"filesystem"} On failure: "Error: "

obsidian_search_notesA

Full-text search across the vault, returning matching notes with context.

When Obsidian is running this uses its native search index and results are ranked the way they would be in the app. Otherwise it falls back to scanning files directly, which matches all terms as substrings.

Args: params (SearchNotesInput): - query (str): Search text; all terms must be present to match - context_length (int): Characters of context per match, 10-1000 - limit (int): Maximum notes returned, 1-100 - response_format (str): 'markdown' or 'json'

Returns: str: Markdown results, or JSON of the shape {"query": str, "count": int, "backend": "rest"|"filesystem", "results": [{"path": str, "score": float, "context": [str]}]} On no matches: a message suggesting broader terms. On failure: "Error: "

obsidian_list_tagsA

List every tag in the vault with how many notes use it.

Useful for orienting in an unfamiliar vault, or checking which tag spelling is already in use before adding a new one.

Args: params (EmptyInput): - response_format (str): 'markdown' or 'json'

Returns: str: Markdown table, or JSON of the shape {"count": int, "backend": "rest"|"filesystem", "tags": {"": int}} Tag names have no leading '#'. Counts may be 0 when the REST backend reports tags without usage data. On failure: "Error: "

obsidian_get_active_noteA

Read whichever note is currently open in the Obsidian window.

Requires Obsidian to be running with the Local REST API plugin — there is no filesystem equivalent of "the active note".

Args: params (EmptyInput): - response_format (str): 'markdown' or 'json'

Returns: str: Same shape as obsidian_read_note. On failure: "Error: Cannot read the active note: "

obsidian_backend_statusA

Report, per vault, which backend is live and which capabilities are usable.

Call this first when a tool fails with a connectivity error, or when you need to know whether backlinks, the active note, and commands work right now. With no vault named it probes every configured vault.

Set verify=true to cross-check that each vault's REST port is really serving the vault at its configured path. Worth doing after adding a vault or changing ports, since every vault's plugin defaults to port 27124 and they collide.

Args: params (StatusInput): - vault (Optional[str]): One vault to check; omit to check all - verify (bool): Also cross-check REST endpoint against vault path - response_format (str): unused; JSON is always returned

Returns: str: JSON of the shape {"current_vault": str, "read_only": bool, "vaults": [{"vault": str, "rest_configured": bool, "rest_reachable": bool, "rest_base_url": str|null, "filesystem_configured": bool, "vault_path": str|null, "active_backend": "rest"|"filesystem", "obsidian_only_features_available": bool, "is_current": bool, "identity": {...}}]} On failure: "Error: "

obsidian_write_noteA

Create a note, or fully replace an existing one.

This overwrites the entire file. To add to a note without losing what is already there, use obsidian_append_to_note or obsidian_patch_note instead. Parent folders are created as needed.

Args: params (WriteNoteInput): - path (str): Vault-relative path - content (str): Complete markdown content - overwrite (bool): Required to replace an existing note

Returns: str: JSON of the shape {"status": "ok", "action": "created"|"replaced", "path": str, "backend": "rest"|"filesystem"} On failure: "Error: "

obsidian_append_to_noteA

Add markdown to the end of a note, creating the note if it does not exist.

Safe by design: nothing already in the note is modified. Repeated calls append repeatedly.

Args: params (AppendNoteInput): - path (str): Vault-relative path - content (str): Markdown to append

Returns: str: JSON of the shape {"status": "ok", "action": "appended", "path": str, "backend": "rest"|"filesystem"} On failure: "Error: "

obsidian_patch_noteA

Insert content at a specific heading, block reference, or frontmatter key.

This is the surgical option: it edits one section and leaves the rest of the note byte-for-byte unchanged. Read the note first to confirm the target exists — a missing heading or block ID is an error, not a silent no-op.

Args: params (PatchNoteInput): - path (str): Vault-relative path to an existing note - target_type (str): 'heading', 'block', or 'frontmatter' - target (str): Heading text ('::' separates nesting levels), block ID without '^', or frontmatter key - content (str): Markdown to insert, or the frontmatter value - operation (str): 'append', 'prepend', or 'replace'

Returns: str: JSON of the shape {"status": "ok", "action": "patched", "path": str, "backend": "rest"|"filesystem"} On failure: "Error: ", including when the target heading or block ID does not exist.

Examples: - Add today's entry under a Log heading -> target_type='heading', target='Log', operation='append' - Set a status field -> target_type='frontmatter', target='status', content='active', operation='replace'

obsidian_append_to_daily_noteA

Append to the daily note for today or a given date, creating it if needed.

The daily note path is built from OBSIDIAN_DAILY_FOLDER and OBSIDIAN_DAILY_FORMAT, so it works whether or not Obsidian is running.

Args: params (DailyNoteInput): - content (str): Markdown to append - day (Optional[str]): ISO date 'YYYY-MM-DD'; defaults to today - heading (Optional[str]): Append under an existing heading instead of at the end of the note

Returns: str: JSON of the shape {"status": "ok", "action": "appended"|"patched", "path": str, "backend": "rest"|"filesystem", "note": str} On failure: "Error: "

obsidian_move_noteA

Move or rename a note, creating destination folders as needed.

Wikilinks elsewhere in the vault are NOT rewritten — Obsidian only updates links when the move happens inside the app. Search for links to the old name afterwards if that matters.

Args: params (MoveNoteInput): - source (str): Current vault-relative path - destination (str): New vault-relative path - overwrite (bool): Replace the destination if it exists

Returns: str: JSON of the shape {"status": "ok", "action": "moved", "path": str, "backend": "rest"|"filesystem", "note": str} On failure: "Error: "

obsidian_delete_noteA

Delete a note, by default into the vault's .trash folder.

A default delete is recoverable: the note moves to '.trash' inside the vault and can be restored from Obsidian. Pass permanent=true only when the note should be unrecoverable.

Args: params (DeleteNoteInput): - path (str): Vault-relative path to delete - permanent (bool): True deletes outright and cannot be undone

Returns: str: JSON of the shape {"status": "ok", "action": "trashed"|"deleted", "path": str, "backend": "rest"|"filesystem", "note": str} where path is the .trash location for a recoverable delete. On failure: "Error: "

obsidian_open_noteA

Bring a note up in the Obsidian window.

Changes what the user sees but not the vault's contents. Requires Obsidian to be running with the Local REST API plugin.

Args: params (OpenNoteInput): - path (str): Vault-relative path to open

Returns: str: JSON {"status": "ok", "action": "opened", "path": str, "backend": "rest"} On failure: "Error: "

obsidian_list_commandsA

List every command in Obsidian's command palette, with IDs for running them.

Requires Obsidian to be running with the Local REST API plugin.

Returns: str: JSON of the shape {"count": int, "commands": [{"id": str, "name": str}]} On failure: "Error: "

Args: params (VaultOnlyInput): - vault (Optional[str]): Which vault's Obsidian window to query

obsidian_run_commandA

Run a command from Obsidian's command palette by ID.

Effects depend entirely on the command — some only change the view, others modify notes or invoke other plugins. Check obsidian_list_commands for valid IDs and prefer a specific tool when one exists.

Args: params (RunCommandInput): - command_id (str): ID from obsidian_list_commands

Returns: str: JSON {"status": "ok", "action": "executed", "command_id": str, "backend": "rest"} On failure: "Error: "

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

TDQS

A4.2/5.0

Scored across 17 tools

Disambiguation5/5

Every tool targets a distinct resource and action: reading (read_note, get_active_note), discovery (list_notes, search_notes, list_tags), writing (write_note, append_to_note, patch_note), and vault administration (list_vaults, switch_vault, backend_status). Overlapping write tools are clearly differentiated by insertion point and cross-reference each other.

Naming Consistency4/5

The overwhelming majority follow the obsidian_verb_noun pattern (list_notes, read_note, write_note, delete_note, run_command). Only obsidian_backend_status deviates by using a noun-noun name instead of a verb such as get_status or get_backend_status.

Tool Count4/5

17 tools is slightly above the ideal 3-15 range, but each tool earns its place covering vaults, notes, search, commands, and status. The granularity between append, patch, and append_to_daily_note is justified by real workflow differences.

Completeness4/5

Note CRUD is fully covered (create via write, read, update via write/append/patch, move, delete), plus discovery, search, tag listing, vault management, and Obsidian command execution. Minor gaps exist—such as no restore-from-trash tool and no explicit folder creation—but agents can work around them.

Maintenance

ActivitySlowing
ResponsivenessNo issues