Setting Up Code Index MCP in Copilot CLI and FAILING!!

· nat's blog


Prerequisites #

Step 1: Install code-index-mcp #

1pip install code-index-mcp

Verify it works:

1python3 -m code_index_mcp --help

Note: uvx code-index-mcp does NOT work in our environment due to permission issues. Use python3 -m code_index_mcp instead.

Step 2: (Optional) Install language grammar #

For projects using mulle-objc (or other tree-sitter grammars), install the grammar package:

1pip install tree-sitter-mulle-objc

Important: See "Post-mortem: ObjC indexing gaps" below before relying on this for symbol coverage.

Step 3: Create the MCP config #

Create ~/.copilot/mcp-config.json with the following content. Replace /path/to/your/project with the absolute path to your repo:

1{
2  "mcpServers": {
3    "code-index": {
4      "command": "python3",
5      "args": ["-m", "code_index_mcp", "--project-path", "/path/to/your/project"]
6    }
7  }
8}

Example for MulleEOF:

1{
2  "mcpServers": {
3    "code-index": {
4      "command": "python3",
5      "args": ["-m", "code_index_mcp", "--project-path", "/home/src/srcM/MulleEOF"]
6    }
7  }
8}

Step 4: Restart Copilot CLI #

Type /restart in the CLI (or exit and relaunch). The MCP server is picked up on startup.

Verify it connected with /mcp or /env.

Step 5: Initialize the index #

Once restarted, tell Copilot to set the project path and build the deep index:

Set the project path to /path/to/your/project
Build the deep index

Or as a single instruction:

Set the project path to /path/to/your/project and build the deep index

The initial build takes ~30-60 seconds for large projects. Subsequent sessions reuse the cache.

Available Tools (used automatically by Copilot) #

Tool What it does
set_project_path Initialize the project for indexing
build_deep_index Full symbol extraction (classes, methods, imports)
refresh_index Rebuild shallow file list after changes
search_code_advanced Ripgrep-backed search with regex, glob, fuzzy support
find_files Glob pattern file discovery
get_file_summary Per-file structure: functions, imports, complexity
get_symbol_body Source code of a specific class or method
get_settings_info Check index status and config
clear_settings Wipe cache and start fresh

Example Queries #

Once indexed, you can ask Copilot things like:

Troubleshooting #

MCP not showing up after restart:

"Permission denied" with uvx:

Index seems stale after file changes:

Start completely fresh:

Multi-Project Setup #

Each Copilot CLI session spawns its own MCP server process (stdio-based, not shared). This means:

Global config (~/.copilot/mcp-config.json) — no --project-path:

1{
2  "mcpServers": {
3    "code-index": {
4      "command": "python3",
5      "args": ["-m", "code_index_mcp"]
6    }
7  }
8}

Per-project (.github/copilot-instructions.md) — tell the agent to self-initialize:

1## Session Initialization
2
3At the start of every session, initialize the code index:
4
5    Set the project path to /absolute/path/to/project
6
7Then if the index is not yet built (first use or after a reboot):
8
9    Build the deep index

This way each session auto-points at the right project just by reading the repo's own instructions. No manual switching, no cross-contamination between projects.

Index Scope #

What Where Scope
MCP server config ~/.copilot/mcp-config.json Global (all sessions, all projects)
In-memory project state MCP server process Per-session
Index cache (deep) /tmp/code_indexer/<md5(path)>/index.db Per-project, shared across sessions, lost on reboot
Index cache (shallow) /tmp/code_indexer/<md5(path)>/index.shallow.json Per-project, shared across sessions, lost on reboot

Note on mulle-sde Dependencies #

Each project's index includes fetched dependency sources (from mulle-sde craft), since those land inside the project tree. Two projects built against different dependency versions will have different indexes naturally — no special handling needed.


Post-mortem: ObjC indexing gaps #

Problem: code-index-mcp claims tree-sitter support for Objective-C, but in practice the ObjC strategy (objective_c_strategy.py) is regex-only. Only .m and .mm files get specialized parsing. .h, .c, and .inc files fall through to a generic fallback that lists files but extracts zero symbols.

For MulleEOF this resulted in: 20,992 files indexed, but only ~9,241 symbols — with most .h headers (where @interface declarations live) contributing nothing.

Root cause:

What was attempted: Patching objective_c_strategy.py in the installed venv to:

  1. Extend extensions to .h, .c, .inc
  2. Replace regex with tree_sitter_objc AST walker

Why abandoned: Patching installed packages in a venv is fragile — will be overwritten on any pip install --upgrade, hard to track, and the edit left the file in a broken state (dead code after a return). The right fix belongs upstream.

The grammar works fine: tree-sitter-mulle-objc (PyPI: tree-sitter-mulle-objc, Python module: tree_sitter_objc) is installed and functional. Parsing is accurate. The blocker is entirely in code-index-mcp's strategy layer.

Proper fix: Contribute a PR to johnhuang316/code-index-mcp that:

  1. Adds .h, .c, .inc to ObjectiveCParsingStrategy.get_supported_extensions()
  2. Replaces regex parsing with tree_sitter_objc AST traversal
  3. Adds .inc to _file_type_mappings in strategy_factory.py as a fallback

Until then, the MCP index is useful for file discovery and search, but symbol lookup for header-declared classes/methods is incomplete.

last updated: