# AkiMCP over HTTP · client spec

Guide v1 · AkiMCP 3.2+ · canonical: https://akimcp.top/guide/mcp-http/v1.md

This document specifies how an AI agent in a web chat talks to an AkiMCP server when the chat has no custom MCP connector but can send HTTPS requests (a shell with curl, a fetch tool, a Postman agent). The owner's own message in the chat says what to do; this page says how.

## 0. Kickoff block

The AkiMCP panel gives the owner one block to paste into the chat:

````text
I own this AkiMCP server. Connect to MCP_URL using TOKEN by following the protocol spec at GUIDE, then wait for my task. When I say the work is done, revoke the token as section 4 of the spec describes: send DELETE to MCP_URL with the same Bearer.
GUIDE:   https://akimcp.top/guide/mcp-http/v1.md
MCP_URL: https://<owner-host>/mcp
TOKEN:   <temporary token>
EXPIRES: <date and time>
````

| Field | Meaning |
|---|---|
| `GUIDE` | this page |
| `MCP_URL` | the owner's AkiMCP endpoint; behind it are file, shell, search, git and browser tools on the owner's computer |
| `TOKEN` | a temporary access token made for this one chat; it stops working when revoked (section 4 or the panel), after `EXPIRES`, or when the server restarts |
| `EXPIRES` | when the token stops working on its own (4 hours after it was made; the owner may extend it from the panel) |

Without `MCP_URL` and `TOKEN` there is nothing to connect with; the block comes from the AkiMCP panel.

## 1. Token handling

- The token grants access to the owner's computer, within the folders and commands the owner allowed. AkiMCP expects a client to keep it in a variable only: out of chat replies, files, commits, URLs and anything public.
- Tool calls follow the owner's requests in the chat. Reading is harmless; writes and commands follow an ask from the owner.
- Section 4 revokes the token when the work is done. The owner's other apps and tokens are not affected.

## 2. Handshake

Every request goes to `MCP_URL` and carries one JSON-RPC 2.0 object. AkiMCP answers with plain JSON.

| Header | Value |
|---|---|
| `Authorization` | `Bearer <TOKEN>` |
| `Content-Type` | `application/json` |
| `Accept` | `application/json, text/event-stream` |
| `MCP-Protocol-Version` | `2025-06-18` |
| `MCP-Session-Id` | the id returned by `initialize`; required on every request after it |

AkiMCP's CORS headers allow these request headers and `DELETE`, and expose `MCP-Session-Id`, so a client running inside a browser page can read the session id too.

1. **`POST initialize`.** The response header `MCP-Session-Id` carries the session id. Without it, every later request gets `404 Session not found`.
   ````json
   {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"web-chat-agent","version":"1.0.0"}}}
   ````
   The notification `{"jsonrpc":"2.0","method":"notifications/initialized"}` is optional here: AkiMCP answers it with `202` and needs nothing from it.
2. **`POST tools/list`.** Each tool arrives with its description and argument schema. Tool names start with the server's Tool prefix, `aki__` by default: take the exact names from this list. Argument names come from here: `aki__run_cmd`, for example, takes `command` (one command, no `&&`, pipes or redirection) and `cwd`.
   ````json
   {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
   ````
3. **`POST tools/call` the tool ending in `akidevrule_context` (`aki__akidevrule_context` by default).** Loads the owner's working rules and returns a line `receipt=sha256:<64 hex>`. Every tool that changes something (write, edit, move, run a command) refuses without that value in its `receipt` argument. The rest of that output is the owner's rule set for coding agents working in the owner's repositories; a chat client needs only the `sha256:` receipt from it.
   ````json
   {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"aki__akidevrule_context","arguments":{}}}
   ````

Every later call has the same shape:

````json
{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"aki__run_cmd","arguments":{"command":"git status","cwd":"/path/to/project","receipt":"sha256:<64 hex>"}}}
````

### 2a. curl

````bash
export MCP_URL='<MCP_URL>' TOKEN='<TOKEN>'
H=(-H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' -H 'MCP-Protocol-Version: 2025-06-18')
SID=$(curl -sS -D - -o /dev/null "${H[@]}" "$MCP_URL" -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"web-chat-agent","version":"1.0.0"}}}' | tr -d '\r' | awk -F': ' 'tolower($1)=="mcp-session-id"{print $2}')
call() { curl -sS "${H[@]}" -H "MCP-Session-Id: $SID" "$MCP_URL" -d "$1"; }
call '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
RECEIPT=$(call '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"aki__akidevrule_context","arguments":{}}}' | grep -o 'sha256:[0-9a-f]\{64\}' | head -1)
````

### 2b. Postman or another request builder

Collection variables `mcp_url`, `token` (secret) and `session_id`; one request per step above, with the header table and the JSON bodies. A post-response script on `initialize` stores the session id:

````javascript
const sid = pm.response.headers.get("MCP-Session-Id");
if (sid) pm.collectionVariables.set("session_id", sid);
````

## 3. Errors

| Response | Meaning | Next step |
|---|---|---|
| `401 Unauthorized` | token wrong, expired or revoked | after section 4: nothing, the work is done; otherwise a new kickoff block from the owner |
| `404` · `Session not found` | `MCP-Session-Id` missing or stale | `initialize` again, then retry |
| `-32602` with an argument hint | wrong argument name | the names the hint lists |
| tool refuses: receipt missing or unknown | no receipt, or the owner's rules changed | the `...akidevrule_context` tool again, the new receipt |
| connection error, no HTTP status | the owner's server or tunnel is down | tell the owner; no retry loop |

## 4. Revoke the token

When the owner says the work is done, one request ends the session and revokes the token together:

````bash
curl -sS -X DELETE "$MCP_URL" -H "Authorization: Bearer $TOKEN" -H "MCP-Session-Id: $SID"
````

The answer is `2xx`. From then on every request with that token gets `401`; a `401` on a repeated `DELETE` means the token was already revoked. `MCP-Session-Id` is optional here: without it the token is still revoked. The owner's other connected apps and tokens keep working. The chat reports "token revoked" and stops calling `MCP_URL`.

A client that can send only `POST` cannot revoke the token itself: it tells the owner, who clicks **Revoke** beside it in the AkiMCP panel.
