ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-MCP/lib/AnyEvent/MCP/Intro.pod
Revision: 1.2
Committed: Sun Oct 11 15:29:10 2026 UTC (3 weeks ago) by root
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3     AnyEvent::MCP::Intro - getting started with MCP servers and permissions
4    
5     =head1 DESCRIPTION
6    
7     A practical introduction to the bundled MCP servers, authentication,
8     permission rules and connecting MCP clients. For the Perl programming
9     interfaces and general configuration reference, see L<AnyEvent::MCP>.
10     This page describes how to use the machinery before taking it apart.
11    
12     =head1 GETTING STARTED
13    
14     This distribution contains an MCP client/server library and several ready-to-use
15     programs. You do not need to write Perl to use them.
16    
17     =over
18    
19     =item C<mcp-fs>
20    
21     A filesystem and command server. Each operation runs in a Linux bubblewrap
22     sandbox with only the filesystem and other capabilities approved for that
23     operation. Read, write, search, patch, path operations and command execution
24     are exposed as MCP tools.
25    
26     =item C<mcp-multibroker>
27    
28     Combines several MCP servers behind one connection. Each downstream server has
29     a prefix, so a C<file-read> tool belonging to C<files> becomes
30     C<files.file-read>. Its clients may connect over HTTP or be launched over
31     stdio. The multibroker itself can serve HTTP or stdio.
32    
33     =item C<anyevent-mcp> and C<anyevent-mcp-askpermission>
34    
35     C<anyevent-mcp> initializes private configuration and opens the rule manager.
36     C<anyevent-mcp-askpermission> asks the local user for approval; it is normally
37     started automatically when a tool needs permission.
38    
39     =back
40    
41     =head2 Start with one filesystem server
42    
43     Install this Perl distribution first. On Debian or Ubuntu, install the
44     runtime sandbox and optional graphical permission helper with:
45    
46     sudo apt install bubblewrap yad
47    
48     The executable is called C<bwrap>, although the package is C<bubblewrap>.
49     C<yad> provides graphical approval dialogs; without it, the default helper
50     tries C</dev/tty> and denies if no terminal is available. Unprivileged user
51     namespaces must be available. C<mcp-fs> also uses GNU C<find>, C<grep>,
52     C<patch> and C<sed>, and a compatible Perl interpreter. On a minimal
53     Debian installation, these can be installed with:
54    
55     sudo apt install findutils grep patch sed perl
56    
57     Tools whose required programs are missing are omitted at startup.
58    
59     Give the server one or more directories that you actually intend to make
60     available. For example:
61    
62     mcp-fs --name code --bind :31741 /home/alice/src/project
63    
64     This starts an authenticated HTTP MCP server without printing its URL.
65     C<mcp-fs --name code --bind :31741 --print-url> obtains its URL without
66     opening another listener; both invocations must use the same overrides.
67     keep it private. The same token also works in an Authorization bearer
68     header. C<--bind :0> selects an ephemeral port, for which a URL cannot
69     be predicted. The permission-rule file is printed on stderr.
70    
71     For a local MCP client that starts its servers as subprocesses, use stdio:
72    
73     mcp-fs --stdio /home/alice/src/project
74    
75     The MCP client, not a human terminal, should start this process: stdin and
76     stdout carry protocol messages. For a quick manual sandbox test without MCP
77     or permission prompting, run from the intended workdir:
78    
79     mcp-fs --exec-cmd workdir-read -- ls
80    
81     C<--exec-cmd> runs the supplied command with exactly the named capabilities,
82     without consulting saved permission rules. It is a local debugging facility.
83    
84     Within MCP, begin with the C<workdirs> tool to inspect the configured
85     workdirs and capabilities. Relative paths are resolved against the selected
86     workdir; access beyond the granted mounts needs additional permission.
87     Providing a workdir does not give arbitrary commands unrestricted host access.
88     See L<mcp-fs/SANDBOX GRANTS> and L<mcp-fs/LIMITATIONS>.
89    
90     Once the client is connected, you can just ask the LLM to use the tools,
91     for example:
92    
93     Show me the available workdirs, find the TODO comments in my project,
94     and suggest the next task. Do not modify any files.
95    
96     The client can call C<workdirs> and C<grep> itself; you need not know the
97     MCP request format or write your own integration.
98    
99     =head2 Combine servers with mcp-multibroker
100    
101     Rather than configure each MCP client with every server, configure them
102     once behind the multibroker. For example, to expose two distinct filesystem
103     servers over one HTTP endpoint:
104    
105     mcp-multibroker code 'stdio:mcp-fs --name code /home/alice/src/project' \
106     notes 'stdio:mcp-fs --name notes /home/alice/notes'
107    
108     Each C<stdio:> value is a shell command; quote it as one argument.
109     The multibroker starts the child with the correct stdio environment
110     and an alias equal to its prefix. The explicit C<--name> arguments
111     select separate C<mcp-fs> rule files; the routing alias by itself
112     does not change the filesystem server's name.
113    
114     The multibroker's C<--print-url> prints its authenticated HTTP URL. A client sees
115     tools such as C<code.file-read>, C<code.file-patch> and
116     C<notes.file-read>. The additional C<discover-brokers>, C<list-tools>
117     and C<call-tool> tools support explicit discovery and dispatch.
118     The client normally can call the prefixed tools directly.
119    
120     If the LLM is still using an old tool list after a downstream server
121     becomes available or changes its tools, simply tell it:
122    
123     Call discover-brokers and list-tools again, then use the newly
124     discovered tools.
125    
126     C<discover-brokers> connects to reachable servers and retrieves their
127     instructions; C<list-tools> requests their current tool lists. C<call-tool>
128     can dispatch a newly discovered prefixed tool even when the client has not
129     refreshed its own direct tool list yet. If the client hides or caches the
130     broker's tools, reconnect or refresh the MCP connection in that client.
131     Changing the broker's configured prefix/URL pairs requires restarting
132     C<mcp-multibroker>; discovery cannot change its command-line configuration.
133    
134     The same broker can mix remote HTTP servers with local subprocesses.
135     For example, an installation might combine office and automation tools:
136    
137     mcp-multibroker \
138     office http://localhost:8766/mcp \
139     homeassistant http://homeassistant.local:8123/api/mcp \
140     --bearer TOKEN \
141     marco http://marco.example.net:31746/COOKIE/
142    
143     Or combine a custom application server, remote machines and a third-party
144     stdio server:
145    
146     mcp-multibroker \
147     agni 'stdio:/opt/agni/bin/agni-mcp' \
148     cerebro http://cerebro.example.net:31748/COOKIE/ \
149     chrome 'stdio:npx -y chrome-devtools-mcp@latest --no-usage-statistics'
150    
151     These are illustrative hostnames and redacted credentials, not usable
152     endpoints. C<--bearer> belongs immediately after the HTTP server it
153     authenticates. A token-bearing URL already carries its credential. Never publish
154     or check in either kind of secret. The broker does not impose the C<mcp-fs>
155     bubblewrap sandbox on other servers: those processes and services have their
156     own security boundaries. A shell wrapper can use C<exec mcp-multibroker>
157     to replace itself with the broker process.
158    
159     To start the multibroker itself over stdio, let the client set
160     C<PERL_ANYEVENT_MCP_MULTIBROKER_PROTOCOL=stdio>, or use a command like:
161    
162     PERL_ANYEVENT_MCP_MULTIBROKER_PROTOCOL=stdio \
163     mcp-multibroker code 'stdio:mcp-fs /home/alice/src/project'
164    
165     The broker can also connect to existing HTTP MCP servers:
166    
167     mcp-multibroker files 'stdio:mcp-fs /home/alice/src/project' \
168     remote https://example.org/mcp/ --bearer TOKEN
169    
170     The token is a credential; avoid exposing it in shell history or process
171     arguments in a real deployment. An HTTP client can instead use
172     C<[client PREFIX]> in the private global configuration. See
173     L<mcp-multibroker> and L<AnyEvent::MCP/GLOBAL CONFIGURATION>.
174    
175     =head2 Connect an AI client
176    
177     These are examples for clients with MCP support. Paths are illustrative;
178     substitute your installed commands and real workdirs. Client interfaces
179     evolve independently of this module, so consult their documentation if an
180     option has changed.
181    
182     =head3 OpenAI Codex CLI
183    
184     Codex can start the broker locally over stdio:
185    
186     codex mcp add mytools --env PERL_ANYEVENT_MCP_MULTIBROKER_PROTOCOL=stdio \
187     -- mcp-multibroker \
188     files 'stdio:mcp-fs /home/alice/src/project'
189     codex mcp list
190    
191     Use C</mcp> within Codex to inspect connections.
192     See L<Codex MCP documentation|https://learn.chatgpt.com/docs/extend/mcp>.
193    
194     =head3 Anthropic Claude Code
195    
196     Claude Code can start the same broker:
197    
198     claude mcp add --transport stdio --scope user mytools \
199     --env PERL_ANYEVENT_MCP_MULTIBROKER_PROTOCOL=stdio -- \
200     mcp-multibroker files 'stdio:mcp-fs /home/alice/src/project'
201     claude mcp list
202    
203     Use C</mcp> within Claude Code for connection status. See
204     L<Claude Code MCP documentation|https://code.claude.com/docs/en/mcp>.
205    
206     =head3 Google Gemini CLI
207    
208     Add a local broker to C<~/.gemini/settings.json> (merge with any existing
209     settings):
210    
211     {
212     "mcpServers": {
213     "mytools": {
214     "command": "mcp-multibroker",
215     "args": [
216     "files", "stdio:mcp-fs /home/alice/src/project"
217     ],
218     "env": {
219     "PERL_ANYEVENT_MCP_MULTIBROKER_PROTOCOL": "stdio"
220     }
221     }
222     }
223     }
224    
225     Use C</mcp> in Gemini CLI to inspect the connection.
226     See L<Gemini CLI MCP documentation|https://geminicli.com/docs/tools/mcp-server/>.
227    
228     =head3 ChatGPT web
229    
230     ChatGPT is a hosted client and cannot spawn a local stdio process or
231     connect directly to a local loopback server. Start C<mcp-multibroker> in
232     HTTP mode and connect it through ChatGPT's custom MCP plugin setup.
233     For a private local server, use an appropriately configured Secure MCP
234     Tunnel rather than making the machine publicly accessible. The connection
235     is subject to the client's plan, workspace and feature permissions.
236     See L<ChatGPT custom MCP servers|https://developers.openai.com/api/docs/guides/custom-mcp-server>
237     and L<Secure MCP Tunnel|https://developers.openai.com/blog/connect-private-mcp-servers-to-openai-products>.
238    
239     =head2 HTTP authentication: URL tokens and bearer headers
240    
241     The bundled HTTP servers require an unguessable token for every MCP POST.
242     A client can supply any accepted token in one of two ways:
243    
244     POST /TOKEN/ # credential-bearing URL
245     POST / # Authorization: Bearer TOKEN
246    
247     Those paths are for the bundled servers, whose HTTP endpoint is C</>.
248     For another endpoint path, C</TOKEN> prefixes that path. URL tokens are
249     B<not> HTTP cookies: the server does not depend on browser-managed login
250     state. HTTP Basic authentication is not supported. Neither is OAuth token
251     validation; a string that looks like a JWT is still just a static token here.
252    
253     Without explicit configuration, each named server derives one stable token
254     from the private global master secret. For several tokens, configure:
255    
256 root 1.2 [instance code]
257 root 1.1 tokens = first-secret,second-secret
258    
259     or use repeated C<--token TOKEN> switches when starting the server.
260     The command-line list replaces the entire configured list, and either
261     replaces the derived default. All tokens authorize the same operations;
262     their order only decides which is printed by C<--print-url>. They are
263     not permission levels, and adding a second token does not create a
264     second user.
265    
266     In C<mcp-multibroker>, C<--token> before the downstream server pairs
267     configures the upstream listener; C<--bearer> after an HTTP child URL
268     authenticates the connection to that child. C<mcp-vim> also uses the
269     same accepted token set for its private Vim connection and browser
270     WebSocket connection.
271    
272     For example, to retrieve the URL of a running configuration without
273     starting another server:
274    
275     mcp-fs --name code --bind :31741 --print-url
276    
277     Repeat any C<--bind> and C<--token> overrides used to start that server,
278     and run the command under the same user and configuration directory.
279     C<--print-url> exits without listening. Port zero cannot be predicted
280     in advance. Extract the token from the URL when a client requires an
281     Authorization header instead.
282    
283     Protect token-bearing URLs, configuration files, shell histories and process
284     arguments. Use TLS or an appropriate tunnel across untrusted networks.
285     An Origin allowlist is a browser restriction, not a credential; accepting
286     requests from a particular origin never grants access by itself. A CORS
287     preflight can answer without authentication, but an MCP POST still requires
288     its token. Localhost has many virtues; authentication isn't one of them.
289    
290     C<stdio> uses the parent client's process connection rather than HTTP,
291     so it has no URL or bearer-header authentication. That says nothing about
292     whether a tool operation is approved: the permission system below is a
293     separate decision. For custom servers, C<mcp_start> supplies the named
294     default token; the low-level L<AnyEvent::MCP::Server::HTTP> object requires
295     explicit C<tokens> (or authentication enforced by its embedding layer).
296     See L<AnyEvent::MCP::Server::Simple> for the function interface.
297    
298     =head2 Permissions and approval dialogs
299    
300     C<mcp-fs> does not treat a connected model as fully trusted. Each tool
301     asks for the authority it needs; you can allow or deny the request once,
302     or save a rule for subsequent matching requests. Its default prompting
303     mode is C<--ask helper>, using C<anyevent-mcp-askpermission> on the
304     server's machine (YAD or C</dev/tty>). Closing the prompt denies once.
305    
306     C<mcp-fs> asks for an B<action> such as C<inspect>, C<read>,
307     C<write>, C<manage> or C<exec>. This is authorization to perform a kind of
308     operation, not a synonym for the MCP tool name: C<file-read> and C<grep>
309     both request C<read>. Independently, the worker needs B<sandbox grants>,
310     such as C<workdir-read>, C<workdir-write>, C<network> or C<world-write>.
311     The permission engine decides which grants are allowed; the worker's
312     bubblewrap sandbox must enforce that decision. Approving C<read> does not
313     approve C<write>. The authentication token gets a client to the door,
314     not through every door inside.
315    
316     For example, C<mcp-fs --name code> reads its rules from
317     C<$XDG_CONFIG_HOME/anyevent-mcp/rules-fs-code.ini>, or the corresponding
318     C<$HOME/.config> path. The following ordered rules allow reading within
319     one directory tree while requiring explicit approval for everything else
320     except execution, which is denied:
321    
322     [rule]
323     decision=allow
324     action=read
325     subject=^/home/alice/src/project/
326     sandbox-grants=workdir-read
327    
328     [rule]
329     decision=deny
330     action=exec
331    
332     Rules are tried B<in order>, stopping at the first match. Action and
333     subject match literally unless the matcher starts with C<^>, in which
334     case it is a Perl regular expression. A missing subject matches all
335     subjects. Allow rules must specify C<sandbox-grants>, and only authorize
336     requests whose needed grants are covered, including implied grants.
337     For example, C<workdir-write> implies C<workdir-read>, but C<network>
338     remains a separate grant. An explicit C<ask> rule can force a prompt;
339     otherwise a request not covered by any rule is prompted automatically.
340    
341     When prompted, choose allow or deny, once or always. Permanent choices
342     are appended as rules using an offered scope such as the exact path,
343     containing directory or workdir. Broader scopes are not inferred from
344     good intentions. A worker that needs several paths checks each, and
345     its effective sandbox grants are restricted to those allowed for all
346     of them. The accepted rule file is reread for subsequent checks without
347     restarting the server. Editing it changes policy, not the token.
348    
349     For a client that supports the newer MCP form-elicitation protocol, try:
350    
351     mcp-fs --ask auto --stdio /home/alice/src/project
352    
353     C<--ask auto> uses MCP elicitation when the client advertises the necessary
354     support, otherwise the local helper. C<--ask mcp> requires elicitation and
355     fails if it is unavailable; it does not silently fall back. Not all MCP
356     clients or versions support the required input/continuation flow, even if
357     they support ordinary tool calls. Use client-side approval only if that
358     client is a trusted authority to grant access; otherwise keep the prompt
359     on the server machine. For an ordinary stdio broker configuration, put
360     the chosen option in the child command:
361    
362     mcp-multibroker files \
363     'stdio:mcp-fs --name files --ask auto /home/alice/src/project'
364    
365     Use C<--name NAME> to choose the filesystem server's rules file,
366     independently of the multibroker's routing prefix. Rule files must be
367     private and owned by the server user. They can be edited directly, or
368     managed with C<anyevent-mcp rules FILE>. Review persistent rules rather
369     than granting C<world-write> casually. For worker sandbox details see
370     L<mcp-fs/SANDBOX GRANTS>; for the programming interface and rule syntax
371     see L<AnyEvent::MCP::Server::Permissions>.
372    
373     =head2 Further documentation
374    
375     perldoc mcp-fs
376     perldoc mcp-multibroker
377     perldoc anyevent-mcp
378     perldoc AnyEvent::MCP::Server::Simple
379     perldoc AnyEvent::MCP::Server::Permissions
380    
381     The programs describe their own command-line options. If a client reports
382     no tools, first check that the selected program starts and that its required
383     utilities are detected. Stdio servers must not print diagnostics or banners
384     to stdout. For HTTP, check that the client can reach the configured URL and
385     has the correct authentication credentials.
386    
387     =head1 SEE ALSO
388    
389     L<AnyEvent::MCP>, L<AnyEvent::MCP::Server::Simple>,
390     L<AnyEvent::MCP::Server::HTTP>,
391     L<AnyEvent::MCP::Server::Permissions>, L<mcp-fs>, L<mcp-multibroker>
392    
393     =cut