From 32eb17f5c9a2fc973bb5f7fc1a176c6c229675c5 Mon Sep 17 00:00:00 2001 From: Mouse Date: Tue, 7 Jul 2026 18:11:21 -0700 Subject: [PATCH 1/3] feat: add optional you.com search tool --- README.md | 48 +++++++++----- dist/index.js | 157 ++++++++++++++++++++++++++++++++++++++++++++++ package-lock.json | 8 --- src/index.ts | 137 ++++++++++++++++++++++++++++++++-------- 4 files changed, 299 insertions(+), 51 deletions(-) create mode 100755 dist/index.js diff --git a/README.md b/README.md index c67b81da..5e1595cc 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ This is a Model Context Protocol (MCP) server that integrates [AgentQL](https:// ### Tools - `extract-web-data` - extract structured data from a given 'url', using 'prompt' as a description of actual data and its fields to extract. +- `search-web` - optional You.com web search helper for finding candidate pages before extraction. Requires `YDC_API_KEY`. ## Installation @@ -33,7 +34,8 @@ npm install -g agentql-mcp "command": "npx", "args": ["-y", "agentql-mcp"], "env": { - "AGENTQL_API_KEY": "YOUR_API_KEY" + "AGENTQL_API_KEY": "YOUR_API_KEY", + "YDC_API_KEY": "YOUR_YOUCOM_API_KEY" } } } @@ -46,7 +48,7 @@ Read more about MCP configuration in Claude [here](https://modelcontextprotocol. For one-click installation, click one of the install buttons below: -[![Install with NPX in VS Code](https://img.shields.io/badge/VS_Code-NPM-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=agentql&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22agentql-mcp%22%5D%2C%22env%22%3A%7B%22AGENTQL_API_KEY%22%3A%22%24%7Binput%3AapiKey%7D%22%7D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22apiKey%22%2C%22description%22%3A%22AgentQL+API+Key%22%2C%22password%22%3Atrue%7D%5D) [![Install with NPX in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-NPM-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=agentql&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22agentql-mcp%22%5D%2C%22env%22%3A%7B%22AGENTQL_API_KEY%22%3A%22%24%7Binput%3AapiKey%7D%22%7D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22apiKey%22%2C%22description%22%3A%22AgentQL+API+Key%22%2C%22password%22%3Atrue%7D%5D&quality=insiders) +[![Install with NPX in VS Code](https://img.shields.io/badge/VS_Code-NPM-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=agentql&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22agentql-mcp%22%5D%2C%22env%22%3A%7B%22AGENTQL_API_KEY%22%3A%22%24%7Binput%3AapiKey%7D%22%2C%22YDC_API_KEY%22%3A%22%24%7Binput%3AydcApiKey%7D%22%7D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22apiKey%22%2C%22description%22%3A%22AgentQL+API+Key%22%2C%22password%22%3Atrue%7D%2C%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22ydcApiKey%22%2C%22description%22%3A%22You.com+API+Key%22%2C%22password%22%3Atrue%7D%5D) [![Install with NPX in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-NPM-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=agentql&config=%7B%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22agentql-mcp%22%5D%2C%22env%22%3A%7B%22AGENTQL_API_KEY%22%3A%22%24%7Binput%3AapiKey%7D%22%2C%22YDC_API_KEY%22%3A%22%24%7Binput%3AydcApiKey%7D%22%7D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22apiKey%22%2C%22description%22%3A%22AgentQL+API+Key%22%2C%22password%22%3Atrue%7D%2C%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22ydcApiKey%22%2C%22description%22%3A%22You.com+API+Key%22%2C%22password%22%3Atrue%7D%5D&quality=insiders) #### Manual Installation @@ -63,6 +65,12 @@ Add the following JSON block to your User Settings (JSON) file in VS Code. You c "id": "apiKey", "description": "AgentQL API Key", "password": true + }, + { + "type": "promptString", + "id": "ydcApiKey", + "description": "You.com API Key", + "password": true } ], "servers": { @@ -70,7 +78,8 @@ Add the following JSON block to your User Settings (JSON) file in VS Code. You c "command": "npx", "args": ["-y", "agentql-mcp"], "env": { - "AGENTQL_API_KEY": "${input:apiKey}" + "AGENTQL_API_KEY": "${input:apiKey}", + "YDC_API_KEY": "${input:ydcApiKey}" } } } @@ -88,6 +97,12 @@ Optionally, you can add it to a file called `.vscode/mcp.json` in your workspace "id": "apiKey", "description": "AgentQL API Key", "password": true + }, + { + "type": "promptString", + "id": "ydcApiKey", + "description": "You.com API Key", + "password": true } ], "servers": { @@ -95,7 +110,8 @@ Optionally, you can add it to a file called `.vscode/mcp.json` in your workspace "command": "npx", "args": ["-y", "agentql-mcp"], "env": { - "AGENTQL_API_KEY": "${input:apiKey}" + "AGENTQL_API_KEY": "${input:apiKey}", + "YDC_API_KEY": "${input:ydcApiKey}" } } } @@ -110,7 +126,7 @@ Optionally, you can add it to a file called `.vscode/mcp.json` in your workspace - Enter the following: - Name: "agentql" (or your preferred name) - Type: "command" - - Command: `env AGENTQL_API_KEY=YOUR_API_KEY npx -y agentql-mcp` + - Command: `env AGENTQL_API_KEY=YOUR_API_KEY YDC_API_KEY=YOUR_YOUCOM_API_KEY npx -y agentql-mcp` Read more about MCP configuration in Cursor [here](https://docs.cursor.com/context/model-context-protocol). @@ -128,7 +144,8 @@ Read more about MCP configuration in Cursor [here](https://docs.cursor.com/conte "command": "npx", "args": ["-y", "agentql-mcp"], "env": { - "AGENTQL_API_KEY": "YOUR_API_KEY" + "AGENTQL_API_KEY": "YOUR_API_KEY", + "YDC_API_KEY": "YOUR_YOUCOM_API_KEY" } } } @@ -145,6 +162,12 @@ Give your agent a task that will require extracting data from the web. For examp Extract the list of videos from the page https://www.youtube.com/results?search_query=agentql, every video should have a title, an author name, a number of views and a url to the video. Make sure to exclude ads items. Format this as a markdown table. ``` +Or use the optional You.com helper first: + +```text +search-web query="playwright locator best practices" count=5 +``` + > [!TIP] > In case your agent complains that it can't open urls or load content from the web instead of using AgentQL, try adding "use tools" or "use agentql tool" hint. @@ -176,7 +199,8 @@ If you want to try out development version, you can use the following config ins "agentql": { "command": "/path/to/agentql-mcp/dist/index.js", "env": { - "AGENTQL_API_KEY": "YOUR_API_KEY" + "AGENTQL_API_KEY": "YOUR_API_KEY", + "YDC_API_KEY": "YOUR_YOUCOM_API_KEY" } } } @@ -185,13 +209,3 @@ If you want to try out development version, you can use the following config ins > [!NOTE] > Don't forget to remove the default AgentQL MCP server config to not confuse Claude with two similar servers. - -## Debugging - -Since MCP servers communicate over stdio, debugging can be challenging. We recommend using the [MCP Inspector](https://github.com/modelcontextprotocol/inspector), which is available as a package script: - -```bash -npm run inspector -``` - -The Inspector will provide a URL to access debugging tools in your browser. diff --git a/dist/index.js b/dist/index.js new file mode 100755 index 00000000..3353589f --- /dev/null +++ b/dist/index.js @@ -0,0 +1,157 @@ +#!/usr/bin/env node +import { Server } from '@modelcontextprotocol/sdk/server/index.js'; +import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; +import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'; +import fetch from 'node-fetch'; +const server = new Server({ + name: 'agentql-mcp', + version: '1.0.1', +}, { + capabilities: { + tools: {}, + }, +}); +const EXTRACT_TOOL_NAME = 'extract-web-data'; +const SEARCH_TOOL_NAME = 'search-web'; +const AGENTQL_API_KEY = process.env.AGENTQL_API_KEY; +const YDC_API_KEY = process.env.YDC_API_KEY; +if (!AGENTQL_API_KEY) { + console.error('Error: AGENTQL_API_KEY environment variable is required'); + process.exit(1); +} +function buildToolList() { + const tools = [ + { + name: EXTRACT_TOOL_NAME, + description: 'Extracts structured data as JSON from a web page given a URL using a Natural Language description of the data.', + inputSchema: { + type: 'object', + properties: { + url: { + type: 'string', + description: 'The URL of the public webpage to extract data from', + }, + prompt: { + type: 'string', + description: 'Natural Language description of the data to extract from the page', + }, + }, + required: ['url', 'prompt'], + }, + }, + ]; + if (YDC_API_KEY) { + tools.push({ + name: SEARCH_TOOL_NAME, + description: 'Searches the web with You.com and returns the top web and news results as JSON.', + inputSchema: { + type: 'object', + properties: { + query: { + type: 'string', + description: 'Search query to send to You.com', + }, + count: { + type: 'number', + description: 'Number of results per section to request', + default: 10, + }, + }, + required: ['query'], + }, + }); + } + return tools; +} +async function searchWeb(query, count = 10) { + const endpoint = new URL('https://ydc-index.io/v1/search'); + endpoint.searchParams.set('query', query); + endpoint.searchParams.set('count', String(count)); + const response = await fetch(endpoint.toString(), { + headers: { + 'X-API-Key': `${YDC_API_KEY}`, + }, + }); + if (!response.ok) { + throw new Error(`You.com API error: ${response.statusText}\n${await response.text()}`); + } + return (await response.json()); +} +server.setRequestHandler(ListToolsRequestSchema, async () => { + return { tools: buildToolList() }; +}); +server.setRequestHandler(CallToolRequestSchema, async (request) => { + switch (request.params.name) { + case EXTRACT_TOOL_NAME: { + const url = String(request.params.arguments?.url); + const prompt = String(request.params.arguments?.prompt); + if (!url || !prompt) { + throw new Error("Both 'url' and 'prompt' are required"); + } + const endpoint = 'https://api.agentql.com/v1/query-data'; + const response = await fetch(endpoint, { + method: 'POST', + headers: { + 'X-API-Key': `${AGENTQL_API_KEY}`, + 'X-TF-Request-Origin': 'mcp-server', + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + url: url, + prompt: prompt, + params: { + wait_for: 0, + is_scroll_to_bottom_enabled: false, + mode: 'fast', + is_screenshot_enabled: false, + }, + }), + }); + if (!response.ok) { + throw new Error(`AgentQL API error: ${response.statusText}\n${await response.text()}`); + } + const json = (await response.json()); + return { + content: [ + { + type: 'text', + text: JSON.stringify(json.data, null, 2), + }, + ], + }; + } + case SEARCH_TOOL_NAME: { + if (!YDC_API_KEY) { + throw new Error('YDC_API_KEY environment variable is required for search-web'); + } + const query = String(request.params.arguments?.query); + const count = Number(request.params.arguments?.count ?? 10); + if (!query) { + throw new Error("'query' is required"); + } + const json = await searchWeb(query, Number.isFinite(count) && count > 0 ? count : 10); + const results = { + web: json.results?.web ?? [], + news: json.results?.news ?? [], + }; + return { + content: [ + { + type: 'text', + text: JSON.stringify(results, null, 2), + }, + ], + }; + } + default: + throw new Error(`Unknown tool: '${request.params.name}'`); + } +}); +async function main() { + const transport = new StdioServerTransport(); + await server.connect(transport); +} +main().catch((error) => { + console.error('Server error:', error); + process.exit(1); +}); diff --git a/package-lock.json b/package-lock.json index 20bc0c77..7dbc0960 100644 --- a/package-lock.json +++ b/package-lock.json @@ -957,7 +957,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1431,7 +1430,6 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -1698,7 +1696,6 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "license": "MIT", - "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", @@ -2181,7 +2178,6 @@ "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.27.tgz", "integrity": "sha512-1yrb/+w6HWQJrUCLkJ2IF5jNIPvvFkblV5RNOYl6bV+OA6p9GLcMpHFFGTosSvHvcAUibuUukRqhlYI4z32C7Q==", "license": "MIT", - "peer": true, "engines": { "node": ">=16.9.0" } @@ -2776,7 +2772,6 @@ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -2809,7 +2804,6 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -3314,7 +3308,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3416,7 +3409,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/src/index.ts b/src/index.ts index da8bf8b3..dc0c1eb7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,12 +4,24 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js' import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'; import fetch from 'node-fetch'; -// Interface for parsing AQL REST API response. interface AqlResponse { data: object; } -// Create an MCP server with only tools capability (trigger 'query-data' call). +interface YoucomSearchResult { + url: string; + title?: string; + description?: string; + snippets?: string[]; +} + +interface YoucomSearchResponse { + results?: { + web?: YoucomSearchResult[]; + news?: YoucomSearchResult[]; + }; +} + const server = new Server( { name: 'agentql-mcp', @@ -23,41 +35,89 @@ const server = new Server( ); const EXTRACT_TOOL_NAME = 'extract-web-data'; +const SEARCH_TOOL_NAME = 'search-web'; const AGENTQL_API_KEY = process.env.AGENTQL_API_KEY; +const YDC_API_KEY = process.env.YDC_API_KEY; if (!AGENTQL_API_KEY) { console.error('Error: AGENTQL_API_KEY environment variable is required'); process.exit(1); } -// Handler that lists available tools. -server.setRequestHandler(ListToolsRequestSchema, async () => { - return { - tools: [ - { - name: EXTRACT_TOOL_NAME, - description: - 'Extracts structured data as JSON from a web page given a URL using a Natural Language description of the data.', - inputSchema: { - type: 'object', - properties: { - url: { - type: 'string', - description: 'The URL of the public webpage to extract data from', - }, - prompt: { - type: 'string', - description: 'Natural Language description of the data to extract from the page', - }, +function buildToolList() { + const tools: Array<{ + name: string; + description: string; + inputSchema: Record; + }> = [ + { + name: EXTRACT_TOOL_NAME, + description: + 'Extracts structured data as JSON from a web page given a URL using a Natural Language description of the data.', + inputSchema: { + type: 'object', + properties: { + url: { + type: 'string', + description: 'The URL of the public webpage to extract data from', + }, + prompt: { + type: 'string', + description: 'Natural Language description of the data to extract from the page', }, - required: ['url', 'prompt'], }, + required: ['url', 'prompt'], }, - ], - }; + }, + ]; + + if (YDC_API_KEY) { + tools.push({ + name: SEARCH_TOOL_NAME, + description: 'Searches the web with You.com and returns the top web and news results as JSON.', + inputSchema: { + type: 'object', + properties: { + query: { + type: 'string', + description: 'Search query to send to You.com', + }, + count: { + type: 'number', + description: 'Number of results per section to request', + default: 10, + }, + }, + required: ['query'], + }, + }); + } + + return tools; +} + +async function searchWeb(query: string, count = 10) { + const endpoint = new URL('https://ydc-index.io/v1/search'); + endpoint.searchParams.set('query', query); + endpoint.searchParams.set('count', String(count)); + + const response = await fetch(endpoint.toString(), { + headers: { + 'X-API-Key': `${YDC_API_KEY}`, + }, + }); + + if (!response.ok) { + throw new Error(`You.com API error: ${response.statusText}\n${await response.text()}`); + } + + return (await response.json()) as YoucomSearchResponse; +} + +server.setRequestHandler(ListToolsRequestSchema, async () => { + return { tools: buildToolList() }; }); -// Handler for the 'extract-web-data' tool. server.setRequestHandler(CallToolRequestSchema, async (request) => { switch (request.params.name) { case EXTRACT_TOOL_NAME: { @@ -103,12 +163,37 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { }; } + case SEARCH_TOOL_NAME: { + if (!YDC_API_KEY) { + throw new Error('YDC_API_KEY environment variable is required for search-web'); + } + const query = String(request.params.arguments?.query); + const count = Number(request.params.arguments?.count ?? 10); + if (!query) { + throw new Error("'query' is required"); + } + + const json = await searchWeb(query, Number.isFinite(count) && count > 0 ? count : 10); + const results = { + web: json.results?.web ?? [], + news: json.results?.news ?? [], + }; + + return { + content: [ + { + type: 'text', + text: JSON.stringify(results, null, 2), + }, + ], + }; + } + default: throw new Error(`Unknown tool: '${request.params.name}'`); } }); -// Start the server using stdio transport. async function main() { const transport = new StdioServerTransport(); await server.connect(transport); From b4eeddaa91a0887bd7b130f7298ef7b44bbf4522 Mon Sep 17 00:00:00 2001 From: Mouse Date: Tue, 7 Jul 2026 19:45:43 -0700 Subject: [PATCH 2/3] fix: harden you.com search tool input handling --- dist/index.js | 8 +++++--- src/index.ts | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/dist/index.js b/dist/index.js index 3353589f..02f13caa 100755 --- a/dist/index.js +++ b/dist/index.js @@ -71,6 +71,7 @@ async function searchWeb(query, count = 10) { headers: { 'X-API-Key': `${YDC_API_KEY}`, }, + signal: AbortSignal.timeout(30_000), }); if (!response.ok) { throw new Error(`You.com API error: ${response.statusText}\n${await response.text()}`); @@ -124,11 +125,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { if (!YDC_API_KEY) { throw new Error('YDC_API_KEY environment variable is required for search-web'); } - const query = String(request.params.arguments?.query); - const count = Number(request.params.arguments?.count ?? 10); - if (!query) { + const rawQuery = request.params.arguments?.query; + if (rawQuery === undefined || rawQuery === null || rawQuery === '') { throw new Error("'query' is required"); } + const query = String(rawQuery); + const count = Number(request.params.arguments?.count ?? 10); const json = await searchWeb(query, Number.isFinite(count) && count > 0 ? count : 10); const results = { web: json.results?.web ?? [], diff --git a/src/index.ts b/src/index.ts index dc0c1eb7..51b7381c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -105,6 +105,7 @@ async function searchWeb(query: string, count = 10) { headers: { 'X-API-Key': `${YDC_API_KEY}`, }, + signal: AbortSignal.timeout(30_000), }); if (!response.ok) { @@ -167,11 +168,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { if (!YDC_API_KEY) { throw new Error('YDC_API_KEY environment variable is required for search-web'); } - const query = String(request.params.arguments?.query); - const count = Number(request.params.arguments?.count ?? 10); - if (!query) { + const rawQuery = request.params.arguments?.query; + if (rawQuery === undefined || rawQuery === null || rawQuery === '') { throw new Error("'query' is required"); } + const query = String(rawQuery); + const count = Number(request.params.arguments?.count ?? 10); const json = await searchWeb(query, Number.isFinite(count) && count > 0 ? count : 10); const results = { From 9e378afc9f19cb3ecb3b718bd72b313152382023 Mon Sep 17 00:00:00 2001 From: Mouse Date: Thu, 9 Jul 2026 12:58:46 -0700 Subject: [PATCH 3/3] fix: handle missing search query --- dist/index.js | 8 +++++--- src/index.ts | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/dist/index.js b/dist/index.js index 02f13caa..c5075904 100755 --- a/dist/index.js +++ b/dist/index.js @@ -84,11 +84,13 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { server.setRequestHandler(CallToolRequestSchema, async (request) => { switch (request.params.name) { case EXTRACT_TOOL_NAME: { - const url = String(request.params.arguments?.url); - const prompt = String(request.params.arguments?.prompt); - if (!url || !prompt) { + const rawUrl = request.params.arguments?.url; + const rawPrompt = request.params.arguments?.prompt; + if (rawUrl === undefined || rawUrl === null || rawUrl === '' || rawPrompt === undefined || rawPrompt === null || rawPrompt === '') { throw new Error("Both 'url' and 'prompt' are required"); } + const url = String(rawUrl); + const prompt = String(rawPrompt); const endpoint = 'https://api.agentql.com/v1/query-data'; const response = await fetch(endpoint, { method: 'POST', diff --git a/src/index.ts b/src/index.ts index 51b7381c..bad2d062 100644 --- a/src/index.ts +++ b/src/index.ts @@ -122,11 +122,13 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { server.setRequestHandler(CallToolRequestSchema, async (request) => { switch (request.params.name) { case EXTRACT_TOOL_NAME: { - const url = String(request.params.arguments?.url); - const prompt = String(request.params.arguments?.prompt); - if (!url || !prompt) { + const rawUrl = request.params.arguments?.url; + const rawPrompt = request.params.arguments?.prompt; + if (rawUrl === undefined || rawUrl === null || rawUrl === '' || rawPrompt === undefined || rawPrompt === null || rawPrompt === '') { throw new Error("Both 'url' and 'prompt' are required"); } + const url = String(rawUrl); + const prompt = String(rawPrompt); const endpoint = 'https://api.agentql.com/v1/query-data'; const response = await fetch(endpoint, {