VOOZH about

URL: https://deepwiki.com/ppl-ai/modelcontextprotocol/4.5-response-processing-and-citations

⇱ Response Processing and Citations | ppl-ai/modelcontextprotocol | DeepWiki


Loading...
Last indexed: 28 February 2026 (95c7a8)
Menu

Response Processing and Citations

This document describes how responses from the Perplexity API are processed before being returned to MCP clients. It covers response validation, thinking token stripping, citation appending, and result formatting for both chat completion and search operations.

For information about the individual tools that invoke these response processing mechanisms, see perplexity_ask, perplexity_research, perplexity_reason, and perplexity_search.


Response Processing Pipeline

The response processing pipeline differs between chat completions (used by perplexity_ask, perplexity_research, and perplexity_reason) and search operations (used by perplexity_search).

Chat Completion Response Flow


Sources: src/server.ts189-247 src/server.ts118-187 src/index.test.ts57-176


Response Validation and Parsing

All chat completion responses undergo strict validation using Zod schemas before content extraction.

Validation Schema

The ChatCompletionResponseSchema validates the response structure:


Implementation Location: src/validation.ts and src/server.ts11

Validation Process

The validation occurs in performChatCompletion at src/server.ts210-229 The path taken depends on which model is in use:

  • Non-streaming models (sonar-pro, sonar-reasoning-pro): response.json() is called, then ChatCompletionResponseSchema.parse(json) validates the full object src/server.ts215-216
  • Streaming model (sonar-deep-research): consumeSSEStream(response) reassembles chunks into a ChatCompletionResponse, which is then validated with ChatCompletionResponseSchema.parse(assembled) src/server.ts186

After parsing, Zod errors are classified into specific failure types src/server.ts218-228:

  • Missing message content: Issues with message or content paths
  • Empty choices array: Issues with choices path
  • Generic parse failures: Other validation errors

Error Handling Table

Validation FailureError MessageTest Coverage
Empty choices array"Invalid API response: missing or empty choices array"src/index.test.ts289-299
Missing message.content"Invalid API response: missing message content"src/index.test.ts302-313
Null or undefined choices"Invalid API response: missing or empty choices array"src/index.test.ts341-352
Invalid JSON structure"Failed to parse JSON response from Perplexity API"src/index.test.ts405-418

Sources: src/server.ts210-229 src/index.test.ts288-402


SSE Streaming (sonar-deep-research)

The sonar-deep-research model responds with a Server-Sent Events (SSE) stream instead of a single JSON object. The consumeSSEStream function src/server.ts118-187 handles reassembly.

consumeSSEStream Flow

consumeSSEStream reassembly diagram


Sources: src/server.ts118-187

SSE Chunk Handling Details

Each SSE chunk arriving over the wire is a line beginning with data: . The function:

  1. Maintains a text buffer between reads to handle chunks split across byte boundaries src/server.ts133 src/server.ts141-143
  2. Skips lines that don't start with data:, and skips the terminal [DONE] sentinel src/server.ts147-150
  3. Silently discards malformed JSON (keep-alive pings, etc.) src/server.ts165-167
  4. Collects delta.content from choices[0].delta src/server.ts161-164
  5. Overwrites citations, usage, id, model, created with the latest seen values from any chunk src/server.ts155-159
  6. After the stream ends, assembles all contentParts by joining them and constructs a synthetic ChatCompletionResponse object, then validates it with ChatCompletionResponseSchema.parse src/server.ts171-186

The assembled object is structurally identical to a non-streaming response, so all downstream processing (thinking-token stripping, citation appending) is model-agnostic.

Sources: src/server.ts118-187


Thinking Token Stripping

Certain Perplexity models (sonar-deep-research and sonar-reasoning-pro) may include reasoning tokens wrapped in `` tags. These can be optionally removed to save context tokens.

stripThinkingTokens Function

Location: src/server.ts59-61


Citation Format

Citations are formatted as a numbered list:

Response content here

Citations:
[1] https://example.com/source1
[2] https://example.com/source2
[3] https://example.com/source3

Citation Data Flow


Sources: src/server.ts239-244 src/index.test.ts94-121


Search Result Formatting

Search operations use a different formatting mechanism via the formatSearchResults function.

formatSearchResults Function

Location: src/server.ts249-269


Search Result Structure

Each search result contains:

FieldTypeRequiredDescription
titlestringYesResult title in bold markdown
urlstringYesFull URL of the result
snippetstringNoText excerpt from the page
datestringNoPublication or last modified date

Example Search Output

Found 2 search results:

1. **Understanding Model Context Protocol**
 URL: https://example.com/mcp-intro
 MCP enables applications to provide context to AI models through standardized interfaces.
 Date: 2025-01-15

2. **Perplexity API Documentation**
 URL: https://docs.perplexity.ai/
 Complete API reference for Perplexity's language models.

Sources: src/server.ts249-269 src/index.test.ts16-55 src/index.test.ts546-563


Response Content Types

The MCP server returns responses in two formats to accommodate different client needs.

Dual Response Format

All tool handlers return both text and structured content. The same processed string is placed in both fields.

Tool handler return format diagram


Content Type Mapping

ToolCallscontent[0].textstructuredContent key
perplexity_askperformChatCompletion(..., "sonar-pro", ...)result stringresponse
perplexity_researchperformChatCompletion(..., "sonar-deep-research", ...)result stringresponse
perplexity_reasonperformChatCompletion(..., "sonar-reasoning-pro", ...)result stringresponse
perplexity_searchperformSearch(...)result stringresults

Implementation Locations:

Sources: src/server.ts361-529


Edge Cases and Error Handling

Empty or Null Citations

The guard condition at src/server.ts239 is:

data.citations && Array.isArray(data.citations) && data.citations.length > 0

Empty citations arrays (length 0) and missing citations fields are both silently skipped; no "Citations:" header is appended.

Test coverage: src/index.test.ts367-383

Malformed Citation Data

Non-array citation values trigger validation errors during schema parsing: src/index.test.ts385-401

Special Characters

All response content preserves special characters, emojis, and unicode: src/index.test.ts437-452

Long Content

The system handles arbitrarily long response strings with no truncation: src/index.test.ts454-470

Sources: src/index.test.ts367-470


Complete Response Processing Code Map


Sources: src/server.ts58-247 src/validation.js