[PATCH 22/23] mcp-server: Restructure as Python package with dynamic paths
John Kacur <[email protected]>
| Newsgroups | org.kernel.vger.linux-rt-users |
|---|---|
| Message-ID | <[email protected]> |
Restructure the MCP server into a standard Python package to enable both development and system installation scenarios. Directory and file changes: - Rename mcp-server/ to rteval_mcp/ (Python package naming convention) - Rename server.py to rteval_server.py (avoid naming conflicts) - Add __init__.py with package metadata - Add __main__.py to enable 'python3 -m rteval_mcp' execution - Create rteval-mcp-server wrapper script for command-line execution - Update all test imports from 'server' to 'rteval_server' Configuration files now use relative paths instead of hardcoded paths: - manifest.json: ./rteval_mcp/rteval-mcp-server - .claude-plugin/plugin.json: ./rteval_mcp/rteval-mcp-server The wrapper script dynamically calculates paths: - Finds its own location using BASH_SOURCE - Sets PYTHONPATH only when running from git (detects .git directory) - For system installations, relies on standard site-packages location This approach supports both development from git (./rteval-cmd pattern) and future system packaging without path conflicts. Assisted-by: Claude:claude-sonnet-4-5 Signed-off-by: John Kacur <[email protected]> --- .../.claude-plugin/plugin.json | 6 ++-- {mcp-server => rteval_mcp}/DEMO.md | 0 {mcp-server => rteval_mcp}/DEPENDENCIES.md | 0 {mcp-server => rteval_mcp}/Makefile | 0 {mcp-server => rteval_mcp}/README.md | 4 +-- rteval_mcp/__init__.py | 13 ++++++++ rteval_mcp/__main__.py | 33 +++++++++++++++++++ {mcp-server => rteval_mcp}/manifest.json | 8 ++--- rteval_mcp/rteval-mcp-server | 21 ++++++++++++ .../server.py => rteval_mcp/rteval_server.py | 0 .../tests/test_histogram.py | 4 +-- .../tests/test_mcp_integration.py | 4 +-- .../tests/test_new_tools.py | 4 +-- .../tests/test_per_cpu_stats.py | 4 +-- 14 files changed, 82 insertions(+), 19 deletions(-) rename {mcp-server => rteval_mcp}/.claude-plugin/plugin.json (79%) rename {mcp-server => rteval_mcp}/DEMO.md (100%) rename {mcp-server => rteval_mcp}/DEPENDENCIES.md (100%) rename {mcp-server => rteval_mcp}/Makefile (100%) rename {mcp-server => rteval_mcp}/README.md (99%) create mode 100644 rteval_mcp/__init__.py create mode 100644 rteval_mcp/__main__.py rename {mcp-server => rteval_mcp}/manifest.json (70%) create mode 100755 rteval_mcp/rteval-mcp-server rename mcp-server/server.py => rteval_mcp/rteval_server.py (100%) rename {mcp-server => rteval_mcp}/tests/test_histogram.py (95%) rename {mcp-server => rteval_mcp}/tests/test_mcp_integration.py (98%) rename {mcp-server => rteval_mcp}/tests/test_new_tools.py (97%) rename {mcp-server => rteval_mcp}/tests/test_per_cpu_stats.py (97%) diff --git a/mcp-server/.claude-plugin/plugin.json b/rteval_mcp/.claude-plugin/plugin.json similarity index 79% rename from mcp-server/.claude-plugin/plugin.json rename to rteval_mcp/.claude-plugin/plugin.json index c3469c048524..e48d8c95c655 100644 --- a/mcp-server/.claude-plugin/plugin.json +++ b/rteval_mcp/.claude-plugin/plugin.json @@ -10,10 +10,8 @@ "keywords": ["rteval", "real-time", "latency", "testing", "timerlat", "cyclictest"], "mcpServers": { "rteval-mcp": { - "command": "python3", - "args": [ - "/home/jkacur/src/rteval/mcp-server/server.py" - ], + "command": "./rteval_mcp/rteval-mcp-server", + "args": [], "env": {} } } diff --git a/mcp-server/DEMO.md b/rteval_mcp/DEMO.md similarity index 100% rename from mcp-server/DEMO.md rename to rteval_mcp/DEMO.md diff --git a/mcp-server/DEPENDENCIES.md b/rteval_mcp/DEPENDENCIES.md similarity index 100% rename from mcp-server/DEPENDENCIES.md rename to rteval_mcp/DEPENDENCIES.md diff --git a/mcp-server/Makefile b/rteval_mcp/Makefile similarity index 100% rename from mcp-server/Makefile rename to rteval_mcp/Makefile diff --git a/mcp-server/README.md b/rteval_mcp/README.md similarity index 99% rename from mcp-server/README.md rename to rteval_mcp/README.md index 370aa0e9ca71..fc54c8074754 100644 --- a/mcp-server/README.md +++ b/rteval_mcp/README.md @@ -74,7 +74,7 @@ sudo dnf install python3-mcp python3-mcp+cli python3-lxml The MCP server includes a test suite to verify functionality: ```bash -cd mcp-server +cd rteval_mcp # Run all tests make test @@ -157,7 +157,7 @@ Which CPUs have the most variable latency? ### Using with MCP Inspector ```bash -mcp dev server.py +mcp dev rteval-mcp-server ``` ## Complete Tool Usage Guide diff --git a/rteval_mcp/__init__.py b/rteval_mcp/__init__.py new file mode 100644 index 000000000000..390f2bd0f8c0 --- /dev/null +++ b/rteval_mcp/__init__.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later +# +# rteval MCP Server package +# +# Copyright 2026 John Kacur <[email protected]> +# +"""rteval MCP Server - tools for analyzing rteval results.""" + +__version__ = "0.1.0" +__author__ = "John Kacur" +__email__ = "[email protected]" diff --git a/rteval_mcp/__main__.py b/rteval_mcp/__main__.py new file mode 100644 index 000000000000..2a027c57b0c9 --- /dev/null +++ b/rteval_mcp/__main__.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# SPDX-License-Identifier: GPL-2.0-or-later +# +# rteval MCP Server entry point +# +# Copyright 2026 John Kacur <[email protected]> +# +"""Entry point for running rteval MCP server as a module.""" + +import sys +import asyncio +from pathlib import Path + +# Add package directory to path for development mode +package_dir = Path(__file__).parent +sys.path.insert(0, str(package_dir)) + +from rteval_server import app, stdio_server + + +async def main(): + """Run the MCP server.""" + async with stdio_server() as (read_stream, write_stream): + await app.run( + read_stream, + write_stream, + app.create_initialization_options() + ) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/mcp-server/manifest.json b/rteval_mcp/manifest.json similarity index 70% rename from mcp-server/manifest.json rename to rteval_mcp/manifest.json index 6127dcd26774..a04732245efa 100644 --- a/mcp-server/manifest.json +++ b/rteval_mcp/manifest.json @@ -9,12 +9,10 @@ }, "server": { "type": "python", - "entry_point": "server.py", + "entry_point": "rteval-mcp-server", "mcp_config": { - "command": "python3", - "args": [ - "/home/jkacur/src/rteval/mcp-server/server.py" - ] + "command": "./rteval_mcp/rteval-mcp-server", + "args": [] } } } diff --git a/rteval_mcp/rteval-mcp-server b/rteval_mcp/rteval-mcp-server new file mode 100755 index 000000000000..34ce8a4d0e43 --- /dev/null +++ b/rteval_mcp/rteval-mcp-server @@ -0,0 +1,21 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# +# rteval MCP Server wrapper script +# +# Copyright 2026 John Kacur <[email protected]> +# +# This wrapper executes the rteval MCP server as a Python module. +# It works for both development (local git) and installed (system) versions. + +# Find the directory containing this script +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# Parent directory is where Python should search for rteval_mcp module +PARENT_DIR="$(dirname "$SCRIPT_DIR")" + +# Only set PYTHONPATH if running from a git development tree +if [ -d "${PARENT_DIR}/.git" ]; then + export PYTHONPATH="${PARENT_DIR}:${PYTHONPATH}" +fi + +exec python3 -m rteval_mcp "$@" diff --git a/mcp-server/server.py b/rteval_mcp/rteval_server.py similarity index 100% rename from mcp-server/server.py rename to rteval_mcp/rteval_server.py diff --git a/mcp-server/tests/test_histogram.py b/rteval_mcp/tests/test_histogram.py similarity index 95% rename from mcp-server/tests/test_histogram.py rename to rteval_mcp/tests/test_histogram.py index 917afb1aac93..c15763663958 100644 --- a/mcp-server/tests/test_histogram.py +++ b/rteval_mcp/tests/test_histogram.py @@ -13,9 +13,9 @@ Test script for histogram extraction and percentile calculation. import sys from pathlib import Path -# Add parent directory to path to import server module +# Add parent directory to path to import rteval_server module sys.path.insert(0, str(Path(__file__).parent.parent)) -from server import extract_histogram_data, calculate_percentiles +from rteval_server import extract_histogram_data, calculate_percentiles # Find test file relative to script location # From tests/ -> mcp-server/ -> rteval/ diff --git a/mcp-server/tests/test_mcp_integration.py b/rteval_mcp/tests/test_mcp_integration.py similarity index 98% rename from mcp-server/tests/test_mcp_integration.py rename to rteval_mcp/tests/test_mcp_integration.py index 0b5f2954a16f..543f4ea7c249 100644 --- a/mcp-server/tests/test_mcp_integration.py +++ b/rteval_mcp/tests/test_mcp_integration.py @@ -16,9 +16,9 @@ import sys import asyncio from pathlib import Path -# Add parent directory to path to import server module +# Add parent directory to path to import rteval_server module sys.path.insert(0, str(Path(__file__).parent.parent)) -from server import call_tool, list_tools +from rteval_server import call_tool, list_tools def find_test_data(): diff --git a/mcp-server/tests/test_new_tools.py b/rteval_mcp/tests/test_new_tools.py similarity index 97% rename from mcp-server/tests/test_new_tools.py rename to rteval_mcp/tests/test_new_tools.py index a81b23bbffbb..b178146d3e4d 100644 --- a/mcp-server/tests/test_new_tools.py +++ b/rteval_mcp/tests/test_new_tools.py @@ -12,9 +12,9 @@ import sys import asyncio from pathlib import Path -# Add parent directory to path to import server module +# Add parent directory to path to import rteval_server module sys.path.insert(0, str(Path(__file__).parent.parent)) -from server import extract_rteval_data +from rteval_server import extract_rteval_data async def test_find_best_worst(): diff --git a/mcp-server/tests/test_per_cpu_stats.py b/rteval_mcp/tests/test_per_cpu_stats.py similarity index 97% rename from mcp-server/tests/test_per_cpu_stats.py rename to rteval_mcp/tests/test_per_cpu_stats.py index 6ec07dbf39fe..851cbd710165 100644 --- a/mcp-server/tests/test_per_cpu_stats.py +++ b/rteval_mcp/tests/test_per_cpu_stats.py @@ -12,9 +12,9 @@ import sys import asyncio from pathlib import Path -# Add parent directory to path to import server module +# Add parent directory to path to import rteval_server module sys.path.insert(0, str(Path(__file__).parent.parent)) -from server import call_tool +from rteval_server import call_tool async def main(): -- 2.55.0