SearchProvider

NAME

MCP::Server::Tool::Web::SearchProvider - the pluggable seam behind web_search

SYNOPSIS


use MCP::Server::Tool::Web::SearchProvider;

class MyProvider does MCP::Server::Tool::Web::SearchProvider {
    method name(--> Str:D) { 'my-provider' }

    method search(Str:D $query, Int:D $count --> List:D) {
        # ... call out to whatever search backend, then ...
        (
            %( title => 'Example', url => 'https://example.com/', snippet => '...' ),
        );
    }
}

DESCRIPTION

web_search does not talk to any particular search engine directly — it asks whatever object composes this role. MCP::Server::Tool::Web picks a concrete implementation (MCP::Server::Tool::Web::Provider::Brave by default) via its provider attribute; tests compose a tiny fake that never touches the network. A provider is exactly two methods.

METHODS

method name


method name(--> Str:D) { ... }

A short, stable, lowercase identifier for the provider ('brave', 'my-provider', ...). web_search's JSON result carries this under its provider key, so callers — and the model reading the tool output — can tell which engine actually answered.


method search(Str:D $query, Int:D $count --> List:D) { ... }

Run one search and return up to $count results as a List of plain Hashes, each shaped:

  • title — Str:D, the result's headline text.

  • url — Str:D, the result's absolute URL.

  • snippet — Str:D, a short excerpt of the page (empty string when the provider has none, never omitted).

  • age — Str, OPTIONAL. A human-readable freshness hint ("3 days ago", "2026-08-01", ...) when the provider supplies one. Omitted from the Hash entirely when unknown — callers must check :exists, not merely definedness.

An empty List is a legitimate, non-error answer (the query matched nothing, or the provider only had non-web results to offer) — it is NOT how failure is reported.

Failure is reported by throwing. Implementations die with a plain Str message (never a typed exception the caller would have to know about) whose first line is a teaching sentence — one a person (or the model that triggered the call) can act on without reading source: it names what went wrong, and, wherever one exists, the specific config key or environment variable that would change the outcome. MCP::Server::Tool::Web's web_search tool catches whatever a provider throws and surfaces .message verbatim as the tool's is_error text, so a vague "search failed" here becomes the whole story the model gets. Multi-line messages are fine (extra context on later lines); the first line alone must stand on its own.

$query is guaranteed non-empty and already length-checked by the tool layer against the provider's advertised limit before this method is ever called; $count is guaranteed to be a positive integer within whatever range the tool layer negotiated. A provider is free to apply its own tighter limits (and should die with a teaching message, not silently clamp, if it does) but does not need to re-validate the basics.

AUTHOR

Matt Doughty

COPYRIGHT AND LICENSE

Copyright 2026 Matt Doughty

This library is free software; you can redistribute it and/or modify it under the Artistic License 2.0.

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.