From baa8c0beae54f91481e77f7cba882e5e86fc0718 Mon Sep 17 00:00:00 2001 From: Codex Date: Sun, 5 Jul 2026 11:38:49 +0000 Subject: [PATCH] refactor: consolidate MCP service scripts Replace per-command shell wrappers with a single scripts/mcp_service.sh entrypoint that forwards subcommands to manage_mcp_service.py. Update docs and tests so remote MCP service management stays on the consolidated command surface. --- .env.example | 4 ++-- README.md | 14 +++++++------- scripts/manage_mcp_service.py | 2 +- scripts/{stop_mcp_service.sh => mcp_service.sh} | 2 +- scripts/new_mcp_service_token.sh | 5 ----- scripts/show_mcp_service_config.sh | 5 ----- scripts/start_mcp_service.sh | 5 ----- scripts/uninstall_mcp_service.sh | 5 ----- tests/test_mcp_service.py | 17 +++++++++++++++++ 9 files changed, 28 insertions(+), 31 deletions(-) rename scripts/{stop_mcp_service.sh => mcp_service.sh} (62%) delete mode 100755 scripts/new_mcp_service_token.sh delete mode 100755 scripts/show_mcp_service_config.sh delete mode 100755 scripts/start_mcp_service.sh delete mode 100755 scripts/uninstall_mcp_service.sh diff --git a/.env.example b/.env.example index 9900a27..41a7dd0 100644 --- a/.env.example +++ b/.env.example @@ -41,8 +41,8 @@ OBSIDIAN_MCP_EXPOSE_PATHS=false # Run locally: # OBSIDIAN_MCP_TOKEN='' obsidian-wiki-mcp --transport streamable-http # Or manage a user-level service: -# bash scripts/new_mcp_service_token.sh -# bash scripts/start_mcp_service.sh +# bash scripts/mcp_service.sh new-token +# bash scripts/mcp_service.sh start OBSIDIAN_MCP_TOKEN= OBSIDIAN_MCP_HOST=127.0.0.1 OBSIDIAN_MCP_PORT=8765 diff --git a/README.md b/README.md index f9b0e01..008f667 100644 --- a/README.md +++ b/README.md @@ -364,19 +364,19 @@ Client configuration example: For long-running access from another machine, use the managed user service: ```bash -bash scripts/new_mcp_service_token.sh -bash scripts/start_mcp_service.sh +bash scripts/mcp_service.sh new-token +bash scripts/mcp_service.sh start ``` -`new_mcp_service_token.sh` writes `.runtime/obsidian-wiki-mcp.env` with `0600` permissions and prints the remote URL, `Authorization` header, and client JSON. `start_mcp_service.sh` writes `~/.config/systemd/user/obsidian-wiki-mcp.service` and starts it. The service defaults to `0.0.0.0:8765/mcp` because it is intended for remote clients, but it still requires the bearer token. Prefer SSH tunnel, Tailscale, WireGuard, or another trusted network boundary instead of directly exposing the port to the public internet. +`mcp_service.sh new-token` writes `.runtime/obsidian-wiki-mcp.env` with `0600` permissions and prints the remote URL, `Authorization` header, and client JSON. `mcp_service.sh start` writes `~/.config/systemd/user/obsidian-wiki-mcp.service` and starts it. The service defaults to `0.0.0.0:8765/mcp` because it is intended for remote clients, but it still requires the bearer token. Prefer SSH tunnel, Tailscale, WireGuard, or another trusted network boundary instead of directly exposing the port to the public internet. Useful service commands: ```bash -bash scripts/show_mcp_service_config.sh -bash scripts/stop_mcp_service.sh -bash scripts/uninstall_mcp_service.sh -python3 scripts/manage_mcp_service.py status +bash scripts/mcp_service.sh show-config +bash scripts/mcp_service.sh stop +bash scripts/mcp_service.sh uninstall +bash scripts/mcp_service.sh status ``` ### `_raw/` Staging Directory diff --git a/scripts/manage_mcp_service.py b/scripts/manage_mcp_service.py index cbf0518..67a77d6 100755 --- a/scripts/manage_mcp_service.py +++ b/scripts/manage_mcp_service.py @@ -124,7 +124,7 @@ def write_token_env_file( def read_service_env_file(env_path: Path) -> dict[str, str]: if not env_path.exists(): - raise RuntimeError(f"Missing MCP service env file: {env_path}. Run scripts/new_mcp_service_token.sh first.") + raise RuntimeError(f"Missing MCP service env file: {env_path}. Run scripts/mcp_service.sh new-token first.") values: dict[str, str] = {} for raw_line in env_path.read_text(encoding="utf-8").splitlines(): diff --git a/scripts/stop_mcp_service.sh b/scripts/mcp_service.sh similarity index 62% rename from scripts/stop_mcp_service.sh rename to scripts/mcp_service.sh index f6c2683..8792009 100755 --- a/scripts/stop_mcp_service.sh +++ b/scripts/mcp_service.sh @@ -2,4 +2,4 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -exec python3 "$SCRIPT_DIR/manage_mcp_service.py" stop "$@" +exec python3 "$SCRIPT_DIR/manage_mcp_service.py" "$@" diff --git a/scripts/new_mcp_service_token.sh b/scripts/new_mcp_service_token.sh deleted file mode 100755 index ffb8023..0000000 --- a/scripts/new_mcp_service_token.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -exec python3 "$SCRIPT_DIR/manage_mcp_service.py" new-token "$@" diff --git a/scripts/show_mcp_service_config.sh b/scripts/show_mcp_service_config.sh deleted file mode 100755 index ca4a719..0000000 --- a/scripts/show_mcp_service_config.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -exec python3 "$SCRIPT_DIR/manage_mcp_service.py" show-config "$@" diff --git a/scripts/start_mcp_service.sh b/scripts/start_mcp_service.sh deleted file mode 100755 index e34e3de..0000000 --- a/scripts/start_mcp_service.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -exec python3 "$SCRIPT_DIR/manage_mcp_service.py" start "$@" diff --git a/scripts/uninstall_mcp_service.sh b/scripts/uninstall_mcp_service.sh deleted file mode 100755 index 8535178..0000000 --- a/scripts/uninstall_mcp_service.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -exec python3 "$SCRIPT_DIR/manage_mcp_service.py" uninstall "$@" diff --git a/tests/test_mcp_service.py b/tests/test_mcp_service.py index fc8e801..248b2db 100644 --- a/tests/test_mcp_service.py +++ b/tests/test_mcp_service.py @@ -15,6 +15,23 @@ import manage_mcp_service class McpServiceConfigTests(unittest.TestCase): + def test_service_commands_use_one_shell_entrypoint(self): + entrypoint = SCRIPTS_DIR / "mcp_service.sh" + legacy_wrappers = [ + "new_mcp_service_token.sh", + "start_mcp_service.sh", + "show_mcp_service_config.sh", + "stop_mcp_service.sh", + "uninstall_mcp_service.sh", + ] + + self.assertTrue(entrypoint.is_file()) + self.assertTrue(os.access(entrypoint, os.X_OK)) + content = entrypoint.read_text(encoding="utf-8") + self.assertIn('exec python3 "$SCRIPT_DIR/manage_mcp_service.py" "$@"', content) + for wrapper in legacy_wrappers: + self.assertFalse((SCRIPTS_DIR / wrapper).exists(), f"{wrapper} should be folded into mcp_service.sh") + def test_render_service_unit_uses_http_transport_without_embedding_token(self): unit = manage_mcp_service.render_service_unit( project_root=Path("/opt/obsidian-wiki"),