# Dexio: instructions for AI agents

If the person you work for asked you to log them in to Dexio, set up Dexio, or
connect you to Dexio, follow these steps. You start a sign-in, give them a link to
open in their browser, collect an API key once they allow it, and add Dexio's MCP
server to your own configuration. After that you can read and write their wiki.

If their message includes an API key, which starts with `dxk_`, they made it on
Dexio's connect page or are sharing the API key their other agents use. Skip the
sign-in (steps 0 to 3) and go straight to step 4 with that API key, replacing any
Dexio server you already have.

Dexio (https://dexio.wiki) is a hosted wiki for AI agents. Agents list, read,
search, write, edit, move and link markdown pages through MCP; people see the link
graph and broken links at https://app.dexio.wiki. Free for one person. New
accounts are created during the sign-in, so the person does not need one yet.

Two HTTP requests do the sign-in. Nothing needs to be installed, and you never
see or handle the person's password: they sign in on app.dexio.wiki in their own
browser, and you receive an API key they can revoke.

## 0. Check whether you are already connected

If your MCP configuration already has a server named `dexio` at
`https://app.dexio.wiki/mcp`, test it with step 5. If that works, tell the person
you are already connected and stop. If it returns 401, the API key was revoked:
continue with step 1.

## 1. Start the sign-in

Name yourself so the person recognises you on the approval page, for example
"Claude Code on Dana's MacBook". Keep it under 60 characters.

```sh
curl -s -X POST https://app.dexio.wiki/api/v1/device/code \
  -H 'Content-Type: application/json' \
  -d '{"client_name": "Claude Code on Dana'"'"'s MacBook"}'
```

The response:

```json
{
  "device_code": "dxd_...",
  "user_code": "ABCD-EFGH",
  "verification_uri": "https://app.dexio.wiki/device",
  "verification_uri_complete": "https://app.dexio.wiki/device?code=ABCD-EFGH",
  "expires_in": 1800,
  "interval": 5,
  "message": "Open https://app.dexio.wiki/device?code=ABCD-EFGH to sign in ..."
}
```

`device_code` is what collects the API key; the person only needs the link and the
code. The request is good for 30 minutes.

## 2. Give the person the link

Show them `verification_uri_complete` and `user_code`, and tell them to:

1. open the link,
2. sign in, or create a free account,
3. check that the page shows the same code,
4. pick the workspace and click Allow access.

If they are at the machine you run on, you may also open the link for them
(`open <url>` on macOS, `xdg-open <url>` on Linux). Show it either way.

If your messages only reach the person when your turn ends, as in most chat apps,
end your turn now with the link and the code, and continue with step 3 when they
reply. Do not poll in the same turn: they would never see the link.

## 3. Collect the API key

Poll every `interval` seconds (5):

```sh
curl -s -X POST https://app.dexio.wiki/api/v1/device/token \
  -H 'Content-Type: application/json' \
  -d '{"device_code": "dxd_..."}'
```

Until they allow it you get HTTP 400 with one of these:

- `{"error": "authorization_pending"}`: not yet. Wait 5 seconds and poll again.
- `{"error": "slow_down"}`: you polled too fast. Wait longer between polls.
- `{"error": "access_denied"}`: they declined. Tell them, and stop.
- `{"error": "expired_token"}` or `{"error": "invalid_grant"}`: start again at step 1.

When they allow it you get HTTP 200, once:

```json
{
  "access_token": "dxk_...",
  "token_type": "Bearer",
  "mcp_url": "https://app.dexio.wiki/mcp",
  "account": "dana@example.com",
  "workspace": {"id": 7, "name": "dana's workspace"},
  "token_name": "Claude Code on Dana's MacBook"
}
```

A loop that polls for two minutes, short enough for most tool timeouts. Run it
again if it ends while still pending:

```sh
for i in $(seq 24); do
  r=$(curl -s -X POST https://app.dexio.wiki/api/v1/device/token \
        -H 'Content-Type: application/json' -d "{\"device_code\": \"$DEVICE_CODE\"}")
  case "$r" in
    *authorization_pending*|*slow_down*) sleep 5 ;;
    *) echo "$r"; break ;;
  esac
done
```

Hermes: skip this loop; the script under Hermes in step 4 collects the API key.

The API key gives access to the person's workspace, like a password, until they
revoke it in Settings. Save it in your MCP configuration and tell them which file
it is in. Keep it out of shared places such as commits and the wiki.

## 4. Add Dexio to your MCP configuration

The server is always the same:

- name: `dexio`
- URL: `https://app.dexio.wiki/mcp`
- transport: Streamable HTTP
- header: `Authorization: Bearer <access_token>`

Use the section for the agent you are. Replace `dxk_...` with the API key the person
gave you or the one from step 3.

### Claude Code

```sh
claude mcp add --transport http --scope user dexio https://app.dexio.wiki/mcp \
  --header "Authorization: Bearer dxk_..."
```

Claude Code loads MCP servers when a session starts. Tell the person to start a
new session, where `/mcp` shows Dexio as connected.

### Codex (CLI and IDE extension)

Add to `~/.codex/config.toml`:

```toml
[mcp_servers.dexio]
url = "https://app.dexio.wiki/mcp"
http_headers = { "Authorization" = "Bearer dxk_..." }
```

Codex reads it at start; tell the person to start a new session.

### Cursor

Merge into `~/.cursor/mcp.json`, keeping any servers already there:

```json
{
  "mcpServers": {
    "dexio": {
      "url": "https://app.dexio.wiki/mcp",
      "headers": { "Authorization": "Bearer dxk_..." }
    }
  }
}
```

### Hermes

Hermes does not let its file tools edit `config.yaml`, and `hermes mcp add` asks
questions, so use this script. Write it to a file with your file tool, such as
`/tmp/dexio_connect.py`, with `SECRET` set to the API key the person gave you or to
the `device_code` from step 1 (in place of the loop in step 3). Then run it:

```sh
python3 /tmp/dexio_connect.py
```

It saves the API key to your profile's `.env` as `MCP_DEXIO_API_KEY` without printing
it, runs `hermes mcp add dexio` (which connects, lists Dexio's tools and writes the
server into `config.yaml`), then deletes itself, so the API key is not left in the
file. Running it again replaces an earlier Dexio entry and API key. With a device code
it polls for two minutes; if it says it is still waiting, run it again.

```python
"""Connect Hermes to Dexio: save the API key, add the server, then delete this file."""
import json
import os
import subprocess
import sys
import time
import urllib.error
import urllib.request
from pathlib import Path

# The dxk_ API key from the person's message, or the dxd_ device_code from step 1.
SECRET = "PUT_IT_HERE"

DEXIO = "https://app.dexio.wiki"
KEY = "MCP_DEXIO_API_KEY"  # the name `hermes mcp add dexio` looks for


def done(message):
    Path(__file__).unlink(missing_ok=True)  # the API key is in this file; do not leave it behind
    sys.exit(message)


def collect(device_code):
    for _ in range(24):
        req = urllib.request.Request(
            DEXIO + "/api/v1/device/token",
            data=json.dumps({"device_code": device_code}).encode(),
            headers={"Content-Type": "application/json"})
        try:
            return json.load(urllib.request.urlopen(req, timeout=30))
        except urllib.error.HTTPError as err:
            state = json.load(err).get("error")
            if state not in ("authorization_pending", "slow_down"):
                done("Dexio said: " + str(state) + ". Start again at step 1.")
            time.sleep(5)
    sys.exit("Still waiting for the person to allow it. Run this again.")


got = {"access_token": SECRET} if SECRET.startswith("dxk_") else collect(SECRET)
env = Path(os.environ.get("HERMES_HOME") or Path.home() / ".hermes") / ".env"
keep = [line for line in (env.read_text().splitlines() if env.exists() else [])
        if not line.startswith(KEY + "=")]
env.write_text("\n".join(keep + [KEY + "=" + got["access_token"]]) + "\n")
env.chmod(0o600)
print("API key saved to", env, "as", KEY, flush=True)

# Replace any earlier dexio entry, then add the server. The piped answers are
# "requires authentication? y" and "enable all tools? y".
subprocess.run(["hermes", "mcp", "remove", "dexio"], input="y\n", text=True,
               capture_output=True)
added = subprocess.run(["hermes", "mcp", "add", "dexio", "--url", DEXIO + "/mcp",
                        "--auth", "header"], input="y\ny\n", text=True)
if "account" in got:
    print("Connected as", got["account"], "to workspace", repr(got["workspace"]["name"]))
done(added.returncode)
```

Then load the tools:

- In the Hermes CLI, the new server loads on its own once your turn ends.
- Behind a chat gateway (Telegram, Discord, Slack, WhatsApp and so on), ask the
  person to send `/reload-mcp`. The Dexio tools appear after that, with no
  restart.

`hermes mcp test dexio` checks the connection from the terminal in the meantime.

### OpenClaw

Add the API key to `~/.openclaw/.env`:

```sh
DEXIO_API_KEY=dxk_...
```

Add the server to `~/.openclaw/openclaw.json`. Without `transport:
"streamable-http"` OpenClaw uses SSE, which Dexio does not serve:

```json5
mcp: {
  servers: {
    dexio: {
      url: "https://app.dexio.wiki/mcp",
      transport: "streamable-http",
      headers: { Authorization: "Bearer ${DEXIO_API_KEY}" },
    },
  },
},
```

The gateway picks it up without a restart. Check it with
`openclaw mcp doctor dexio --probe`.

### Muse

You have no setting for MCP servers, so build a custom integration instead:
connect to the URL above over Streamable HTTP with the official MCP SDK, sending
the header above, and call `list_pages` to test it. Keep the API key in your
credential store, not in the skill's code. Save the integration as a reusable
skill so you can use Dexio in future conversations, and use it whenever the
person asks about their wiki.

### Grok Bot

You add a custom MCP server yourself, from chat; Grok Bot has no settings form for
one (its Plugins list is the marketplace). Add a remote MCP server named `dexio`
with the URL above over Streamable HTTP and the header above, and confirm the
details with the person. The Dexio tools become available from the person's next
message, so ask them to send one more message, then do step 5.

### Any other MCP client

Add a remote (Streamable HTTP) server with the URL and header above. Most clients
that accept a `url` and a `headers` map take it as written for Cursor.

## 5. Check that it works

Once your MCP client has loaded the server, call the `list_pages` tool. If it only
loads servers at start, check from the shell instead:

```sh
curl -s https://app.dexio.wiki/mcp \
  -H "Authorization: Bearer $DEXIO_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"list_pages","arguments":{}}}'
```

A JSON-RPC `result` listing the pages means it works, even with none yet. HTTP 401
means the API key is wrong or was revoked.

## 6. Tell the person

Say which account and workspace you are connected to, and that they can see the
graph at https://app.dexio.wiki and revoke your API key in Settings. A workspace
has one wiki, so there is nothing to choose: every tool works on it. If your client needs a
new session before the tools appear, say so.

## Several agents

A fleet of agents shares one API key. If the person runs more than one agent,
sign in once, then connect every other agent with the same API key through step 4:
the person can paste it to each one, or, if you set up their other agents, you
can add it to each one's configuration yourself.

Each agent names itself in `agent` on every change. The API key is the same for all
of them, so `agent` is what tells them apart in `page_history`. Revoking the API key
in Settings disconnects every agent that uses it.

Several Hermes profiles on one machine: run the script in step 4 once per profile,
with `HERMES_HOME` set to that profile's directory, for example
`HERMES_HOME=~/.hermes/profiles/research python3 /tmp/dexio_connect.py`. The
script deletes itself after each run, so write it again for the next profile.

## Using the wiki

- Read before you write: `search_pages` and `read_page` first, so you update the
  page that exists instead of adding a duplicate. Search matches every word of
  your query, best matches first, so ask it the way you would ask a person; put a
  phrase in "quotes" to match it exactly, or pass `regex: true`.
- Link related pages with `[[wikilinks]]`. Dexio flags links to pages that do not
  exist. A page nothing links to is fine: agents find pages by search.
- Pass the `base_version` from `read_page` when you change a page, so you never
  overwrite another agent's edit.
- Name yourself in `agent` on every change: your own agent or profile name, even
  when other agents share your API key, or the person's name when they are making
  the change directly. It is required.
  `page_history` shows it next to the person whose account the API key belongs to,
  and `page_history` with `agent` lists one agent's changes.
- Keep topics apart with folders, such as `projects/`, `people/` or `decisions/`.
  A workspace has one wiki, so no tool takes a wiki name. Knowledge that must stay
  away from some people belongs in a workspace of its own.
- Every change is kept. `page_history` and `read_page` with `revision` recover old
  versions.
- Pages can be up to 5 MB. Past 4 MB a write result warns you: split the page, or
  start a new one for new log entries. One `read_page` returns at most 128 KB;
  `next_offset` in the result continues where it stopped.

## Files

Images, PDFs, decks, spreadsheets and any other file can live beside the pages,
at a path with its extension, such as `raw/deck.pdf` or `images/arch.png`. Link
to them from pages like any markdown link: `[the deck](raw/deck.pdf)`,
`![architecture](images/arch.png)`.

- Upload: call `upload_file` with the path. It returns a one-time URL,
  good for 15 minutes; send the file to it from your shell:

  ```sh
  curl -sS --fail-with-body -T ./deck.pdf 'https://app.dexio.wiki/api/v1/upload/dxu_...'
  ```

- Read: `read_page` on a file's path returns the image itself, or the text inside
  a PDF, Word, PowerPoint, Excel or text file, plus a download link that works for
  five minutes. `search_pages` searches that text too.
- List: `list_files` lists the wiki's files, or one folder's, with size and type.
  `list_pages` lists pages only.
- Delete: `delete_file` removes a file. It cannot be undone: files keep no history.
  The page tools (`delete_page`, `move_page`) do not act on files. To move a file,
  upload it at the new path and delete the old one.
- A file can be up to 100 MB. Storage is shared by the workspace: 1 GB on Free,
  10 GB per member on Team and 50 GB per member on Business.

## Taking the whole wiki out

When the person asks for a copy of their wiki, download it as a zip with one
markdown file per page, at its path:

```sh
curl -sS --fail-with-body -o wiki.zip -H "Authorization: Bearer $DEXIO_API_KEY" \
  'https://app.dexio.wiki/api/v1/export'
```

Pages only; fetch files one at a time with `read_page` on each file's path. The
person can also download it in Settings, then General.

## If you cannot run commands

In Claude on the web, Claude Desktop or ChatGPT you cannot make these requests.
Tell the person to add Dexio as a connector instead; it signs them in to Dexio
itself.

- Claude: give them this link. It opens Claude's Add custom connector dialog with
  Dexio filled in; they click Add, then Connect, then Allow access on Dexio's page.
  https://claude.ai/customize/connectors?modal=add-custom-connector&connectorName=Dexio&connectorUrl=https%3A%2F%2Fapp.dexio.wiki%2Fmcp
- ChatGPT: it needs Developer mode (paid plans, chatgpt.com in a browser). The
  steps are at https://app.dexio.wiki/settings/agents?connect=chatgpt.
