Skip to content

feat: add news search to CLI and MCP#94

Merged
Microck merged 5 commits intoMicrock:mainfrom
nickclyde:feat/search-news-and-mcp
May 2, 2026
Merged

feat: add news search to CLI and MCP#94
Microck merged 5 commits intoMicrock:mainfrom
nickclyde:feat/search-news-and-mcp

Conversation

@nickclyde
Copy link
Copy Markdown
Contributor

Summary

kagi search gains a --news flag that hits Kagi's News tab and returns articles grouped into story clusters. The MCP server gets two corresponding tools: kagi_news (the existing kagi news headlines product) and kagi_news_search (the new vertical). Also fixes a pre-existing bug where kagi news could not parse live responses because total_stories was typed as a string but the API always returns an integer, and another bug with MCP notification handling.

Why

I originally just wanted to add an MCP tool for searching for news stories. I first added an MCP tool for the kagi news command and the bug was discovered during smoke testing. I then realized kagi news was for news.kagi.com rather than for the "News" tab in a search result, so I decided to add a flag to kagi search for grabbing those news stories.

Things to look out for

  • Public API surface: new --news flag, two new MCP tools, new NewsSearchResponse JSON shape. The --news path forces session auth and rejects incompatible flags (--lens, --snap, date filters, --verbatim, --personalized, --follow, --template, --time year, --order trackers).
  • Output-contract change in kagi news: total_stories shifts from "20" to 20 in the JSON output. Documented as Fixed in CHANGELOG. The live command never actually. returned data with the string form (parsing always failed), so no consumer can have depended on the string shape.
  • Relative time strings (e.g. "2 hours ago") are preserved verbatim in news-search output; Kagi's News tab does not expose absolute timestamps.
  • Fix MCP notification handling. The server was replying to JSON-RPC notifications (messages without an id), which violates the spec and caused Claude's MCP client to reject the connection with a Zod validation error on notifications/initialized. Notifications are now ignored, and unsupported methods return a proper error object instead of stuffing the error into result.

Screenshots

Screenshot 2026-05-01 at 1 53 22 PM Screenshot 2026-05-01 at 1 55 28 PM Screenshot 2026-05-01 at 2 15 06 PM

Test plan

  • make check — fmt + clippy + 202 tests (8 new news-related).
  • kagi search "iran" --news --format json returns the documented NewsSearchResponse shape.
  • kagi search "iran" --news --lens 1 exits non-zero with a clear error.
  • kagi news --category tech succeeds and emits "total_stories": <integer> (regression check for the fix).
  • echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | kagi mcp | jq lists both kagi_news and kagi_news_search.

nickclyde added 4 commits May 1, 2026 13:41
Surfaces the existing `kagi news` command via the MCP server. The tool
needs no auth (mirrors `kagi news`) and accepts `category` (default
`world`), `limit` (default `12`), and `lang` (default `default`).
`NewsStoriesPayload` and `NewsStoriesResponse` declared `total_stories`
as `String`, but the live Kagi News API always returns it as an integer,
so every live `kagi news` invocation failed with a parse error. The
existing integration fixture hardcoded the field as a JSON string, which
masked the bug in CI.

Switch the type to `u64`, update the fixture, and correct the documented
JSON shape. The output JSON now emits an integer for `total_stories`
instead of the never-actually-delivered string form.
Adds a News-tab vertical to `kagi search`. With `--news`, the CLI hits
`kagi.com/news?q=...` (session auth) and returns articles grouped into
story clusters via a new `NewsSearchResponse` JSON shape. The flag
forces session-only auth and rejects incompatible options (--lens,
--snap, --from-date/--to-date, --verbatim, --personalized,
--no-personalized, --follow, --template, --time year, --order trackers).

A new HTML parser walks the `.newsResultGroup`/`.newsResultItem`
markup, preserves Kagi's relative time strings verbatim ("2 hours
ago"), and exposes the per-cluster grouping in the response.

Also exposes the same vertical via a new `kagi_news_search` MCP tool
that accepts `query`, optional `region`, `freshness` (day/week/month),
`order` (default/recency/website), and `limit`.
Replying to notifications (messages without an `id`) violates JSON-RPC
2.0 and caused Claude's MCP client to reject the connection with a Zod
validation error on `notifications/initialized`. Skip notifications and
return proper `error` objects for unsupported methods instead of
embedding errors in `result`.
@nickclyde nickclyde requested a review from Microck as a code owner May 1, 2026 21:19
@Microck Microck merged commit 4989f26 into Microck:main May 2, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants