# Quickstart

Five steps take an installed Hub to its first answered script: create the configuration and the token, enable Inkscape, declare the Hub in your MCP client, check what the Hub sees, send a script. It is for engineers who already have the package; Inkscape needs no bridge. Otherwise start with [Installation](https://libremodular.davalan.fr/installation/index.md).

## Create the configuration and the token

Run this once, as your own user:

```sh
libremodular-mcp init
```

It prints one line per directory and per file it creates; this page writes `$HOME` for the start of each path:

```text
directory ready: $HOME/.config/libremodular-mcp
directory ready: $HOME/.local/state/libremodular-mcp
configuration created: $HOME/.config/libremodular-mcp/config.toml
token created: $HOME/.config/libremodular-mcp/token
```

Both files are in mode 600. Run a second time, `init` leaves them as they are and says `configuration exists, unchanged` and `token exists, unchanged`.

## Enable Inkscape

After `init`, every application is disabled. This command enables Inkscape:

```sh
sed -i '/^\[apps.inkscape\]/,/^$/ s/enabled = false/enabled = true/' ~/.config/libremodular-mcp/config.toml
```

The entry in `config.toml` then reads:

```toml
[apps.inkscape]
enabled = true
mode = "cli"
```

Inkscape 1.4 is the version this page ran against. In the `cli` mode the Hub starts one Python process per script, so there is no bridge to start. GIMP, Krita, Blender and LibreOffice are reached through a bridge that you start by hand; each guide gives the commands: [GIMP](https://github.com/RonanDavalan/LibreModular-MCP/blob/main/docs/modules/gimp.md), [Krita](https://github.com/RonanDavalan/LibreModular-MCP/blob/main/docs/modules/krita.md), [Blender](https://github.com/RonanDavalan/LibreModular-MCP/blob/main/docs/modules/blender.md) and [LibreOffice](https://github.com/RonanDavalan/LibreModular-MCP/blob/main/docs/modules/libreoffice.md).

## Declare the Hub in your MCP client

The client runs the Hub as a command with the argument `serve`. With the package, the command is `/usr/bin/libremodular-mcp`; built from the sources, it is the absolute path of `target/release/libremodular-mcp` in your clone.

```json
{
  "mcpServers": {
    "libremodular": {
      "command": "/usr/bin/libremodular-mcp",
      "args": ["serve"]
    }
  }
}
```

The Hub needs the variable `XDG_RUNTIME_DIR`, which a desktop session sets. Without it, `libremodular-mcp serve` stops at once with `error: XDG_RUNTIME_DIR is not set; refusing to write volatile files elsewhere`.

[Connect your model](https://libremodular.davalan.fr/clients/index.md) gives this entry for Claude Code and for opencode, each tried in the client, with the answer to `get_state` that the client received.

> **Limit**
>
> No other MCP client was tried. Which file the entry goes into, and what its keys are called, depends on your client.


## Make the first call

The guide for the model makes `get_state` on `hub` the first call: it lists the applications the Hub can reach. Ask your model to make it, or run the client of the Demonstration, whose first answer is this one:

**Hub response**

```json
{
  "app": "hub",
  "app_version": "0.1.0",
  "bridge_version": null,
  "captured_at": "2026-10-21T07:57:39.858Z",
  "connected": true,
  "content_origin": "hub",
  "screenshot": null,
  "state": {
    "modules": [
      {
        "app_version": "1.4",
        "bridge_version": null,
        "connected": true,
        "mode": "cli",
        "name": "inkscape"
      }
    ]
  },
  "warnings": []
}
```


`inkscape` is connected, in the `cli` mode, and its `app_version` is `1.4`. The Hub exposes two tools and no more: a client that asks for the list of tools gets `["execute_script", "get_state"]`.

## Send the first script

A model sends a script like this one through `execute_script`. To send it yourself, save it as `first.py`, save the client of the [Demonstration](https://libremodular.davalan.fr/demonstration/index.md) as `client.py`, and run `python3 client.py first.py`.

**Script written**

```python
import json

print("the script ran inside Inkscape's Python")
print("LMM_RESULT: " + json.dumps({"answer": 6 * 7}))
```


The third answer of the client is the Hub's answer to the script:

**Hub response**

```json
{
  "app": "inkscape",
  "duration_ms": 30,
  "error": null,
  "result": {
    "answer": 42
  },
  "status": "ok",
  "stderr": "",
  "stdout": "the script ran inside Inkscape's Python\n",
  "truncated": false
}
```


`stdout` is what the script printed, `result` is the value after `LMM_RESULT: `, and `status` is `ok`. The guide for the model lists the other statuses (`error`, `refused`, `timeout`, `busy` and `unavailable`) and what to do with each: [guide for the model](https://github.com/RonanDavalan/LibreModular-MCP/blob/main/docs/GUIDE_LLM.md). A script that draws, and the image it produced, are on the [Demonstration](https://libremodular.davalan.fr/demonstration/index.md) page.

