MCP Code Checker
MarcusJellinghaus/mcp-tools-py · 19 stars · Python · MIT
MCP server MCP server providing code quality checks (pylint and pytest) with smart LLM-friendly prompts for analysis and fixes. Enables Claude and other AI assistants to analyze your code and suggest improvements.
Install
The repo has no one-line install. Follow its README.
Files
MCP Tools Py
A Model Context Protocol (MCP) server providing code quality checking operations with easy client configuration. This server offers an API for performing code quality checks within a specified project directory, following the MCP protocol design.
Overview
This MCP server enables AI assistants like Claude (via Claude Desktop), VSCode with GitHub Copilot, or other MCP-compatible clients to run code quality checks, formatting and refactoring on Python projects. See Available Tools for the full list.
Scope: This server covers Python projects only. Support for other languages can be provided through separate, dedicated MCP servers with similar functionality.
Why a dedicated MCP server instead of bash access?
A general-purpose bash MCP tool allows more flexibility, but at the expense of less control. This server takes a more focused approach:
- Security: Only a defined set of tools can be executed — see Available Tools. All operations are scoped to the specified
project_dir. - Context management: Results are formatted and size-limited to reduce context load on the AI assistant. Output is structured as actionable prompts rather than raw tool output.
- Transparency: The server is open source, and detailed structured logging records every tool call with parameters, timing, and results.
Features
All tools are listed under Available Tools. The sections below document the parameters of the most-used ones.
Pylint Parameters
The pylint tools expose the following parameters for customization:
| Parameter | Type | Default | Description |
|---|---|---|---|
extra_args |
list | None | Optional list of additional pylint CLI arguments (e.g. ["--disable=W0611"]) |
target_directories |
list | None (auto-detected) | Directories to analyze relative to project_dir. Auto-detected from pyproject.toml when omitted |
max_issues |
integer | 1 | Number of issue types shown in detail; the rest are summarised as counts. 0 = counts only (per-rule count and directory split) |
Pylint Configuration
Pylint reads your project's pyproject.toml automatically. Control which issues
are reported by configuring [tool.pylint.messages_control] in your pyproject.toml.
See docs/pyproject-configuration.md for examples
and migration guidance.
Target Directory Auto-Detection
When target_directories is not specified, the tools that accept it (pylint, mypy, ruff
check, ruff fix, bandit, vulture, and run_format_code) auto-detect directories from
pyproject.toml:
- Source dirs from
[tool.setuptools.packages.find] where(fallback:["src"]) - Test dirs from
[tool.pytest.ini_options] testpaths(fallback:["tests"])
Only directories that exist on disk are included. You can override auto-detection by passing an explicit list:
["src"]- Analyze only source code directory["src", "tests"]- Analyze both source and test directories["mypackage", "tests"]- For projects with different package structures["."]- Analyze entire project directory (may be slow for large projects)
Pytest Parameters
run_pytest_check exposes the following parameters for customization:
| Parameter | Type | Default | Description |
|---|---|---|---|
markers |
list | None | Optional list of pytest markers to filter tests |
extra_args |
list | None | Optional list of additional pytest arguments; use -v/-vv/-vvv to control verbosity |
env_vars |
dictionary | None | Optional environment variables for the subprocess |
timeout_seconds |
integer | None (resolved from config, else 300) | Maximum seconds to wait for the test run. Positive integers only |
coverage |
boolean | False | Measure coverage with pytest-cov and append a coverage digest to the reply |
coverage_source |
list | None (auto-detected) | Directories to measure. Auto-detected from [tool.setuptools.packages.find] where, excluding test paths |
max_modules |
integer | 10 | How many modules the coverage digest details in each list |
Note: Parallel test execution is enabled by default using pytest-xdist (-n auto).
Coverage: coverage=True needs pytest-cov installed in the project's environment. The digest gives the total, the modules with the most missing statements and their per-function line ranges, the modules with nothing covered, and the test selection the numbers come from. The project's fail_under is reported but not applied, so pass/fail reflects the tests only. To exclude code, use coverage's own [tool.coverage.run] omit or # pragma: no cover.
Mypy Parameters
The mypy tools expose the following parameters for customization:
| Parameter | Type | Default | Description |
|---|---|---|---|
disable_error_codes |
list | None | List of mypy error codes to ignore |
target_directories |
list | None (auto-detected) | Directories to check relative to project_dir. Auto-detected from pyproject.toml when omitted |
follow_imports |
string | None (no flag sent; the project's [tool.mypy] decides) |
How to handle imports during type checking |
cache_dir |
string | None (no flag sent; MYPY_CACHE_DIR decides, else [tool.mypy] cache_dir, else .mypy_cache) |
Custom cache directory for incremental checking |
timeout_seconds |
integer | None (resolved from config, else 120) | Maximum seconds to wait for mypy. Positive integers only |
max_issues |
integer | None | Number of error codes shown in detail (5 locations each); the rest get one summary line each. None details every code; 0 = counts only (per-code count and directory split) |
Mypy Configuration
Mypy reads your project's pyproject.toml automatically, and [tool.mypy] is the
single source of truth for the flag set — the tool adds only output-formatting flags,
unless you pass follow_imports, cache_dir or disable_error_codes. A project with
no [tool.mypy] section of its own has no floor: with no config in scope it runs at
mypy's defaults and reports "passed" having checked very little; with a parent
directory's config (mypy 1.15 and later) or a user-level ~/.config/mypy/config or
~/.mypy.ini in scope it runs at those settings and can report errors the project
never asked for. See
docs/pyproject-configuration.md for migration
guidance and the effect on mypy's cache.
Command Line Interface (CLI)
Basic Usage
mcp-tools-py --project-dir /path/to/project [options]
Required Parameters
| Parameter | Type | Description |
|---|---|---|
--project-dir |
string | Required. Base directory for code checking operations |
Optional Parameters
Python Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
--python-executable |
string | sys.executable | Path to the Python interpreter of the project's environment. pytest, pylint and mypy run in it and library/symbol lookups resolve against it, so it must be the environment holding the project's dependencies. black, isort, ruff, bandit, vulture, tach and lint-imports come from mcp-tools-py's own environment and need not be installed here. A bare name is looked up on PATH; a path that neither exists nor resolves fails at startup |
--venv-path |
string | None | Deprecated, hidden from --help. Still accepted, and still resolves the interpreter (taking precedence over --python-executable), but no longer used to locate tools. Use --python-executable instead |
Test Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
--test-folder |
string | "tests" | Path to the test folder (relative to project-dir) |
--keep-temp-files |
flag | False | Keep temporary files after test execution. Useful for debugging when tests fail |
Logging Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
--log-level |
string | "INFO" | Set logging level. Choices: DEBUG, INFO, WARNING, ERROR, CRITICAL |
--log-file |
string | None | Path for structured JSON logs. If not specified, logs go to project_dir/logs/mcp_tools_py_{timestamp}.log |
--console-only |
flag | False | Log only to console: no default log file, and --log-file is ignored |
Tool Configuration
| Parameter | Type | Default | Description |
|---|---|---|---|
--check-timeout |
integer | None (120; pytest 300) | Timeout in seconds for every checker and formatter subprocess. Overridden per tool by [tool.mcp-tools-py] in the project's pyproject.toml — see Project configuration |
--refactoring-timeout |
integer | 120 | Timeout in seconds for rope refactoring operations |
--vulture-whitelist |
string | "vulture_whitelist.py" | Path to the vulture whitelist file, relative to project-dir. Auto-included by run_vulture_check when the file exists |
Notes
- When the deprecated
--venv-pathis specified, it takes precedence over--python-executable. Resolving the interpreter is now its only effect - The
--console-onlyflag is useful during development to avoid creating log files - Log files are created in JSON format for structured analysis
- Temporary files are automatically cleaned up unless
--keep-temp-filesis specified
Environment Configuration
Two environments are in play, and only one of them is configurable:
- project env — named by
--python-executable. It holds your project's dependencies, and pytest, pylint and mypy, which have to import those dependencies to do their work. Library and symbol resolution (get_library_source,list_symbols,find_references) follows the same interpreter, so pointing the flag at the wrong venv makes those tools resolve against the wrong packages. - tool env — where
mcp_tools_pyitself is installed. It supplies black, isort, ruff, bandit, vulture, tach and lint-imports, which are mcp-tools-py's own dependencies. It is not configurable.
Those seven therefore run at the tool env's versions, which may differ from what your project pins, so a project that cares about parity with its CI should keep compatible ranges in both places. lint-imports still checks your working tree: it runs from the tool env, but finds the project's root package, read from the import-linter config and located through the project interpreter. A custom contract_types entry inside that root package still resolves through the same bridge; one that lives in a separate distribution installed only in the project env does not, since only the root package's directory is handed over.
The first example below builds that path by interpolating an environment variable, so an unset or stale variable leaves --python-executable pointing nowhere. The server then fails at startup with a FileNotFoundError naming the flag, rather than starting up and reporting the project's tools as missing. A bare interpreter name such as python3 is looked up on PATH instead.
Correct Configuration
Point to the project's venv, with pytest, pylint and mypy installed in it, here on Windows:
{
"mcpServers": {
"mcp-tools-py": {
"command": "mcp-tools-py",
"args": [
"--project-dir", "/path/to/your/project",
"--python-executable", "${VIRTUAL_ENV}\\Scripts\\python.exe"
]
}
}
}
On macOS and Linux the interpreter sits in bin instead:
"--python-executable", "${VIRTUAL_ENV}/bin/python"
Incorrect Configuration
Do not point to an interpreter that is not the project's:
{
"mcpServers": {
"mcp-tools-py": {
"command": "mcp-tools-py",
"args": [
"--project-dir", "/path/to/your/project",
"--python-executable", "/usr/bin/python3"
]
}
}
}
A system interpreter, or any venv that is not the project's, reports pytest, pylint and mypy as missing and resolves library and symbol lookups against the wrong packages. Your project's own .venv fails the same way if those three are not installed in it — install them there rather than pointing the flag elsewhere.
Troubleshooting
- "Python interpreter not found" at startup:
--python-executablepoints at a path that doesn't exist — usually because the environment variable it interpolates is unset. The message names the flag that supplied the path. - "No module named pytest" (or pylint/mypy): Your
--python-executablepoints to an environment that doesn't have the required tools installed. Point it at the project's environment and install them there. - "ruff is not available" (or black/isort/bandit/vulture/tach/lint-imports): these console scripts come from the tool env, not from
--python-executable, so the flag is not the problem. They are dependencies of mcp-tools-py, and the message names the tool env directory searched: reinstall mcp-tools-py with its dependencies and restart the server. - After installing missing tools: pytest, pylint and mypy are answered by a probe of the configured interpreter that runs once and is cached for the process lifetime, so restart the MCP server after installing one of those three.
Installation
See INSTALL.md for detailed installation instructions.
Quick install:
# Install from GitHub (recommended) pip install git+https://github.com/MarcusJellinghaus/mcp-tools-py.git # Verify installation mcp-tools-py --help
Development install:
# Clone and install for development git clone https://github.com/MarcusJellinghaus/mcp-tools-py.git cd mcp-tools-py python -m venv .venv source .venv/bin/activate # On Windows: .venv\Scripts\activate pip install -e ".[dev]" mcp-tools-py --help
MCP Client Configuration
This server can be configured with mcp-config, a separate Python tool you install yourself — it is not a dependency of this package. It provides:
- Interactive setup: Works with Claude Desktop and VSCode
- Configuration management: Add, remove, and view server configurations
- Server repository: Access to curated MCP server collection
Prerequisites: Install Python, then install mcp-config separately.
Note: While other MCP clients like Windsurf and Cursor support MCP servers, they may require manual configuration.
Using as a Dependency
In requirements.txt
Add this line to your requirements.txt:
mcp-tools-py @ git+https://github.com/MarcusJellinghaus/mcp-tools-py.git
In pyproject.toml
Add to your project dependencies:
[project]
dependencies = [
"mcp-tools-py @ git+https://github.com/MarcusJellinghaus/mcp-tools-py.git",
# ... other dependencies
]
# Or as an optional dependency
[project.optional-dependencies]
dev = [
"mcp-tools-py @ git+https://github.com/MarcusJellinghaus/mcp-tools-py.git",
]
Installation Commands
After adding to requirements.txt or pyproject.toml:
# Install from requirements.txt pip install -r requirements.txt # Install from pyproject.toml pip install . # Or with optional dependencies pip install ".[dev]"
Running the Server
Using the CLI Command (Recommended)
After installation, you can run the server using the mcp-tools-py command:
mcp-tools-py --project-dir /path/to/project [options]
Using Python Module (Alternative)
You can also run the server as a Python module:
python -m mcp_tools_py --project-dir /path/to/project [options] # Or for development (from source directory) python -m src.main --project-dir /path/to/project [options]
For detailed information about all available command-line options, see the CLI section.
Project Structure Support
The server automatically detects and analyzes Python code in standard project structures:
Default Analysis:
src/directory (if present) - Main source codetests/directory (if present) - Test files
Custom Project Structures:
Use the target_directories parameter to specify different directories:
# For a package-based structure target_directories = ["mypackage", "tests"] # For a simple project with code in root target_directories = ["."] # For complex multi-module projects target_directories = ["module1", "module2", "shared", "tests"]
Structured Logging
The server provides comprehensive logging capabilities:
- Standard human-readable logs to console for development/debugging
- Structured JSON logs to file for analysis and monitoring
- Function call tracking with parameters, timing, and results
- Automatic error context capture with full stack traces
- Configurable log levels (DEBUG, INFO, WARNING, ERROR, CRITICAL)
- Default timestamped log files in
project_dir/logs/mcp_tools_py_{timestamp}.log
Example structured log entries:
{
"timestamp": "2025-08-05 14:30:15",
"level": "info",
"event": "Starting pylint check",
"project_dir": "/path/to/project",
"target_directories": ["src", "tests"],
"max_issues": 1
}
Use --console-only to disable file logging for simple development scenarios.
Quick MCP Client Setup
Automated Setup (Recommended)
-
First install the server:
pip install git+https://github.com/MarcusJellinghaus/mcp-tools-py.git
-
Configure with mcp-config (install it separately — it is not pulled in by this package):
mcp-config
Then select "Add New" and search for this server.
This will prompt you for your project directory and automatically configure your MCP client.
Note: mcp-config's server registry does not yet carry an entry for mcp-tools-py, so use the Manual Setup below if it cannot find this server.
Manual Setup
If you prefer manual configuration, edit your MCP configuration file:
Claude Desktop (%APPDATA%\Claude\claude_desktop_config.json on Windows):
{
"mcpServers": {
"mcp-tools-py": {
"command": "mcp-tools-py",
"args": ["--project-dir", "/path/to/your/project"]
}
}
}
For development mode:
{
"mcpServers": {
"mcp-tools-py": {
"command": "python",
"args": [
"-m",
"src.main",
"--project-dir",
"/path/to/your/project"
],
"env": {
"PYTHONPATH": "/path/to/mcp-tools-py"
}
}
}
}
VSCode (.vscode/mcp.json):
{
"servers": {
"mcp-tools-py": {
"command": "mcp-tools-py",
"args": ["--project-dir", "."]
}
}
}
VSCode development mode:
{
"servers": {
"mcp-tools-py": {
"command": "python",
"args": ["-m", "src.main", "--project-dir", "."],
"env": {
"PYTHONPATH": "/path/to/mcp-tools-py"
}
}
}
}
Testing with MCP Inspector
npx @modelcontextprotocol/inspector mcp-tools-py --project-dir /path/to/project
Available Tools
The server exposes 17 MCP tools.
| Tool | What it does |
|---|---|
run_pylint_check |
Static analysis; findings returned as an LLM-actionable prompt |
run_pytest_check |
Runs the test suite, parses the JSON report, summarises failures |
run_mypy_check |
Type checking driven by the project's [tool.mypy], with configurable error codes |
run_ruff_check |
Ruff lint analysis, read-only |
run_ruff_fix |
Applies ruff's safe fixes in place; unsafe fixes are opt-in |
run_bandit_check |
Security lint |
run_vulture_check |
Dead-code detection against vulture_whitelist.py |
run_tach_check |
Architectural boundary validation from tach.toml |
run_lint_imports_check |
Import-contract validation from .importlinter |
run_format_code |
Runs isort then black, or ruff's import sort then ruff format, as pyproject.toml declares; check_only reports without writing |
list_symbols |
Top-level functions, classes and variables in a file |
find_references |
All references to a symbol across the project |
move_symbol |
Moves top-level symbols to another module, updating imports |
rename_symbol |
Renames a module-level symbol project-wide |
move_module |
Moves a module into another package, updating references |
get_library_source |
Resolves a dotted import path in the configured project environment and returns its source |
sleep |
Pauses execution for a given number of seconds |
Parameters for pylint, pytest and mypy are documented under Features.
Development
Setting up the development environment
# Clone the repository git clone https://github.com/MarcusJellinghaus/mcp-tools-py.git cd mcp-tools-py # Create and activate a virtual environment python -m venv .venv # On Windows: .venv\Scripts\activate # On Unix/MacOS: source .venv/bin/activate # Install dependencies pip install -e . # Install development dependencies pip install -e ".[dev]"
Running with MCP Dev Tools
# Set the PYTHONPATH and run the server module using mcp dev set PYTHONPATH=. && mcp dev src/server.py
License
This project is licensed under the MIT License - see the LICENSE file for details.
The MIT License is a permissive license that allows reuse with minimal restrictions. It permits use, copying, modification, and distribution with proper attribution.
Links
Facts
- Kind
- MCP server
- Group
- Uncategorized
- Stars
- 19
- License
- MIT
- Language
- Python
- Last push
- 2026-10-05
- Forks
- 4
- Topics
- mcp, mcp-server, pylint, pytest, python
- 1REAio.github.morluto/reaReverse engineer anything from your terminal or agent with one CLI and MCP server.125.3k
- 2com.browser-use/browser-usecom.browser-use/browser-useControl a real Chrome browser to complete any task: fill forms, extract data, book flights.117.7k
- 3World Monitorapp.worldmonitor/mcpLive markets, conflicts, country risk, chokepoints, energy, and China decision signals. 93 tools.88.3k
- 4Scrapling MCP Serverd4vinci/scrapling🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl! Don't be shy, join here: https://discord.gg/EMgGbDceNQ and follow here for daily tips and tricks: https://x.com/Scraplingdev86.9k
- 5Everythingmodelcontextprotocol/serversThis MCP server attempts to exercise all the features of the MCP protocol. It is not intended to be a useful server, but rather a test server for builders of MCP clients. It implements prompts, tools, resources, sampling, and more to showcase MCP capabilities.85.8k
- 6Fetchmodelcontextprotocol/serversA Model Context Protocol server that provides web content fetching capabilities. This server enables LLMs to retrieve and process content from web pages, converting HTML to markdown for easier consumption.85.8k