Skip to main content
Glama
TingPing

gobject-introspection-mcp

by TingPing
README.md
# gobject-introspection-mcp

An MCP server that exposes GObject Introspection metadata to coding agents.
It parses the `.gir` XML files installed on your system and makes every
library, class, function, signal, property, enum member, and struct field
queryable through a standard set of MCP tools.

All data is C-language-oriented: C symbol names, C type strings, header
includes, ownership-transfer semantics (`none` / `container` / `full`),
argument directions (`in` / `out` / `inout`), and GType information.

A SQLite cache (`~/.cache/gi-mcp/cache.db`) is maintained automatically.
Each namespace is re-parsed only when its `.gir` file changes on disk.

## Requirements

- Python 3.11+
- `lxml` (usually already installed system-wide)
- GIR files — install the `-dev` / `-devel` packages for the libraries you
  want to introspect, e.g. `libgtk-4-dev`, `libglib2.0-dev`

## Running

### With uv (no install required)

```sh
# stdio transport — used by Claude Code and VS Code Copilot
uv run --project /path/to/gobject-introspection-mcp gi-mcp

# streamable-HTTP transport (for remote/browser clients)
uv run --project /path/to/gobject-introspection-mcp gi-mcp --transport http --port 8000
```

### Installed via pip

```sh
pip install --user .
gi-mcp                          # stdio (default)
gi-mcp --transport http --port 8000
```

## Editor integration

### VS Code Copilot

Add to `.vscode/mcp.json` in your workspace (a ready-made file is included):

```json
{
  "servers": {
    "gi": {
      "type": "stdio",
      "command": "uv",
      "args": ["run", "--directory", "${workspaceFolder}", "gi-mcp"]
    }
  }
}
```

### Claude Code

Add to `.claude/settings.json` in your project (a ready-made file is included):

```json
{
  "mcpServers": {
    "gi": {
      "command": "uv",
      "args": ["run", "--directory", "/absolute/path/to/gobject-introspection-mcp", "gi-mcp"]
    }
  }
}
```

Switch to **Agent mode** in Copilot Chat, or start a Claude Code session —
the tools listed below will be available automatically.

## MCP tools

| Tool | Description |
|------|-------------|
| `list_namespaces` | All installed GIR namespaces with version, shared library, C prefixes, headers, and dependencies |
| `list_symbols(namespace, [version], [kind])` | All top-level symbols in a namespace; filter by `kind` (`"class"`, `"function"`, `"enumeration"`, …) |
| `search_symbols(query, [max_results])` | Case-insensitive name substring search across all namespaces |
| `search_by_c_identifier(c_identifier, [max_results])` | Find symbols by C name (e.g. `gtk_widget_show`, `GTK_ALIGN_FILL`) |
| `get_symbol_details(namespace, name, [version])` | Full details for any top-level symbol — C type, methods, properties, signals, fields, parent, interfaces, headers |
| `list_members(namespace, symbol_name, [version])` | Methods, constructors, properties, signals, and fields of a class, interface, record, or union |
| `get_inheritance_chain(namespace, symbol_name, [version])` | Full ancestor chain from a class to the root, including which interfaces each ancestor implements |
| `find_implementations(namespace, interface_name, [version])` | All classes across all namespaces that implement an interface |
| `get_signal(namespace, symbol_name, signal_name, [version])` | Full signal details: parameters with types and transfer ownership, emission timing, flags, doc |
| `get_property(namespace, symbol_name, property_name, [version])` | Property type, C type, read/write/construct flags, transfer ownership, doc |
| `get_field(namespace, symbol_name, field_name, [version])` | Struct/record/union field: type, C type, pointer flag, readable/writable, doc |
| `get_enum_member(namespace, symbol_name, member_name, [version])` | Enum or flags member: integer value, C macro name (e.g. `GTK_ALIGN_FILL`), doc |
| `get_callback(namespace, name, [version])` | Callback typedef: full parameter list with directions and transfer, return type, GError flag |
| `search_signals(query, [namespace], [max_results])` | Find signals by name substring — answers "which class emits `clicked`?" |
| `search_properties(query, [namespace], [max_results])` | Find properties by name substring across all types |
| `get_constant(namespace, name, [version])` | Top-level constant: value, C macro name, type, headers |
| `list_deprecated(namespace, [version], [kind])` | All deprecated symbols in a namespace, optionally filtered by kind |

## Example queries

```
list_namespaces
→ [{namespace: "GLib", version: "2.0", headers: ["glib.h"], ...}, ...]

get_symbol_details("GObject", "Object")
→ {name: "Object", c_type: "GObject", gtype_name: "GObject",
   headers: ["glib-object.h"], methods: [...], signals: [...], ...}

get_signal("GObject", "Object", "notify")
→ {name: "notify", when: "first", callable: {parameters: [{name: "pspec", ...}]}}

search_signals("clicked")
→ [{signal_name: "clicked", defined_on: "Button", namespace: "Gtk", ...}, ...]

get_enum_member("Gtk", "Align", "fill")
→ {name: "fill", value: 0, c_identifier: "GTK_ALIGN_FILL", kind: "enumeration"}

search_by_c_identifier("g_object_ref")
→ [{c_identifier: "g_object_ref", name: "ref", kind: "method",
    defined_on: "Object", namespace: "GObject"}]

get_inheritance_chain("Gtk", "Button")
→ {name: "Button", parent: "Gtk.Widget", implements: ["Gtk.Actionable", ...],
   ancestors: [{name: "Widget", ...}, {name: "Object", namespace: "GObject"}]}
```

## Cache

Parsed data is stored in `$XDG_CACHE_HOME/gi-mcp/cache.db` (default
`~/.cache/gi-mcp/cache.db`). Each namespace is a set of rows in a SQLite
database — one row for namespace metadata and one row per symbol — keyed by
namespace name and the `.gir` file's modification time. Stale entries are
replaced automatically; no manual cache management is needed.

Override the cache location via `XDG_CACHE_HOME`. Override which `.gir`
directories are searched via `GIR_PATH` (colon-separated).