MCP Server for DiscoPoP - Enables Claude to interact with DiscoPoP profiling and analysis tools
Project description
DiscoPoP MCP Server
A Model Context Protocol (MCP) server that exposes DiscoPoP functionality to Claude, enabling Claude to drive the full instrumentation pipeline and query static and dynamic data dependencies.
Overview
The DiscoPoP MCP Server bridges the gap between Claude and DiscoPoP's profiling and analysis tools. It allows Claude to:
- Instrument a project, run profiling, detect parallel patterns, and retrieve OpenMP patches
- Query static and dynamic data dependencies for arbitrary code regions to support code understanding, refactoring, and correctness checks
- Retrieve profiling information from executed instrumented code
- List and discover available profiling data and execution configurations
Features
- Standalone CLI executable - Run independently via command line
- Local deployment - Uses stdio for direct Claude integration
- Persistent daemon mode - Optional long-running server that keeps analysis data in memory between calls
- Automatic daemon launch - Spawns a daemon terminal on the first tool call when none is running
- Transparent fallback - Falls back to inline execution when no daemon is available
- Comprehensive logging - View all incoming calls and outgoing responses
- Type-safe - Full type hints throughout
- Extensible - Easy to add new tools and capabilities
Installation
Option 1: Install from source (Recommended for development)
cd mcp_server
pip install -e ".[dev]"
Option 2: Install as standalone package
pip install .
Option 3: Direct script usage
python mcp_server/server.py --debug
Quick Start
Run the server
discopop_mcp_server --debug
This starts the server in stdio mode, which is used by Claude. The --debug flag enables verbose logging.
Usage Examples
From the command line
# Default mode — proxy that routes to daemon if available, otherwise runs inline
discopop_mcp_server
# With debug logging
discopop_mcp_server --debug
# Persistent daemon — keeps analysis data in memory between calls
discopop_mcp_server --daemon
# Daemon on a custom port (default: 7777)
discopop_mcp_server --daemon --daemon-port 8888
Integration with Claude Code
Use the built-in setup flag for easy integration:
discopop_mcp_server --setup claude_code
This automatically configures Claude Code to use the server, handling virtual environment detection, configuration directory creation, and path resolution.
See SETUP_GUIDE.md for more options or CLAUDE_INTEGRATION.md for detailed setup instructions.
Available Tools
1. get_configurations
Retrieves the list of defined execution configurations from a target project.
Parameters:
project_path(string, required): Path to the target project
Looks for configuration directories under <project_path>/.discopop/project/configs/.
Example:
{
"project_path": "./my_project"
}
2. get_execution_results
Retrieves execution results from prior program executions.
Parameters:
project_path(string, required): Path to the target project
Reads <project_path>/.discopop/project/execution_results.json.
Example:
{
"project_path": "./my_project"
}
3. get_data_dependencies
Returns data dependencies (RAW, WAR, WAW) that cross or lie within a specified code region. Results contain both statically and dynamically identified dependencies — dynamic profiling correctly captures aliasing and other cases that pure static analysis cannot resolve.
Dependencies are grouped by direction:
incoming— source outside the region, sink insideoutgoing— source inside the region, sink outsideintra_region— both source and sink within the region
Parameters:
project_path(string, required): Absolute path to the project rootfile_path(string, required): Absolute path to the source filestart_line(integer, required): First line of the code region (inclusive)end_line(integer, required): Last line of the code region (inclusive)include_raw/include_war/include_waw(boolean, optional): Filter by dependency type (default: all true)include_incoming/include_outgoing/include_intra_region(boolean, optional): Filter by direction (default: all true)var_name(string, optional): Restrict results to a specific variable; automatically excludes incoming dependencies (aliasing safety)
This tool is cheap to call repeatedly — DetectionResult and FileMapping are cached in memory after the first load. Requires gather_data to have been run first.
Logging Output
The server logs all incoming and outgoing communication:
2026-05-19 10:30:00 - discopop-mcp - INFO - Starting DiscoPoP MCP Server (stdio mode)
2026-05-19 10:30:05 - discopop-mcp - INFO - → Incoming call: get_configurations
2026-05-19 10:30:05 - discopop-mcp - DEBUG - Arguments: {"project_path": "./my_project"}
2026-05-19 10:30:05 - discopop-mcp - INFO - ← Outgoing response: get_configurations
Enable --debug for full argument/response logging.
Testing
Run the test suite:
python -m unittest discover -s mcp_server -p "test_*.py" -v
Or with pytest:
pytest mcp_server/test_server.py -v
Guidelines for LLM Agents
LLM agents must not inspect
.discopopdirectories directly (e.g. via file reads, directory listings, or shell commands). All DiscoPoP data must be accessed exclusively through thediscopop_mcp_servertool calls.
Reading raw files from .discopop is wasteful and unreliable: the directory contains large binary files, intermediate artefacts, and serialised objects that are expensive to parse and consume a significant number of tokens. The MCP tools return pre-processed, structured summaries that contain exactly the information needed — at a fraction of the token cost.
If a piece of information appears to be missing from the available tools, the correct response is to use the tool that produces it (e.g. run gather_data before calling get_parallelization_patches or get_data_dependencies) rather than reading the underlying files directly.
Daemon Mode
By default, Claude Code spawns a fresh discopop_mcp_server process for each session. This is stateless — every tool call starts from scratch and any data loaded during the session (such as the DetectionResult produced by run_pattern_detection) is discarded when the session ends.
Daemon mode (--daemon) solves this by running a single long-lived server process that keeps its internal state alive across multiple tool calls and across multiple Claude sessions.
How it works
When Claude Code runs discopop_mcp_server (the default, no flags), the process acts as a proxy. No daemon connection is attempted at startup — the check is deferred until the first actual tool call, so idle sessions consume no extra resources.
On the first tool call:
- The proxy checks whether a daemon is already listening on
localhost:7777. - If no daemon is found, it attempts to automatically spawn one in a new terminal window using the first available terminal emulator (
gnome-terminal,xterm,konsole,alacritty,kitty, and others). - Once a daemon is reachable, the proxy opens a single persistent connection to it and forwards all subsequent tool calls through that connection for the lifetime of the Claude session.
- If the daemon cannot be reached (no graphical display, spawn timeout, or connection error), every tool call falls back to inline execution — the old stateless behaviour — so the server remains fully functional without a daemon.
Running the daemon manually
You can start the daemon yourself instead of relying on auto-spawn:
discopop_mcp_server --daemon
The terminal window stays open showing daemon logs. Press Ctrl+C to stop it.
Use --daemon-port to run on a non-default port (both the daemon and the proxy must use the same value):
# Terminal 1 — daemon
discopop_mcp_server --daemon --daemon-port 8888
# Claude Code config — proxy pointing at the same port
discopop_mcp_server --daemon-port 8888
Comparison
discopop_mcp_server (default) |
discopop_mcp_server --daemon |
|
|---|---|---|
| Who runs it | Claude Code (automatic) | You, manually (or auto-spawned on first tool call) |
| Lifetime | One Claude session | Until Ctrl+C |
| Daemon check timing | First tool call | N/A |
| State between tool calls | None | Kept alive in ToolContext |
DetectionResult cache |
Not applicable | Loaded once, reused across calls |
| Fallback if unavailable | Inline execution | N/A |
What is cached
The daemon's ToolContext maintains two caches:
DetectionResult— loaded from.discopop/explorer/detection_result_dump.jsonusingjsonpickleon the first call that needs it (e.g.get_data_dependencies,get_parallelization_patches). Subsequent calls skip the deserialization step entirely.FileMapping— loaded from.discopop/FileMapping.txton the first call toget_data_dependencies. Maps numeric file IDs to absolute source file paths.
Both caches are keyed by project_path and automatically invalidated when the underlying file's modification time changes (i.e., after gather_data runs again).
Architecture
Transport
The default (discopop_mcp_server) uses stdio for communication with Claude Code. The daemon (--daemon) uses SSE over HTTP (Starlette + uvicorn on localhost:7777). The proxy bridges between the two: it presents a stdio interface to Claude Code and forwards calls to the daemon over SSE.
Tool Handler Flow
- Claude calls a tool via stdio
- Proxy checks whether a daemon session is open
- If yes: forwards the call to the daemon over SSE
- If no: executes the tool inline
- Server logs the incoming call and outgoing response
- Response returned to Claude
Shipping to Users
Method 1: PyPI Package (Recommended)
- Update version in
pyproject.toml - Build:
python -m build - Publish:
python -m twine upload dist/* - Users install:
pip install discopop_mcp_server
Method 2: Source Distribution
Include in your DiscoPoP repository:
pip install git+https://github.com/discopop-tool/discopop.git#subdirectory=mcp_server
Method 3: Bundled Binary
Use PyInstaller to create standalone executables:
pip install pyinstaller
pyinstaller --onefile mcp_server/server.py --name discopop_mcp_server
Development
Adding New Tools
- Define tool schema in
_register_tools():
Tool(
name="your_tool",
description="...",
inputSchema={...}
)
- Add handler method:
def _handle_your_tool(self, arguments: dict[str, Any]) -> list[TextContent]:
self._log_call("your_tool", arguments)
# Implementation here
self._log_response("your_tool", result)
return [TextContent(type="text", text=json.dumps(result))]
- Register in tool call handler:
elif name == "your_tool":
return self._handle_your_tool(arguments)
Type Checking
mypy mcp_server/server.py
Troubleshooting
Claude setup issues
- Automatically configure Claude Code:
discopop_mcp_server --setup claude_code
- Verify the setup with:
discopop_mcp_server --verify claude_code
- See CLAUDE_INTEGRATION.md for detailed troubleshooting
Server won't start
- Check Python version (requires 3.8+)
- Verify MCP package is installed:
pip show mcp - Run with
--debugfor detailed error messages
Claude can't connect
- Verify server is running:
discopop_mcp_server --debug - Check claude configuration points to correct command
- Ensure stdio mode is being used (default)
- Check setup status:
discopop_mcp_server --status
Missing dependencies
# Install all dependencies
pip install -e ".[dev,sse]"
License
This software is part of DiscoPoP and is licensed under the 3-Clause BSD License. See the LICENSE file in the package base directory for details.
Support
For issues, questions, or contributions:
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file discopop_mcp_server-0.0.1a8.tar.gz.
File metadata
- Download URL: discopop_mcp_server-0.0.1a8.tar.gz
- Upload date:
- Size: 6.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b41ec2da215e62f788585dcba7ea9f2250deda7134f0ee1269a21788cb78df86
|
|
| MD5 |
c8f236a1b31442ab9b357518cd1a9440
|
|
| BLAKE2b-256 |
de6b74a5320cb24d98851ec3643b82b91d19c48d04b06b4c96a3ac37e3501173
|
Provenance
The following attestation bundles were made for discopop_mcp_server-0.0.1a8.tar.gz:
Publisher:
publish_mcp_server.yml on discopop-project/discopop
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
discopop_mcp_server-0.0.1a8.tar.gz -
Subject digest:
b41ec2da215e62f788585dcba7ea9f2250deda7134f0ee1269a21788cb78df86 - Sigstore transparency entry: 1968817482
- Sigstore integration time:
-
Permalink:
discopop-project/discopop@2d840a29e4d97a0118ea3ddff63eb00f7151472b -
Branch / Tag:
refs/tags/mcp_server_v0.0.1a8 - Owner: https://github.com/discopop-project
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish_mcp_server.yml@2d840a29e4d97a0118ea3ddff63eb00f7151472b -
Trigger Event:
push
-
Statement type:
File details
Details for the file discopop_mcp_server-0.0.1a8-py3-none-any.whl.
File metadata
- Download URL: discopop_mcp_server-0.0.1a8-py3-none-any.whl
- Upload date:
- Size: 6.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ab0b31d5967ac650cdd0a750fa75acd914a2d6875c0c4a8317ff98486dce8088
|
|
| MD5 |
2991d99a4925ab29bcb6831d48f5a048
|
|
| BLAKE2b-256 |
025acff557bc404b0373cc6bf9ab5bd9f6d6e3cec3745439bab85c2d2a0b10f3
|
Provenance
The following attestation bundles were made for discopop_mcp_server-0.0.1a8-py3-none-any.whl:
Publisher:
publish_mcp_server.yml on discopop-project/discopop
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
discopop_mcp_server-0.0.1a8-py3-none-any.whl -
Subject digest:
ab0b31d5967ac650cdd0a750fa75acd914a2d6875c0c4a8317ff98486dce8088 - Sigstore transparency entry: 1968817585
- Sigstore integration time:
-
Permalink:
discopop-project/discopop@2d840a29e4d97a0118ea3ddff63eb00f7151472b -
Branch / Tag:
refs/tags/mcp_server_v0.0.1a8 - Owner: https://github.com/discopop-project
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish_mcp_server.yml@2d840a29e4d97a0118ea3ddff63eb00f7151472b -
Trigger Event:
push
-
Statement type: