Skip to main content
Glama
KunihiroS

Google Patents MCP Server

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
NameRequiredDescriptionDefault
afterNoMinimum date filter (e.g., 'publication:20230101', 'filing:20220601'). Format: type:YYYYMMDD where type is 'priority', 'filing', or 'publication'.
assigneeNoFilter by assignee names. Separate multiple names with a comma (,).
beforeNoMaximum date filter (e.g., 'publication:20231231', 'filing:20220101'). Format: type:YYYYMMDD where type is 'priority', 'filing', or 'publication'.
countryNoFilter by country codes (e.g., 'US', 'WO,JP'). Separate multiple codes with a comma (,).
inventorNoFilter by inventor names. Separate multiple names with a comma (,).
languageNoFilter 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.
numNoNumber of results per page (default: 10). **IMPORTANT: Must be 10 or greater (up to 100).**
pageNoPage number for pagination (default: 1).
qYesSearch 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.
scholarNoInclude Google Scholar results (default: false).
sortNoSorting method. 'relevance' (default), 'new' (newest by filing/publication date), 'old' (oldest by filing/publication date).relevance
statusNoFilter by patent status: 'GRANT' or 'APPLICATION'.
typeNoFilter by patent type: 'PATENT' or 'DESIGN'.

Implementation Reference

  • 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 の最初でクリアする
      }
      // --- 元のコードここまで ---
  • 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']
            }
          }
        ]
      };
    });
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden but offers minimal behavioral insight. It mentions filtering and sorting but omits critical details like rate limits, authentication needs, pagination behavior, error handling, or response format. For a search tool with 13 parameters, this is insufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core purpose and enumerates key capabilities without redundancy. Every word serves a purpose, making it highly concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex search tool with 13 parameters, no annotations, and no output schema, the description is incomplete. It lacks behavioral context, usage guidelines, and details on results or errors, leaving significant gaps for agent understanding.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents all 13 parameters. The description adds no additional parameter semantics beyond listing filter types, which are already covered in schema descriptions. Baseline 3 is appropriate as the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Searches Google Patents') and resource ('patents'), and mentions the service provider ('using SerpApi'). It lists key filtering capabilities, making the purpose specific and actionable. However, without sibling tools, it cannot differentiate from alternatives, preventing a perfect score.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives, prerequisites, or typical use cases. It lists filtering options but lacks context on optimal scenarios or limitations, leaving the agent without usage direction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/KunihiroS/google-patents-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server