使用说明
Makefile MCP Server
A Model Context Protocol (MCP) server that exposes Makefile targets as executable tools for AI assistants.
Features
- Dynamic make target tools: every Makefile target becomes an executable tool named
make_<target>(e.g.make_build,make_test,make_clean) list_available_targets: list every make target the server exposes, with descriptions and tool namesget_makefile_info: detailed information about the Makefile and the include/exclude filtering configurationget_output: page through the full cached stdout/stderr of any previous execution byexecution_idsearch_output: search a previous execution's full cached output for a literal substring, with surrounding context- Target discovery: Makefiles are parsed automatically to discover targets and descriptions
- Comment-based descriptions: comments above a target become its tool description
- Include/exclude filtering:
--includeand--excludecontrol which targets are exposed as tools - Dry-run mode: call any target tool with
dry_run=trueto preview recipes with make's-n; Makefile expansion and recursive make may still have side effects (a tool parameter — the server itself takes no--dry-runCLI flag) - Bounded responses, full output retained: inline responses carry a configurable tail of each stream plus line/char totals; the complete output stays addressable through the
execution_id
Install
# Run directly from GitHub (no install needed)
uvx --from git+https://github.com/wdm0006/makefile-mcp makefile-mcp --makefile /path/to/Makefile
# Or install from source
git clone https://github.com/wdm0006/makefile-mcp
cd makefile-mcp
uv sync
uv run makefile_mcp.py --makefile /path/to/Makefile
Usage
# Use default Makefile in current directory
makefile-mcp
# Use specific Makefile
makefile-mcp --makefile /path/to/Makefile
# Include only specific targets
makefile-mcp --include build,test,clean
# Exclude specific targets
makefile-mcp --exclude deploy,publish
# Custom working directory
makefile-mcp --working-dir /path/to/project
# Keep 50 cached executions instead of the default 20
makefile-mcp --max-cached-executions 50
# Include only the last 10 lines of each stream inline
makefile-mcp --tail-lines 10
# Kill targets that run longer than 60 seconds
makefile-mcp --timeout 60
Filter names are checked against the targets the Makefile actually defines. An
--exclude name that is not a target is a startup error: the server reports every
unknown entry on stderr and exits non-zero rather than serving with a filter that hides
nothing — so a typo, or a target renamed out from under the configuration, cannot
silently re-expose something you meant to hide. An unknown --include name only warns
and startup continues, because an include filter that names a missing target already
fails closed, and one client configuration may point at several Makefiles with
different target sets.
CLI reference
| Flag | Default | Meaning |
|---|---|---|
--makefile PATH |
Makefile |
Makefile to parse and execute |
--include a,b |
all targets | expose only these targets; an unknown name warns |
--exclude a,b |
none | hide these targets; an unknown name is a startup error |
--working-dir PATH |
the Makefile's directory | directory make runs in |
--max-cached-executions N |
20 |
how many executions stay cached; the oldest is evicted first, so old execution_ids eventually expire |
--tail-lines N |
50 |
lines of each stream included inline in make tool responses |
--timeout SECONDS |
300 |
kill a running target after this many seconds; the timeout is reported as an error and any partial output is still cached |
MCP Client Configuration
{
"mcpServers": {
"makefile": {
"command": "uvx",
"args": [
"--from", "git+https://github.com/wdm0006/makefile-mcp",
"makefile-mcp",
"--makefile", "/path/to/your/project/Makefile",
"--exclude", "deploy,publish"
]
}
}
}
Tools
Every server exposes four utility tools plus one make_<target> tool per discovered make target (after include/exclude filtering). All tool names are snake_case.
make_<target>(additional_args=None, dry_run=False)
Executes make -C <working-dir> -f <makefile> <target>.
additional_args— a string of extra make arguments (e.g."-j4 VERBOSE=1"). Validated against the security allowlist below before make runs.dry_run— whentrue, make runs with-n: it prints recipes without ordinary execution, but Makefile expansion (including$(shell ...)) and recursive make may still have side effects. This is a tool parameter, not a CLI flag of the server process.- The response carries
status,exit_code, the exactcommand,working_directory, a bounded tail of stdout/stderr with line/char totals, and anexecution_idaddressing the full cached output. - A target killed by the timeout returns
status: "error"with a timeout message andexit_code: -1; whatever it printed before the kill is cached and readable viaget_output/search_output.
list_available_targets()
Returns the Makefile path, working directory, total and exposed target counts, and each exposed target's name, description, and tool_name.
get_makefile_info()
Returns all targets (including filtered-out ones) versus the exposed set, plus the active include/exclude filters.
get_output(execution_id, stream="stdout", start_line=0, end_line=100)
Pages through a cached execution's full output. Lines are 0-indexed and end_line is exclusive; the response includes total_lines and the selected content. Use this to read past the inline tail.
search_output(execution_id, pattern, stream="stdout", context_lines=3, max_results=20)
Case-insensitive literal substring search over a cached execution's full output. Each match comes with context_lines of surrounding context and its line number. Every match is counted in total_matches, but at most max_results matches are returned; when truncated is true, page through the rest with get_output around the returned line numbers.
Execution lifecycle
execution_id: every execution — success, failure, or timeout — is cached in full and gets a sequentialexecution_idin its response.get_outputandsearch_outputaddress the complete stdout/stderr through it.- Cache eviction: the cache holds the most recent
--max-cached-executionsexecutions (default 20). Older entries are evicted; an expiredexecution_idreturns a "not found in cache" error. - Timeout: a target running longer than
--timeoutseconds is killed and reported as an error; partial output captured before the kill is cached like any other run.
Security: the additional_args allowlist
additional_args is the only channel through which a caller can shape the make command line, so every token is validated (validate_additional_args) before make is invoked. Anything not listed here is rejected with an error response — make never runs.
Allowed:
- Execution-tuning short options:
-B -d -e -i -j -k -l -n -O -q -R -r -s -w(-jand-lmay take a value, attached like-j4or separated like-j 4;-Otakes an attached value like-Oline) - Execution-tuning long options, no value:
--keep-going --silent --quiet --ignore-errors --dry-run --just-print --recon --print-directory --no-print-directory --always-make --no-builtin-rules --no-builtin-variables --environment-overrides --question --trace --warn-undefined-variables - Long options with a value:
--jobs,--load-average,--max-load(attached--jobs=4or separated--jobs 4); optional attached value:--output-sync,--debug - Variable assignments with literal values:
NAME=value,NAME:=value,NAME::=value,NAME+=value,NAME?=value
Rejected (structured error returned to the caller):
- Any bare word — it would select another target (e.g.
clean) --— the end-of-options marker would turn later tokens into targets- Any option outside the sets above, including options that change what make builds or where it runs:
-f/--file,-C/--directory,-I/--include-dir,-o,-W - Assignments using make's
!=shell-assignment operator — its value would be run through a shell - Assignment values containing make expansion references (
$(...)or${...}) — make evaluates these itself, soX=$(shell ...)would execute a command even with a literal shell disabled
The test suite proves these guards against real GNU make, including control tests showing that make does execute X=$(shell ...) and X!=... values if validation were bypassed.
Development
make install # Set up venv and install deps
make test # Run tests
make lint # Lint with ruff
make format # Format with ruff
License
MIT License. See LICENSE for details.
