Leveraging Gemini CLI and the underlying Gemini LLM to build Model Context Protocol (MCP) AI applications with PHP 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.
PHP? For AI? Are you Serious?
The goal of this article is to provide a minimal viable basic working MCP stdio server in PHP that can be run locally without any unneeded extra code or extensions. Like it or not — a huge swath of the Internet still runs on PHP and this strategy is a low risk approach to modernize some of those apps. The official announcement is here:
Announcing the Official PHP SDK for MCP
What Is PHP?
PHP (a recursive acronym for PHP: Hypertext Preprocessor) is a widely-used, open-source, server-side scripting language designed primarily for web development. It can be embedded directly into HTML code to create dynamic and interactive websites and applications.
The full details of the language can be found here:
PHP
PHP provides the core language support-the actual package are managed by a package manager called Composer.
Composer? What is this — the Opera?
The granular package management and support is provided by Composer-which is used to download the correct versions of the packages needed to support the application. The full details of Composer are available here:
Composer
PHP Version Management
One of the downsides of the wide deployment of PHP has been managing the language versions across platforms and maintaining a supported version. Every environment is a little different- but PHP8 version support is recommended.
To check your PHP version:
xbill@penguin:~$ php -v
PHP 8.2.29 (cli) (built: Jul 3 2025 16:16:05) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.29, Copyright (c) Zend Technologies
with Zend OPcache v8.2.29, Copyright (c), by Zend Technologies
If you do not have the PHP interpreter in your environment- follow the system recommended installation instructions. For a Debian style Linux — this would be similar to:
PHP
Recommended PHP Extensions
Along with the base PHP installation- several key extensions are needed. The exact installation will vary by platform- but here are the main Debian PHP Extensions:
sudo apt-get install php-dom
sudo apt-get install php-curl
sudo apt-get install php-mbstring
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:
GitHub – nvm-sh/nvm: Node Version Manager – POSIX-compliant bash script to manage multiple active node.js versions
PHP MCP Documentation
The official MCP GitHub Repo provides samples and documentation for getting started:
GitHub – modelcontextprotocol/php-sdk: The official PHP SDK for Model Context Protocol servers and clients. Maintained in collaboration with The PHP Foundation.
Composer packages are here:
mcp/sdk – Packagist
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 PHP 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 PHP 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 PHP code.
Setup the Basic Environment
At this point you should have a working PHP interpreter 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 STDIO 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 connection over stdio will look similar to this:
// Explicitly use stdio transport
$transport = new StdioTransport();
$server->run($transport);
Running the PHP Code
First- switch the directory with the PHP MCP sample code:
cd ~/gemini-cli-codeassist/mcp-stdio-php
BootStrapping Composer
You need a working Composer and PHP environment for the sample code to run. Gemini CLI can be used to setup and run Composer:
███ █████████ ██████████ ██████ ██████ █████ ██████ █████ █████
░░░███ ███░░░░░███░░███░░░░░█░░██████ ██████ ░░███ ░░██████ ░░███ ░░███
░░░███ ███ ░░░ ░███ █ ░ ░███░█████░███ ░███ ░███░███ ░███ ░███
░░░███ ░███ ░██████ ░███░░███ ░███ ░███ ░███░░███░███ ░███
███░ ░███ █████ ░███░░█ ░███ ░░░ ░███ ░███ ░███ ░░██████ ░███
███░ ░░███ ░░███ ░███ ░ █ ░███ ░███ ░███ ░███ ░░█████ ░███
███░ ░░█████████ ██████████ █████ █████ █████ █████ ░░█████ █████
░░░ ░░░░░░░░░ ░░░░░░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░ ░░░░░
Tips for getting started:
1. Ask questions, edit files, or run commands.
2. Be specific for the best results.
3. /help for more information.
✕ Error during discovery for MCP server 'hello-stdio-php': MCP error -32000: Connection closed
> make
✦ I will read the Makefile to understand the available targets and their actions.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ ReadFile Makefile │
│ │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ I will execute the make command, which will install dependencies, run tests, and lint the code.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ Shell make [current working directory /home/xbill/gemini-cli-codeassist/mcp-stdio-php] │
│ │
│ Installing dependencies... │
│ make: composer: No such file or directory │
│ make: *** [Makefile:10: install] Error 127 │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ I will check if composer or composer.phar is available in the environment.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ Shell which composer || ls composer.phar [current working directory /home/xbill/gemini-cli-codeassist/mcp-stdio-php] │
│ │
│ ls: cannot access 'composer.phar': No such file or directory │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ I will check if php is available and its version.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ Shell php -v [current working directory /home/xbill/gemini-cli-codeassist/mcp-stdio-php] │
│ │
│ PHP 8.2.29 (cli) (built: Jul 3 2025 16:16:05) (NTS) │
│ Copyright (c) The PHP Group │
│ Zend Engine v4.2.29, Copyright (c) Zend Technologies │
│ with Zend OPcache v8.2.29, Copyright (c), by Zend Technologies │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ I will read the README.md file to see if it contains more accurate setup instructions.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ ReadFile README.md │
│ │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ I will search for composer in common locations and also try to download it if it's not found.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ? Shell curl -sS https://getcomposer.org/installer | php -- --install-dir=. --filename=composer.phar [current working dir… ← │
│ │
│ curl -sS https://getcomposer.org/installer | php -- --install-dir=. --filename=composer.phar │
│ │
│ Allow execution of: 'curl'? │
│ │
│ 1. Yes, allow once │
│ ● 2. Yes, allow always ... │
│ 3. No, suggest changes (esc) │
│ │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
Composer is downloaded:
✦ I will search for composer in common locations and also try to download it if it's not found.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ Shell curl -sS https://getcomposer.org/installer | php -- --install-dir=. --filename=composer.phar [current working direc… │
│ │
│ All settings correct for using Composer │
│ Downloading... │
│ │
│ Composer (version 2.9.2) successfully installed to: /home/xbill/gemini-cli-codeassist/mcp-stdio-php/composer.phar │
│ Use it: php ./composer.phar │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ I will install the dependencies using the newly downloaded composer.phar.
And the requirements are pulled:
✦ I will read the composer.json file to check the project dependencies.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ ReadFile composer.json │
│ │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ I will try to install the production dependencies only, ignoring platform requirements if necessary.
Current Version of PHP composer dependencies:
{
"require": {
"mcp/sdk": "^0.2.0",
"monolog/monolog": "^3.9"
},
"config": {
"allow-plugins": {
"php-http/discovery": true
}
},
"require-dev": {
"phpunit/phpunit": "^11.5",
"phpstan/phpstan": "^2.1"
}
}
Installing and Running the PHP Code
Run the install make target on the local system:
cd ~/gemini-cli-codeassist/mcp-stdio-php
make install
You can validate the final result by checking the messages:
Installing dependencies...
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Nothing to install, update or remove
Generating autoload files
30 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
Loading composer repositories with package information
Updating dependencies
Nothing to modify in lock file
Writing lock file
Installing dependencies from lock file (including require-dev)
Nothing to install, update or remove
Generating autoload files
30 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
No security vulnerability advisories found.
To test the PHP Code:
xbill@penguin:~/gemini-cli-codeassist/mcp-stdio-php$ make test
Running tests...
PHPUnit 11.5.46 by Sebastian Bergmann and contributors.
Runtime: PHP 8.2.29
. 1 / 1 (100%)
Time: 00:00.002, Memory: 8.00 MB
OK (1 test, 1 assertion)
xbill@penguin:~/gemini-cli-codeassist/mcp-stdio-php$ make lint
Linting the code...
No syntax errors detected in ./main.php
No syntax errors detected in ./tests/ExampleTest.php
xbill@penguin:~/gemini-cli-codeassist/mcp-stdio-php$ make run
Running the application...
{"message":"Protocol connected to transport","context":{"transport":"Mcp\\Server\\Transport\\StdioTransport"},"level":200,"level_name":"INFO","channel":"mcp","datetime":"2025-12-22T16:18:29.742866+00:00","extra":{}}
{"message":"Running server...","context":{},"level":200,"level_name":"INFO","channel":"mcp","datetime":"2025-12-22T16:18:29.742931+00:00","extra":{}}
Gemini CLI settings.json
The default Gemini CLI settings.json has an entry for the PHP source:
{
"mcpServers": {
"hello-stdio-php": {
"command": "php",
"args": [
"$HOME/gemini-cli-codeassist/mcp-stdio-php/main.php"
]
}
}
}
Validation with Gemini CLI
Finally- Gemini CLI is restarted and the MCP connection over stdio to the PHP Code is validated, The full Gemini CLI Session will start:
> /mcp list
Configured MCP servers:
🟢 hello-stdio-php - Ready (1 tool)
Tools:
- greet
> /mcp schema
Configured MCP servers:
🟢 hello-stdio-php - Ready (1 tool)
Tools:
- greet
Get a greeting from a local stdio server.
Parameters:
{
"type": "object",
"properties": {
"param": {
"type": "string"
}
},
"required": [
"param"
]
}
And you can then connect to the MCP Server over stdio:
> greet ElePHPant!
✦ I'll call the greet tool for you.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ? greet (hello-stdio-php MCP Server) {"param":"ElePHPant!"} ← │
│ │
│ MCP Server: hello-stdio-php │
│ Tool: greet │
│ │
│ Allow execution of MCP tool "greet" from server "hello-stdio-php"? │
│ │
│ 1. Yes, allow once │
│ 2. Yes, always allow tool "greet" from server "hello-stdio-php" │
│ ● 3. Yes, always allow all tools from server "hello-stdio-php" │
│ 4. No, suggest changes (esc) │
│ │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ I'll call the greet tool for you.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ greet (hello-stdio-php MCP Server) {"param":"ElePHPant!"} │
│ │
│ ElePHPant! │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ ElePHPant
Extending the PHP MCP Server with Gemini CLI
Now that the basic MCP functionality has been tested and verified with Gemini CLI- the PHP server code can be extended with new MCP tools:
> > with @main.php add 2 new MCP tools- one that gets the current system time and one that gets system specs and information
Gemini CLI will get right to work:
│ 33 + ->addTool( │
│ 34 + function () use ($logger): string { │
│ 35 + /** │
│ 36 + * Get the current system time. │
│ 37 + */ │
│ 38 + $logger->debug("Executed get_time tool"); │
│ 39 + return date('Y-m-d H:i:s'); │
│ 40 + }, │
│ 41 + 'get_time', │
│ 42 + 'Get the current system time.' │
│ 43 + ) │
│ 44 + ->addTool( │
│ 45 + function () use ($logger): string { │
│ 46 + /** │
│ 47 + * Get system specifications and information. │
│ 48 + */ │
│ 49 + $logger->debug("Executed get_system_specs tool"); │
│ 50 + return json_encode([ │
│ 51 + 'os' => php_uname(), │
│ 52 + 'php_version' => phpversion(), │
│ 53 + 'architecture' => php_uname('m'), │
│ 54 + 'hostname' => gethostname(), │
│ 55 + ], JSON_PRETTY_PRINT); │
│ 56 + }, │
│ 57 + 'get_system_specs', │
│ 58 + 'Get system specifications and information.' │
│ 59 + )
Restart Gemini CLI and check for the new MCP tools:
> /mcp list
Configured MCP servers:
🟢 hello-stdio-php - Ready (3 tools)
Tools:
- get_system_specs
- get_time
- greet
The new MCP tools can be used in the current context:
✦ Greetings! I'm ready to assist you with your PHP-based MCP server project. How can I help you today?
> get_time
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ get_time (hello-stdio-php MCP Server) {} │
│ │
│ 2025-12-22 16:30:15 │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ OK. It's 4:30 PM on Monday, December 22, 2025. What's next?
> how many days until summer arrives?
✦ I will calculate the number of days until the summer solstice (June 21, 2026) for the Northern Hemisphere.
╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ ✓ Shell php -r 'printf("%d days\n", (strtotime("2026-06-21") - strtotime("2025-12-22")) / 86400);' [current working directo… │
│ │
│ 181 days │
╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
✦ There are 181 days until summer arrives in the Northern Hemisphere (June 21, 2026). In the Southern Hemisphere, summer just
began yesterday
and system information:
> can I run ARM binaries native on this system
✦ No, you cannot run ARM binaries natively on this system.
Your CPU is an Intel Core i5-1235U, which uses the x86_64 (AMD64) instruction set architecture. ARM binaries are compiled for a
completely different instruction set used by processors like Apple's M-series, Raspberry Pi, or mobile phone chips.
Key Points:
* Architecture Mismatch: Your system is x86_64. ARM binaries require an aarch64 or armv7 processor to run "natively."
* Emulation Alternative: While you can't run them natively, you can run them via emulation using tools like qemu-user-static.
This allows the x86 CPU to "translate" ARM instructions on the fly, though it is significantly slower than native execution.
* Development: If you are a developer, you can cross-compile code for ARM on this system, but you would still need an ARM
device (or an emulator) to actually execute the resulting binary.
The information from the MCP tool execution comes back into the current Gemini CLI context. You can use the information returned from the tools along with the underlying Gemini Models.
One Last Question for Gemini CLI
Given that the PHP mascot is ElePHPant — who would win a Battle Royale?!?!
> given that the PHP mascot is ElePHPant who would win a battle royale?
Rust Crab, Gopher Go, Python Two Snakes, Java Duke,
ElePHPant, or Node Rocket Turtle?
✦ The introduction of Ferris the Rust Crab completely changes the meta. This is no longer just a brawl; it’s a collision of
philosophies.
Here is the updated Server-Side Arena lineup:
The New Challenger
Ferris the Rust Crab (Rust)
* Class: Ironclad Juggernaut.
* Stats: Max Defense, Max Speed, Steep Learning Curve.
* Special Ability: The Borrow Checker. A passive forcefield that retroactively prevents him from taking damage. If an opponent
tries to hit him in a way that isn't "memory safe," the universe rewinds and prevents the attack from ever happening
(Compile Error).
The Battle Royale v2.0
* Phase 1: The Filtering
* Node Rocket Turtle sprints out of the gate, trips over an undefined is not a function error, and explodes immediately.
* Java Duke is still instantiating his weapon via a WeaponFactoryBuilder. He takes a defensive stance behind a wall of XML
configuration files.
* Python Two Snakes realizes this is a physical fight, not a math problem. They summon a "C-Extension Golem" (NumPy) to
fight for them, hiding behind it.
* Phase 2: The Skirmish
* Gopher (Go) dashes around, creating thousands of clones. He tries to swarm Ferris the Crab.
* Ferris ignores the swarm. He doesn't have a Garbage Collector weighing him down. He moves with the speed of C++ but
without the foot-guns. He snaps his pincers, and the Gopher clones vanish due to a deadlock.
* The Python Snakes' Golem attacks. Ferris looks at the Golem, sees it's written in C, points out a buffer overflow
vulnerability, and the Golem collapses. The Snakes surrender.
* Phase 3: The Standoff
* It comes down to the ElePHPant (The Undying Legacy) vs. Ferris the Crab (The Perfect Machine).
* The ElePHPant attacks with "Spaghetti Code Lash." It's messy, unpredictable, and loosely typed.
* Ferris raises his claw. "Does this variable live long enough?" he whispers. "No."
* The ElePHPant's attack is rejected before it even lands.
* Ferris attacks. He is thread-safe. He is fearless. He pierces the ElePHPant's thick hide with zero-cost abstractions.
* The Twist:
* Just as Ferris is about to deliver the killing blow, he stops. He realizes he has to re-compile the entire world to
finish the move. The compile time takes 20 minutes.
* In that time, the ElePHPant patches itself, deploys a hotfix, and wanders away to serve another billion WordPress
requests.
The Winner: Draw / Stalemate
* Ferris (Rust) is technically the superior fighter. He took zero damage and dominated the field.
* ElePHPant (PHP) is the survivor. You can't kill him because he doesn't care if he's "correct," he only cares if he's
"running."
But if forced to pick a killer: Ferris the Crab. If the battle goes long enough, the Crab's safety and efficiency eventually
grind the Elephant down. The Elephant is aging; the Crab is the future.
Summary
The strategy for using PHP for MCP development with Gemini CLI was validated with a incremental step by step approach.
A minimal stdio transport MCP Server was started from PHP 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 PHP code with several MCP tools and use these tools inside the context for the underlying LLM.
This approach can be extended to more complex deployments using other MCP transports and Cloud based options.
Local MCP Development with PHP and Gemini CLI was originally published in Google Cloud – Community on Medium, where people are continuing the conversation by highlighting and responding to this story.
Source Credit: https://medium.com/google-cloud/local-mcp-development-with-php-and-gemini-cli-f39aae6ccf6c?source=rss—-e52cf94d98af—4
