Skip to content

Commit 5713e29

Browse files
committed
v0.7.0: align command name with the project name
- primary command is now mcp-gtags-server (matches repo and PyPI package); gtags-mcp remains as a compatibility alias so existing MCP client configs and background servers keep working - all user-facing output, docs, and the installer use the new name
1 parent a5f039a commit 5713e29

7 files changed

Lines changed: 37 additions & 35 deletions

File tree

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ curl -fsSL https://raw.githubusercontent.com/harshithsunku/mcp-gtags-server/main
1717

1818
Every AI coding agent — Claude Code, Cursor, Codex, you name it — answers *"where is this function defined?"* the same way: **grep the entire tree**. On a million-line C/C++ codebase that's a full scan per question, and the output is a firehose: every comment, string literal, and unrelated match, dumped straight into the model's context window.
1919

20-
**mcp-gtags-server** replaces those scans with indexed lookups powered by [GNU Global (gtags)](https://www.gnu.org/software/global/) — the same tags engine kernel and systems developers have trusted for decades — exposed to agents over the [Model Context Protocol](https://modelcontextprotocol.io/).
20+
**mcp-gtags-server** replaces those scans with indexed lookups powered by [GNU Global (gtags)](https://www.gnu.org/software/global/) — the same tags engine kernel and systems developers have trusted for decades — exposed to agents over the [Model Context Protocol](https://modelcontextprotocol.io/). Built for the codebases LSP-based tools can't handle: kernel-scale C/C++, trees that don't currently compile, machines you can't sudo on.
2121

2222
- **~100× faster per query** — milliseconds instead of seconds, at any codebase size
2323
- **Radically less noise** — the definition, not 7,873 lines of matches
@@ -81,18 +81,18 @@ Prefer stdio (client-launched processes) over a background server? That works to
8181
{
8282
"mcpServers": {
8383
"gtags": {
84-
"command": "gtags-mcp"
84+
"command": "mcp-gtags-server"
8585
}
8686
}
8787
}
8888
```
8989

90-
That's it. No indexing step, no configuration, **no per-repo setup** — 20 repos need zero extra installs. Ask your agent *"who calls `tcp_v4_rcv`?"* — the first query in any repo builds that repo's index automatically, and every query after that is answered in milliseconds. Run `gtags-mcp doctor` any time to see what the server detects, or `gtags-mcp config` to re-print the client configuration.
90+
That's it. No indexing step, no configuration, **no per-repo setup** — 20 repos need zero extra installs. Ask your agent *"who calls `tcp_v4_rcv`?"* — the first query in any repo builds that repo's index automatically, and every query after that is answered in milliseconds. Run `mcp-gtags-server doctor` any time to see what the server detects, or `mcp-gtags-server config` to re-print the client configuration.
9191

9292
<details>
9393
<summary><b>Background server details</b> (network access, port, lifecycle)</summary>
9494

95-
The installer runs `gtags-mcp --transport http --host 127.0.0.1 --port 8383` in the background (pid: `~/.gtags-mcp/server.pid`, log: `~/.gtags-mcp/server.log`). Environment overrides for the installer:
95+
The installer runs `mcp-gtags-server --transport http --host 127.0.0.1 --port 8383` in the background (pid: `~/.gtags-mcp/server.pid`, log: `~/.gtags-mcp/server.log`). Environment overrides for the installer:
9696

9797
| Variable | Default | Meaning |
9898
|---|---|---|
@@ -109,7 +109,7 @@ The installer runs `gtags-mcp --transport http --host 127.0.0.1 --port 8383` in
109109

110110
```bash
111111
# 1. GNU Global — EITHER user-space (no sudo):
112-
gtags-mcp setup
112+
mcp-gtags-server setup
113113
# OR a system package:
114114
sudo apt install global # Debian/Ubuntu
115115
sudo dnf install global # Fedora
@@ -132,7 +132,7 @@ Add to `claude_desktop_config.json` (pin the project since Desktop doesn't launc
132132
{
133133
"mcpServers": {
134134
"gtags": {
135-
"command": "gtags-mcp",
135+
"command": "mcp-gtags-server",
136136
"args": ["--root", "/absolute/path/to/your/project"]
137137
}
138138
}
@@ -232,7 +232,7 @@ Real projects mix languages — a C core with Python tooling, JS frontends, Go s
232232
- **Native languages** (C, C++, Java, PHP, Yacc, assembly) use GNU Global's fast built-in parser.
233233
- **Everything else** (Python, Go, Rust, JavaScript, TypeScript, Ruby, ... ~150 languages) is indexed through Global's **ctags + Pygments plugin parsers** — same index, same tools, same queries.
234234

235-
The one-line installer (and `gtags-mcp setup`) enables this automatically — it installs universal-ctags and Pygments into user space, and the server switches to the `native-pygments` parser label on its own. Prefer system packages? Those work too:
235+
The one-line installer (and `mcp-gtags-server setup`) enables this automatically — it installs universal-ctags and Pygments into user space, and the server switches to the `native-pygments` parser label on its own. Prefer system packages? Those work too:
236236

237237
```bash
238238
sudo apt install exuberant-ctags python3-pygments # Debian/Ubuntu
@@ -280,7 +280,7 @@ The tool descriptions are written to steer the model: they say *when* to use ind
280280
git clone https://github.com/harshithsunku/mcp-gtags-server
281281
cd mcp-gtags-server
282282
uv run --extra dev pytest # 51 tests; e2e tests auto-skip if GNU Global is absent
283-
npx @modelcontextprotocol/inspector gtags-mcp # poke at it interactively
283+
npx @modelcontextprotocol/inspector mcp-gtags-server # poke at it interactively
284284
```
285285

286286
Tests build a real C project in a temp dir and exercise auto-indexing, auto-refresh, caller mapping, body extraction, pagination, user-space binary discovery, and config layering end-to-end.

pyproject.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "mcp-gtags-server"
3-
version = "0.6.2"
3+
version = "0.7.0"
44
description = "Indexed code navigation for AI coding agents — replace grep scans with GNU Global (gtags) lookups over MCP. ~100x faster and radically less noise on million-line C/C++ codebases."
55
readme = "README.md"
66
requires-python = ">=3.10"
@@ -46,6 +46,8 @@ dev = [
4646
]
4747

4848
[project.scripts]
49+
mcp-gtags-server = "gtags_mcp.server:main"
50+
# Legacy alias — kept so existing MCP client configs keep working.
4951
gtags-mcp = "gtags_mcp.server:main"
5052

5153
[build-system]

scripts/install.sh

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# 1. Ensures `uv` is available (~/.local/bin) — installs it if missing.
88
# 2. Installs OR UPDATES the mcp-gtags-server package (release-driven:
99
# every GitHub tag published to PyPI is picked up automatically).
10-
# 3. Runs `gtags-mcp setup`: installs GNU Global (prebuilt binaries when
10+
# 3. Runs `mcp-gtags-server setup`: installs GNU Global (prebuilt binaries when
1111
# available, otherwise built from source) plus universal-ctags and
1212
# Pygments into ~/.gtags-mcp. On updates, outdated toolchains are
1313
# wiped and reinstalled automatically.
@@ -45,7 +45,7 @@ PID_FILE="$GTAGS_HOME/server.pid"
4545
LOG_FILE="$GTAGS_HOME/server.log"
4646

4747
installed_version() {
48-
command -v gtags-mcp >/dev/null 2>&1 && gtags-mcp --version 2>/dev/null | awk '{print $NF}' || true
48+
command -v mcp-gtags-server >/dev/null 2>&1 && mcp-gtags-server --version 2>/dev/null | awk '{print $NF}' || true
4949
}
5050

5151
server_running() {
@@ -64,7 +64,7 @@ stop_server() {
6464
start_server() {
6565
mkdir -p "$GTAGS_HOME"
6666
say "Starting background MCP server on ${HOST}:${PORT} ..."
67-
nohup gtags-mcp --transport http --host "$HOST" --port "$PORT" \
67+
nohup mcp-gtags-server --transport http --host "$HOST" --port "$PORT" \
6868
>> "$LOG_FILE" 2>&1 &
6969
echo $! > "$PID_FILE"
7070
sleep 2
@@ -80,15 +80,15 @@ start_server() {
8080
print_config() {
8181
echo
8282
if server_running; then
83-
gtags-mcp config --transport http --host "$HOST" --port "$PORT"
83+
mcp-gtags-server config --transport http --host "$HOST" --port "$PORT"
8484
echo
8585
echo " (Prefer per-client processes? The stdio variant also works:)"
86-
echo " claude mcp add --scope user gtags -- gtags-mcp"
86+
echo " claude mcp add --scope user gtags -- mcp-gtags-server"
8787
else
88-
gtags-mcp config
88+
mcp-gtags-server config
8989
fi
9090
echo
91-
echo " Sanity check any time: gtags-mcp doctor"
91+
echo " Sanity check any time: mcp-gtags-server doctor"
9292
echo " No per-repo installs — every repo is indexed automatically on"
9393
echo " the first query."
9494
}
@@ -105,7 +105,7 @@ fi
105105
BEFORE="$(installed_version)"
106106
say "Checking mcp-gtags-server ..."
107107
uv tool install --upgrade --quiet mcp-gtags-server
108-
command -v gtags-mcp >/dev/null 2>&1 || die "gtags-mcp not on PATH after install"
108+
command -v mcp-gtags-server >/dev/null 2>&1 || die "mcp-gtags-server not on PATH after install"
109109
AFTER="$(installed_version)"
110110

111111
UPDATED=0
@@ -120,7 +120,7 @@ fi
120120

121121
# --- 3. gtags toolchain (idempotent; self-heals after updates) ----------------
122122
say "Verifying gtags toolchain in $GTAGS_HOME (no sudo) ..."
123-
gtags-mcp setup
123+
mcp-gtags-server setup
124124

125125
# --- 4. PATH persistence ------------------------------------------------------
126126
ensure_path_line='export PATH="$HOME/.local/bin:$PATH"'

src/gtags_mcp/server.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
it before each query — so agents never have to think about indexing.
88
99
GNU Global (``gtags``/``global``) is resolved through user-space locations
10-
first (see :mod:`gtags_mcp.toolchain`); ``gtags-mcp setup`` installs it
10+
first (see :mod:`gtags_mcp.toolchain`); ``mcp-gtags-server setup`` installs it
1111
without root when it is missing.
1212
"""
1313

@@ -99,7 +99,7 @@ def _check_global_installed() -> str | None:
9999
if toolchain.find_global(_bin_dir) is None or toolchain.find_gtags(_bin_dir) is None:
100100
return (
101101
"Error: GNU Global (gtags/global) was not found. "
102-
"Install it into user space with `gtags-mcp setup` (no sudo needed), "
102+
"Install it into user space with `mcp-gtags-server setup` (no sudo needed), "
103103
"or via a system package (`apt install global`, `brew install global`), "
104104
"or point GTAGS_MCP_BIN_DIR / --bin-dir / `bin_dir` in .gtags-mcp.toml "
105105
"at a directory containing the binaries."
@@ -1093,7 +1093,7 @@ def index_project(project_root: str | None = None) -> str:
10931093
if non_native:
10941094
message += (
10951095
f" Note: {', '.join(sorted(non_native))} files were NOT indexed — "
1096-
"run `gtags-mcp setup` (installs ctags + Pygments into user space, "
1096+
"run `mcp-gtags-server setup` (installs ctags + Pygments into user space, "
10971097
"no sudo) to enable multi-language indexing."
10981098
)
10991099
return message
@@ -1170,12 +1170,12 @@ def _client_config_text(transport: str, host: str, port: int) -> str:
11701170
"MCP client configuration (stdio transport):",
11711171
"",
11721172
" Claude Code (once per device, all repos):",
1173-
" claude mcp add --scope user gtags -- gtags-mcp",
1173+
" claude mcp add --scope user gtags -- mcp-gtags-server",
11741174
"",
11751175
" Cursor / any MCP client — global settings or .mcp.json:",
11761176
" {",
11771177
' "mcpServers": {',
1178-
' "gtags": { "command": "gtags-mcp" }',
1178+
' "gtags": { "command": "mcp-gtags-server" }',
11791179
" }",
11801180
" }",
11811181
]
@@ -1186,7 +1186,7 @@ def main() -> None:
11861186
"""Entry point: serve MCP over stdio/HTTP, or run a maintenance subcommand."""
11871187
global _default_root, _forced_label, _bin_dir
11881188
parser = argparse.ArgumentParser(
1189-
prog="gtags-mcp",
1189+
prog="mcp-gtags-server",
11901190
description=(
11911191
"MCP server exposing GNU Global (gtags) code navigation. "
11921192
"Subcommands: 'setup' installs the toolchain into user space "
@@ -1274,7 +1274,7 @@ def main() -> None:
12741274
sys.exit(toolchain.run_setup(with_ctags=not args.no_ctags, force=args.force))
12751275
if args.command == "doctor":
12761276
root, _ = _effective_root(args.root)
1277-
print(f"gtags-mcp doctor (v{_package_version()})")
1277+
print(f"mcp-gtags-server doctor (v{_package_version()})")
12781278
print(toolchain.doctor_report(project_root=root))
12791279
label = _gtags_label(root)
12801280
print(f" parser label : {label or 'native (C/C++/Java/PHP/asm only)'}")
@@ -1286,7 +1286,7 @@ def main() -> None:
12861286
mcp.settings.host = args.host
12871287
mcp.settings.port = args.port
12881288
print(
1289-
f"gtags-mcp v{_package_version()} — streamable HTTP server on "
1289+
f"mcp-gtags-server v{_package_version()} — streamable HTTP server on "
12901290
f"{args.host}:{args.port}\n",
12911291
flush=True,
12921292
)
@@ -1298,11 +1298,11 @@ def main() -> None:
12981298
return
12991299
if sys.stdin.isatty():
13001300
print(
1301-
"gtags-mcp: serving MCP over stdio — this mode is meant to be "
1301+
"mcp-gtags-server: serving MCP over stdio — this mode is meant to be "
13021302
"launched by an MCP client (Claude Code, Cursor, ...), not typed "
13031303
"into.\n"
1304-
" Maintenance commands: gtags-mcp doctor | config | setup | help\n"
1305-
" Shared background server: gtags-mcp --transport http\n"
1304+
" Maintenance commands: mcp-gtags-server doctor | config | setup | help\n"
1305+
" Shared background server: mcp-gtags-server --transport http\n"
13061306
" Press Ctrl+C to exit.",
13071307
file=sys.stderr,
13081308
flush=True,

src/gtags_mcp/toolchain.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
The server never assumes ``gtags``/``global`` come from a system package.
44
Binaries are resolved through a search order that puts user-space locations
5-
first, and ``gtags-mcp setup`` can install the whole toolchain without root:
5+
first, and ``mcp-gtags-server setup`` can install the whole toolchain without root:
66
77
1. an explicit ``bin_dir`` (tool argument, ``--bin-dir``, ``GTAGS_MCP_BIN_DIR``
88
env var, or ``bin_dir`` in a config file),
@@ -577,7 +577,7 @@ def run_setup(with_ctags: bool = True, force: bool = False, log=print) -> int:
577577
differs from the pinned ``GLOBAL_VERSION`` (e.g. after the package was
578578
upgraded), the whole managed home is removed and reinstalled fresh.
579579
"""
580-
log(f"gtags-mcp setup — installing into {managed_home()} (no sudo needed)")
580+
log(f"mcp-gtags-server setup — installing into {managed_home()} (no sudo needed)")
581581

582582
managed_version = _managed_global_version()
583583
if managed_version and managed_version != GLOBAL_VERSION:
@@ -663,12 +663,12 @@ def version_of(exe: str | None) -> str:
663663
)
664664
if not find_global(project_root=project_root):
665665
lines.append(
666-
"\n GNU Global is missing — run `gtags-mcp setup` to install it "
666+
"\n GNU Global is missing — run `mcp-gtags-server setup` to install it "
667667
"into user space (no sudo needed)."
668668
)
669669
elif not pygments_available():
670670
lines.append(
671671
"\n Pygments is missing — multi-language references are disabled. "
672-
"Re-run `gtags-mcp setup` to install it into user space."
672+
"Re-run `mcp-gtags-server setup` to install it into user space."
673673
)
674674
return "\n".join(lines)

tests/test_toolchain.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ def test_doctor_report_mentions_setup_when_missing(tmp_path, monkeypatch):
171171
# Hide any system global from the report.
172172
monkeypatch.setattr(toolchain.shutil, "which", lambda name: None)
173173
report = toolchain.doctor_report()
174-
assert "gtags-mcp setup" in report
174+
assert "mcp-gtags-server setup" in report
175175
assert "NOT FOUND" in report
176176

177177

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)