Skip to content

Commit f6e0a5b

Browse files
phernandezclaude
andauthored
fix: Speed up bm --version startup (#534)
Signed-off-by: phernandez <paul@basicmachines.co> Signed-off-by: Paul Hernandez <60959+phernandez@users.noreply.github.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 7624a20 commit f6e0a5b

2 files changed

Lines changed: 40 additions & 26 deletions

File tree

src/basic_memory/cli/commands/mcp.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,24 @@
11
"""MCP server command with streamable HTTP transport."""
22

33
import os
4+
from typing import Any, Optional
5+
46
import typer
5-
from typing import Optional
7+
from loguru import logger
68

79
from basic_memory.cli.app import app
810
from basic_memory.config import ConfigManager, init_mcp_logging
911

10-
# Import mcp instance (has lifespan that handles initialization and file sync)
11-
from basic_memory.mcp.server import mcp as mcp_server # pragma: no cover
1212

13-
# Import mcp tools to register them
14-
import basic_memory.mcp.tools # noqa: F401 # pragma: no cover
13+
class _DeferredMcpServer:
14+
def run(self, *args: Any, **kwargs: Any) -> None: # pragma: no cover
15+
from basic_memory.mcp.server import mcp as live_mcp_server
1516

16-
# Import prompts to register them
17-
import basic_memory.mcp.prompts # noqa: F401 # pragma: no cover
18-
from loguru import logger
17+
live_mcp_server.run(*args, **kwargs)
18+
19+
20+
# Keep module-level attribute for tests/monkeypatching while deferring heavy import.
21+
mcp_server = _DeferredMcpServer()
1922

2023

2124
@app.command()
@@ -47,6 +50,10 @@ def mcp(
4750
# Even when cloud_mode_enabled is True, stdio MCP runs locally and needs local API access.
4851
os.environ["BASIC_MEMORY_FORCE_LOCAL"] = "true"
4952

53+
# Import mcp tools/prompts to register them with the server
54+
import basic_memory.mcp.tools # noqa: F401 # pragma: no cover
55+
import basic_memory.mcp.prompts # noqa: F401 # pragma: no cover
56+
5057
# Initialize logging for MCP (file only, stdout breaks protocol)
5158
init_mcp_logging()
5259

src/basic_memory/cli/main.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,33 @@
11
"""Main CLI entry point for basic-memory.""" # pragma: no cover
22

3+
import sys
4+
import warnings
5+
36
from basic_memory.cli.app import app # pragma: no cover
47

5-
# Register commands
6-
from basic_memory.cli.commands import ( # noqa: F401 # pragma: no cover
7-
cloud,
8-
db,
9-
doctor,
10-
import_chatgpt,
11-
import_claude_conversations,
12-
import_claude_projects,
13-
import_memory_json,
14-
mcp,
15-
project,
16-
schema,
17-
status,
18-
tool,
19-
)
8+
def _version_only_invocation(argv: list[str]) -> bool:
9+
# Trigger: invocation is exactly `bm --version` or `bm -v`
10+
# Why: avoid importing command modules on the hot version path
11+
# Outcome: eager version callback exits quickly with minimal startup work
12+
return len(argv) == 1 and argv[0] in {"--version", "-v"}
13+
2014

21-
# Re-apply warning filter AFTER all imports
22-
# (authlib adds a DeprecationWarning filter that overrides ours)
23-
import warnings # pragma: no cover
15+
if not _version_only_invocation(sys.argv[1:]):
16+
# Register commands only when not short-circuiting for --version
17+
from basic_memory.cli.commands import ( # noqa: F401 # pragma: no cover
18+
cloud,
19+
db,
20+
doctor,
21+
import_chatgpt,
22+
import_claude_conversations,
23+
import_claude_projects,
24+
import_memory_json,
25+
mcp,
26+
project,
27+
schema,
28+
status,
29+
tool,
30+
)
2431

2532
warnings.filterwarnings("ignore") # pragma: no cover
2633

0 commit comments

Comments
 (0)