Skip to main content
Glama

kconfig-mcp

"Why can't I enable CONFIG_X?", answered with file:line and a fix that's been checked.

kconfig-mcp is an MCP server that lets an AI agent reason about Kconfig, the configuration system used by the Linux kernel, Zephyr, U-Boot, Buildroot and others.

Everyone who has configured a kernel has hit this: the option you want isn't in menuconfig, or it's there but greyed out, and the reason is five depends on hops away in a different directory. kconfig-mcp walks that chain for you. Then it searches for the smallest set of changes that would unlock the option, and applies them to the real tree to verify they work before it shows them to you.

What it looks like

This is real output on the current Linux tree (18,913 symbols) for x86:

> kconfig_why_not X86_X2APIC
X86_X2APIC = n (default), needs y - bool at arch/x86/Kconfig:463
  its prompt (arch/x86/Kconfig:463) is visible only if
  X86_LOCAL_APIC && X86_64 && (IRQ_REMAP || HYPERVISOR_GUEST), which is n:
    needs any one of (2 options, all currently too low):
      IRQ_REMAP = n (default), needs y - bool at drivers/iommu/Kconfig:201
        its prompt is visible only if X86_64 && X86_IO_APIC && PCI_MSI && ACPI && IOMMU_SUPPORT:
          PCI_MSI = n (default), needs y - bool at drivers/pci/Kconfig:44
            its prompt is visible only if PCI, which is n:
              PCI = n (default) - set PCI=y directly.
      HYPERVISOR_GUEST = n (default), needs y - bool at arch/x86/Kconfig:787
        its prompt is visible - set HYPERVISOR_GUEST=y directly.

Verified fix (2 change(s)): HYPERVISOR_GUEST=y, X86_X2APIC=y
  HYPERVISOR_GUEST: arch/x86/Kconfig:787
  X86_X2APIC: arch/x86/Kconfig:463
Unverified alternatives: PCI=y, PCI_MSI=y, IRQ_REMAP=y, X86_X2APIC=y

> kconfig_set HYPERVISOR_GUEST y
CONFIG_HYPERVISOR_GUEST: 'n' -> 'y'.
1 other symbol(s) changed as a consequence: X86_X2APIC n->y

The same question on a 32-bit build (ARCH=i386) ends somewhere no symbol change can reach, and the tool says so instead of inventing a fix:

64BIT = n (default), needs y - bool at arch/x86/Kconfig:3
  requires "i386" = "x86", which compares two constants and is always false here.
  One side was probably expanded from an environment variable (like $(ARCH)) when
  the tree was loaded: no symbol change can fix this - reload with a different env.
No verified fix: every route ends in something no assignment can change.

Related MCP server: codegraph-mcp

Why it's built this way

  • Fixes are verified, not guessed. Kconfig is full of edge cases: tristate m needs MODULES, bools promote m to y, choices deselect their other members, select overrides depends on, and default y turns things on silently. So every candidate plan is applied to the loaded tree and checked. Only plans that really reach the goal are shown as fixes, together with their side effects (what else select/imply/defaults switch on or off).

  • It parses current Linux. It's built on Kconfiglib, which hasn't had a release since 2020 and can't parse Linux's newer modules, transitional and depends on X if Y syntax. kconfig-mcp rewrites those lines as files are read, keeping every line number exact. depends on X if Y is lowered with a line-by-line port of expr_trans_compare from scripts/kconfig/expr.c, so it behaves exactly as kconfig does, including how kconfig treats !S when S is m.

  • Environment problems are named. Linux sources arch/$(SRCARCH)/Kconfig, and an unset variable silently becomes "". kconfig-mcp tracks undefined variables and names them in the error (undefined variable(s): SRCARCH (the arch/ directory to use, ...)) instead of leaving you with arch//Kconfig not found.

Install

pip install kconfig-mcp
claude mcp add kconfig -- kconfig-mcp

Python 3.10+. You don't need a kernel build environment. A source tree with its Kconfig files is enough, even a sparse checkout:

git clone --depth 1 --filter=blob:none --sparse https://github.com/torvalds/linux.git
cd linux && git sparse-checkout set --no-cone '/Kconfig' '**/Kconfig*' '/arch/*/configs/*'

Loading trees

Tree

kconfig_load arguments

Linux

kconfig_path="linux/Kconfig", env={"SRCARCH": "x86", "ARCH": "x86"} (or arm64/arm64, riscv/riscv, ...). Add config_path=".config" for an existing config.

Linux, no compiler / Windows

the same plus shell="dry"

Any other tree

the top-level Kconfig plus whatever variables it expands. A load error names each missing one.

shell controls the tree's $(shell,...) calls, which is how Linux probes the compiler:

  • "run" (default) runs them with a POSIX sh, as make menuconfig would. Compiler-dependent symbols then reflect your real toolchain.

  • "dry" runs nothing. Linux's probe idioms get fixed answers: feature probes read as absent, and the toolchain reports as GCC 13.2. $(error-if) checks become warnings. Results then carry a note that compiler-dependent symbols such as CC_HAS_* read as absent.

Tools

Tool

What it does

kconfig_load

Parse a tree (plus optional .config) into a named session. Reports undefined variables and warnings.

kconfig_why_not

The unmet conditions behind symbol not being y/m/n, recursively with file:line, plus a verified minimal fix and its side effects.

kconfig_symbol

Type, prompt, value and why it has that value, assignable values, dependencies, defaults, select/imply in both directions, help text.

kconfig_what_selects

Every symbol that selects or implies this one, with current values and which are active.

kconfig_search

Regex search over names, prompts and help, with name matches first.

kconfig_set

Assign a value as menuconfig would, and report every other symbol that changed. A refused assignment says so.

kconfig_diff

Compare with another .config, or with a defconfig or fragment using fragment=True.

kconfig_save

Write .config, or a minimal defconfig with minimal=True.

kconfig_sessions / kconfig_unload

Manage loaded trees.

Symbol names work with or without CONFIG_. A misspelt name gets "Did you mean: ...".

Limitations

  • transitional symbols are always n. Real kconfig reads them from an old .config to migrate a value during a rename. Kconfiglib has no equivalent.

  • The fix search is bounded. Selects and defaults are only explored when a symbol can't be reached through its own prompt, and the search has an expansion budget. If no verified fix is found, the result says whether the budget ran out or every route is genuinely blocked.

  • why_not covers bool and tristate symbols. For int/hex/string symbols, use kconfig_symbol and kconfig_set.

  • Dry mode answers compiler probes generically (see above), so trust CC_HAS_*-style symbols only with shell="run" on a real toolchain.

  • It depends on Kconfiglib 14.1.0, pinned because compat.py hooks two of its internal methods. CI parses the latest Linux tree every week, so the next new keyword shows up as a failing build rather than a silent wrong answer.

Tests

pip install ".[test]" "ruff==0.16.0" "mypy==2.3.0"
ruff check src tests && mypy --strict src
pytest tests                                   # unit + stdio tests, fixture trees
LINUX_SRC=/path/to/linux pytest tests/test_linux_integration.py

The fixture tree in tests/fixtures/tree exercises every construct the explainer handles: depends on, select, imply, choice, visible if, menuconfig/if blocks, defaults, tristate and modules, and an arch directory chosen by $(SRCARCH). The Linux tests assert real facts, such as x2APIC's dependencies, the i386 dead end, and the x86_64 defconfig already enabling it. CI runs them against a sparse checkout of the current tree.

License

MIT. Kconfiglib is ISC-licensed.

Available Tools

10 tools
kconfig_diffA

Compare the session's current values with another config file.

A full .config lists every symbol that has a value, so a bool/tristate missing from it is n - that's the default. For a defconfig or a config fragment (only the interesting lines), pass fragment=True to compare just the symbols the file mentions.

Inputs: name (required), other_config (required), limit, fragment. Returns: result

kconfig_loadA

Parse a Kconfig tree (and optionally a .config) into a session named name.

kconfig_path is the top-level Kconfig file; its directory becomes srctree. env supplies the variables the tree expands - Linux needs SRCARCH and ARCH (e.g. {"SRCARCH": "x86", "ARCH": "x86_64"}); Zephyr needs ZEPHYR_BASE and friends. Missing ones are named in the error. shell: "run" executes the tree's $(shell,...) compiler probes with a POSIX sh, as make menuconfig would. "dry" runs nothing (no compiler needed, works on Windows); compiler-feature symbols then read as absent. A Linux tree takes 10-40 s to parse; the session stays loaded.

Inputs: name (required), kconfig_path (required), env, shell, +1 more. Returns: result

kconfig_saveC

Write the current configuration. minimal=True writes a defconfig-style file with only the values that differ from defaults.

Inputs: name (required), path (required), minimal. Returns: result

kconfig_sessionsB

List loaded sessions.

Inputs: no named parameters. Returns: result

kconfig_setA

Assign a value (y/m/n for bool/tristate; a number or string otherwise) as if in menuconfig, then report everything else that changed as a result. If the value doesn't stick (hidden prompt, unmet dependency, choice rules) it says so - use kconfig_why_not to see why.

Inputs: name (required), value (required), symbol (required). Returns: result

kconfig_symbolB

Everything about one symbol: type, prompt, current value and why, help text, where it's defined, its dependencies, and what selects/implies it.

Inputs: name (required), symbol (required). Returns: result

kconfig_unloadC

Forget a loaded session.

Inputs: name (required). Returns: result

kconfig_what_selectsB

Who forces this symbol on (select), who suggests it (imply), and what it selects/implies itself - with current values and locations.

Inputs: name (required), symbol (required). Returns: result

kconfig_why_notA

Explain why a symbol isn't (or can't be) at value, and how to fix it.

Walks every unmet depends on, visible if, if block, choice and select/default condition with file:line, recursing into the symbols they name. Then searches for a minimal set of assignments and VERIFIES it by applying it to the tree - a fix is only shown if Kconfig agrees it works, along with its side effects. value: "y", "m", or "n" (why can't I turn it off?).

Inputs: name (required), symbol (required), value. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.4/5.0

    Scored across 10 tools

    Disambiguation5/5

    Each tool has a distinct role: load/unload/list sessions, search symbols, inspect one symbol, set a value, diagnose why a value cannot be set, inspect select/imply relationships, save, and diff. kconfig_set and kconfig_why_not are complementary rather than overlapping: set attempts an assignment and why_not explains failures and verified fixes.

    Naming Consistency4/5

    All tools use a consistent kconfig_ prefix and snake_case, making the namespace predictable. Most names are action-oriented, though kconfig_sessions and kconfig_symbol are noun-based rather than verb-based, a minor deviation from the otherwise consistent convention.

    Tool Count5/5

    Ten tools is well-scoped for a Kconfig exploration and configuration server. Each tool covers a meaningful part of the workflow without obvious redundancy or excessive granularity.

    Completeness4/5

    The surface covers the core lifecycle: loading a tree/session, searching and inspecting symbols, setting values, diagnosing failures, examining select/imply relationships, saving, and diffing configs. A minor gap is the lack of an explicit menu-structure or full-symbol-listing tool, though search and symbol inspection can work around this.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Provides a semantic understanding of your codebase by parsing with tree-sitter and building a graph of symbols and dependencies. Enables AI assistants to navigate code, analyze changes, and discover architecture using 18 tools with minimal context overhead.
      18 npm
      1
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Exposes a codebase's symbol graph and symbol-aware editing tools to AI agents, enabling targeted symbol lookup, impact analysis, and atomic multi-file edits with reduced context tokens.
      9 npm
      MIT
    • A
      license
      Not graded
      quality
      Not graded
      maintenance
      Enables AI agents to explore a repository by querying a pre-built structural knowledge graph of symbols and their relationships — definitions, callers, callees, blast radius, and file-level impact — instead of grepping and reading files. This cuts the tokens spent on code exploration by roughly 96–99% while running entirely on local SQLite with tree-sitter parsing.
      1
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables AI coding agents and developers to search code by meaning and exact text, map symbols, dependencies, blast radius and context, inspect git-change impacts, and trace live Python or JavaScript execution from a local air-gapped SQLite index.
      Apache 2.0