Skip to content

fix: replace python3 -m mempalace with CLI entry point (PEP 668)#410

Open
armujahid wants to merge 6 commits intoMemPalace:developfrom
armujahid:fix/pep668-cli-entrypoint
Open

fix: replace python3 -m mempalace with CLI entry point (PEP 668)#410
armujahid wants to merge 6 commits intoMemPalace:developfrom
armujahid:fix/pep668-cli-entrypoint

Conversation

@armujahid
Copy link
Copy Markdown

@armujahid armujahid commented Apr 9, 2026

Summary

  • Adds mempalace mcp-serve CLI subcommand to replace python3 -m mempalace.mcp_server
  • mcp-serve accepts --palace both before and after the subcommand (mempalace --palace /path mcp-serve and mempalace mcp-serve --palace /path)
  • Replaces all python3 -m mempalace invocations with the mempalace CLI entry point across both .claude-plugin/ and .codex-plugin/ (MCP configs, hook scripts, standalone hooks)
  • Updates docs (README, examples, instructions) to recommend uv tool install / pipx install as primary install methods
  • Backward compat preserved — python -m mempalace still works via __main__.py

Closes #408

Test plan

  • uv run pytest tests/test_cli.py — all 44 tests pass including new test_main_mcp_serve_dispatches and test_main_mcp_serve_palace_after_subcommand
  • mempalace mcp-serve starts the MCP server (reads JSON-RPC from stdin)
  • mempalace --palace /tmp/test mcp-serve and mempalace mcp-serve --palace /tmp/test both pass --palace through correctly
  • Verify no remaining python3 -m mempalace in plugin/hook files
  • Test on a PEP 668 system with uv tool install mempalace

@armujahid armujahid force-pushed the fix/pep668-cli-entrypoint branch from f14f4ba to 258fc91 Compare April 9, 2026 18:03
The plugin assumed python3 -m mempalace works, which breaks on modern
Linux (PEP 668), uv tool install, and pipx installs where the CLI
binary is on PATH but the module isn't importable by system python3.

- Add `mempalace mcp-serve` CLI subcommand to replace
  `python3 -m mempalace.mcp_server`
- Update MCP server configs in both .claude-plugin and .codex-plugin
- Update all hook scripts to use `mempalace` CLI directly
- Update docs to recommend uv/pipx install methods
- Backward compat preserved: python -m mempalace still works

Closes MemPalace#408
@armujahid armujahid force-pushed the fix/pep668-cli-entrypoint branch from 258fc91 to fa28be6 Compare April 9, 2026 18:08
@armujahid armujahid marked this pull request as ready for review April 9, 2026 18:09
@bgauryy
Copy link
Copy Markdown

bgauryy commented Apr 9, 2026

PR #410 Review: fix: replace python3 -m mempalace with CLI entry point (PEP 668)

URL: #410
Author: armujahid | Status: Draft | Branch: fix/pep668-cli-entrypointmain
Scope: 14 files | +52 / -24


Executive Summary

This PR adds a mempalace mcp-serve CLI subcommand and migrates all python3 -m mempalace invocations to the mempalace entry point across plugin configs, hook scripts, and documentation. It also updates install instructions to recommend uv tool install / pipx install for PEP 668 compliance. The change is well-scoped and mostly mechanical, but contains one medium-severity bug and one fragile implementation pattern that should be addressed before merge.

Recommendation: Request changes (2 issues to fix)


Ratings

Dimension Score Notes
Correctness 3/5 --palace passthrough via docstring is wrong for argparse subparsers
Security 5/5 No new attack surface
Performance 5/5 No performance implications
Maintainability 3/5 sys.argv manipulation pattern is fragile

Issues

1. [MEDIUM / HIGH confidence] Documentation bug: --palace position incorrect for argparse subparsers

Location: mempalace/mcp_server.py:5

The updated docstring says:

Install: claude mcp add mempalace -- mempalace mcp-serve [--palace /path/to/palace]

With the current argparse setup, --palace is defined on the parent parser (cli.py:~372), not on the mcp-serve subparser. Argparse requires parent-level optional arguments to appear before the subcommand:

  • mempalace --palace /path mcp-serve — works
  • mempalace mcp-serve --palace /pathraises "unrecognized arguments"

Any user following the docstring instruction would get a CLI error.

Fix (option A — fix the docs):

-Install: claude mcp add mempalace -- mempalace mcp-serve [--palace /path/to/palace]
+Install: claude mcp add mempalace -- mempalace --palace /path/to/palace mcp-serve

Fix (option B — better UX, add --palace to the subparser):

p_mcp_serve = sub.add_parser(
    "mcp-serve",
    help="Start the MCP server (JSON-RPC over stdin/stdout)",
)
p_mcp_serve.add_argument("--palace", default=None, help="Path to palace directory")

Option B is preferred since users naturally expect mempalace mcp-serve --palace /path.


2. [MEDIUM / HIGH confidence] Fragile sys.argv manipulation pattern in cmd_mcp_serve

Location: mempalace/cli.py:236-240 (on PR branch)

def cmd_mcp_serve(args):
    """Start the MCP server (JSON-RPC over stdin/stdout)."""
    sys.argv = ["mempalace-mcp-server"] + (["--palace", args.palace] if args.palace else [])
    from .mcp_server import main as mcp_main
    mcp_main()

This works by overwriting sys.argv before the import, relying on mcp_server.py's module-level _parse_args() executing at import time to pick up the modified sys.argv.

This is fragile because:

  • If mcp_server is already imported (e.g., by a test harness, a pre-import, or a future refactor), the module-level _parse_args() won't re-run, and --palace is silently lost
  • It mutates global sys.argv state, which is a side-effect hazard

Fix — set the env var directly (same mechanism mcp_server._parse_args uses internally):

def cmd_mcp_serve(args):
    """Start the MCP server (JSON-RPC over stdin/stdout)."""
    if args.palace:
        os.environ["MEMPALACE_PALACE_PATH"] = os.path.abspath(args.palace)
    from .mcp_server import main as mcp_main
    mcp_main()

This is idempotent, doesn't rely on import ordering, and uses the same MEMPALACE_PALACE_PATH env var that mcp_server.py already respects.


What Looks Good

  • Backward compat preserved: python -m mempalace still works via __main__.py which imports cli.main()
  • Entry point is correct: pyproject.toml has mempalace = "mempalace:main" which resolves through __init__.py to cli.main()
  • Consistent migration: All 6 plugin/hook files are updated from python3 -m mempalace to mempalace entry point
  • PEP 668 guidance: instructions/init.md now correctly recommends uv tool install / pipx install and explains the externally-managed-environment error
  • Test follows existing patterns: test_main_mcp_serve_dispatches mirrors the dispatch test pattern used by other subcommands

Minor Observations (Non-blocking)

  • The test only validates dispatch routing (patches cmd_mcp_serve and checks it's called). A test for the actual --palace forwarding behavior would catch issue Integrating MemPalace with SoulForge's code intelligence system #2 above, but this is consistent with how all other commands are tested.
  • hooks/mempal_precompact_hook.sh and hooks/mempal_save_hook.sh now call mempalace mine instead of python3 -m mempalace mine — this requires mempalace to be on PATH, which is guaranteed by uv tool install / pipx install but not by pip install -e . in a venv unless the venv is activated.

Flow Impact

Changed Symbol Type Callers Affected
cmd_mcp_serve (new) New function Called only from main() dispatch table
mcp-serve subparser (new) New CLI command User-facing; no internal callers
Hook scripts (modified) Shell scripts Called by Claude Code / Codex harnesses

Blast radius is low — this is additive (new subcommand) with string replacements in configs/hooks.

Use argparse.SUPPRESS as default for the mcp-serve --palace argument
so it doesn't overwrite the parent parser's value when omitted.
Both forms now work: mempalace --palace /path mcp-serve
                     mempalace mcp-serve --palace /path
- Apply os.path.expanduser() to --palace in cmd_mcp_serve so tilde
  paths from MCP JSON configs resolve correctly
- Use mempalace status instead of pip show to detect existing installs
  (pip show misses uv/pipx installs)
- Add test_cmd_mcp_serve_expands_tilde to verify ~ is expanded before
  forwarding --palace to the MCP server
- Fix init.md wording: say "report that mempalace is installed" instead
  of "report the version" since there is no --version flag
@armujahid
Copy link
Copy Markdown
Author

@bgauryy Thanks for the thorough review! All issues have been addressed:

Fixed:

  1. --palace position bug (Medium) — Added --palace to the mcp-serve subparser with default=argparse.SUPPRESS so both forms work: mempalace --palace /path mcp-serve and mempalace mcp-serve --palace /path. Tests cover both argument orders (test_main_mcp_serve_palace_after_subcommand, test_main_mcp_serve_palace_before_subcommand).

  2. ~ expansion for non-shell launchers (Medium)cmd_mcp_serve now calls os.path.expanduser() before forwarding --palace, so tilde paths from MCP JSON configs resolve correctly. Covered by test_cmd_mcp_serve_expands_tilde.

  3. Install detection misses uv/pipx (Low)instructions/init.md now uses mempalace status instead of pip show mempalace to detect existing installs.

Not changed (by design):

  • sys.argv rewrite pattern in cmd_mcp_serve — acknowledged as fragile but low risk since mcp_server is never pre-imported in any code path. The env var alternative has its own downsides (leaks to child processes).

Current head: 928f610. Would appreciate a re-review when you get a chance.

…hon -m

The mcp guidance command was still telling users to use
python -m mempalace.mcp_server. Update to use the new CLI entry point.
Copy link
Copy Markdown

@web3guru888 web3guru888 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This overlaps significantly with #340 (messelink) — both replace python3 -m mempalace.mcp_server for pipx/uv compatibility. Worth noting the differences:

#340 (messelink) #410 (this PR)
MCP entry mempalace-mcp (separate entry point) mempalace mcp-serve (subcommand)
Hook scripts Use mempalace CLI Use mempalace CLI
Docs Updated Updated + recommends uv/pipx
Tests None added 4 new CLI tests
pyproject.toml Adds entry point No entry point added

This PR is more thorough (tests, --palace forwarding both before/after subcommand, tilde expansion for non-shell launchers). The subcommand approach has the advantage of keeping everything under one binary.

The cmd_mcp_serve implementation is well thought out — especially the sys.argv rewriting to pass --palace through to mcp_server.main(). The tilde expansion test caught a real edge case for MCP JSON configs where the shell doesn't expand ~.

Since these two PRs conflict, the maintainers should pick one approach. Both work; this one has better test coverage.

🔭 Reviewed as part of the MemPalace-AGI integration project — autonomous research with perfect memory. Community interaction updates are posted regularly on the dashboard.

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

Labels

area/cli CLI commands area/hooks Claude Code hook scripts (Stop, PreCompact, SessionStart) area/mcp MCP server and tools bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Plugin assumes python3 -m mempalace — breaks on modern Linux (PEP 668) and with uv/pipx

4 participants