kernel-mcp
An MCP server that enables AI-powered Linux kernel development, exposing tools for symbol search, static analysis, build automation, QEMU/GDB debugging, and more via IBM Bob.
README
kernel-mcp
AI-powered Linux kernel development assistant as an MCP server for IBM Bob.
kernel-mcp is a Python MCP server that exposes kernel development tools — symbol search, static analysis, build automation, QEMU, GDB, and more — to IBM Bob via the Model Context Protocol. It runs locally as a stdio child process and integrates with the existing LocalLLM-MCP server for LLM routing.
Features
| Status | Tool | Description |
|---|---|---|
| ✅ Feature 1 | search_kernel_symbol |
Search the Linux kernel source tree for a symbol by name |
| ✅ Feature 2 | explain_kernel_file |
Explain a kernel source file using a local LLM |
| ✅ Feature 3 | build_kernel |
Build the kernel with a given config |
| ✅ Feature 4 | run_checkpatch |
Run checkpatch.pl on a patch or file |
| ✅ Feature 5 | run_sparse |
Run the Sparse static analyser |
| ✅ Feature 6 | boot_qemu |
Boot a kernel image in QEMU |
| ✅ Feature 7 | analyze_oops |
Analyse a kernel oops / crash log |
| ✅ Feature 8 | git_bisect |
Assist with git bisect sessions |
| ✅ Feature 9 | review_patch |
Review a patch with checkpatch.pl and optional LLM semantic review |
| ✅ Feature 10 | run_smatch |
Run the Smatch static analyser (make C=1 CHECK=smatch) |
| ✅ Feature 11 | run_coccinelle |
Run Coccinelle semantic patch tool (spatch) on a kernel source directory |
| ✅ Feature 12 | generate_commit_message |
Generate a kernel-style commit message from a unified diff using a local LLM |
| ✅ Feature 13 | route_to_best_model |
Route a kernel development prompt to the best local LLM using a capability matrix |
| ✅ Feature 14 | debug_kernel |
Attach GDB to a QEMU/KGDB kernel and execute debug commands (backtrace, registers, break, etc.) |
| ✅ Feature 15 | find_subsystem |
Identify the kernel subsystem that owns a file path, returning the MAINTAINERS entry, maintainer list, mailing list, git tree, and status |
| ✅ Feature 16 | list_kernel_configs |
List all available defconfig/specialconfig targets by parsing make help output |
| ✅ Feature 16 | run_menuconfig |
Return the terminal command needed to run make menuconfig interactively (TUI requires a real terminal) |
| ✅ Feature 16 | clean_kernel |
Clean the kernel build tree with make clean (keeps .config) or make mrproper (full reset) |
| ✅ Feature 17 | shutdown_qemu |
Stop a QEMU session previously started by boot_qemu using its session UUID |
| ✅ Feature 18 | generate_call_graph |
Generate a call graph for a kernel function using cflow (with grep fallback) |
| ✅ Feature 19 | search_documentation |
Search the Documentation/ directory for .rst, .txt, and .md files matching a literal query |
Architecture
See docs/Architecture.md for the full layered architecture diagram and design rationale.
IBM Bob ──MCP STDIO──► kernel-mcp/server.py
│
router.py (validation)
│
tools/*.py (business logic)
│
services/*.py (subprocess calls)
│
ripgrep / grep / make / qemu / gdb
│
Linux kernel source tree
Prerequisites
| Requirement | Notes |
|---|---|
| Python 3.11+ | 3.14 recommended |
| Linux kernel source tree | Any version; clone from kernel.org |
ripgrep (rg) |
Strongly recommended for speed; falls back to grep |
grep |
Standard fallback; available on all Linux/macOS systems |
| IBM Bob with MCP support | For full integration |
Installation
1. Clone or copy the project
# kernel-mcp lives alongside LocalLLM-MCP in your workspace
git clone <your-repo> kernel-mcp
cd kernel-mcp
2. Create a virtual environment
python -m venv .venv
# Linux / macOS
source .venv/bin/activate
# Windows
.venv\Scripts\activate
3. Install dependencies
pip install -r requirements.txt
4. Configure environment
cp .env.example .env
Edit .env and set KERNEL_SOURCE_PATH:
KERNEL_SOURCE_PATH=/home/user/linux
5. Verify configuration
python config.py
Expected output:
=== kernel-mcp Configuration Smoke Test ===
kernel_source_path : /home/user/linux
search_timeout_seconds : 30
max_results : 50
context_lines : 5
ripgrep_path : rg
grep_path : grep
=== Smoke test passed ===
IBM Bob Integration
Add kernel-mcp to Bob's mcp.json:
Linux / macOS:
{
"mcpServers": {
"kernel-mcp": {
"command": "/path/to/kernel-mcp/.venv/bin/python",
"args": ["/path/to/kernel-mcp/server.py"],
"cwd": "/path/to/kernel-mcp",
"env": {
"KERNEL_SOURCE_PATH": "/home/user/linux",
"LOG_LEVEL": "INFO"
},
"alwaysAllow": ["search_kernel_symbol", "review_patch"],
"disabled": false
}
}
}
Windows:
{
"mcpServers": {
"kernel-mcp": {
"command": "C:\\kernel-mcp\\.venv\\Scripts\\python.exe",
"args": ["C:\\kernel-mcp\\server.py"],
"cwd": "C:\\kernel-mcp",
"env": {
"KERNEL_SOURCE_PATH": "C:\\linux",
"LOG_LEVEL": "INFO"
},
"alwaysAllow": ["search_kernel_symbol", "review_patch"],
"disabled": false
}
}
}
Usage Examples
Once Bob has the server connected, ask naturally:
| Prompt | What happens |
|---|---|
| "Find all declarations of task_struct in the kernel" | search_kernel_symbol("task_struct") |
| "Search for kmalloc only in the mm subsystem" | search_kernel_symbol("kmalloc", path_filter="mm/") |
| "Where is do_fork defined?" | search_kernel_symbol("do_fork", path_filter="kernel/") |
| "Find netif_receive_skb in the network stack" | search_kernel_symbol("netif_receive_skb", path_filter="net/") |
| "Generate a default kernel config" | build_kernel("defconfig") |
| "Build the kernel for ARM64 with 8 jobs" | build_kernel("all", arch="arm64", jobs=8) |
| "Clean the kernel build tree" | build_kernel("mrproper") |
| "Build only the e1000e driver module" | build_kernel("M=drivers/net/e1000e/", jobs=4) |
| "Check my patch for style issues" | run_checkpatch("0001-my-fix.patch") |
| "Run checkpatch on a source file" | run_checkpatch("drivers/net/foo.c", is_patch=False) |
| "Run strict checkpatch on a patch" | run_checkpatch("fix.patch", strict=True) |
| "Run sparse on the mm subsystem" | run_sparse("mm/") |
| "Sparse-check a single object file" | run_sparse("mm/slab.o") |
| "Deep sparse check for ARM64" | run_sparse("drivers/usb/", check_level=2, arch="arm64") |
| "Boot the default x86 kernel image" | boot_qemu("arch/x86/boot/bzImage") |
| "Boot with a serial console and panic timeout" | boot_qemu("arch/x86/boot/bzImage", append="console=ttyS0 panic=5") |
| "Boot an ARM64 kernel with initrd" | boot_qemu("arch/arm64/boot/Image", arch="arm64", machine="virt", initrd="initrd.img", memory_mb=512) |
| "Boot with 2 CPUs and 1 GiB RAM" | boot_qemu("arch/x86/boot/bzImage", memory_mb=1024, extra_args=["-smp", "2"]) |
| "Analyse this oops log" | analyze_oops("<paste log text>") |
| "What caused this kernel panic?" | analyze_oops("<log>", kernel_version_hint="6.1.0-rc4") |
| "Analyse oops with a symbol map" | analyze_oops("<log>", symbol_map_path="System.map") |
| "Start bisecting between v6.2 (bad) and v6.1 (good)" | git_bisect("start", bad_commit="v6.2", good_commits=["v6.1"]) |
| "Mark current commit as good" | git_bisect("good") |
| "Mark current commit as bad" | git_bisect("bad") |
| "Skip the current untestable commit" | git_bisect("skip") |
| "Run automated bisect with build test" | git_bisect("run", run_command="make defconfig && make -j4 && ./test.sh") |
| "Show bisect session log" | git_bisect("log") |
| "Abort bisect and restore HEAD" | git_bisect("reset") |
| "Review my patch for style issues" | review_patch("patches/0001-fix-mm-slab.patch") |
| "Strict checkpatch on a patch file" | review_patch("fix.patch", strict=True) |
| "Review inline diff text for style" | review_patch("<paste raw diff here>") |
| "Full review: checkpatch + LLM code review" | review_patch("fix.patch", use_llm=True) |
| "LLM review with Qwen Coder model" | review_patch("fix.patch", use_llm=True, model_name="qwen-coder") |
| "Run Coccinelle kzalloc-simple script on drivers/net/" | run_coccinelle("scripts/coccinelle/api/kzalloc-simple.cocci", "drivers/net/") |
| "Apply my custom .cocci script to the mm subsystem" | run_coccinelle("my-checks.cocci", "mm/") |
| "Run Coccinelle without headers" | run_coccinelle("scripts/coccinelle/api/foo.cocci", "drivers/", extra_args=["--no-includes"]) |
| "Generate a commit message for my patch" | generate_commit_message("<paste unified diff here>") |
| "Write a kernel commit message for this fix.patch" | generate_commit_message("fix.patch") |
| "Use Qwen Coder to write a commit message" | generate_commit_message("<diff>", model_name="qwen-coder") |
Running Tests
# From the kernel-mcp directory, with venv active
pytest tests/ -v
Test groups (test_search_symbol.py):
- A — Backend detection (ripgrep/grep/neither)
- B — Subprocess execution and output parsing
- C — MatchType classification heuristic
- D — Context enrichment (async file reads)
- E — Deduplication and result assembly
- F — Router input validation
- G — Smoke: server tool returns valid JSON
- H — Integration: real backend against synthetic kernel tree
Test groups (test_build_kernel.py):
- A —
locate_make: binary detection - B —
run_build: subprocess execution (mocked) - C —
_parse_diagnostics: GCC/Clang error and warning extraction - D —
_build_make_args: argument assembly (arch, jobs, target) - E —
build_kerneltool layer (mocked service) - F — Router input validation
- G — Server smoke: tool returns valid JSON
Integration tests (group H) are automatically skipped if neither rg nor grep is found on PATH.
Test groups (test_run_checkpatch.py):
- A —
locate_checkpatch: script detection (in-tree, explicit, missing) - B —
run_checkpatchservice: subprocess execution (mocked) - C —
_parse_issues: ERROR/WARNING/CHECK extraction - D —
_parse_total_lines: summary line parsing - E —
run_checkpatchtool layer (mocked service) - F — Router input validation
- G — Server smoke: tool returns valid JSON
Test groups (test_boot_qemu.py):
- A —
locate_qemu: binary detection (found, missing, custom path, arch aliases) - B —
run_qemuservice: subprocess execution (mocked) - C —
_detect_events: boot/panic/oops detection from output text - D —
_build_summary: summary string construction - E —
boot_qemutool layer (mocked service) - F — Router input validation
- G — Server smoke:
boot_qemureturns valid JSON
Test groups (test_analyze_oops.py):
- A —
_detect_oops_type: crash-type detection (oops, bug, panic, warning, kasan, ubsan, lockdep, …) - B —
_extract_metadata: CPU / PID / comm / kernel-version extraction - C —
_extract_registers: register dump parsing (x86-64, ARM64, RISC-V) - D —
_extract_call_trace: call-trace frame extraction and indexing - E —
_build_summary/_build_root_cause_hint/_infer_subsystem - F —
analyze_oopstool layer (direct call) - G — Router input validation (
route_analyze_oops) - H — Server smoke:
analyze_oopsreturns valid JSON
Test groups (test_run_sparse.py):
- A —
locate_sparse: binary detection (found, missing) - B —
run_sparse_via_makeservice: subprocess execution (mocked) - C —
_parse_findings: sparse diagnostic extraction from stderr - D —
_build_summary: summary string construction - E —
run_sparsetool layer (mocked service) - F — Router input validation
- G — Server smoke: tool returns valid JSON
Test groups (test_git_bisect.py):
- A —
locate_git: binary detection (found, missing, custom path) - B —
run_git_commandservice: subprocess execution (mocked) - C —
_build_git_args: argument assembly for each action - D —
_parse_bisect_output: state detection from git output - E —
_build_summary: summary string construction - F —
git_bisecttool layer (mocked service) - G — Router input validation (
route_git_bisect) - H — Server smoke:
git_bisectreturns valid JSON
Test groups (test_review_patch.py):
- A —
normalise_patch_input: file-path detection vs inline-text detection - B —
run_patch_checkpatchservice: subprocess delegation (mocked) - C —
_parse_diff_metadata: changed-file extraction and statistics - D —
_infer_subsystem: top-level subsystem detection - E —
review_patchtool layer (mocked service + mocked LLM) - F — Router input validation (
route_review_patch) - G — Server smoke:
review_patchreturns valid JSON
Test groups (test_run_smatch.py):
- A —
locate_smatch: binary detection (found, missing, custom path) - B —
run_smatch_via_makeservice: subprocess execution (mocked) - C —
_parse_findings: smatch diagnostic extraction from stderr - D —
_build_summary: summary string construction - E —
run_smatchtool layer (mocked service) - F — Router input validation
- G — Server smoke: tool returns valid JSON
Test groups (test_run_coccinelle.py):
- A —
locate_spatch: binary detection (found, missing, custom path) - B —
run_spatchservice: subprocess execution (mocked) - C —
_parse_transformations: unified diff parsing from stdout - D —
_parse_findings: Coccinelle diagnostic extraction from stderr - E —
run_coccinelletool layer (mocked service) - F — Router input validation
- G — Server smoke: tool returns valid JSON
Test groups (test_generate_commit_message.py):
- A —
_parse_diff_metadata: file path extraction and line counts - B —
_infer_subsystem: top-level subsystem detection - C —
_build_prompt/_extract_commit_message/_split_subject_body: prompt + response post-processing - D —
generate_commit_messagetool layer (LLM mocked) - E — Router input validation (
route_generate_commit_message) - F — Server smoke: tool returns valid JSON
Configuration Reference
kernel_mcp_config.json
| Key | Type | Default | Description |
|---|---|---|---|
search_timeout_seconds |
int | 30 |
Max seconds for a search subprocess |
max_results |
int | 50 |
Hard cap on total matches returned |
context_lines |
int | 5 |
Lines above/below each match |
ripgrep_path |
string | "rg" |
Name or absolute path of ripgrep binary |
grep_path |
string | "grep" |
Name or absolute path of grep binary |
make_path |
string | "make" |
Name or absolute path of the make binary |
build_timeout_seconds |
int | 1800 |
Max seconds for a kernel build (30 min) |
build_jobs |
int | 0 |
Default -j N for make. 0 = no -j flag |
checkpatch_path |
string | "" |
Path to checkpatch.pl. Empty = auto-detect at scripts/checkpatch.pl |
perl_path |
string | "perl" |
Name or absolute path of the Perl interpreter |
checkpatch_timeout_seconds |
int | 60 |
Max seconds for a checkpatch.pl run |
sparse_path |
string | "sparse" |
Name or absolute path of the sparse binary |
sparse_timeout_seconds |
int | 300 |
Max seconds for a make C= sparse run (5 min) |
smatch_path |
string | "smatch" |
Name or absolute path of the smatch binary |
smatch_timeout_seconds |
int | 300 |
Max seconds for a make C= smatch run (5 min) |
spatch_path |
string | "spatch" |
Name or absolute path of the spatch (Coccinelle) binary |
coccinelle_timeout_seconds |
int | 600 |
Max seconds for a spatch run (10 min) |
qemu_path |
string | "" |
Name or absolute path of the qemu-system binary. Empty = auto-detect qemu-system-<arch> on PATH |
qemu_timeout_seconds |
int | 60 |
Max seconds for a QEMU boot session |
qemu_memory_mb |
int | 256 |
Default guest RAM in MiB (-m <N>M) |
oops_log_max_bytes |
int | 131072 |
Max byte length of a kernel oops log accepted by analyze_oops (default 128 KiB) |
generate_commit_message_max_bytes |
int | 131072 |
Max byte length of a unified diff accepted by generate_commit_message (default 128 KiB) |
Environment Variables
| Variable | Required | Description |
|---|---|---|
KERNEL_SOURCE_PATH |
Yes | Absolute path to the Linux kernel source tree |
SEARCH_TIMEOUT_SECONDS |
No | Override search_timeout_seconds |
MAX_RESULTS |
No | Override max_results |
CONTEXT_LINES |
No | Override context_lines |
RIPGREP_PATH |
No | Override ripgrep binary path |
GREP_PATH |
No | Override grep binary path |
MAKE_PATH |
No | Override make binary path |
BUILD_TIMEOUT_SECONDS |
No | Override build_timeout_seconds |
BUILD_JOBS |
No | Override build_jobs |
CHECKPATCH_PATH |
No | Override path to checkpatch.pl |
PERL_PATH |
No | Override Perl interpreter path |
CHECKPATCH_TIMEOUT_SECONDS |
No | Override checkpatch_timeout_seconds |
SPARSE_PATH |
No | Override sparse binary path |
SPARSE_TIMEOUT_SECONDS |
No | Override sparse_timeout_seconds |
QEMU_PATH |
No | Override qemu-system binary path |
QEMU_TIMEOUT_SECONDS |
No | Override qemu_timeout_seconds |
QEMU_MEMORY_MB |
No | Override qemu_memory_mb |
OOPS_LOG_MAX_BYTES |
No | Override oops_log_max_bytes |
SMATCH_PATH |
No | Override smatch binary path |
SMATCH_TIMEOUT_SECONDS |
No | Override smatch_timeout_seconds |
SPATCH_PATH |
No | Override spatch binary path |
COCCINELLE_TIMEOUT_SECONDS |
No | Override coccinelle_timeout_seconds |
GENERATE_COMMIT_MESSAGE_MAX_BYTES |
No | Override generate_commit_message_max_bytes |
LOG_LEVEL |
No | DEBUG, INFO, WARNING, ERROR (default INFO) |
Tool Reference
- search_kernel_symbol
- explain_kernel_file
- build_kernel
- run_checkpatch
- run_sparse
- boot_qemu
- analyze_oops
- git_bisect
- review_patch
- run_smatch
- run_coccinelle
- generate_commit_message
Relationship to LocalLLM-MCP
kernel-mcp is a sibling project to LocalLLM-MCP. They run as separate MCP servers registered independently in Bob's mcp.json. Kernel MCP does not modify or depend on LocalLLM-MCP's code. Future features will call LocalLLM-MCP tools via Bob's tool-routing to send kernel source code to local LLMs for explanation and review.
License
MIT
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.
E2B
Using MCP to run code via e2b.