✨ From vibe coding to vibe deployment. UBOS MCP turns ideas into infra with one message.

Learn more
Andrii Bidochko
  • Updated: April 30, 2025
  • 5 min read

Creating Custom MCP Clients with Gemini: A Guide to Enhancing AI Development

Unlocking the Power of Custom MCP Clients with Gemini API

In the ever-evolving landscape of AI development, creating custom Model Context Protocol (MCP) Clients using the Gemini API is becoming increasingly vital. These custom clients enable AI developers and researchers to connect their applications with MCP servers, unlocking powerful capabilities to supercharge their projects. This article delves into the importance of custom MCP Clients, the setup process, and the impact on AI applications.

Custom MCP Clients with Gemini API

Understanding the Importance of Custom MCP Clients

Custom MCP Clients are essential for AI developers who want to leverage the full potential of the Gemini API. These clients allow for seamless integration with various MCP servers, enabling developers to harness unique tools and capabilities tailored to their specific needs. By creating custom MCP Clients, developers can enhance their AI applications’ functionality, efficiency, and scalability.

Setting Up Your Environment and Dependencies

Before diving into the implementation, setting up the environment and dependencies is crucial. Here’s a step-by-step guide:

  • Gemini API Key: Obtain your Gemini API key by visiting Google’s Gemini API Key page. Store it safely as it will be needed later.
  • Node.js: Download the latest version of Node.js from nodejs.org and run the installer with default settings.
  • National Park Services API: Request an API key by visiting the National Park Service API page. Keep this key accessible for later use.
  • Python Libraries: Install the necessary Python libraries by running the following command:

    pip install mcp python-dotenv google-genai

Implementation Steps and Best Practices

With the environment set up, it’s time to implement the MCP Client. Follow these steps for a successful implementation:

Creating Configuration Files

Start by creating an mcp.json file to store configuration details about the MCP servers your client will connect to. Add the following content:


{
    "mcpServers": {
        "nationalparks": {
            "command": "npx",
            "args": ["-y", "mcp-server-nationalparks"],
            "env": {
                "NPS_API_KEY": ""
            }
        }
    }
}
    

Replace <YOUR_NPS_API_KEY> with the key you generated. Next, create a .env file in the same directory and add:

GEMINI_API_KEY = <YOUR_GEMINI_API_KEY>

Replace <YOUR_GEMINI_API_KEY> with your Gemini API key.

Implementing the MCP Client

Create a client.py file to implement the MCP Client. Ensure it is in the same directory as mcp.json and .env.

Begin by importing necessary libraries and creating a basic client class:


import asyncio
import json
import os
from typing import List, Optional
from contextlib import AsyncExitStack
import warnings
from google import genai
from google.genai import types
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from dotenv import load_dotenv

load_dotenv()
warnings.filterwarnings("ignore", category=ResourceWarning)

def clean_schema(schema):
    allowed_keys = {"type", "properties", "required", "description", "title", "default", "enum"}
    return {k: v for k, v in schema.items() if k in allowed_keys}

class MCPGeminiAgent:
    def __init__(self):
        self.session: Optional[ClientSession] = None
        self.exit_stack = AsyncExitStack()
        self.genai_client = genai.Client(api_key=os.getenv("GEMINI_API_KEY"))
        self.model = "gemini-2.0-flash"
        self.tools = None
        self.server_params = None
        self.server_name = None
    

The __init__ method initializes the MCPGeminiAgent by setting up an asynchronous session manager, loading the Gemini API client, and preparing placeholders for model configuration, tools, and server details.

Connecting to the MCP Server

Establish an asynchronous connection to the selected MCP server using stdio transport. Initialize the MCP session and retrieve the available tools from the server.


async def connect(self):
    await self.select_server()
    self.stdio_transport = await self.exit_stack.enter_async_context(stdio_client(self.server_params))
    self.stdio, self.write = self.stdio_transport
    self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))
    await self.session.initialize()
    print(f"Successfully connected to: {self.server_name}")

    mcp_tools = await self.session.list_tools()
    print("\nAvailable MCP tools for this server:")
    for tool in mcp_tools.tools:
        print(f"- {tool.name}: {tool.description}")
    

Handling User Queries and Tool Calls

This method sends the user’s prompt to Gemini, processes any tool calls returned by the model, executes the corresponding MCP tools, and iteratively refines the response.


async def agent_loop(self, prompt: str) -> str:
    contents = [types.Content(role="user", parts=[types.Part(text=prompt)])]
    mcp_tools = await self.session.list_tools()
    tools = types.Tool(function_declarations=[
        {
            "name": tool.name,
            "description": tool.description,
            "parameters": clean_schema(getattr(tool, "inputSchema", {}))
        } for tool in mcp_tools.tools
    ])
    self.tools = tools

    response = await self.genai_client.aio.models.generate_content(
        model=self.model,
        contents=contents,
        config=types.GenerateContentConfig(
            temperature=0,
            tools=[tools],
        ),
    )
    contents.append(response.candidates[0].content)

    turn_count = 0
    max_tool_turns = 5
    while response.function_calls and turn_count = max_tool_turns and response.function_calls:
        print(f"Stopped after {max_tool_turns} tool calls to avoid infinite loops.")
    print("All tool calls complete. Displaying Gemini's final response.")
    return response
    

Interactive Chat Loop

This provides a


Andrii Bidochko

CTO UBOS

Andrii Bidochko is an AI entrepreneur and researcher focused on AI agents, reinforcement learning, and autonomous systems. He writes about the technologies shaping the future of machine intelligence, from frontier models and agent architectures to real-world AI applications.

Sign up for our newsletter

Stay up to date with the roadmap progress, announcements and exclusive discounts feel free to sign up with your email.

Sign In

Register

Reset Password

Please enter your username or email address, you will receive a link to create a new password via email.