ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/AnyEvent-MCP/README
Revision: 1.2
Committed: Fri Oct 16 15:35:14 2026 UTC (4 days, 21 hours ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +971 -0 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 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 cpan AnyEvent AnyEvent::HTTP common::sense JSON::XS
52
53 Use the same Perl installation for dependency installation, building and
54 running the servers. A module installed for the system Perl might not be
55 available to a Perl installed under "/opt". "make install" needs write
56 access to the selected Perl's installation directories; use an
57 appropriate local Perl installation or run that final step with the
58 required privileges.
59
60 Installation puts "mcp-fs", "mcp-multibroker", "mcp-vim",
61 "mcp-webbrowser", "mcp-ask-user", "anyevent-mcp" and
62 "anyevent-mcp-askpermission" in the selected executable directory. Make
63 that directory available in the environment of your MCP client, or
64 configure absolute executable paths. A desktop application need not have
65 the same "PATH" as your shell.
66
67 To try an uninstalled source tree after installing its dependencies, you
68 can run a program with the source library path:
69
70 perl -Ilib bin/mcp-fs --stdio --name code /home/alice/src/project
71
72 Do this from the distribution directory. When configuring a client to
73 start such a command, account for the client's working directory or use
74 absolute paths to Perl, "lib" and the script. An installed executable
75 avoids that extra setup.
76
77 CONNECTED BROWSER PAGES
78 "mcp-webbrowser" is the browser-page counterpart to "mcp-vim". Its own
79 HTTP/WebSocket listener remains active when MCP uses stdio or
80 "--connect":
81
82 mcp-webbrowser --stdio
83 mcp-webbrowser --print-url
84
85 A userscript or extension explicitly enables a page and connects to the
86 WebSocket URL formed from the returned address. The broker supplies
87 "pages" and asynchronous "execute" tools, page-name collision/reconnect
88 handling, permission prompts, cancellation and execution timeouts. The
89 browser client implements JavaScript evaluation and awaits Promise
90 results. See "BROWSER PROTOCOL" in mcp-webbrowser for the small wire
91 contract.
92
93 The userscript/extension UI is a separate component and is not included
94 yet. DOM revision tracking and acknowledgement-before-navigation remain
95 client design work. To keep a lazily spawned multibroker child available
96 for browser connections from startup, use "--eager":
97
98 mcp-multibroker browser --- mcp-webbrowser --- --eager
99
100 YOUR FIRST FILESYSTEM SERVER
101 Start with one project and one connection. You do not need a
102 multibroker, a hand-written configuration file or saved permission rules
103 yet.
104
105 Choose stdio or HTTP
106 Use stdio when your MCP client runs on the same machine and can launch a
107 server process. Configure the client to start the following command:
108
109 mcp-fs --stdio --name code /home/alice/src/project
110
111 The client starts this process and uses its stdin/stdout for MCP. You do
112 not start a second copy in a terminal, and there is no listener URL or
113 HTTP token to configure. Diagnostics go to stderr.
114
115 Clients that take a command and an argument array need these values:
116
117 command: mcp-fs
118 arguments: --stdio, --name, code, /home/alice/src/project
119
120 These describe separate arguments, not one shell command string. Use an
121 absolute executable path if the client cannot find "mcp-fs". See "CLIENT
122 EXAMPLES" for examples of particular clients.
123
124 Use HTTP when the client connects to an already-running server, or when
125 it cannot launch a local process. Start this in a terminal on the server
126 machine and leave it running:
127
128 mcp-fs --name code --bind :31741 /home/alice/src/project
129
130 In another terminal, obtain the matching connection URL:
131
132 mcp-fs --name code --bind :31741 --print-url
133
134 The second command prints a credential-bearing URL and exits without
135 opening a listener. Configure that URL in the client. The default
136 address is IPv4 loopback, so this example is reachable from the same
137 machine only. A hosted client needs a suitable tunnel or reachable
138 endpoint; its own "localhost" is not your computer.
139
140 Repeat the same name and listener overrides when printing the URL. Both
141 commands must use the same user and configuration directory. Port zero
142 chooses an ephemeral port, which "--print-url" cannot predict; use an
143 explicit port for this walkthrough.
144
145 The HTTP server generates and saves its private master secret when
146 needed. You can initialize it explicitly with "anyevent-mcp init", but
147 that command is unnecessary when configuration already exists and will
148 refuse to replace it. Keep the printed URL private: possession of its
149 token authenticates a client.
150
151 Make a useful request
152 Once your client reports that the server is connected, ask the LLM:
153
154 Show me the configured workdirs. List the top-level files in the
155 project, then read its README. Do not modify files or run commands.
156
157 "workdirs" returns the configured paths, sandbox grants, trusted mounts
158 and runtime paths. Listing names requests "inspect" permission; reading
159 contents requests "read" permission. Expect a permission prompt when
160 there is no saved rule allowing the operation.
161
162 Choose "Allow once" for the first operation. The worker then runs with
163 the requested sandbox grants. A denial is a tool failure that the LLM
164 should report, rather than an empty file or a disconnected server.
165
166 For a slightly larger task, ask:
167
168 Find TODO comments in this project and explain the three that look
169 most useful to address next. Do not modify files or run commands.
170
171 This can use "find", "grep" and "read-lines". You need not write MCP
172 requests yourself. If a client offers its own tool-approval prompt, that
173 is an additional client policy; it does not replace mcp-fs's
174 permissions.
175
176 Understand the workdir
177 The directory passed at startup tells mcp-fs which workdir to expose. It
178 does not grant permission for every operation in that directory. Each
179 operation still requests its action and sandbox grants.
180
181 With one workdir, tools can omit the "workdir" argument. With several:
182
183 mcp-fs --stdio --name code /home/alice/src/project /home/alice/notes
184
185 tools select one using a persistent positive integer ID, a numeric
186 string or an exact configured/resolved path returned by "workdirs". The
187 "workdirs" and "resolved_workdirs" objects use these IDs as keys.
188 Relative tool paths are relative to that selection. Permission rules
189 continue to use the configured path, not its numeric ID.
190
191 IDs are shared across filesystem servers in
192 "$XDG_CONFIG_HOME/anyevent-mcp/fs-workdir-ids.json", or under
193 "$HOME/.config" by default. They identify resolved absolute paths and
194 survive restarts and argument reordering. Startup resolves IDs once and
195 reserves new allocations under the lock. A timer runs immediately and
196 every 5.25 days to reread the registry and refresh the server's fixed
197 assignments. Other entries expire after seven days and their IDs may be
198 reused. Restart servers after manually changing the registry.
199
200 "workdir-read" exposes the selected workdir read-only. "workdir-write"
201 makes it writable and implies read access. A path in another configured
202 workdir requires all-workdirs authority; a path elsewhere requires
203 suitable home/world or shared-tmp authority. A symlink cannot make an
204 unmounted target appear inside the sandbox.
205
206 Prefer separate, non-overlapping workdirs. Overlapping mounts have
207 unspecified access effects. See "SANDBOX GRANTS" in mcp-fs before
208 granting access beyond the selected workdir.
209
210 Inspect version-control changes
211 For a Git, SVN, CVS or Mercurial working copy, ask the LLM to use
212 "vcs-diff" and "vcs-status", with "backend" set to "git", "svn", "cvs"
213 or "hg". "workdirs" reports the available clients. These tools accept
214 filenames and construct the command themselves; no shell pipeline or
215 arbitrary VCS options need to be approved.
216
217 For example:
218
219 Show the CVS diff for this project, limited to 200 lines.
220 Then show its status, keeping stdout lines matching "File:|Status:".
221
222 These operations have their own permission actions. They request read
223 access to the selected workdir and home configuration; CVS also requests
224 network access automatically. Read permission for ordinary file tools
225 does not automatically authorize a VCS operation.
226
227 For arbitrary "exec" commands, the same output options are available:
228 "grep" filters stdout using PCRE, "max_lines" limits matching stdout
229 lines, and "max_bytes" bounds returned bytes per stream. Prefer these
230 options to a shell wrapper that mixes execution and output processing.
231 Stderr is unfiltered, and exit status still describes the original
232 command.
233
234 Defaults return at most 2000 stdout lines and 64 KiB per stream. Raw
235 capture has a separate 1 MiB limit per stream. A true
236 "capture_truncated" means output was omitted before filtering or
237 collection ended on timeout, so absent matches do not prove the omitted
238 output had none. See "Command output" in mcp-fs for all result flags and
239 limits.
240
241 CONFIGURING YOUR SETUP
242 There are three different things to configure: how the client connects,
243 how the server runs, and which operations the user allows. Changing one
244 does not necessarily change the other two.
245
246 Where each setting belongs
247 Directories to expose
248 Pass workdirs on the mcp-fs startup command. For a stdio server,
249 that command belongs in the client's server configuration. For an
250 HTTP server, it belongs in the command used to run the service.
251
252 Connection transport
253 The client launches a command for stdio or connects to a URL for
254 HTTP. "--stdio" selects the former for mcp-fs and the multibroker.
255
256 Listener address, port and tokens
257 Use "[instance NAME]" in the global configuration or command-line
258 "--bind" and "--token" overrides.
259
260 Trusted mounts and utility paths
261 For mcp-fs, use "[program NAME]" defaults and "[instance NAME]"
262 overrides in the global configuration.
263
264 Allowed operations and sandbox grants
265 Use the permission rules file, normally created through approval
266 dialogs. This file is separate from the global configuration.
267
268 Location of permission prompts
269 Use "--ask helper", "--ask tty", "--ask yad", "--ask auto" or "--ask
270 mcp", or set "PERL_ANYEVENT_MCP_PERMISSION_ASK" in the server's
271 environment.
272
273 Combined server connections
274 Put prefix/server pairs on the multibroker startup command. HTTP
275 child credentials can also use "[client PREFIX]" in the global
276 configuration.
277
278 One complete named configuration
279 The global file is "$XDG_CONFIG_HOME/anyevent-mcp/global.ini", falling
280 back to "$HOME/.config/anyevent-mcp/global.ini". Settings are UTF-8 "key
281 = value" lines; values are unquoted. Whole-line "#" and ";" comments are
282 allowed. See "GLOBAL CONFIGURATION" in AnyEvent::MCP for the complete
283 format.
284
285 Start with the existing file, preserving its "[global]" secret. If you
286 have no file yet, "anyevent-mcp init" creates it privately. Add the
287 following sections:
288
289 [program mcp-fs]
290 mount.opt = ro:/opt
291
292 [instance code]
293 bind = 127.0.0.1:31741
294
295 The optional "mount.opt" line assumes "/opt" exists and contains tools
296 or libraries your workers need. Omit it if you do not need that access.
297 The ordinary sandbox runtime includes "/usr", "/bin" and system
298 libraries, but not "/opt". If your worker Perl is "/opt/bin/perl", you
299 can additionally put "executable.perl = /opt/bin/perl" in that program
300 section. Supply the actual executable path; selecting it does not itself
301 mount its files or libraries.
302
303 Now start:
304
305 mcp-fs --name code /home/alice/src/project
306
307 and retrieve its URL with:
308
309 mcp-fs --name code --print-url
310
311 Both use "[instance code]". No explicit token is needed: the server
312 derives one from its name and the existing master secret.
313
314 For this setup:
315
316 program defaults: [program mcp-fs]
317 instance settings: [instance code]
318 selected workdir: /home/alice/src/project
319 permission file: ~/.config/anyevent-mcp/rules/fs-code.ini
320 rule-manager profile: fs-code
321
322 The permission pathname above assumes the default configuration
323 directory. "anyevent-mcp manage-rules fs-code" opens the graphical rule
324 manager; "anyevent-mcp edit-rules fs-code" opens the file in your
325 editor.
326
327 Keep global configuration and rule files owned by the server user and
328 private, normally mode 0600. "--config FILE" on "anyevent-mcp init"
329 selects that command's output file; it does not make the servers use an
330 arbitrary alternate file. Use the same "HOME"/"XDG_CONFIG_HOME"
331 environment when running the server and its management commands.
332
333 Names, prefixes and profiles
334 "--name code" selects instance settings, derived HTTP credentials and
335 mcp-fs's "rules/fs-code.ini". Without "--name", mcp-fs uses "default",
336 giving profile "fs-default". Two processes with the same program, name
337 and configuration share credentials and rules, even if their workdirs
338 differ.
339
340 A multibroker prefix, such as "files", only routes tools: "grep" becomes
341 "files.grep". It does not rename the child server or select its rules.
342 For example:
343
344 mcp-multibroker files \
345 'stdio:mcp-fs --name code /home/alice/src/project'
346
347 The tools are "files.*", but the child still uses instance "code" and
348 rule-manager profile "fs-code". The multibroker's own "--name" selects
349 its upstream listener settings.
350
351 Configuration changes and restarts
352 Command-line listener options override the named global settings. For
353 mcp-fs trusted settings, an instance entry overrides the corresponding
354 program entry; an empty instance mount value suppresses the inherited
355 mount.
356
357 Workdirs, mounts, utility paths, listener settings and tokens are read
358 at startup. Change the file or startup command, then restart the
359 affected server. The multibroker also needs restarting to change its
360 prefix/server pairs; refreshing discovery does not change those pairs.
361
362 Permission rules are reread on permission checks, so editing them does
363 not require a restart. A client's displayed tool list can still be
364 cached. After restarting a child, refresh tool discovery or reconnect
365 the client as described in "COMBINING SERVERS".
366
367 PERMISSIONS IN PRACTICE
368 HTTP authentication establishes that the client may connect. Permission
369 checks decide whether a tool may perform an operation. A correct token
370 therefore does not prevent permission prompts.
371
372 What the prompt means
373 The prompt describes an action, paths or command, a reason and sandbox
374 grants. For filesystem tools, the actions are:
375
376 inspect stat, list, find
377 read file-read, read-lines, grep
378 write file-write, file-patch
379 manage path-op
380 exec arbitrary command execution
381 vcs-diff working-copy differences
382 vcs-status working-copy status
383
384 The action and grants are independent. Allowing "read" does not allow
385 "write", even if a worker grant permits both kinds of filesystem access.
386 "exec" runs arbitrary commands; it is not a classification of supposedly
387 safe command prefixes.
388
389 Choose allow/deny once, or always. Closing the dialog denies once. An
390 optional denial reason is returned with the error; it is not added to
391 successful tool results. An always choice opens a rule editor. Choose an
392 indefinite lifetime (the default), 900 seconds or 16 hours. Finite
393 lifetimes are stored as "expires" Unix timestamps. Expired rules
394 disappear on every read; the next ordinary save removes them from disk.
395 Expiry affects future permission checks, not operations already
396 authorized. Filesystem allow rules can select grants and the selected
397 workdir when the authority depends on it. Deny rules can also select an
398 exact affected path. Exec offers persistent command/argv subjects.
399
400 For exec, "View stdin..." lets you inspect supplied input without
401 closing the approval dialog. Filesystem and Vim patch tools similarly
402 offer "View patch...", including the target file or editor and buffer.
403 Longer text is shown as an explicitly incomplete preview. These are YAD
404 button labels; other interfaces can show the details inline. That input
405 is display-only: an exec allow rule does not constrain future stdin.
406 Allowing an interpreter command can therefore allow a different script
407 on its next invocation.
408
409 A worker accessing several paths requests their combined sandbox
410 authority once. If the chosen grants are insufficient, it fails before
411 starting.
412
413 Save a useful read-only policy
414 After trying individual operations, you might want the LLM to inspect
415 and read the project without asking each time, while keeping changes
416 subject to approval. Put these rules in "rules/fs-code.ini", or create
417 equivalent allow rules through the prompt:
418
419 [rule]
420 decision=allow
421 action=inspect
422 workdir=/home/alice/src/project
423 sandbox-grants=workdir-read
424
425 [rule]
426 decision=allow
427 action=read
428 workdir=/home/alice/src/project
429 sandbox-grants=workdir-read
430
431 [rule]
432 decision=deny
433 action=exec
434
435 Use the exact workdir spelling passed at server startup. Absolute
436 startup paths make this easier. If creating the rules file manually,
437 ensure it belongs to the server user and is private before making
438 another request. For the default configuration directory:
439
440 chmod 600 ~/.config/anyevent-mcp/rules/fs-code.ini
441
442 Use the corresponding XDG path when configured. Without matching rules,
443 write and manage operations still ask. The final rule denies command
444 execution outright; omit it if you want execution to ask instead.
445
446 Rules run in order, stopping at the first match. An allow rule matches
447 only when its grants cover the request, including implications.
448 "workdir-write" implies "workdir-read"; "network" remains independent.
449 Action and subject match exactly unless beginning with "^", which
450 selects a Perl regular expression. Workdir matching is always exact. An
451 explicit "ask" rule can override later allow rules.
452
453 These allow rules authorize sandbox access to the selected workdir. They
454 cannot confine authority to one file or a subtree inside it. Filesystem
455 operations do not offer persistent path subjects. An exact "path"
456 matcher is available for deny rules only. Trusted runtime and configured
457 mounts remain baseline access independently of these grants. See
458 "TRUSTED CONFIGURATION" in mcp-fs.
459
460 Change or remove saved rules
461 Use:
462
463 anyevent-mcp manage-rules fs-code
464 anyevent-mcp edit-rules fs-code
465
466 The first command lets you delete and reorder rules in YAD. The second
467 uses $VISUAL, $EDITOR, "sensible-editor" or "vi". An earlier deny or ask
468 rule can explain why adding a later allow rule does not change the
469 result.
470
471 For a custom application with another rule pathname, use:
472
473 anyevent-mcp manage-rules-file /path/to/rules.ini
474 anyevent-mcp edit-rules-file /path/to/rules.ini
475
476 A failed attempt to save a permanent rule is an error, not a successful
477 permanent approval. The file must remain private and owned by the server
478 user. For full syntax and programming interfaces, see
479 AnyEvent::MCP::Server::Permissions.
480
481 Choose where to ask
482 The default "helper" mode runs "anyevent-mcp-askpermission" on the
483 server machine. It tries YAD, then "/dev/tty", then denies if neither
484 can be used. The helper inherits the server's display environment.
485 "--ask tty" and "--ask yad" instead force the built-in terminal or YAD
486 interface. They ignore custom helper settings and never try another
487 interface. These modes work for permission prompts and ordinary forms,
488 including forms handled by a multibroker.
489 "PERL_ANYEVENT_MCP_PERMISSION_HELPER" selects a different executable.
490
491 For a modern client supporting MCP form elicitation, you can instead
492 use:
493
494 mcp-fs --stdio --name code --ask auto /home/alice/src/project
495
496 "auto" uses the client's form support when advertised for that request,
497 otherwise the local helper. "mcp" requires that support and fails when
498 unavailable. It does not silently fall back. Use client-side permission
499 approval only when that client is a trusted authority to grant access.
500
501 To set the default for servers using the shared permission engine:
502
503 PERL_ANYEVENT_MCP_PERMISSION_ASK=auto \
504 mcp-fs --stdio --name code /home/alice/src/project
505
506 An explicit application "ask" setting or "--ask" overrides the
507 environment. For spawned stdio children, "mcp-multibroker --ask auto"
508 passes this default to them. It cannot change the environment of an
509 independently running HTTP server.
510
511 The multibroker can handle form elicitation locally for both stdio and
512 HTTP children. "--ask helper" selects local dialogs even if the upstream
513 client advertises native forms; "--ask mcp" forwards forms upstream, and
514 "auto" uses native forms when advertised. If a client claims support but
515 silently declines questions, use "helper". A decline never causes a
516 fallback prompt.
517
518 Standalone "mcp-ask-user" also supports these modes and defaults to the
519 local helper. A question is different from an approval: answering it
520 does not grant a filesystem worker any authority.
521
522 COMBINING SERVERS
523 Once the first connection works, use the multibroker to give a client
524 one connection for several servers:
525
526 mcp-multibroker --name tools --bind :31740 \
527 code 'stdio:mcp-fs --name code /home/alice/src/project' \
528 notes 'stdio:mcp-fs --name notes /home/alice/notes'
529
530 Quote each "stdio:" shell command as one argument. The broker supplies
531 the child's stdio environment and starts ordinary children lazily, on
532 first use. The explicit child names give them separate permission
533 profiles "fs-code" and "fs-notes".
534
535 Obtain the upstream HTTP URL with:
536
537 mcp-multibroker --name tools --bind :31740 --print-url
538
539 Configure this URL in place of the client's old direct connection. The
540 client can now see "code.grep", "code.read-lines", "notes.find" and
541 other prefixed tools. It does not need a separate connection to each
542 child.
543
544 For a client launching the multibroker locally, configure:
545
546 mcp-multibroker --stdio --name tools \
547 code 'stdio:mcp-fs --name code /home/alice/src/project' \
548 notes 'stdio:mcp-fs --name notes /home/alice/notes'
549
550 "--stdio" selects the upstream connection. The child commands still use
551 "stdio:"; that selects each downstream connection independently. No
552 upstream HTTP URL is needed in this case.
553
554 Discover and refresh tools
555 Ask the LLM:
556
557 Call discover-brokers and list-tools, then show me which servers
558 are available and what each is for.
559
560 "discover-brokers" returns instructions, no instructions, or an error
561 for each configured server. "list-tools" requests current tool
562 definitions; unreachable servers are omitted. A reachable server can
563 still fail later.
564
565 If the client still has an old direct tool list, "call-tool" can invoke
566 an exact prefixed name found by "list-tools". Refresh the client's MCP
567 connection if it continues to hide newly available tools.
568
569 Discovery queries configured servers and currently registered reverse
570 connections. Changing the static downstream command still requires a
571 restart.
572
573 Let a server connect to the multibroker
574 To add independently started servers without editing the multibroker
575 command, keep its HTTP/extension listener active alongside stdio:
576
577 mcp-multibroker --stdio --listen --bind 127.0.0.1:31740
578 mcp-multibroker --bind 127.0.0.1:31740 --print-url
579
580 Append an alias to the returned credential-bearing URL:
581
582 mcp-fs --connect http://127.0.0.1:31740/TOKEN/files /home/alice/project
583
584 The filesystem server initiates the TCP connection but remains the MCP
585 server. The multibroker authenticates the same token used for HTTP,
586 registers the alias and discovers the tools. A configured or connected
587 alias cannot be replaced. After disconnecting, the server retries once
588 per second for sixty attempts. Pending calls fail and are never
589 replayed. Remote registration does not grant the multibroker
590 spawned-child shutdown authority.
591
592 The hello is a raw JSON line, followed by ordinary MCP JSONL on the same
593 socket; the HTTP-shaped URL is an address and credential, not an HTTP
594 request. The bundled connector supports plain "http://" endpoints. An
595 HTTP listener is already active by default when the upstream connection
596 is HTTP.
597
598 Add an HTTP child
599 A broker can mix spawned stdio servers and existing HTTP endpoints:
600
601 mcp-multibroker --stdio \
602 code 'stdio:mcp-fs --name code /home/alice/src/project' \
603 remote https://example.org/mcp/ --bearer TOKEN
604
605 "--bearer" immediately after the HTTP pair belongs to that child.
606 "--token" before all pairs configures the multibroker's own HTTP
607 listener. They authenticate different connections.
608
609 To avoid putting a child's bearer token in the startup command, add:
610
611 [client remote]
612 bearer = TOKEN
613 timeout = 300
614
615 to the private global configuration, and omit "--bearer" from the
616 command. The prefix "remote" selects these client defaults. The
617 command-line URL still chooses the endpoint. Use the actual credential
618 accepted by that server, not the literal placeholder "TOKEN".
619
620 A token already present in a child's URL needs no separate bearer
621 option. The bundled servers use static URL-safe tokens; they do not
622 validate OAuth access tokens or implement HTTP Basic authentication. Use
623 TLS or an appropriate tunnel when credentials cross untrusted networks.
624
625 The multibroker does not put every child inside the mcp-fs sandbox. Each
626 process or remote service has its own authority and enforcement.
627
628 Add a live Vim editor
629 Install the Vim plugin using "VIM PLUGIN INSTALLATION" in mcp-vim. It is
630 included in the source distribution but is not installed by Perl's "make
631 install".
632
633 A spawned mcp-vim child also listens for editor connections. Start it
634 eagerly so Vim can connect before the first MCP tool call:
635
636 mcp-multibroker --stdio \
637 code 'stdio:mcp-fs --name code /home/alice/src/project' \
638 vim 'stdio:mcp-vim --name editor' --eager
639
640 In another terminal, obtain the editor child's URL prefix:
641
642 mcp-vim --name editor --print-url
643
644 Append the desired target name in Vim:
645
646 :Mcp http://HOST:PORT/TOKEN/my-editor
647
648 Use the actual printed prefix in place of "http://HOST:PORT/TOKEN/". Ask
649 the LLM to call "vim.targets", then "vim.state" before reading or
650 editing buffers. These tools see live, possibly unsaved buffers. Edits
651 require a current changedtick and do not save files to disk.
652
653 To pass arguments directly, use "PREFIX --- PROGRAM ARG... ---":
654
655 mcp-multibroker --stdio \
656 vim --- mcp-vim --name editor --bind :: --- --eager \
657 code --- mcp-fs --name code '/home/alice/project with spaces' ---
658
659 Only the invoking shell processes quoting. The broker passes all
660 arguments between the delimiters unchanged, including empty arguments
661 and child options. Use "stdio:COMMAND" for shell syntax or a literal
662 "---" child argument. An empty command or missing closing delimiter is
663 an error.
664
665 "--eager" belongs immediately after its stdio URL or closing "---". An
666 eager connection failure is logged; the broker does not continuously
667 restart the child. Later tool use can try connecting again.
668
669 Ask the client's human a question
670 To let the assistant ask you questions, add a question server:
671
672 mcp-multibroker --stdio \
673 code 'stdio:mcp-fs --name code /home/alice/src/project' \
674 questions 'stdio:mcp-ask-user'
675
676 The LLM can call "questions.ask-user" with a question, up to three
677 suggested answers and room for free text. For example, tell it to use
678 that tool if choosing among several possible tasks needs your input. For
679 several fields or other value types, "questions.ask-form" accepts
680 "message" and "requestedSchema" directly and returns the standard
681 elicitation response. Both tools use the same configured presentation
682 mode. Decline and cancel are distinct results; neither supplies an
683 answer.
684
685 By default the multibroker displays questions locally, using YAD or a
686 terminal. Add "--ask mcp" before the broker entries to use the client's
687 native forms, or "--ask auto" to select by advertised capability. This
688 also works with "mcp-ask-user" started separately: give that server
689 "--ask mcp" so it delegates presentation to its connecting multibroker.
690
691 "anyevent-mcp-form-elicitation" is the standalone form renderer. It
692 reads standard MCP form parameters as UTF-8 JSON on stdin and writes an
693 accept/decline/cancel response as JSON on stdout.
694 "PERL_ANYEVENT_MCP_ELICITATION_HELPER" selects a replacement executable.
695 See anyevent-mcp-form-elicitation for supported fields and mcp-ask-user
696 for question arguments and result fields.
697
698 HTTP TOKENS AND SERVER IDENTITY
699 For the ordinary bundled HTTP endpoints, a client can present an
700 accepted token in either of these ways:
701
702 POST /TOKEN/
703 POST / Authorization: Bearer TOKEN
704
705 URL tokens are path components, not browser cookies. For another
706 configured endpoint, "/TOKEN" prefixes that endpoint path. All accepted
707 tokens authenticate the same operations; they are not separate users or
708 permission levels. Permissions still govern the tool operation.
709
710 By default, the master secret and server name determine one stable token
711 and a port in 16384..32767. Changing a server's name changes its derived
712 credentials and default port. Changing or losing the master secret
713 changes all derived credentials. Keep an existing "[global]" secret when
714 editing other configuration.
715
716 To configure explicit tokens:
717
718 [instance code]
719 tokens = first-secret,second-secret
720
721 Replace those placeholders with actual unguessable URL-safe tokens.
722 Repeated "--token" options replace the whole configured list and the
723 derived default. The first token appears in "--print-url"; all are
724 accepted. mcp-vim also accepts its token set for Vim and browser
725 WebSocket connections.
726
727 If "--print-url" disagrees with the client's URL, compare the name,
728 command-line overrides, user and configuration environment with the
729 running process. The command resolves configuration; it does not ask the
730 running server which URL it uses. A changed file needs a server restart.
731
732 An Origin allowlist restricts browser origins; it does not authenticate
733 clients. A CORS preflight can succeed without a token, while the MCP
734 POST still requires one. See "AUTHENTICATION" in
735 AnyEvent::MCP::Server::HTTP for the low-level server interface.
736
737 CLIENT EXAMPLES
738 Client settings and command syntax evolve independently of this
739 distribution. These examples show the connection choices; consult the
740 linked client documentation if its interface differs. Replace
741 illustrative paths and credentials with your own.
742
743 OpenAI Codex CLI
744 For the first direct filesystem connection:
745
746 codex mcp add code -- \
747 mcp-fs --stdio --name code /home/alice/src/project
748 codex mcp list
749
750 For a multibroker connection:
751
752 codex mcp add mytools -- \
753 mcp-multibroker --stdio \
754 code 'stdio:mcp-fs --name code /home/alice/src/project'
755
756 Use "/mcp" within Codex to inspect connections. See Codex MCP
757 documentation <https://learn.chatgpt.com/docs/extend/mcp>.
758
759 Anthropic Claude Code
760 For the direct connection:
761
762 claude mcp add --transport stdio --scope user code -- \
763 mcp-fs --stdio --name code /home/alice/src/project
764 claude mcp list
765
766 Replace the launched command with the multibroker command above when you
767 want several servers. Use "/mcp" for connection status. See Claude Code
768 MCP documentation <https://code.claude.com/docs/en/mcp>.
769
770 Google Gemini CLI
771 Merge a direct server entry into "~/.gemini/settings.json":
772
773 {
774 "mcpServers": {
775 "code": {
776 "command": "mcp-fs",
777 "args": [
778 "--stdio", "--name", "code", "/home/alice/src/project"
779 ]
780 }
781 }
782 }
783
784 For a combined connection, use "mcp-multibroker" as the command and its
785 "--stdio" and prefix/server pairs as the argument array. Use "/mcp" to
786 inspect the connection. See Gemini CLI MCP documentation
787 <https://geminicli.com/docs/tools/mcp-server/>.
788
789 Hosted clients, including ChatGPT web
790 A hosted client cannot spawn your local stdio command or reach your
791 machine's loopback address directly. Run the server or multibroker in
792 HTTP mode and configure a supported tunnel or reachable endpoint.
793
794 For ChatGPT, use its custom MCP setup and, for a private server, an
795 appropriately configured Secure MCP Tunnel. Availability depends on the
796 client's plan, workspace and feature permissions. See ChatGPT custom MCP
797 servers
798 <https://developers.openai.com/api/docs/guides/custom-mcp-server> and
799 Secure MCP Tunnel
800 <https://developers.openai.com/blog/connect-private-mcp-servers-to-opena
801 i-products>.
802
803 TROUBLESHOOTING
804 The server does not start
805 Read stderr or the client's server log. Missing Perl modules, a missing
806 workdir, unsuitable utilities or an unavailable bubblewrap executable
807 can fail startup. Confirm that the client launches the same executable
808 and arguments you intended, with the expected "PATH" and Perl
809 installation.
810
811 For a local sandbox check, run from the project directory:
812
813 mcp-fs --exec-cmd workdir-read -- ls
814
815 This runs "ls" with the named grants and trusted baseline mounts,
816 without MCP or saved permission rules. A failure here can identify a
817 bubblewrap or runtime problem. It does not test the client connection or
818 approval UI. "--sandbox none" disables isolation and changes worker
819 authority; it is not a fix that preserves the same permission boundary.
820
821 The client cannot connect
822 For stdio, configure a command the client launches, rather than a URL. A
823 separately running stdio process is not the client's connection. Do not
824 put banners or diagnostics on stdout.
825
826 For HTTP, leave the server running and check its address and port.
827 "--print-url" exits without starting it. Loopback binds accept local
828 connections only; hosted or remote clients need the appropriate route or
829 tunnel. An occupied port causes a listener error, so check the server
830 log.
831
832 Authentication fails
833 Obtain the URL with the same name, bind/token overrides and
834 configuration environment as the running process. Use the complete path,
835 including any required trailing slash. A clean URL needs an accepted
836 bearer token.
837
838 A multibroker child credential is not necessarily the upstream
839 listener's credential. "--bearer" after a child pair and "--token"
840 before the pairs configure different sides of the connection.
841
842 If the server warns that it cannot save the master secret, another
843 process may derive a different token. Fix ownership and write access to
844 the private configuration. Do not replace an existing secret simply to
845 add a setting.
846
847 Connected, but there are no tools
848 Inspect the server's stderr for omitted utilities. mcp-fs's "workdirs"
849 tool reports configuration even when a utility-dependent tool is absent.
850 For a multibroker, call "discover-brokers" to see individual connection
851 errors, then "list-tools" to refresh definitions.
852
853 A third-party child might require initialization or features this client
854 implementation does not support. See AnyEvent::MCP::Client and its
855 transport documentation for limitations.
856
857 There is no approval dialog
858 First check whether the tool was denied by a saved rule or is waiting
859 for the client's own approval. An allowed operation needs no server
860 prompt.
861
862 The default helper runs on the server machine. A background service may
863 have neither a usable display nor "/dev/tty", even though your
864 interactive shell has both. Supply the appropriate display environment,
865 a usable helper, or "--ask auto" with a modern client supporting form
866 elicitation. "--ask mcp" reports an error if that support is absent.
867
868 Setting an asking mode cannot make an unsupported client display a form.
869 Check stderr and the tool error instead of assuming a missing dialog is
870 an approval.
871
872 It asks again after I chose allow
873 Allow-once covers one tool invocation, including its permission retries.
874 The next invocation asks again. Use allow-always to save a rule.
875
876 Inspect the saved rule's action, workdir and grants. Listing names and
877 reading contents are different actions. A rule for one exact workdir
878 spelling will not match a differently spelled startup argument. A
879 request for extra authority, such as networking, does not match a
880 workdir-read-only allow rule. Earlier ask or deny rules take precedence.
881
882 Confirm that the prompt's permanent rule was successfully saved and that
883 you are editing the rules for the actual child name, not merely its
884 multibroker prefix.
885
886 The worker cannot see a directory or executable
887 The worker sees granted mounts and trusted baseline mounts, not
888 everything the server process can see. Check "workdirs" for the selected
889 path, mounts and runtime paths. A symlink target outside those mounts is
890 unavailable.
891
892 For tools or libraries under "/opt", add an appropriate trusted mount as
893 shown earlier and restart mcp-fs. A configured executable path alone
894 does not mount the executable or its dependencies inside the worker. A
895 trusted mount supplies baseline access to every worker using it; a
896 writable mount likewise supplies baseline write authority.
897
898 An arbitrary command might also need its user's configuration or
899 repository credentials under HOME, or network access. Request the
900 corresponding grants when needed; do not assume "workdir-read" includes
901 them. For example, CVS over SSH can use "workdir-read" and "ssh-agent".
902 The latter includes network access, the agent socket and
903 "~/.ssh/known_hosts", without exposing private key files or the rest of
904 HOME. The broker must inherit "SSH_AUTH_SOCK" from your environment.
905 User-configured helpers outside the runtime mounts need an explicit
906 trusted mount. An explicit exec grant array replaces the default rather
907 than adding to it.
908
909 My configuration change seems to be ignored
910 Check which file and section the process actually selects. Global
911 settings use the server user's "HOME"/"XDG_CONFIG_HOME". Instance names,
912 program basenames and multibroker prefixes serve different purposes.
913
914 Restart after changing startup settings, mounts or utilities. Permission
915 rules need no restart, but their order still matters. Refresh discovery
916 after a child restart; reconnect a client that retains an old tool list.
917 "--print-url" reads the current configuration, which can differ from an
918 older running process.
919
920 The command failed, but the MCP request succeeded
921 "exec" reports exit status, signal or timeout as a normal tool result. A
922 successful MCP exchange is not a successful Unix command. Conversely, a
923 transport failure does not prove a command did nothing: it may have
924 completed before the connection was lost. Calls are not automatically
925 replayed after a transport failure.
926
927 TESTING
928 The default test level is 0. It checks protocol behaviour, permissions,
929 validation and ordinary process operation, including worker cancellation
930 and reaping. Watchdogs allow slow machines time to finish; they do not
931 make successful tests wait for the whole timeout.
932
933 prove -Ilib t
934
935 Set "PERL_ANYEVENT_MCP_TESTS" to 1 to include the extended tests:
936
937 PERL_ANYEVENT_MCP_TESTS=1 prove -Ilib t
938
939 Level 1 adds GNU find/grep/sed/patch operations, real Vim scripting,
940 browser transfer integration, short idle-lifetime tests, a helper
941 descendant holding a pipe open, and tests which deliberately wait for a
942 command timeout or cancel a form helper across several processes. Run
943 this level before releases. Values greater than 1 currently select the
944 same tests as level 1.
945
946 Missing GNU utilities or required Vim functions cause explicit skips
947 even at level 1. The permission and form UI tests use a YAD stand-in:
948 neither level requires YAD, X11 or an interactive display. The
949 filesystem tests use a bubblewrap stand-in and check arguments and
950 worker behaviour; they do not test kernel isolation. The browser tests
951 use simulated peers.
952
953 WHERE TO GO NEXT
954 For available tools and server-specific options:
955
956 perldoc mcp-fs
957 perldoc mcp-multibroker
958 perldoc mcp-vim
959 perldoc mcp-ask-user
960 perldoc anyevent-mcp
961
962 For a complete first Perl server, options, replies, permission checks
963 and asynchronous work, see "TUTORIAL" in AnyEvent::MCP::Server::Simple.
964 For the module map and shared configuration reference, see
965 AnyEvent::MCP. For permission rule details, see
966 AnyEvent::MCP::Server::Permissions.
967
968 SEE ALSO
969 AnyEvent::MCP, AnyEvent::MCP::Server::Simple, mcp-fs, mcp-multibroker,
970 mcp-vim, mcp-ask-user, AnyEvent::MCP::Server::Permissions
971