Skip to content

feat(responses): surface query echo + mode field in structuredContent #5

@cyanheads

Description

@cyanheads

All nine tool handlers set search_criteria only when results are empty (results.length === 0 ? buildSearchCriteria(input) : undefined). Multi-mode tools (search-contributions, search-disbursements, search-expenditures) do not echo the resolved mode back in their response.

Without a query echo on non-empty responses, an agent cannot verify that its filters were applied as intended — e.g., a cycle defaulted from 2023 to 2024, or an aggregate mode silently resolved to a _candidate variant. Without a mode echo, an agent receiving a contributions response cannot confirm whether it got itemized records or an aggregate bucket, leading to misinterpretation of the result shape.

Proposal

Two related output schema changes that bring response surfaces inline with what agents need to self-verify.

Proposed behavior

1. Always populate search_criteria in every tool handler return statement, unconditionally:

// Current — only on empty
search_criteria: results.length === 0 ? buildSearchCriteria(input) : undefined,

// Proposed — always
search_criteria: buildSearchCriteria(input),

Applies to: search-candidates, search-committees, search-contributions, search-disbursements, search-expenditures, search-filings, lookup-elections, search-legal, lookup-calendar.

2. Echo resolved mode in multi-mode tool responses:

// search-contributions — aggregateMode already has the resolved variant ('by_size_candidate' etc.)
return {
  results: result.results,
  mode: aggregateMode,   // or 'itemized'
  pagination: result.pagination,
  search_criteria: buildSearchCriteria(input),
};

// search-disbursements — mode variable available in handler scope
return {
  results: result.results,
  mode: mode,   // 'itemized' | 'by_purpose' | 'by_recipient' | 'by_recipient_id'
  ...
};

// search-expenditures — mode variable available
return {
  results: result.results,
  mode: mode,   // 'itemized' | 'by_candidate'
  ...
};

The mode field should be added to the output Zod schema of each affected tool (string literal or enum, with .describe()).

Scope

  • src/mcp-server/tools/definitions/search-candidates.tool.ts
  • src/mcp-server/tools/definitions/search-committees.tool.ts
  • src/mcp-server/tools/definitions/search-contributions.tool.ts (+ mode field)
  • src/mcp-server/tools/definitions/search-disbursements.tool.ts (+ mode field)
  • src/mcp-server/tools/definitions/search-expenditures.tool.ts (+ mode field)
  • src/mcp-server/tools/definitions/search-filings.tool.ts
  • src/mcp-server/tools/definitions/lookup-elections.tool.ts
  • src/mcp-server/tools/definitions/search-legal.tool.ts
  • src/mcp-server/tools/definitions/lookup-calendar.tool.ts

Out of scope

  • Changing the buildSearchCriteria implementation itself
  • Adding mode echo to single-mode tools (they have no ambiguity)

Alternatives considered

Keeping search_criteria conditional preserves a slight payload reduction on non-empty responses, but the cost — agents being unable to verify applied filters — outweighs it. The field is already in the schema as optional; changing it to always-populated is non-breaking for consumers that handle the optional shape.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions