Building a Custom MCP Server for Gemini CLI: A Hands-on guide
Introduction
The Model Context Protocol (MCP) empowers developers to create custom servers that extend the capabilities of AI agents like Google’s Gemini CLI. By building an MCP server, you can integrate tailored functionalities — such as a personal finance assistant — into your workflow.
In this tutorial, I’ll guide you through constructing a Python-based MCP server using FastMCP, designed to calculate interest, categorize expenses, project savings, and generate budget plans. By the end, you’ll have a working agent and the confidence to expand and customise it further.
Prerequisites
Before diving in, ensure you have:
- Python 3.9+: Verify with python — version.
- Gemini CLI: Install via npm install -g @google/gemini-cli@latest.
- uv: A fast package manager, install with pip install uv.
- Basic Knowledge: Familiarity with Python, virtual environments, and command-line tools.
💡 Tip: You can use
python -m venv .venv && source .venv/bin/activateinstead ofuvif you prefer the classic approach.
Step 1: Setting Up the Environment
Begin by setting up a dedicated workspace to keep your project organized. Open your terminal and execute:
mkdir finance-assistant
cd finance-assistant
uv init
uv add fastmcpActivate the environment:
- On Unix/Mac: source .venv/bin/activate
- On Windows: .venv\Scripts\activate
Check FastMCP is installed:
fastmcp --versionYou now have a clean, isolated workspace for your server. This environment ensures isolated dependencies, a best practice for development.
Step 2: Creating the Initial Server and Tool
Create a file named server.py in the finance-assistant directory. Start with a basic MCP server and a single tool:
import math
from fastmcp import mcp
@mcp.tool
def calculate_interest(principal: float, rate: float, time: int) -> float:
"""Calculates compound interest."""
return principal * (math.pow(1 + rate, time) - 1)
if __name__ == "__main__":
mcp.run_server(port=8080, transport="http")Understanding the Tool
This tool calculates compound interest using the formula principal * ( (1 + rate)^time — 1 ), which gives the interest earned (not the total amount). For example, with principal=1000, rate=0.05, and time=1, the result is approximately $50.
Go ahead and Run the Server:
fastmcp run server.py — transport=”http” — port=”8080"If everything works, you’ll see:
Step 3: Integrating with Gemini CLI
To make your tool accessible in Gemini CLI, configure it in the CLI’s settings. Gemini CLI needs to know where to find your server. Open or create ~/.gemini/settings.json and add:
{
"mcpServers": {
"finance-assistant": {
"httpUrl": "http://127.0.0.1:8080/mcp/"
}
}
}This JSON file tells Gemini CLI where to find your MCP server. The httpUrl points to the server’s base endpoint.
Restart Gemini CLI and check available servers:
/mcpYou should see:
Now try it, invoke the tool:
calculate_interest principal=1000 rate=0.05 time=1Gemini CLI will ask permission.
On giving permissions, it successfully calculates the interest based on the user input values.
✅ Your first MCP tool is live!
Step 4: Expanding to a Full Finance Assistant Agent
Enhance server.py with additional financial tools and a prompt to create a comprehensive agent. Update server.py with more tools:
import math
from fastmcp import mcp
@mcp.tool
def calculate_interest(principal: float, rate: float, time: int) -> float:
"""Calculates compound interest on an initial amount."""
return principal * (math.pow(1 + rate, time) - 1)
@mcp.tool
def categorize_expenses(expenses: str) -> dict:
"""Categorizes and sums expenses from a comma-separated string (e.g., 'rent:2000,food:800')."""
categories = {}
for item in expenses.split(','):
try:
category, amount = item.split(':')
if category and amount:
num = float(amount)
if not math.isnan(num):
categories[category.strip()] = categories.get(category.strip(), 0) + num
except ValueError:
continue
return categories
@mcp.tool
def project_savings(income: float, monthly_expenses: float, months: int, interest_rate: float = 0.03) -> dict:
"""Projects future savings with monthly compounding interest."""
total = 0
for _ in range(months):
total += income - monthly_expenses
total += total * (interest_rate / 12)
return {"total_savings": round(total, 2), "breakdowns": []}Here you can see the server.py file has the new categorize_expenses and project_savings tools.
Adding a Budget Plan Prompt
@mcp.prompt
def budget_plan(income: float, expenses: str, months: int) -> str:
"""Creates a detailed budget plan based on income, expenses, and time period."""
categories = categorize_expenses(expenses)
total_expenses = sum(categories.values())
savings = project_savings(income, total_expenses, months)
net_income = income - total_expenses
highest_expense = max(categories, key=categories.get) if categories else "N/A"
return (
f"**Budget Plan**\n"
f"- Expenses: {categories}\n"
f"- Total Expenses: ${total_expenses:.2f}\n"
f"- Net Income: ${net_income:.2f}\n"
f"- Projected Savings: ${savings['total_savings']}\n"
f"- Tip: Consider reducing expenses in {highest_expense} category!"
)
if __name__ == "__main__":
mcp.run_server(port=8080, transport="http")In the context of MCP servers, a prompt is a special type of function decorated with @mcp.prompt that serves as an orchestrator or higher-level entry point. Unlike tools, which are discrete, deterministic functions performing specific actions (e.g., calculating interest), prompts define workflows or conversation templates.
They can invoke tools, process their outputs, and generate formatted responses. Prompts are exposed as slash commands in Gemini CLI (e.g., /budget_plan), making them user-friendly for complex tasks.
Why Are We Adding This?
Adding a prompt like budget_plan transforms your MCP server from a collection of isolated tools into a cohesive agent. It allows users to perform multi-step operations with a single command, such as categorizing expenses, calculating net income, projecting savings, and providing actionable tips — all in one response.
This enhances usability, as the prompt handles the logic of chaining tools, reducing the need for multiple CLI calls. It’s a key feature for building practical AI assistants, enabling customization (e.g., adding more tips or integrating external data) and scalability (e.g., for more advanced financial modeling).
Testing the Expanded Agent
After restarting the server, open Gemini CLI and first verify the new tools with /mcp — you should see calculate_interest, categorize_expenses, project_savings, and budget_plan.
calculate_interest principal=1000 rate=0.05 time=1Here you can see on successfully execution, it generates the interest and even specifies which tool it used, which in this case is the calculate_interest tool.
Next we will test the project_savings tool to see if it generates a monthly savings breakdown for us.
project_savings income=5000 monthly_expenses=2800 months=6 interest_rate=0.03Conclusion
You’ve built a custom MCP server for a personal finance assistant using Python and FastMCP! This detailed tutorial covered setup, tool creation, and integration. The is just a starting point; tweak it to fit your goals.
You now know how to:
- Set up an MCP server
- Build tools and prompts
- Test everything directly inside Gemini CLI
You can:
- Add more financial tools (e.g., debt calculators, investment trackers)
- Integrate APIs (stock market data, currency exchange rates)
- Deploy your MCP server to Cloud Run for secure, always-on access
Resources
- FastMCP Documentation.
- Getting Started with Gemini CLI Codelab
- Deploy a secure MCP server on Cloud Run
- GitHub Repo: finance-assistant.

