fix: Replace sys.exit() with exception in config validation
Fixes MCP server hanging when bd executable is not found at default path. Problem: - Config validation used sys.exit(1) on failure - sys.exit() hangs in async MCP server context (doesn't properly terminate) - Default bd path was hardcoded to ~/.local/bin/bd Solution: 1. Use shutil.which() to find bd in PATH before falling back to default 2. Raise ConfigError instead of calling sys.exit() 3. MCP server now properly fails with error message instead of hanging This fixes the multi-minute hang when trying to use MCP tools if bd is installed in a non-default location (e.g., /usr/local/bin/bd). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""Configuration for beads MCP server."""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
@@ -11,9 +12,17 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||
def _default_beads_path() -> str:
|
||||
"""Get default bd executable path.
|
||||
|
||||
First tries to find bd in PATH, falls back to ~/.local/bin/bd.
|
||||
|
||||
Returns:
|
||||
Default path to bd executable (~/.local/bin/bd)
|
||||
Default path to bd executable
|
||||
"""
|
||||
# Try to find bd in PATH first
|
||||
bd_in_path = shutil.which("bd")
|
||||
if bd_in_path:
|
||||
return bd_in_path
|
||||
|
||||
# Fall back to common install location
|
||||
return str(Path.home() / ".local" / "bin" / "bd")
|
||||
|
||||
|
||||
@@ -84,6 +93,12 @@ class Config(BaseSettings):
|
||||
return v
|
||||
|
||||
|
||||
class ConfigError(Exception):
|
||||
"""Configuration error with helpful message."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
def load_config() -> Config:
|
||||
"""Load and validate configuration from environment variables.
|
||||
|
||||
@@ -91,13 +106,13 @@ def load_config() -> Config:
|
||||
Validated configuration
|
||||
|
||||
Raises:
|
||||
SystemExit: If configuration is invalid
|
||||
ConfigError: If configuration is invalid
|
||||
"""
|
||||
try:
|
||||
return Config()
|
||||
except Exception as e:
|
||||
default_path = _default_beads_path()
|
||||
print(
|
||||
error_msg = (
|
||||
f"Configuration Error: {e}\n\n"
|
||||
+ "Environment variables:\n"
|
||||
+ f" BEADS_PATH - Path to bd executable (default: {default_path})\n"
|
||||
@@ -105,7 +120,7 @@ def load_config() -> Config:
|
||||
+ " BEADS_ACTOR - Actor name for audit trail (default: $USER)\n"
|
||||
+ " BEADS_NO_AUTO_FLUSH - Disable automatic JSONL sync (default: false)\n"
|
||||
+ " BEADS_NO_AUTO_IMPORT - Disable automatic JSONL import (default: false)\n\n"
|
||||
+ "Make sure bd is installed and the path is correct.",
|
||||
file=sys.stderr,
|
||||
+ "Make sure bd is installed and the path is correct."
|
||||
)
|
||||
sys.exit(1)
|
||||
print(error_msg, file=sys.stderr)
|
||||
raise ConfigError(error_msg) from e
|
||||
|
||||
Reference in New Issue
Block a user