@youdotcom-oss/mcp 1.3.7 → 1.3.8

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/README.md CHANGED
@@ -22,6 +22,8 @@ Visit [you.com/platform/api-keys](https://you.com/platform/api-keys) to get your
22
22
 
23
23
  ### 2. Choose your setup
24
24
 
25
+ You can discover this server in the [Anthropic MCP Registry](https://registry.modelcontextprotocol.io/) as `io.github.youdotcom-oss/mcp`, or configure it manually:
26
+
25
27
  **Remote server (recommended)** - No installation, always up-to-date, just add the URL and API key
26
28
  - Use `https://api.you.com/mcp` with HTTP transport
27
29
  - Authentication via `Authorization: Bearer <your-key>` header
package/bin/stdio.js CHANGED
@@ -12155,7 +12155,7 @@ class StdioServerTransport {
12155
12155
  // package.json
12156
12156
  var package_default = {
12157
12157
  name: "@youdotcom-oss/mcp",
12158
- version: "1.3.7",
12158
+ version: "1.3.8",
12159
12159
  description: "You.com API Model Context Protocol Server",
12160
12160
  license: "MIT",
12161
12161
  engines: {
@@ -12214,6 +12214,7 @@ var package_default = {
12214
12214
  "test:coverage:watch": "bun test --coverage --watch",
12215
12215
  "test:watch": "bun test --watch"
12216
12216
  },
12217
+ mcpName: "io.github.youdotcom-oss/mcp",
12217
12218
  dependencies: {
12218
12219
  zod: "^4.1.13",
12219
12220
  "@hono/mcp": "^0.2.0",
@@ -20062,8 +20063,8 @@ var getMCpServer = () => new McpServer({
20062
20063
  // src/search/search.schemas.ts
20063
20064
  var SearchQuerySchema = object({
20064
20065
  query: string2().min(1, "Query is required").describe("Search query (supports +, -, site:, filetype:, lang:)"),
20065
- count: number2().int().min(1).max(20).optional().describe("Max results per section"),
20066
- freshness: _enum(["day", "week", "month", "year"]).optional().describe("Filter by freshness"),
20066
+ count: number2().int().min(1).max(100).optional().describe("Max results per section"),
20067
+ freshness: string2().optional().describe("day/week/month/year or YYYY-MM-DDtoYYYY-MM-DD"),
20067
20068
  offset: number2().int().min(0).max(9).optional().describe("Pagination offset"),
20068
20069
  country: _enum([
20069
20070
  "AR",
@@ -20108,7 +20109,9 @@ var SearchQuerySchema = object({
20108
20109
  fileType: string2().optional().describe("File type"),
20109
20110
  language: string2().optional().describe("ISO 639-1 language code"),
20110
20111
  excludeTerms: string2().optional().describe("Terms to exclude (pipe-separated)"),
20111
- exactTerms: string2().optional().describe("Exact terms (pipe-separated)")
20112
+ exactTerms: string2().optional().describe("Exact terms (pipe-separated)"),
20113
+ livecrawl: _enum(["web", "news", "all"]).optional().describe("Live-crawl sections for full content"),
20114
+ livecrawl_formats: _enum(["html", "markdown"]).optional().describe("Format for crawled content")
20112
20115
  });
20113
20116
  var WebResultSchema = object({
20114
20117
  url: string2().describe("URL"),
@@ -20116,16 +20119,27 @@ var WebResultSchema = object({
20116
20119
  description: string2().describe("Description"),
20117
20120
  snippets: array(string2()).describe("Content snippets"),
20118
20121
  page_age: string2().optional().describe("Publication timestamp"),
20119
- authors: array(string2()).optional().describe("Authors")
20122
+ authors: array(string2()).optional().describe("Authors"),
20123
+ thumbnail_url: string2().optional().describe("Thumbnail image URL"),
20124
+ favicon_url: string2().optional().describe("Favicon URL"),
20125
+ contents: object({
20126
+ html: string2().optional().describe("Full HTML content"),
20127
+ markdown: string2().optional().describe("Full Markdown content")
20128
+ }).optional().describe("Live-crawled page content")
20120
20129
  });
20121
20130
  var NewsResultSchema = object({
20122
20131
  title: string2().describe("Title"),
20123
20132
  description: string2().describe("Description"),
20124
20133
  page_age: string2().describe("Publication timestamp"),
20125
- url: string2().describe("URL")
20134
+ url: string2().describe("URL"),
20135
+ thumbnail_url: string2().optional().describe("Thumbnail image URL"),
20136
+ contents: object({
20137
+ html: string2().optional().describe("Full HTML content"),
20138
+ markdown: string2().optional().describe("Full Markdown content")
20139
+ }).optional().describe("Live-crawled page content")
20126
20140
  });
20127
20141
  var MetadataSchema = object({
20128
- request_uuid: string2().optional().describe("Request ID"),
20142
+ search_uuid: string2().optional().describe("Unique search request ID"),
20129
20143
  query: string2().describe("Query"),
20130
20144
  latency: number2().describe("Latency in seconds")
20131
20145
  });
@@ -20164,7 +20178,7 @@ var fetchSearchResults = async ({
20164
20178
  const searchParams = new URLSearchParams;
20165
20179
  const searchQuery = [query];
20166
20180
  site && searchQuery.push(`site:${site}`);
20167
- fileType && searchQuery.push(`fileType:${fileType}`);
20181
+ fileType && searchQuery.push(`filetype:${fileType}`);
20168
20182
  language && searchQuery.push(`lang:${language}`);
20169
20183
  if (exactTerms && excludeTerms) {
20170
20184
  throw new Error("Cannot specify both exactTerms and excludeTerms - please use only one");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youdotcom-oss/mcp",
3
- "version": "1.3.7",
3
+ "version": "1.3.8",
4
4
  "description": "You.com API Model Context Protocol Server",
5
5
  "license": "MIT",
6
6
  "engines": {
@@ -59,6 +59,7 @@
59
59
  "test:coverage:watch": "bun test --coverage --watch",
60
60
  "test:watch": "bun test --watch"
61
61
  },
62
+ "mcpName": "io.github.youdotcom-oss/mcp",
62
63
  "dependencies": {
63
64
  "zod": "^4.1.13",
64
65
  "@hono/mcp": "^0.2.0",
@@ -2,8 +2,8 @@ import * as z from 'zod';
2
2
 
3
3
  export const SearchQuerySchema = z.object({
4
4
  query: z.string().min(1, 'Query is required').describe('Search query (supports +, -, site:, filetype:, lang:)'),
5
- count: z.number().int().min(1).max(20).optional().describe('Max results per section'),
6
- freshness: z.enum(['day', 'week', 'month', 'year']).optional().describe('Filter by freshness'),
5
+ count: z.number().int().min(1).max(100).optional().describe('Max results per section'),
6
+ freshness: z.string().optional().describe('day/week/month/year or YYYY-MM-DDtoYYYY-MM-DD'),
7
7
  offset: z.number().int().min(0).max(9).optional().describe('Pagination offset'),
8
8
  country: z
9
9
  .enum([
@@ -52,6 +52,8 @@ export const SearchQuerySchema = z.object({
52
52
  language: z.string().optional().describe('ISO 639-1 language code'),
53
53
  excludeTerms: z.string().optional().describe('Terms to exclude (pipe-separated)'),
54
54
  exactTerms: z.string().optional().describe('Exact terms (pipe-separated)'),
55
+ livecrawl: z.enum(['web', 'news', 'all']).optional().describe('Live-crawl sections for full content'),
56
+ livecrawl_formats: z.enum(['html', 'markdown']).optional().describe('Format for crawled content'),
55
57
  });
56
58
 
57
59
  export type SearchQuery = z.infer<typeof SearchQuerySchema>;
@@ -63,6 +65,15 @@ const WebResultSchema = z.object({
63
65
  snippets: z.array(z.string()).describe('Content snippets'),
64
66
  page_age: z.string().optional().describe('Publication timestamp'),
65
67
  authors: z.array(z.string()).optional().describe('Authors'),
68
+ thumbnail_url: z.string().optional().describe('Thumbnail image URL'),
69
+ favicon_url: z.string().optional().describe('Favicon URL'),
70
+ contents: z
71
+ .object({
72
+ html: z.string().optional().describe('Full HTML content'),
73
+ markdown: z.string().optional().describe('Full Markdown content'),
74
+ })
75
+ .optional()
76
+ .describe('Live-crawled page content'),
66
77
  });
67
78
 
68
79
  const NewsResultSchema = z.object({
@@ -70,12 +81,20 @@ const NewsResultSchema = z.object({
70
81
  description: z.string().describe('Description'),
71
82
  page_age: z.string().describe('Publication timestamp'),
72
83
  url: z.string().describe('URL'),
84
+ thumbnail_url: z.string().optional().describe('Thumbnail image URL'),
85
+ contents: z
86
+ .object({
87
+ html: z.string().optional().describe('Full HTML content'),
88
+ markdown: z.string().optional().describe('Full Markdown content'),
89
+ })
90
+ .optional()
91
+ .describe('Live-crawled page content'),
73
92
  });
74
93
 
75
94
  export type NewsResult = z.infer<typeof NewsResultSchema>;
76
95
 
77
96
  const MetadataSchema = z.object({
78
- request_uuid: z.string().optional().describe('Request ID'),
97
+ search_uuid: z.string().optional().describe('Unique search request ID'),
79
98
  query: z.string().describe('Query'),
80
99
  latency: z.number().describe('Latency in seconds'),
81
100
  });
@@ -91,7 +110,7 @@ export const SearchResponseSchema = z.object({
91
110
  export type SearchResponse = z.infer<typeof SearchResponseSchema>;
92
111
 
93
112
  // Minimal schema for structuredContent (reduces payload duplication)
94
- // Excludes metadata (query, request_uuid, latency) as these are not actionable by LLM
113
+ // Excludes metadata (query, search_uuid, latency) as these are not actionable by LLM
95
114
  export const SearchStructuredContentSchema = z.object({
96
115
  resultCounts: z.object({
97
116
  web: z.number().describe('Web results'),
@@ -18,7 +18,7 @@ export const fetchSearchResults = async ({
18
18
  // Build Query Param
19
19
  const searchQuery = [query];
20
20
  site && searchQuery.push(`site:${site}`);
21
- fileType && searchQuery.push(`fileType:${fileType}`);
21
+ fileType && searchQuery.push(`filetype:${fileType}`);
22
22
  language && searchQuery.push(`lang:${language}`);
23
23
  if (exactTerms && excludeTerms) {
24
24
  throw new Error('Cannot specify both exactTerms and excludeTerms - please use only one');
@@ -22,8 +22,8 @@ describe('fetchSearchResults', () => {
22
22
  expect(typeof result.metadata?.query).toBe('string');
23
23
 
24
24
  // Optional fields: only assert type if present
25
- if (result.metadata?.request_uuid !== undefined) {
26
- expect(typeof result.metadata.request_uuid).toBe('string');
25
+ if (result.metadata?.search_uuid !== undefined) {
26
+ expect(typeof result.metadata.search_uuid).toBe('string');
27
27
  }
28
28
  });
29
29
 
@@ -66,6 +66,52 @@ describe('fetchSearchResults', () => {
66
66
  expect(newsResult).toHaveProperty('description');
67
67
  expect(newsResult).toHaveProperty('page_age');
68
68
  });
69
+
70
+ test('handles livecrawl parameters', async () => {
71
+ const result = await fetchSearchResults({
72
+ searchQuery: {
73
+ query: 'python tutorial',
74
+ count: 2,
75
+ livecrawl: 'web',
76
+ livecrawl_formats: 'markdown',
77
+ },
78
+ getUserAgent,
79
+ });
80
+
81
+ expect(result.results.web?.length).toBeLessThanOrEqual(2);
82
+ // If livecrawl worked, results should have contents field
83
+ if (result.results.web?.[0]?.contents) {
84
+ expect(result.results.web[0].contents).toHaveProperty('markdown');
85
+ expect(typeof result.results.web[0].contents.markdown).toBe('string');
86
+ }
87
+ });
88
+
89
+ test('handles freshness date ranges', async () => {
90
+ const result = await fetchSearchResults({
91
+ searchQuery: {
92
+ query: 'AI news',
93
+ freshness: '2024-01-01to2024-12-31',
94
+ count: 3,
95
+ },
96
+ getUserAgent,
97
+ });
98
+
99
+ expect(result).toHaveProperty('results');
100
+ expect(result.metadata?.query).toContain('AI news');
101
+ });
102
+
103
+ test('handles count greater than 20', async () => {
104
+ const result = await fetchSearchResults({
105
+ searchQuery: {
106
+ query: 'machine learning',
107
+ count: 50,
108
+ },
109
+ getUserAgent,
110
+ });
111
+
112
+ expect(result.results.web?.length).toBeGreaterThan(0);
113
+ expect(result.results.web?.length).toBeLessThanOrEqual(50);
114
+ });
69
115
  });
70
116
 
71
117
  describe('formatSearchResults', () => {
@@ -85,7 +131,7 @@ describe('formatSearchResults', () => {
85
131
  news: [],
86
132
  },
87
133
  metadata: {
88
- request_uuid: 'test-uuid',
134
+ search_uuid: 'test-uuid',
89
135
  query: 'test query',
90
136
  latency: 0.1,
91
137
  },
@@ -132,7 +178,7 @@ describe('formatSearchResults', () => {
132
178
  ],
133
179
  },
134
180
  metadata: {
135
- request_uuid: 'test-uuid',
181
+ search_uuid: 'test-uuid',
136
182
  query: 'test query',
137
183
  latency: 0.1,
138
184
  },
@@ -182,7 +228,7 @@ describe('formatSearchResults', () => {
182
228
  ],
183
229
  },
184
230
  metadata: {
185
- request_uuid: 'test-uuid',
231
+ search_uuid: 'test-uuid',
186
232
  query: 'test query',
187
233
  latency: 0.1,
188
234
  },