A Python-based Model Context Protocol (MCP) server that exposes Bazel build operations as standardized tools for AI agents in VS Code, Cursor, and Warp. This allows AI assistants to discover, build, test, and run targets in your Bazel-managed C++/Python repositories.
py_bazel_mcp/
├── src/bazel_mcp/ # Main package
│ ├── __init__.py # Package initialization
│ ├── server.py # MCP server implementation
│ ├── bazel.py # Bazel command wrappers (query, build, run, test)
│ ├── targets.py # Target discovery and caching
│ └── util.py # Helper utilities
├── .vscode/ # VS Code configuration
│ └── mcp.json # Example MCP configuration
├── pyproject.toml # Python package metadata
├── setup.sh # Automated installation script
├── generate_mcp_config.sh # Configuration generator
├── README.md # Full documentation
├── QUICKSTART.md # Quick start guide
├── LICENSE # MIT License
└── .gitignore # Git ignore rules
- Implements MCP protocol using
mcpPython library - Exposes 6 MCP tools and 1 resource
- Handles async Bazel command execution
- Streams build/test logs to agents
- Validates Bazel workspace on startup
run_query()- Execute Bazel query expressionsrun_build()- Build targetsrun_test()- Run testsrun_binary()- Execute binary targets- All operations are async and support custom flags
- Auto-discovers targets by kind (cc_, py_)
- Caches results to avoid repeated queries
- Returns structured JSON with target metadata
- Supports refresh on demand
which_bazel()- Detects Bazel/Bazelisk executablevalidate_bazel_workspace()- Validates Bazel workspace presenceDEFAULT_KINDS- Configurable target kinds to discover
| Tool | Purpose | Required Args | Optional Args |
|---|---|---|---|
bazel_list_targets |
List all targets by kind | - | refresh |
bazel_query |
Run Bazel query | expr |
flags |
bazel_build |
Build targets | targets |
flags |
bazel_run |
Run binary | target |
args, flags |
bazel_test |
Run tests | - | targets, flags |
repo_setup |
Run setup scripts | - | skipInstall |
bazel://targets- JSON snapshot of discovered targets with metadata
./setup.sh
source .venv/bin/activatepython3 -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -e ../generate_mcp_config.sh /path/to/bazel/repo
# Copy output to Warp → Warp Drive → MCP ServersPlace .vscode/mcp.json in your Bazel repository with appropriate paths.
Use Settings → MCP Servers → Add Custom Server with generated config.
- Startup: Server validates Bazel workspace (requires WORKSPACE, WORKSPACE.bazel, or MODULE.bazel). Exits with error if not found.
- Discovery: On first
bazel_list_targetscall, queries all target kinds - Caching: Results cached in memory; refresh with
refresh: true - Execution: Bazel commands run via
asyncio.create_subprocess_exec - Streaming: stdout/stderr forwarded in real-time to agent
- Transport: Uses MCP stdio protocol for local editor integration
BAZEL_PATH- Override Bazel executable (default:bazel)BAZELISK- Use Bazelisk launcherPYTHONPATH- Must includesrc/for module resolution
Default (configurable in util.py):
cc_librarycc_binarycc_testpy_librarypy_binarypy_test
To add more kinds (e.g., go_binary, java_library), edit DEFAULT_KINDS in util.py.
- Server executes arbitrary Bazel commands in specified workspace
- Only use with trusted repositories
- Uses stdio transport (local only, not exposed to network)
- Scripts in
repo_setuptool can run arbitrary bash commands
- Target discovery: ~5-30s depending on repo size (cached after first run)
- Build/test: Same as native Bazel (no overhead)
- Query: Near-instant for cached targets, ~1-5s for complex queries
- Define tool schema in
list_tools() - Add handler in
call_tool() - Implement Bazel operation in
bazel.py
- Define resource in
list_resources() - Implement read handler in
read_resource()
Edit DEFAULT_KINDS in util.py.
- Warp: View via MCP Servers page → View Logs
- VS Code/Cursor: Check MCP extension logs
source .venv/bin/activate
bazel-mcp --repo /path/to/bazel/repo
# Server starts and waits for MCP protocol messages on stdinsource .venv/bin/activate
python3 -c "
import asyncio
from bazel_mcp.targets import discover_targets
print(asyncio.run(discover_targets('/path/to/repo')))
"- Solution:
source .venv/bin/activate && pip install -e .
- Server requires WORKSPACE, WORKSPACE.bazel, or MODULE.bazel in the
--repodirectory - Check the path provided to
--repoargument - Server will exit with error code 1 if workspace files are not found
- Ensure WORKSPACE/MODULE.bazel exists
- Check Bazel is in PATH:
bazel version - Set
BAZEL_PATHenvironment variable
- Normal for large repos (10k+ targets)
- Results are cached after first discovery
- Consider filtering to specific packages in query
- Verify
working_directoryandPYTHONPATHin MCP config - Check MCP server is running (editor logs)
- Restart editor after configuration changes
- Python: 3.10+
- mcp: >=1.2.0 (Model Context Protocol library)
- Bazel: Any version (Bazelisk recommended)
MIT License - Free for commercial and personal use.
- Fork the repository
- Create feature branch
- Add tests if applicable
- Submit pull request
- File watching to auto-refresh targets
-
bazel cquerysupport - Coverage and profiling tools
- Build event protocol (BEP) streaming
- Remote execution support
- Multi-workspace support
- Web UI for monitoring
Questions? Open an issue on GitHub or check the documentation.