Skip to content

Environment Variable Default Parameters Not Respected at Runtime #86

@fred-levernet

Description

@fred-levernet

Disclaimer: I am not a developer but I investigated this issue for my personal use case with the help of Claude Sonnet 4. Hope this helps.

Deployed using the dockerized version https://github.com/docker/mcp-obsidian

Summary

The MCP Obsidian server fails to connect to Obsidian instances running on non-default ports (anything other than 27124) due to how environment variables are evaluated in default parameter values. When multiple Obsidian vaults are configured on different ports, only the vault on port 27124 works correctly, while others fail with authorization errors.

Root Cause

The issue is in src/mcp_obsidian/obsidian.py in the Obsidian class constructor:

python

def init(
self,
api_key: str,
protocol: str = os.getenv('OBSIDIAN_PROTOCOL', 'https').lower(),
host: str = str(os.getenv('OBSIDIAN_HOST', '127.0.0.1')),
port: int = int(os.getenv('OBSIDIAN_PORT', '27124')), # Problem here
verify_ssl: bool = False,
):

The os.getenv() calls in default parameters are evaluated when the module is imported, not when __init__() is called. This means if OBSIDIAN_PORT is not set during module import, it defaults to 27124 and never changes, even if the environment variable is set correctly at runtime.

Additionally, src/mcp_obsidian/tools.py doesn't explicitly pass the port parameter when instantiating the Obsidian class:

python

api = obsidian.Obsidian(api_key=api_key, host=obsidian_host) # port not passed

This relies on the default parameter behavior, which is broken.

Solution

Option 1 (Recommended): Read environment variables inside __init__() instead of as default parameters:

python

def init(
self,
api_key: str,
protocol: str = None,
host: str = None,
port: int = None,
verify_ssl: bool = False,
):
self.api_key = api_key

protocol = protocol or os.getenv('OBSIDIAN_PROTOCOL', 'https')
self.protocol = 'http' if protocol.lower() == 'http' else 'https'

self.host = host or os.getenv('OBSIDIAN_HOST', '127.0.0.1')
self.port = port if port is not None else int(os.getenv('OBSIDIAN_PORT', '27124'))
self.verify_ssl = verify_ssl
self.timeout = (3, 6)

Option 2: Explicitly pass the port in tools.py:

python

# At the top of tools.py with other environment variables obsidian_port = int(os.getenv("OBSIDIAN_PORT", "27124"))

# In each tool handler's run_tool method api = obsidian.Obsidian(api_key=api_key, host=obsidian_host, port=obsidian_port)

Reproduction

  1. Set up two Obsidian vaults with Local REST API plugin on different ports (e.g., 27124 and 27126)
  2. Configure two MCP servers with different OBSIDIAN_PORT values
  3. The server with port 27124 works, but the one with 27126 fails with "Error 40101: Authorization required"
  4. Despite OBSIDIAN_PORT=27126 being correctly set in the container environment, the code uses port 27124

Impact

This bug prevents users from running multiple MCP Obsidian servers to access different vaults simultaneously, which is a common use case for users managing multiple knowledge bases.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions