X

NAME

MCP::Server::Tool::Web::X - the typed failures thrown by the web tool pack

SYNOPSIS


use MCP::Server::Tool::Web::X;

# The tool surface catches the base class and reports it as a tool error;
# everything else is a bug and should keep travelling.
{
    CATCH {
        when X::MCP::Server::Tool::Web {
            return %( isError => True, content => [ { type => 'text', text => .message } ] );
        }
    }
    # ... a fetch, a crawl, a grep ...
}

Reacting to particular failures rather than to all of them:


CATCH {
    when X::MCP::Server::Tool::Web::Blocked {
        # .address-class is 'loopback', 'private', 'metadata', ... — the
        # refusal is teachable without re-reading the message.
        note "SSRF floor said no: {.address-class} at {.address}";
        note "the operator could permit it with {.config-key}";
    }
    when X::MCP::Server::Tool::Web::BadUrl {
        note "bad URL ({.reason}): {.url}";
    }
}

DESCRIPTION

Every failure this distribution raises on its own behalf is an X::MCP::Server::Tool::Web, so one CATCH arm separates "the web request went wrong" from "the code around it went wrong". The tool handlers catch the base class and turn it into an MCP isError result; nothing else is caught, so a genuine bug still surfaces as a bug.

Two properties are enforced across the whole family, because the consumer of these messages is a language model that has to decide what to do next:

  • Every .message names the rule that refused the request — not "denied" but "private address (RFC 1918)", "port out of range", "robots.txt Disallow: /private".

  • Every .message names the configuration key that would change the answer, or says plainly that no key would. A refusal an operator cannot act on is a support ticket; a refusal that names allow-loopback is a one-line fix.

The classes are declared as plain global classes — no unit module, no is export — exactly the way Rakudo core declares X::AdHoc. is export on a nested-name class exports its leaf name too, which makes two distributions that both ship, say, an X::…::Transport impossible to import together. Consumers use this file and refer to the full names.

The failures

  • X::MCP::Server::Tool::Web::BadUrl — the URL was refused on its shape alone (scheme, credentials, obfuscated host, port range). No allow-list rescues these; they are refused before anything is resolved or connected.

  • X::MCP::Server::Tool::Web::Blocked — the address behind the URL is one the SSRF floor will not connect to. Carries the host, the address, the classification and the permitting config key.

  • X::MCP::Server::Tool::Web::TooManyRedirects — the hop budget ran out. Carries the whole chain, in order.

  • X::MCP::Server::Tool::Web::RedirectLoop — a redirect came back to a URL already visited on this fetch.

  • X::MCP::Server::Tool::Web::Deadline — a time budget expired. Carries the phase ('connecting', 'reading headers', 'reading the body') so the caller can tell a dead host from a slow one.

  • X::MCP::Server::Tool::Web::Transport — the connection itself failed: refused, reset, DNS miss, TLS rejection.

  • X::MCP::Server::Tool::Web::RobotsRefused — robots.txt disallows the URL for our user agent.

MCP::Server::Tool::Web v0.1.1

web search, fetch, crawl and grep for MCP::Server

Authors

  • Matt Doughty

License

Artistic-2.0

Dependencies

MCP::Server:auth<zef:apogee>:ver<0.6.0+>Cro::HTTP:auth<zef:cro>:ver<0.8.11+>Cro::Core:auth<zef:cro>:ver<0.8.10+>IO::Socket::Async::SSL:auth<zef:raku-community-modules>:ver<0.8.2+>JSON::Fast:ver<0.19>:auth<cpan:TIMOTIMO>

Test Dependencies

Provides

  • MCP::Server::Tool::Web
  • MCP::Server::Tool::Web::Addr
  • MCP::Server::Tool::Web::Budget
  • MCP::Server::Tool::Web::Crawl
  • MCP::Server::Tool::Web::Extract
  • MCP::Server::Tool::Web::Fetcher
  • MCP::Server::Tool::Web::Guard
  • MCP::Server::Tool::Web::Provider::Brave
  • MCP::Server::Tool::Web::Robots
  • MCP::Server::Tool::Web::SearchProvider
  • MCP::Server::Tool::Web::Transport
  • MCP::Server::Tool::Web::Url
  • MCP::Server::Tool::Web::X

The Camelia image is copyright 2009 by Larry Wall. "Raku" is a trademark of the Yet Another Society. All rights reserved.

Built with Podlite — the markup and publishing tools behind this site.