@youdotcom-oss/mcp 1.1.6 → 1.2.1

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.
Files changed (3) hide show
  1. package/README.md +121 -5
  2. package/bin/stdio.js +373 -145
  3. package/package.json +12 -11
package/README.md CHANGED
@@ -34,6 +34,115 @@ This server can be integrated with MCP clients in two ways:
34
34
  }
35
35
  ```
36
36
 
37
+ ### you-express
38
+
39
+ Fast AI-powered agent for quick responses with optional real-time web search integration.
40
+
41
+ **Parameters:**
42
+ - `input` (string, required): The query or instruction to send to the Express agent. Example: "What is the capital of France?"
43
+ - `tools` (array, optional): Array of tool objects to expand the agent's capabilities. Currently supports:
44
+ - `{ type: "web_search" }` - Enables real-time web search to provide more accurate and up-to-date information
45
+
46
+ **Features:**
47
+ - Fast response times optimized for straightforward queries
48
+ - Optional web search integration for real-time information
49
+ - AI-synthesized answers with source citations (when web_search is enabled)
50
+ - Progress notifications support (when client provides `progressToken` in request metadata)
51
+ - Non-streaming JSON responses for reliability
52
+
53
+ **Response Structure:**
54
+
55
+ The tool returns a token-efficient MCP response format:
56
+ - `answer` (string, required): AI-synthesized answer from the Express agent
57
+ - `results` (object, optional): Web search results included when `web_search` tool is used
58
+ - `web` (array): Array of search result objects, each containing:
59
+ - `url` (string): The URL of the search result
60
+ - `title` (string): The title of the search result
61
+ - `snippet` (string): A text snippet from the search result
62
+ - `agent` (string, optional): Agent identifier (e.g., "express")
63
+
64
+ **Example 1: Simple query without web_search**
65
+
66
+ Input:
67
+ ```json
68
+ {
69
+ "input": "What is 2 + 2?"
70
+ }
71
+ ```
72
+
73
+ Response:
74
+ ```json
75
+ {
76
+ "content": [
77
+ {
78
+ "type": "text",
79
+ "text": "Express Agent Answer:\n\n2 + 2 equals 4."
80
+ }
81
+ ],
82
+ "structuredContent": {
83
+ "answer": "2 + 2 equals 4.",
84
+ "agent": "express"
85
+ }
86
+ }
87
+ ```
88
+
89
+ **Example 2: Query with web_search enabled**
90
+
91
+ Input:
92
+ ```json
93
+ {
94
+ "input": "What is the capital of France?",
95
+ "tools": [{ "type": "web_search" }]
96
+ }
97
+ ```
98
+
99
+ Response:
100
+ ```json
101
+ {
102
+ "content": [
103
+ {
104
+ "type": "text",
105
+ "text": "Express Agent Answer:\n\nThe capital of France is Paris, the country's largest city and its political, economic, and cultural center..."
106
+ },
107
+ {
108
+ "type": "text",
109
+ "text": "\nSearch Results:\n\nTitle: Paris - Wikipedia\nURL: https://en.wikipedia.org/wiki/Paris\nSnippet: Paris is the capital and most populous city of France. With an official estimated population of 2,102,650 residents...\n\nTitle: Paris | History, Map, Population, & Facts | Britannica\nURL: https://www.britannica.com/place/Paris\nSnippet: Paris, city and capital of France, situated in the north-central part of the country..."
110
+ }
111
+ ],
112
+ "structuredContent": {
113
+ "answer": "The capital of France is Paris, the country's largest city and its political, economic, and cultural center...",
114
+ "results": {
115
+ "web": [
116
+ {
117
+ "url": "https://en.wikipedia.org/wiki/Paris",
118
+ "title": "Paris - Wikipedia",
119
+ "snippet": "Paris is the capital and most populous city of France. With an official estimated population of 2,102,650 residents..."
120
+ },
121
+ {
122
+ "url": "https://www.britannica.com/place/Paris",
123
+ "title": "Paris | History, Map, Population, & Facts | Britannica",
124
+ "snippet": "Paris, city and capital of France, situated in the north-central part of the country..."
125
+ }
126
+ ]
127
+ },
128
+ "agent": "express"
129
+ }
130
+ }
131
+ ```
132
+
133
+ **Progress Notifications:**
134
+
135
+ When a client provides a `progressToken` in the request metadata, the tool sends progress notifications at key milestones:
136
+ - 0% - Starting Express agent query
137
+ - 33% - Connecting to You.com API
138
+ - 100% - Complete (implicit with final response)
139
+
140
+ **Notes:**
141
+ - The `content` array always displays the answer first, followed by search results (if web_search was used)
142
+ - The response format is optimized for token efficiency, returning only essential fields
143
+ - Search results are formatted consistently with the `you-search` tool using shared formatting utilities
144
+ ```
145
+
37
146
  **Local NPM Package:**
38
147
  ```json
39
148
  {
@@ -364,7 +473,7 @@ echo "export YDC_API_KEY=<you-api-key>" > .env
364
473
 
365
474
  ```bash
366
475
  # Build is optional for development, required for production bin executables
367
- bun run build # Builds only stdio.ts to dist/stdio.js
476
+ bun run build # Builds only stdio.ts to bin/stdio.js
368
477
  ```
369
478
 
370
479
  **For MCP Client Integration:**
@@ -392,7 +501,7 @@ Use the full path to your local server installation in your `.mcp.json`:
392
501
  "ydc-search": {
393
502
  "type": "stdio",
394
503
  "command": "node",
395
- "args": ["/full/path/to/you-mcp-server/bin/stdio"],
504
+ "args": ["/full/path/to/you-mcp-server/bin/stdio.js"],
396
505
  "env": {
397
506
  "YDC_API_KEY": "<you-api-key>"
398
507
  }
@@ -425,15 +534,20 @@ export YDC_API_KEY="your-api-key-here"
425
534
  ### Available Scripts
426
535
 
427
536
  - `bun run dev` - Start server in stdio mode for development
428
- - `bun run build` - Build stdio.ts to dist/ for production
537
+ - `bun run build` - Build stdio.ts to bin/ for production
429
538
  - `bun start` - Start HTTP server on port 4000 (or PORT env var)
430
539
  - `bun run test` - Run test suite
540
+ - `bun run test:coverage` - Run tests with coverage report
541
+ - `bun run test:coverage:watch` - Run tests with coverage in watch mode
431
542
  - `bun run check` - Run Biome linting and formatting checks
543
+ - `bun run check:write` - Auto-fix linting and formatting issues
544
+ - `bun run inspect` - Start MCP inspector with environment variables loaded
545
+ - `bun run prepare` - Set up git hooks for the repository
432
546
 
433
547
  ### Executable Scripts
434
548
 
435
549
  The project includes executable scripts in `bin/`:
436
- - `./bin/stdio` - Stdio transport server (requires `bun run build` first)
550
+ - `./bin/stdio.js` - Stdio transport server (requires `bun run build` first)
437
551
  - `./bin/http` - HTTP transport server (runs directly from source)
438
552
 
439
553
  ### Running the Server
@@ -447,7 +561,7 @@ bun src/stdio.ts
447
561
 
448
562
  # Production mode (built distribution)
449
563
  bun run build # Build first
450
- ./bin/stdio # Run built version
564
+ ./bin/stdio.js # Run built version
451
565
  ```
452
566
 
453
567
  **HTTP Mode** - For web applications and remote clients:
@@ -541,6 +655,8 @@ To use this MCP server with Claude Code via Docker:
541
655
 
542
656
  ## API Reference
543
657
 
658
+ This MCP server provides two tools for different AI-powered workflows:
659
+
544
660
  ### you-search
545
661
 
546
662
  Performs a comprehensive web and news search using the You.com Search API.
package/bin/stdio.js CHANGED
@@ -10171,12 +10171,7 @@ var coerce = {
10171
10171
  var NEVER = INVALID;
10172
10172
  // node_modules/@modelcontextprotocol/sdk/dist/esm/types.js
10173
10173
  var LATEST_PROTOCOL_VERSION = "2025-06-18";
10174
- var SUPPORTED_PROTOCOL_VERSIONS = [
10175
- LATEST_PROTOCOL_VERSION,
10176
- "2025-03-26",
10177
- "2024-11-05",
10178
- "2024-10-07"
10179
- ];
10174
+ var SUPPORTED_PROTOCOL_VERSIONS = [LATEST_PROTOCOL_VERSION, "2025-03-26", "2024-11-05", "2024-10-07"];
10180
10175
  var JSONRPC_VERSION = "2.0";
10181
10176
  var ProgressTokenSchema = exports_external.union([exports_external.string(), exports_external.number().int()]);
10182
10177
  var CursorSchema = exports_external.string();
@@ -10236,12 +10231,7 @@ var JSONRPCErrorSchema = exports_external.object({
10236
10231
  })
10237
10232
  }).strict();
10238
10233
  var isJSONRPCError = (value) => JSONRPCErrorSchema.safeParse(value).success;
10239
- var JSONRPCMessageSchema = exports_external.union([
10240
- JSONRPCRequestSchema,
10241
- JSONRPCNotificationSchema,
10242
- JSONRPCResponseSchema,
10243
- JSONRPCErrorSchema
10244
- ]);
10234
+ var JSONRPCMessageSchema = exports_external.union([JSONRPCRequestSchema, JSONRPCNotificationSchema, JSONRPCResponseSchema, JSONRPCErrorSchema]);
10245
10235
  var EmptyResultSchema = ResultSchema.strict();
10246
10236
  var CancelledNotificationSchema = NotificationSchema.extend({
10247
10237
  method: exports_external.literal("notifications/cancelled"),
@@ -10253,7 +10243,10 @@ var CancelledNotificationSchema = NotificationSchema.extend({
10253
10243
  var IconSchema = exports_external.object({
10254
10244
  src: exports_external.string(),
10255
10245
  mimeType: exports_external.optional(exports_external.string()),
10256
- sizes: exports_external.optional(exports_external.string())
10246
+ sizes: exports_external.optional(exports_external.array(exports_external.string()))
10247
+ }).passthrough();
10248
+ var IconsSchema = exports_external.object({
10249
+ icons: exports_external.array(IconSchema).optional()
10257
10250
  }).passthrough();
10258
10251
  var BaseMetadataSchema = exports_external.object({
10259
10252
  name: exports_external.string(),
@@ -10261,9 +10254,8 @@ var BaseMetadataSchema = exports_external.object({
10261
10254
  }).passthrough();
10262
10255
  var ImplementationSchema = BaseMetadataSchema.extend({
10263
10256
  version: exports_external.string(),
10264
- websiteUrl: exports_external.optional(exports_external.string()),
10265
- icons: exports_external.optional(exports_external.array(IconSchema))
10266
- });
10257
+ websiteUrl: exports_external.optional(exports_external.string())
10258
+ }).merge(IconsSchema);
10267
10259
  var ClientCapabilitiesSchema = exports_external.object({
10268
10260
  experimental: exports_external.optional(exports_external.object({}).passthrough()),
10269
10261
  sampling: exports_external.optional(exports_external.object({}).passthrough()),
@@ -10349,15 +10341,14 @@ var ResourceSchema = BaseMetadataSchema.extend({
10349
10341
  uri: exports_external.string(),
10350
10342
  description: exports_external.optional(exports_external.string()),
10351
10343
  mimeType: exports_external.optional(exports_external.string()),
10352
- icons: exports_external.optional(exports_external.array(IconSchema)),
10353
10344
  _meta: exports_external.optional(exports_external.object({}).passthrough())
10354
- });
10345
+ }).merge(IconsSchema);
10355
10346
  var ResourceTemplateSchema = BaseMetadataSchema.extend({
10356
10347
  uriTemplate: exports_external.string(),
10357
10348
  description: exports_external.optional(exports_external.string()),
10358
10349
  mimeType: exports_external.optional(exports_external.string()),
10359
10350
  _meta: exports_external.optional(exports_external.object({}).passthrough())
10360
- });
10351
+ }).merge(IconsSchema);
10361
10352
  var ListResourcesRequestSchema = PaginatedRequestSchema.extend({
10362
10353
  method: exports_external.literal("resources/list")
10363
10354
  });
@@ -10408,9 +10399,8 @@ var PromptArgumentSchema = exports_external.object({
10408
10399
  var PromptSchema = BaseMetadataSchema.extend({
10409
10400
  description: exports_external.optional(exports_external.string()),
10410
10401
  arguments: exports_external.optional(exports_external.array(PromptArgumentSchema)),
10411
- icons: exports_external.optional(exports_external.array(IconSchema)),
10412
10402
  _meta: exports_external.optional(exports_external.object({}).passthrough())
10413
- });
10403
+ }).merge(IconsSchema);
10414
10404
  var ListPromptsRequestSchema = PaginatedRequestSchema.extend({
10415
10405
  method: exports_external.literal("prompts/list")
10416
10406
  });
@@ -10487,9 +10477,8 @@ var ToolSchema = BaseMetadataSchema.extend({
10487
10477
  required: exports_external.optional(exports_external.array(exports_external.string()))
10488
10478
  }).passthrough()),
10489
10479
  annotations: exports_external.optional(ToolAnnotationsSchema),
10490
- icons: exports_external.optional(exports_external.array(IconSchema)),
10491
10480
  _meta: exports_external.optional(exports_external.object({}).passthrough())
10492
- });
10481
+ }).merge(IconsSchema);
10493
10482
  var ListToolsRequestSchema = PaginatedRequestSchema.extend({
10494
10483
  method: exports_external.literal("tools/list")
10495
10484
  });
@@ -10514,16 +10503,7 @@ var CallToolRequestSchema = RequestSchema.extend({
10514
10503
  var ToolListChangedNotificationSchema = NotificationSchema.extend({
10515
10504
  method: exports_external.literal("notifications/tools/list_changed")
10516
10505
  });
10517
- var LoggingLevelSchema = exports_external.enum([
10518
- "debug",
10519
- "info",
10520
- "notice",
10521
- "warning",
10522
- "error",
10523
- "critical",
10524
- "alert",
10525
- "emergency"
10526
- ]);
10506
+ var LoggingLevelSchema = exports_external.enum(["debug", "info", "notice", "warning", "error", "critical", "alert", "emergency"]);
10527
10507
  var SetLevelRequestSchema = RequestSchema.extend({
10528
10508
  method: exports_external.literal("logging/setLevel"),
10529
10509
  params: BaseRequestParamsSchema.extend({
@@ -10568,11 +10548,7 @@ var CreateMessageResultSchema = ResultSchema.extend({
10568
10548
  model: exports_external.string(),
10569
10549
  stopReason: exports_external.optional(exports_external.enum(["endTurn", "stopSequence", "maxTokens"]).or(exports_external.string())),
10570
10550
  role: exports_external.enum(["user", "assistant"]),
10571
- content: exports_external.discriminatedUnion("type", [
10572
- TextContentSchema,
10573
- ImageContentSchema,
10574
- AudioContentSchema
10575
- ])
10551
+ content: exports_external.discriminatedUnion("type", [TextContentSchema, ImageContentSchema, AudioContentSchema])
10576
10552
  });
10577
10553
  var BooleanSchemaSchema = exports_external.object({
10578
10554
  type: exports_external.literal("boolean"),
@@ -10602,12 +10578,7 @@ var EnumSchemaSchema = exports_external.object({
10602
10578
  enum: exports_external.array(exports_external.string()),
10603
10579
  enumNames: exports_external.optional(exports_external.array(exports_external.string()))
10604
10580
  }).passthrough();
10605
- var PrimitiveSchemaDefinitionSchema = exports_external.union([
10606
- BooleanSchemaSchema,
10607
- StringSchemaSchema,
10608
- NumberSchemaSchema,
10609
- EnumSchemaSchema
10610
- ]);
10581
+ var PrimitiveSchemaDefinitionSchema = exports_external.union([BooleanSchemaSchema, StringSchemaSchema, NumberSchemaSchema, EnumSchemaSchema]);
10611
10582
  var ElicitRequestSchema = RequestSchema.extend({
10612
10583
  method: exports_external.literal("elicitation/create"),
10613
10584
  params: BaseRequestParamsSchema.extend({
@@ -10686,18 +10657,8 @@ var ClientNotificationSchema = exports_external.union([
10686
10657
  InitializedNotificationSchema,
10687
10658
  RootsListChangedNotificationSchema
10688
10659
  ]);
10689
- var ClientResultSchema = exports_external.union([
10690
- EmptyResultSchema,
10691
- CreateMessageResultSchema,
10692
- ElicitResultSchema,
10693
- ListRootsResultSchema
10694
- ]);
10695
- var ServerRequestSchema = exports_external.union([
10696
- PingRequestSchema,
10697
- CreateMessageRequestSchema,
10698
- ElicitRequestSchema,
10699
- ListRootsRequestSchema
10700
- ]);
10660
+ var ClientResultSchema = exports_external.union([EmptyResultSchema, CreateMessageResultSchema, ElicitResultSchema, ListRootsResultSchema]);
10661
+ var ServerRequestSchema = exports_external.union([PingRequestSchema, CreateMessageRequestSchema, ElicitRequestSchema, ListRootsRequestSchema]);
10701
10662
  var ServerNotificationSchema = exports_external.union([
10702
10663
  CancelledNotificationSchema,
10703
10664
  ProgressNotificationSchema,
@@ -10819,6 +10780,329 @@ class StdioServerTransport {
10819
10780
  });
10820
10781
  }
10821
10782
  }
10783
+ // package.json
10784
+ var package_default = {
10785
+ name: "@youdotcom-oss/mcp",
10786
+ version: "1.2.1",
10787
+ description: "You.com API Model Context Protocol Server",
10788
+ type: "module",
10789
+ bin: "bin/stdio.js",
10790
+ scripts: {
10791
+ build: "bun build ./src/stdio.ts --outfile ./bin/stdio.js --target=node",
10792
+ dev: "bun src/stdio.ts",
10793
+ inspect: "bash -c 'source .env 2>/dev/null || true; bunx @modelcontextprotocol/inspector -e YDC_API_KEY=$YDC_API_KEY bun dev'",
10794
+ start: "bun run bin/http",
10795
+ test: "bun test",
10796
+ "test:coverage": "bun test --coverage",
10797
+ "test:coverage:watch": "bun test --coverage --watch",
10798
+ check: "biome check",
10799
+ "check:write": "biome check --write",
10800
+ prepare: "git config core.hooksPath .hooks"
10801
+ },
10802
+ keywords: [
10803
+ "mcp",
10804
+ "web search",
10805
+ "model context protocol"
10806
+ ],
10807
+ author: "You.com (https://you.com)",
10808
+ license: "MIT",
10809
+ repository: {
10810
+ type: "git",
10811
+ url: "git+https://github.com/youdotcom-oss/youdotcom-mcp-server.git"
10812
+ },
10813
+ bugs: {
10814
+ url: "https://github.com/youdotcom-oss/youdotcom-mcp-server/issues"
10815
+ },
10816
+ homepage: "https://github.com/youdotcom-oss/youdotcom-mcp-server/tree/main#readme",
10817
+ files: [
10818
+ "bin/stdio.js"
10819
+ ],
10820
+ publishConfig: {
10821
+ access: "public"
10822
+ },
10823
+ engines: {
10824
+ node: ">=18",
10825
+ bun: ">= 1.2.21"
10826
+ },
10827
+ devDependencies: {
10828
+ "@biomejs/biome": "2.3.2",
10829
+ "@commitlint/cli": "^20.1.0",
10830
+ "@commitlint/config-conventional": "^20.0.0",
10831
+ "@eslint/js": "9.38.0",
10832
+ "@modelcontextprotocol/inspector": "0.17.2",
10833
+ "@types/bun": "latest",
10834
+ typescript: "5.9.3",
10835
+ "lint-staged": "^16.2.6",
10836
+ "@hono/bun-compress": "0.1.0",
10837
+ "@hono/mcp": "0.1.5",
10838
+ "@modelcontextprotocol/sdk": "1.20.2",
10839
+ hono: "^4.10.4",
10840
+ neverthrow: "8.2.0",
10841
+ zod: "3.25.76"
10842
+ },
10843
+ "lint-staged": {
10844
+ "*.{ts,tsx,json}": [
10845
+ "bunx @biomejs/biome check --write"
10846
+ ]
10847
+ }
10848
+ };
10849
+
10850
+ // src/shared/shared.utils.ts
10851
+ var useGetClientVersion = (mcp) => () => {
10852
+ const clientVersion = mcp.server.getClientVersion();
10853
+ if (clientVersion) {
10854
+ const { name, version, title, websiteUrl } = clientVersion;
10855
+ return [name, version, title, websiteUrl].filter(Boolean).join("; ");
10856
+ }
10857
+ return "UNKNOWN";
10858
+ };
10859
+ var setUserAgent = (client) => `MCP/${package_default.version} (You.com; ${client})`;
10860
+ var getLogger = (mcp) => async (params, _sessionId) => {
10861
+ await mcp.server.sendLoggingMessage(params);
10862
+ };
10863
+ var checkResponseForErrors = (responseData) => {
10864
+ if (typeof responseData === "object" && responseData !== null && "error" in responseData) {
10865
+ const errorMessage = typeof responseData.error === "string" ? responseData.error : JSON.stringify(responseData.error);
10866
+ throw new Error(`You.com API Error: ${errorMessage}`);
10867
+ }
10868
+ return responseData;
10869
+ };
10870
+ var formatSearchResultItem = (result, _index) => {
10871
+ const parts = [`Title: ${result.title}`, `URL: ${result.url}`];
10872
+ if (result.description) {
10873
+ parts.push(`Description: ${result.description}`);
10874
+ }
10875
+ if (result.snippets && result.snippets.length > 0) {
10876
+ parts.push(`Snippets:
10877
+ - ${result.snippets.join(`
10878
+ - `)}`);
10879
+ } else if (result.snippet) {
10880
+ parts.push(`Snippet: ${result.snippet}`);
10881
+ }
10882
+ return parts.join(`
10883
+ `);
10884
+ };
10885
+ var formatSearchResultsText = (results) => {
10886
+ return results.map((result, index) => formatSearchResultItem(result, index + 1)).join(`
10887
+
10888
+ `);
10889
+ };
10890
+
10891
+ // src/express/express.schemas.ts
10892
+ var ExpressAgentInputSchema = objectType({
10893
+ input: stringType().min(1, "Input is required").describe('The query or prompt to send to the Express agent. Example: "What is the capital of France?"'),
10894
+ tools: arrayType(objectType({
10895
+ type: enumType(["web_search"]).describe('Tool type: currently only "web_search" is supported for Express agent')
10896
+ })).optional().describe("Tools the system can call to expand its capabilities, providing more precise answers. Currently supports web search only.")
10897
+ });
10898
+ var ApiSearchResultItemSchema = objectType({
10899
+ source_type: stringType().optional(),
10900
+ citation_uri: stringType().optional(),
10901
+ url: stringType(),
10902
+ title: stringType(),
10903
+ snippet: stringType(),
10904
+ thumbnail_url: stringType().optional(),
10905
+ provider: anyType().optional()
10906
+ });
10907
+ var ExpressAgentApiOutputItemSchema = unionType([
10908
+ objectType({
10909
+ type: literalType("web_search.results"),
10910
+ content: arrayType(ApiSearchResultItemSchema)
10911
+ }),
10912
+ objectType({
10913
+ type: literalType("message.answer"),
10914
+ text: stringType()
10915
+ })
10916
+ ]);
10917
+ var ExpressAgentApiResponseSchema = objectType({
10918
+ output: arrayType(ExpressAgentApiOutputItemSchema),
10919
+ agent: stringType().optional().describe("The agent identifier at the response level."),
10920
+ mode: stringType().optional().describe("The mode used for the agent."),
10921
+ input: arrayType(anyType()).optional().describe("The input messages sent to the agent.")
10922
+ }).passthrough();
10923
+ var McpSearchResultItemSchema = objectType({
10924
+ url: stringType().describe("The URL of the search result."),
10925
+ title: stringType().describe("The title of the search result."),
10926
+ snippet: stringType().describe("A text snippet from the search result.")
10927
+ });
10928
+ var ExpressAgentMcpResponseSchema = objectType({
10929
+ answer: stringType().describe("The AI-synthesized answer from Express agent."),
10930
+ results: objectType({
10931
+ web: arrayType(McpSearchResultItemSchema).describe("Array of web search results.")
10932
+ }).optional().describe("Web search results when web_search tool is used."),
10933
+ agent: stringType().optional().describe("The agent identifier at the response level.")
10934
+ });
10935
+ var ExpressAgentResponseSchema = ExpressAgentMcpResponseSchema;
10936
+ var ExpressAgentErrorSchema = objectType({
10937
+ errors: arrayType(objectType({
10938
+ status: stringType(),
10939
+ code: stringType(),
10940
+ title: stringType(),
10941
+ detail: stringType()
10942
+ }))
10943
+ });
10944
+
10945
+ // src/express/express.utils.ts
10946
+ var AGENTS_RUN_URL = "https://api.you.com/v1/agents/runs";
10947
+ var agentThrowOnFailedStatus = async (response) => {
10948
+ const errorCode = response.status;
10949
+ const errorData = await response.json();
10950
+ checkResponseForErrors(errorData);
10951
+ if (errorCode === 400) {
10952
+ throw new Error(`Bad Request:
10953
+ ${JSON.stringify(errorData)}`);
10954
+ } else if (errorCode === 401) {
10955
+ throw new Error(`Unauthorized: The Agent APIs require a valid You.com API key with agent access. Note: Agent APIs use Bearer token authentication, while Search API uses X-API-Key. Ensure your YDC_API_KEY has permissions for agent endpoints.`);
10956
+ } else if (errorCode === 403) {
10957
+ throw new Error(`Forbidden: You are not allowed to use the requested tool for this agent or tenant`);
10958
+ } else if (errorCode === 429) {
10959
+ throw new Error("Rate limited by You.com API. Please try again later.");
10960
+ }
10961
+ throw new Error(`Failed to call agent. Error code: ${errorCode}`);
10962
+ };
10963
+ var callExpressAgent = async ({
10964
+ YDC_API_KEY = process.env.YDC_API_KEY,
10965
+ agentInput: { input, tools },
10966
+ getClientVersion,
10967
+ progressToken,
10968
+ sendProgress
10969
+ }) => {
10970
+ const requestBody = {
10971
+ agent: "express",
10972
+ input,
10973
+ stream: false
10974
+ };
10975
+ if (tools) {
10976
+ requestBody.tools = tools;
10977
+ }
10978
+ if (progressToken && sendProgress) {
10979
+ await sendProgress({
10980
+ progressToken,
10981
+ progress: 33,
10982
+ total: 100,
10983
+ message: "Connecting to You.com API..."
10984
+ });
10985
+ }
10986
+ const options = {
10987
+ method: "POST",
10988
+ headers: new Headers({
10989
+ Authorization: `Bearer ${YDC_API_KEY || ""}`,
10990
+ "Content-Type": "application/json",
10991
+ Accept: "application/json",
10992
+ "User-Agent": setUserAgent(getClientVersion())
10993
+ }),
10994
+ body: JSON.stringify(requestBody)
10995
+ };
10996
+ const response = await fetch(AGENTS_RUN_URL, options);
10997
+ if (!response.ok) {
10998
+ await agentThrowOnFailedStatus(response);
10999
+ }
11000
+ const jsonResponse = await response.json();
11001
+ checkResponseForErrors(jsonResponse);
11002
+ const apiResponse = ExpressAgentApiResponseSchema.parse(jsonResponse);
11003
+ const answerItem = apiResponse.output.find((item) => item.type === "message.answer");
11004
+ const searchItem = apiResponse.output.find((item) => item.type === "web_search.results");
11005
+ const mcpResponse = {
11006
+ answer: answerItem.text,
11007
+ agent: apiResponse.agent
11008
+ };
11009
+ if (searchItem && "content" in searchItem && Array.isArray(searchItem.content)) {
11010
+ mcpResponse.results = {
11011
+ web: searchItem.content.map((item) => ({
11012
+ url: item.url || item.citation_uri || "",
11013
+ title: item.title || "",
11014
+ snippet: item.snippet || ""
11015
+ }))
11016
+ };
11017
+ }
11018
+ return mcpResponse;
11019
+ };
11020
+ var formatExpressAgentResponse = (response) => {
11021
+ const _agentId = response.agent || "express";
11022
+ const content = [];
11023
+ content.push({
11024
+ type: "text",
11025
+ text: `Express Agent Answer:
11026
+
11027
+ ${response.answer}`
11028
+ });
11029
+ if (response.results?.web?.length) {
11030
+ const formattedResults = formatSearchResultsText(response.results.web);
11031
+ content.push({
11032
+ type: "text",
11033
+ text: `
11034
+ Search Results:
11035
+
11036
+ ${formattedResults}`
11037
+ });
11038
+ }
11039
+ return {
11040
+ content,
11041
+ structuredContent: response
11042
+ };
11043
+ };
11044
+
11045
+ // src/express/register-express-tool.ts
11046
+ var registerExpressTool = ({
11047
+ mcp,
11048
+ YDC_API_KEY,
11049
+ getClientVersion
11050
+ }) => {
11051
+ mcp.registerTool("you-express", {
11052
+ title: "You.com Express Agent",
11053
+ description: "Calls the You.com Express agent for quick AI-powered responses with optional web search capabilities. Returns an AI-synthesized answer and optionally web search results when the web_search tool is used. Best for straightforward queries that benefit from real-time web information.",
11054
+ inputSchema: ExpressAgentInputSchema.shape,
11055
+ outputSchema: ExpressAgentResponseSchema.shape
11056
+ }, async (agentInput, extra) => {
11057
+ const logger = getLogger(mcp);
11058
+ const progressToken = extra?._meta?.progressToken;
11059
+ try {
11060
+ if (progressToken) {
11061
+ await mcp.server.notification({
11062
+ method: "notifications/progress",
11063
+ params: {
11064
+ progressToken,
11065
+ progress: 0,
11066
+ total: 100,
11067
+ message: "Starting Express agent query..."
11068
+ }
11069
+ });
11070
+ }
11071
+ const response = await callExpressAgent({
11072
+ agentInput,
11073
+ YDC_API_KEY,
11074
+ getClientVersion,
11075
+ progressToken,
11076
+ sendProgress: progressToken ? async (params) => {
11077
+ await mcp.server.notification({
11078
+ method: "notifications/progress",
11079
+ params
11080
+ });
11081
+ } : undefined
11082
+ });
11083
+ await logger({
11084
+ level: "info",
11085
+ data: `Express agent call successful for input: "${agentInput.input}"`
11086
+ });
11087
+ return formatExpressAgentResponse(response);
11088
+ } catch (err) {
11089
+ const errorMessage = err instanceof Error ? err.message : String(err);
11090
+ await logger({
11091
+ level: "error",
11092
+ data: `Express agent call failed: ${errorMessage}`
11093
+ });
11094
+ return {
11095
+ content: [
11096
+ {
11097
+ type: "text",
11098
+ text: `Error: ${errorMessage}`
11099
+ }
11100
+ ],
11101
+ isError: true
11102
+ };
11103
+ }
11104
+ });
11105
+ };
10822
11106
 
10823
11107
  // node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js
10824
11108
  var DEFAULT_REQUEST_TIMEOUT_MSEC = 60000;
@@ -10860,7 +11144,10 @@ class Protocol {
10860
11144
  const totalElapsed = Date.now() - info.startTime;
10861
11145
  if (info.maxTotalTimeout && totalElapsed >= info.maxTotalTimeout) {
10862
11146
  this._timeoutInfo.delete(messageId);
10863
- throw new McpError(ErrorCode.RequestTimeout, "Maximum total timeout exceeded", { maxTotalTimeout: info.maxTotalTimeout, totalElapsed });
11147
+ throw new McpError(ErrorCode.RequestTimeout, "Maximum total timeout exceeded", {
11148
+ maxTotalTimeout: info.maxTotalTimeout,
11149
+ totalElapsed
11150
+ });
10864
11151
  }
10865
11152
  clearTimeout(info.timeoutId);
10866
11153
  info.timeoutId = setTimeout(info.onTimeout, info.timeout);
@@ -12688,13 +12975,17 @@ class McpServer {
12688
12975
  title: tool.title,
12689
12976
  description: tool.description,
12690
12977
  inputSchema: tool.inputSchema ? zodToJsonSchema(tool.inputSchema, {
12691
- strictUnions: true
12978
+ strictUnions: true,
12979
+ pipeStrategy: "input"
12692
12980
  }) : EMPTY_OBJECT_JSON_SCHEMA,
12693
12981
  annotations: tool.annotations,
12694
12982
  _meta: tool._meta
12695
12983
  };
12696
12984
  if (tool.outputSchema) {
12697
- toolDefinition.outputSchema = zodToJsonSchema(tool.outputSchema, { strictUnions: true });
12985
+ toolDefinition.outputSchema = zodToJsonSchema(tool.outputSchema, {
12986
+ strictUnions: true,
12987
+ pipeStrategy: "output"
12988
+ });
12698
12989
  }
12699
12990
  return toolDefinition;
12700
12991
  })
@@ -13214,71 +13505,6 @@ var EMPTY_COMPLETION_RESULT = {
13214
13505
  hasMore: false
13215
13506
  }
13216
13507
  };
13217
- // package.json
13218
- var package_default = {
13219
- name: "@youdotcom-oss/mcp",
13220
- version: "1.1.6",
13221
- description: "You.com API Model Context Protocol Server",
13222
- type: "module",
13223
- bin: "bin/stdio.js",
13224
- scripts: {
13225
- build: "bun build ./src/stdio.ts --outfile ./bin/stdio.js --target=node",
13226
- dev: "bun src/stdio.ts",
13227
- inspect: "bash -c 'source .env 2>/dev/null || true; bunx @modelcontextprotocol/inspector -e YDC_API_KEY=$YDC_API_KEY bun dev'",
13228
- start: "bun run bin/http",
13229
- test: "bun test",
13230
- "test:coverage": "bun test --coverage",
13231
- "test:coverage:watch": "bun test --coverage --watch",
13232
- check: "biome check",
13233
- "check:write": "biome check --write",
13234
- prepare: "git config core.hooksPath .hooks"
13235
- },
13236
- keywords: [
13237
- "mcp",
13238
- "web search",
13239
- "model context protocol"
13240
- ],
13241
- author: "You.com (https://you.com)",
13242
- license: "MIT",
13243
- repository: {
13244
- type: "git",
13245
- url: "git+https://github.com/youdotcom-oss/youdotcom-mcp-server.git"
13246
- },
13247
- bugs: {
13248
- url: "https://github.com/youdotcom-oss/youdotcom-mcp-server/issues"
13249
- },
13250
- homepage: "https://github.com/youdotcom-oss/youdotcom-mcp-server/tree/main#readme",
13251
- files: [
13252
- "bin/stdio.js"
13253
- ],
13254
- publishConfig: {
13255
- access: "public"
13256
- },
13257
- engines: {
13258
- node: ">=18",
13259
- bun: ">= 1.2.21"
13260
- },
13261
- devDependencies: {
13262
- "@biomejs/biome": "2.2.4",
13263
- "@commitlint/cli": "^19.8.1",
13264
- "@commitlint/config-conventional": "^19.8.1",
13265
- "@eslint/js": "9.36.0",
13266
- "@modelcontextprotocol/inspector": "0.16.8",
13267
- "@types/bun": "latest",
13268
- typescript: "5.9.2",
13269
- "lint-staged": "^16.2.0",
13270
- "@hono/mcp": "0.1.4",
13271
- "@modelcontextprotocol/sdk": "1.18.1",
13272
- hono: "^4.9.8",
13273
- neverthrow: "8.2.0",
13274
- zod: "3.25.76"
13275
- },
13276
- "lint-staged": {
13277
- "*.{ts,tsx,json}": [
13278
- "bunx @biomejs/biome check --write"
13279
- ]
13280
- }
13281
- };
13282
13508
 
13283
13509
  // src/get-mcp-server.ts
13284
13510
  var getMCpServer = () => new McpServer({
@@ -13437,7 +13663,8 @@ var fetchSearchResults = async ({
13437
13663
  exactTerms,
13438
13664
  excludeTerms,
13439
13665
  ...rest
13440
- }
13666
+ },
13667
+ getClientVersion
13441
13668
  }) => {
13442
13669
  const url = new URL("https://api.ydc-index.io/v1/search");
13443
13670
  const searchParams = new URLSearchParams;
@@ -13459,7 +13686,8 @@ var fetchSearchResults = async ({
13459
13686
  const options = {
13460
13687
  method: "GET",
13461
13688
  headers: new Headers({
13462
- "X-API-Key": YDC_API_KEY || ""
13689
+ "X-API-Key": YDC_API_KEY || "",
13690
+ "User-Agent": setUserAgent(getClientVersion())
13463
13691
  })
13464
13692
  };
13465
13693
  const response = await fetch(url, options);
@@ -13473,22 +13701,14 @@ var fetchSearchResults = async ({
13473
13701
  throw new Error(`Failed to perform search. Error code: ${errorCode}`);
13474
13702
  }
13475
13703
  const results = await response.json();
13704
+ checkResponseForErrors(results);
13476
13705
  const parsedResults = SearchResponseSchema.parse(results);
13477
13706
  return parsedResults;
13478
13707
  };
13479
13708
  var formatSearchResults = (response) => {
13480
13709
  let formattedResults = "";
13481
13710
  if (response.results.web?.length) {
13482
- const webResults = response.results.web.map((hit) => `Title: ${hit.title}
13483
- URL: ${hit.url}
13484
- Description: ${hit.description}
13485
- Snippets:
13486
- - ${hit.snippets.join(`
13487
- - `)}`).join(`
13488
-
13489
- ---
13490
-
13491
- `);
13711
+ const webResults = formatSearchResultsText(response.results.web);
13492
13712
  formattedResults += `WEB RESULTS:
13493
13713
 
13494
13714
  ${webResults}`;
@@ -13527,22 +13747,28 @@ ${formattedResults}`
13527
13747
  };
13528
13748
 
13529
13749
  // src/search/register-search-tool.ts
13530
- var registerSearchTool = (server, YDC_API_KEY) => {
13531
- server.registerTool("you-search", {
13750
+ var registerSearchTool = ({
13751
+ mcp,
13752
+ YDC_API_KEY,
13753
+ getClientVersion
13754
+ }) => {
13755
+ mcp.registerTool("you-search", {
13532
13756
  title: "You.com Search",
13533
13757
  description: "Performs a web and news search using the You.com Search API and returns a formatted list of results.",
13534
13758
  inputSchema: SearchQuerySchema.shape,
13535
13759
  outputSchema: SearchResponseSchema.shape
13536
13760
  }, async (searchQuery) => {
13761
+ const logger = getLogger(mcp);
13537
13762
  try {
13538
13763
  const response = await fetchSearchResults({
13539
13764
  searchQuery,
13540
- YDC_API_KEY
13765
+ YDC_API_KEY,
13766
+ getClientVersion
13541
13767
  });
13542
13768
  const webCount = response.results.web?.length ?? 0;
13543
13769
  const newsCount = response.results.news?.length ?? 0;
13544
13770
  if (!webCount && !newsCount) {
13545
- await server.server.sendLoggingMessage({
13771
+ await logger({
13546
13772
  level: "info",
13547
13773
  data: `No results found for query: "${searchQuery.query}"`
13548
13774
  });
@@ -13551,14 +13777,14 @@ var registerSearchTool = (server, YDC_API_KEY) => {
13551
13777
  structuredContent: response
13552
13778
  };
13553
13779
  }
13554
- await server.server.sendLoggingMessage({
13780
+ await logger({
13555
13781
  level: "info",
13556
13782
  data: `Search successful for query: "${searchQuery.query}" - ${webCount} web results, ${newsCount} news results (${webCount + newsCount} total)`
13557
13783
  });
13558
13784
  return formatSearchResults(response);
13559
13785
  } catch (err) {
13560
13786
  const errorMessage = err instanceof Error ? err.message : String(err);
13561
- await server.server.sendLoggingMessage({
13787
+ await logger({
13562
13788
  level: "error",
13563
13789
  data: `Search API call failed: ${errorMessage}`
13564
13790
  });
@@ -13578,10 +13804,12 @@ var registerSearchTool = (server, YDC_API_KEY) => {
13578
13804
  // src/stdio.ts
13579
13805
  var YDC_API_KEY = process.env.YDC_API_KEY;
13580
13806
  try {
13581
- const mcpServer = getMCpServer();
13582
- registerSearchTool(mcpServer, YDC_API_KEY);
13807
+ const mcp = getMCpServer();
13808
+ const getClientVersion = useGetClientVersion(mcp);
13809
+ registerSearchTool({ mcp, YDC_API_KEY, getClientVersion });
13810
+ registerExpressTool({ mcp, YDC_API_KEY, getClientVersion });
13583
13811
  const transport = new StdioServerTransport;
13584
- await mcpServer.connect(transport);
13812
+ await mcp.connect(transport);
13585
13813
  } catch (error) {
13586
13814
  console.error("Failed to start server:", error);
13587
13815
  process.exit(1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@youdotcom-oss/mcp",
3
- "version": "1.1.6",
3
+ "version": "1.2.1",
4
4
  "description": "You.com API Model Context Protocol Server",
5
5
  "type": "module",
6
6
  "bin": "bin/stdio.js",
@@ -42,17 +42,18 @@
42
42
  "bun": ">= 1.2.21"
43
43
  },
44
44
  "devDependencies": {
45
- "@biomejs/biome": "2.2.4",
46
- "@commitlint/cli": "^19.8.1",
47
- "@commitlint/config-conventional": "^19.8.1",
48
- "@eslint/js": "9.36.0",
49
- "@modelcontextprotocol/inspector": "0.16.8",
45
+ "@biomejs/biome": "2.3.2",
46
+ "@commitlint/cli": "^20.1.0",
47
+ "@commitlint/config-conventional": "^20.0.0",
48
+ "@eslint/js": "9.38.0",
49
+ "@modelcontextprotocol/inspector": "0.17.2",
50
50
  "@types/bun": "latest",
51
- "typescript": "5.9.2",
52
- "lint-staged": "^16.2.0",
53
- "@hono/mcp": "0.1.4",
54
- "@modelcontextprotocol/sdk": "1.18.1",
55
- "hono": "^4.9.8",
51
+ "typescript": "5.9.3",
52
+ "lint-staged": "^16.2.6",
53
+ "@hono/bun-compress": "0.1.0",
54
+ "@hono/mcp": "0.1.5",
55
+ "@modelcontextprotocol/sdk": "1.20.2",
56
+ "hono": "^4.10.4",
56
57
  "neverthrow": "8.2.0",
57
58
  "zod": "3.25.76"
58
59
  },