@youdotcom-oss/mcp 1.3.2 → 1.3.4

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/AGENTS.md CHANGED
@@ -13,6 +13,7 @@ A Model Context Protocol (MCP) server that provides web search, AI agent, and co
13
13
  > **Note for end users**: If you want to use this MCP server (not develop or contribute), see [README.md](./README.md) for setup instructions, getting started guides, and usage examples.
14
14
 
15
15
  **This guide (AGENTS.md) is for developers, contributors, and AI coding agents** who want to:
16
+
16
17
  - Set up a local development environment
17
18
  - Understand the codebase architecture
18
19
  - Contribute code or bug fixes
@@ -24,11 +25,11 @@ A Model Context Protocol (MCP) server that provides web search, AI agent, and co
24
25
  ## Tech Stack
25
26
 
26
27
  - **Runtime**: Bun >= 1.2.21 (not Node.js)
27
- - **Framework**: Model Context Protocol SDK v1.22.0
28
+ - **Framework**: Model Context Protocol SDK v1.24.0
28
29
  - **HTTP Server**: Hono v4.10.6 with @hono/mcp for HTTP transport (SSE protocol support)
29
30
  - **Validation**: Zod 3.25.76 for schema validation
30
31
  - **Testing**: Bun test (built-in test runner)
31
- - **Code Quality**: Biome 2.3.6 (linter + formatter)
32
+ - **Code Quality**: Biome 2.3.7 (linter + formatter)
32
33
  - **Type Checking**: TypeScript 5.9.3
33
34
  - **Git Hooks**: lint-staged 16.2.7
34
35
 
@@ -48,17 +49,20 @@ bun install # Install dependencies
48
49
  bun run dev # Start stdio server
49
50
  bun start # Start HTTP server on port 4000
50
51
  bun test # Run tests
52
+ bun test:coverage # Run tests with coverage report
53
+ bun test:watch # Run tests in watch mode
51
54
  bun run check # Run all checks (biome + types + package format)
52
55
  bun run check:write # Auto-fix all issues
53
56
  ```
54
57
 
55
58
  ## Code Style
56
59
 
57
- This project uses [Biome](https://biomejs.dev/) for automated code formatting and linting. Most style rules are enforced automatically via git hooks (see `biome.json:55`).
60
+ This project uses [Biome](https://biomejs.dev/) for automated code formatting and linting. Most style rules are enforced automatically via git hooks.
58
61
 
59
62
  ### Manual Adherence Required
60
63
 
61
64
  **Arrow Functions**: Always use arrow functions for declarations (not enforced by Biome)
65
+
62
66
  ```ts
63
67
  // ✅ Preferred
64
68
  export const fetchData = async (params: Params) => { ... };
@@ -68,6 +72,7 @@ export async function fetchData(params: Params) { ... }
68
72
  ```
69
73
 
70
74
  **No Unused Exports**: All exports must be actively used (Biome detects unused variables/imports, but NOT unused exports)
75
+
71
76
  ```bash
72
77
  # Before adding exports, verify usage:
73
78
  grep -r "ExportName" src/
@@ -76,36 +81,45 @@ grep -r "ExportName" src/
76
81
  ### MCP-Specific Patterns
77
82
 
78
83
  **Schema Design**: Always use Zod for input/output validation
84
+
79
85
  ```ts
80
86
  export const MyToolInputSchema = z.object({
81
- query: z.string().min(1).describe('Search query'),
82
- limit: z.number().optional().describe('Max results'),
87
+ query: z.string().min(1).describe("Search query"),
88
+ limit: z.number().optional().describe("Max results"),
83
89
  });
84
90
  ```
85
91
 
86
92
  **Error Handling**: Always use try/catch with typed error handling
93
+
87
94
  ```ts
88
95
  try {
89
96
  const response = await apiCall();
90
97
  return formatResponse(response);
91
98
  } catch (err: unknown) {
92
99
  const errorMessage = err instanceof Error ? err.message : String(err);
93
- await logger({ level: 'error', data: `API call failed: ${errorMessage}` });
94
- return { content: [{ type: 'text', text: `Error: ${errorMessage}` }], isError: true };
100
+ await logger({ level: "error", data: `API call failed: ${errorMessage}` });
101
+ return {
102
+ content: [{ type: "text", text: `Error: ${errorMessage}` }],
103
+ isError: true,
104
+ };
95
105
  }
96
106
  ```
97
107
 
98
108
  **Logging**: Use `getLogger(mcp)` helper, never console.log
109
+
99
110
  ```ts
111
+ import { getLogger } from "../shared/get-logger.ts";
112
+
100
113
  const logger = getLogger(mcp);
101
- await logger({ level: 'info', data: `Operation successful: ${result}` });
102
- await logger({ level: 'error', data: `Operation failed: ${errorMessage}` });
114
+ await logger({ level: "info", data: `Operation successful: ${result}` });
115
+ await logger({ level: "error", data: `Operation failed: ${errorMessage}` });
103
116
  ```
104
117
 
105
118
  **Response Format**: Return both `content` and `structuredContent`
119
+
106
120
  ```ts
107
121
  return {
108
- content: [{ type: 'text', text: formattedText }],
122
+ content: [{ type: "text", text: formattedText }],
109
123
  structuredContent: responseData,
110
124
  };
111
125
  ```
@@ -153,6 +167,7 @@ bun run format:package # Format package.json only
153
167
  ## Contributing
154
168
 
155
169
  For detailed contribution guidelines, including:
170
+
156
171
  - Bug reporting
157
172
  - Feature requests
158
173
  - Pull request workflow
@@ -166,22 +181,22 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md)
166
181
  ### Tool Registration
167
182
 
168
183
  Use Zod schemas for tool parameter validation. See examples:
169
- - Search tool: `src/search/register-search-tool.ts:7-47`
170
- - Express tool: `src/express/register-express-tool.ts:7-35`
171
- - Contents tool: `src/contents/register-contents-tool.ts:7-45`
184
+
185
+ - Search tool: `src/search/register-search-tool.ts:7-86`
186
+ - Express tool: `src/express/register-express-tool.ts:7-66`
187
+ - Contents tool: `src/contents/register-contents-tool.ts:7-89`
172
188
 
173
189
  ### Error Handling
174
190
 
175
- Always use try/catch with typed error handling (`err: unknown`). See `src/search/search.utils.ts:90-105` for standard pattern.
191
+ Always use try/catch with typed error handling (`err: unknown`). See tool registration files for standard pattern.
176
192
 
177
193
  ### Logging
178
194
 
179
- Use `getLogger(mcp)` helper, never console.log. See `src/shared/shared.utils.ts:35-40` for implementation.
195
+ Use `getLogger(mcp)` helper, never console.log. See `src/shared/get-logger.ts:8-11` for implementation.
180
196
 
181
197
  ### Error Reporting
182
198
 
183
- Include mailto links in error logs using `generateErrorReportLink()` helper (`src/shared/shared.utils.ts:75-100`). This creates one-click error reporting with full diagnostic context.
184
-
199
+ Include mailto links in error logs using `generateErrorReportLink()` helper (`src/shared/generate-error-report-link.ts:6-37`). This creates one-click error reporting with full diagnostic context.
185
200
 
186
201
  ## Testing
187
202
 
@@ -192,6 +207,7 @@ Include mailto links in error logs using `generateErrorReportLink()` helper (`sr
192
207
  - **Coverage Target**: >80% for core utilities
193
208
 
194
209
  For test patterns, see:
210
+
195
211
  - Unit tests: `src/search/tests/search.utils.spec.ts`
196
212
  - Integration tests: `src/tests/tool.spec.ts`
197
213
 
@@ -200,30 +216,35 @@ For test patterns, see:
200
216
  **IMPORTANT: Avoid patterns that silently skip assertions** - they hide failures.
201
217
 
202
218
  ❌ **Early Returns** - Silently exits test, skips remaining assertions
219
+
203
220
  ```ts
204
221
  if (!item) return; // Bad: test passes even if item is undefined
205
222
  ```
206
223
 
207
224
  ❌ **Redundant Conditionals** - Asserts defined, then conditionally checks type
225
+
208
226
  ```ts
209
227
  expect(item?.markdown).toBeDefined();
210
228
  if (item?.markdown) {
211
- expect(typeof item.markdown).toBe('string'); // Redundant!
229
+ expect(typeof item.markdown).toBe("string"); // Redundant!
212
230
  }
213
231
  ```
214
232
 
215
233
  ✅ **Let tests fail naturally** - Use optional chaining and direct assertions:
234
+
216
235
  ```ts
217
236
  expect(item).toBeDefined();
218
- expect(item).toHaveProperty('url'); // Fails with clear error if undefined
237
+ expect(item).toHaveProperty("url"); // Fails with clear error if undefined
219
238
  ```
220
239
 
221
240
  ### Running Tests
222
241
 
223
242
  ```bash
224
- bun test # All tests
225
- bun test --coverage # With coverage report
226
- bun test src/search/tests/ # Specific directory
243
+ bun test # All tests
244
+ bun test:coverage # With coverage report
245
+ bun test:watch # Run tests in watch mode
246
+ bun test:coverage:watch # Coverage with watch mode
247
+ bun test src/search/tests/ # Specific directory
227
248
  ```
228
249
 
229
250
  Requires `YDC_API_KEY` environment variable for API tests.
@@ -237,6 +258,7 @@ Requires `YDC_API_KEY` environment variable for API tests.
237
258
  **Symptom**: Error message "YDC_API_KEY environment variable is required"
238
259
 
239
260
  **Solution**:
261
+
240
262
  ```bash
241
263
  # Set up .env file
242
264
  echo "export YDC_API_KEY=your-actual-api-key-here" > .env
@@ -254,6 +276,7 @@ echo $YDC_API_KEY
254
276
  **Symptom**: `bun run build` fails with TypeScript errors
255
277
 
256
278
  **Solution**:
279
+
257
280
  ```bash
258
281
  # Check TypeScript errors
259
282
  bun run check:types
@@ -271,6 +294,7 @@ bun run build
271
294
  **Symptom**: Tests fail with 429 (Too Many Requests) errors
272
295
 
273
296
  **Solution**:
297
+
274
298
  - Wait a few minutes before re-running tests
275
299
  - Run specific test suites instead of all tests at once
276
300
  - Use `bun test --bail` to stop after first failure
@@ -281,6 +305,7 @@ bun run build
281
305
  **Symptom**: Docker build fails with permission errors
282
306
 
283
307
  **Solution**:
308
+
284
309
  ```bash
285
310
  # Ensure Docker daemon is running
286
311
  docker info
@@ -297,6 +322,7 @@ groups $USER
297
322
  **Symptom**: Pre-commit hook fails or `bun run check` shows errors
298
323
 
299
324
  **Solution**:
325
+
300
326
  ```bash
301
327
  # Auto-fix most issues
302
328
  bun run check:write
@@ -318,6 +344,7 @@ bun run lint:fix
318
344
  **Symptom**: "Cannot find module" errors in TypeScript
319
345
 
320
346
  **Solution**:
347
+
321
348
  - Always use `.js` extensions in imports (even for `.ts` files)
322
349
  - Check that the file exists at the specified path
323
350
  - Use relative paths correctly (`./` for same directory, `../` for parent)
@@ -328,11 +355,13 @@ bun run lint:fix
328
355
  **Symptom**: MCP client can't connect to server
329
356
 
330
357
  **Solution for Stdio mode**:
358
+
331
359
  - Verify the path to `stdio.ts` or `stdio.js` is correct and absolute
332
360
  - Check that Bun is installed and in PATH
333
361
  - Test manually: `bun src/stdio.ts`
334
362
 
335
363
  **Solution for HTTP mode**:
364
+
336
365
  - Verify server is running: `curl http://localhost:4000/mcp-health`
337
366
  - Check port isn't in use: `lsof -i :4000` (macOS/Linux)
338
367
  - Verify Bearer token matches your API key
@@ -363,13 +392,13 @@ const validatedResponse = ResponseSchema.parse(jsonResponse);
363
392
 
364
393
  // Handle specific status codes
365
394
  if (response.status === 401) {
366
- throw new Error('Invalid or expired API key');
395
+ throw new Error("Invalid or expired API key");
367
396
  }
368
397
  if (response.status === 403) {
369
- throw new Error('API key lacks permissions for this endpoint');
398
+ throw new Error("API key lacks permissions for this endpoint");
370
399
  }
371
400
  if (response.status === 429) {
372
- throw new Error('Rate limit exceeded');
401
+ throw new Error("Rate limit exceeded");
373
402
  }
374
403
  ```
375
404
 
@@ -412,7 +441,7 @@ Content extraction from web pages
412
441
  graph TD
413
442
  Clients["MCP Clients
414
443
  (Claude Desktop, Claude Code, Custom Clients)"]
415
-
444
+
416
445
  Clients -->|"Stdio (Local)"| Stdio["src/stdio.ts
417
446
  - Process I/O
418
447
  - JSON-RPC"]
@@ -420,14 +449,14 @@ graph TD
420
449
  - /mcp
421
450
  - /mcp-health
422
451
  - Bearer Auth"]
423
-
452
+
424
453
  Stdio --> Server["src/get-mcp-server.ts
425
454
  MCP Server Factory
426
455
  - registerTool()
427
456
  - Tool Handlers
428
457
  - Logging"]
429
458
  HTTP --> Server
430
-
459
+
431
460
  Server --> Search["you-search
432
461
  - Validation
433
462
  - Query Build
@@ -440,7 +469,7 @@ graph TD
440
469
  - Validation
441
470
  - Multi-URL
442
471
  - Formatting"]
443
-
472
+
444
473
  Search -->|X-API-Key| APIs["You.com APIs
445
474
  - Search API (ydc-index.io)
446
475
  - Agent API (api.you.com)
@@ -452,6 +481,7 @@ graph TD
452
481
  ### Request Flow
453
482
 
454
483
  **Stdio Transport (Local Development)**:
484
+
455
485
  1. MCP Client sends JSON-RPC request via stdin
456
486
  2. `stdio.ts` receives and parses request
457
487
  3. Calls MCP Server with tool name + parameters
@@ -461,6 +491,7 @@ graph TD
461
491
  7. JSON-RPC response sent via stdout
462
492
 
463
493
  **HTTP Transport (Remote Deployment)**:
494
+
464
495
  1. MCP Client connects via SSE to `/mcp`
465
496
  2. Client sends tool request over SSE connection
466
497
  3. `http.ts` authenticates Bearer token
@@ -521,11 +552,24 @@ graph TD
521
552
 
522
553
  ### Shared Utilities
523
554
 
524
- - `src/shared/shared.utils.ts` - Cross-tool utilities
525
- - `useGetClientVersion(mcp)` - Returns a `getUserAgent` function that creates User-Agent strings with MCP client version info
555
+ - `src/shared/use-client-version.ts` - User-Agent generation with MCP client version info
556
+ - `useGetClientVersion(mcp)` - Returns a `getUserAgent` function for creating User-Agent strings
557
+ - `src/shared/get-logger.ts` - MCP server logging
526
558
  - `getLogger(mcp)` - Returns a logging function for MCP server notifications
559
+ - `src/shared/check-response-for-errors.ts` - API response validation
527
560
  - `checkResponseForErrors()` - Validates API responses for error fields
528
- - `generateErrorReportLink()` - Creates mailto links for error reporting
561
+ - `src/shared/generate-error-report-link.ts` - Error reporting utilities
562
+ - `generateErrorReportLink()` - Creates mailto links for one-click error reporting
563
+ - `src/shared/format-search-results-text.ts` - Search result formatting
564
+ - `formatSearchResultsText()` - Formats search results for text display
565
+
566
+ ### Library Export
567
+
568
+ - `src/main.ts` - Public API export file for library consumers
569
+ - Exports all schemas from contents, express, and search tools
570
+ - Exports utility functions from contents, express, and search
571
+ - Exports shared utilities (checkResponseForErrors, formatSearchResultsText)
572
+ - Used when consuming this package as a library (not as MCP server)
529
573
 
530
574
  ### Integration Tests
531
575
 
@@ -534,35 +578,134 @@ graph TD
534
578
 
535
579
  ## Deployment
536
580
 
537
- ### Quick Start
581
+ This section covers local development setup, self-hosting options, and production deployment strategies.
582
+
583
+ ### Local development setup
584
+
585
+ **Prerequisites:**
586
+
587
+ - Bun >= 1.2.21 installed
588
+ - You.com API key from [you.com/platform/api-keys](https://you.com/platform/api-keys)
589
+
590
+ **Quick start:**
538
591
 
539
592
  ```bash
540
- # Local development
541
- git clone <repository-url>
542
- cd you-mcp-server
593
+ # Clone repository
594
+ git clone https://github.com/youdotcom-oss/youdotcom-mcp-server.git
595
+ cd youdotcom-mcp-server
596
+
597
+ # Install dependencies
543
598
  bun install
544
- echo "export YDC_API_KEY=your-key" > .env
599
+
600
+ # Set up environment
601
+ echo "export YDC_API_KEY=your-actual-api-key-here" > .env
545
602
  source .env
546
- bun run dev # Stdio mode
547
603
 
548
- # HTTP server
549
- bun start # Port 4000
604
+ # Start development server (STDIO mode)
605
+ bun run dev
606
+
607
+ # Or start HTTP server on port 4000
608
+ bun start
609
+ ```
610
+
611
+ **Verify setup:**
612
+
613
+ ```bash
614
+ # Test STDIO mode
615
+ echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | bun src/stdio.ts
616
+
617
+ # Test HTTP mode (in separate terminal)
618
+ curl http://localhost:4000/mcp-health
619
+ ```
620
+
621
+ ### Self-hosting with Docker
622
+
623
+ **Build and run:**
550
624
 
551
- # Docker
625
+ ```bash
626
+ # Build Docker image
552
627
  docker build -t youdotcom-mcp-server .
553
- docker run -d -p 4000:4000 youdotcom-mcp-server
628
+
629
+ # Run container with API key
630
+ docker run -d \
631
+ -p 4000:4000 \
632
+ --name youdotcom-mcp \
633
+ -e YDC_API_KEY=your-actual-api-key-here \
634
+ youdotcom-mcp-server
635
+
636
+ # Check health
637
+ curl http://localhost:4000/mcp-health
554
638
  ```
555
639
 
556
- ### Deployment Modes
640
+ **Docker Compose:**
641
+
642
+ ```yaml
643
+ version: "3.8"
644
+ services:
645
+ youdotcom-mcp:
646
+ build: .
647
+ ports:
648
+ - "4000:4000"
649
+ environment:
650
+ - YDC_API_KEY=${YDC_API_KEY}
651
+ restart: unless-stopped
652
+ ```
653
+
654
+ ### Deployment modes
557
655
 
558
- | Mode | Use Case | Command |
559
- |------|----------|---------|
560
- | **Stdio Dev** | Local development | `bun run dev` |
561
- | **Stdio Prod** | MCP client integration | `./bin/stdio.js` |
562
- | **HTTP** | Web apps, remote clients | `bun start` |
563
- | **Docker** | Containerized deployment | `docker run ...` |
656
+ | Mode | Use Case | Transport | Command |
657
+ | -------------- | ------------------------------------ | --------- | ------------------------------- |
658
+ | **STDIO Dev** | Local development and testing | STDIO | `bun run dev` |
659
+ | **STDIO Prod** | MCP client integration (local) | STDIO | `./bin/stdio.js` |
660
+ | **HTTP Dev** | Local HTTP server testing | HTTP/SSE | `bun start` |
661
+ | **HTTP Prod** | Remote clients, web apps, production | HTTP/SSE | `bun run build && bun bin/http` |
662
+ | **Docker** | Containerized deployment | HTTP/SSE | `docker run ...` |
564
663
 
565
- For detailed deployment instructions, Docker configuration, and MCP client setup, see README.md.
664
+ ### Production deployment
665
+
666
+ **Building for production:**
667
+
668
+ ```bash
669
+ # Build optimized STDIO bundle
670
+ bun run build
671
+
672
+ # Outputs:
673
+ # - bin/stdio.js (compiled STDIO transport)
674
+ # Note: bin/http is an executable script, not compiled
675
+ ```
676
+
677
+ **Running in production:**
678
+
679
+ ```bash
680
+ # Set API key
681
+ export YDC_API_KEY=your-actual-api-key-here
682
+
683
+ # STDIO mode (for MCP clients)
684
+ node bin/stdio.js
685
+
686
+ # HTTP mode (for remote access)
687
+ PORT=4000 bun bin/http
688
+ ```
689
+
690
+ **Environment variables:**
691
+
692
+ | Variable | Required | Default | Description |
693
+ | ------------- | -------- | ------- | --------------------------------- |
694
+ | `YDC_API_KEY` | Yes | - | You.com API key |
695
+ | `PORT` | No | 4000 | HTTP server port (HTTP mode only) |
696
+
697
+ **Production considerations:**
698
+
699
+ - **Security**: Never expose STDIO mode to external networks
700
+ - **HTTP mode**: Use reverse proxy (nginx, Caddy) with HTTPS in production
701
+ - **Rate limiting**: Consider implementing rate limiting for HTTP endpoints
702
+ - **Monitoring**: Set up health check monitoring on `/mcp-health`
703
+ - **Logging**: MCP server logs to stderr; configure log aggregation as needed
704
+ - **API key rotation**: Restart server after rotating API keys
705
+
706
+ ### MCP client configuration
707
+
708
+ For connecting MCP clients to your self-hosted server, see the "Adding to your MCP client" section in [README.md](./README.md).
566
709
 
567
710
  For complete API reference documentation including parameters, response formats, and examples, see [API.md](./docs/API.md).
568
711
 
@@ -577,10 +720,11 @@ bun test # Built-in test runner
577
720
  ```
578
721
 
579
722
  **Import Extensions** (enforced by Biome):
723
+
580
724
  - Local files: `.ts` extension
581
725
  - NPM packages: `.js` extension
582
726
  - JSON files: `.json` with import assertion
583
727
 
584
728
  See `src/contents/register-contents-tool.ts:1-5` for import examples.
585
729
 
586
- **Build**: See `scripts/build.ts` for Bun.build configuration.
730
+ **Build**: Build configuration is defined in `package.json` scripts. The `bun run build` command compiles `src/stdio.ts` to `bin/stdio.js` for production use.