Reference: ACP client tools (specification)
The protocol an ACP client follows to offer its own tools to mini-me. In ACP mode (
mm -acp), mm discovers the tools a client exposes as custom extension methods and the model calls them like its built-in tools. This page is the specification a client implements; the Go steps are in How to offer tools from your ACP client.
Scope
| Item | Value |
|---|---|
| Front end | ACP mode only (mm -acp). The terminal, the window (-tui) and -p have no client: no client tool exists there. |
| Configuration | acp.clientTools in the agent file. |
| Namespace | org.mini-me |
| ACP mechanism | Extensibility: methods whose name starts with _, capabilities in _meta. ACP defines no way to describe a method's parameters; this page defines mm's. |
| Who calls whom | mm (the agent) sends the requests; the client answers them. |
Identifiers
| Identifier | Kind | Where |
|---|---|---|
org.mini-me/tools |
_meta key |
clientCapabilities._meta of the initialize request. |
_org.mini-me/tools/list |
request method, agent → client | Discovery request only. |
org.mini-me/sessionId |
_meta key |
params._meta of every tool call. |
client_<name> |
tool name | The name the model sees for the tool <name>. |
Tool description
One JSON object per tool. The same object is used by both discovery modes.
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | yes | The tool's name, unique in the list. The model sees client_<name>, where every character outside [A-Za-z0-9] becomes _, runs of _ are collapsed, and leading/trailing _ are removed (open buffers → client_open_buffers). |
description |
string | no | What the model reads to decide when to call the tool. Absent: Tool provided by the editor (<method>). |
method |
string | yes | The extension method mm calls for this tool. Must start with _. Recommended form: _<reverse-dns>/<path>, for example _com.example/workspace/buffers. |
inputSchema |
object | no | JSON Schema of the arguments. When present, type must be "object" (or absent). Absent: the tool takes no parameter. |
Schema as the model sees it
The schema is passed to the model with these changes (the same as for MCP tools):
In inputSchema |
Declared to the model |
|---|---|
required |
Removed from the schema; the names are appended to the description as Required parameters: a, b. mm checks them before the call. |
enum |
Removed; the values are appended to the property's description as One of: x, y. |
additionalProperties: false, $schema |
Removed. |
type, properties |
Always present: type: "object", properties: {} when absent. |
Validation of a list
Each entry is validated on its own. An invalid entry is skipped and a line is written on mm's stderr ([acp] client tools: entry <i> skipped: <reason>); the other entries are kept, and the session never fails because of the list.
| Reason | Cause |
|---|---|
not a tool description: … |
The entry is not a JSON object of the shape above. |
no name |
name is absent or blank. |
method "…" must start with "_" (an ACP extension method) |
method is absent or not an extension method. |
inputSchema.type must be "object", got … |
The schema describes something other than an object. |
duplicate tool name "client_…" |
Two entries give the same model name; the first one is kept. |
The tools are sorted by model name.
Discovery
The mode is set by acp.clientTools.discovery in the agent file. The client must use the mode the agent file names.
Mode meta (default)
The client puts the list in its initialize request. The list applies to every session of the connection.
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{
"protocolVersion":1,
"clientInfo":{"name":"my-client","version":"1.0.0"},
"clientCapabilities":{
"_meta":{
"org.mini-me/tools":[
{"name":"open_buffers",
"description":"List the files open in the editor.",
"method":"_com.example/workspace/buffers",
"inputSchema":{"type":"object",
"properties":{"language":{"type":"string","description":"Only the buffers of this language."}},
"required":["language"]}}
]
}
}
}}
In mode meta, the value true instead of a list gives no tool and the stderr line "org.mini-me/tools" is not a list of tools; a client that answers _org.mini-me/tools/list needs acp.clientTools.discovery: request.
Mode request
The client only advertises the capability:
"clientCapabilities":{"_meta":{"org.mini-me/tools":true}}
mm then sends _org.mini-me/tools/list while it handles session/new, session/load and session/resume, before it answers them. The client must therefore answer this request while it waits for its own session/new response (the ACP SDKs handle each incoming request concurrently).
Request:
{"jsonrpc":"2.0","id":7,"method":"_org.mini-me/tools/list",
"params":{"sessionId":"20261110-224507-1f3a9c2e","cwd":"/home/me/project"}}
| Param | Type | Description |
|---|---|---|
sessionId |
string | The id of the session being opened; the session/new response that carries it has not been sent yet. |
cwd |
string | The session's working directory, as the client sent it. |
Response:
{"jsonrpc":"2.0","id":7,"result":{"tools":[
{"name":"open_buffers","method":"_com.example/workspace/buffers"}
]}}
| Outcome | Effect |
|---|---|
A tools array |
Those tools, validated as above, for this session only. |
An error, no answer within acp.clientTools.timeout, or no tools array |
No client tool for this session; one stderr line; the session opens normally. |
Each session asks again: two sessions of the same connection may have different tools.
Tool call
When the model calls client_<name>, mm sends a request to the tool's method.
Before the request
| Check | Result when it fails |
|---|---|
Every parameter of required is present in the model's arguments. |
No request is sent; the model reads [client tool error: missing required parameters: a, b]. |
Permission: with acp.clientTools.permissions: ask, or with auto when yolo is false, mm sends session/request_permission to the client first (see session/request_permission requests sent). The tool call's title is client: <name>, its kind other. |
The model reads [client_<name> rejected by user]. |
Request
{"jsonrpc":"2.0","id":12,"method":"_com.example/workspace/buffers",
"params":{"language":"go",
"_meta":{"org.mini-me/sessionId":"20261110-224507-1f3a9c2e"}}}
| Param | Description |
|---|---|
| the model's arguments | Copied as the model sent them, at the top level of params. |
_meta["org.mini-me/sessionId"] |
The session the call belongs to. A _meta the model may have put in its arguments is replaced. |
Response
Two shapes are accepted.
Content list (the shape of MCP's tools/call result):
{"jsonrpc":"2.0","id":12,"result":{
"content":[{"type":"text","text":"main.go\nutil.go"}],
"isError":false}}
| Field | Type | Effect |
|---|---|---|
content |
array | The text of every block of type text, joined with no separator, is what the model reads. A block of another type is replaced by [client tool: non-text content of type <type> skipped]. |
isError |
boolean, optional | true: the call is a failed call; the model reads [client tool error: <the text>]. |
Any other JSON value: a JSON string is given to the model unquoted; any other value (object, number, array without content) is given as its JSON text.
Errors
| Situation | What the model reads | Turn |
|---|---|---|
JSON-RPC error (for example -32601 Method not found) |
[client tool error: {"code":-32601,"message":"Method not found"}] |
Goes on. |
No answer within acp.clientTools.timeout |
[client tool error: …], with the SDK's error for the expired deadline. mm sends $/cancel_request for the request. |
Goes on. |
The turn is cancelled (session/cancel) |
mm sends $/cancel_request for the request. |
Ends as cancelled. |
isError: true |
[client tool error: <text>] |
Goes on. |
Every result, failed or not, is cut to maxOutput characters (head and tail kept), reported to the editor as the end of the tool call (session/update, tool_call_update), and counted by the loop detector like any tool call: the same call with the same answer repeated is flagged, then stops the turn.
Configuration
| Key | Default | Effect on this protocol |
|---|---|---|
acp.clientTools.enabled |
true |
false: org.mini-me/tools is ignored; no list request, no client tool. |
acp.clientTools.discovery |
meta |
meta or request, as described above. |
acp.clientTools.permissions |
auto |
auto: a call asks the client for permission only when yolo is false. ask: every call asks. |
acp.clientTools.timeout |
30s |
Bound of one tool call, and of the list request. |
Log lines (mm's stderr)
| Line | When |
|---|---|
[acp] client tools (meta): client_a, client_b |
After initialize, mode meta, when the client advertised a list. |
[acp] session <id> client tools (request): client_a |
After a list request answered. |
[acp] client tools: … |
A skipped entry, a failed list request, a bare true in mode meta. |
Implementations
demo.acp.sdk/go:minime.Options.ToolsandToolDiscoveryimplement the client side of this page in Go;examples/clienttoolsis a to-do list offered as two tools.
See also
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
|