{"version":3,"sources":["../src/index.ts","../src/tools/google-search.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n  CallToolRequestSchema,\n  ListToolsRequestSchema,\n  ErrorCode,\n  McpError,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { createGoogleSearchAI, searchGoogle, GoogleSearchParams } from \"./tools/google-search.js\";\n\n// Environment variable validation is now handled in createGoogleSearchAI\n\nconst server = new Server(\n  {\n    name: \"mcp-gemini-google-search\",\n    version: \"0.1.0\",\n  },\n  {\n    capabilities: {\n      tools: {},\n    },\n  }\n);\n\nconst googleSearchAI = createGoogleSearchAI();\n\nserver.setRequestHandler(ListToolsRequestSchema, async () => {\n  return {\n    tools: [\n      {\n        name: \"google_search\",\n        description: \"Performs a web search using Google Search (via the Gemini API) and returns the results. This tool is useful for finding information on the internet based on a query.\",\n        inputSchema: {\n          type: \"object\",\n          properties: {\n            query: {\n              type: \"string\",\n              description: \"The search query to find information on the web.\",\n            },\n          },\n          required: [\"query\"],\n        },\n      },\n    ],\n  };\n});\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n  if (request.params.name !== \"google_search\") {\n    throw new McpError(\n      ErrorCode.MethodNotFound,\n      `Unknown tool: ${request.params.name}`\n    );\n  }\n\n  if (!request.params.arguments) {\n    throw new McpError(ErrorCode.InvalidParams, \"Missing arguments\");\n  }\n\n  const args = request.params.arguments as Record<string, unknown>;\n\n  if (typeof args.query !== \"string\") {\n    throw new McpError(\n      ErrorCode.InvalidParams,\n      \"Invalid arguments: query must be a string\"\n    );\n  }\n\n  try {\n    const searchParams: GoogleSearchParams = {\n      query: args.query,\n    };\n\n    const result = await searchGoogle(googleSearchAI, searchParams);\n\n    return {\n      content: result.content,\n    };\n  } catch (error) {\n    throw new McpError(\n      ErrorCode.InternalError,\n      `Search failed: ${error instanceof Error ? error.message : \"Unknown error\"}`\n    );\n  }\n});\n\nasync function main() {\n  const transport = new StdioServerTransport();\n  await server.connect(transport);\n  console.error(\"MCP Gemini Google Search server running on stdio\");\n}\n\nmain().catch((error) => {\n  console.error(\"Server error:\", error);\n  process.exit(1);\n});","import { GoogleGenAI } from \"@google/genai\";\n\nexport interface GoogleSearchParams {\n  query: string;\n}\n\nexport interface GoogleSearchResult {\n  content: Array<{\n    type: string;\n    text: string;\n  }>;\n}\n\nexport function createGoogleSearchAI(): GoogleGenAI {\n  const provider = process.env.GEMINI_PROVIDER;\n  \n  if (provider === 'vertex') {\n    const projectId = process.env.VERTEX_PROJECT_ID;\n    const location = process.env.VERTEX_LOCATION || 'us-central1';\n    \n    if (!projectId) {\n      throw new Error('VERTEX_PROJECT_ID environment variable is required when using Vertex AI');\n    }\n    \n    return new GoogleGenAI({ \n      vertexai: true,\n      project: projectId,\n      location\n    });\n  }\n  \n  const apiKey = process.env.GEMINI_API_KEY;\n  if (!apiKey) {\n    throw new Error('GEMINI_API_KEY environment variable is required when using Google AI Studio');\n  }\n  \n  return new GoogleGenAI({ apiKey });\n}\n\nfunction getResponseText(response: any): string | undefined {\n  const parts = response.candidates?.[0]?.content?.parts;\n  if (!parts) {\n    return undefined;\n  }\n  const textSegments = parts\n    .map((part: any) => part.text)\n    .filter((text: string): text is string => typeof text === 'string');\n\n  if (textSegments.length === 0) {\n    return undefined;\n  }\n  return textSegments.join('');\n}\n\nexport async function searchGoogle(ai: GoogleGenAI, params: GoogleSearchParams): Promise<GoogleSearchResult> {\n  try {\n    if (!params.query || params.query.trim() === '') {\n      throw new Error(\"Search query cannot be empty\");\n    }\n\n    const model = process.env.GEMINI_MODEL || \"gemini-2.5-flash\";\n\n    const response = await ai.models.generateContent({\n      model,\n      contents: [\n        {\n          role: \"user\",\n          parts: [{ text: params.query }]\n        }\n      ],\n      config: {\n        tools: [{ googleSearch: {} }]\n      }\n    });\n    \n    // Extract response text using the same method as web-search.ts\n    const responseText = getResponseText(response);\n    \n    if (!responseText || responseText.trim() === '') {\n      throw new Error(\"No response from Gemini model\");\n    }\n\n    // Extract grounding metadata from the first candidate\n    const groundingMetadata = response?.candidates?.[0]?.groundingMetadata;\n    \n    let finalText = responseText;\n    \n    if (groundingMetadata) {\n      const sources = groundingMetadata.groundingChunks || [];\n      const supports = groundingMetadata.groundingSupports || [];\n      \n      // Create source list\n      const sourceList: string[] = [];\n      sources.forEach((source: any, index: number) => {\n        if (source.web) {\n          sourceList.push(`[${index + 1}] ${source.web.title} (${source.web.uri})`);\n        }\n      });\n      \n      // Insert citation markers based on grounding supports\n      if (supports.length > 0 && sources.length > 0) {\n        const insertions: Array<{ index: number; text: string }> = [];\n        \n        supports.forEach((support: any) => {\n          if (support.segment && support.groundingChunkIndices) {\n            const endIndex = support.segment.endIndex || 0;\n            const sourceNumbers = support.groundingChunkIndices\n              .map((idx: number) => idx + 1)\n              .sort((a: number, b: number) => a - b);\n            const citationText = `[${sourceNumbers.join(',')}]`;\n            insertions.push({ index: endIndex, text: citationText });\n          }\n        });\n        \n        // Sort insertions by index in descending order to avoid index shifting\n        insertions.sort((a, b) => b.index - a.index);\n        \n        // Apply insertions to the text\n        let modifiedText = finalText;\n        insertions.forEach(insertion => {\n          modifiedText = modifiedText.slice(0, insertion.index) + \n                        insertion.text + \n                        modifiedText.slice(insertion.index);\n        });\n        finalText = modifiedText;\n      }\n      \n      // Append source list if available\n      if (sourceList.length > 0) {\n        finalText += '\\n\\nSources:\\n' + sourceList.join('\\n');\n      }\n    }\n\n    return {\n      content: [{\n        type: \"text\",\n        text: finalText\n      }]\n    };\n  } catch (error) {\n    throw new Error(`Google search failed: ${error instanceof Error ? error.message : 'Unknown error'}`);\n  }\n}"],"mappings":"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","names":[]}