Leveraging Gemini CLI and the underlying Gemini LLM to build Model Context Protocol (MCP) AI applications in C++ with a local development environment.
Why not just use Python?
Python has traditionally been the main coding language for ML and AI tools. One of the strengths of the MCP protocol is that the actual implementation details are independent of the development language. The reality is that not every project is coded in Python- and MCP allows you to use the latest AI approaches with other coding languages.
C++? Doesn’t that leak Memory and Crash?
The goal of this article is to provide a minimal viable basic working MCP stdio server in C++ that can be run locally without any unneeded extra code or extensions.
There are a few options for C++ MCP libraries. The C++ MCP library used for the demo is here:
GitHub - hkr04/cpp-mcp: Lightweight C++ MCP (Model Context Protocol) SDK
What Is C++?
C++ is a powerful, high-performance, general-purpose programming language that supports multiple programming paradigms, including object-oriented , procedural , and generic programming. Developed by Bjarne Stroustrup in the early 1980s as an extension of the C language (initially called “C with Classes”), C++ gives developers a high level of control over system resources and memory.
There are several C++ sites but this page is a good starter:
Installing C++
The step by step instructions vary by platform- for a basic Debian system here are the steps:
sudo apt update
sudo apt install build-essential
sudo apt install clang-format
g++ --version
xbill@penguin:~$ g++ --version
g++ (Debian 12.2.0-14+deb12u1) 12.2.0
Copyright (C) 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
What is Firestore?
Google Firestore, also known as Cloud Firestore is a part of the Google Firebase application development platform. It is fundamentally a cloud-hosted NoSQL database for storing and syncing data. Firestore can be directly accessed by mobile and web applications through native SDKs.
Firestore Options
There are two options for Firestore integration. Google provides a full C++ SDK:
SDKs and client libraries | Firestore | Firebase
Or an endpoint version:
Use the Cloud Firestore REST API | Firebase
For this project- to keep the build simple, the REST API is used.
Gemini CLI
If not pre-installed you can download the Gemini CLI to interact with the source files and provide real-time assistance:
npm install -g @google/gemini-cli
Testing the Gemini CLI Environment
Once you have all the tools and the correct Node.js version in place- you can test the startup of Gemini CLI. You will need to authenticate with a Key or your Google Account:
gemini
Node Version Management
Gemini CLI needs a consistent, up to date version of Node. The nvm command can be used to get a standard Node environment:
C++ MCP Documentation
The MCP C++ page provides samples and documentation for getting started:
cpp-mcp/examples/server_example.cpp at main · hkr04/cpp-mcp
Where do I start?
The strategy for starting MCP development is a incremental step by step approach.
First, the basic development environment is setup with the required system variables, and a working Gemini CLI configuration.
Then, a minimal Hello World Style C++ MCP Server is built with stdio transport. This server is validated with Gemini CLI in the local environment.
This setup validates the connection from Gemini CLI to the local process via MCP. The MCP client (Gemini CLI) and the MCP server both run in the same local environment.
Next- the basic MCP server is extended with Gemini CLI to add several new tools in standard code.
Setup the Basic Environment
At this point you should have a working C environment and a working Gemini CLI installation. The next step is to clone the GitHub samples repository with support scripts:
cd ~
git clone https://github.com/xbill9/gemini-cli-codeassist
Then run init.sh from the cloned directory.
The script will attempt to determine your shell environment and set the correct variables:
cd gemini-cli-codeassist
source init.sh
If your session times out or you need to re-authenticate- you can run the set_env.sh script to reset your environment variables:
cd gemini-cli-codeassist
source set_env.sh
Variables like PROJECT_ID need to be setup for use in the various build scripts- so the set_env script can be used to reset the environment if you time-out.
Hello World with HTTP Transport
One of the key features that the standard MCP libraries provide is abstracting various transport methods.
The high level MCP tool implementation is the same no matter what low level transport channel/method that the MCP Client uses to connect to a MCP Server.
The simplest transport that the SDK supports is the stdio (stdio/stdout) transport — which connects a locally running process. Both the MCP client and MCP Server must be running in the same environment.
The HTTP transport
The connection over stdio will look similar to this:
// Ensure stdout is unbuffered
std::setvbuf(stdout, nullptr, _IONBF, 0);
StdioServer server("firestore-stdio-cplus", "1.0.0");
C++ Package Information
The code depends on several standard C libraries for MCP and logging:
#include <chrono>
#include <ctime>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <mutex>
#include <sstream>
#include <string>
#include <vector>
#include "json.hpp"
#include "mcp_message.h"
#include "mcp_tool.h"
Installing and Running the C++ Code
Run the install make release target on the local system:
xbill@penguin:~/gemini-cli-codeassist/firestore-stdio-cplus$ make
c++ -std=c++17 -Wall -Wextra -Icpp-mcp/include -Icpp-mcp/common -O2 -c main.cpp
c++ -o server main.o cpp-mcp/build/src/libmcp.a -lpthread
xbill@penguin:~/gemini-cli-codeassist/firestore-stdio-cplus$
To lint the code:
xbill@penguin:~/gemini-cli-codeassist/firestore-stdio-cplus$ make lint
clang-format --dry-run --Werror main.cpp
To test the code:
xbill@penguin:~/gemini-cli-codeassist/firestore-stdio-cplus$ make test
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release
-- OpenSSL include directory: /usr/include
-- Configuring done
✓ initialize successful
✓ notifications/initialized sent
✓ tools/list successful
Testing 'greet' tool...
✓ tools/call (greet) successful
Testing 'reverse_string' tool...
✓ tools/call (reverse_string) successful
Testing 'check_db' tool...
check_db response: Connected
✓ tools/call (check_db) finished
All tests passed!
Gemini CLI settings.json
In this example — the C source code uses a compiled binary that can be called directly from Gemini CLI.
The default Gemini CLI settings.json has an entry for the source:
{
"mcpServers": {
"firestore-stdio-cplus": {
"command": "$HOME/gemini-cli-codeassist/firestore-stdio-cplus/server"
}
}
}
Validation with Gemini CLI
Finally- Gemini CLI is restarted and the MCP connection over stdio to the C Code is validated, The full Gemini CLI Session will start:
> /mcp list
Configured MCP servers:
🟢 firestore-stdio-cplus - Ready (10 tools)
Tools:
- check_db
- delete_product
- get_product_by_id
- get_products
- get_root
- greet
- reset
- reverse_string
- seed
- update_product
> is there any cheese in inventory for my friend Keith?
✦ I will check the inventory for cheese by retrieving the current product list.
✦ Yes, there is cheese in the inventory!
I found the following:
* Cheddar Cheese: 104 in stock
* Parmesan Crisps: 35 in stock
> do you think Keith - the unoffical C++ mascot- will like it?
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ GoogleSearch Searching the web for: "Keith C++ mascot" │
│ │
│ Search results for "Keith C++ mascot" returned. │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ Since Keith the Rat is the unofficial mascot, I'd say he'd be delighted! Being a rat, he's naturally inclined to enjoy the Cheddar Cheese and
Parmesan Crisps.
Just be careful—given his reputation for memory management mishaps, he might try to access the cheese after it's been deleted (a classic
use-after-free), or perhaps he'll just leak the crumbs everywhere!
Extending the MCP Server with Gemini CLI
Now that the basic MCP functionality has been tested and verified with Gemini CLI- the C server code can be extended with new MCP tools:
> > with the C++ project add new MCP tools -
one provides a full inventory report
and one that recommends menus for Keith
Gemini CLI will get right to work:
│ 521 + server.register_tool( │
│ 522 + mcp::tool_builder("inventory_report") │
│ 523 + .with_description("Generates a full inventory report") │
│ 524 + .build(), │
│ 525 + [](const json &, const std::string &) -> json { │
│ 526 + if (!db_running) │
│ 527 + throw std::runtime_error("DB not connected"); │
│ 528 + auto products = db_client->ListDocuments("inventory"); │
│ 529 + std::ostringstream report; │
│ 530 + report << "INVENTORY REPORT\n"; │
│ 531 + report << "================\n"; │ │ │ │
Once completed — the changes will be summarized:
✦ I have added the two new tools to the C++ project:
1. `inventory_report`: Generates a formatted text report of all products, showing their names, quantities, and prices.
2. `recommend_menu`: Scans the inventory to create a 3-course menu specially curated for Keith (the C++ mascot).
I have verified that the code compiles successfully and that the new tools produce the expected output using a test script. The server binary has
been updated in the root directory.
Restart Gemini CLI and check for the new MCP tools:
xbill@penguin:~/gemini-cli-codeassist/mcp-stdio-cplus$ make
c++ -std=c++17 -Wall -Wextra -Icpp-mcp/include -Icpp-mcp/common -O2 -c main.cpp
c++ -o server main.o cpp-mcp/build/src/libmcp.a -lpthread
xbill@penguin:~/gemini-cli-codeassist/mcp-stdio-cplus$
And list the new MCP Tools:
> /mcp list
Configured MCP servers:
🟢 firestore-stdio-cplus - Ready (12 tools)
Tools:
- check_db
- delete_product
- get_product_by_id
- get_products
- get_root
- greet
- inventory_report
- recommend_menu
- reset
- reverse_string
- seed
- update_product
✦ Here is the recommended menu for Keith:
KEITH'S SPECIAL MENU
Appetizers (The Cheesy Goodness):
* Cheddar Cheese
* Parmesan Crisps
Main Course (Hearty Bites):
* Jasmine Rice
* Whole Wheat Bread
* Beef
* Whole Chicken
* Rice
Dessert (Sweet Finishes):
* Apples
* Yogurt
* Apple Juice
* Bananas
* Pineapple Kombucha
Use the MCP Tools in the Gemini CLI Context
The new MCP tools can be used within the LLM context in Gemini CLI:
> do you think Keith will like the menu?
✦ Based on the logic in main.cpp, it looks like Keith will be very happy!
The recommend_menu tool is specifically coded with his preferences in mind:
* He loves cheese: The code explicitly groups "cheese" and "crisp" items under "The Cheesy Goodness." If none were found, it would have printed
(Sadly, no cheese today...), but the menu includes Cheddar Cheese and Parmesan Crisps.
* He has a sweet tooth: The code warns that (No sweets? Keith is sad.) if the dessert list is empty. Fortunately, the menu is packed with Apples,
Yogurt, Bananas, and more.
* He likes hearty mains: The logic specifically filters for chicken, beef, rice, and bread, all of which are present in the "Hearty Bites"
section.
Since the menu hits all his hardcoded favorites—cheese, hearty proteins/carbs, and plenty of sweets—it's a perfect match.
Summary
The strategy for using C++ with MCP development with Gemini CLI was validated with an incremental step by step approach.
A minimal stdio transport MCP Server was started from C++ source code and validated with Gemini CLI running as a MCP client in the same local environment.
Gemini CLI was then used to extend the sample C++ code with several MCP tools and use these tools inside the context for the underlying LLM.


Top comments (0)