Module: Html2rss::MCP::Server
- Defined in:
- lib/html2rss/mcp/server.rb,
lib/html2rss/mcp/server/tools.rb
Overview
Thin MCP wire adapter over public html2rss APIs.
Ownership: scraping/capture/validate/feed stay on gem entrypoints (Html2rss.auto_feed_result, Capture.build, Config.validate, Html2rss.feed_result). This module maps MCP kwargs to those APIs, then Outcome + Contract shape the envelope.
Strategy note: MCP auto passes through to FeedPipeline AutoFallback
(default → botasaurus). Concrete strategies are used as-is.
Botasaurus requires BOTASAURUS_SCRAPER_URL.
Defined Under Namespace
Modules: Tools
Constant Summary collapse
- SERVER_NAME =
MCP server display name.
'html2rss'- SERVER_VERSION =
MCP server version (mirrors the gem version).
Html2rss::VERSION
- HTTP_BIND_HOST =
Loopback bind for HTTP transport (local use only).
'127.0.0.1'- RESOURCES =
Declarative MCP resource registrations consumed by register_resources.
[ { uri: 'html2rss://schema', name: 'Configuration JSON Schema', description: 'Full JSON Schema for html2rss feed configurations', mime_type: 'application/json', body: lambda { [{ uri: 'html2rss://schema', mimeType: 'application/json', text: Html2rss::Config.json_schema_json(pretty: true) }] } }, { uri: 'html2rss://extractors', name: 'Available Extractors', description: 'Registered extractor names for selector configs ' \ '(full option docs live in html2rss://schema $defs)', mime_type: 'application/json', body: lambda { extractors = Html2rss::Selectors::Extractors::NAME_TO_CLASS.keys.map(&:to_s).sort [{ uri: 'html2rss://extractors', mimeType: 'application/json', text: JSON.pretty_generate(extractors) }] } }, { uri: 'html2rss://strategies', name: 'Available Strategies', description: 'Published MCP request strategy names', mime_type: 'application/json', body: lambda { [{ uri: 'html2rss://strategies', mimeType: 'application/json', text: JSON.generate(Contract::STRATEGIES) }] } }, { uri: 'html2rss://runtime', name: 'Runtime capabilities', description: 'Gem version, MCP contract version, catalog fingerprint, tool names, and Botasaurus config', mime_type: 'application/json', body: lambda { [{ uri: 'html2rss://runtime', mimeType: 'application/json', text: JSON.pretty_generate(Runtime.snapshot.to_h) }] } } ].freeze
- PROMPTS =
Declarative MCP prompt registrations; SDK argument objects built at register_prompts time.
[ { name: 'scrape-webpage', description: 'Guided one-shot scrape: one scrape call (auto already falls back)', arguments: [{ name: 'url', description: 'URL to scrape', required: true }], body: ->(args) { Outcome::Playbook.scrape_webpage_prompt(args.fetch(:url)) } }, { name: 'capture-feed-config', description: 'Guided capture → test → apply; YAML draft plus catalog rewrite', arguments: [{ name: 'url', description: 'URL to analyze', required: true }], body: ->(args) { Outcome::Playbook.capture_feed_config_prompt(args.fetch(:url)) } } ].freeze
Class Method Summary collapse
-
.build ⇒ ::MCP::Server
Builds the configured MCP protocol server (tools/resources/prompts).
-
.start(transport: :stdio, port: 8080) ⇒ Object
Starts the MCP server with the given transport.
Class Method Details
.build ⇒ ::MCP::Server
Builds the configured MCP protocol server (tools/resources/prompts).
110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/html2rss/mcp/server.rb', line 110 def build # rubocop:disable Metrics/MethodLength -- protocol server construction ::MCP::Server.new( name: SERVER_NAME, title: SERVER_NAME, version: SERVER_VERSION, instructions: instructions_text, configuration: protocol_configuration ).tap do |server| register_tools(server) register_resources(server) register_prompts(server) end end |
.start(transport: :stdio, port: 8080) ⇒ Object
Starts the MCP server with the given transport.
Points Html2rss.logger at $stderr so stdio JSON-RPC on stdout stays
intact, and raises the process log level to info unless LOG_LEVEL is set.
A foreground watcher then sees the start banner, tool calls, and pipeline warns.
95 96 97 98 99 100 101 102 103 104 |
# File 'lib/html2rss/mcp/server.rb', line 95 def start(transport: :stdio, port: 8080) raise ArgumentError, "Unknown transport: #{transport.inspect}" unless %i[stdio http].include?(transport) configure_daemon_logging! app = build Log.info((transport:, port:)) return start_http(app, port:) if transport == :http ::MCP::Server::Transports::StdioTransport.new(app).open end |