---
title: "Work with an AI agent"
description: "Connect an agent with a key of its own, sign it in from its client, and have it open a document for you to review."
---

> Documentation Index
> Fetch the complete documentation index at: https://commentware.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Work with an AI agent

Point an AI agent at your server, so it reads and answers the same threads you
do under its own name, and have it open a document for you to comment on.
Learn more about [what an agent can do](/docs/concepts/agents/).

## Prerequisites

- A running server, and a shell on its machine. If there is no server yet,
  start at [Install a server](/docs/install-server/).
- An MCP client: Claude Code, Codex, OpenCode, Gemini CLI, VS Code, Cursor, or
  another that speaks streamable HTTP.

## Connect the clients on the server's machine

If the agent's client runs on the same machine as a server bound to
`127.0.0.1` with no public address set, one command connects it, with no
browser sign-in. It gives the client a user of its own, named for the client
and holding `can_collaborate`, and writes that user's access key into the
client's own config file. A server reachable from anywhere else is refused,
because the key would sit in a file; [sign in through a
browser](#browser-sign-in) instead. The installer offers this once, on a first
install, for every client it finds.

1. List the MCP clients on this machine:

```sh
commentware mcp clients
```

   It prints each client it can connect and whether it is installed, and for
   one connected to this server, the name of its entry and its user. VS Code is
   not one: it signs in through a browser, as under [Sign in through a
   browser](#browser-sign-in).

```text
   Claude Code  "commentware": connected, as user 3
   Codex        "commentware": connected, as user 4
   OpenCode     not connected
   Gemini CLI   not connected
   Cursor       not connected

   Connect one with "commentware mcp connect <client>": claude-code, codex, opencode, gemini-cli, cursor.
```

2. Connect one, by its id from that last line:

```sh
   commentware mcp connect cursor
```

   It prints the user it made and the file the key went into:

```text
   Connected Cursor to http://127.0.0.1:7042/api/mcp as user 5 (Cursor), holding "can_collaborate".
   Its key is in /home/alex/.cursor/mcp.json, under "commentware". "commentware mcp disconnect cursor" revokes it.

   A Cursor window that is already open picks it up once it is reloaded.
```

   If the client already signs in to this server through a browser, it is
   left as it is:

```text
   Cursor already reaches this server under "commentware", signed in through a browser.
   Nothing was changed. "--replace" gives it a user and a key of its own instead.
```

   To trade the browser sign-in for a key of its own, add `--replace`:

```sh
   commentware mcp connect cursor --replace
```

3. To take a client out, and revoke its key:

```sh
   commentware mcp disconnect cursor
```

   The user stays, so what its agent wrote keeps its name. If a client's entry
   holds a key this server did not mint, as when you run
   `commentware mcp disconnect gemini-cli`, the entry is left in place and the
   command says where it is:

```text
   Gemini CLI's "commentware" entry is at this server's address with a key it does not have, and was
   left alone: it may be another server's on the same port. Remove it from /home/alex/.gemini/settings.json
   if it is not, or "commentware mcp connect gemini-cli" writes this server over it.
```

To give the client's user another permission, change it as in [Choose the
agent's permission](#the-two-permissions). [`mcp connect`](/docs/server/commands/#mcp-connect)
and [`mcp disconnect`](/docs/server/commands/#mcp-disconnect) list their
options, including replacing another server's entry and taking out every client
at once. A key in the configuration switches Claude Code's browser sign-in off
for that server, as the caution under [Connect an agent with no
browser](#agents-with-no-browser) says. To keep another server's entry beside
this one, see [Connect one agent to several
servers](#several-servers). Learn more about [a server only your machine can
reach](/docs/concepts/local-servers/).

To check that it worked, run `commentware mcp clients` again. The client reads
`"commentware": connected, as user 5`.

## Wire one up

On the machine running the server:

1. **Mint the agent a key of its own.**

```sh
commentware users new my-agent --permissions can_collaborate
```

   The agent's comments are signed with its own name, and `can_collaborate`
   lets it read, comment, reply and resolve, and not delete. See [the agent's
   permission](#the-two-permissions).

2. **Print the endpoint.**

```sh
commentware mcp
```

   It prints the address clients reach your running server at, and, on a
   server with sign-in, what adds it to each client: a command or two for most,
   a file to edit for some. Add `--json` if the thing reading it is the agent
   rather than you.

3. **Add the server to your client and sign in**, in a browser. See [Sign in through a
   browser](#browser-sign-in) for your client. The key is typed into a page on
   your own server and never reaches the client's configuration. If you cannot
   open a browser, see [Connect an agent with no
   browser](#agents-with-no-browser).

4. **Choose a project.** Ask the agent to pick one with `set_active_project`, or
   to make one first with `create_project`. An agent's project is its own,
   separate from your browser's.

## Choose the agent's permission

**`can_collaborate` on its own is what to hand an agent**, and it is what step 1
gives it: read everything, comment, reply and resolve, and delete nothing.

1. Optional: if the agent has to delete too, grant `can_admin` as well:

```sh
   commentware users permissions <id> can_admin,can_collaborate
```

The key prints once and is stored hashed. [Manage users and access
keys](/docs/server/users/) covers minting another and stopping a lost one.

## Sign in through a browser

The key is typed into a page on your own server, once, and never reaches a
config file, a shell history or the agent's environment. Learn more about [how
an agent signs in](/docs/concepts/agents/#how-an-agent-signs-in).

1. Add the server to your client with no credential, using its lines below.
   `<url>` is the address `commentware mcp` printed; on a server bound to
   `127.0.0.1`, `localhost` in its place works too.
2. Run the client's sign-in step. It opens a page on your server.
3. Paste the access key, or the whole connection string, into that page.

If `commentware mcp` says your server has no sign-in, bind loopback and reach it
over an SSH forward to the same port number — `ssh -L 7042:127.0.0.1:7042` for
one on `7042` — or put HTTPS in front of it and set its [public
address](/docs/server/config/). Otherwise see [connect an agent with no
browser](#agents-with-no-browser).

### Claude Code

```sh
claude mcp add --transport http --scope user commentware <url>
```

Then `claude mcp login commentware`. `/mcp` inside a session
does the same.

### Codex

```sh
codex mcp add commentware --url <url>
```

It opens the sign-in page itself. If it does not, run
`codex mcp login commentware`.

### OpenCode

Add the server to `~/.config/opencode/opencode.json`:

```json
{
  "mcp": {
    "commentware": {
      "type": "remote",
      "url": "<url>"
    }
  }
}
```

Then `opencode mcp auth commentware`, or let OpenCode ask the first
time it uses the server.

### Gemini CLI

```sh
gemini mcp add --transport http --scope user commentware <url>
```

Then, inside Gemini, `/mcp auth commentware`.

### VS Code

```sh
code --add-mcp '{"name":"commentware","type":"http","url":"<url>"}'
```

VS Code asks to authenticate the first time the server starts. Allow it, and a
browser opens.

### Cursor

Add the server to `~/.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "commentware": {
      "url": "<url>"
    }
  }
}
```

Then **Connect** it in Cursor's MCP settings. Cursor signs in through
`http://localhost:8787/callback`. An older install that still sends a
`cursor://` callback is refused — that address is not one an authorization
server may accept — so update Cursor if sign-in stops at an error page. Cursor
listens for that callback on IPv6 only, so a browser that takes `localhost` to
mean `127.0.0.1` reaches nothing; Cursor treats that as its own bug.

### Other clients

Any client that speaks streamable HTTP and signs in to MCP servers with OAuth
works the same way: add `<url>` with no header, and use its sign-in step. Devin
Desktop, formerly Windsurf, is one:

```sh
devin mcp add -s user commentware <url>
devin mcp login commentware
```

**Claude Desktop and claude.ai are the exception.** Their connectors reach a
server from Anthropic's cloud rather than from your machine, so they only work
with a server at a public HTTPS address.

## Connect an agent with no browser

Two different situations, with different answers.

**The browser is on another machine** — you are working over SSH, say:

1. Run your client's sign-in without a browser. Claude Code and Codex can:

```sh
   claude mcp login --no-browser commentware
   codex mcp login --no-browser commentware
```

2. Open the sign-in address it prints in the browser you have. That browser has
   to reach the server too — over an SSH forward if the server is on the remote
   machine.
3. Paste the address the browser ends up on back into the terminal.

**There is no browser at all, or the server has no sign-in.** The key travels
in a header instead, and on a server with no sign-in it crosses the network in
clear text, so use it only over a network you trust, or an SSH forward.

If the client is on the same machine as a server bound to `127.0.0.1`,
[Connect the clients on the server's machine](#connect-local-clients) writes
the header into the client's config for you.

1. Put the key in the environment, not on a command line and not in a config
   file:

```sh
   export COMMENTWARE_ACCESS_KEY=<the key that printed>
```

2. Point the client at it:
- **Claude Code** reads `${COMMENTWARE_ACCESS_KEY}` in an `mcpServers` block
     itself: `"headers": { "Authorization": "Bearer ${COMMENTWARE_ACCESS_KEY}" }`.
- **Codex** takes the variable's name:
     `codex mcp add commentware --url <url> --bearer-token-env-var COMMENTWARE_ACCESS_KEY`.
- **Any other client** takes an `Authorization: Bearer <key>` header in its
     own configuration. One that does not expand a variable needs the key
     written in its place.

> **Caution:** A configured header switches browser sign-in off. Claude Code
> does not fall back to sign-in for a server whose configuration carries an
> `Authorization` header, and a server already added with a header has to be
> removed and added again before sign-in works.

## Connect one agent to several servers

Add a second server to a client that already has a server, under a name of
its own, when one agent works on threads on more than one server.

A client keeps one entry per server, under a name, and shows the agent each
server's tools under that name. Every line [`mcp`](/docs/server/commands/#mcp)
prints and every entry [`mcp connect`](/docs/server/commands/#mcp-connect)
writes is named `commentware` unless you give it another name with `--entry`.
A name starts with a letter or a digit and goes on in letters, digits, `-` and
`_`, at most 35 characters, because Gemini CLI shortens a longer one in the
tool names its model sees. Codex shows its model `-` as `_`, so `my-work` and
`my_work` look the same to it.

### Add a server by its lines

1. On the second server's machine, print its lines under the name you choose.
   The example uses `work`:

```sh
   commentware mcp --entry work --client codex
```

   Every line names the entry `work`:

```text
   Codex
 codex mcp add work --url http://127.0.0.1:7044/api/mcp
 codex mcp login work
   (only if adding it did not open a browser)
```

2. Add the server and sign in with those lines, as under [Sign in through a
   browser](#browser-sign-in). Where a line on this page says `commentware`,
   such as Devin's or a `--no-browser` sign-in, put your name in its place.

> **Caution:** Under a name a client already has, Codex, Gemini CLI and VS Code
> replace that entry without asking, so the server it named is gone from the
> client. Claude Code refuses the name instead.

### Connect a client on the server's machine

1. Connect the client with the same flag, as under [Connect the clients on the
   server's machine](#connect-local-clients):

```sh
   commentware mcp connect cursor --entry work
```

   It writes the entry beside the first server's:

```text
   Connected Cursor to http://127.0.0.1:7044/api/mcp as user 3 (Cursor), holding "can_collaborate".
   Its key is in /home/alex/.cursor/mcp.json, under "work". "commentware mcp disconnect cursor" revokes it.
```

   Without `--entry`, it refuses rather than replace the first server's entry,
   and changes nothing:

```text
   Cursor's config already has a "commentware" server this one did not write, at http://127.0.0.1:7042/api/mcp.
   Nothing was changed. "--replace" replaces it with this server, and
   "--entry <name>" writes this server under another name beside it.
```

A later `mcp connect` keeps the name the entry has, and `mcp clients` and
`mcp disconnect` find the entry under whatever name it has.

Then ask the agent to choose a project on each server, with that server's
`set_active_project`. Each server keeps the agent's project for itself.

[`whoami`](/docs/server/tools/#whoami) answers `serverOrigin`, the address a
[comment link](/docs/concepts/comment-links/) names after `server=`, so the
agent opens a link on the server whose `whoami` matches. A server reached over
an SSH forward answers with its own address, which can be the same as a local
server's, so name the server when you ask the agent about one.

### Check each server's entry

1. On each server's machine, list the clients:

```sh
commentware mcp clients
```

   On the second server, the line shows the entry name you chose:

```text
   Cursor       "work": connected, as user 3
```

   For an entry added by its lines, the line reads
   `"work": signs in through a browser` instead.

2. Ask the agent to call `whoami` on the `commentware` server, then on the
   `work` server. The second answers:

```text
   {"id":"3","name":"Cursor","permissions":["can_collaborate"],"activeProject":null,"serverOrigin":"http://127.0.0.1:7044"}
```

## Open a document for comment

1. Ask your agent to open a plan, a design note or a review "in Commentware",
   or pick the **open_in_planner** prompt from your client's list of prompts
   and give it the file.
2. Open the link it hands you. The document opens with the comment overlay
   already open, beside an outline of its headings and a map of its whole
   length.
3. Comment on it the way you comment on any page.

The agent uploads the Markdown with its images, reads your comments back with
the same tools it reads any thread with, and can revise the document at the same
link. With **open_in_planner** it stays with the review: it answers each comment
in its thread, makes the changes you ask for in the file, and revises the
document to match, until you stop it.

Learn more about [the `open_in_planner` prompt](/docs/server/tools/#open_in_planner).

**A link to another file asks the agent for it.** The file is on the agent's
computer, so the link cannot open it. Pressing it opens a comment on the link
that is already written: it mentions the agent and asks it to open the file.
Press **Comment** to send it. The agent replies in that thread with a link to
the file, opened as a document of its own. Pressing the link again opens the
same thread.

**A document is a review, and a review ends.** Pressing **End review** on the
page, or asking the agent to end it, deletes the document and every comment on
it from your server at once, so it needs a key that may delete. An idle review
also ends on its own; learn more about [what the server deletes on its
own](/docs/concepts/retention/#the-retention-purge). The document is a copy of a
file your agent holds, so the file itself is never touched.

**This is experimental.** The planner may change or be removed in any release,
with no notice first, and every tool and prompt it adds says so.

Math between `$…$` and `$$…$$` is drawn, and so are tables, task lists and
footnotes. Raw HTML in the Markdown is left out.

## Check that it worked

Ask the agent to call `whoami`. It answers who the key is, what it may do,
which project it is in, and the server's own address.

## Next steps

- [What an agent can do](/docs/concepts/agents/): the tools, skills and prompts
  it gets, and what it cannot do.
- [MCP tools, prompts and resources](/docs/server/tools/): look up the
  arguments a tool or a prompt takes.
- [Export threads through an agent](/docs/using/export/#export-through-an-agent):
  have an agent export threads to a file.