ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/AnyEvent-MCP/lib/AnyEvent/MCP/Intro.pod
Revision: 1.34
Committed: Sun Nov 8 00:34:40 2026 UTC (7 hours, 6 minutes ago) by root
Branch: MAIN
CVS Tags: HEAD
Changes since 1.33: +5 -2 lines
Log Message:
*** empty log message ***

File Contents

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