| 1 |
root |
1.2 |
NAME |
| 2 |
|
|
AnyEvent::MCP::Intro - using MCP servers, clients and permissions |
| 3 |
|
|
|
| 4 |
|
|
DESCRIPTION |
| 5 |
|
|
You can use the servers in this distribution without writing any Perl. |
| 6 |
|
|
This walkthrough starts with one filesystem server, connects it to an |
| 7 |
|
|
MCP client, and makes a useful request. Once that works, it explains |
| 8 |
|
|
persistent configuration, permissions and combining several servers. |
| 9 |
|
|
|
| 10 |
|
|
If you want to write a small server yourself, continue with "TUTORIAL" |
| 11 |
|
|
in AnyEvent::MCP::Server::Simple. Applications needing their own |
| 12 |
|
|
connection management or dispatch can use the modules described in |
| 13 |
|
|
"MODULES" in AnyEvent::MCP. |
| 14 |
|
|
|
| 15 |
|
|
The examples use "/home/alice/src/project" as an existing project |
| 16 |
|
|
directory. Replace it with your own absolute path. Commands shown here |
| 17 |
|
|
are commands for you to run; requests addressed to the LLM are shown |
| 18 |
|
|
separately. |
| 19 |
|
|
|
| 20 |
|
|
INSTALLATION |
| 21 |
|
|
Install the Perl distribution and the external programs used by the |
| 22 |
|
|
servers. Installing one does not install the other. |
| 23 |
|
|
|
| 24 |
|
|
For mcp-fs, install Linux bubblewrap and the filesystem utilities. On |
| 25 |
|
|
Debian or Ubuntu, for example: |
| 26 |
|
|
|
| 27 |
|
|
sudo apt install bubblewrap findutils grep patch sed perl yad |
| 28 |
|
|
|
| 29 |
|
|
"yad" is optional: it supplies graphical permission dialogs. Without a |
| 30 |
|
|
usable YAD dialog, the helper tries "/dev/tty"; if neither is available, |
| 31 |
|
|
it denies the request. Bubblewrap's executable is "bwrap". The machine |
| 32 |
|
|
must allow the unprivileged user namespaces it needs. |
| 33 |
|
|
|
| 34 |
|
|
mcp-fs detects its utilities at startup and omits tools whose utilities |
| 35 |
|
|
are unavailable or unsuitable. It requires bubblewrap by default. See |
| 36 |
|
|
"TRUSTED CONFIGURATION" in mcp-fs for explicit utility paths and |
| 37 |
|
|
"LIMITATIONS" in mcp-fs for the sandbox's limits. |
| 38 |
|
|
|
| 39 |
|
|
If you have an unpacked distribution or source checkout, run these |
| 40 |
|
|
commands in its top-level directory: |
| 41 |
|
|
|
| 42 |
|
|
perl Makefile.PL |
| 43 |
|
|
make |
| 44 |
|
|
make test |
| 45 |
|
|
make install |
| 46 |
|
|
|
| 47 |
|
|
"perl Makefile.PL" reports missing Perl dependencies. Install those with |
| 48 |
|
|
your usual package manager or CPAN client before continuing. For |
| 49 |
|
|
example, the main non-core dependencies can be installed with: |
| 50 |
|
|
|
| 51 |
root |
1.8 |
cpan AnyEvent AnyEvent::HTTP common::sense JSON::XS |
| 52 |
|
|
|
| 53 |
|
|
"mcp-webbrowser" requires "AnyEvent::WebSocket::Server" and |
| 54 |
|
|
"AnyEvent::WebSocket::Message". "mcp-vim" needs them only for browser |
| 55 |
|
|
connections, not for ordinary Vim clients. Both modules are recommended |
| 56 |
|
|
rather than required by the distribution. |
| 57 |
root |
1.2 |
|
| 58 |
root |
1.10 |
"mcp-imap" needs "Mail::IMAPTalk", "IO::Socket::SSL", |
| 59 |
|
|
"AnyEvent::Fork::RPC" and "Term::ReadKey". OAuth2 login additionally |
| 60 |
|
|
needs "Authen::SASL"; provider autoconfiguration uses "XML::LibXML". |
| 61 |
|
|
Install these optional modules with your Perl's package manager or CPAN |
| 62 |
|
|
client before using that server. "mcp-http" needs no additional modules |
| 63 |
|
|
beyond the distribution's required dependencies. |
| 64 |
|
|
|
| 65 |
root |
1.2 |
Use the same Perl installation for dependency installation, building and |
| 66 |
|
|
running the servers. A module installed for the system Perl might not be |
| 67 |
|
|
available to a Perl installed under "/opt". "make install" needs write |
| 68 |
|
|
access to the selected Perl's installation directories; use an |
| 69 |
|
|
appropriate local Perl installation or run that final step with the |
| 70 |
|
|
required privileges. |
| 71 |
|
|
|
| 72 |
|
|
Installation puts "mcp-fs", "mcp-multibroker", "mcp-vim", |
| 73 |
root |
1.10 |
"mcp-webbrowser", "mcp-imap", "mcp-http", "mcp-ask-user", |
| 74 |
|
|
"anyevent-mcp", "anyevent-mcp-askpermission" and |
| 75 |
|
|
"anyevent-mcp-form-elicitation" in the selected executable directory. |
| 76 |
|
|
Make that directory available in the environment of your MCP client, or |
| 77 |
root |
1.2 |
configure absolute executable paths. A desktop application need not have |
| 78 |
|
|
the same "PATH" as your shell. |
| 79 |
|
|
|
| 80 |
|
|
To try an uninstalled source tree after installing its dependencies, you |
| 81 |
|
|
can run a program with the source library path: |
| 82 |
|
|
|
| 83 |
|
|
perl -Ilib bin/mcp-fs --stdio --name code /home/alice/src/project |
| 84 |
|
|
|
| 85 |
|
|
Do this from the distribution directory. When configuring a client to |
| 86 |
|
|
start such a command, account for the client's working directory or use |
| 87 |
|
|
absolute paths to Perl, "lib" and the script. An installed executable |
| 88 |
|
|
avoids that extra setup. |
| 89 |
|
|
|
| 90 |
root |
1.3 |
PICK A SERVER |
| 91 |
|
|
For a local MCP client, configure it to launch the server that provides |
| 92 |
|
|
the tools you want: |
| 93 |
root |
1.2 |
|
| 94 |
root |
1.3 |
mcp-fs --stdio /home/alice/src/project |
| 95 |
|
|
mcp-vim --stdio |
| 96 |
root |
1.2 |
mcp-webbrowser --stdio |
| 97 |
root |
1.3 |
mcp-ask-user --stdio |
| 98 |
root |
1.10 |
mcp-http --stdio |
| 99 |
|
|
mcp-imap --stdio --name personal |
| 100 |
root |
1.3 |
|
| 101 |
|
|
"--stdio" means the MCP client launches the process. Do not start a |
| 102 |
|
|
separate copy in a terminal. For HTTP clients, use a running server and |
| 103 |
|
|
its "--print-url" instead, as explained below. |
| 104 |
|
|
|
| 105 |
|
|
"mcp-fs" reads, searches and changes files and runs commands in a |
| 106 |
|
|
sandbox. The first walkthrough below uses this server. |
| 107 |
|
|
|
| 108 |
|
|
"mcp-vim" reads and edits live Vim buffers. Install the companion Vim |
| 109 |
|
|
plugin and connect the editor to its listener; see "Add a live Vim |
| 110 |
|
|
editor" and "VIM PLUGIN INSTALLATION" in mcp-vim. |
| 111 |
|
|
|
| 112 |
|
|
"mcp-webbrowser" works with explicitly approved browser tabs. Install |
| 113 |
|
|
its companion userscript and connect each tab you want to expose; see |
| 114 |
|
|
"CONNECTED BROWSER PAGES". |
| 115 |
root |
1.2 |
|
| 116 |
root |
1.3 |
"mcp-ask-user" lets the assistant ask you questions through a local YAD |
| 117 |
|
|
or terminal dialog, or through the client's native form UI; see "Ask the |
| 118 |
|
|
client's human a question". |
| 119 |
root |
1.2 |
|
| 120 |
root |
1.10 |
"mcp-http" makes HTTP(S) requests with method- and URL-scoped |
| 121 |
|
|
permissions. It does not follow redirects automatically; see "Use an |
| 122 |
|
|
HTTP request tool". |
| 123 |
|
|
|
| 124 |
|
|
"mcp-imap" reads, searches and manages mailboxes. Configure the account |
| 125 |
|
|
interactively before starting the server; see "Read and organize mail" |
| 126 |
|
|
and mcp-imap for OAuth2 and account management. |
| 127 |
|
|
|
| 128 |
root |
1.4 |
To offer several servers over one MCP connection, use "mcp-multibroker". |
| 129 |
|
|
It combines these servers with each other or with third-party MCP |
| 130 |
|
|
servers, whether started locally over stdio or reached over HTTP. Their |
| 131 |
|
|
tools appear under separate name prefixes; see "COMBINING SERVERS" and |
| 132 |
|
|
mcp-multibroker for the full command syntax. |
| 133 |
root |
1.2 |
|
| 134 |
|
|
YOUR FIRST FILESYSTEM SERVER |
| 135 |
|
|
Start with one project and one connection. You do not need a |
| 136 |
|
|
multibroker, a hand-written configuration file or saved permission rules |
| 137 |
|
|
yet. |
| 138 |
|
|
|
| 139 |
|
|
Choose stdio or HTTP |
| 140 |
|
|
Use stdio when your MCP client runs on the same machine and can launch a |
| 141 |
|
|
server process. Configure the client to start the following command: |
| 142 |
|
|
|
| 143 |
|
|
mcp-fs --stdio --name code /home/alice/src/project |
| 144 |
|
|
|
| 145 |
|
|
The client starts this process and uses its stdin/stdout for MCP. You do |
| 146 |
|
|
not start a second copy in a terminal, and there is no listener URL or |
| 147 |
|
|
HTTP token to configure. Diagnostics go to stderr. |
| 148 |
|
|
|
| 149 |
|
|
Clients that take a command and an argument array need these values: |
| 150 |
|
|
|
| 151 |
|
|
command: mcp-fs |
| 152 |
|
|
arguments: --stdio, --name, code, /home/alice/src/project |
| 153 |
|
|
|
| 154 |
|
|
These describe separate arguments, not one shell command string. Use an |
| 155 |
|
|
absolute executable path if the client cannot find "mcp-fs". See "CLIENT |
| 156 |
|
|
EXAMPLES" for examples of particular clients. |
| 157 |
|
|
|
| 158 |
|
|
Use HTTP when the client connects to an already-running server, or when |
| 159 |
|
|
it cannot launch a local process. Start this in a terminal on the server |
| 160 |
|
|
machine and leave it running: |
| 161 |
|
|
|
| 162 |
|
|
mcp-fs --name code --bind :31741 /home/alice/src/project |
| 163 |
|
|
|
| 164 |
|
|
In another terminal, obtain the matching connection URL: |
| 165 |
|
|
|
| 166 |
|
|
mcp-fs --name code --bind :31741 --print-url |
| 167 |
|
|
|
| 168 |
|
|
The second command prints a credential-bearing URL and exits without |
| 169 |
|
|
opening a listener. Configure that URL in the client. The default |
| 170 |
|
|
address is IPv4 loopback, so this example is reachable from the same |
| 171 |
|
|
machine only. A hosted client needs a suitable tunnel or reachable |
| 172 |
|
|
endpoint; its own "localhost" is not your computer. |
| 173 |
|
|
|
| 174 |
|
|
Repeat the same name and listener overrides when printing the URL. Both |
| 175 |
|
|
commands must use the same user and configuration directory. Port zero |
| 176 |
|
|
chooses an ephemeral port, which "--print-url" cannot predict; use an |
| 177 |
|
|
explicit port for this walkthrough. |
| 178 |
|
|
|
| 179 |
|
|
The HTTP server generates and saves its private master secret when |
| 180 |
|
|
needed. You can initialize it explicitly with "anyevent-mcp init", but |
| 181 |
|
|
that command is unnecessary when configuration already exists and will |
| 182 |
|
|
refuse to replace it. Keep the printed URL private: possession of its |
| 183 |
|
|
token authenticates a client. |
| 184 |
|
|
|
| 185 |
|
|
Make a useful request |
| 186 |
|
|
Once your client reports that the server is connected, ask the LLM: |
| 187 |
|
|
|
| 188 |
|
|
Show me the configured workdirs. List the top-level files in the |
| 189 |
root |
1.3 |
project, then read its README if it has one. Do not modify files |
| 190 |
|
|
or run commands. |
| 191 |
root |
1.2 |
|
| 192 |
|
|
"workdirs" returns the configured paths, sandbox grants, trusted mounts |
| 193 |
|
|
and runtime paths. Listing names requests "inspect" permission; reading |
| 194 |
|
|
contents requests "read" permission. Expect a permission prompt when |
| 195 |
|
|
there is no saved rule allowing the operation. |
| 196 |
|
|
|
| 197 |
|
|
Choose "Allow once" for the first operation. The worker then runs with |
| 198 |
|
|
the requested sandbox grants. A denial is a tool failure that the LLM |
| 199 |
|
|
should report, rather than an empty file or a disconnected server. |
| 200 |
|
|
|
| 201 |
|
|
For a slightly larger task, ask: |
| 202 |
|
|
|
| 203 |
|
|
Find TODO comments in this project and explain the three that look |
| 204 |
|
|
most useful to address next. Do not modify files or run commands. |
| 205 |
|
|
|
| 206 |
|
|
This can use "find", "grep" and "read-lines". You need not write MCP |
| 207 |
|
|
requests yourself. If a client offers its own tool-approval prompt, that |
| 208 |
|
|
is an additional client policy; it does not replace mcp-fs's |
| 209 |
|
|
permissions. |
| 210 |
|
|
|
| 211 |
root |
1.3 |
Give the server a purpose |
| 212 |
|
|
To explain why an instance exists, provide a short purpose: |
| 213 |
|
|
|
| 214 |
|
|
mcp-fs --stdio --name memory \ |
| 215 |
|
|
--custom-instructions 'Use this server to retrieve and store persistent memory.' \ |
| 216 |
|
|
/home/alice/memory |
| 217 |
|
|
|
| 218 |
|
|
For persistent configuration, use "custom_instructions" in the global |
| 219 |
|
|
configuration's "[program mcp-fs]" or "[instance memory]" section. |
| 220 |
|
|
Instance settings override program settings; the command line overrides |
| 221 |
|
|
both. This purpose appears first in the advertised MCP instructions so a |
| 222 |
|
|
model can decide whether to discover the server's tools. |
| 223 |
|
|
|
| 224 |
|
|
Servers using "AnyEvent::MCP::Server::Simple" also expose the instance |
| 225 |
|
|
purpose and complete operating instructions as a "meta-instructions" |
| 226 |
|
|
tool description. Calling that tool returns the complete text when a |
| 227 |
|
|
client truncates descriptions. Clients that understand MCP server |
| 228 |
|
|
instructions still receive a short purpose or routing hint at discovery |
| 229 |
|
|
time, followed by an automatic pointer to the full instructions in the |
| 230 |
|
|
tool description. |
| 231 |
|
|
|
| 232 |
root |
1.2 |
Understand the workdir |
| 233 |
|
|
The directory passed at startup tells mcp-fs which workdir to expose. It |
| 234 |
|
|
does not grant permission for every operation in that directory. Each |
| 235 |
|
|
operation still requests its action and sandbox grants. |
| 236 |
|
|
|
| 237 |
|
|
With one workdir, tools can omit the "workdir" argument. With several: |
| 238 |
|
|
|
| 239 |
|
|
mcp-fs --stdio --name code /home/alice/src/project /home/alice/notes |
| 240 |
|
|
|
| 241 |
|
|
tools select one using a persistent positive integer ID, a numeric |
| 242 |
|
|
string or an exact configured/resolved path returned by "workdirs". The |
| 243 |
|
|
"workdirs" and "resolved_workdirs" objects use these IDs as keys. |
| 244 |
|
|
Relative tool paths are relative to that selection. Permission rules |
| 245 |
|
|
continue to use the configured path, not its numeric ID. |
| 246 |
|
|
|
| 247 |
|
|
IDs are shared across filesystem servers in |
| 248 |
|
|
"$XDG_CONFIG_HOME/anyevent-mcp/fs-workdir-ids.json", or under |
| 249 |
|
|
"$HOME/.config" by default. They identify resolved absolute paths and |
| 250 |
|
|
survive restarts and argument reordering. Startup resolves IDs once and |
| 251 |
|
|
reserves new allocations under the lock. A timer runs immediately and |
| 252 |
|
|
every 5.25 days to reread the registry and refresh the server's fixed |
| 253 |
|
|
assignments. Other entries expire after seven days and their IDs may be |
| 254 |
|
|
reused. Restart servers after manually changing the registry. |
| 255 |
|
|
|
| 256 |
|
|
"workdir-read" exposes the selected workdir read-only. "workdir-write" |
| 257 |
|
|
makes it writable and implies read access. A path in another configured |
| 258 |
|
|
workdir requires all-workdirs authority; a path elsewhere requires |
| 259 |
|
|
suitable home/world or shared-tmp authority. A symlink cannot make an |
| 260 |
|
|
unmounted target appear inside the sandbox. |
| 261 |
|
|
|
| 262 |
|
|
Prefer separate, non-overlapping workdirs. Overlapping mounts have |
| 263 |
|
|
unspecified access effects. See "SANDBOX GRANTS" in mcp-fs before |
| 264 |
|
|
granting access beyond the selected workdir. |
| 265 |
|
|
|
| 266 |
|
|
Inspect version-control changes |
| 267 |
|
|
For a Git, SVN, CVS or Mercurial working copy, ask the LLM to use |
| 268 |
|
|
"vcs-diff" and "vcs-status", with "backend" set to "git", "svn", "cvs" |
| 269 |
|
|
or "hg". "workdirs" reports the available clients. These tools accept |
| 270 |
|
|
filenames and construct the command themselves; no shell pipeline or |
| 271 |
|
|
arbitrary VCS options need to be approved. |
| 272 |
|
|
|
| 273 |
|
|
For example: |
| 274 |
|
|
|
| 275 |
|
|
Show the CVS diff for this project, limited to 200 lines. |
| 276 |
|
|
Then show its status, keeping stdout lines matching "File:|Status:". |
| 277 |
|
|
|
| 278 |
|
|
These operations have their own permission actions. They request read |
| 279 |
root |
1.3 |
access to the selected workdir. CVS additionally requests the |
| 280 |
|
|
"ssh-agent" grant, which includes network access, the agent socket and |
| 281 |
|
|
"known_hosts", but not general home-directory access. Read permission |
| 282 |
|
|
for ordinary file tools does not automatically authorize a VCS |
| 283 |
|
|
operation. |
| 284 |
root |
1.2 |
|
| 285 |
|
|
For arbitrary "exec" commands, the same output options are available: |
| 286 |
|
|
"grep" filters stdout using PCRE, "max_lines" limits matching stdout |
| 287 |
|
|
lines, and "max_bytes" bounds returned bytes per stream. Prefer these |
| 288 |
|
|
options to a shell wrapper that mixes execution and output processing. |
| 289 |
|
|
Stderr is unfiltered, and exit status still describes the original |
| 290 |
|
|
command. |
| 291 |
|
|
|
| 292 |
|
|
Defaults return at most 2000 stdout lines and 64 KiB per stream. Raw |
| 293 |
|
|
capture has a separate 1 MiB limit per stream. A true |
| 294 |
|
|
"capture_truncated" means output was omitted before filtering or |
| 295 |
|
|
collection ended on timeout, so absent matches do not prove the omitted |
| 296 |
|
|
output had none. See "Command output" in mcp-fs for all result flags and |
| 297 |
|
|
limits. |
| 298 |
|
|
|
| 299 |
|
|
CONFIGURING YOUR SETUP |
| 300 |
|
|
There are three different things to configure: how the client connects, |
| 301 |
|
|
how the server runs, and which operations the user allows. Changing one |
| 302 |
|
|
does not necessarily change the other two. |
| 303 |
|
|
|
| 304 |
|
|
Where each setting belongs |
| 305 |
|
|
Directories to expose |
| 306 |
|
|
Pass workdirs on the mcp-fs startup command. For a stdio server, |
| 307 |
|
|
that command belongs in the client's server configuration. For an |
| 308 |
|
|
HTTP server, it belongs in the command used to run the service. |
| 309 |
|
|
|
| 310 |
|
|
Connection transport |
| 311 |
|
|
The client launches a command for stdio or connects to a URL for |
| 312 |
|
|
HTTP. "--stdio" selects the former for mcp-fs and the multibroker. |
| 313 |
|
|
|
| 314 |
|
|
Listener address, port and tokens |
| 315 |
|
|
Use "[instance NAME]" in the global configuration or command-line |
| 316 |
|
|
"--bind" and "--token" overrides. |
| 317 |
|
|
|
| 318 |
|
|
Trusted mounts and utility paths |
| 319 |
|
|
For mcp-fs, use "[program NAME]" defaults and "[instance NAME]" |
| 320 |
|
|
overrides in the global configuration. |
| 321 |
|
|
|
| 322 |
|
|
Allowed operations and sandbox grants |
| 323 |
|
|
Use the permission rules file, normally created through approval |
| 324 |
|
|
dialogs. This file is separate from the global configuration. |
| 325 |
|
|
|
| 326 |
|
|
Location of permission prompts |
| 327 |
|
|
Use "--ask helper", "--ask tty", "--ask yad", "--ask auto" or "--ask |
| 328 |
|
|
mcp", or set "PERL_ANYEVENT_MCP_PERMISSION_ASK" in the server's |
| 329 |
|
|
environment. |
| 330 |
|
|
|
| 331 |
|
|
Combined server connections |
| 332 |
|
|
Put prefix/server pairs on the multibroker startup command. HTTP |
| 333 |
|
|
child credentials can also use "[client PREFIX]" in the global |
| 334 |
|
|
configuration. |
| 335 |
|
|
|
| 336 |
|
|
One complete named configuration |
| 337 |
|
|
The global file is "$XDG_CONFIG_HOME/anyevent-mcp/global.ini", falling |
| 338 |
|
|
back to "$HOME/.config/anyevent-mcp/global.ini". Settings are UTF-8 "key |
| 339 |
|
|
= value" lines; values are unquoted. Whole-line "#" and ";" comments are |
| 340 |
|
|
allowed. See "GLOBAL CONFIGURATION" in AnyEvent::MCP for the complete |
| 341 |
|
|
format. |
| 342 |
|
|
|
| 343 |
|
|
Start with the existing file, preserving its "[global]" secret. If you |
| 344 |
root |
1.3 |
have no file yet, "anyevent-mcp init" creates it privately. Add this |
| 345 |
|
|
section: |
| 346 |
root |
1.2 |
|
| 347 |
|
|
[instance code] |
| 348 |
|
|
bind = 127.0.0.1:31741 |
| 349 |
|
|
|
| 350 |
|
|
Now start: |
| 351 |
|
|
|
| 352 |
|
|
mcp-fs --name code /home/alice/src/project |
| 353 |
|
|
|
| 354 |
|
|
and retrieve its URL with: |
| 355 |
|
|
|
| 356 |
|
|
mcp-fs --name code --print-url |
| 357 |
|
|
|
| 358 |
|
|
Both use "[instance code]". No explicit token is needed: the server |
| 359 |
|
|
derives one from its name and the existing master secret. |
| 360 |
|
|
|
| 361 |
|
|
For this setup: |
| 362 |
|
|
|
| 363 |
|
|
instance settings: [instance code] |
| 364 |
|
|
selected workdir: /home/alice/src/project |
| 365 |
|
|
permission file: ~/.config/anyevent-mcp/rules/fs-code.ini |
| 366 |
|
|
rule-manager profile: fs-code |
| 367 |
|
|
|
| 368 |
|
|
The permission pathname above assumes the default configuration |
| 369 |
|
|
directory. "anyevent-mcp manage-rules fs-code" opens the graphical rule |
| 370 |
|
|
manager; "anyevent-mcp edit-rules fs-code" opens the file in your |
| 371 |
|
|
editor. |
| 372 |
|
|
|
| 373 |
root |
1.3 |
Settings shared by all mcp-fs instances go in "[program mcp-fs]". |
| 374 |
|
|
Instance settings override program settings. |
| 375 |
|
|
|
| 376 |
root |
1.6 |
File ownership and permissions are under the user's control. The global |
| 377 |
|
|
configuration contains a master authentication secret, so take care when |
| 378 |
|
|
sharing it. "--config FILE" on "anyevent-mcp init" selects that |
| 379 |
|
|
command's output file; it does not make the servers use an arbitrary |
| 380 |
|
|
alternate file. Use the same "HOME"/"XDG_CONFIG_HOME" environment when |
| 381 |
|
|
running the server and its management commands. |
| 382 |
root |
1.2 |
|
| 383 |
|
|
Names, prefixes and profiles |
| 384 |
|
|
"--name code" selects instance settings, derived HTTP credentials and |
| 385 |
|
|
mcp-fs's "rules/fs-code.ini". Without "--name", mcp-fs uses "default", |
| 386 |
|
|
giving profile "fs-default". Two processes with the same program, name |
| 387 |
|
|
and configuration share credentials and rules, even if their workdirs |
| 388 |
|
|
differ. |
| 389 |
|
|
|
| 390 |
|
|
A multibroker prefix, such as "files", only routes tools: "grep" becomes |
| 391 |
|
|
"files.grep". It does not rename the child server or select its rules. |
| 392 |
|
|
For example: |
| 393 |
|
|
|
| 394 |
|
|
mcp-multibroker files \ |
| 395 |
|
|
'stdio:mcp-fs --name code /home/alice/src/project' |
| 396 |
|
|
|
| 397 |
|
|
The tools are "files.*", but the child still uses instance "code" and |
| 398 |
|
|
rule-manager profile "fs-code". The multibroker's own "--name" selects |
| 399 |
|
|
its upstream listener settings. |
| 400 |
|
|
|
| 401 |
|
|
Configuration changes and restarts |
| 402 |
|
|
Command-line listener options override the named global settings. For |
| 403 |
|
|
mcp-fs trusted settings, an instance entry overrides the corresponding |
| 404 |
|
|
program entry; an empty instance mount value suppresses the inherited |
| 405 |
|
|
mount. |
| 406 |
|
|
|
| 407 |
|
|
Workdirs, mounts, utility paths, listener settings and tokens are read |
| 408 |
|
|
at startup. Change the file or startup command, then restart the |
| 409 |
|
|
affected server. The multibroker also needs restarting to change its |
| 410 |
|
|
prefix/server pairs; refreshing discovery does not change those pairs. |
| 411 |
|
|
|
| 412 |
|
|
Permission rules are reread on permission checks, so editing them does |
| 413 |
|
|
not require a restart. A client's displayed tool list can still be |
| 414 |
|
|
cached. After restarting a child, refresh tool discovery or reconnect |
| 415 |
|
|
the client as described in "COMBINING SERVERS". |
| 416 |
|
|
|
| 417 |
|
|
PERMISSIONS IN PRACTICE |
| 418 |
|
|
HTTP authentication establishes that the client may connect. Permission |
| 419 |
|
|
checks decide whether a tool may perform an operation. A correct token |
| 420 |
|
|
therefore does not prevent permission prompts. |
| 421 |
|
|
|
| 422 |
|
|
What the prompt means |
| 423 |
|
|
The prompt describes an action, paths or command, a reason and sandbox |
| 424 |
|
|
grants. For filesystem tools, the actions are: |
| 425 |
|
|
|
| 426 |
|
|
inspect stat, list, find |
| 427 |
|
|
read file-read, read-lines, grep |
| 428 |
|
|
write file-write, file-patch |
| 429 |
|
|
manage path-op |
| 430 |
|
|
exec arbitrary command execution |
| 431 |
|
|
vcs-diff working-copy differences |
| 432 |
|
|
vcs-status working-copy status |
| 433 |
|
|
|
| 434 |
|
|
The action and grants are independent. Allowing "read" does not allow |
| 435 |
|
|
"write", even if a worker grant permits both kinds of filesystem access. |
| 436 |
|
|
"exec" runs arbitrary commands; it is not a classification of supposedly |
| 437 |
|
|
safe command prefixes. |
| 438 |
|
|
|
| 439 |
|
|
Choose allow/deny once, or always. Closing the dialog denies once. An |
| 440 |
|
|
optional denial reason is returned with the error; it is not added to |
| 441 |
|
|
successful tool results. An always choice opens a rule editor. Choose an |
| 442 |
|
|
indefinite lifetime (the default), 900 seconds or 16 hours. Finite |
| 443 |
|
|
lifetimes are stored as "expires" Unix timestamps. Expired rules |
| 444 |
|
|
disappear on every read; the next ordinary save removes them from disk. |
| 445 |
|
|
Expiry affects future permission checks, not operations already |
| 446 |
|
|
authorized. Filesystem allow rules can select grants and the selected |
| 447 |
|
|
workdir when the authority depends on it. Deny rules can also select an |
| 448 |
|
|
exact affected path. Exec offers persistent command/argv subjects. |
| 449 |
|
|
|
| 450 |
|
|
For exec, "View stdin..." lets you inspect supplied input without |
| 451 |
|
|
closing the approval dialog. Filesystem and Vim patch tools similarly |
| 452 |
|
|
offer "View patch...", including the target file or editor and buffer. |
| 453 |
|
|
Longer text is shown as an explicitly incomplete preview. These are YAD |
| 454 |
|
|
button labels; other interfaces can show the details inline. That input |
| 455 |
|
|
is display-only: an exec allow rule does not constrain future stdin. |
| 456 |
|
|
Allowing an interpreter command can therefore allow a different script |
| 457 |
|
|
on its next invocation. |
| 458 |
|
|
|
| 459 |
|
|
A worker accessing several paths requests their combined sandbox |
| 460 |
|
|
authority once. If the chosen grants are insufficient, it fails before |
| 461 |
|
|
starting. |
| 462 |
|
|
|
| 463 |
|
|
Save a useful read-only policy |
| 464 |
|
|
After trying individual operations, you might want the LLM to inspect |
| 465 |
|
|
and read the project without asking each time, while keeping changes |
| 466 |
|
|
subject to approval. Put these rules in "rules/fs-code.ini", or create |
| 467 |
|
|
equivalent allow rules through the prompt: |
| 468 |
|
|
|
| 469 |
|
|
[rule] |
| 470 |
|
|
decision=allow |
| 471 |
|
|
action=inspect |
| 472 |
root |
1.8 |
match.workdir=/home/alice/src/project |
| 473 |
root |
1.2 |
sandbox-grants=workdir-read |
| 474 |
|
|
|
| 475 |
|
|
[rule] |
| 476 |
|
|
decision=allow |
| 477 |
|
|
action=read |
| 478 |
root |
1.8 |
match.workdir=/home/alice/src/project |
| 479 |
root |
1.2 |
sandbox-grants=workdir-read |
| 480 |
|
|
|
| 481 |
|
|
[rule] |
| 482 |
|
|
decision=deny |
| 483 |
|
|
action=exec |
| 484 |
|
|
|
| 485 |
|
|
Use the exact workdir spelling passed at server startup. Absolute |
| 486 |
root |
1.6 |
startup paths make this easier. Rule-file permissions follow the usual |
| 487 |
|
|
Unix filesystem rules; any user who can edit the file can change the |
| 488 |
|
|
server's approval policy. |
| 489 |
|
|
|
| 490 |
|
|
Without matching rules, write and manage operations still ask. The final |
| 491 |
|
|
rule denies command execution outright; omit it if you want execution to |
| 492 |
|
|
ask instead. |
| 493 |
root |
1.2 |
|
| 494 |
|
|
Rules run in order, stopping at the first match. An allow rule matches |
| 495 |
|
|
only when its grants cover the request, including implications. |
| 496 |
|
|
"workdir-write" implies "workdir-read"; "network" remains independent. |
| 497 |
root |
1.8 |
Action and "match.NAME" match exactly unless beginning with "^", which |
| 498 |
|
|
selects a Perl regular expression; workdir scopes use the same |
| 499 |
|
|
mechanism. An explicit "ask" rule can override later allow rules. |
| 500 |
root |
1.2 |
|
| 501 |
|
|
These allow rules authorize sandbox access to the selected workdir. They |
| 502 |
|
|
cannot confine authority to one file or a subtree inside it. Filesystem |
| 503 |
|
|
operations do not offer persistent path subjects. An exact "path" |
| 504 |
|
|
matcher is available for deny rules only. Trusted runtime and configured |
| 505 |
|
|
mounts remain baseline access independently of these grants. See |
| 506 |
|
|
"TRUSTED CONFIGURATION" in mcp-fs. |
| 507 |
|
|
|
| 508 |
|
|
Change or remove saved rules |
| 509 |
|
|
Use: |
| 510 |
|
|
|
| 511 |
|
|
anyevent-mcp manage-rules fs-code |
| 512 |
|
|
anyevent-mcp edit-rules fs-code |
| 513 |
|
|
|
| 514 |
|
|
The first command lets you delete and reorder rules in YAD. The second |
| 515 |
|
|
uses $VISUAL, $EDITOR, "sensible-editor" or "vi". An earlier deny or ask |
| 516 |
|
|
rule can explain why adding a later allow rule does not change the |
| 517 |
|
|
result. |
| 518 |
|
|
|
| 519 |
|
|
For a custom application with another rule pathname, use: |
| 520 |
|
|
|
| 521 |
|
|
anyevent-mcp manage-rules-file /path/to/rules.ini |
| 522 |
|
|
anyevent-mcp edit-rules-file /path/to/rules.ini |
| 523 |
|
|
|
| 524 |
|
|
A failed attempt to save a permanent rule is an error, not a successful |
| 525 |
root |
1.6 |
permanent approval. The file mode is preserved when saved through these |
| 526 |
|
|
commands. For full syntax and programming interfaces, see |
| 527 |
root |
1.2 |
AnyEvent::MCP::Server::Permissions. |
| 528 |
|
|
|
| 529 |
|
|
Choose where to ask |
| 530 |
|
|
The default "helper" mode runs "anyevent-mcp-askpermission" on the |
| 531 |
|
|
server machine. It tries YAD, then "/dev/tty", then denies if neither |
| 532 |
|
|
can be used. The helper inherits the server's display environment. |
| 533 |
|
|
"--ask tty" and "--ask yad" instead force the built-in terminal or YAD |
| 534 |
|
|
interface. They ignore custom helper settings and never try another |
| 535 |
|
|
interface. These modes work for permission prompts and ordinary forms, |
| 536 |
|
|
including forms handled by a multibroker. |
| 537 |
|
|
"PERL_ANYEVENT_MCP_PERMISSION_HELPER" selects a different executable. |
| 538 |
|
|
|
| 539 |
|
|
For a modern client supporting MCP form elicitation, you can instead |
| 540 |
|
|
use: |
| 541 |
|
|
|
| 542 |
|
|
mcp-fs --stdio --name code --ask auto /home/alice/src/project |
| 543 |
|
|
|
| 544 |
|
|
"auto" uses the client's form support when advertised for that request, |
| 545 |
|
|
otherwise the local helper. "mcp" requires that support and fails when |
| 546 |
|
|
unavailable. It does not silently fall back. Use client-side permission |
| 547 |
|
|
approval only when that client is a trusted authority to grant access. |
| 548 |
|
|
|
| 549 |
|
|
To set the default for servers using the shared permission engine: |
| 550 |
|
|
|
| 551 |
|
|
PERL_ANYEVENT_MCP_PERMISSION_ASK=auto \ |
| 552 |
|
|
mcp-fs --stdio --name code /home/alice/src/project |
| 553 |
|
|
|
| 554 |
|
|
An explicit application "ask" setting or "--ask" overrides the |
| 555 |
root |
1.9 |
environment. The multibroker sets this default to "mcp" for spawned |
| 556 |
|
|
stdio children, regardless of its own asking mode. Children delegate |
| 557 |
|
|
permission prompts to their calling MCP client; the multibroker handles |
| 558 |
|
|
or forwards those prompts according to its own "--ask" mode. An explicit |
| 559 |
|
|
child "--ask" still overrides this default. Independently running HTTP |
| 560 |
|
|
servers keep their own configuration. |
| 561 |
root |
1.2 |
|
| 562 |
|
|
The multibroker can handle form elicitation locally for both stdio and |
| 563 |
|
|
HTTP children. "--ask helper" selects local dialogs even if the upstream |
| 564 |
|
|
client advertises native forms; "--ask mcp" forwards forms upstream, and |
| 565 |
|
|
"auto" uses native forms when advertised. If a client claims support but |
| 566 |
|
|
silently declines questions, use "helper". A decline never causes a |
| 567 |
|
|
fallback prompt. |
| 568 |
|
|
|
| 569 |
|
|
Standalone "mcp-ask-user" also supports these modes and defaults to the |
| 570 |
|
|
local helper. A question is different from an approval: answering it |
| 571 |
|
|
does not grant a filesystem worker any authority. |
| 572 |
|
|
|
| 573 |
|
|
COMBINING SERVERS |
| 574 |
root |
1.4 |
Once the first connection works, "mcp-multibroker" lets you give the |
| 575 |
|
|
client one connection for several MCP servers. It works with the servers |
| 576 |
|
|
in this distribution and with third-party MCP servers, including ones |
| 577 |
|
|
written in other languages. Each downstream server can be a local |
| 578 |
|
|
subprocess communicating over stdio or an existing HTTP endpoint; you |
| 579 |
|
|
can mix both in one broker. The broker discovers their tools and |
| 580 |
|
|
forwards calls to the appropriate server without changing how that |
| 581 |
|
|
server implements its tools. |
| 582 |
|
|
|
| 583 |
|
|
For example, combine two filesystem instances: |
| 584 |
root |
1.2 |
|
| 585 |
|
|
mcp-multibroker --name tools --bind :31740 \ |
| 586 |
|
|
code 'stdio:mcp-fs --name code /home/alice/src/project' \ |
| 587 |
|
|
notes 'stdio:mcp-fs --name notes /home/alice/notes' |
| 588 |
|
|
|
| 589 |
|
|
Quote each "stdio:" shell command as one argument. The broker supplies |
| 590 |
|
|
the child's stdio environment and starts ordinary children lazily, on |
| 591 |
|
|
first use. The explicit child names give them separate permission |
| 592 |
|
|
profiles "fs-code" and "fs-notes". |
| 593 |
|
|
|
| 594 |
|
|
Obtain the upstream HTTP URL with: |
| 595 |
|
|
|
| 596 |
|
|
mcp-multibroker --name tools --bind :31740 --print-url |
| 597 |
|
|
|
| 598 |
|
|
Configure this URL in place of the client's old direct connection. The |
| 599 |
|
|
client can now see "code.grep", "code.read-lines", "notes.find" and |
| 600 |
|
|
other prefixed tools. It does not need a separate connection to each |
| 601 |
|
|
child. |
| 602 |
|
|
|
| 603 |
|
|
For a client launching the multibroker locally, configure: |
| 604 |
|
|
|
| 605 |
|
|
mcp-multibroker --stdio --name tools \ |
| 606 |
|
|
code 'stdio:mcp-fs --name code /home/alice/src/project' \ |
| 607 |
|
|
notes 'stdio:mcp-fs --name notes /home/alice/notes' |
| 608 |
|
|
|
| 609 |
|
|
"--stdio" selects the upstream connection. The child commands still use |
| 610 |
|
|
"stdio:"; that selects each downstream connection independently. No |
| 611 |
|
|
upstream HTTP URL is needed in this case. |
| 612 |
|
|
|
| 613 |
root |
1.4 |
The same setup can include Vim, browser pages, a third-party stdio |
| 614 |
|
|
server or a remote HTTP service. See "Add an HTTP child" for an example |
| 615 |
|
|
mixing local and remote servers, and "DOWNSTREAM SERVERS" in |
| 616 |
|
|
mcp-multibroker for the complete syntax, including direct argv |
| 617 |
|
|
execution, credentials and per-child options. |
| 618 |
|
|
|
| 619 |
root |
1.2 |
Discover and refresh tools |
| 620 |
|
|
Ask the LLM: |
| 621 |
|
|
|
| 622 |
|
|
Call discover-brokers and list-tools, then show me which servers |
| 623 |
|
|
are available and what each is for. |
| 624 |
|
|
|
| 625 |
root |
1.3 |
"discover-brokers" returns advertised instructions (which may be short), |
| 626 |
|
|
no instructions, or an error for each configured server. "list-tools" |
| 627 |
|
|
requests current tool definitions, including any prefixed |
| 628 |
|
|
"meta-instructions" tools and their full instruction descriptions; |
| 629 |
|
|
unreachable servers are omitted. A reachable server can still fail |
| 630 |
|
|
later. |
| 631 |
root |
1.2 |
|
| 632 |
|
|
If the client still has an old direct tool list, "call-tool" can invoke |
| 633 |
|
|
an exact prefixed name found by "list-tools". Refresh the client's MCP |
| 634 |
|
|
connection if it continues to hide newly available tools. |
| 635 |
|
|
|
| 636 |
|
|
Discovery queries configured servers and currently registered reverse |
| 637 |
|
|
connections. Changing the static downstream command still requires a |
| 638 |
|
|
restart. |
| 639 |
|
|
|
| 640 |
|
|
Let a server connect to the multibroker |
| 641 |
|
|
To add independently started servers without editing the multibroker |
| 642 |
|
|
command, keep its HTTP/extension listener active alongside stdio: |
| 643 |
|
|
|
| 644 |
|
|
mcp-multibroker --stdio --listen --bind 127.0.0.1:31740 |
| 645 |
|
|
mcp-multibroker --bind 127.0.0.1:31740 --print-url |
| 646 |
|
|
|
| 647 |
|
|
Append an alias to the returned credential-bearing URL: |
| 648 |
|
|
|
| 649 |
|
|
mcp-fs --connect http://127.0.0.1:31740/TOKEN/files /home/alice/project |
| 650 |
|
|
|
| 651 |
|
|
The filesystem server initiates the TCP connection but remains the MCP |
| 652 |
|
|
server. The multibroker authenticates the same token used for HTTP, |
| 653 |
|
|
registers the alias and discovers the tools. A configured or connected |
| 654 |
root |
1.10 |
alias cannot be replaced. An unexpected disconnect starts a new |
| 655 |
|
|
connection period; refused TCP connections retry once per second, at |
| 656 |
|
|
most sixty times. Other TCP errors and TLS verification failures log an |
| 657 |
|
|
error and stop. Pending calls fail and are never replayed. Remote |
| 658 |
|
|
registration does not grant spawned-child shutdown authority to the |
| 659 |
|
|
multibroker. |
| 660 |
root |
1.2 |
|
| 661 |
|
|
The hello is a raw JSON line, followed by ordinary MCP JSONL on the same |
| 662 |
|
|
socket; the HTTP-shaped URL is an address and credential, not an HTTP |
| 663 |
root |
1.10 |
request. "https://" reverse URLs enable verified TLS; "http://" uses |
| 664 |
|
|
plaintext. A certificate mismatch is an error, not a reason to fall back |
| 665 |
|
|
to HTTP. With "--tls-cert" and "--tls-key" on the listener, |
| 666 |
|
|
"--print-url" gives HTTPS and HTTP URL prefixes. For HTTPS, use a |
| 667 |
|
|
trusted certificate whose hostname matches the URL. An HTTP listener is |
| 668 |
|
|
already active by default when upstream is HTTP. |
| 669 |
root |
1.2 |
|
| 670 |
|
|
Add an HTTP child |
| 671 |
root |
1.4 |
A broker can mix spawned stdio servers and existing HTTP endpoints, |
| 672 |
|
|
including independently implemented third-party servers: |
| 673 |
root |
1.2 |
|
| 674 |
|
|
mcp-multibroker --stdio \ |
| 675 |
|
|
code 'stdio:mcp-fs --name code /home/alice/src/project' \ |
| 676 |
|
|
remote https://example.org/mcp/ --bearer TOKEN |
| 677 |
|
|
|
| 678 |
|
|
"--bearer" immediately after the HTTP pair belongs to that child. |
| 679 |
|
|
"--token" before all pairs configures the multibroker's own HTTP |
| 680 |
|
|
listener. They authenticate different connections. |
| 681 |
|
|
|
| 682 |
|
|
To avoid putting a child's bearer token in the startup command, add: |
| 683 |
|
|
|
| 684 |
|
|
[client remote] |
| 685 |
|
|
bearer = TOKEN |
| 686 |
|
|
timeout = 300 |
| 687 |
|
|
|
| 688 |
|
|
to the private global configuration, and omit "--bearer" from the |
| 689 |
|
|
command. The prefix "remote" selects these client defaults. The |
| 690 |
|
|
command-line URL still chooses the endpoint. Use the actual credential |
| 691 |
|
|
accepted by that server, not the literal placeholder "TOKEN". |
| 692 |
|
|
|
| 693 |
|
|
A token already present in a child's URL needs no separate bearer |
| 694 |
|
|
option. The bundled servers use static URL-safe tokens; they do not |
| 695 |
|
|
validate OAuth access tokens or implement HTTP Basic authentication. Use |
| 696 |
|
|
TLS or an appropriate tunnel when credentials cross untrusted networks. |
| 697 |
|
|
|
| 698 |
|
|
The multibroker does not put every child inside the mcp-fs sandbox. Each |
| 699 |
|
|
process or remote service has its own authority and enforcement. |
| 700 |
|
|
|
| 701 |
|
|
Add a live Vim editor |
| 702 |
|
|
Install the Vim plugin using "VIM PLUGIN INSTALLATION" in mcp-vim. It is |
| 703 |
|
|
included in the source distribution but is not installed by Perl's "make |
| 704 |
|
|
install". |
| 705 |
|
|
|
| 706 |
root |
1.3 |
Without a multibroker, configure the MCP client to launch: |
| 707 |
|
|
|
| 708 |
|
|
mcp-vim --stdio --name editor |
| 709 |
|
|
|
| 710 |
|
|
Even in stdio mode, mcp-vim listens separately for editor connections. |
| 711 |
|
|
If using a multibroker, start its child eagerly so Vim can connect |
| 712 |
|
|
before the first MCP tool call: |
| 713 |
root |
1.2 |
|
| 714 |
|
|
mcp-multibroker --stdio \ |
| 715 |
|
|
code 'stdio:mcp-fs --name code /home/alice/src/project' \ |
| 716 |
|
|
vim 'stdio:mcp-vim --name editor' --eager |
| 717 |
|
|
|
| 718 |
root |
1.3 |
In another terminal, obtain the editor broker's URL prefix: |
| 719 |
root |
1.2 |
|
| 720 |
|
|
mcp-vim --name editor --print-url |
| 721 |
|
|
|
| 722 |
|
|
Append the desired target name in Vim: |
| 723 |
|
|
|
| 724 |
|
|
:Mcp http://HOST:PORT/TOKEN/my-editor |
| 725 |
|
|
|
| 726 |
|
|
Use the actual printed prefix in place of "http://HOST:PORT/TOKEN/". Ask |
| 727 |
root |
1.3 |
the LLM to call "targets", then "state" before reading or editing |
| 728 |
|
|
buffers ("vim.targets" and "vim.state" through the multibroker). These |
| 729 |
|
|
tools see live, possibly unsaved buffers. Edits require a current |
| 730 |
|
|
changedtick and do not save files to disk. |
| 731 |
root |
1.2 |
|
| 732 |
|
|
To pass arguments directly, use "PREFIX --- PROGRAM ARG... ---": |
| 733 |
|
|
|
| 734 |
|
|
mcp-multibroker --stdio \ |
| 735 |
|
|
vim --- mcp-vim --name editor --bind :: --- --eager \ |
| 736 |
|
|
code --- mcp-fs --name code '/home/alice/project with spaces' --- |
| 737 |
|
|
|
| 738 |
|
|
Only the invoking shell processes quoting. The broker passes all |
| 739 |
|
|
arguments between the delimiters unchanged, including empty arguments |
| 740 |
|
|
and child options. Use "stdio:COMMAND" for shell syntax or a literal |
| 741 |
|
|
"---" child argument. An empty command or missing closing delimiter is |
| 742 |
|
|
an error. |
| 743 |
|
|
|
| 744 |
|
|
"--eager" belongs immediately after its stdio URL or closing "---". An |
| 745 |
|
|
eager connection failure is logged; the broker does not continuously |
| 746 |
|
|
restart the child. Later tool use can try connecting again. |
| 747 |
|
|
|
| 748 |
|
|
Ask the client's human a question |
| 749 |
root |
1.3 |
To let the assistant ask you questions, configure its MCP client to |
| 750 |
|
|
launch: |
| 751 |
|
|
|
| 752 |
|
|
mcp-ask-user --stdio |
| 753 |
|
|
|
| 754 |
|
|
Or add the question server to a multibroker: |
| 755 |
root |
1.2 |
|
| 756 |
|
|
mcp-multibroker --stdio \ |
| 757 |
|
|
code 'stdio:mcp-fs --name code /home/alice/src/project' \ |
| 758 |
|
|
questions 'stdio:mcp-ask-user' |
| 759 |
|
|
|
| 760 |
root |
1.3 |
The LLM can call "ask-user" ("questions.ask-user" through the |
| 761 |
|
|
multibroker) with a question, up to three suggested answers and room for |
| 762 |
|
|
free text. For example, tell it to use that tool if choosing among |
| 763 |
|
|
several possible tasks needs your input. For several fields or other |
| 764 |
|
|
value types, "ask-form" ("questions.ask-form" through the multibroker) |
| 765 |
|
|
accepts "message" and "requestedSchema" directly and returns the |
| 766 |
|
|
standard elicitation response. Both tools use the same configured |
| 767 |
|
|
presentation mode. Decline and cancel are distinct results; neither |
| 768 |
|
|
supplies an answer. |
| 769 |
root |
1.2 |
|
| 770 |
|
|
By default the multibroker displays questions locally, using YAD or a |
| 771 |
|
|
terminal. Add "--ask mcp" before the broker entries to use the client's |
| 772 |
|
|
native forms, or "--ask auto" to select by advertised capability. This |
| 773 |
|
|
also works with "mcp-ask-user" started separately: give that server |
| 774 |
|
|
"--ask mcp" so it delegates presentation to its connecting multibroker. |
| 775 |
|
|
|
| 776 |
|
|
"anyevent-mcp-form-elicitation" is the standalone form renderer. It |
| 777 |
|
|
reads standard MCP form parameters as UTF-8 JSON on stdin and writes an |
| 778 |
|
|
accept/decline/cancel response as JSON on stdout. |
| 779 |
|
|
"PERL_ANYEVENT_MCP_ELICITATION_HELPER" selects a replacement executable. |
| 780 |
|
|
See anyevent-mcp-form-elicitation for supported fields and mcp-ask-user |
| 781 |
|
|
for question arguments and result fields. |
| 782 |
|
|
|
| 783 |
root |
1.10 |
MAIL AND HTTP TOOLS |
| 784 |
|
|
Read and organize mail |
| 785 |
|
|
Configure an IMAP account interactively before starting its MCP server. |
| 786 |
|
|
Look up provider setup instructions and candidate login commands: |
| 787 |
|
|
|
| 788 |
|
|
mcp-imap --name personal providers alice@example.net |
| 789 |
|
|
|
| 790 |
|
|
Replace the example address. Provider OAuth client registrations may not |
| 791 |
|
|
be usable by unrelated applications. For ordinary password or |
| 792 |
|
|
app-password authentication, a manual login looks like: |
| 793 |
|
|
|
| 794 |
|
|
mcp-imap --name personal login method password \ |
| 795 |
|
|
server imap.example.net user alice@example.net tls ssl port 993 |
| 796 |
|
|
|
| 797 |
|
|
The password is requested on the terminal, never as a command argument. |
| 798 |
|
|
For OAuth2, use a provider-approved registration and the suggested |
| 799 |
|
|
"login method oauth2" parameters. Authorize the intended mail account in |
| 800 |
|
|
a browser, then paste the entire final redirect URL in the terminal. An |
| 801 |
|
|
error page at the unserved loopback redirect is expected. See mcp-imap |
| 802 |
|
|
for OAuth options, refresh tokens and other restrictions. |
| 803 |
|
|
|
| 804 |
|
|
After login, configure your MCP client to launch: |
| 805 |
|
|
|
| 806 |
|
|
mcp-imap --stdio --name personal |
| 807 |
|
|
|
| 808 |
|
|
Or combine it with other servers: |
| 809 |
|
|
|
| 810 |
|
|
mcp-multibroker --stdio mail --- mcp-imap --name personal --stdio --- |
| 811 |
|
|
|
| 812 |
|
|
The prefix "mail" produces tools such as "mail.lsub" and |
| 813 |
|
|
"mail.messages"; "personal" selects the account and its permission |
| 814 |
|
|
rules. For example, ask your assistant: |
| 815 |
|
|
|
| 816 |
|
|
List my subscribed mailboxes, then show five recent messages in INBOX, |
| 817 |
|
|
with their senders and subjects. Do not change any flags. |
| 818 |
|
|
|
| 819 |
|
|
"lsub" lists subscriptions; "mailboxes" lists all available folders. The |
| 820 |
|
|
"mailbox" tool can subscribe and unsubscribe, without changing access |
| 821 |
|
|
rights or deleting messages. |
| 822 |
|
|
|
| 823 |
|
|
To search, pass a "filter" to "messages", for example: |
| 824 |
|
|
|
| 825 |
|
|
{ |
| 826 |
|
|
"mailbox": "INBOX", |
| 827 |
|
|
"limit": 20, |
| 828 |
|
|
"filter": { |
| 829 |
|
|
"since": "1-Nov-2026", |
| 830 |
|
|
"any": [ |
| 831 |
|
|
{"from": "alice@example.net"}, |
| 832 |
|
|
{"subject": "invoice"} |
| 833 |
|
|
], |
| 834 |
|
|
"not": {"deleted": true} |
| 835 |
|
|
} |
| 836 |
|
|
} |
| 837 |
|
|
|
| 838 |
|
|
Filter keys are ANDed; "any" adds OR, "all" groups AND, and "not" |
| 839 |
|
|
negates a group. Searches scan bounded UID windows. If the result says |
| 840 |
|
|
"incomplete", continue with "next_cursor", even for an empty page. Use |
| 841 |
|
|
the returned mailbox, UIDVALIDITY and UID together for later operations. |
| 842 |
|
|
Read tools never mark messages Seen. |
| 843 |
|
|
|
| 844 |
|
|
Changing flags, moving messages and expunging require separate |
| 845 |
|
|
permissions. Marking "\\Deleted" does not remove a message permanently; |
| 846 |
|
|
expunging does. After an interrupted write, inspect the mailbox before |
| 847 |
|
|
attempting it again. APPEND stores mail (including drafts) but does not |
| 848 |
|
|
send it. See "TOOLS" in mcp-imap for complete operations and limits. |
| 849 |
|
|
|
| 850 |
|
|
Use an HTTP request tool |
| 851 |
|
|
Launch "mcp-http --stdio" or combine it as "web --- mcp-http --stdio |
| 852 |
|
|
---". For example, ask your assistant: |
| 853 |
|
|
|
| 854 |
|
|
Fetch https://example.org/ and show the status and page title. |
| 855 |
|
|
Do not send a modifying request. |
| 856 |
|
|
|
| 857 |
|
|
A "request" call can use: |
| 858 |
|
|
|
| 859 |
|
|
{"url": "https://example.org/", "method": "GET", "max_bytes": 8192} |
| 860 |
|
|
|
| 861 |
|
|
Permissions distinguish HTTP methods and URL scopes; allowing a GET does |
| 862 |
|
|
not authorize a POST. "grep" and "regex" can filter response text, while |
| 863 |
|
|
"cookie_jar" must be passed between calls by the caller. Redirects and |
| 864 |
|
|
automatic retries are disabled. See mcp-http for response limits and |
| 865 |
|
|
network trust boundaries. |
| 866 |
|
|
|
| 867 |
root |
1.3 |
CONNECTED BROWSER PAGES |
| 868 |
|
|
"mcp-webbrowser" is the browser-page counterpart to "mcp-vim". It |
| 869 |
|
|
exposes only tabs explicitly allowed by the browser user. Configure your |
| 870 |
|
|
MCP client to launch: |
| 871 |
|
|
|
| 872 |
|
|
mcp-webbrowser --stdio |
| 873 |
|
|
|
| 874 |
|
|
The broker keeps its own HTTP/WebSocket listener active even in stdio |
| 875 |
|
|
mode; the userscript connects to that listener, not to MCP's stdio |
| 876 |
|
|
stream. In a separate terminal, obtain its URL: |
| 877 |
|
|
|
| 878 |
|
|
mcp-webbrowser --print-url |
| 879 |
|
|
|
| 880 |
|
|
Use the same instance name and configuration as the broker. Keep this |
| 881 |
|
|
credential-bearing URL private. Install the companion userscript from |
| 882 |
|
|
"webbrowser/mcp-webbrowser.user.js" in the source distribution or from |
| 883 |
|
|
<https://dist.schmorp.de/mcp-webbrowser/1/mcp-webbrowser.user.js>. |
| 884 |
|
|
Chromium with ScriptCat has been tested. On a tab you want to expose, |
| 885 |
|
|
choose Allow MCP access to this tab from the userscript menu and enter |
| 886 |
|
|
the printed URL when prompted. Other tabs remain unexposed. |
| 887 |
|
|
|
| 888 |
root |
1.5 |
The broker supplies "tabs", "execute" and "add-element" tools, |
| 889 |
root |
1.3 |
permission prompts, cancellation and execution timeouts. See "USERSCRIPT |
| 890 |
|
|
INSTALLATION AND USE" in mcp-webbrowser for setup, compatibility and the |
| 891 |
|
|
current ScriptCat discarded-tab limitation. |
| 892 |
|
|
|
| 893 |
|
|
If the multibroker launches the browser broker, keep that child running |
| 894 |
|
|
from startup so browser tabs can connect: |
| 895 |
|
|
|
| 896 |
|
|
mcp-multibroker --stdio browser --- mcp-webbrowser --- --eager |
| 897 |
|
|
|
| 898 |
root |
1.2 |
HTTP TOKENS AND SERVER IDENTITY |
| 899 |
|
|
For the ordinary bundled HTTP endpoints, a client can present an |
| 900 |
|
|
accepted token in either of these ways: |
| 901 |
|
|
|
| 902 |
|
|
POST /TOKEN/ |
| 903 |
|
|
POST / Authorization: Bearer TOKEN |
| 904 |
|
|
|
| 905 |
|
|
URL tokens are path components, not browser cookies. For another |
| 906 |
root |
1.7 |
configured endpoint, "/TOKEN" prefixes that endpoint path. The HTTP |
| 907 |
|
|
server also accepts "/TOKEN" and the corresponding bare path without the |
| 908 |
|
|
final slash when the endpoint is configured with one. This works around |
| 909 |
|
|
clients (observed with Claude) that drop the final slash from a |
| 910 |
root |
1.10 |
configured URL. Managed tokens authenticate distinct users for saved |
| 911 |
|
|
permissions. Existing rules without match.user still apply to every |
| 912 |
|
|
user. |
| 913 |
|
|
|
| 914 |
|
|
To add a user and obtain their multibroker URL: |
| 915 |
|
|
|
| 916 |
|
|
anyevent-mcp create-user chatgpt |
| 917 |
|
|
mcp-multibroker --print-url=chatgpt |
| 918 |
|
|
|
| 919 |
|
|
An implicit global "default" user starts at generation 1. The program, |
| 920 |
|
|
instance, user and generation derive its token; the program, instance |
| 921 |
|
|
and master secret determine a stable port in 16384..32767. Revoke a user |
| 922 |
|
|
to disable its token; create it again to rotate the generation. Losing |
| 923 |
|
|
the master secret changes all derived credentials. Keep an existing |
| 924 |
|
|
"[global]" secret when editing other configuration. |
| 925 |
root |
1.2 |
|
| 926 |
|
|
To configure explicit tokens: |
| 927 |
|
|
|
| 928 |
|
|
[instance code] |
| 929 |
|
|
tokens = first-secret,second-secret |
| 930 |
|
|
|
| 931 |
|
|
Replace those placeholders with actual unguessable URL-safe tokens. |
| 932 |
|
|
Repeated "--token" options replace the whole configured list and the |
| 933 |
root |
1.10 |
derived managed users. In this mode "--print-url" lists all enabled |
| 934 |
|
|
users; explicit tokens still print the first accepted token. Vim |
| 935 |
|
|
editors, browser tabs, and reverse servers need the effective |
| 936 |
|
|
"connect_user" token (default "default"), not an arbitrary named user's |
| 937 |
|
|
token. |
| 938 |
root |
1.2 |
|
| 939 |
|
|
If "--print-url" disagrees with the client's URL, compare the name, |
| 940 |
|
|
command-line overrides, user and configuration environment with the |
| 941 |
|
|
running process. The command resolves configuration; it does not ask the |
| 942 |
|
|
running server which URL it uses. A changed file needs a server restart. |
| 943 |
|
|
|
| 944 |
|
|
An Origin allowlist restricts browser origins; it does not authenticate |
| 945 |
|
|
clients. A CORS preflight can succeed without a token, while the MCP |
| 946 |
|
|
POST still requires one. See "AUTHENTICATION" in |
| 947 |
|
|
AnyEvent::MCP::Server::HTTP for the low-level server interface. |
| 948 |
|
|
|
| 949 |
|
|
CLIENT EXAMPLES |
| 950 |
|
|
Client settings and command syntax evolve independently of this |
| 951 |
|
|
distribution. These examples show the connection choices; consult the |
| 952 |
|
|
linked client documentation if its interface differs. Replace |
| 953 |
|
|
illustrative paths and credentials with your own. |
| 954 |
|
|
|
| 955 |
|
|
OpenAI Codex CLI |
| 956 |
|
|
For the first direct filesystem connection: |
| 957 |
|
|
|
| 958 |
|
|
codex mcp add code -- \ |
| 959 |
|
|
mcp-fs --stdio --name code /home/alice/src/project |
| 960 |
|
|
codex mcp list |
| 961 |
|
|
|
| 962 |
|
|
For a multibroker connection: |
| 963 |
|
|
|
| 964 |
|
|
codex mcp add mytools -- \ |
| 965 |
|
|
mcp-multibroker --stdio \ |
| 966 |
|
|
code 'stdio:mcp-fs --name code /home/alice/src/project' |
| 967 |
|
|
|
| 968 |
|
|
Use "/mcp" within Codex to inspect connections. See Codex MCP |
| 969 |
|
|
documentation <https://learn.chatgpt.com/docs/extend/mcp>. |
| 970 |
|
|
|
| 971 |
|
|
Anthropic Claude Code |
| 972 |
|
|
For the direct connection: |
| 973 |
|
|
|
| 974 |
|
|
claude mcp add --transport stdio --scope user code -- \ |
| 975 |
|
|
mcp-fs --stdio --name code /home/alice/src/project |
| 976 |
|
|
claude mcp list |
| 977 |
|
|
|
| 978 |
|
|
Replace the launched command with the multibroker command above when you |
| 979 |
|
|
want several servers. Use "/mcp" for connection status. See Claude Code |
| 980 |
|
|
MCP documentation <https://code.claude.com/docs/en/mcp>. |
| 981 |
|
|
|
| 982 |
|
|
Google Gemini CLI |
| 983 |
|
|
Merge a direct server entry into "~/.gemini/settings.json": |
| 984 |
|
|
|
| 985 |
|
|
{ |
| 986 |
|
|
"mcpServers": { |
| 987 |
|
|
"code": { |
| 988 |
|
|
"command": "mcp-fs", |
| 989 |
|
|
"args": [ |
| 990 |
|
|
"--stdio", "--name", "code", "/home/alice/src/project" |
| 991 |
|
|
] |
| 992 |
|
|
} |
| 993 |
|
|
} |
| 994 |
|
|
} |
| 995 |
|
|
|
| 996 |
|
|
For a combined connection, use "mcp-multibroker" as the command and its |
| 997 |
|
|
"--stdio" and prefix/server pairs as the argument array. Use "/mcp" to |
| 998 |
|
|
inspect the connection. See Gemini CLI MCP documentation |
| 999 |
|
|
<https://geminicli.com/docs/tools/mcp-server/>. |
| 1000 |
|
|
|
| 1001 |
|
|
Hosted clients, including ChatGPT web |
| 1002 |
|
|
A hosted client cannot spawn your local stdio command or reach your |
| 1003 |
root |
1.5 |
machine's loopback address directly. A Secure MCP Tunnel runs locally, |
| 1004 |
|
|
connects out to OpenAI, and forwards MCP requests to a local stdio |
| 1005 |
|
|
command or HTTP URL. No public listener or inbound firewall port is |
| 1006 |
|
|
needed. |
| 1007 |
|
|
|
| 1008 |
|
|
First create a tunnel in OpenAI Platform tunnel settings and obtain its |
| 1009 |
|
|
"tunnel_..." ID and a runtime API key. Arrange for |
| 1010 |
|
|
"CONTROL_PLANE_API_KEY" to be set securely in the tunnel client's |
| 1011 |
|
|
environment; do not put a real key in a script, command line or example. |
| 1012 |
|
|
Associate the tunnel with the ChatGPT workspace where you want to use |
| 1013 |
|
|
it. |
| 1014 |
|
|
|
| 1015 |
|
|
For stdio, put the server startup command in a small executable wrapper, |
| 1016 |
|
|
for example "/home/alice/bin/my-mcp": |
| 1017 |
|
|
|
| 1018 |
|
|
#!/bin/sh |
| 1019 |
|
|
exec mcp-multibroker --stdio \ |
| 1020 |
|
|
code --- mcp-fs --name code /home/alice/src/project --- \ |
| 1021 |
|
|
questions --- mcp-ask-user --- |
| 1022 |
|
|
|
| 1023 |
|
|
With a tunnel installation providing "tunnel-client-runtime", run: |
| 1024 |
|
|
|
| 1025 |
|
|
tunnel-client-runtime run \ |
| 1026 |
|
|
--log.format=struct-text \ |
| 1027 |
|
|
--log.level=warn \ |
| 1028 |
|
|
--control-plane.tunnel-id=tunnel_... \ |
| 1029 |
|
|
--mcp.connection-max-ttl=120s \ |
| 1030 |
|
|
--mcp.command=/home/alice/bin/my-mcp |
| 1031 |
|
|
|
| 1032 |
|
|
The tunnel starts the wrapper as its stdio MCP server. Do not start a |
| 1033 |
|
|
separate copy yourself. Make the wrapper executable and ensure its |
| 1034 |
|
|
programs and Perl modules are on the tunnel process's "PATH". |
| 1035 |
root |
1.2 |
|
| 1036 |
root |
1.5 |
For HTTP, instead start the server or multibroker separately: |
| 1037 |
|
|
|
| 1038 |
|
|
mcp-multibroker --name tools --bind 127.0.0.1:16586 \ |
| 1039 |
|
|
code 'stdio:mcp-fs --name code /home/alice/src/project' |
| 1040 |
|
|
|
| 1041 |
|
|
Obtain the matching credential-bearing URL: |
| 1042 |
|
|
|
| 1043 |
|
|
mcp-multibroker --name tools --bind 127.0.0.1:16586 --print-url |
| 1044 |
|
|
|
| 1045 |
|
|
Then point the tunnel runtime at that URL, rather than a command: |
| 1046 |
|
|
|
| 1047 |
|
|
tunnel-client-runtime run \ |
| 1048 |
|
|
--log.format=struct-text \ |
| 1049 |
|
|
--log.level=warn \ |
| 1050 |
|
|
--control-plane.tunnel-id=tunnel_... \ |
| 1051 |
|
|
--mcp.connection-max-ttl=120s \ |
| 1052 |
|
|
--mcp.server-url=http://127.0.0.1:16586/TOKEN/ |
| 1053 |
|
|
|
| 1054 |
|
|
Replace "TOKEN" with the actual URL path printed above, and keep it |
| 1055 |
|
|
private. In this mode, the multibroker must remain running separately; |
| 1056 |
|
|
the tunnel only connects to it. Both modes require the tunnel runtime to |
| 1057 |
|
|
remain active while the hosted client uses the server. Use one of |
| 1058 |
|
|
"--mcp.command" and "--mcp.server-url", not both. |
| 1059 |
|
|
|
| 1060 |
|
|
In ChatGPT, add a custom MCP server using a Tunnel connection and select |
| 1061 |
|
|
the tunnel ID. Creation and visibility depend on the Platform and |
| 1062 |
|
|
ChatGPT workspace permissions. The tunnel client's CLI and supported |
| 1063 |
|
|
configuration forms can vary between releases; the examples above use |
| 1064 |
|
|
the direct runtime CLI rather than its optional profile setup. See |
| 1065 |
root |
1.2 |
Secure MCP Tunnel |
| 1066 |
root |
1.5 |
<https://developers.openai.com/api/docs/guides/secure-mcp-tunnels> for |
| 1067 |
|
|
obtaining a tunnel, runtime, credentials and connecting it to ChatGPT. |
| 1068 |
root |
1.2 |
|
| 1069 |
|
|
TROUBLESHOOTING |
| 1070 |
|
|
The server does not start |
| 1071 |
|
|
Read stderr or the client's server log. Missing Perl modules, a missing |
| 1072 |
|
|
workdir, unsuitable utilities or an unavailable bubblewrap executable |
| 1073 |
|
|
can fail startup. Confirm that the client launches the same executable |
| 1074 |
|
|
and arguments you intended, with the expected "PATH" and Perl |
| 1075 |
|
|
installation. |
| 1076 |
|
|
|
| 1077 |
|
|
For a local sandbox check, run from the project directory: |
| 1078 |
|
|
|
| 1079 |
|
|
mcp-fs --exec-cmd workdir-read -- ls |
| 1080 |
|
|
|
| 1081 |
|
|
This runs "ls" with the named grants and trusted baseline mounts, |
| 1082 |
|
|
without MCP or saved permission rules. A failure here can identify a |
| 1083 |
|
|
bubblewrap or runtime problem. It does not test the client connection or |
| 1084 |
|
|
approval UI. "--sandbox none" disables isolation and changes worker |
| 1085 |
|
|
authority; it is not a fix that preserves the same permission boundary. |
| 1086 |
|
|
|
| 1087 |
|
|
The client cannot connect |
| 1088 |
|
|
For stdio, configure a command the client launches, rather than a URL. A |
| 1089 |
|
|
separately running stdio process is not the client's connection. Do not |
| 1090 |
|
|
put banners or diagnostics on stdout. |
| 1091 |
|
|
|
| 1092 |
|
|
For HTTP, leave the server running and check its address and port. |
| 1093 |
|
|
"--print-url" exits without starting it. Loopback binds accept local |
| 1094 |
|
|
connections only; hosted or remote clients need the appropriate route or |
| 1095 |
|
|
tunnel. An occupied port causes a listener error, so check the server |
| 1096 |
|
|
log. |
| 1097 |
|
|
|
| 1098 |
root |
1.10 |
For reverse "--connect" servers, check the connecting process's log as |
| 1099 |
|
|
well as the multibroker. "https://" requires a certificate trusted by |
| 1100 |
|
|
the connecting process and a hostname matching the URL. A TLS error |
| 1101 |
|
|
stops that reverse server immediately; it does not retry with plaintext. |
| 1102 |
|
|
TCP connection refusal is retried for up to sixty attempts. |
| 1103 |
|
|
|
| 1104 |
root |
1.2 |
Authentication fails |
| 1105 |
|
|
Obtain the URL with the same name, bind/token overrides and |
| 1106 |
root |
1.7 |
configuration environment as the running process. Use the complete path; |
| 1107 |
|
|
the final slash is optional for endpoints whose configured path ends in |
| 1108 |
|
|
one. A clean URL needs an accepted bearer token. |
| 1109 |
root |
1.2 |
|
| 1110 |
|
|
A multibroker child credential is not necessarily the upstream |
| 1111 |
|
|
listener's credential. "--bearer" after a child pair and "--token" |
| 1112 |
|
|
before the pairs configure different sides of the connection. |
| 1113 |
|
|
|
| 1114 |
root |
1.10 |
For IMAP OAuth2, obtaining an access token does not by itself prove that |
| 1115 |
|
|
IMAP authentication will work. Check the authorized browser account, |
| 1116 |
|
|
requested IMAP scope and saved "user" name. Copy the complete redirected |
| 1117 |
|
|
address-bar URL after authorization, even when the browser displays an |
| 1118 |
|
|
unreachable loopback page. |
| 1119 |
|
|
|
| 1120 |
root |
1.2 |
If the server warns that it cannot save the master secret, another |
| 1121 |
root |
1.6 |
process may derive a different token. Check write access to the global |
| 1122 |
|
|
configuration. Do not replace an existing secret simply to add a |
| 1123 |
|
|
setting. |
| 1124 |
root |
1.2 |
|
| 1125 |
|
|
Connected, but there are no tools |
| 1126 |
|
|
Inspect the server's stderr for omitted utilities. mcp-fs's "workdirs" |
| 1127 |
|
|
tool reports configuration even when a utility-dependent tool is absent. |
| 1128 |
|
|
For a multibroker, call "discover-brokers" to see individual connection |
| 1129 |
|
|
errors, then "list-tools" to refresh definitions. |
| 1130 |
|
|
|
| 1131 |
|
|
A third-party child might require initialization or features this client |
| 1132 |
|
|
implementation does not support. See AnyEvent::MCP::Client and its |
| 1133 |
|
|
transport documentation for limitations. |
| 1134 |
|
|
|
| 1135 |
|
|
There is no approval dialog |
| 1136 |
|
|
First check whether the tool was denied by a saved rule or is waiting |
| 1137 |
|
|
for the client's own approval. An allowed operation needs no server |
| 1138 |
|
|
prompt. |
| 1139 |
|
|
|
| 1140 |
|
|
The default helper runs on the server machine. A background service may |
| 1141 |
|
|
have neither a usable display nor "/dev/tty", even though your |
| 1142 |
|
|
interactive shell has both. Supply the appropriate display environment, |
| 1143 |
|
|
a usable helper, or "--ask auto" with a modern client supporting form |
| 1144 |
|
|
elicitation. "--ask mcp" reports an error if that support is absent. |
| 1145 |
|
|
|
| 1146 |
|
|
Setting an asking mode cannot make an unsupported client display a form. |
| 1147 |
|
|
Check stderr and the tool error instead of assuming a missing dialog is |
| 1148 |
|
|
an approval. |
| 1149 |
|
|
|
| 1150 |
|
|
It asks again after I chose allow |
| 1151 |
|
|
Allow-once covers one tool invocation, including its permission retries. |
| 1152 |
|
|
The next invocation asks again. Use allow-always to save a rule. |
| 1153 |
|
|
|
| 1154 |
|
|
Inspect the saved rule's action, workdir and grants. Listing names and |
| 1155 |
|
|
reading contents are different actions. A rule for one exact workdir |
| 1156 |
|
|
spelling will not match a differently spelled startup argument. A |
| 1157 |
|
|
request for extra authority, such as networking, does not match a |
| 1158 |
|
|
workdir-read-only allow rule. Earlier ask or deny rules take precedence. |
| 1159 |
|
|
|
| 1160 |
|
|
Confirm that the prompt's permanent rule was successfully saved and that |
| 1161 |
|
|
you are editing the rules for the actual child name, not merely its |
| 1162 |
|
|
multibroker prefix. |
| 1163 |
|
|
|
| 1164 |
|
|
The worker cannot see a directory or executable |
| 1165 |
|
|
The worker sees granted mounts and trusted baseline mounts, not |
| 1166 |
|
|
everything the server process can see. Check "workdirs" for the selected |
| 1167 |
|
|
path, mounts and runtime paths. A symlink target outside those mounts is |
| 1168 |
|
|
unavailable. |
| 1169 |
|
|
|
| 1170 |
root |
1.3 |
The ordinary sandbox runtime includes "/usr", "/bin" and system |
| 1171 |
|
|
libraries, but not "/opt". For tools or libraries under "/opt", add this |
| 1172 |
|
|
to "[program mcp-fs]" in the private global configuration: |
| 1173 |
|
|
|
| 1174 |
|
|
mount.opt = ro:/opt |
| 1175 |
|
|
|
| 1176 |
|
|
This assumes "/opt" exists. Restart mcp-fs after changing trusted |
| 1177 |
|
|
mounts. If your worker Perl is "/opt/bin/perl", you can also set |
| 1178 |
|
|
"executable.perl = /opt/bin/perl" in that program section. Supply the |
| 1179 |
|
|
actual executable path: selecting it does not itself mount the |
| 1180 |
|
|
executable or its dependencies inside the worker. |
| 1181 |
|
|
|
| 1182 |
|
|
A trusted mount supplies baseline access to every worker using it; a |
| 1183 |
root |
1.2 |
writable mount likewise supplies baseline write authority. |
| 1184 |
|
|
|
| 1185 |
|
|
An arbitrary command might also need its user's configuration or |
| 1186 |
|
|
repository credentials under HOME, or network access. Request the |
| 1187 |
|
|
corresponding grants when needed; do not assume "workdir-read" includes |
| 1188 |
|
|
them. For example, CVS over SSH can use "workdir-read" and "ssh-agent". |
| 1189 |
|
|
The latter includes network access, the agent socket and |
| 1190 |
|
|
"~/.ssh/known_hosts", without exposing private key files or the rest of |
| 1191 |
|
|
HOME. The broker must inherit "SSH_AUTH_SOCK" from your environment. |
| 1192 |
|
|
User-configured helpers outside the runtime mounts need an explicit |
| 1193 |
|
|
trusted mount. An explicit exec grant array replaces the default rather |
| 1194 |
|
|
than adding to it. |
| 1195 |
|
|
|
| 1196 |
|
|
My configuration change seems to be ignored |
| 1197 |
|
|
Check which file and section the process actually selects. Global |
| 1198 |
|
|
settings use the server user's "HOME"/"XDG_CONFIG_HOME". Instance names, |
| 1199 |
|
|
program basenames and multibroker prefixes serve different purposes. |
| 1200 |
|
|
|
| 1201 |
|
|
Restart after changing startup settings, mounts or utilities. Permission |
| 1202 |
|
|
rules need no restart, but their order still matters. Refresh discovery |
| 1203 |
|
|
after a child restart; reconnect a client that retains an old tool list. |
| 1204 |
|
|
"--print-url" reads the current configuration, which can differ from an |
| 1205 |
|
|
older running process. |
| 1206 |
|
|
|
| 1207 |
|
|
The command failed, but the MCP request succeeded |
| 1208 |
|
|
"exec" reports exit status, signal or timeout as a normal tool result. A |
| 1209 |
|
|
successful MCP exchange is not a successful Unix command. Conversely, a |
| 1210 |
|
|
transport failure does not prove a command did nothing: it may have |
| 1211 |
|
|
completed before the connection was lost. Calls are not automatically |
| 1212 |
|
|
replayed after a transport failure. |
| 1213 |
|
|
|
| 1214 |
|
|
TESTING |
| 1215 |
|
|
The default test level is 0. It checks protocol behaviour, permissions, |
| 1216 |
|
|
validation and ordinary process operation, including worker cancellation |
| 1217 |
|
|
and reaping. Watchdogs allow slow machines time to finish; they do not |
| 1218 |
|
|
make successful tests wait for the whole timeout. |
| 1219 |
|
|
|
| 1220 |
|
|
prove -Ilib t |
| 1221 |
|
|
|
| 1222 |
|
|
Set "PERL_ANYEVENT_MCP_TESTS" to 1 to include the extended tests: |
| 1223 |
|
|
|
| 1224 |
|
|
PERL_ANYEVENT_MCP_TESTS=1 prove -Ilib t |
| 1225 |
|
|
|
| 1226 |
|
|
Level 1 adds GNU find/grep/sed/patch operations, real Vim scripting, |
| 1227 |
|
|
browser transfer integration, short idle-lifetime tests, a helper |
| 1228 |
|
|
descendant holding a pipe open, and tests which deliberately wait for a |
| 1229 |
|
|
command timeout or cancel a form helper across several processes. Run |
| 1230 |
|
|
this level before releases. Values greater than 1 currently select the |
| 1231 |
|
|
same tests as level 1. |
| 1232 |
|
|
|
| 1233 |
|
|
Missing GNU utilities or required Vim functions cause explicit skips |
| 1234 |
|
|
even at level 1. The permission and form UI tests use a YAD stand-in: |
| 1235 |
|
|
neither level requires YAD, X11 or an interactive display. The |
| 1236 |
|
|
filesystem tests use a bubblewrap stand-in and check arguments and |
| 1237 |
|
|
worker behaviour; they do not test kernel isolation. The browser tests |
| 1238 |
|
|
use simulated peers. |
| 1239 |
|
|
|
| 1240 |
|
|
WHERE TO GO NEXT |
| 1241 |
|
|
For available tools and server-specific options: |
| 1242 |
|
|
|
| 1243 |
|
|
perldoc mcp-fs |
| 1244 |
|
|
perldoc mcp-multibroker |
| 1245 |
|
|
perldoc mcp-vim |
| 1246 |
|
|
perldoc mcp-ask-user |
| 1247 |
|
|
perldoc anyevent-mcp |
| 1248 |
|
|
|
| 1249 |
|
|
For a complete first Perl server, options, replies, permission checks |
| 1250 |
|
|
and asynchronous work, see "TUTORIAL" in AnyEvent::MCP::Server::Simple. |
| 1251 |
|
|
For the module map and shared configuration reference, see |
| 1252 |
|
|
AnyEvent::MCP. For permission rule details, see |
| 1253 |
|
|
AnyEvent::MCP::Server::Permissions. |
| 1254 |
|
|
|
| 1255 |
|
|
SEE ALSO |
| 1256 |
|
|
AnyEvent::MCP, AnyEvent::MCP::Server::Simple, mcp-fs, mcp-multibroker, |
| 1257 |
|
|
mcp-vim, mcp-ask-user, AnyEvent::MCP::Server::Permissions |
| 1258 |
|
|
|