While we're here, also add `brew tests --no-parallel` which I relied
on during testing.
Pretty much anywhere we rely on a stubbed formula on disk to work: we
need to disable the API.
Instead of repeatedly outputting the same identical messages across
multiple packages and repeating them all for every package after they
were all installed: just output the identical messages in the final
caveats output instead.
This was more painful that I expected but will allow `brew bundle sh`
and `brew sh` to use the user's configuration but use our custom prompt
for Bash and ZSH.
Add a new `brew mcp-server` command for a Model Context Protocol (MCP)
server for Homebrew. This integrates with AI/LLM tools like Claude,
Claude Code and Cursor.
It currently supports the calls needed/used by the MCP Inspector and
Cursor (where I've tested it).
It provides as `tools` the subcommands output by `brew help` but should
be fairly straightforward to add more in future.
It is implemented in a slightly strange way (a standalone Ruby command
called from a shell command) as MCP servers need a faster startup time
than a normal Homebrew Ruby command allows and fail if they don't get
it.
There are a few Ruby libraries available but, given how relatively
simplistic the implementation is, it didn't feel worthwhile to use and
vendor them.
Inspired by curl's blog post, [Detecting malicious Unicode][1], this likely captures most if not all cases and nudges the user toward supplying IDNs with punycode.
A possible improvement would be telling the user exactly what punycode domain to use instead, but that may require another library as I can't quickly find something built into the Ruby stdlib that handles punycode encoding.
[1]: https://daniel.haxx.se/blog/2025/05/16/detecting-malicious-unicode/
Co-authored-by: Štefan Baebler <319826+stefanb@users.noreply.github.com>
The `Bitbucket` strategy checks download or tag pages but the content
is now fetched separately on page load, so the strategy is failing for
all related formulae. This updates the generated strategy URLs to
fetch the page content instead, which works as expected.