make
Run any target from a Makefile by specifying the target name and optional arguments to automate development tasks such as testing or code formatting.
Instructions
Run a make target from the Makefile
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| target | Yes | Make target to run | |
| args | No | List of command line arguments (e.g. VAR=value) |
Implementation Reference
- src/mcp_server_make/server.py:73-138 (handler)The call_tool handler that executes the 'make' tool logic. It parses the Make arguments, builds the make command, runs it as a subprocess, and returns the output.
@server.call_tool() async def call_tool(name: str, arguments: Dict[str, Any]) -> List[TextContent]: """Execute a tool. Args: name: Name of the tool to execute arguments: Arguments for the tool Returns: List of text content with tool execution results """ if name != "make": return [TextContent(type="text", text=f"Unknown tool: {name}")] try: make_args = Make(**arguments) except Exception as e: return [TextContent(type="text", text=f"Invalid arguments: {str(e)}")] try: # Run make command cmd = ["make", "-f", make_path, make_args.target] cmd.extend(make_args.args) proc = await asyncio.create_subprocess_exec( *cmd, stdout=PIPE, stderr=PIPE, # Ensure proper error propagation from child process start_new_session=True, ) except Exception as e: return [ TextContent(type="text", text=f"Failed to start make process: {str(e)}") ] try: stdout, stderr = await proc.communicate() except asyncio.CancelledError: # Handle task cancellation if proc.returncode is None: try: proc.terminate() await asyncio.sleep(0.1) if proc.returncode is None: proc.kill() except Exception: pass raise except Exception as e: return [ TextContent(type="text", text=f"Error during make execution: {str(e)}") ] stderr_text = stderr.decode() if stderr else "" stdout_text = stdout.decode() if stdout else "" if proc.returncode != 0: return [ TextContent( type="text", text=f"Make failed with exit code {proc.returncode}:\n{stderr_text}\n{stdout_text}", ) ] return [TextContent(type="text", text=stdout_text)] - src/mcp_server_make/server.py:22-29 (schema)The Make Pydantic model that defines the input schema for the 'make' tool, with 'target' (string) and 'args' (list of strings) fields.
class Make(BaseModel): """Parameters for running make.""" target: str = Field(description="Make target to run") args: List[str] = Field( default_factory=list, description="List of command line arguments (e.g. VAR=value)", ) - src/mcp_server_make/server.py:58-71 (registration)Registration of the 'make' tool via list_tools. Returns a Tool object with name='make', description, and inputSchema from the Make model.
@server.list_tools() async def list_tools() -> List[Tool]: """List available tools. Returns: List of available tools, currently only the make tool. """ return [ Tool( name="make", description="Run a make target from the Makefile", inputSchema=Make.model_json_schema(), ) ] - src/mcp_server_make/__init__.py:9-40 (helper)Main entry point that parses command line arguments (--make-path, --working-dir) and calls serve() to start the MCP server.
def main() -> NoReturn: """Run the MCP Make Server. This function is the entry point for the MCP Make Server. It parses command line arguments and starts the server process. Raises: SystemExit: Always exits the program after running. """ import argparse import asyncio import sys parser = argparse.ArgumentParser( description="give a model the ability to run make commands" ) parser.add_argument( "--make-path", type=str, default="Makefile", help="Path to makefile" ) parser.add_argument( "--working-dir", type=str, default=str(Path.cwd()), help="Working directory" ) args = parser.parse_args() try: asyncio.run(serve(args.make_path, args.working_dir)) sys.exit(0) # Successful execution except KeyboardInterrupt: sys.exit(0) # Clean exit on interrupt except Exception as e: print(f"Error: {e}", file=sys.stderr) sys.exit(1) # Exit with error