AnyEvent-MCP
view release on metacpan or search on metacpan
bin/mcp-vim view on Meta::CPAN
this exact command in this editor, any Ex command in this editor, or any
Ex command in all current and future editors. Exact means the complete
command string, including whitespace and newlines. Such a rule applies to
all buffers in that editor: approving C<update> is not approval for only
the buffer used in the original request. Commands can invoke mappings,
functions and autocommands whose behaviour changes independently of the
command text.
The result is C<{output: STRING}>, containing captured Vim messages.
An error is returned as a tool error; effects before that error remain.
Use noninteractive commands. Message capture suppresses ordinary message
display, but does not prevent commands from prompting or blocking Vim.
Request cancellation stops waiting for the reply, not a command already
running in Vim. If a command exits Vim, the connection can close before
a reply is delivered.
=head1 VIM PLUGIN INSTALLATION
The Vim plugin is included in the AnyEvent::MCP source distribution as
C<vim/plugin/mcp-vim.vim>. Installing the Perl distribution does not install
the Vim plugin. From the source distribution, install it yourself:
mkdir -p ~/.vim/plugin
cp vim/plugin/mcp-vim.vim ~/.vim/plugin/mcp-vim.vim
Alternatively, download the published plugin:
mkdir -p ~/.vim/plugin
wget -O ~/.vim/plugin/mcp-vim.vim \
https://dist.schmorp.de/mcp-vim/1/mcp-vim.vim
The C</1/> is the major version of the private Vim/broker protocol, not
the MCP protocol or the Perl distribution. Restart Vim after installing
or updating the plugin.
Connect a Vim instance with C<:Mcp URL>, appending the desired target name
to the broker URL (which C<mcp-vim --print-url> can show):
:Mcp http://HOST:PORT/TOKEN/TARGET
To avoid typing the URL prefix repeatedly, configure
C<g:mcp_broker_url> in your vimrc:
let g:mcp_broker_url = 'http://HOST:PORT/TOKEN/'
Then use C<:Mcp TARGET>, with the target name alone.
Distinct Vim instances requesting the same target name receive suffixes
such as C< #2>. Reconnecting the same instance replaces its connection and
keeps its assigned name. Use C<targets> to obtain the actual names.
The Vim plugin uses a private protocol, not MCP. Its initial raw JSON line is
C<["mcp-vim", cookie, major, minor, target, instance_id]>; subsequent messages
use Vim's ordinary JSON channel envelope. The broker accepts clients with the
same major version and a minor version no newer than its own. Keep the broker
and plugin versions compatible when updating them.
The broker itself can connect to a multibroker using
C<--connect http://host:port/token/alias>. Its own TCP listener remains active
for Vim and browser connections. The multibroker URL and the Vim broker's own
listener URL have independent credentials.
=head1 CONNECTIONS AND AUTHENTICATION
By default, the broker derives a stable port in the 16384..32767 range
from its service-instance name, defaulting to C<default>. Managed users
have individually derived tokens. All enabled users may authenticate MCP
requests, but only C<connect_user> (default C<default>) may register Vim
editors or XPCSE WebSockets. Configured C<tokens> or repeated C<--token>
options replace managed credentials and admit those explicit tokens for all
connection types. Keep tokens private.
By default the TCP listener binds IPv4 loopback on the name-derived port.
C<bind> in C<[instance NAME]> or C<--bind> overrides the address and port.
C<--stdio>, or C<PERL_ANYEVENT_MCP_MULTIBROKER_PROTOCOL=stdio>, additionally
serves MCP over stdin/stdout. The TCP listener remains active. In this mode
the process exits after stdio closes and pending responses have drained.
C<--print-url> prints enabled user URLs, annotating the connect user;
C<--print-url=USER> selects one. Neither starts a listener. Normal startup does not print
the credential. Use the same C<HOME> and C<XDG_CONFIG_HOME> as the
running broker, for example when checking the URL of a systemd service
account. Changing the global master secret changes derived tokens and
invalidates URLs using those tokens. Explicitly configured tokens are
independent of the master secret.
=head1 PERMISSIONS
MCP tool calls require permission independently of connection authentication.
C<read> covers C<targets>, C<state>, C<read-lines> and C<grep>.
C<write> covers C<apply-diff>, C<substitute>, C<undo>, C<redo> and C<set-cursor>, including
changes to the visible editor position. C<save> authorizes the C<save> tool and is
independent of C<read> and C<write>. C<open> independently authorizes loading
files by pathname. C<exec> authorizes the unrestricted
C<ex> tool. Neither C<read> nor C<write> implies C<exec>, or each other.
Explicit all-action rules also match C<exec>. Dedicated
editing tools leave buffers unsaved; C<save> saves explicitly, and Ex
commands can save files or perform other arbitrary work.
Permission prompts offer the selected editor (all its buffers), or all
editors including future connections. Listing target names has its own
scope. Rules identify editors by their assigned target names, not connection
IDs; a saved rule also applies to a later editor using that name.
Buffer filenames do not restrict these grants.
C<apply-diff> attaches display-only C<View patch> details containing the
editor name, buffer number and supplied diff. YAD offers a separate viewer;
terminal and native MCP prompts show a bounded preview inline. These details
do not narrow a saved editor-wide write grant.
Rules are stored in
C<$XDG_CONFIG_HOME/anyevent-mcp/rules/vim-NAME.ini>, or the corresponding
C<$HOME/.config> path. C<NAME> is the service-instance name. For example,
C<mcp-vim> uses C<rules/vim-default.ini>. Subjects are C<target:TARGET>
for read/write access to an editor and C<targets> for discovery. Ex subjects
are C<ex:JSON_TARGET:JSON_COMMAND>, where both JSON values are strings.
The helper offers exact and editor-wide matchers; there is no need to
write their quoting by hand. An omitted subject still matches all subjects.
An allow rule needs an empty C<sandbox-grants> value:
[rule]
decision=allow
action=read
subject=target:my-editor
sandbox-grants=
By default, questions go to the local permission helper. C<--ask tty> and
C<--ask yad> force the built-in terminal or YAD interface without fallback.
Use C<--ask mcp>
( run in 1.797 second using v1.01-cache-2.11-cpan-3f962061493 )