Skip to content

ask tool silently returns zero citations (dead 'citations' SSE handler) #82

Description

@arnav2

Summary

The ask tool returns no citations, always. _stream_answer in src/ks_mcp/tools/ask.py handles a citations SSE event that the backend never emits, so the citations list stays empty and AskResult.citations == [] for every answer (asserted, unknowingly, by tests/test_schema.py).

Root cause

ask.py is SSE-only — it opens the thread stream, accumulates text_deltas, and expects a citations SSE event to carry citations:

# src/ks_mcp/tools/ask.py (~line 131)
elif event == "citations":
    for raw in payload.get("citations") or []:
        citations.append(_to_ask_citation(raw))

But on the backend:

  • the citations SSE event was never wiredThreadStreamEvent.CITATIONS / CitationsPayload had zero producers and have now been removed (ks-backend PR #474);
  • even had it fired, its payload was a bare Citation (chunk_id, quote, offsets) — not the enriched shape _to_ask_citation expects (document_id, document_name, materialized_path).

The backend contract is: citations live on the persisted message, not on the wire. The frontend gets them by refetching the message after the stream (content.citations, enriched with document ancestry + permission-filtered). ks-mcp never refetches, so it gets nothing.

Fix

After the stream ends (message_end / [DONE]), do a REST GET of the message ks-mcp already tracks (it captures message_id from the message_start event) and populate citations from content.citations:

  • GET /v1/threads/{thread_id}/messages/{message_id} (or list) via ksapi
  • read content.citations — already enriched (document_id, document_name, materialized_path) and permission-filtered by the read API
  • map into AskCitation (the shape already matches the enriched content.citations)

with_details=false is enough: ks-backend PR #474 decoupled citation enrichment from with_details, so a light request now still returns enriched citations — one small request, no step-timeline payload.

Then remove the dead elif event == "citations" branch from _stream_answer.

Refs

  • ks-backend PR #474 (removed the dead citations SSE event; decoupled enrichment from with_details)
  • src/ks_mcp/tools/ask.py _stream_answer / _to_ask_citation
  • tests/test_schema.py (assert result.citations == [] — update once fixed)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions