Skip to content

OpenDSS MCP server crashes on macOS arm64 before MCP initialize #47

Description

@trashchenkov

Summary

powermcp run opendss crashes during startup on macOS arm64 before the MCP server can complete initialize / list_tools.

In the same environment, other PowerMCP stdio servers start normally:

  • powermcp run pandapower: MCP initialize + list tools succeeds
  • powermcp run powerio: MCP initialize + list tools succeeds
  • powermcp run opendss: process exits; MCP client receives Connection closed

The failure appears to come from eager OpenDSS engine construction at import time:

# OpenDSS/core/engine.py
from py_dss_interface import DSS
from py_dss_toolkit import dss_tools

dss = DSS()
dss_tools.update_dss(dss)

On my macOS arm64 machine, DSS() raises before the FastMCP server is created, so MCP clients only see a generic connection failure.

Environment

  • PowerMCP commit tested: cc99f348b394766b9958962638b2b31dee982755
  • Installed package version: powermcp 0.1.3
  • Python: 3.12.11
  • Platform: macOS arm64
  • py-dss-interface: 2.2.1
  • py-dss-toolkit: 0.7.0

Reproduction

python -m powermcp run opendss

or via an MCP stdio client:

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

params = StdioServerParameters(
    command="python",
    args=["-m", "powermcp", "run", "opendss"],
)

async with stdio_client(params) as (read, write):
    async with ClientSession(read, write) as session:
        await session.initialize()
        await session.list_tools()

Actual behavior

The MCP client sees:

McpError: Connection closed

The server traceback ends with:

File ".../PowerMCP/OpenDSS/core/engine.py", line 6, in <module>
    dss = DSS()
File ".../py_dss_interface/DSS.py", line 93, in __init__
    os.chdir(self._dll_path)
AttributeError: 'DSS' object has no attribute '_dll_path'

Expected behavior

The OpenDSS MCP server should not crash before MCP initialization. Ideally it should either:

  1. initialize successfully, or
  2. expose the MCP tools and return an actionable structured error from OpenDSS tools when the backend cannot initialize, or
  3. fail during an explicit preflight/doctor step with a clear platform/dependency diagnostic before users add it to an MCP client config.

Proposed direction

Would you be open to a PR that makes OpenDSS backend initialization lazy?

The conservative fix would be:

  • do not construct py_dss_interface.DSS() at module import time;
  • let create_mcp() and initialize/list_tools complete even if the OpenDSS backend is unavailable on the current platform;
  • initialize DSS() on first OpenDSS tool call;
  • if backend initialization fails, return the existing _err(...) response shape with an actionable message instead of crashing the stdio process;
  • add a small regression test that server creation/listing tools does not instantiate DSS() or crash when DSS() is monkeypatched to raise.

This should be backwards-compatible for users where py_dss_interface already works: the default backend, tool names, and tool schemas would remain unchanged. The only behavior change would be that unsupported/misconfigured platforms get MCP-level diagnostics instead of a process-level Connection closed failure.

A separate follow-up could consider an optional opendssdirect.py / dss-python fallback for macOS, but I would keep that out of the first PR unless maintainers prefer that direction.

If this approach sounds acceptable, I can prepare a PR.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions