Skip to content

feat: make web search mandatory in research and plan commands#40

Merged
iamladi merged 14 commits intomainfrom
feat/multi-provider-search-mcp
Feb 14, 2026
Merged

feat: make web search mandatory in research and plan commands#40
iamladi merged 14 commits intomainfrom
feat/multi-provider-search-mcp

Conversation

@iamladi
Copy link
Owner

@iamladi iamladi commented Feb 14, 2026

Summary

  • web-search-researcher agent: Rewrote to use parallel multi-tool search (mcp__search__search_web + WebSearch) instead of sequential Sonar-first flow. Added partial/total failure handling.
  • /research: Web search now always runs as 4th parallel subagent (standard) and mandatory subagent (swarm). Removed all "optional" conditionals.
  • /research-deep: Web search now always runs in both Standard and Swarm Discovery. Added 500-word context.md merge limit and 2-minute timeout.
  • /plan: Web search spawns during Research Checkpoint with 3-minute timeout, blocking Solution Design until complete.
  • All commands gracefully degrade if search APIs are unavailable.

Plan

plans/mandatory-web-search-integration.md

Review

Reviewed by GPT-5.3-Codex (xhigh) and Gemini 3 Pro in parallel. Two findings addressed:

  • P1: Added missing timeout for Standard Discovery web search
  • P2: Added explicit failure fallback to Swarm workflow

Test plan

  • /research <topic> spawns web-search-researcher without explicit request
  • /research --swarm <topic> spawns web-search-researcher alongside team
  • /research-deep <topic> includes web findings in context.md
  • /plan <feature> uses web search during Research Checkpoint
  • Commands complete gracefully with no API keys configured
  • No remaining "Optional Web Research" or "if explicitly requested" conditionals (verified via grep)
  • bun run validate passes

Implements searchExa adapter following TDD strict workflow:
- DI-based ExaClient interface for testability
- Maps recency to startPublishedDate using recencyToDate()
- Maps search options (type, domains, category, include_text)
- Clamps num_results to max 100 via clampNumResults()
- Handles null titles, empty results, cost tracking
- Extracts images and combines content from results
- 15 test cases covering all adapter behaviors

Task: Create the Exa adapter with TDD strict (tests first)
Created Perplexity adapter for search-mcp with strict TDD workflow:
- Tests cover SSE parsing, citation extraction, image extraction, error handling
- Implementation uses dependency injection for testability
- Supports LLM tuning params (temperature, top_p, top_k, max_tokens, etc.)
- Handles timeout and error scenarios with standardized error messages

Task: Create the Perplexity adapter with TDD strict (tests first)
Implements Brave Search API adapter following TDD strict workflow.
Tests written first (RED), then minimal implementation (GREEN).

- 10 test cases covering all specified behaviors
- Dependency injection for testability
- 30s timeout with AbortController
- Recency to freshness mapping (day→pd, week→pw, month→pm, year→py)
- Proper error handling for non-OK responses and timeouts
- Result parsing: web.results → SearchResult format
- types.ts: SearchInput, SearchResult, SearchProvider, ToolOutput types
- types.ts: recencyToDate(), clampNumResults(), validateProviderParams()
- types.ts: PROVIDER_PARAM_MATRIX for FR-7 param validation
- format.ts: formatResponse() converts SearchResult to MCP text output
- package.json: add exa-js@2.4.0 dependency
- 31 tests covering types and format modules
- index.ts: MCP server with search_web tool registration
- Detects available providers from env vars at startup
- Validates DEFAULT_PROVIDER against available providers
- Static Zod enum for provider param (FR-6)
- Provider-specific param validation in handler (FR-7)
- Dynamic tool description listing available providers
- Dispatches to correct adapter based on provider param
- 15 tests covering provider detection, resolution, and description
- .mcp.json: replace perplexity entry with search entry, add env vars
- web-search-researcher.md: mcp__perplexity__search_web → mcp__search__search_web
- README.md: update MCP config example and directory structure
…d type safety

- Add AbortController timeout (30s) and error normalization to Exa adapter (FR-8)
- Replace exaClient! non-null assertion with defensive null check in index.ts
- Add typed BraveWebResult/BraveSearchResponse interfaces, remove `any` casts
- Fix brave.ts clampNumResults to use literal "brave" instead of input.provider
- Add 3 new tests for exa timeout and error normalization (87 total passing)
Replaced by the multi-provider search-mcp which supports Perplexity, Exa, and Brave.
Instead of hardcoding "30s", derive from actual timeoutMs parameter.
Clear Exa setTimeout after Promise.race resolves to prevent timer
memory leak. Remove redundant clearTimeout from Perplexity catch block
(finally block handles it). Reorder default provider cascade to
Exa > Brave > Perplexity based on result quality preference.
Bump version for multi-provider search MCP server, review fixes,
and provider priority reordering.
The .mcp.json hardcoded DEFAULT_PROVIDER=perplexity, which defeated
the ALL_PROVIDERS priority order (Exa > Brave > Perplexity) set in
index.ts. Removing it lets the code cascade work as intended.
Web search was optional, triggered only when users explicitly requested it.
Now web-search-researcher always spawns in parallel with codebase subagents
across /research, /research-deep, and /plan. The agent uses parallel
multi-tool search (mcp__search__search_web + WebSearch) instead of
sequential Sonar-first flow. Graceful degradation ensures commands complete
even when all search APIs are unavailable.
@iamladi iamladi merged commit f83f2e0 into main Feb 14, 2026
1 check passed
@iamladi iamladi deleted the feat/multi-provider-search-mcp branch February 14, 2026 16:16
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.

1 participant