Revision history for AnyEvent::MCP

0.9   Tue 10 Nov 2026 17:21:58 CET
	- build mcp-fs host mounts parent-first and restore protected private
	  mounts afterward: support / and /etc as workdirs without writing
	  host passwd, keep root-write writable, and handle symlinked /var/tmp
	  mount destinations locally and remotely.
	- retire mcp-webbrowser tab-specific saved permission rules when tabs
	  explicitly disconnect or stay disconnected for five minutes;
	  retain site-wide and all-tab rules.
	- split mcp-webbrowser exec permissions into independent tab,
	  JavaScript/operation and origin dimensions. Default persistent JS
	  approvals to this tab, any JavaScript, and this origin. Old combined
	  match.subject execution grants no longer match and must be approved
	  again; they cannot silently broaden authority.
	- fix Vim stdio core test when "." is absent from Perl's @INC by
	  explicitly do-loading ./bin/mcp-vim (seen in CPAN Testers reports).
	- raise mcp-imap messages page and explicit UID batch limits from 100
	  to 1000, with page size default 100 and matching tool schemas.
	- refuse mcp-imap mailbox DELETE when STATUS reports messages;
	  expunge first or explicitly pass force to delete a nonempty mailbox.
	- move INI parsing from AnyEvent::MCP into Config, add canonical
	  serializer and merge_sections utility. Shared grammar now handles
	  global settings, IMAP accounts and ordered permission rules; replace
	  create-user/revoke-user's independent line-editing parser with
	  Config load/modify/save under the existing lock. Rewrites normalize
	  formatting and discard comments; master-secret append is unchanged.
	- split Config construction from loading and secret initialization;
	  global_config() is the initialized cached singleton, while new
	  has no file side effects and load/ensure_secret are explicit.
	  Make anyevent-mcp init idempotent and fail on secret persistence errors.
	- send 30-second elapsed-time progress for outstanding tool calls,
	  forward downstream progress through mcp-multibroker, and stream
	  request-scoped notifications over modern HTTP POST/SSE before the
	  final result, retaining plain JSON for calls without notifications.
	- make mcp-imap messages.more indicate any remaining search work,
	  including sparse UID ranges; document next_cursor as authoritative
	  and recommend threads for targeted whole-mailbox lookups.
	- eliminate the last utf8::is_utf8-based encoding decision in OAuth2:
	  form values are Unicode text encoded to UTF-8 before percent escaping;
	  decode redirect and persisted refresh-token bytes explicitly.
	- centralize UTF-8 configuration file I/O in file_load/file_save:
	  files contain UTF-8 bytes, parse_ini handles Unicode text, and all
	  config, rules and IMAP callers share the same conversion boundary.
	  Keep the atomic byte-oriented file_replace for JSON and raw streams;
	  preserve raw passwords and Base64/hex-encoded binary secrets.
	- load Encode::MIME::Header explicitly in the mcp-imap worker; only
	  mcp-imap requires it, not other AnyEvent::MCP components.
	- decode RFC 2047 encoded subject and address display fields in
	  mcp-imap ENVELOPE summaries; include attachment names, MIME types,
	  sizes and part numbers in read-only previews without extra FETCHes.
	- make mcp-fs remote subprocess framing byte-only: explicitly UTF-8
	  encode MCP argv and Unicode paths at their source, preserve raw OS
	  executable/env paths and binary stdin, reject non-octet frame fields;
	  add remote and VCS Unicode path/argv regressions.
	- log idle IMAP keepalive failure details at trace and suppress only
	  IMAPTalk's raw warning for our expected timeout exception.
	- register installed optional Encode::HanExtra, Encode::JIS2K and
	  Encode::EUCJPASCII charsets for mcp-imap MIME decoding; advertise
	  them as runtime suggestions, not dependencies.
	- split distribution tests into core cNN_ files run by default and
	  extended eNN_ files skipped without PERL_ANYEVENT_MCP_TESTS=1;
	  add independent core filesystem smoke tests while retaining the full
	  integration and failure-injection suite for development and releases.
	- include mailbox, destination, operation, batch size, paging position
	  and bounded SEARCH criteria in mcp-imap request logs, without
	  logging message bodies or UID lists.
	- keep remote filesystem tests valid with long CPAN tester Perl paths:
	  the mock rsh checks the short loader overhead without imposing
	  an artificial 256-byte limit on the executable pathname.
	- shorten mcp-fs remote bootstrap: embed the launcher byte length with
	  sprintf and append source directly via sysread without extra argv.
	- raise sort_create/sort_page UID page maximum from 100 to 1000,
	  keeping the default at 100 and leaving message fetching and MOVE
	  batches capped at 100.
	- enable multibroker-managed idle exit in mcp-http and mcp-ask-user
	  after 300 seconds, and mcp-imap after 3600 seconds (mcp-fs already
	  supported 300 seconds). Retain ask-user continuations; disposable
	  IMAP SORT snapshots are lost on idle exit. Retry declined idle
	  shutdown after the interval.
	- add worker-local immutable UID SORT (SUBJECT DATE) snapshots for
	  subject-grouped classification: sort_create returns the first 100
	  UIDs, sort_page pages without re-sorting, sort_discard frees the
	  snapshot; one snapshot per worker, invalidated on restart.
	- expose read-only UID THREAD ORDEREDSUBJECT through mcp-imap:
	  group by base subject with optional SEARCH filter and UID range,
	  retaining the complete nested server order without pagination.
	- keep mcp-imap connections alive with an idle NOOP (250 seconds by
	  default, configurable via --keepalive, 0 disables); stop pinging
	  on failure, and reconnect on the next tool call without retrying
	  interrupted operations.
	- allow shell-friendly instance names (ASCII alphanumerics, underscore,
	  hyphen, dot, @ and +), with separate strict managed-user names.
	- fold small state-file locking and atomic replacement helper into
	  MCP.pm instead of a separate AnyEvent::MCP::File module.
	- make --ask a shared common option, with per-option exclusion;
	  add --ask none to deny unresolved permissions and decline
	  downstream elicitation without prompting.
	- document mcp-imap login keys individually in --help and manpage;
	  support tls connect/starttls/none (including explicit unencrypted IMAP)
	  and reset default ports on TLS mode changes.
	- report LOGINDISABLED with no supported SASL mechanism cleanly on
	  IMAP password login, without obscure Authen::SASL warnings.
	- add mcp_permissions to Simple: default permission engine, explicit
	  object or explicit undef; apply --ask and automatic rule overrides
	  centrally without dropping application-supplied automatic rules.
	- give mcp-fs writable private /tmp and /var/tmp (mode 1777) even
	  with world-read; only shared-tmp or world-write exposes host
	  temporary directories. Make world-write formally imply shared-tmp
	  for permission checks; document the private/host lifetime distinction.
	- add read-only mcp-imap previews for 25 UIDs, with bounded partial
	  MIME decoding, HTML link preservation and grouped IMAP FETCH calls.
	- allow mcp-imap messages to fetch selected UIDs without SEARCH.
	- actually truncate bounded IMAP part/raw responses to max_bytes,
	  not just flag them as truncated.
	- use a 15-second HTTP read-inactivity timeout by default, suspended
	  while processing complete requests; respect explicit handle rtimeout.
	- load MIME::Base64 in the HTTP server itself for encoded modern
	  Mcp-Name headers, without depending on the HTTP client loading it.
	- log ordinary HTTP 404 responses at trace rather than warn,
	  including GET /; keep other HTTP rejection warnings.
	- return 404 to GET / even when / is the MCP POST endpoint; drop
	  the unhelpful connection object address from HTTP rejection logs
	  while retaining the remote address and sanitized URI.
	- reuse the latest saved per-dimension scope as the next permission
	  rule editor's default where offered, otherwise keep the original
	  conservative choice; native, YAD and terminal forms agree.
	- handle the common token-only HTTP endpoint in warning logs:
	  redact known tokens without misclassifying unrelated paths.
	- include bounded, JSON-escaped request paths in rejected HTTP request
	  warnings; omit queries and redact configured and attempted URL tokens.
	- show captured helper status, stderr and stdout when the permission
	  UI test fails, and report remote file-patch results and file content
	  when the mock remote filesystem test fails (CPAN Testers diagnostics).

0.82  Fri 06 Nov 2026 15:53:46 CET
	- add a first-permission-dialog walkthrough to Intro.pod, explaining
	  one-time versus persistent grants, rule scopes and exec stdin risks;
	  correct its description of logical workdir IDs.
	- add common repeatable -s/--set KEY=VALUE process-local overrides
	  for trusted instance configuration, after program/instance defaults.
	- key remote mcp-fs host permissions by --host alone, independent of
	  --rsh; add independent local/remote host scopes (this host by
	  default, or all hosts), retaining old unscoped saved rules.
	  Workdir scopes remain plain paths, independent of host.
	- omit single-choice permission scope selectors from native, YAD and
	  terminal rule dialogs, automatically retaining the sole match in
	  saved rules without broadening their applicability.
	- log rejected HTTP requests (status 400 and above) with method,
	  status and peer information, without leaking URL tokens; demote
	  ordinary connection/TLS errors to trace.
	- do not warn on routine GET / requests; keep the normal 404
	  response without exposing a server-identification page.
	- preserve mcp-vim subprocess stderr when its JSONL initialization
	  fails, instead of hiding the failure behind EOF and SIGPIPE.
	- bootstrap remote mcp-fs over a short Perl command, streaming the
	  launcher source over stdin. Avoid rsh command length limits and
	  preserve worker input across exec by using exact sysread.
	- format mcp-fs sandbox grants, tools, trusted configuration keys
	  and permission action classes as individually searchable POD items.
	- give the mock remote filesystem test its running Perl interpreter
	  explicitly, rather than assuming it is in a fixed Unix PATH.
	- avoid locale-dependent TCP error strings in reverse-connection tests,
	  and skip mcp-imap provider CLI tests when optional fork modules
	  are unavailable while retaining standalone provider parser tests.

0.81  Thu 05 Nov 2026 04:51:59 CET
	- keep OAuth2 tests working without optional Mail::IMAPTalk,
	  IO::Socket::SSL or Authen::SASL; skip only worker-specific checks.
	- support optional `mount-try.SUFFIX = ro:/path` or `rw:/path` in
	  mcp-fs configuration. Pass these directly as bubblewrap
	  --ro-bind-try/--bind-try for each invocation, without startup path
	  checks, locally and remotely; required mount.* entries are unchanged.
	- support one remote host per mcp-fs instance with -h/--host and
	  -e/--rsh; resolve remote workdirs and available tools in a single
	  startup probe, then execute existing workers through a binary-framed
	  remote Perl launcher without installing any MCP modules remotely.
	- use logical absolute pathnames (without resolving symlinks) as compact
	  workdir IDs across hosts; qualify remote permission scopes independently.
	  Named profiles remain shared between instances. Report cached remote
	  VCS markers and remote umask.
	- reserve -h for application-specific options; --help remains common.
	- test remote workers, external GNU utilities, permission isolation,
	  shell argument quoting and startup probing using a mock remote shell
	  and bubblewrap, including unsandboxed/auto behavior. Verify matching
	  workdir IDs for identical logical paths across local and remote
	  instances.
	- make mock remote-agent tests independent of a local SSH_AUTH_SOCK
	  inherited from the test runner (including CPAN Testers).
	- document --eager when starting mcp-webbrowser through multibroker;
	  defer possible downstream preferences for --eager and --hidden.

0.8   Thu 05 Nov 2026 01:52:48 CET
	- INCOMPATIBLE CHANGE: due to the added user management, existing
          url tokens have been invalidated.
        - limit distribution permission normalization to its staging
          directory, and supply proper CPAN author and abstract metadata.
        - give shared command-line switches their own reference in
          Server::Simple; use individually indexed POD items for executable
          options and application-specific shared-option behavior.
        - refresh the introductory guide and mcp-imap/mcp-http manuals
          with first-use workflows, OAuth2 setup, mailbox/search examples
          and reverse-TLS troubleshooting; correct stale retry documentation.
        - extend mcp-imap SEARCH filters with recursive AND/OR/NOT, header,
          text/body, date, size and flag criteria; use explicitly quoted
          IMAP arguments and bounded filter complexity.
        - capture deliberately triggered connection errors in test assertions,
          avoiding noisy successful test runs.
        - expose IMAP LSUB to inspect subscribed mailboxes, alongside
          subscribe/unsubscribe; return the same format as LIST.
        - remove superseded IMAP OAuth provider and pagination prototypes
          and their obsolete reference tests.
        - defer outgoing mail submission research (mcp-smtp or mcp-imap)
          in TODO.md.
        - retry reverse connections only for TCP connection refusal and
          unexpected disconnects; report and stop on other TCP errors or
          TLS handshake/verification failures.
        - force scalar context when checking Mail::IMAPTalk results;
          list context truncated LIST responses and could corrupt SEARCH
          results. Test with context-sensitive IMAP mocks.
        - report HTTPS reverse-connection handshake failures rather than
          silently retrying; send credentials only after verified TLS succeeds.
        - omit pointless mailbox permission dimension for mcp-imap mailboxes.
        - clarify expected OAuth redirect error page and account selection.
        - implement mcp-imap OAuth2 authorization-code login with PKCE,
          human-pasted headless browser redirect, HTTPS token exchange,
          refresh-token persistence/rotation and IMAP SASL XOAUTH2.
          Keep interactive credentials outside MCP tools and argv.
        - omit unnecessary shell quotes in mcp-imap providers commands.
        - expand mcp-imap providers with Thunderbird ISPDB domain search,
          provider-hosted HTTPS autoconfig lookup and ISPDB fallback,
          password-based IMAP alternatives and provider setup instructions;
          continue printing optional OAuth configuration without saving it.
	- add per-downstream --hidden to mcp-multibroker, omitting a
	  server's tools from normal discovery while retaining explicit
	  list-tools, discover-brokers and call-tool access.
	- number the user management test consecutively as t/27_users.t.
	- tidy Perl import grouping, internal comments and source layout
	  in the command-line tools and library modules.
	- stop imposing an IMAP account file mode check; access is governed
	  by ordinary filesystem permissions.
	- use the permission engine's literal matching convention for exact
	  user identities and test positive permission-scope validation.
	- reject invalid browser WebSocket credentials via the documented
	  handshake exception interface, producing one specific warning.
	- apply the same handshake rejection handling to Vim WebSocket
	  connections, including peer and invalid-token/path warnings.
	- document user-management scopes and URL examples in command help.
        - add scoped, revocable MCP users with HKDF-derived credentials,
	  an implicit global default user, and atomic user management;
	  list effective user URLs with --print-url[=USER], also accepting
	  --print-urls, without binding the advertised listener port.
	- associate HTTP credentials with per-request users, bind user
	  identity to persistent permissions and permission continuations,
	  and delegate original users through trusted multibrokers.
	- select the effective connect_user (default: default) for reverse
	  MCP, private Vim and browser connections, independently of normal
	  authenticated HTTP tool calls.
	- treat empty directory paths as "." in mcp-fs list, find, grep and
	  VCS cwd, without accepting empty filenames.
	- support opportunistic HTTP/HTTPS and reverse MCP connections on the
	  same listener, TLS certificate/key CLI options, and dual URL discovery;
	  support verified HTTPS for outgoing reverse connections.
	- treat idle HTTP disconnects as normal EOF while retaining errors
	  for clients disconnecting during request headers or bodies.
	- identify failing MCP connections by client name, remote address
	  and connection id, including modern per-request client metadata.
	- trace local multibroker prompt starts, outcomes and cancellations
	  with elapsed time to diagnose disappearing permission dialogs.
	- use an 8 MiB default MCP message size across JSONL and HTTP
	  clients and servers, allowing large base64 tool requests through
	  mcp-multibroker; log server transport errors at warn level
	  instead of silently closing connections.
	- load AnyEvent::Log at compile time so its format_time call is parsed
	  as a function, fixing activity logging on Perl 5.10.

0.71  Fri 30 Oct 2026 18:01:51 CET
	- make multibroker-spawned children ask for permissions through MCP,
	  independently of the multibroker's own permission prompt mode.
	- log VCS backend and a bounded, JSON-quoted preview of filenames for
	  vcs-diff, vcs-status and vcs-log.
	- load only core modules in t/00_load.t; optional IMAP dependencies
	  are tested separately when available.
	- let the fake bubblewrap test use the host temporary directory on
	  systems without /tmp (notably Termux).
	- suppress Perl startup locale warnings in sandbox workers when
	  the requested C.UTF-8 locale is unavailable.
	- canonicalize temporary test paths to match mcp-fs on systems with
	  symlinked temp directories; diagnose failing filesystem assertions.
	- test SSE notification ordering at client delivery rather than
	  server enqueue time, avoiding a network scheduling race.
	- diagnose failing multibroker HTTP integration tests with preflight
	  responses, RPC results and bounded server startup diagnostics.

0.7   Fri 30 Oct 2026 14:56:18 CET
	- WARNING: mcp-imap is unfinished and has not been tested against a real IMAP server.
	- INCOMPATIBLE CHANGE: rules have changed, old rules will be erased.
	- declare the same license terms as Perl itself in distribution metadata.
        - new mcp servers in this release: mcp-http
	- accept optional dimension default matcher for persistent-rule prompts;
	- clarify that mcp-fs exec has private /tmp by default; shared-tmp
	  exposes host /tmp and is not needed for ordinary temporary files or IPC.
	- add mcp-fs vcs-log for Git, SVN, CVS and Mercurial, reusing bounded
	  output and dedicated permission actions; SVN log receives network
	  and SSH-agent grants alongside CVS operations.
	  mcp-webbrowser prefers any JavaScript in the current tab, while the
	  independent origin dimension remains scoped to the current origin.
	- log mcp-http requests with their method and a sanitized URL preview;
	  identify mcp-http/$VERSION in User-Agent unless overridden by the caller.
	  Allow generic key=value context in the shared mcp_log_request formatter.
	- silently treat invalid saved permission-rule files as empty, prompting
	  instead of aborting broker startup; subsequent saves replace the old file.
	- add mcp-http for arbitrary HTTP methods with URL-scoped approvals,
	  caller-managed cookie jars, bounded bodies and text grep/regex/substitution.
	  Disable redirects, retries and proxies; verify HTTPS certificates.
	- derive browser permission origins from reported URLs, not a new
	  userscript field; keep older browser clients able to execute with
	  origin-scoped permissions.
	- accept compatible browser-protocol minor versions; return empty
	  operation discovery for 1.0 clients instead of disconnecting them.
	  Direct rule saves no longer perform semantic validation.
	- replace special-case subject, origin and workdir permission scopes with
	  named dimensions: metadata-driven prompts, generic match.NAME rule keys,
	  and engine-enforced matcher choices. Reject old request and rule fields;
	  no conversion or backward-compatible rule loading.
	- preserve selected origin scopes when external permission helpers
	  forward persistent decisions through native MCP elicitation.
	- add origin-scoped MCP permission rules, selectable independently of
	  code/tab scopes; mcp-webbrowser derives browser origins for
	  JavaScript and tab operations, with exact, any-port and any-origin
	  choices. Existing rules without origins continue to match all origins.
	- use POSIX::uname instead of nonportable hostname -f for the XPCSE
	  browser nickname, consistent with HTTP URL wildcard host selection.
	- make form helper test run via explicit ./ path, avoid early HTTP
	  timer races, and test filesystem discovery with optional tools absent.
	- report browser protocol rejections through bounded WebSocket close
	  reasons; show abnormal disconnects in the userscript console and toast.
	- document browser wire-protocol minor-version compatibility: accept
	  compatible older and newer clients without breaking base functionality.
	- remove the obsolete private stdio permission-result bridge from
	  mcp-multibroker; use ordinary form elicitation.
	- add per-tab operation discovery and calls to mcp-webbrowser, with
	  per-tab routing, ordinary MCP permissions and browser protocol 1.1;
	  the userscript initially advertises no extra operations.
	- make the unsandboxed-warning test tolerate diagnostic output from
	  non-GNU utility probes (FreeBSD and BusyBox).
	- add mcp-imap with one named password-authenticated account per instance,
	  bounded UID search, MIME reads, explicit mailbox/message mutations,
	  UIDPLUS-only targeted expunge, forked worker and MCP permissions.
	- propagate XPCSE save response ETags back to Vim session metadata;
	  make stale upload HTTP status an editor error.
	- require GNU sed in worker tool discovery; report missing-Perl diagnostics in tests.
	- xpcse: forward Vim's :write! flag through mcp-vim to browser
	  uploads, without changing upload behavior yet.
	- recommend rather than require WebSocket modules: only mcp-vim and
	  mcp-webbrowser use them; mcp-vim loads them only for browser clients,
	  and tests skip optional WebSocket coverage when unavailable.

0.65  Fri 23 Oct 2026 22:41:32 CEST
	- fix mcp-webbrowser userscript title indicator duplicating prefixes on empty titles.
	- use built scripts in make test PATH, avoiding source shebangs and
	  accidentally installed helpers in rule management tests.
	- clarify browser execute code wrapper and reject function/symbol return
	  values instead of silently converting them to null.
        - fix many bugs in the testsuite.

0.62  Thu 22 Oct 2026 13:32:52 CEST
	- INCOMPATIBLE API CHANGE: mcp_getoptions now returns a hash reference instead of
          a key/value list.
	- Simple accepts server_name/server_version independently of the local
	  instance name, leaving server_info as an unmodified protocol override.
	- query multibroker children in parallel for tool and broker discovery,
	  preserving tool order and returning partial results after 15 seconds
	  instead of blocking on an unresponsive child.
	- accept a missing trailing slash on HTTP MCP endpoint URLs, working
	  around Claude's MCP connector wrongly dropping it from the configured URL,
	  thus corrupting it.
	- allow omitted ports in reverse extension URLs, defaulting to port 80.
	- fix MCP client/server version fields serialized as JSON numbers in 0.61.

0.61  Thu 22 Oct 2026 08:57:42 CEST
	- resolve bind hostnames via AnyEvent::Socket instead of Socket::getaddrinfo.
	- honor user-selected file permissions and preserve them across replacements.
	- fix permission test fixture grants.
	- fix activity log timestamp formatting on older perl versions.
	- correct multibroker test tool count (including meta-instructions).
	- fix perl 5.12 syntax errors in mcp-fs and mcp-vim.

0.6  Wed 21 Oct 2026 20:43:20 CEST
	- 34k LOC of pure llm madness. but seems to work. yay.

0.0  Sat 03 Oct 2026 07:29:39 CEST
	- original version, an AnyEvent::HTTP clone.
