victor HF Staff commited on
Commit
2d994c9
·
unverified ·
1 Parent(s): d4e1a40

fix(mcp): reduce Exa API context size sent to LLM (#2026)

Browse files

Use highlights instead of full page text to minimize context size.
The previous implementation requested `text: true` which returned
entire page contents (5-20K+ chars per result), overwhelming LLM context.

Now uses:
- highlights: 3 sentences, 2 per URL (concise, query-relevant)
- text fallback: max 500 chars (only if highlights empty)

This matches what the MCP server at mcp.exa.ai likely returns.

Files changed (1) hide show
  1. src/lib/server/mcp/exaDirect.ts +17 -6
src/lib/server/mcp/exaDirect.ts CHANGED
@@ -140,6 +140,7 @@ interface ExaSearchResponse {
140
 
141
  /**
142
  * Format Exa search results as human-readable text
 
143
  */
144
  function formatSearchResultsAsText(results: ExaSearchResult[]): string {
145
  if (results.length === 0) {
@@ -154,10 +155,11 @@ function formatSearchResultsAsText(results: ExaSearchResult[]): string {
154
  parts.push(` Published: ${result.publishedDate}`);
155
  }
156
 
157
- if (result.text) {
158
- parts.push(` ${result.text}`);
159
- } else if (result.highlights && result.highlights.length > 0) {
160
  parts.push(` ${result.highlights.join(" ... ")}`);
 
 
161
  }
162
 
163
  return parts.join("\n");
@@ -186,13 +188,22 @@ export async function callExaDirectApi(
186
  throw new Error("Missing required parameter: query");
187
  }
188
 
189
- // Build request body - pass through all args, ensure query exists and request text content
 
 
190
  const requestBody: Record<string, unknown> = {
191
  ...args,
192
  query,
193
- // Required to get page text content, not just metadata
194
  contents: {
195
- text: true,
 
 
 
 
 
 
 
 
196
  },
197
  };
198
 
 
140
 
141
  /**
142
  * Format Exa search results as human-readable text
143
+ * Prioritizes highlights (concise snippets) over full text to minimize LLM context
144
  */
145
  function formatSearchResultsAsText(results: ExaSearchResult[]): string {
146
  if (results.length === 0) {
 
155
  parts.push(` Published: ${result.publishedDate}`);
156
  }
157
 
158
+ // Prefer highlights (concise, query-relevant) over full text
159
+ if (result.highlights && result.highlights.length > 0) {
 
160
  parts.push(` ${result.highlights.join(" ... ")}`);
161
+ } else if (result.text) {
162
+ parts.push(` ${result.text}`);
163
  }
164
 
165
  return parts.join("\n");
 
188
  throw new Error("Missing required parameter: query");
189
  }
190
 
191
+ // Build request body - pass through all args, ensure query exists
192
+ // Use highlights (not full text) to minimize context size sent to LLM
193
+ // This matches what the MCP server at mcp.exa.ai returns
194
  const requestBody: Record<string, unknown> = {
195
  ...args,
196
  query,
 
197
  contents: {
198
+ // Use highlights for concise, query-relevant snippets (much smaller than full text)
199
+ highlights: {
200
+ numSentences: 3,
201
+ highlightsPerUrl: 2,
202
+ },
203
+ // Also get limited text as fallback if highlights are empty
204
+ text: {
205
+ maxCharacters: 500,
206
+ },
207
  },
208
  };
209