@youdotcom-oss/mcp 3.2.2 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/stdio.js CHANGED
@@ -12572,7 +12572,7 @@ var ResearchQuerySchema = object({
12572
12572
  var ResearchSourceSchema = object({
12573
12573
  url: string2().describe("Source webpage URL"),
12574
12574
  title: string2().optional().describe("Source webpage title"),
12575
- snippets: array(string2()).describe("Relevant excerpts from the source page used in generating the answer")
12575
+ snippets: array(string2()).optional().describe("Relevant excerpts from the source page used in generating the answer")
12576
12576
  });
12577
12577
  var ResearchOutputSchema = object({
12578
12578
  content: string2().describe("Comprehensive response with inline citations, formatted in Markdown"),
@@ -12634,7 +12634,7 @@ var formatResearchResponse = (response) => {
12634
12634
  `);
12635
12635
  parts.push(`**URL:** ${source.url}
12636
12636
  `);
12637
- if (source.snippets.length > 0) {
12637
+ if (source.snippets?.length) {
12638
12638
  parts.push(`
12639
12639
  **Key Excerpts:**
12640
12640
  `);
@@ -12747,8 +12747,17 @@ var SearchQuerySchema = object({
12747
12747
  ]).optional().describe("Country code"),
12748
12748
  safesearch: _enum(["off", "moderate", "strict"]).optional().describe("Filter level"),
12749
12749
  livecrawl: _enum(["web", "news", "all"]).optional().describe("Live-crawl sections for full content"),
12750
- livecrawl_formats: _enum(["html", "markdown"]).optional().describe("Format for crawled content")
12750
+ livecrawl_formats: array(_enum(["html", "markdown"])).optional().describe("Formats for crawled content"),
12751
+ language: LanguageSchema.optional().describe("Language code (BCP 47 format)"),
12752
+ include_domains: array(string2()).max(500).optional().describe("Domains to include in results (up to 500)"),
12753
+ exclude_domains: array(string2()).max(500).optional().describe("Domains to exclude from results (up to 500)"),
12754
+ crawl_timeout: number2().int().min(1).max(60).optional().describe("Crawl timeout in seconds (1-60)")
12751
12755
  });
12756
+ var validateSearchQuery = (searchQuery) => {
12757
+ if (searchQuery.include_domains && searchQuery.exclude_domains) {
12758
+ throw new Error("Cannot combine include_domains and exclude_domains");
12759
+ }
12760
+ };
12752
12761
  var WebResultSchema = object({
12753
12762
  url: string2().describe("URL"),
12754
12763
  title: string2().describe("Title"),
@@ -12807,23 +12816,18 @@ var fetchSearchResults = async ({
12807
12816
  getUserAgent,
12808
12817
  customHeaders
12809
12818
  }) => {
12810
- const url = new URL(SEARCH_API_URL);
12811
- const searchParams = new URLSearchParams;
12812
- for (const [name, value] of Object.entries(searchQuery)) {
12813
- if (value !== undefined && value !== null) {
12814
- searchParams.append(name, `${value}`);
12815
- }
12816
- }
12817
- url.search = searchParams.toString();
12819
+ validateSearchQuery(searchQuery);
12818
12820
  const options = {
12819
- method: "GET",
12821
+ method: "POST",
12820
12822
  headers: new Headers({
12821
12823
  ...customHeaders,
12822
12824
  "X-API-Key": YDC_API_KEY || "",
12825
+ "Content-Type": "application/json",
12823
12826
  "User-Agent": getUserAgent()
12824
- })
12827
+ }),
12828
+ body: JSON.stringify(searchQuery)
12825
12829
  };
12826
- const response = await fetch(url, options);
12830
+ const response = await fetch(SEARCH_API_URL, options);
12827
12831
  if (!response.ok) {
12828
12832
  const errorCode = response.status;
12829
12833
  if (errorCode === 429) {
@@ -12885,29 +12889,12 @@ var getLogger = (sendNotification) => async (params) => {
12885
12889
  await sendNotification({ method: "notifications/message", params });
12886
12890
  };
12887
12891
 
12888
- // src/contents/contents.schemas.ts
12889
- var ContentsStructuredContentSchema = object({
12890
- count: number2().describe("URLs processed"),
12891
- formats: array(string2()).describe("Content formats requested"),
12892
- items: array(object({
12893
- url: string2().describe("URL"),
12894
- title: string2().optional().describe("Title"),
12895
- markdown: string2().optional().describe("Markdown content"),
12896
- html: string2().optional().describe("HTML content"),
12897
- metadata: object({
12898
- favicon_url: string2().describe("Favicon URL"),
12899
- site_name: string2().optional().nullable().describe("Site name")
12900
- }).optional().nullable().describe("Page metadata")
12901
- })).describe("Extracted items")
12902
- });
12903
-
12904
12892
  // src/contents/contents.utils.ts
12905
12893
  var formatContentsResponse = (response, formats) => {
12906
12894
  const textParts = [`Successfully extracted content from ${response.length} URL(s):
12907
12895
  `];
12908
12896
  textParts.push(`Formats: ${formats.join(", ")}
12909
12897
  `);
12910
- const items = [];
12911
12898
  for (const item of response) {
12912
12899
  textParts.push(`
12913
12900
  ## ${item.title || "Untitled"}`);
@@ -12953,28 +12940,14 @@ var formatContentsResponse = (response, formats) => {
12953
12940
  textParts.push(`
12954
12941
  ---
12955
12942
  `);
12956
- items.push({
12957
- url: item.url,
12958
- title: item.title ?? undefined,
12959
- markdown: item.markdown ?? undefined,
12960
- html: item.html ?? undefined,
12961
- metadata: item.metadata ?? undefined
12962
- });
12963
12943
  }
12964
- return {
12965
- content: [
12966
- {
12967
- type: "text",
12968
- text: textParts.join(`
12944
+ return [
12945
+ {
12946
+ type: "text",
12947
+ text: textParts.join(`
12969
12948
  `)
12970
- }
12971
- ],
12972
- structuredContent: {
12973
- count: response.length,
12974
- formats,
12975
- items
12976
12949
  }
12977
- };
12950
+ ];
12978
12951
  };
12979
12952
 
12980
12953
  // src/contents/register-contents-tool.ts
@@ -12986,8 +12959,10 @@ var registerContentsTool = ({
12986
12959
  mcp.registerTool("you-contents", {
12987
12960
  title: "Extract Web Page Contents",
12988
12961
  description: "Extract page content in markdown or HTML",
12989
- inputSchema: ContentsQuerySchema.shape,
12990
- outputSchema: ContentsStructuredContentSchema.shape
12962
+ inputSchema: ContentsQuerySchema,
12963
+ outputSchema: object({
12964
+ output: ContentsApiResponseSchema
12965
+ })
12991
12966
  }, async (contentsQuery, { sendNotification }) => {
12992
12967
  const logger = getLogger(sendNotification);
12993
12968
  try {
@@ -13003,14 +12978,16 @@ var registerContentsTool = ({
13003
12978
  YDC_API_KEY,
13004
12979
  getUserAgent
13005
12980
  });
13006
- const { content, structuredContent } = formatContentsResponse(response, requestFormats);
12981
+ const content = formatContentsResponse(response, requestFormats);
13007
12982
  await logger({
13008
12983
  level: "info",
13009
12984
  data: `Contents API call successful: extracted ${response.length} page(s)`
13010
12985
  });
13011
12986
  return {
13012
12987
  content,
13013
- structuredContent
12988
+ structuredContent: {
12989
+ output: response
12990
+ }
13014
12991
  };
13015
12992
  } catch (err) {
13016
12993
  const errorMessage = err instanceof Error ? err.message : String(err);
@@ -20460,7 +20437,7 @@ var EMPTY_COMPLETION_RESULT = {
20460
20437
  // package.json
20461
20438
  var package_default = {
20462
20439
  name: "@youdotcom-oss/mcp",
20463
- version: "3.2.2",
20440
+ version: "3.3.0",
20464
20441
  description: "You.com MCP server — web search, AI research, and content extraction via You.com APIs",
20465
20442
  license: "MIT",
20466
20443
  engines: {
@@ -20513,11 +20490,12 @@ var package_default = {
20513
20490
  mcpName: "io.github.youdotcom-oss/mcp",
20514
20491
  dependencies: {
20515
20492
  "@modelcontextprotocol/sdk": "^1.28.0",
20516
- "@youdotcom-oss/api": "0.5.1",
20493
+ "@youdotcom-oss/api": "0.5.2",
20517
20494
  zod: "^4.3.6"
20518
20495
  },
20519
20496
  devDependencies: {
20520
- "@modelcontextprotocol/inspector": "0.21.1"
20497
+ "@modelcontextprotocol/inspector": "0.21.2",
20498
+ "@types/bun": "latest"
20521
20499
  }
20522
20500
  };
20523
20501
 
@@ -20533,37 +20511,15 @@ var getMcpServer = () => new McpServer({
20533
20511
  instructions: `Use this server to search the web, get AI-powered answers with web context, and extract content from web pages using You.com. The you-contents tool extracts page content and returns it in markdown or HTML format. Use HTML format for layout preservation, interactive content, and visual fidelity; use markdown for text extraction and simpler consumption.`
20534
20512
  });
20535
20513
 
20536
- // src/research/research.schemas.ts
20537
- var ResearchStructuredContentSchema = object({
20538
- contentType: string2().describe("Format of the content field"),
20539
- sourceCount: number2().describe("Number of sources used"),
20540
- sources: array(object({
20541
- url: string2().describe("Source URL"),
20542
- title: string2().optional().describe("Source title"),
20543
- snippetCount: number2().describe("Number of excerpts from this source")
20544
- })).describe("Sources used in the research answer")
20545
- });
20546
-
20547
20514
  // src/research/research.utils.ts
20548
20515
  var formatResearchResults = (response) => {
20549
20516
  const text = formatResearchResponse(response);
20550
- return {
20551
- content: [
20552
- {
20553
- type: "text",
20554
- text
20555
- }
20556
- ],
20557
- structuredContent: {
20558
- contentType: response.output.content_type,
20559
- sourceCount: response.output.sources.length,
20560
- sources: response.output.sources.map((source) => ({
20561
- url: source.url,
20562
- title: source.title,
20563
- snippetCount: source.snippets?.length ?? 0
20564
- }))
20517
+ return [
20518
+ {
20519
+ type: "text",
20520
+ text
20565
20521
  }
20566
- };
20522
+ ];
20567
20523
  };
20568
20524
 
20569
20525
  // src/research/register-research-tool.ts
@@ -20575,8 +20531,8 @@ var registerResearchTool = ({
20575
20531
  mcp.registerTool("you-research", {
20576
20532
  title: "Research",
20577
20533
  description: "Research a topic with comprehensive answers and cited sources. Configurable effort levels (lite, standard, deep, exhaustive).",
20578
- inputSchema: ResearchQuerySchema.shape,
20579
- outputSchema: ResearchStructuredContentSchema.shape
20534
+ inputSchema: ResearchQuerySchema,
20535
+ outputSchema: ResearchResponseSchema
20580
20536
  }, async (researchQuery, { sendNotification }) => {
20581
20537
  const logger = getLogger(sendNotification);
20582
20538
  try {
@@ -20590,8 +20546,8 @@ var registerResearchTool = ({
20590
20546
  level: "info",
20591
20547
  data: `Research for "${researchQuery.input.substring(0, 100)}" complete: ${sourceCount} source(s)`
20592
20548
  });
20593
- const { content, structuredContent } = formatResearchResults(response);
20594
- return { content, structuredContent };
20549
+ const content = formatResearchResults(response);
20550
+ return { content, structuredContent: response };
20595
20551
  } catch (err) {
20596
20552
  const errorMessage = err instanceof Error ? err.message : String(err);
20597
20553
  const reportLink = generateErrorReportLink({
@@ -20619,28 +20575,8 @@ Report this issue: ${reportLink}`
20619
20575
  });
20620
20576
  };
20621
20577
 
20622
- // src/search/search.schemas.ts
20623
- var SearchStructuredContentSchema = object({
20624
- resultCounts: object({
20625
- web: number2().describe("Web results"),
20626
- news: number2().describe("News results"),
20627
- total: number2().describe("Total results")
20628
- }),
20629
- results: object({
20630
- web: array(object({
20631
- url: string2().describe("URL"),
20632
- title: string2().describe("Title"),
20633
- page_age: string2().optional().describe("Publication timestamp")
20634
- })).optional().describe("Web results"),
20635
- news: array(object({
20636
- url: string2().describe("URL"),
20637
- title: string2().describe("Title"),
20638
- page_age: string2().describe("Publication timestamp")
20639
- })).optional().describe("News results")
20640
- }).optional().describe("Search results")
20641
- });
20642
-
20643
20578
  // src/shared/format-search-results-text.ts
20579
+ var formatCharCount = (count) => count.toLocaleString();
20644
20580
  var formatSearchResultsText = (results) => {
20645
20581
  return results.map((result) => {
20646
20582
  const parts = [`Title: ${result.title}`];
@@ -20658,6 +20594,18 @@ var formatSearchResultsText = (results) => {
20658
20594
  } else if (result.snippet) {
20659
20595
  parts.push(`Snippet: ${result.snippet}`);
20660
20596
  }
20597
+ if (result.contents) {
20598
+ const formats = [];
20599
+ if (result.contents.markdown) {
20600
+ formats.push(`${formatCharCount(result.contents.markdown.length)} chars (markdown)`);
20601
+ }
20602
+ if (result.contents.html) {
20603
+ formats.push(`${formatCharCount(result.contents.html.length)} chars (html)`);
20604
+ }
20605
+ if (formats.length > 0) {
20606
+ parts.push(`Page content available: ${formats.join(", ")}`);
20607
+ }
20608
+ }
20661
20609
  return parts.join(`
20662
20610
  `);
20663
20611
  }).join(`
@@ -20675,14 +20623,7 @@ var formatSearchResults = (response) => {
20675
20623
  ${webResults}`;
20676
20624
  }
20677
20625
  if (response.results.news?.length) {
20678
- const newsResults = response.results.news.map((article) => `Title: ${article.title}
20679
- URL: ${article.url}
20680
- Description: ${article.description}
20681
- Published: ${article.page_age}`).join(`
20682
-
20683
- ---
20684
-
20685
- `);
20626
+ const newsResults = formatSearchResultsText(response.results.news);
20686
20627
  if (formattedResults) {
20687
20628
  formattedResults += `
20688
20629
 
@@ -20694,44 +20635,14 @@ ${"=".repeat(50)}
20694
20635
 
20695
20636
  ${newsResults}`;
20696
20637
  }
20697
- const structuredResults = {};
20698
- if (response.results.web?.length) {
20699
- structuredResults.web = response.results.web.map((result) => {
20700
- const item = {
20701
- url: result.url,
20702
- title: result.title
20703
- };
20704
- if (result.page_age)
20705
- item.page_age = result.page_age;
20706
- return item;
20707
- });
20708
- }
20709
- if (response.results.news?.length) {
20710
- structuredResults.news = response.results.news.map((article) => ({
20711
- url: article.url,
20712
- title: article.title,
20713
- page_age: article.page_age
20714
- }));
20715
- }
20716
- return {
20717
- content: [
20718
- {
20719
- type: "text",
20720
- text: `Search Results for "${response.metadata.query}":
20638
+ return [
20639
+ {
20640
+ type: "text",
20641
+ text: `Search Results for "${response.metadata.query}":
20721
20642
 
20722
20643
  ${formattedResults}`
20723
- }
20724
- ],
20725
- structuredContent: {
20726
- resultCounts: {
20727
- web: response.results.web?.length || 0,
20728
- news: response.results.news?.length || 0,
20729
- total: (response.results.web?.length || 0) + (response.results.news?.length || 0)
20730
- },
20731
- results: Object.keys(structuredResults).length > 0 ? structuredResults : undefined
20732
- },
20733
- fullResponse: response
20734
- };
20644
+ }
20645
+ ];
20735
20646
  };
20736
20647
 
20737
20648
  // src/search/register-search-tool.ts
@@ -20742,9 +20653,9 @@ var registerSearchTool = ({
20742
20653
  }) => {
20743
20654
  mcp.registerTool("you-search", {
20744
20655
  title: "Web Search",
20745
- description: "Web and news search via You.com",
20746
- inputSchema: SearchQuerySchema.shape,
20747
- outputSchema: SearchStructuredContentSchema.shape
20656
+ description: "Web and news search via You.com. Supports domain filtering, language selection, livecrawl for full page content, and date freshness controls.",
20657
+ inputSchema: SearchQuerySchema,
20658
+ outputSchema: SearchResponseSchema
20748
20659
  }, async (searchQuery, { sendNotification }) => {
20749
20660
  const logger = getLogger(sendNotification);
20750
20661
  try {
@@ -20762,21 +20673,15 @@ var registerSearchTool = ({
20762
20673
  });
20763
20674
  return {
20764
20675
  content: [{ type: "text", text: "No results found." }],
20765
- structuredContent: {
20766
- resultCounts: {
20767
- web: 0,
20768
- news: 0,
20769
- total: 0
20770
- }
20771
- }
20676
+ structuredContent: response
20772
20677
  };
20773
20678
  }
20774
20679
  await logger({
20775
20680
  level: "info",
20776
20681
  data: `Search successful for query: "${searchQuery.query}" - ${webCount} web results, ${newsCount} news results (${webCount + newsCount} total)`
20777
20682
  });
20778
- const { content, structuredContent } = formatSearchResults(response);
20779
- return { content, structuredContent };
20683
+ const content = formatSearchResults(response);
20684
+ return { content, structuredContent: response };
20780
20685
  } catch (err) {
20781
20686
  const errorMessage = err instanceof Error ? err.message : String(err);
20782
20687
  const reportLink = generateErrorReportLink({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youdotcom-oss/mcp",
3
- "version": "3.2.2",
3
+ "version": "3.3.0",
4
4
  "description": "You.com MCP server — web search, AI research, and content extraction via You.com APIs",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -53,10 +53,11 @@
53
53
  "mcpName": "io.github.youdotcom-oss/mcp",
54
54
  "dependencies": {
55
55
  "@modelcontextprotocol/sdk": "^1.28.0",
56
- "@youdotcom-oss/api": "0.5.1",
56
+ "@youdotcom-oss/api": "0.5.2",
57
57
  "zod": "^4.3.6"
58
58
  },
59
59
  "devDependencies": {
60
- "@modelcontextprotocol/inspector": "0.21.1"
60
+ "@modelcontextprotocol/inspector": "0.21.2",
61
+ "@types/bun": "latest"
61
62
  }
62
63
  }
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.github.youdotcom-oss/mcp",
4
4
  "title": "You.com Web Access & AI",
5
5
  "description": "Web search, AI agent, and content extraction via You.com APIs",
6
- "version": "3.0.0",
6
+ "version": "3.2.3",
7
7
  "remotes": [
8
8
  {
9
9
  "type": "streamable-http",
@@ -22,7 +22,7 @@
22
22
  {
23
23
  "registryType": "npm",
24
24
  "identifier": "@youdotcom-oss/mcp",
25
- "version": "3.0.0",
25
+ "version": "3.2.3",
26
26
  "transport": {
27
27
  "type": "stdio"
28
28
  },
@@ -39,7 +39,7 @@
39
39
  "description": "Remote MCP server URL (defaults to https://api.you.com/mcp)",
40
40
  "isRequired": false,
41
41
  "isSecret": false,
42
- "format": "uri"
42
+ "format": "string"
43
43
  }
44
44
  ]
45
45
  }
@@ -1,33 +1,23 @@
1
1
  import type { ContentsApiResponse } from '@youdotcom-oss/api'
2
- import type { ContentsStructuredContent } from './contents.schemas.ts'
3
2
 
4
3
  /**
5
4
  * Format contents API response for MCP output
6
- * Returns full content in both text and structured formats
7
5
  * @param response - Validated API response
8
6
  * @param formats - Formats used for extraction
9
- * @returns Formatted response with content and structuredContent
7
+ * @returns Text content blocks for the MCP response
10
8
  */
11
9
  export const formatContentsResponse = (
12
10
  response: ContentsApiResponse,
13
11
  formats: string[],
14
- ): {
15
- content: Array<{ type: 'text'; text: string }>
16
- structuredContent: ContentsStructuredContent
17
- } => {
18
- // Build text content with full extracted content
12
+ ): Array<{ type: 'text'; text: string }> => {
19
13
  const textParts: string[] = [`Successfully extracted content from ${response.length} URL(s):\n`]
20
14
  textParts.push(`Formats: ${formats.join(', ')}\n`)
21
15
 
22
- const items: ContentsStructuredContent['items'] = []
23
-
24
16
  for (const item of response) {
25
- // Add header for this item
26
17
  textParts.push(`\n## ${item.title || 'Untitled'}`)
27
18
  textParts.push(`URL: ${item.url}\n`)
28
19
  textParts.push('---\n')
29
20
 
30
- // Add content based on requested formats
31
21
  if (formats.includes('markdown') && item.markdown) {
32
22
  textParts.push('\n### Markdown Content\n')
33
23
  textParts.push(item.markdown)
@@ -35,7 +25,7 @@ export const formatContentsResponse = (
35
25
  }
36
26
 
37
27
  if (formats.includes('html') && item.html) {
38
- // Text output is a brief preview only — full HTML is in structuredContent.items[].html
28
+ // Text output is a brief preview only — full HTML is in structuredContent.output[].html
39
29
  textParts.push('\n### HTML Content\n')
40
30
  textParts.push(`Length: ${item.html.length} characters\n`)
41
31
  textParts.push(item.html.substring(0, 500))
@@ -58,28 +48,12 @@ export const formatContentsResponse = (
58
48
  }
59
49
 
60
50
  textParts.push('\n---\n')
61
-
62
- // Add to structured content
63
- items.push({
64
- url: item.url,
65
- title: item.title ?? undefined,
66
- markdown: item.markdown ?? undefined,
67
- html: item.html ?? undefined,
68
- metadata: item.metadata ?? undefined,
69
- })
70
51
  }
71
52
 
72
- return {
73
- content: [
74
- {
75
- type: 'text',
76
- text: textParts.join('\n'),
77
- },
78
- ],
79
- structuredContent: {
80
- count: response.length,
81
- formats,
82
- items,
53
+ return [
54
+ {
55
+ type: 'text',
56
+ text: textParts.join('\n'),
83
57
  },
84
- }
58
+ ]
85
59
  }
@@ -1,7 +1,12 @@
1
1
  import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
2
- import { ContentsQuerySchema, fetchContents, generateErrorReportLink } from '@youdotcom-oss/api'
2
+ import {
3
+ ContentsApiResponseSchema,
4
+ ContentsQuerySchema,
5
+ fetchContents,
6
+ generateErrorReportLink,
7
+ } from '@youdotcom-oss/api'
8
+ import * as z from 'zod'
3
9
  import { getLogger } from '../shared/get-logger.ts'
4
- import { ContentsStructuredContentSchema } from './contents.schemas.ts'
5
10
  import { formatContentsResponse } from './contents.utils.ts'
6
11
 
7
12
  /**
@@ -17,43 +22,39 @@ export const registerContentsTool = ({
17
22
  YDC_API_KEY?: string
18
23
  getUserAgent: () => string
19
24
  }) => {
20
- // Register the tool
21
25
  mcp.registerTool(
22
26
  'you-contents',
23
27
  {
24
28
  title: 'Extract Web Page Contents',
25
29
  description: 'Extract page content in markdown or HTML',
26
- inputSchema: ContentsQuerySchema.shape,
27
- outputSchema: ContentsStructuredContentSchema.shape,
30
+ inputSchema: ContentsQuerySchema,
31
+ outputSchema: z.object({
32
+ output: ContentsApiResponseSchema,
33
+ }),
28
34
  },
29
35
  async (contentsQuery, { sendNotification }) => {
30
36
  const logger = getLogger(sendNotification)
31
37
 
32
38
  try {
33
- // Validate and parse input
34
39
  const { urls, formats, format, crawl_timeout } = contentsQuery
35
40
 
36
41
  // Handle backward compatibility: prefer formats array, fallback to format string, default to ['markdown']
37
42
  const requestFormats = formats || (format ? [format] : ['markdown'])
38
43
 
39
- // Log the request
40
44
  const timeoutInfo = crawl_timeout ? ` with timeout: ${crawl_timeout}s` : ''
41
45
  await logger({
42
46
  level: 'info',
43
47
  data: `Contents API call initiated for ${urls.length} URL(s) with formats: ${requestFormats.join(', ')}${timeoutInfo}`,
44
48
  })
45
49
 
46
- // Fetch contents from API
47
50
  const response = await fetchContents({
48
51
  contentsQuery,
49
52
  YDC_API_KEY,
50
53
  getUserAgent,
51
54
  })
52
55
 
53
- // Format response with full content
54
- const { content, structuredContent } = formatContentsResponse(response, requestFormats)
56
+ const content = formatContentsResponse(response, requestFormats)
55
57
 
56
- // Log success
57
58
  await logger({
58
59
  level: 'info',
59
60
  data: `Contents API call successful: extracted ${response.length} page(s)`,
@@ -61,10 +62,11 @@ export const registerContentsTool = ({
61
62
 
62
63
  return {
63
64
  content,
64
- structuredContent,
65
+ structuredContent: {
66
+ output: response,
67
+ },
65
68
  }
66
69
  } catch (err: unknown) {
67
- // Handle and log errors
68
70
  const errorMessage = err instanceof Error ? err.message : String(err)
69
71
  const reportLink = generateErrorReportLink({
70
72
  errorMessage,