search_patents
Query Google Patents with advanced filters by date, inventor, assignee, country, language, status, type, and sorting options to retrieve precise patent data.
Instructions
Searches Google Patents using SerpApi. Allows filtering by date, inventor, assignee, country, language, status, type, and sorting.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| after | No | Minimum date filter (e.g., 'publication:20230101', 'filing:20220601'). Format: type:YYYYMMDD where type is 'priority', 'filing', or 'publication'. | |
| assignee | No | Filter by assignee names. Separate multiple names with a comma (,). | |
| before | No | Maximum date filter (e.g., 'publication:20231231', 'filing:20220101'). Format: type:YYYYMMDD where type is 'priority', 'filing', or 'publication'. | |
| country | No | Filter by country codes (e.g., 'US', 'WO,JP'). Separate multiple codes with a comma (,). | |
| inventor | No | Filter by inventor names. Separate multiple names with a comma (,). | |
| language | No | Filter by language (e.g., 'ENGLISH', 'JAPANESE,GERMAN'). Separate multiple languages with a comma (,). Supported: ENGLISH, GERMAN, CHINESE, FRENCH, SPANISH, ARABIC, JAPANESE, KOREAN, PORTUGUESE, RUSSIAN, ITALIAN, DUTCH, SWEDISH, FINNISH, NORWEGIAN, DANISH. | |
| num | No | Number of results per page (default: 10). **IMPORTANT: Must be 10 or greater (up to 100).** | |
| page | No | Page number for pagination (default: 1). | |
| q | Yes | Search query (required). Although optional in SerpApi docs, a non-empty query is practically needed. Use semicolon (;) to separate multiple terms. Advanced syntax like '(Coffee) OR (Tea);(A47J)' is supported. See 'About Google Patents' for details. | |
| scholar | No | Include Google Scholar results (default: false). | |
| sort | No | Sorting method. 'relevance' (default), 'new' (newest by filing/publication date), 'old' (oldest by filing/publication date). | relevance |
| status | No | Filter by patent status: 'GRANT' or 'APPLICATION'. | |
| type | No | Filter by patent type: 'PATENT' or 'DESIGN'. |
Implementation Reference
- src/index.ts:317-386 (handler)The execution handler for the 'search_patents' tool within the CallToolRequestSchema handler. It validates inputs, constructs the SerpApi URL for Google Patents, performs the fetch with timeout, handles errors, and returns the JSON response as text content.if (name === 'search_patents') { // --- 元のコードに戻す --- const { q, ...otherParams } = args; // q は必須、その他はオプション if (!q) { logger.error('Missing required argument "q" for search_patents'); throw new McpError(400, 'Missing required argument: q'); } if (!SERPAPI_API_KEY) { logger.error('SERPAPI_API_KEY is not configured.'); throw new McpError(500, 'Server configuration error: SERPAPI_API_KEY is missing.'); } const controller = new AbortController(); // AbortController を try の前に移動 const timeoutId = setTimeout(() => controller.abort(), 30000); // 30 seconds timeout try { console.log('[DEBUG] Entered API call try block'); // tryブロック開始 // パラメータを構築 (必須パラメータ) const searchParams = new URLSearchParams({ engine: 'google_patents', q: q, api_key: SERPAPI_API_KEY }); // オプションパラメータを安全に追加 for (const [key, value] of Object.entries(otherParams)) { if (value !== undefined) { searchParams.append(key, String(value)); // 値を文字列に変換 } } const apiUrl = `https://serpapi.com/search.json?${searchParams.toString()}`; // console.log(`[DEBUG] Calling SerpApi URL: ${apiUrl}`); // デバッグ用console.log削除 logger.info(`Calling SerpApi: ${apiUrl.replace(SERPAPI_API_KEY, '****')}`); // ログにはAPIキーを隠す // Use node-fetch with AbortController for timeout (controller と timeoutId は上で定義済み) const response = await fetch(apiUrl, { signal: controller.signal }); if (!response.ok) { // Handle HTTP errors (like 4xx, 5xx) let errorBody = 'Could not retrieve error body.'; // Default error message try { errorBody = await response.text(); // Try to get error body } catch (bodyError) { logger.warn(`Failed to read error response body: ${bodyError instanceof Error ? bodyError.message : String(bodyError)}`); } logger.error(`SerpApi request failed with status ${response.status} ${response.statusText}. Response body: ${errorBody}`); // Log the actual error body throw new McpError(response.status, `SerpApi request failed: ${response.statusText}. Body: ${errorBody}`); // Include body in error } const data = await response.json(); // Parse JSON response logger.info(`SerpApi request successful for query: "${q}"`); logger.debug(`SerpApi response status: ${response.status}`); // レスポンスを type: 'text' の JSON 文字列として返す clearTimeout(timeoutId); // 成功時もタイマーをクリア return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }; } catch (error: any) { clearTimeout(timeoutId); // エラー発生時もタイマーをクリア if (error.name === 'AbortError') { logger.error(`SerpApi request timed out after 30 seconds for query "${q}"`); throw new McpError(408, 'SerpApi request timed out'); } // Handle other network errors or JSON parsing errors logger.error(`Error during fetch or JSON parsing for query "${q}": ${error.message}`); logger.error(`Unexpected error: ${error.stack}`); throw new McpError(500, `An unexpected error occurred: ${error.message}`); } finally { // finally は不要になったので削除 (clearTimeout は try の最後と catch の最初で行う) // clearTimeout(timeoutId); // try の最後でクリアするか、catch の最初でクリアする } // --- 元のコードここまで ---
- src/index.ts:281-303 (schema)The input schema definition for the 'search_patents' tool, defining parameters like query (q), pagination, filters, sorting, etc., returned in the ListTools response.{ name: 'search_patents', description: 'Searches Google Patents using SerpApi. Allows filtering by date, inventor, assignee, country, language, status, type, and sorting.', inputSchema: { type: 'object', properties: { q: { type: 'string', description: "Search query (required). Although optional in SerpApi docs, a non-empty query is practically needed. Use semicolon (;) to separate multiple terms. Advanced syntax like '(Coffee) OR (Tea);(A47J)' is supported. See 'About Google Patents' for details." }, page: { type: 'integer', description: 'Page number for pagination (default: 1).', default: 1 }, num: { type: 'integer', description: 'Number of results per page (default: 10). **IMPORTANT: Must be 10 or greater (up to 100).**', default: 10, minimum: 10, maximum: 100 }, sort: { type: 'string', enum: ['relevance', 'new', 'old'], description: "Sorting method. 'relevance' (default), 'new' (newest by filing/publication date), 'old' (oldest by filing/publication date).", default: 'relevance' }, before: { type: 'string', description: "Maximum date filter (e.g., 'publication:20231231', 'filing:20220101'). Format: type:YYYYMMDD where type is 'priority', 'filing', or 'publication'." }, after: { type: 'string', description: "Minimum date filter (e.g., 'publication:20230101', 'filing:20220601'). Format: type:YYYYMMDD where type is 'priority', 'filing', or 'publication'." }, inventor: { type: 'string', description: 'Filter by inventor names. Separate multiple names with a comma (,).' }, assignee: { type: 'string', description: 'Filter by assignee names. Separate multiple names with a comma (,).' }, country: { type: 'string', description: "Filter by country codes (e.g., 'US', 'WO,JP'). Separate multiple codes with a comma (,)." }, language: { type: 'string', description: "Filter by language (e.g., 'ENGLISH', 'JAPANESE,GERMAN'). Separate multiple languages with a comma (,). Supported: ENGLISH, GERMAN, CHINESE, FRENCH, SPANISH, ARABIC, JAPANESE, KOREAN, PORTUGUESE, RUSSIAN, ITALIAN, DUTCH, SWEDISH, FINNISH, NORWEGIAN, DANISH." }, status: { type: 'string', enum: ['GRANT', 'APPLICATION'], description: "Filter by patent status: 'GRANT' or 'APPLICATION'." }, type: { type: 'string', enum: ['PATENT', 'DESIGN'], description: "Filter by patent type: 'PATENT' or 'DESIGN'." }, scholar: { type: 'boolean', description: 'Include Google Scholar results (default: false).', default: false } }, required: ['q'] } }
- src/index.ts:277-306 (registration)Registers the 'search_patents' tool by handling ListToolsRequestSchema and returning the tool metadata including name, description, and input schema.this.server.setRequestHandler(ListToolsRequestSchema, async () => { logger.debug('ListTools handler called'); return { tools: [ { name: 'search_patents', description: 'Searches Google Patents using SerpApi. Allows filtering by date, inventor, assignee, country, language, status, type, and sorting.', inputSchema: { type: 'object', properties: { q: { type: 'string', description: "Search query (required). Although optional in SerpApi docs, a non-empty query is practically needed. Use semicolon (;) to separate multiple terms. Advanced syntax like '(Coffee) OR (Tea);(A47J)' is supported. See 'About Google Patents' for details." }, page: { type: 'integer', description: 'Page number for pagination (default: 1).', default: 1 }, num: { type: 'integer', description: 'Number of results per page (default: 10). **IMPORTANT: Must be 10 or greater (up to 100).**', default: 10, minimum: 10, maximum: 100 }, sort: { type: 'string', enum: ['relevance', 'new', 'old'], description: "Sorting method. 'relevance' (default), 'new' (newest by filing/publication date), 'old' (oldest by filing/publication date).", default: 'relevance' }, before: { type: 'string', description: "Maximum date filter (e.g., 'publication:20231231', 'filing:20220101'). Format: type:YYYYMMDD where type is 'priority', 'filing', or 'publication'." }, after: { type: 'string', description: "Minimum date filter (e.g., 'publication:20230101', 'filing:20220601'). Format: type:YYYYMMDD where type is 'priority', 'filing', or 'publication'." }, inventor: { type: 'string', description: 'Filter by inventor names. Separate multiple names with a comma (,).' }, assignee: { type: 'string', description: 'Filter by assignee names. Separate multiple names with a comma (,).' }, country: { type: 'string', description: "Filter by country codes (e.g., 'US', 'WO,JP'). Separate multiple codes with a comma (,)." }, language: { type: 'string', description: "Filter by language (e.g., 'ENGLISH', 'JAPANESE,GERMAN'). Separate multiple languages with a comma (,). Supported: ENGLISH, GERMAN, CHINESE, FRENCH, SPANISH, ARABIC, JAPANESE, KOREAN, PORTUGUESE, RUSSIAN, ITALIAN, DUTCH, SWEDISH, FINNISH, NORWEGIAN, DANISH." }, status: { type: 'string', enum: ['GRANT', 'APPLICATION'], description: "Filter by patent status: 'GRANT' or 'APPLICATION'." }, type: { type: 'string', enum: ['PATENT', 'DESIGN'], description: "Filter by patent type: 'PATENT' or 'DESIGN'." }, scholar: { type: 'boolean', description: 'Include Google Scholar results (default: false).', default: false } }, required: ['q'] } } ] }; });