DEV Community: Google Developer Experts The latest articles on DEV Community by Google Developer Experts (@gde). https://dev.to/gde https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F11939%2Fe3080d5b-ecde-42a8-b089-bafecc31fa97.png DEV Community: Google Developer Experts https://dev.to/gde en MCP Development with Python, and the Azure App Service xbill Fri, 20 Mar 2026 13:15:21 +0000 https://dev.to/gde/mcp-development-with-python-and-the-azure-app-service-3ekl https://dev.to/gde/mcp-development-with-python-and-the-azure-app-service-3ekl <p>Leveraging Gemini CLI and the underlying Gemini LLM to build Model Context Protocol (MCP) AI applications with Python with a local development environment deployed to the Azure App Service container runtime.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjycsd6ktdqeh7ruho2mk.jpeg" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjycsd6ktdqeh7ruho2mk.jpeg"></a></p> <h4> What is Gemini CLI? </h4> <p>The Gemini CLI is an open-source, terminal-based AI agent from Google that allows developers to interact directly with Gemini models, such as Gemini 2.5 Pro, for coding, content creation, and workflow automation. It supports file operations, shell commands, and connects to external tools via the Model Context Protocol (MCP).</p> <p>The full details on Gemini CLI are available here:</p> <p><a href="proxy.php?url=https://geminicli.com/" rel="noopener noreferrer">Build, debug &amp; deploy with AI</a></p> <h4> Azure App Service </h4> <p>Azure App Service is a fully managed Platform-as-a-Service (PaaS) that enables developers to build, deploy, and scale web applications, APIs, and mobile backends quickly. It supports multiple languages (<a href="proxy.php?url=https://www.google.com/search?q=.NET&amp;rlz=1CAIWTJ_enUS1155&amp;oq=what+is+azure+app+service&amp;gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIHCAEQABiABDIHCAIQABiABDIHCAMQABiABDIHCAQQABiABDIHCAUQABiABDIICAYQABgWGB4yCAgHEAAYFhgeMggICBAAGBYYHjIICAkQABgWGB7SAQgzNzkzajBqN6gCALACAA&amp;sourceid=chrome&amp;ie=UTF-8&amp;ved=2ahUKEwiLxOi4mKWTAxUfkYkEHW3NNloQgK4QegYIAQgAEAQ" rel="noopener noreferrer">.NET</a>, <a href="proxy.php?url=https://www.google.com/search?q=Java&amp;rlz=1CAIWTJ_enUS1155&amp;oq=what+is+azure+app+service&amp;gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIHCAEQABiABDIHCAIQABiABDIHCAMQABiABDIHCAQQABiABDIHCAUQABiABDIICAYQABgWGB4yCAgHEAAYFhgeMggICBAAGBYYHjIICAkQABgWGB7SAQgzNzkzajBqN6gCALACAA&amp;sourceid=chrome&amp;ie=UTF-8&amp;ved=2ahUKEwiLxOi4mKWTAxUfkYkEHW3NNloQgK4QegYIAQgAEAU" rel="noopener noreferrer">Java</a>, <a href="proxy.php?url=https://www.google.com/search?q=Node.js&amp;rlz=1CAIWTJ_enUS1155&amp;oq=what+is+azure+app+service&amp;gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIHCAEQABiABDIHCAIQABiABDIHCAMQABiABDIHCAQQABiABDIHCAUQABiABDIICAYQABgWGB4yCAgHEAAYFhgeMggICBAAGBYYHjIICAkQABgWGB7SAQgzNzkzajBqN6gCALACAA&amp;sourceid=chrome&amp;ie=UTF-8&amp;ved=2ahUKEwiLxOi4mKWTAxUfkYkEHW3NNloQgK4QegYIAQgAEAY" rel="noopener noreferrer">Node.js</a>, <a href="proxy.php?url=https://www.google.com/search?q=Python&amp;rlz=1CAIWTJ_enUS1155&amp;oq=what+is+azure+app+service&amp;gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIHCAEQABiABDIHCAIQABiABDIHCAMQABiABDIHCAQQABiABDIHCAUQABiABDIICAYQABgWGB4yCAgHEAAYFhgeMggICBAAGBYYHjIICAkQABgWGB7SAQgzNzkzajBqN6gCALACAA&amp;sourceid=chrome&amp;ie=UTF-8&amp;ved=2ahUKEwiLxOi4mKWTAxUfkYkEHW3NNloQgK4QegYIAQgAEAc" rel="noopener noreferrer">Python</a>, PHP) on Windows or Linux, offering built-in CI/CD, auto-scaling, and high security.</p> <p><a href="proxy.php?url=https://azure.microsoft.com/en-us/products/app-service" rel="noopener noreferrer">https://azure.microsoft.com/en-us/products/app-service</a></p> <h4> Why would I want Gemini CLI with Azure? Isn’t that a Google Thing? </h4> <p>Yes- Gemini CLI leverages the Google Cloud console and Gemini models but it is also open source and platform agnostic. Many applications are already cross-cloud so this enables familiar tools to be run natively on Microsoft Azure.</p> <h4> Node Version Management </h4> <p>Gemini CLI needs a consistent, up to date version of Node. The <strong>nvm</strong> command can be used to get a standard Node environment:</p> <p><a href="proxy.php?url=https://github.com/nvm-sh/nvm" rel="noopener noreferrer">GitHub - nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions</a></p> <h4> Gemini CLI Installation </h4> <p>You can then download the Gemini CLI :<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>npm <span class="nb">install</span> <span class="nt">-g</span> @google/gemini-cli </code></pre> </div> <p>You will see the log messages:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">azureuser@azure-new:~/gemini-cli-azure$</span><span class="w"> </span>npm <span class="nb">install</span> <span class="nt">-g</span> @google/gemini-cli <span class="gp">npm warn deprecated [email protected]: No longer maintained. Please contact the author of the relevant native addon;</span><span class="w"> </span>alternatives are available. <span class="go">npm warn deprecated [email protected]: Use your platform's native DOMException instead npm warn deprecated [email protected]: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting [email protected] </span></code></pre> </div> <h4> Testing the Gemini CLI Environment </h4> <p>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:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>gemini </code></pre> </div> <h4> Authentication </h4> <p>Several authentication options are available. To use an existing Code Assist licence — authenticate with a Google Account:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>&gt; /auth ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ ? Get started │ │ │ │ How would you like to authenticate for this project? │ │ │ │ ● 1. Login with Google │ │ 2. Use Gemini API Key │ │ 3. Vertex AI │ │ │ │ (Use Enter to select) │ │ │ │ Terms of Services and Privacy Notice for Gemini CLI │ │ │ │ https://geminicli.com/docs/resources/tos-privacy/ │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ </code></pre> </div> <p>Then set the GOOGLE_CLOUD_PROJECT to a valid project setup on the Google Cloud console:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>~ <span class="nv">$ </span><span class="nb">export </span><span class="nv">GOOGLE_CLOUD_PROJECT</span><span class="o">=</span>comglitn ~ <span class="err">$</span> </code></pre> </div> <p>Other options include Google Cloud API Key that can be generated directly from the Google Cloud Console.</p> <h4> Installing Google Cloud Tools </h4> <p>To simplify working with Google Cloud — install the Google Cloud Tools:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>https://docs.cloud.google.com/sdk/docs/install-sdk </code></pre> </div> <p>Once the installation is completed — you can verify the setup:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">william@Azure:~$</span><span class="w"> </span>gcloud auth list <span class="go"> Credentialed Accounts ACTIVE ACCOUNT * [email protected] </span></code></pre> </div> <h4> Installing Azure Customized GEMINI.md </h4> <p>A sample GitHub repo contains tools for working with Gemini CLI on Azure. This repo is available here:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>git clone https://gitHub.com/xbill9/gemini-cli-azure </code></pre> </div> <p>A sample <strong>GEMINI.md</strong> customized for the Azure environment is provided in the repo:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight markdown"><code>This is a multi linux git repo hosted at: github.com/xbill9/gemini-cli-azure You are a cross platform developer working with Microsoft Azure and Google Cloud You can use the Azure CLI : https://learn.microsoft.com/en-us/cli/azure/install-azure-cli https://learn.microsoft.com/en-us/cli/azure/ https://learn.microsoft.com/en-us/cli/azure/reference https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux?view=azure-cli-latest&amp;pivots=apt <span class="gu">## Azure CLI Tools</span> You can use the Azure CLI to manage resources across Azure Storage, Virtual Machines, and other services. <span class="p"> -</span> <span class="gs">**List Resource Groups**</span> : <span class="sb">`az group list -o table`</span> <span class="p">-</span> <span class="gs">**List Storage Accounts**</span> : <span class="sb">`az storage account list -o table`</span> <span class="p">-</span> <span class="gs">**List Virtual Machines**</span> : <span class="sb">`az vm list -d -o table`</span> <span class="gu">### Azure Update Script</span> <span class="p"> -</span> <span class="sb">`azure-update`</span>: This script is specifically for Azure Linux environments. It updates all packages and ensures necessary libraries are installed. <span class="gu">## Automation Scripts</span> This repository contains scripts for updating various Linux environments and tools: <span class="p"> -</span> <span class="sb">`linux-update`</span>: Detects OS (Debian/Ubuntu/Azure Linux) and runs the corresponding update scripts. <span class="p">-</span> <span class="sb">`azure-update`</span>: Updates Azure Linux packages and installs necessary dependencies. <span class="p">-</span> <span class="sb">`debian-update`</span>: Updates Debian/Ubuntu packages and installs <span class="sb">`git`</span>. <span class="p">-</span> <span class="sb">`gemini-update`</span>: Updates the <span class="sb">`@google/gemini-cli`</span> via npm and checks versions of Node.js and Gemini. <span class="p">-</span> <span class="sb">`nvm-update`</span>: Installs NVM (Node Version Manager) and Node.js version 25. </code></pre> </div> <h4> Python MCP Documentation </h4> <p>The official GitHub Repo provides samples and documentation for getting started:</p> <p><a href="proxy.php?url=https://github.com/modelcontextprotocol/python-sdk" rel="noopener noreferrer">GitHub - modelcontextprotocol/python-sdk: The official Python SDK for Model Context Protocol servers and clients</a></p> <p>The most common MCP Python deployment path uses the FASTMCP library:</p> <p><a href="proxy.php?url=https://gofastmcp.com/getting-started/welcome" rel="noopener noreferrer">Welcome to FastMCP - FastMCP</a></p> <h4> Where do I start? </h4> <p>The strategy for starting MCP development is a incremental step by step approach.</p> <p>First, the basic development environment is setup with the required system variables, and a working Gemini CLI configuration.</p> <p>Then, a minimal Hello World Style Python MCP Server was built with stdio transport. This server was validated with Gemini CLI in the local environment.</p> <p>This current setup validates the connection from Gemini CLI to the local process via MCP. The MCP client (Gemini CLI) and the Python MCP server both run in the same local environment.</p> <p>Next- the basic MCP server is extended with Gemini CLI to add several new tools in standard Python code.</p> <h4> Setup the Basic Environment </h4> <p>At this point you should have a working Python interpreter and a working Gemini CLI installation. The next step is to clone the GitHub samples repository with support scripts:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd</span> ~ git clone https://github.com/xbill9/gemini-cli-azure </code></pre> </div> <p>Then run <strong>init.sh</strong> from the cloned directory.</p> <p>The script will attempt to determine your shell environment and set the correct variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd </span>gemini-cli-azure <span class="nb">source </span>init.sh </code></pre> </div> <p>If your session times out or you need to re-authenticate- you can run the <strong>set_env.sh</strong> script to reset your environment variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd </span>gemini-cli-azure <span class="nb">source </span>set_env.sh </code></pre> </div> <p>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.</p> <h4> Hello World with HTTP Transport </h4> <p>One of the key features that the standard MCP libraries provide is abstracting various transport methods.</p> <p>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.</p> <p>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.</p> <p>The HTTP transport allows the MCP Client and Server to be in the same environment or distributed over the Internet.</p> <p>The connection over HTTP will look similar to this:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code><span class="n">mcp</span><span class="p">.</span><span class="nf">run</span><span class="p">(</span> <span class="n">transport</span><span class="o">=</span><span class="sh">"</span><span class="s">http</span><span class="sh">"</span><span class="p">,</span> <span class="n">host</span><span class="o">=</span><span class="sh">"</span><span class="s">0.0.0.0</span><span class="sh">"</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="n">port</span><span class="p">,</span> <span class="p">)</span> </code></pre> </div> <h4> Running the Python Code </h4> <p>First- switch the directory with the Python MCP sample code:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-azure/mcp-appservice-python-azure$</span><span class="w"> </span>make <span class="go">pip install -r requirements.txt </span></code></pre> </div> <p>You can validate the final result by checking the messages:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight json"><code><span class="p">[</span><span class="mi">03</span><span class="err">/</span><span class="mi">16</span><span class="err">/</span><span class="mi">26</span><span class="w"> </span><span class="mi">15</span><span class="err">:</span><span class="mi">55</span><span class="err">:</span><span class="mi">34</span><span class="p">]</span><span class="w"> </span><span class="err">INFO</span><span class="w"> </span><span class="err">Starting</span><span class="w"> </span><span class="err">MCP</span><span class="w"> </span><span class="err">server</span><span class="w"> </span><span class="err">'hello-world-server'</span><span class="w"> </span><span class="err">with</span><span class="w"> </span><span class="err">transport</span><span class="w"> </span><span class="err">'http'</span><span class="w"> </span><span class="err">on</span><span class="w"> </span><span class="err">http://</span><span class="mf">0.0</span><span class="err">.</span><span class="mf">0.0</span><span class="err">:</span><span class="mi">8080</span><span class="err">/mcp</span><span class="w"> </span><span class="err">server.py:</span><span class="mi">2618</span><span class="w"> </span><span class="err">INFO:</span><span class="w"> </span><span class="err">Started</span><span class="w"> </span><span class="err">server</span><span class="w"> </span><span class="err">process</span><span class="w"> </span><span class="p">[</span><span class="mi">24332</span><span class="p">]</span><span class="w"> </span><span class="err">INFO:</span><span class="w"> </span><span class="err">Waiting</span><span class="w"> </span><span class="err">for</span><span class="w"> </span><span class="err">application</span><span class="w"> </span><span class="err">startup.</span><span class="w"> </span><span class="p">{</span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Starting worker 'penguin#24332' with the following tasks:"</span><span class="p">}</span><span class="w"> </span><span class="p">{</span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"* trace(message: str, ...)"</span><span class="p">}</span><span class="w"> </span><span class="p">{</span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"* fail(message: str, ...)"</span><span class="p">}</span><span class="w"> </span><span class="p">{</span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"* sleep(seconds: float, ...)"</span><span class="p">}</span><span class="w"> </span><span class="p">{</span><span class="nl">"message"</span><span class="p">:</span><span class="w"> </span><span class="s2">"StreamableHTTP session manager started"</span><span class="p">}</span><span class="w"> </span><span class="err">INFO:</span><span class="w"> </span><span class="err">Application</span><span class="w"> </span><span class="err">startup</span><span class="w"> </span><span class="err">complete.</span><span class="w"> </span><span class="err">INFO:</span><span class="w"> </span><span class="err">Uvicorn</span><span class="w"> </span><span class="err">running</span><span class="w"> </span><span class="err">on</span><span class="w"> </span><span class="err">http://</span><span class="mf">0.0</span><span class="err">.</span><span class="mf">0.0</span><span class="err">:</span><span class="mi">8080</span><span class="w"> </span><span class="err">(Press</span><span class="w"> </span><span class="err">CTRL+C</span><span class="w"> </span><span class="err">to</span><span class="w"> </span><span class="err">quit)</span><span class="w"> </span></code></pre> </div> <p>Once you have validated the server can run locally — exit with control-c.</p> <p>Then run a deployment to Azure App Service:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-azure/mcp-appservice-python-azure$</span><span class="w"> </span>make deploy <span class="go">Building the Docker image... Deployment complete. Visit: http://mcp-app-penguin.azurewebsites.net xbill@penguin:~/gemini-cli-azure/mcp-appservice-python-azure </span></code></pre> </div> <h4> Gemini CLI settings.json </h4> <p>The default Gemini CLI settings.json has an entry for the Python source:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight json"><code><span class="p">{</span><span class="w"> </span><span class="nl">"mcpServers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"azure-appservice-python"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"httpUrl"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://mcp-app-penguin.azurewebsites.net/mcp"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre> </div> <h4> Validation with Gemini CLI </h4> <p>Leaver the MCP server window running. Start a new shell. Gemini CLI is restarted and the MCP connection over HTTP to the Python Code is validated, The full Gemini CLI Session will start:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-azure/mcp-appservice-python-azure$</span><span class="w"> </span>gemini <span class="go"> ▝▜▄ Gemini CLI v0.33.1 ▝▜▄ ▗▟▀ Logged in with Google /auth ▝▀ Gemini Code Assist Standard /upgrade </span><span class="gp"> &gt;</span><span class="w"> </span>/mcp list <span class="go">Configured MCP servers: 🟢 azure-appservice-python - Ready (1 tool) Tools: - mcp_azure-appservice-python_greet ? for shortcuts </span></code></pre> </div> <p>And you can then connect to the MCP Server over HTTP:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code> &gt; greet Azure App Service! ✦ I will call the greet tool with "Azure App Service!" as the argument. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ Action Required │ │ │ │ ? greet (azure-appservice-python MCP Server) {"param":"Azure App Service!"} │ │ │ │ MCP Server: azure-appservice-python │ │ Tool: greet │ │ │ │ MCP Tool Details: │ │ (press Ctrl+O to expand MCP tool details) │ │ Allow execution of MCP tool "greet" from server "azure-appservice-python"? │ │ │ │ 1. Allow once │ │ 2. Allow tool for this session │ │ 3. Allow all server tools for this session │ │ ● 4. Allow tool for all future sessions │ │ 5. No, suggest changes (esc) │ │ │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ I will call the greet tool with "Azure App Service!" as the argument. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ greet (azure-appservice-python MCP Server) {"param":"Azure App Service!"} │ │ │ │ Azure App Service! │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ Azure App Service! </code></pre> </div> <h4> Project Review </h4> <p>Finally — you can use Gemini CLI to review the project:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>✦ This project is a Python-based Model Context Protocol (MCP) server named hello-world-server, built using the FastMCP framework and optimized for deployment to Azure App Service. Core Features * Protocol: Implements the MCP standard over HTTP (defaulting to port 8080). * Tools: Exposes a greet tool that echoes back a provided string parameter. * Health Check: Includes a standard /health GET endpoint for monitoring. * Logging: Uses python-json-logger to send structured logs to stderr, keeping stdout clear for protocol communication. Infrastructure &amp; Deployment * Containerization: Uses a python:3.13-slim Docker image for consistent environments. * Azure Integration: Fully automated deployment pipeline via Makefile that handles: * ACR: Creating and pushing images to Azure Container Registry. * App Service: Provisioning Linux App Service Plans and Web Apps. * Configuration: Automatically setting PORT and WEBSITES_PORT environment variables. * Live Endpoint: The current configuration (settings.json) points to https://mcp-app-penguin.azurewebsites.net/mcp. Development Workflow * Local Execution: Run via python main.py or make run. * Management: The Makefile provides utility commands for status, endpoint, az-logs, and clean. * Dependencies: Managed via requirements.txt (primarily mcp, fastmcp, python-json-logger, and starlette). </code></pre> </div> <h4> Summary </h4> <p>The strategy for using Python for MCP development with Gemini CLI was validated with a incremental step by step approach.</p> <p>A minimal HTTP transport MCP Server was started from Python source code and validated with Gemini CLI running as a MCP client in the same local environment. Then this solution was deployed remotely to the Azure App Service and validated with the local installation of Gemini CLI.</p> <p>This approach can be extended to more complex deployments using other MCP transports and Cloud based options.</p> python azureappservice azure mcpserver MCP Development with Python, Gemini CLI, and the Azure Linux VM xbill Thu, 19 Mar 2026 13:37:56 +0000 https://dev.to/gde/mcp-development-with-python-gemini-cli-and-the-azure-linux-vm-92f https://dev.to/gde/mcp-development-with-python-gemini-cli-and-the-azure-linux-vm-92f <p>Leveraging Gemini CLI and the underlying Gemini LLM to build Model Context Protocol (MCP) AI applications with Python with a local development environment hosted on an Azure Linux VM.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjycsd6ktdqeh7ruho2mk.jpeg" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjycsd6ktdqeh7ruho2mk.jpeg"></a></p> <h4> What is Gemini CLI? </h4> <p>The Gemini CLI is an open-source, terminal-based AI agent from Google that allows developers to interact directly with Gemini models, such as Gemini 2.5 Pro, for coding, content creation, and workflow automation. It supports file operations, shell commands, and connects to external tools via the Model Context Protocol (MCP).</p> <p>The full details on Gemini CLI are available here:</p> <p><a href="proxy.php?url=https://geminicli.com/" rel="noopener noreferrer">Build, debug &amp; deploy with AI</a></p> <h4> Configuring an Azure Linux VM </h4> <p>Step by step instructions on configuring an Azure Linux VM are here:</p> <p><a href="proxy.php?url=https://xbill999.medium.com/customizing-an-azure-vm-for-cross-cloud-development-a27c4855721b" rel="noopener noreferrer">Customizing an Azure VM for Cross Cloud Development</a></p> <h4> Why would I want Gemini CLI on Azure? Isn’t that a Google Thing? </h4> <p>Yes- Gemini CLI leverages the Google Cloud console and Gemini models but it is also open source and platform agnostic. Many applications are already cross-cloud so this enables familiar tools to be run natively on Microsoft Azure.</p> <h4> Node Version Management </h4> <p>Gemini CLI needs a consistent, up to date version of Node. The <strong>nvm</strong> command can be used to get a standard Node environment:</p> <p><a href="proxy.php?url=https://github.com/nvm-sh/nvm" rel="noopener noreferrer">GitHub - nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions</a></p> <h4> Verifying Node.js in Azure VM </h4> <p>The version of Node.js is verified that it is recent enough to support Gemini CLI:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">azureuser@azure-new:~$</span><span class="w"> </span>nvm <span class="nt">--version</span> <span class="go">0.40.3 </span><span class="gp">azureuser@azure-new:~$</span><span class="w"> </span>node <span class="nt">--version</span> <span class="go">v25.8.1 </span><span class="gp">azureuser@azure-new:~$</span><span class="w"> </span>npm <span class="nt">--version</span> <span class="go">11.11.0 </span></code></pre> </div> <h4> Gemini CLI Installation </h4> <p>You can then download the Gemini CLI :<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>npm <span class="nb">install</span> <span class="nt">-g</span> @google/gemini-cli </code></pre> </div> <p>You will see the log messages:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">azureuser@azure-new:~/gemini-cli-azure$</span><span class="w"> </span>npm <span class="nb">install</span> <span class="nt">-g</span> @google/gemini-cli <span class="gp">npm warn deprecated [email protected]: No longer maintained. Please contact the author of the relevant native addon;</span><span class="w"> </span>alternatives are available. <span class="go">npm warn deprecated [email protected]: Use your platform's native DOMException instead npm warn deprecated [email protected]: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting [email protected] added 618 packages in 1m 173 packages are looking for funding run `npm fund` for details </span></code></pre> </div> <h4> Testing the Gemini CLI Environment </h4> <p>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:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>gemini </code></pre> </div> <h4> Authentication </h4> <p>Several authentication options are available. To use an existing Code Assist licence — authenticate with a Google Account:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>&gt; /auth ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ ? Get started │ │ │ │ How would you like to authenticate for this project? │ │ │ │ ● 1. Login with Google │ │ 2. Use Gemini API Key │ │ 3. Vertex AI │ │ │ │ (Use Enter to select) │ │ │ │ Terms of Services and Privacy Notice for Gemini CLI │ │ │ │ https://geminicli.com/docs/resources/tos-privacy/ │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ </code></pre> </div> <p>Then set the GOOGLE_CLOUD_PROJECT to a valid project setup on the Google Cloud console:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>~ <span class="nv">$ </span><span class="nb">export </span><span class="nv">GOOGLE_CLOUD_PROJECT</span><span class="o">=</span>comglitn ~ <span class="err">$</span> </code></pre> </div> <p>Other options include Google Cloud API Key that can be generated directly from the Google Cloud Console.</p> <h4> Installing Google Cloud Tools </h4> <p>To simplify working with Google Cloud — install the Google Cloud Tools:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>https://docs.cloud.google.com/sdk/docs/install-sdk </code></pre> </div> <p>Once the installation is completed — you can verify the setup:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">william@Azure:~$</span><span class="w"> </span>gcloud auth list <span class="go"> Credentialed Accounts ACTIVE ACCOUNT * [email protected] </span></code></pre> </div> <h4> Installing Azure Customized GEMINI.md </h4> <p>A sample GitHub repo contains tools for working with Gemini CLI on Azure. This repo is available here:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>git clone https://gitHub.com/xbill9/gemini-cli-azure </code></pre> </div> <p>A sample <strong>GEMINI.md</strong> customized for the Azure environment is provided in the repo:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight markdown"><code>You are a cross platform developer working with Microsoft Azure and Google Cloud You can use the Azure CLI : https://learn.microsoft.com/en-us/cli/azure/install-azure-cli https://learn.microsoft.com/en-us/cli/azure/ https://learn.microsoft.com/en-us/cli/azure/reference https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux?view=azure-cli-latest&amp;pivots=apt <span class="gu">## Azure CLI Tools</span> You can use the Azure CLI to manage resources across Azure Storage, Virtual Machines, and other services. <span class="p"> -</span> <span class="gs">**List Resource Groups**</span> : <span class="sb">`az group list -o table`</span> <span class="p">-</span> <span class="gs">**List Storage Accounts**</span> : <span class="sb">`az storage account list -o table`</span> <span class="p">-</span> <span class="gs">**List Virtual Machines**</span> : <span class="sb">`az vm list -d -o table`</span> <span class="gu">### Azure Update Script</span> <span class="p"> -</span> <span class="sb">`azure-update`</span>: This script is specifically for Azure Linux environments. It updates all packages and ensures necessary libraries are instal led. <span class="gu">## Automation Scripts</span> This repository contains scripts for updating various Linux environments and tools: <span class="p"> -</span> <span class="sb">`linux-update`</span>: Detects OS (Debian/Ubuntu/Azure Linux) and runs the corresponding update scripts. <span class="p">-</span> <span class="sb">`azure-update`</span>: Updates Azure Linux packages and installs necessary dependencies. <span class="p">-</span> <span class="sb">`debian-update`</span>: Updates Debian/Ubuntu packages and installs <span class="sb">`git`</span>. <span class="p">-</span> <span class="sb">`gemini-update`</span>: Updates the <span class="sb">`@google/gemini-cli`</span> via npm and checks versions of Node.js and Gemini. <span class="p">-</span> <span class="sb">`nvm-update`</span>: Installs NVM (Node Version Manager) and Node.js version 25. </code></pre> </div> <h4> Python MCP Documentation </h4> <p>The official GitHub Repo provides samples and documentation for getting started:</p> <p><a href="proxy.php?url=https://github.com/modelcontextprotocol/python-sdk" rel="noopener noreferrer">GitHub - modelcontextprotocol/python-sdk: The official Python SDK for Model Context Protocol servers and clients</a></p> <p>The most common MCP Python deployment path uses the FASTMCP library:</p> <p><a href="proxy.php?url=https://gofastmcp.com/getting-started/welcome" rel="noopener noreferrer">Welcome to FastMCP - FastMCP</a></p> <h4> Where do I start? </h4> <p>The strategy for starting MCP development is a incremental step by step approach.</p> <p>First, the basic development environment is setup with the required system variables, and a working Gemini CLI configuration.</p> <p>Then, a minimal Hello World Style Python MCP Server was built with stdio transport. This server was validated with Gemini CLI in the local environment.</p> <p>This current setup validates the connection from Gemini CLI to the local process via MCP. The MCP client (Gemini CLI) and the Python MCP server both run in the same local environment.</p> <p>Next- the basic MCP server is extended with Gemini CLI to add several new tools in standard Python code.</p> <h4> Setup the Basic Environment </h4> <p>At this point you should have a working Python interpreter and a working Gemini CLI installation. The next step is to clone the GitHub samples repository with support scripts:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd</span> ~ git clone https://github.com/xbill9/gemini-cli-azure </code></pre> </div> <p>Then run <strong>init.sh</strong> from the cloned directory.</p> <p>The script will attempt to determine your shell environment and set the correct variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd </span>gemini-cli-azure <span class="nb">source </span>init.sh </code></pre> </div> <p>If your session times out or you need to re-authenticate- you can run the <strong>set_env.sh</strong> script to reset your environment variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd </span>gemini-cli-azure <span class="nb">source </span>set_env.sh </code></pre> </div> <p>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.</p> <h4> Hello World with HTTP Transport </h4> <p>One of the key features that the standard MCP libraries provide is abstracting various transport methods.</p> <p>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.</p> <p>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.</p> <p>The HTTP transport allows the MCP Client and Server to be in the same environment or distributed over the Internet.</p> <p>The connection over HTTP will look similar to this:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code> <span class="n">mcp</span><span class="p">.</span><span class="nf">run</span><span class="p">(</span> <span class="n">transport</span><span class="o">=</span><span class="sh">"</span><span class="s">http</span><span class="sh">"</span><span class="p">,</span> <span class="n">host</span><span class="o">=</span><span class="sh">"</span><span class="s">0.0.0.0</span><span class="sh">"</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="n">port</span><span class="p">,</span> <span class="p">)</span> </code></pre> </div> <h4> Running the Python Code </h4> <p>First- switch the directory with the Python MCP sample code:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd</span> ~/gemini-cli-aws/mcp-https-python-azure make release </code></pre> </div> <p>You can validate the final result by checking the messages:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="go"> ╭──────────────────────────────────────────────────────────────────────────────╮ │ │ │ │ │ ▄▀▀ ▄▀█ █▀▀ ▀█▀ █▀▄▀█ █▀▀ █▀█ │ │ █▀ █▀█ ▄▄█ █ █ ▀ █ █▄▄ █▀▀ │ │ │ │ │ │ FastMCP 3.1.1 │ │ https://gofastmcp.com │ │ │ │ 🖥 Server: hello-world-server, 3.1.1 │ │ 🚀 Deploy free: https://fastmcp.cloud │ │ │ ╰──────────────────────────────────────────────────────────────────────────────╯ [03/16/26 17:37:02] INFO Starting MCP server 'hello-world-server' with transport 'http' on http://0.0.0.0:8080/mcp transport.py:273 INFO: Started server process [3700] INFO: Waiting for application startup. {"message": "StreamableHTTP session manager started"} INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8080 (Press CTRL+C to quit) </span></code></pre> </div> <h4> Gemini CLI settings.json </h4> <p>The default Gemini CLI settings.json has an entry for the Python source:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight json"><code><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"mcpServers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"azure-https-python"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"httpUrl"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://127.0.0.1:8080/mcp"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre> </div> <h4> Validation with Gemini CLI </h4> <p>Leaver the MCP server window running. Start a new shell. Gemini CLI is restarted and the MCP connection over HTTP to the Python Code is validated, The full Gemini CLI Session will start:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">azureuser@azure-new:~/gemini-cli-azure/mcp-https-python-azure$</span><span class="w"> </span>gemini <span class="go"> </span><span class="gp">azureuser@azure-new:~/gemini-cli-azure/mcp-https-python-azure$</span><span class="w"> </span>gemini <span class="go"> ▝▜▄ Gemini CLI v0.33.1 ▝▜▄ ▗▟▀ Logged in with Google /auth ▝▀ Gemini Code Assist Standard /upgrade </span><span class="gp">&gt;</span><span class="w"> </span>/mcp list <span class="go">Configured MCP servers: 🟢 azure-https-python - Ready (1 tool) Tools: - mcp_azure-https-python_greet ? for shortcuts ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── shift+tab to accept edits 3 GEMINI.md files | 1 MCP server ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── </span><span class="gp"> &gt;</span><span class="w"> </span></code></pre> </div> <p>And you can then connect to the MCP Server over stdio:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">&gt;</span><span class="w"> </span>greet Azure VM! <span class="go"> ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ Action Required 1 of 2 │ │ │ │ ? greet (azure-https-python MCP Server) {"param":"HTTPS transport!"} │ │ │ │ MCP Server: azure-https-python │ │ Tool: greet │ │ │ │ MCP Tool Details: │ │ (press Ctrl+O to expand MCP tool details) │ │ Allow execution of MCP tool "greet" from server "azure-https-python"? │ │ │ │ 1. Allow once │ │ 2. Allow tool for this session │ │ 3. Allow all server tools for this session │ │ ● 4. Allow tool for all future sessions │ │ 5. No, suggest changes (esc) │ │ │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ I will greet the HTTPS transport and the Azure VM HTTPS transport using the MCP tool. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ greet (azure-https-python MCP Server) {"param":"HTTPS transport!"} │ │ │ │ HTTPS transport! │ │ │ │ ✓ greet (azure-https-python MCP Server) {"param":"Azure VM HTTPS transport!"} │ │ │ │ Azure VM HTTPS transport! │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ I've sent the greetings for the HTTPS transport and the Azure VM HTTPS transport. </span></code></pre> </div> <h4> Summary </h4> <p>The strategy for using Python for MCP development with Gemini CLI was validated with a incremental step by step approach.</p> <p>A minimal HTTP transport MCP Server was started from Python source code and validated with Gemini CLI running as a MCP client in the same local environment.</p> <p>This approach can be extended to more complex deployments using other MCP transports and Cloud based options.</p> azure gemini azurelinux mcpserver Local MCP Development with Python, Gemini CLI, and an Azure Linux VM xbill Thu, 19 Mar 2026 13:04:04 +0000 https://dev.to/gde/local-mcp-development-with-python-gemini-cli-and-an-azure-linux-vm-4ooi https://dev.to/gde/local-mcp-development-with-python-gemini-cli-and-an-azure-linux-vm-4ooi <p>Leveraging Gemini CLI and the underlying Gemini LLM to build Model Context Protocol (MCP) AI applications with Python with a local development environment hosted on an Azure Linux VM.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjycsd6ktdqeh7ruho2mk.jpeg" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjycsd6ktdqeh7ruho2mk.jpeg"></a></p> <h4> What is Gemini CLI? </h4> <p>The Gemini CLI is an open-source, terminal-based AI agent from Google that allows developers to interact directly with Gemini models, such as Gemini 2.5 Pro, for coding, content creation, and workflow automation. It supports file operations, shell commands, and connects to external tools via the Model Context Protocol (MCP).</p> <p>The full details on Gemini CLI are available here:</p> <p><a href="proxy.php?url=https://geminicli.com/" rel="noopener noreferrer">Build, debug &amp; deploy with AI</a></p> <h4> Configuring an Azure Linux VM </h4> <p>Step by step instructions on configuring an Azure Linux VM are here:</p> <p><a href="proxy.php?url=https://xbill999.medium.com/customizing-an-azure-vm-for-cross-cloud-development-a27c4855721b" rel="noopener noreferrer">Customizing an Azure VM for Cross Cloud Development</a></p> <h4> Why would I want Gemini CLI on Azure? Isn’t that a Google Thing? </h4> <p>Yes- Gemini CLI leverages the Google Cloud console and Gemini models but it is also open source and platform agnostic. Many applications are already cross-cloud so this enables familiar tools to be run natively on Microsoft Azure.</p> <h4> Node Version Management </h4> <p>Gemini CLI needs a consistent, up to date version of Node. The <strong>nvm</strong> command can be used to get a standard Node environment:</p> <p><a href="proxy.php?url=https://github.com/nvm-sh/nvm" rel="noopener noreferrer">GitHub - nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions</a></p> <h4> Verifying Node.js in Azure VM </h4> <p>The version of Node.js is verified that it is recent enough to support Gemini CLI:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">azureuser@azure-new:~$</span><span class="w"> </span>nvm <span class="nt">--version</span> <span class="go">0.40.3 </span><span class="gp">azureuser@azure-new:~$</span><span class="w"> </span>node <span class="nt">--version</span> <span class="go">v25.8.1 </span><span class="gp">azureuser@azure-new:~$</span><span class="w"> </span>npm <span class="nt">--version</span> <span class="go">11.11.0 </span></code></pre> </div> <h4> Gemini CLI Installation </h4> <p>You can then download the Gemini CLI :<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>npm <span class="nb">install</span> <span class="nt">-g</span> @google/gemini-cli </code></pre> </div> <p>You will see the log messages:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">azureuser@azure-new:~/gemini-cli-azure$</span><span class="w"> </span>npm <span class="nb">install</span> <span class="nt">-g</span> @google/gemini-cli <span class="gp">npm warn deprecated [email protected]: No longer maintained. Please contact the author of the relevant native addon;</span><span class="w"> </span>alternatives are available. <span class="go">npm warn deprecated [email protected]: Use your platform's native DOMException instead npm warn deprecated [email protected]: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting [email protected] added 618 packages in 1m 173 packages are looking for funding run `npm fund` for details </span></code></pre> </div> <h4> Testing the Gemini CLI Environment </h4> <p>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:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>gemini </code></pre> </div> <h4> Authentication </h4> <p>Several authentication options are available. To use an existing Code Assist licence — authenticate with a Google Account:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">&gt;</span><span class="w"> </span>/auth <span class="go">▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ ? Get started │ │ │ │ How would you like to authenticate for this project? │ │ │ │ ● 1. Login with Google │ │ 2. Use Gemini API Key │ │ 3. Vertex AI │ │ │ │ (Use Enter to select) │ │ │ │ Terms of Services and Privacy Notice for Gemini CLI │ │ │ │ https://geminicli.com/docs/resources/tos-privacy/ │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ </span></code></pre> </div> <p>Then set the GOOGLE_CLOUD_PROJECT to a valid project setup on the Google Cloud console:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>~ <span class="nv">$ </span><span class="nb">export </span><span class="nv">GOOGLE_CLOUD_PROJECT</span><span class="o">=</span>comglitn ~ <span class="err">$</span> </code></pre> </div> <p>Other options include Google Cloud API Key that can be generated directly from the Google Cloud Console.</p> <h4> Installing Google Cloud Tools </h4> <p>To simplify working with Google Cloud — install the Google Cloud Tools:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>https://docs.cloud.google.com/sdk/docs/install-sdk </code></pre> </div> <p>Once the installation is completed — you can verify the setup:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">william@Azure:~$</span><span class="w"> </span>gcloud auth list <span class="go"> Credentialed Accounts ACTIVE ACCOUNT * [email protected] </span></code></pre> </div> <h4> Installing Azure Customized GEMINI.md </h4> <p>A sample GitHub repo contains tools for working with Gemini CLI on Azure. This repo is available here:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>git clone https://gitHub.com/xbill9/gemini-cli-azure </code></pre> </div> <p>A sample <strong>GEMINI.md</strong> customized for the Azure environment is provided in the repo:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight markdown"><code>You are a cross platform developer working with Microsoft Azure and Google Cloud You can use the Azure CLI : https://learn.microsoft.com/en-us/cli/azure/install-azure-cli https://learn.microsoft.com/en-us/cli/azure/ https://learn.microsoft.com/en-us/cli/azure/reference https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux?view=azure-cli-latest&amp;pivots=apt <span class="gu">## Azure CLI Tools</span> You can use the Azure CLI to manage resources across Azure Storage, Virtual Machines, and other services. <span class="p"> -</span> <span class="gs">**List Resource Groups**</span> : <span class="sb">`az group list -o table`</span> <span class="p">-</span> <span class="gs">**List Storage Accounts**</span> : <span class="sb">`az storage account list -o table`</span> <span class="p">-</span> <span class="gs">**List Virtual Machines**</span> : <span class="sb">`az vm list -d -o table`</span> <span class="gu">### Azure Update Script</span> <span class="p"> -</span> <span class="sb">`azure-update`</span>: This script is specifically for Azure Linux environments. It updates all packages and ensures necessary libraries are instal led. <span class="gu">## Automation Scripts</span> This repository contains scripts for updating various Linux environments and tools: <span class="p"> -</span> <span class="sb">`linux-update`</span>: Detects OS (Debian/Ubuntu/Azure Linux) and runs the corresponding update scripts. <span class="p">-</span> <span class="sb">`azure-update`</span>: Updates Azure Linux packages and installs necessary dependencies. <span class="p">-</span> <span class="sb">`debian-update`</span>: Updates Debian/Ubuntu packages and installs <span class="sb">`git`</span>. <span class="p">-</span> <span class="sb">`gemini-update`</span>: Updates the <span class="sb">`@google/gemini-cli`</span> via npm and checks versions of Node.js and Gemini. <span class="p">-</span> <span class="sb">`nvm-update`</span>: Installs NVM (Node Version Manager) and Node.js version 25. </code></pre> </div> <h4> Python MCP Documentation </h4> <p>The official GitHub Repo provides samples and documentation for getting started:</p> <p><a href="proxy.php?url=https://github.com/modelcontextprotocol/python-sdk" rel="noopener noreferrer">GitHub - modelcontextprotocol/python-sdk: The official Python SDK for Model Context Protocol servers and clients</a></p> <p>The most common MCP Python deployment path uses the FASTMCP library:</p> <p><a href="proxy.php?url=https://gofastmcp.com/getting-started/welcome" rel="noopener noreferrer">Welcome to FastMCP - FastMCP</a></p> <h4> Where do I start? </h4> <p>The strategy for starting MCP development is a incremental step by step approach.</p> <p>First, the basic development environment is setup with the required system variables, and a working Gemini CLI configuration.</p> <p>Then, a minimal Hello World Style Python MCP Server is built with stdio transport. This server is validated with Gemini CLI in the local environment.</p> <p>This setup validates the connection from Gemini CLI to the local process via MCP. The MCP client (Gemini CLI) and the Python MCP server both run in the same local environment.</p> <p>Next- the basic MCP server is extended with Gemini CLI to add several new tools in standard Python code.</p> <h4> Setup the Basic Environment </h4> <p>At this point you should have a working Python interpreter and a working Gemini CLI installation. The next step is to clone the GitHub samples repository with support scripts:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd</span> ~ git clone https://github.com/xbill9/gemini-cli-azure </code></pre> </div> <p>Then run <strong>init.sh</strong> from the cloned directory.</p> <p>The script will attempt to determine your shell environment and set the correct variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd </span>gemini-cli-azure <span class="nb">source </span>init.sh </code></pre> </div> <p>If your session times out or you need to re-authenticate- you can run the <strong>set_env.sh</strong> script to reset your environment variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd </span>gemini-cli-azure <span class="nb">source </span>set_env.sh </code></pre> </div> <p>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.</p> <h4> Hello World with STDIO Transport </h4> <p>One of the key features that the standard MCP libraries provide is abstracting various transport methods.</p> <p>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.</p> <p>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.</p> <p>The connection over stdio will look similar to this:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="sh">"</span><span class="s"> __main__</span><span class="sh">"</span><span class="p">:</span> <span class="c1"># Explicitly use stdio transport </span> <span class="n">mcp</span><span class="p">.</span><span class="nf">run</span><span class="p">(</span><span class="n">transport</span><span class="o">=</span><span class="sh">"</span><span class="s">stdio</span><span class="sh">"</span><span class="p">)</span> </code></pre> </div> <h4> Running the Python Code </h4> <p>First- switch the directory with the Python MCP sample code:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">azureuser@azure-new:~/gemini-cli-azure/mcp-stdio-python-azure$</span><span class="w"> </span>make release </code></pre> </div> <p>You can validate the final result by checking the messages:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>pyjwt[crypto]&gt;=2.10.1-&gt;mcp-&gt;-r requirements.txt (line 1)) (2.0.0) Requirement already satisfied: pycparser in /home/azureuser/.pyenv/versions/3.13.12/lib/python3.13/site-packages (from cffi&gt;=2.0.0-&gt;cryptography&gt;=3.4.0-&gt;pyjwt[crypto]&gt;=2.10.1-&gt;mcp-&gt;-r requirements.txt (line 1)) (3.0) Requirement already satisfied: click&gt;=7.0 in /home/azureuser/.pyenv/versions/3.13.12/lib/python3.13/site-packages (from uvicorn&gt;=0.31.1-&gt;mcp-&gt;-r requirements.txt (line 1)) (8.3.1) </code></pre> </div> <h4> Gemini CLI settings.json </h4> <p>The default Gemini CLI settings.json has an entry for the Python source:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight json"><code><span class="p">{</span><span class="w"> </span><span class="nl">"mcpServers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"azure-stdio-python"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="s2">"python"</span><span class="p">,</span><span class="w"> </span><span class="nl">"args"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s2">"$HOME/gemini-cli-azure/mcp-stdio-python-azure/main.py"</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre> </div> <h4> Validation with Gemini CLI </h4> <p>Finally- Gemini CLI is restarted and the MCP connection over stdio to the Python Code is validated, The full Gemini CLI Session will start:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">azureuser@azure-new:~/gemini-cli-azure/mcp-stdio-python-azure$</span><span class="w"> </span>gemini <span class="go"> ▝▜▄ Gemini CLI v0.33.1 ▝▜▄ ▗▟▀ Logged in with Google /auth ▝▀ Gemini Code Assist Standard /upgrade </span><span class="gp"> &gt;</span><span class="w"> </span>/mcp list <span class="go">Configured MCP servers: 🟢 azure-stdio-python - Ready (1 tool) Tools: - mcp_azure-stdio-python_greet </span></code></pre> </div> <p>And you can then connect to the MCP Server over stdio:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">&gt;</span><span class="w"> </span>greet Azure VM! <span class="go"> </span><span class="gp">&gt;</span><span class="w"> </span>greet Azure VM! <span class="go">✦ I will greet the Azure VM using the mcp_azure-stdio-python_greet tool. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ Action Required │ │ │ │ ? greet (azure-stdio-python MCP Server) {"param":"Azure VM!"} │ │ │ │ MCP Server: azure-stdio-python │ │ Tool: greet │ │ │ │ MCP Tool Details: │ │ (press Ctrl+O to expand MCP tool details) │ │ Allow execution of MCP tool "greet" from server "azure-stdio-python"? │ │ │ │ 1. Allow once │ │ 2. Allow tool for this session │ │ 3. Allow all server tools for this session │ │ ● 4. Allow tool for all future sessions │ │ 5. No, suggest changes (esc) │ │ │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ I will greet the Azure VM using the mcp_azure-stdio-python_greet tool. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ greet (azure-stdio-python MCP Server) {"param":"Azure VM!"} │ │ │ │ Azure VM! │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ OK. I've greeted "Azure VM!". </span></code></pre> </div> <h4> Summary </h4> <p>The strategy for using Python for MCP development with Gemini CLI was validated with a incremental step by step approach.</p> <p>A minimal stdio transport MCP Server was started from Python source code and validated with Gemini CLI running as a MCP client in the same local environment.</p> <p>Gemini CLI was then used to extend the sample Python code with several MCP tools and use these tools inside the context for the underlying LLM.</p> <p>This approach can be extended to more complex deployments using other MCP transports and Cloud based options.</p> mcpserver gemini microsoftazure python Local MCP Development with Python, Gemini CLI, and Azure Cloud Shell xbill Wed, 18 Mar 2026 12:49:53 +0000 https://dev.to/gde/local-mcp-development-with-python-gemini-cli-and-azure-cloud-shell-n2d https://dev.to/gde/local-mcp-development-with-python-gemini-cli-and-azure-cloud-shell-n2d <p>Leveraging Gemini CLI and the underlying Gemini LLM to build Model Context Protocol (MCP) AI applications with Python with a local development environment hosted on Azure Cloud Shell.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjycsd6ktdqeh7ruho2mk.jpeg" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjycsd6ktdqeh7ruho2mk.jpeg"></a></p> <h4> What is Gemini CLI? </h4> <p>The Gemini CLI is an open-source, terminal-based AI agent from Google that allows developers to interact directly with Gemini models, such as Gemini 2.5 Pro, for coding, content creation, and workflow automation. It supports file operations, shell commands, and connects to external tools via the Model Context Protocol (MCP).</p> <p>The full details on Gemini CLI are available here:</p> <p><a href="proxy.php?url=https://geminicli.com/" rel="noopener noreferrer">Build, debug &amp; deploy with AI</a></p> <h4> Azure Cloud Shell </h4> <p>Azure Cloud Shell is a browser-based, authenticated terminal for managing Azure resources, accessible directly through the Azure portal, shell.azure.com, or the mobile app. It provides a preconfigured environment with Bash or PowerShell, eliminating local installation of tools. It runs on a temporary, secure, Linux-based host.</p> <p>The full background information on the Cloud Shell is here:</p> <p><a href="proxy.php?url=https://azure.microsoft.com/en-us/get-started/azure-portal/cloud-shell" rel="noopener noreferrer">https://azure.microsoft.com/en-us/get-started/azure-portal/cloud-shell</a></p> <p>More information is available here:</p> <p><a href="proxy.php?url=https://learn.microsoft.com/en-us/azure/cloud-shell/get-started/classic?wt.mc_id=fulltextsearch_inproduct_azure-portal-global-search&amp;tabs=azurecli" rel="noopener noreferrer">Get started with Azure Cloud Shell</a></p> <h4> Why would I want Gemini CLI on Azure? Isn’t that a Google Thing? </h4> <p>Yes- Gemini CLI leverages the Google Cloud console and Gemini models but it is also open source and platform agnostic. Many applications are already cross-cloud so this enables familiar tools to be run natively on Microsoft Azure.</p> <h4> Activating Azure CloudShell </h4> <p>The Azure CloudShell comes preinstalled on all Azure Accounts.</p> <p>To access the shell — click the Terminal Icon in the upper right hand corner of the console:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsubssxraetql1lmam9n.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsubssxraetql1lmam9n.png"></a></p> <p>Then activate the full shell:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnj6zipv4ru2xdrzjerrc.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnj6zipv4ru2xdrzjerrc.png"></a></p> <p>Note- the disk space in the environment is limited to 5GB- but this is sufficient for Gemini CLI, Google Cloud Tools, and some customization.</p> <h4> Node Version Management </h4> <p>Gemini CLI needs a consistent, up to date version of Node. The <strong>nvm</strong> command can be used to get a standard Node environment:</p> <p><a href="proxy.php?url=https://github.com/nvm-sh/nvm" rel="noopener noreferrer">GitHub - nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions</a></p> <h4> Verifying Node.js in Azure Cloud Shell </h4> <p>The version of Node.js is verified that it is recent enough to support Gemini CLI:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">william@Azure:~$</span><span class="w"> </span>node <span class="nt">--version</span> <span class="go">v25.8.1 </span><span class="gp">william@Azure:~$</span><span class="w"> </span>npm <span class="nt">--version</span> <span class="go">11.11.0 </span><span class="gp">william@Azure:~$</span><span class="w"> </span></code></pre> </div> <h4> Gemini CLI Installation </h4> <p>You can then download the Gemini CLI :<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>npm <span class="nb">install</span> <span class="nt">-g</span> @google/gemini-cli </code></pre> </div> <p>You will see the log messages:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">william@Azure:~$</span><span class="w"> </span>npm <span class="nb">install</span> <span class="nt">-g</span> @google/gemini-cli <span class="gp">npm warn deprecated [email protected]: No longer maintained. Please contact the author of the relevant native addon;</span><span class="w"> </span>alternatives are available. <span class="go">npm warn deprecated [email protected]: Use your platform's native DOMException instead npm warn deprecated [email protected]: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting [email protected] added 618 packages in 48s 173 packages are looking for funding run `npm fund` for details </span><span class="gp">william@Azure:~$</span><span class="w"> </span></code></pre> </div> <h4> Testing the Gemini CLI Environment </h4> <p>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:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>gemini </code></pre> </div> <h4> Authentication </h4> <p>Several authentication options are available. To use an existing Code Assist licence — authenticate with a Google Account:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>&gt; /auth ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ │ │ ? Get started │ │ │ │ How would you like to authenticate for this project? │ │ │ │ ● 1. Login with Google │ │ 2. Use Gemini API Key │ │ 3. Vertex AI │ │ │ │ (Use Enter to select) │ │ │ │ Terms of Services and Privacy Notice for Gemini CLI │ │ │ │ https://geminicli.com/docs/resources/tos-privacy/ │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ </code></pre> </div> <p>Then set the GOOGLE_CLOUD_PROJECT to a valid project setup on the Google Cloud console:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>~ <span class="nv">$ </span><span class="nb">export </span><span class="nv">GOOGLE_CLOUD_PROJECT</span><span class="o">=</span>comglitn ~ <span class="err">$</span> </code></pre> </div> <p>Other options include Google Cloud API Key that can be generated directly from the Google Cloud Console.</p> <h4> Using Gemini CLI on Azure Cloud Shell </h4> <p>Once installed- Gemini CLI has direct access to the Cloud Shell environment:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>Logged in with Google: [email protected] /auth Plan: Gemini Code Assist Standard ✦ Your Azure project information is as follows: - Subscription Name: Azure subscription 1 - Subscription ID: 3db3ce66-50b6-4d11-91ef-5950cf4039ed - Tenant ID: 40482c55-d00d-4c6d-8903-643d76a74b9c - Environment: AzureCloud - User: live.com#[email protected] Active Resource Groups: - cloud-shell-storage-eastus (eastus) - NetworkWatcherRG (eastus) - vm (eastus) Project Metadata: - Repository: github.com/xbill9/gemini-cli-azure (https://github.com/xbill9/gemini-cli-azure) - Google Cloud Project ID: comglitn (from project_id.txt) </code></pre> </div> <p>and Azure operations can be performed directly from Gemini CLI:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>&gt; list azure vms using the az command ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ✦ I'll list your Azure Virtual Machines using the az command. ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ Shell az vm list -d -o table [current working directory /home/william] (List all Azure Virtual Machines in the current subscription with detailed in… │ │ │ │ Name ResourceGroup PowerState PublicIps Fqdns Location │ │ --------- --------------- -------------- ------------- ------- ---------- │ │ azure-new VM VM deallocated 20.124.121.35 eastus │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ You have one Azure Virtual Machine: - Name: azure-new - Resource Group: VM - Power State: VM deallocated - Public IP: 20.124.121.35 - Location: eastus </code></pre> </div> <h4> Installing Google Cloud Tools </h4> <p>To simplify working with Google Cloud — install the Google Cloud Tools:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>https://docs.cloud.google.com/sdk/docs/install-sdk </code></pre> </div> <p>Once the installation is completed — you can verify the setup:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">william@Azure:~$</span><span class="w"> </span>gcloud auth list <span class="go"> Credentialed Accounts ACTIVE ACCOUNT * [email protected] To set the active account, run: </span><span class="gp"> $</span><span class="w"> </span>gcloud config <span class="nb">set </span>account <span class="sb">`</span>ACCOUNT<span class="sb">`</span> <span class="go"> </span><span class="gp">william@Azure:~$</span><span class="w"> </span>gcloud config list <span class="go">[compute] region = us-west2 zone = us-west2-a [core] account = [email protected] disable_usage_reporting = False project = comglitn Your active configuration is: [default] [environment: Development] </span><span class="gp">william@Azure:~$</span><span class="w"> </span></code></pre> </div> <h4> Installing Azure Customized GEMINI.md </h4> <p>A sample GitHub repo contains tools for working with Gemini CLI on Azure. This repo is available here:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>git clone https://gitHub.com/xbill9/gemini-cli-azure </code></pre> </div> <p>A sample <strong>GEMINI.md</strong> customized for the Azure environment is provided in the repo:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight markdown"><code>This is a multi linux git repo hosted at: github.com/xbill9/gemini-cli-azure You are a cross platform developer working with Microsoft Azure and Google Cloud You can use the Azure CLI : https://learn.microsoft.com/en-us/cli/azure/install-azure-cli https://learn.microsoft.com/en-us/cli/azure/ https://learn.microsoft.com/en-us/cli/azure/reference https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux?view=azure-cli-latest&amp;pivots=apt <span class="gu">## Azure CLI Tools</span> You can use the Azure CLI to manage resources across Azure Storage, Virtual Machines, and other services. <span class="p"> -</span> <span class="gs">**List Resource Groups**</span> : <span class="sb">`az group list -o table`</span> <span class="p">-</span> <span class="gs">**List Storage Accounts**</span> : <span class="sb">`az storage account list -o table`</span> <span class="p">-</span> <span class="gs">**List Virtual Machines**</span> : <span class="sb">`az vm list -d -o table`</span> <span class="gu">### Azure Update Script</span> <span class="p"> -</span> <span class="sb">`azure-update`</span>: This script is specifically for Azure Linux environments. It updates all packages and ensures necessary libraries are installed. <span class="gu">## Automation Scripts</span> This repository contains scripts for updating various Linux environments and tools: <span class="p"> -</span> <span class="sb">`linux-update`</span>: Detects OS (Debian/Ubuntu/Azure Linux) and runs the corresponding update scripts. <span class="p">-</span> <span class="sb">`azure-update`</span>: Updates Azure Linux packages and installs necessary dependencies. <span class="p">-</span> <span class="sb">`debian-update`</span>: Updates Debian/Ubuntu packages and installs <span class="sb">`git`</span>. <span class="p">-</span> <span class="sb">`gemini-update`</span>: Updates the <span class="sb">`@google/gemini-cli`</span> via npm and checks versions of Node.js and Gemini. <span class="p">-</span> <span class="sb">`nvm-update`</span>: Installs NVM (Node Version Manager) and Node.js version 25. </code></pre> </div> <h4> Python MCP Documentation </h4> <p>The official GitHub Repo provides samples and documentation for getting started:</p> <p><a href="proxy.php?url=https://github.com/modelcontextprotocol/python-sdk" rel="noopener noreferrer">GitHub - modelcontextprotocol/python-sdk: The official Python SDK for Model Context Protocol servers and clients</a></p> <p>The most common MCP Python deployment path uses the FASTMCP library:</p> <p><a href="proxy.php?url=https://gofastmcp.com/getting-started/welcome" rel="noopener noreferrer">Welcome to FastMCP - FastMCP</a></p> <h4> Where do I start? </h4> <p>The strategy for starting MCP development is a incremental step by step approach.</p> <p>First, the basic development environment is setup with the required system variables, and a working Gemini CLI configuration.</p> <p>Then, a minimal Hello World Style Python MCP Server is built with stdio transport. This server is validated with Gemini CLI in the local environment.</p> <p>This setup validates the connection from Gemini CLI to the local process via MCP. The MCP client (Gemini CLI) and the Python MCP server both run in the same local environment.</p> <p>Next- the basic MCP server is extended with Gemini CLI to add several new tools in standard Python code.</p> <h4> Setup the Basic Environment </h4> <p>At this point you should have a working Python interpreter and a working Gemini CLI installation. The next step is to clone the GitHub samples repository with support scripts:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd</span> ~ git clone https://github.com/xbill9/gemini-cli-azure </code></pre> </div> <p>Then run <strong>init.sh</strong> from the cloned directory.</p> <p>The script will attempt to determine your shell environment and set the correct variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd </span>gemini-cli-azure <span class="nb">source </span>init.sh </code></pre> </div> <p>If your session times out or you need to re-authenticate- you can run the <strong>set_env.sh</strong> script to reset your environment variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd </span>gemini-cli-azure <span class="nb">source </span>set_env.sh </code></pre> </div> <p>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.</p> <h4> Hello World with STDIO Transport </h4> <p>One of the key features that the standard MCP libraries provide is abstracting various transport methods.</p> <p>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.</p> <p>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.</p> <p>The connection over stdio will look similar to this:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="sh">"</span><span class="s"> __main__</span><span class="sh">"</span><span class="p">:</span> <span class="c1"># Explicitly use stdio transport </span> <span class="n">mcp</span><span class="p">.</span><span class="nf">run</span><span class="p">(</span><span class="n">transport</span><span class="o">=</span><span class="sh">"</span><span class="s">stdio</span><span class="sh">"</span><span class="p">)</span> </code></pre> </div> <h4> Running the Python Code </h4> <p>First- switch the directory with the Python MCP sample code:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd</span> ~/gemini-cli-azure/mcp-stdio-python-azurecli </code></pre> </div> <p>Run the release version on the local system:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">william@Azure:~/gemini-cli-azure/mcp-stdio-python-azurecli$</span><span class="w"> </span>make release </code></pre> </div> <p>You can validate the final result by checking the messages:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>Successfully installed annotated-types-0.7.0 anyio-4.12.1 attrs-25.4.0 certifi-2026.2.25 cffi-2.0.0 click-8.3.1 cryptography-46.0.5 h11-0.16.0 httpcore-1.0.9 httpx-0.28.1 httpx-sse-0.4.3 idna-3.11 jsonschema-4.26.0 jsonschema-specifications-2025.9.1 mcp-1.26.0 pycparser-3.0 pydantic-2.12.5 pydantic-core-2.41.5 pydantic-settings-2.13.1 pyjwt-2.12.1 python-dotenv-1.2.2 python-json-logger-4.0.0 python-multipart-0.0.22 referencing-0.37.0 rpds-py-0.30.0 sse-starlette-3.3.2 starlette-0.52.1 typing-extensions-4.15.0 typing-inspection-0.4.2 uvicorn-0.41.0 </code></pre> </div> <h4> Gemini CLI settings.json </h4> <p>The default Gemini CLI settings.json has an entry for the Python source:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight json"><code><span class="p">{</span><span class="w"> </span><span class="nl">"mcpServers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"azurecli-stdio-python"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="s2">"python"</span><span class="p">,</span><span class="w"> </span><span class="nl">"args"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s2">"$HOME/gemini-cli-azure/mcp-stdio-python-azurecli/main.py"</span><span class="w"> </span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre> </div> <h4> Validation with Gemini CLI </h4> <p>Finally- Gemini CLI is restarted and the MCP connection over stdio to the Python Code is validated, The full Gemini CLI Session will start:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>william@Azure:~/gemini-cli-azure/mcp-stdio-python-azurecli$ gemini ▝▜▄ Gemini CLI v0.33.1 ▝▜▄ ▗▟▀ Logged in with Google /auth ▝▀ Gemini Code Assist Standard /upgrade ? for shortcuts ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── shift+tab to accept edits 2 GEMINI.md files | 1 MCP server ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ &gt; /mcp list ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ Configured MCP servers: 🟢 azurecli-stdio-python - Ready (1 tool) Tools: - mcp_azurecli-stdio-python_greet </code></pre> </div> <p>And you can then connect to the MCP Server over stdio:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>&gt; greet Azure CLI ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ✦ I will call the greet tool with "Azure CLI" as the parameter. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ Action Required │ │ │ │ ? greet (azurecli-stdio-python MCP Server) {"param":"Azure CLI"} │ │ │ │ ... first 3 lines hidden (Ctrl+O to show) ... │ │ MCP Tool Details: │ │ (press Ctrl+O to expand MCP tool details) │ │ Allow execution of MCP tool "greet" from server "azurecli-stdio-python"? │ │ │ │ 1. Allow once │ │ 2. Allow tool for this session │ │ 3. Allow all server tools for this session │ │ ● 4. Allow tool for all future sessions │ │ 5. No, suggest changes (esc) │ │ │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ I will call the greet tool with "Azure CLI" as the parameter. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ greet (azurecli-stdio-python MCP Server) {"param":"Azure CLI"} │ │ │ │ Azure CLI │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ </code></pre> </div> <h4> Extending the Python MCP Server with Gemini CLI </h4> <p>Now that the basic MCP functionality has been tested and verified with Gemini CLI- the Python server code can be extended with new MCP tools:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code> &gt; with @main.py add 2 new MCP tools - one that returns the current system time and the other returns information on the current system info like OS, memory, azure versions, etc include full azure environment information ✦ I have successfully added the get_system_time and get_system_info tools to main.py and installed the psutil dependency. The new tools are: 1. get_system_time: Returns the current system time in ISO format. 2. get_system_info: Returns a JSON string containing the OS platform, memory usage (total, available, and percentage), and the Azure CLI version. </code></pre> </div> <p>Restart Gemini CLI and check for the new MCP tools:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>william@Azure:~/gemini-cli-azure/mcp-stdio-python-azurecli$ gemini ▝▜▄ Gemini CLI v0.33.1 ▝▜▄ ▗▟▀ Logged in with Google /auth ▝▀ Gemini Code Assist Standard /upgrade ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ &gt; /mcp list ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ Configured MCP servers: 🟢 azurecli-stdio-python - Ready (3 tools) Tools: - mcp_azurecli-stdio-python_get_system_info - mcp_azurecli-stdio-python_get_system_time - mcp_azurecli-stdio-python_greet ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ &gt; get_system_time ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ✦ I will call the get_system_time tool to retrieve the current system time. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ get_system_time (azurecli-stdio-python MCP Server) {} │ │ │ │ 2026-03-16T16:08:43.772771 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ The current system time is 2026-03-16T16:08:43.772771. ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ &gt; get_system_info ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ ✦ I will call the get_system_info tool to retrieve the current system information. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ get_system_info (azurecli-stdio-python MCP Server) {} │ │ │ │ { │ │ "os": "Linux-6.1.124.1-microsoft-standard-x86_64-with-glibc2.38", │ │ "memory": { │ │ "total": "3.52 GB", │ │ "available": "2.44 GB", │ │ "percent": "30.5%" │ │ }, │ │ "azure_cli": "azure-cli 2.82.0 *\n\ncore 2.82.0 *\ntelemetry 1.1.0\n\nExtensions:\nml │ │ 2.41.0\nssh 2.0.6\n\nDependencies:\nmsal 1.34.0b1\nazure-mgmt-resource 23.3.0\n\nPython location │ │ '/usr/bin/python3.12'\nConfig directory '/home/william/.azure'\nExtensions directory '/home/william/.azure/cliextensions'\nExtensions system directory │ │ '/usr/lib/python3.12/site-packages/azure-cli-extensions'\n\nPython (Linux) 3.12.9 (main, Feb 4 2026, 03:35:55) [GCC 13.2.0]\n\nLegal docs and information: │ │ aka.ms/AzureCliLegal\n\n\n" │ │ } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ The system information is as follows: * OS: Linux-6.1.124.1-microsoft-standard-x86_64 (glibc 2.38) * Memory: 3.52 GB Total, 2.44 GB Available (30.5% used) * Azure CLI: 2.82.0 * Core: 2.82.0 * Telemetry: 1.1.0 * Extensions: ml (2.41.0), ssh (2.0.6) * Python: 3.12.9 (located at /usr/bin/python3.12) </code></pre> </div> <p>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:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>&gt; can i play Cyberpunk 2077 on this machine ✦ I will search for the latest minimum system requirements for Cyberpunk 2077 to compare them with your system's specifications. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ GoogleSearch Searching the web for: "Cyberpunk 2077 minimum system requirements 2026" │ │ │ │ Search results for "Cyberpunk 2077 minimum system requirements 2026" returned. │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ Based on the system information gathered and the latest requirements for Cyberpunk 2077 (Update 2.0+), your current machine cannot run the game. Here is why: * Memory: You have 3.52 GB of available RAM, while the game requires a minimum of 12 GB. * OS/Environment: You are running Linux (WSL). While the game can run on Linux via compatibility layers, the virtualization overhead and severe lack of RAM make it impossible to launch. * Requirements: Cyberpunk 2077 now requires an SSD and a much more powerful GPU (GTX 1060 6GB minimum) than what is typically accessible in a 3.5GB virtualized environment. To play the game, you would need a hardware upgrade to at least 12GB of RAM (16GB recommended) and a dedicated graphics card. ? for shortcuts </code></pre> </div> <p>But you can still play Doom!<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>&gt; can I play Classic Doom on this machine? ✦ Yes, you can absolutely play Classic Doom (1993) on this machine. Your system far exceeds its original requirements (a 486 processor and 4MB of RAM). Since you are in a headless Linux environment (Azure Linux 3.0), you have two main options: 1. Terminal-based Play: You can use a source port like doom-ascii or A-Doom to play directly in your terminal using ASCII characters for graphics. 2. Remote/GUI Play: If you set up X11 forwarding or use a VNC/RDP connection, you can run modern source ports like GZDoom or Chocolate Doom to enjoy the original graphics and sound. With 3.52 GB of RAM, your system could theoretically run over 800 instances of Classic Doom simultaneously! </code></pre> </div> <h4> Summary </h4> <p>The strategy for using Python for MCP development with Gemini CLI was validated with a incremental step by step approach.</p> <p>A minimal stdio transport MCP Server was started from Python source code and validated with Gemini CLI running as a MCP client in the same local environment.</p> <p>Gemini CLI was then used to extend the sample Python code with several MCP tools and use these tools inside the context for the underlying LLM.</p> <p>This approach can be extended to more complex deployments using other MCP transports and Cloud based options.</p> python cloudshell gemini mcpserver Running Azure CLI Tools on ChromeOS / ChromeOS Flex xbill Tue, 17 Mar 2026 19:49:08 +0000 https://dev.to/gde/running-azure-cli-tools-on-chromeos-chromeos-flex-1jbl https://dev.to/gde/running-azure-cli-tools-on-chromeos-chromeos-flex-1jbl <h4> Using ChromeOS / ChromeOS Flex with Azure CLI Tools </h4> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frt2mssjc7wxik22jlha6.jpeg" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frt2mssjc7wxik22jlha6.jpeg" width="800" height="436"></a></p> <h4> What is the Azure CLI? </h4> <p>The <strong>Azure Command-Line Interface (CLI)</strong> is a cross-platform command-line tool used to create, manage, and configure Azure resources efficiently through interactive commands or scripts. It provides granular control over resources and is a key tool for developers, IT administrators, and DevOps engineers.</p> <p>Full details are available here:</p> <p><a href="proxy.php?url=https://learn.microsoft.com/en-us/cli/azure/?view=azure-cli-latest" rel="noopener noreferrer">Azure Command-Line Interface (CLI) documentation</a></p> <h4> Why would I want to use Azure CLI Tools from the Linux VM on ChromeOS Flex? </h4> <p>ChromeOS and ChromeOS Flex provide a standard Debian 12 Linux VM as part of their developer options that has the foundational tools for but can be customized to provide a complete developer environment.</p> <p>This tutorial uses the Azure CLI installation and extends the Linux VM in ChromeOS Flex to allow local development.</p> <h4> Initial Environment Setup </h4> <p>Activate the Linux VM in ChromeOS Flex:</p> <p><a href="proxy.php?url=https://support.google.com/chromebook/answer/9145439?hl=en" rel="noopener noreferrer">https://support.google.com/chromebook/answer/9145439?hl=en</a></p> <p>Make sure to extend the initial disk space to 64GB or higher when setting up the VM:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh76wpgpn3afgghgmlgtd.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh76wpgpn3afgghgmlgtd.png" width="800" height="450"></a></p> <h4> Verifying Linux VM Setup </h4> <p>Start the Linux VM and open the shell:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcryzzy7ztwedprfpy1cb.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcryzzy7ztwedprfpy1cb.png" width="800" height="450"></a></p> <h4> Get all Local Linux VM Updates: </h4> <p>This step makes sure that the Linux VM has all Local updates.<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">sudo </span>apt-get update <span class="nb">sudo </span>apt-get upgrade </code></pre> </div> <p>Add basic development tools to the Linux VM:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">sudo </span>apt-get <span class="nb">install </span>git <span class="nb">sudo </span>apt-get <span class="nb">install </span>curl <span class="nb">sudo </span>apt <span class="nb">install </span>build-essential </code></pre> </div> <p>For a fresh installation — this make take 3–4 minutes to pull all required package dependencies.</p> <h4> Python Version Management </h4> <p>One of the downsides of the wide deployment of Python has been managing the language versions across platforms and maintaining a supported version.</p> <p>The <strong>pyenv</strong> tool enables deploying consistent versions of Python:</p> <p><a href="proxy.php?url=https://github.com/pyenv/pyenv" rel="noopener noreferrer">GitHub - pyenv/pyenv: Simple Python version management</a></p> <p>As of writing — the mainstream python version is 3.13. To validate your current Python:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~$</span><span class="w"> </span>python <span class="nt">--version</span> <span class="go">Python 3.13.11 </span></code></pre> </div> <h4> Installing Azure CLI </h4> <p>The latest Azure CLI is available here:</p> <p><a href="proxy.php?url=https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux?view=azure-cli-latest&amp;pivots=apt" rel="noopener noreferrer">Install the Azure CLI on Linux</a></p> <p>To do a quick install-<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>curl <span class="nt">-sL</span> https://aka.ms/InstallAzureCLIDeb | <span class="nb">sudo </span>bash </code></pre> </div> <p>This will extract the package:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>Reading package lists... Done Reading package lists... Done Building dependency tree... Done Reading state information... Done azure-cli is already the newest version (2.84.0-1~bookworm). 0 upgraded, 0 newly installed, 0 to remove and 5 not upgraded. </code></pre> </div> <p>You can then validate the version:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~$</span><span class="w"> </span>az <span class="nt">--version</span> <span class="go">azure-cli 2.84.0 core 2.84.0 telemetry 1.1.0 Dependencies: msal 1.35.0b1 azure-mgmt-resource 24.0.0 Python location '/opt/az/bin/python3' Config directory '/home/xbill/.azure' Extensions directory '/home/xbill/.azure/cliextensions' Python (Linux) 3.13.11 (main, Feb 25 2026, 02:29:30) [GCC 12.2.0] Legal docs and information: aka.ms/AzureCliLegal Your CLI is up-to-date. </span><span class="gp">xbill@penguin:~$</span><span class="w"> </span></code></pre> </div> <h4> Setting Up the Azure CLI </h4> <p>Full step by step instructions are available here:</p> <p><a href="proxy.php?url=https://learn.microsoft.com/en-us/cli/azure/get-started-with-azure-cli?view=azure-cli-latest" rel="noopener noreferrer">Get started with Azure Command-Line Interface (CLI)</a><br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>https://learn.microsoft.com/en-us/cli/azure/get-started-with-azure-cli?view=azure-cli-latest </code></pre> </div> <p>For short-term sessions- login to the Azure Console:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~$</span><span class="w"> </span>az login <span class="go">A web browser has been opened at https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize. Please continue the login in the web browser. If no web browser is available or if the web browser fails to open, use device code flow with `az login --use-device-code`. Retrieving tenants and subscriptions for the selection... [Tenant and subscription selection] No Subscription name Subscription ID Tenant ----- -------------------- ------------------------------------ ----------------- [1] * Azure subscription 1 3db3ce66-50b6-4d11-91ef-5950cf4039ed Default Directory </span><span class="gp">The default is marked with an *;</span><span class="w"> </span>the default tenant is <span class="s1">'Default Directory'</span> and subscription is <span class="s1">'Azure subscription 1'</span> <span class="o">(</span>3db3ce66-50b6-4d11-91ef-5950cf4039ed<span class="o">)</span><span class="nb">.</span> <span class="go"> Select a subscription and tenant (Type a number or Enter for no changes): Tenant: Default Directory Subscription: Azure subscription 1 (3db3ce66-50b6-4d11-91ef-5950cf4039ed) [Announcements] With the new Azure CLI login experience, you can select the subscription you want to use more easily. Learn more about it and its configuration at https://go.microsoft.com/fwlink/?linkid=2271236 If you encounter any problem, please open an issue at https://aka.ms/azclibug [Warning] The login output has been updated. Please be aware that it no longer displays the full list of available subscriptions by default. </span></code></pre> </div> <h4> Testing the CLI Tools </h4> <p>Once the az tools have been installed and configured- they can be used directly from the command line in the ChromeOS Shell:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight json"><code><span class="err">xbill@penguin:~$</span><span class="w"> </span><span class="err">az</span><span class="w"> </span><span class="err">storage</span><span class="w"> </span><span class="err">container</span><span class="w"> </span><span class="err">list</span><span class="w"> </span><span class="err">--account-name</span><span class="w"> </span><span class="err">cs</span><span class="mi">210032000655</span><span class="err">adffb</span><span class="w"> </span><span class="err">--auth-mode</span><span class="w"> </span><span class="err">login</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"deleted"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="nl">"encryptionScope"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"defaultEncryptionScope"</span><span class="p">:</span><span class="w"> </span><span class="s2">"$account-encryption-key"</span><span class="p">,</span><span class="w"> </span><span class="nl">"preventEncryptionScopeOverride"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nl">"immutableStorageWithVersioningEnabled"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="nl">"metadata"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"my-azure-bucket"</span><span class="p">,</span><span class="w"> </span><span class="nl">"properties"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"etag"</span><span class="p">:</span><span class="w"> </span><span class="s2">"</span><span class="se">\"</span><span class="s2">0x8DE836B85528A08</span><span class="se">\"</span><span class="s2">"</span><span class="p">,</span><span class="w"> </span><span class="nl">"hasImmutabilityPolicy"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="nl">"hasLegalHold"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="nl">"lastModified"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2026-03-16T14:51:35+00:00"</span><span class="p">,</span><span class="w"> </span><span class="nl">"lease"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"duration"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="p">,</span><span class="w"> </span><span class="nl">"state"</span><span class="p">:</span><span class="w"> </span><span class="s2">"available"</span><span class="p">,</span><span class="w"> </span><span class="nl">"status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"unlocked"</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nl">"publicAccess"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="kc">null</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">]</span><span class="w"> </span></code></pre> </div> <h4> Taking it to the Next Level — Gemini CLI </h4> <p>Install Gemini CLI in ChromeOS:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>npm <span class="nb">install</span> <span class="nt">-g</span> @google/gemini-cli </code></pre> </div> <p>A pre-built Git repo with tools for working with Gemini CLI and Azure is available here:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>git clone https://gitHub.com/xbill9/gemini-cli-azure </code></pre> </div> <p>Then Gemini CLI has full visibility and support for the Azure tools along with the <strong>GEMINI.md</strong> configuration file:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight markdown"><code>This is a multi linux git repo hosted at: github.com/xbill9/gemini-cli-azure You are a cross platform developer working with Microsoft Azure and Google Cloud You can use the Azure CLI : https://learn.microsoft.com/en-us/cli/azure/install-azure-cli https://learn.microsoft.com/en-us/cli/azure/ https://learn.microsoft.com/en-us/cli/azure/reference https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-linux?view=azure-cli-latest&amp;pivots=apt <span class="gu">## Azure CLI Tools</span> You can use the Azure CLI to manage resources across Azure Storage, Virtual Machines, and other services. <span class="p"> -</span> <span class="gs">**List Resource Groups**</span> : <span class="sb">`az group list -o table`</span> <span class="p">-</span> <span class="gs">**List Storage Accounts**</span> : <span class="sb">`az storage account list -o table`</span> <span class="p">-</span> <span class="gs">**List Virtual Machines**</span> : <span class="sb">`az vm list -d -o table`</span> <span class="gu">### Azure Update Script</span> <span class="p"> -</span> <span class="sb">`azure-update`</span>: This script is specifically for Azure Linux environments. It updates all packages and ensures necessary libraries are installed. <span class="gu">## Automation Scripts</span> This repository contains scripts for updating various Linux environments and tools: <span class="p"> -</span> <span class="sb">`linux-update`</span>: Detects OS (Debian/Ubuntu/Azure Linux) and runs the corresponding update scripts. <span class="p">-</span> <span class="sb">`azure-update`</span>: Updates Azure Linux packages and installs necessary dependencies. <span class="p">-</span> <span class="sb">`debian-update`</span>: Updates Debian/Ubuntu packages and installs <span class="sb">`git`</span>. <span class="p">-</span> <span class="sb">`gemini-update`</span>: Updates the <span class="sb">`@google/gemini-cli`</span> via npm and checks versions of Node.js and Gemini. <span class="p">-</span> <span class="sb">`nvm-update`</span>: Installs NVM (Node Version Manager) and Node.js version 25. </code></pre> </div> <h4> Running the az CLI from Gemini CLI </h4> <p>Finally — the full suite of az CLI tools is available from Gemini CLI:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>cd gemini-cli-azure gemini &gt; describe my azure buckets ✦ You have one primary Azure storage account that serves as the repository for your "buckets" (containers and shares). Storage Account: cs210032000655adffb * Purpose: Primarily used for Azure Cloud Shell storage (as indicated by tags). * Resource Group: cloud-shell-storage-eastus * Location: eastus (East US) * SKU: Standard_LRS (Locally Redundant Storage) * Kind: StorageV2 (General Purpose v2) --- 1. Blob Containers ("Buckets") Your account has one blob container: * Name: my-azure-bucket * Status: Private (Public access is disabled) * Contents: This container is currently empty. 2. File Shares There is one file share associated with your Cloud Shell environment: * Name: cs-xbill-glitnir-com-10032000655adffb * Contents: Contains a .cloudconsole/ directory, which holds configuration and persistence files for your Azure CLI/Cloud Shell sessions. --- Summary: Your environment is very lean, with a single storage account mostly dedicated to Cloud Shell persistence, plus one user-created empty bucket named my-azure-bucket. ? for shortcut </code></pre> </div> <h4> Summary </h4> <p>The Linux development environment was enabled on a standard ChromeOS environment. Then — the Azure CLI tools were downloaded and installed. The final step was to configure and test the az CLI tools directly from the Linux VM.</p> gemini googlecloud linux azure Running the ADK Visual Builder on an Azure VM xbill Tue, 17 Mar 2026 02:42:09 +0000 https://dev.to/gde/running-the-adk-visual-builder-on-an-azure-vm-1icp https://dev.to/gde/running-the-adk-visual-builder-on-an-azure-vm-1icp <p>Leveraging the Google Agent Development Kit (ADK) and the underlying Gemini LLM to build low code in the Python programming language deployed securely on the Azure Cloud platform.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F722gp42o7m9epkc213p4.jpeg" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F722gp42o7m9epkc213p4.jpeg" width="800" height="436"></a></p> <h4> Azure VM Instance Configuration </h4> <p>To configure your Azure VM Instance with the base system tools- this article provides a reference:</p> <p><a href="proxy.php?url=https://xbill999.medium.com/cross-platform-adk-agents-with-an-azure-linux-vm-f99658eb9787" rel="noopener noreferrer">Cross Platform ADK Agents with an Azure Linux VM</a></p> <p>The key step is to verify that port 8000 is open for Internet traffic to allow access to the ADK:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="go">✦ I'll list all inbound rules for the NSG again to ensure there are no conflicting rules blocking traffic to port 8000. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ Shell az network nsg rule list -g VM --nsg-name azure-newNSG -o table [current working directory /home/azureuser/gemini-cli-azure]… │ │ │ │ Name ResourceGroup Priority SourcePortRanges SourceAddressPrefixes SourceASG Access Protocol │ │ Direction DestinationPortRanges DestinationAddressPrefixes DestinationASG │ │ ----------------- --------------- ---------- ------------------ ----------------------- ----------- -------- ---------- │ │ ----------- ----------------------- ---------------------------- ---------------- │ │ default-allow-ssh VM 1000 * * None Allow Tcp │ │ Inbound 22 * None │ │ allow-port-8000 VM 1010 * * None Allow Tcp │ │ Inbound 8000 * None │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ </span></code></pre> </div> <h4> Python Version Management </h4> <p>One of the downsides of the wide deployment of Python has been managing the language versions across platforms and maintaining a supported version.</p> <p>The <strong>pyenv</strong> tool enables deploying consistent versions of Python:</p> <p><a href="proxy.php?url=https://github.com/pyenv/pyenv" rel="noopener noreferrer">GitHub - pyenv/pyenv: Simple Python version management</a></p> <p>As of writing — the mainstream python version is 3.13. To validate your current Python:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">azureuser@azure-new:~/gemini-cli-azure$</span><span class="w"> </span>python <span class="nt">--version</span> <span class="go">Python 3.13.12 </span></code></pre> </div> <h4> Gemini CLI </h4> <p>If not pre-installed you can download the Gemini CLI to interact with the source files and provide real-time assistance:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="go">npm install -g @google/gemini-cli </span></code></pre> </div> <h4> Testing the Gemini CLI Environment </h4> <p>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:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">azureuser@azure-new:~/gemini-cli-azure$</span><span class="w"> </span>gemini <span class="go"> ▝▜▄ Gemini CLI v0.33.1 ▝▜▄ ▗▟▀ Logged in with Google /auth ▝▀ Gemini Code Assist Standard /upgrade </span></code></pre> </div> <h4> Node Version Management </h4> <p>Gemini CLI needs a consistent, up to date version of Node. The <strong>nvm</strong> command can be used to get a standard Node environment:</p> <p><a href="proxy.php?url=https://github.com/nvm-sh/nvm" rel="noopener noreferrer">GitHub - nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions</a></p> <p>To verify the Node version:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">azureuser@azure-new:~/gemini-cli-azure$</span><span class="w"> </span>nvm <span class="nt">--version</span> <span class="go">0.40.3 </span><span class="gp">azureuser@azure-new:~/gemini-cli-azure$</span><span class="w"> </span>node <span class="nt">--version</span> <span class="go">v25.8.1 </span><span class="gp">azureuser@azure-new:~/gemini-cli-azure$</span><span class="w"> </span>npm <span class="nt">--version</span> <span class="go">11.11.0 </span></code></pre> </div> <h4> Agent Development Kit </h4> <p>The <a href="proxy.php?url=https://www.google.com/search?q=Google+Agent+Development+Kit&amp;rlz=1CAIWTJ_enUS1114&amp;oq=what+is+the+adk+google&amp;gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIICAEQABgWGB4yCAgCEAAYFhgeMggIAxAAGBYYHjIICAQQABgWGB4yCAgFEAAYFhgeMggIBhAAGBYYHjIKCAcQABgKGBYYHjINCAgQABiGAxiABBiKBTIKCAkQABiABBiiBNIBCDMxODlqMGo3qAIAsAIA&amp;sourceid=chrome&amp;ie=UTF-8&amp;mstk=AUtExfB5Oo7ZHHcDEHu7aqZiPBA2l1c-QGh5dB7xkkDPIiYcn8O1Imt2IHNR7bzA6JnyDCSDCUGpGWTeBW14namlN_QqzJLLI5-px1BE9jfSxwli6njPDPERjm5pRqNP3uC6HhUKiRcTJ1T8x5LHQrCkVxylw7QWg0N8B4dQDIcWpnVX9Gc&amp;csui=3&amp;ved=2ahUKEwjYu-G8p-uSAxXrv4kEHUbpLo0QgK4QegQIARAB" rel="noopener noreferrer">Google Agent Development Kit</a> (ADK) is an open-source, Python-based framework designed to streamline the creation, deployment, and orchestration of sophisticated, multi-agent AI systems. It treats agent development like software engineering, offering modularity, state management, and built-in tools (like Google Search) to build autonomous agents.</p> <p>The ADK can be installed from here:</p> <p><a href="proxy.php?url=https://google.github.io/adk-docs/" rel="noopener noreferrer">Agent Development Kit (ADK)</a></p> <h4> Where do I start? </h4> <p>The strategy for starting low code agent development is a incremental step by step approach.</p> <p>The agents in the demo are based on the original code lab:</p> <p><a href="proxy.php?url=https://codelabs.developers.google.com/codelabs/create-low-code-agent-with-ADK-visual-builder#0" rel="noopener noreferrer">Create and deploy low code ADK (Agent Deployment Kit) agents using ADK Visual Builder | Google Codelabs</a></p> <p>First, the basic development environment is setup with the required system variables, and a working Gemini CLI configuration.</p> <p>Then, a minimal ADK Agent is built with the visual builder. Next — the entire solution is deployed to Google Cloud Run.</p> <h4> Setup the Basic Environment </h4> <p>At this point you should have a working Python environment and a working Gemini CLI installation. The next step is to clone the GitHub samples repository with support scripts:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd</span> ~ git clone https://github.com/xbill9/adkui </code></pre> </div> <p>Then run <strong>init.sh</strong> from the cloned directory.</p> <p>The script will attempt to determine your shell environment and set the correct variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">source </span>init.sh pip <span class="nb">install</span> <span class="nt">-r</span> requirements.txt </code></pre> </div> <p>If your session times out or you need to re-authenticate- you can run the <strong>set_env.sh</strong> script to reset your environment variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">source </span>set_env.sh </code></pre> </div> <p>Variables like PROJECT_ID need to be setup for use in the various build scripts- so the <strong>set_env</strong> script can be used to reset the environment if you time-out.</p> <h4> Verify The ADK Installation </h4> <p>To verify the setup, run the ADK CLI with Agent1:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">azureuser@azure-new:~/adkui$</span><span class="w"> </span>adk run Agent1 <span class="go">Log setup complete: /tmp/agents_log/agent.20260316_214351.log To access latest log: tail -F /tmp/agents_log/agent.latest.log /home/azureuser/.pyenv/versions/3.13.12/lib/python3.13/site-packages/google/adk/cli/utils/agent_loader.py:248: UserWarning: [EXPERIMENTAL] _load_from_yaml_config: This feature is experimental and may change or be removed in future versions without notice. It may introduce breaking changes at any time. if root_agent := self._load_from_yaml_config(actual_agent_name, agents_dir): /home/azureuser/.pyenv/versions/3.13.12/lib/python3.13/site-packages/google/adk/features/_feature_decorator.py:81: UserWarning: [EXPERIMENTAL] feature FeatureName.AGENT_CONFIG is enabled. check_feature_enabled() /home/azureuser/.pyenv/versions/3.13.12/lib/python3.13/site-packages/google/adk/cli/cli.py:204: UserWarning: [EXPERIMENTAL] InMemoryCredentialService: This feature is experimental and may change or be removed in future versions without notice. It may introduce breaking changes at any time. credential_service = InMemoryCredentialService() /home/azureuser/.pyenv/versions/3.13.12/lib/python3.13/site-packages/google/adk/auth/credential_service/in_memory_credential_service.py:33: UserWarning: [EXPERIMENTAL] BaseCredentialService: This feature is experimental and may change or be removed in future versions without notice. It may introduce breaking changes at any time. super(). __init__ () Running agent Agent1, type exit to exit. [user]: what is the weather in Weehawken NJ [Agent1]: The current weather in Weehawken, NJ, is light to moderate rain with a 94% chance of precipitation. The temperature is 59°F (15°C), and it feels like 56°F (13°C). The humidity is around 89%. <h4> Running the ADK Web Interface </h4> <p>First- start the ADK interface:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">azureuser@azure-new:~/adkui$</span><span class="w"> </span>adk web <span class="nt">--host</span> 0.0.0.0 <span class="go">2026-03-16 21:44:48,299 - INFO - service_factory.py:266 - Using in-memory memory service 2026-03-16 21:44:48,299 - INFO - local_storage.py:84 - Using per-agent session storage rooted at /home/azureuser/adkui 2026-03-16 21:44:48,305 - INFO - local_storage.py:110 - Using file artifact service at /home/azureuser/adkui/.adk/artifacts /home/azureuser/.pyenv/versions/3.13.12/lib/python3.13/site-packages/google/adk/cli/fast_api.py:192: UserWarning: [EXPERIMENTAL] InMemoryCredentialService: This feature is experimental and may change or be removed in future versions without notice. It may introduce breaking changes at any time. credential_service = InMemoryCredentialService() /home/azureuser/.pyenv/versions/3.13.12/lib/python3.13/site-packages/google/adk/auth/credential_service/in_memory_credential_service.py:33: UserWarning: [EXPERIMENTAL] BaseCredentialService: This feature is experimental and may change or be removed in future versions without notice. It may introduce breaking changes at any time. super(). __init__ () INFO: Started server process [7118] INFO: Waiting for application startup. +-----------------------------------------------------------------------------+ | ADK Web Server started | | | | For local testing, access at http://0.0.0.0:8000. | +-----------------------------------------------------------------------------+ INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) </span></code></pre> </div> <h4> Connecting to the ADK </h4> <p>First — validate your public IP address:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">azureuser@azure-new:~$</span><span class="w"> </span>gemini <span class="go"> ▝▜▄ Gemini CLI v0.33.2 ▝▜▄ ▗▟▀ Logged in with Google /auth ▝▀ Gemini Code Assist Standard /upgrade </span><span class="gp"> &gt;</span><span class="w"> </span>what is my public IP address <span class="go">✦ I will check your public IP address using curl. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ Shell curl -s https://ifconfig.me [current working directory /home/azureuser] (Get public IP address using ifconfig.me) │ │ │ │ 20.124.121.35 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ Your public IP address is 20.124.121.35. </span></code></pre> </div> <p>Then start a connection on port 8000:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>http://20.124.121.35:8000/dev-ui/ </code></pre> </div> <p>This will bring up the ADK UI:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwu1z22gdhpcfr1c5o1an.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwu1z22gdhpcfr1c5o1an.png" width="800" height="450"></a></p> <h4> Run a Sub Agent </h4> <p>Connect to the ADK and select “Agent2”. Give the Agent this prompt:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>Create an image of a cat. </code></pre> </div> <p>The sub agent will then generate the cat image:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1vtbupsuiw0bas1fj0po.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1vtbupsuiw0bas1fj0po.png" width="800" height="450"></a></p> <h4> Visual Build an Agent </h4> <p>To use the ADK visual builder- select the pencil Icon next to Agent 2. You can drill down into the Agent design:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkg5jhyn19pqt9qmutuuo.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkg5jhyn19pqt9qmutuuo.png" width="800" height="450"></a></p> <h4> Run a more Complex Agent </h4> <p>The final agent — Agent3 is a more complex agent that uses image generation to generate comic panels.</p> <p>Switch to Agent3 and use the following prompt:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>Create a Comic Book based on the following story, Title: The Story of Momotaro The story of Momotaro (Peach Boy) is one of Japan's most famous and beloved folktales. It is a classic "hero's journey" that emphasizes the virtues of courage, filial piety, and teamwork. The Miraculous Birth Long, long ago, in a small village in rural Japan, lived an elderly couple. They were hardworking and kind, but they were sad because they had never been blessed with children. One morning, while the old woman was washing clothes by the river, she saw a magnificent, giant peach floating downstream. It was larger than any peach she had ever seen. With great effort, she pulled it from the water and brought it home to her husband for their dinner. As they prepared to cut the fruit open, the peach suddenly split in half on its own. To their astonishment, a healthy, beautiful baby boy stepped out from the pit. "Don't be afraid," the child said. "The Heavens have sent me to be your son." Overjoyed, the couple named him Momotaro (Momo meaning peach, and Taro being a common name for an eldest son). The Call to Adventure Momotaro grew up to be stronger and kinder than any other boy in the village. During this time, the village lived in fear of the Oni-ogres and demons who lived on a distant island called Onigashima. These Oni would often raid the mainland, stealing treasures and kidnapping villagers. When Momotaro reached young adulthood, he approached his parents with a request. "I must go to Onigashima," he declared. "I will defeat the Oni and bring back the stolen treasures to help our people." Though they were worried, his parents were proud. As a parting gift, the old woman prepared Kibi-dango (special millet dumplings), which were said to provide the strength of a hundred men. Gathering Allies Momotaro set off on his journey toward the sea. Along the way, he met three distinct animals: The Spotted Dog: The dog growled at first, but Momotaro offered him one of his Kibi-dango. The dog, tasting the magical dumpling, immediately swore his loyalty. The Monkey: Further down the road, a monkey joined the group in exchange for a dumpling, though he and the dog bickered constantly. The Pheasant: Finally, a pheasant flew down from the sky. After receiving a piece of the Kibi-dango, the bird joined the team as their aerial scout. Momotaro used his leadership to ensure the three animals worked together despite their differences, teaching them that unity was their greatest strength. The Battle of Onigashima The group reached the coast, built a boat, and sailed to the dark, craggy shores of Onigashima. The island was guarded by a massive iron gate. The Pheasant flew over the walls to distract the Oni and peck at their eyes. The Monkey climbed the walls and unbolted the Great Gate from the inside. The Dog and Momotaro charged in, using their immense strength to overpower the demons. The Oni were caught off guard by the coordinated attack. After a fierce battle, the King of the Oni fell to his knees before Momotaro, begging for mercy. He promised to never trouble the villagers again and surrendered all the stolen gold, jewels, and precious silks. The Triumphant Return Momotaro and his three companions loaded the treasure onto their boat and returned to the village. The entire town celebrated their homecoming. Momotaro used the wealth to ensure his elderly parents lived the rest of their lives in comfort and peace. He remained in the village as a legendary protector, and his story was passed down for generations as a reminder that bravery and cooperation can overcome even the greatest evils. </code></pre> </div> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyf1vkmehl2iwyy9l11iy.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyf1vkmehl2iwyy9l11iy.png" width="800" height="450"></a></p> <p>Finally when the process is complete:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="c">#go to the project folder</span> <span class="nb">cd</span> ~/adkui <span class="c">#Go to the output folder</span> <span class="nb">cd</span> ~/adkui/output <span class="c">#start local web server</span> python <span class="nt">-m</span> http.server 8000 <span class="nt">--bind</span> 0.0.0.0 </code></pre> </div> <p>Then verify the Agent output on the external URL:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>http://20.124.121.35:8000/comic.html </code></pre> </div> <p>This will present the final comic:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx52odi78unyx1kc94cmb.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx52odi78unyx1kc94cmb.png" width="800" height="450"></a></p> <h4> Summary </h4> <p>The Agent Development Kit was used to visually define a basic agent and added the Google Search Tool. This Agent was tested locally with the CLI and then with the ADK web tool. Then, several sample ADK agents were run directly from the VM instance from Azure. This approach validates that cross cloud tools can be used — even with more complex agents.</p> </span></code></pre> </div> python azure gemincli googleadk Running the ADK Visual Builder on an AWS EC2 VM xbill Mon, 16 Mar 2026 19:45:31 +0000 https://dev.to/gde/running-the-adk-visual-builder-on-an-aws-ec2-vm-288m https://dev.to/gde/running-the-adk-visual-builder-on-an-aws-ec2-vm-288m <p>Leveraging the Google Agent Development Kit (ADK) and the underlying Gemini LLM to build low code in the Python programming language deployed securely on the Amazon AWS Cloud platform.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F722gp42o7m9epkc213p4.jpeg" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F722gp42o7m9epkc213p4.jpeg" width="800" height="436"></a></p> <h4> Amazon EC2 Instance Configuration </h4> <p>To configure your EC2 Instance with the base system tools- this article provides a reference:</p> <p><a href="proxy.php?url=https://xbill999.medium.com/cross-cloud-agent-development-with-the-google-adk-and-amazon-ec2-d665c297dec9" rel="noopener noreferrer">Cross Cloud Agent Development with the Google ADK and Amazon EC2</a></p> <p>The key step is to verify that port 8000 is open for Internet traffic to allow access to the ADK:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>✦ The AWS configuration for instance i-03456018d00d13504 confirms that port 8000 is open to external traffic. 1. Security Group (sg-079649e89ed485925): A TCP rule allows traffic on port 8000 from all sources (0.0.0.0/0). 2. Network ACL: The subnet's NACL allows all inbound and outbound traffic (0.0.0.0/0 on all protocols). </code></pre> </div> <h4> Python Version Management </h4> <p>One of the downsides of the wide deployment of Python has been managing the language versions across platforms and maintaining a supported version.</p> <p>The <strong>pyenv</strong> tool enables deploying consistent versions of Python:</p> <p><a href="proxy.php?url=https://github.com/pyenv/pyenv" rel="noopener noreferrer">GitHub - pyenv/pyenv: Simple Python version management</a></p> <p>As of writing — the mainstream python version is 3.13. To validate your current Python:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">admin@ip-172-31-70-211:~$</span><span class="w"> </span>python <span class="nt">--version</span> <span class="go">Python 3.13.12 </span><span class="gp">admin@ip-172-31-70-211:~$</span><span class="w"> </span></code></pre> </div> <h4> Gemini CLI </h4> <p>If not pre-installed you can download the Gemini CLI to interact with the source files and provide real-time assistance:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>npm <span class="nb">install</span> <span class="nt">-g</span> @google/gemini-cli </code></pre> </div> <h4> Testing the Gemini CLI Environment </h4> <p>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:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="go">gemini </span><span class="gp">admin@ip-172-31-70-211:~$</span><span class="w"> </span>gemini <span class="go"> ▝▜▄ Gemini CLI v0.33.1 ▝▜▄ ▗▟▀ Logged in with Google /auth ▝▀ Gemini Code Assist Standard /upgrade </span></code></pre> </div> <h4> Node Version Management </h4> <p>Gemini CLI needs a consistent, up to date version of Node. The <strong>nvm</strong> command can be used to get a standard Node environment:</p> <p><a href="proxy.php?url=https://github.com/nvm-sh/nvm" rel="noopener noreferrer">GitHub - nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions</a></p> <h4> Agent Development Kit </h4> <p>The <a href="proxy.php?url=https://www.google.com/search?q=Google+Agent+Development+Kit&amp;rlz=1CAIWTJ_enUS1114&amp;oq=what+is+the+adk+google&amp;gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIICAEQABgWGB4yCAgCEAAYFhgeMggIAxAAGBYYHjIICAQQABgWGB4yCAgFEAAYFhgeMggIBhAAGBYYHjIKCAcQABgKGBYYHjINCAgQABiGAxiABBiKBTIKCAkQABiABBiiBNIBCDMxODlqMGo3qAIAsAIA&amp;sourceid=chrome&amp;ie=UTF-8&amp;mstk=AUtExfB5Oo7ZHHcDEHu7aqZiPBA2l1c-QGh5dB7xkkDPIiYcn8O1Imt2IHNR7bzA6JnyDCSDCUGpGWTeBW14namlN_QqzJLLI5-px1BE9jfSxwli6njPDPERjm5pRqNP3uC6HhUKiRcTJ1T8x5LHQrCkVxylw7QWg0N8B4dQDIcWpnVX9Gc&amp;csui=3&amp;ved=2ahUKEwjYu-G8p-uSAxXrv4kEHUbpLo0QgK4QegQIARAB" rel="noopener noreferrer">Google Agent Development Kit</a> (ADK) is an open-source, Python-based framework designed to streamline the creation, deployment, and orchestration of sophisticated, multi-agent AI systems. It treats agent development like software engineering, offering modularity, state management, and built-in tools (like Google Search) to build autonomous agents.</p> <p>The ADK can be installed from here:</p> <p><a href="proxy.php?url=https://google.github.io/adk-docs/" rel="noopener noreferrer">Agent Development Kit (ADK)</a></p> <h4> Where do I start? </h4> <p>The strategy for starting low code agent development is a incremental step by step approach.</p> <p>The agents in the demo are based on the original code lab:</p> <p><a href="proxy.php?url=https://codelabs.developers.google.com/codelabs/create-low-code-agent-with-ADK-visual-builder#0" rel="noopener noreferrer">Create and deploy low code ADK (Agent Deployment Kit) agents using ADK Visual Builder | Google Codelabs</a></p> <p>First, the basic development environment is setup with the required system variables, and a working Gemini CLI configuration.</p> <p>Then, a minimal ADK Agent is built with the visual builder. Next — the entire solution is deployed to Google Cloud Run.</p> <h4> Setup the Basic Environment </h4> <p>At this point you should have a working Python environment and a working Gemini CLI installation. The next step is to clone the GitHub samples repository with support scripts:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd</span> ~ git clone https://github.com/xbill9/adkui </code></pre> </div> <p>Then run <strong>init.sh</strong> from the cloned directory.</p> <p>The script will attempt to determine your shell environment and set the correct variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">source </span>init.sh pip <span class="nb">install</span> <span class="nt">-r</span> requirements.txt </code></pre> </div> <p>If your session times out or you need to re-authenticate- you can run the <strong>set_env.sh</strong> script to reset your environment variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">source </span>set_env.sh </code></pre> </div> <p>Variables like PROJECT_ID need to be setup for use in the various build scripts- so the <strong>set_env</strong> script can be used to reset the environment if you time-out.</p> <h4> Verify The ADK Installation </h4> <p>To verify the setup, run the ADK CLI with Agent1:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">admin@ip-172-31-70-211:~/adkui$</span><span class="w"> </span>adk run Agent1 <span class="go">Log setup complete: /tmp/agents_log/agent.20260313_141019.log To access latest log: tail -F /tmp/agents_log/agent.latest.log /home/admin/.pyenv/versions/3.13.12/lib/python3.13/site-packages/google/adk/cli/utils/agent_loader.py:248: UserWarning: [EXPERIMENTAL] _load_from_yaml_config: This feature is experimental and may change or be removed in future versions without notice. It may introduce breaking changes at any time. if root_agent := self._load_from_yaml_config(actual_agent_name, agents_dir): /home/admin/.pyenv/versions/3.13.12/lib/python3.13/site-packages/google/adk/features/_feature_decorator.py:81: UserWarning: [EXPERIMENTAL] feature FeatureName.AGENT_CONFIG is enabled. check_feature_enabled() /home/admin/.pyenv/versions/3.13.12/lib/python3.13/site-packages/google/adk/cli/cli.py:204: UserWarning: [EXPERIMENTAL] InMemoryCredentialService: This feature is experimental and may change or be removed in future versions without notice. It may introduce breaking changes at any time. credential_service = InMemoryCredentialService() /home/admin/.pyenv/versions/3.13.12/lib/python3.13/site-packages/google/adk/auth/credential_service/in_memory_credential_service.py:33: UserWarning: [EXPERIMENTAL] BaseCredentialService: This feature is experimental and may change or be removed in future versions without notice. It may introduce breaking changes at any time. super(). __init__ () Running agent Agent1, type exit to exit. [user]: what is the weather in Hoboken NJ [Agent1]: The weather in Hoboken, NJ, is currently cloudy with a temperature of approximately 36-38°F (2-3°C), feeling like 31-33°F (0-0°C). There is a 10% chance of snow, though some forecasts indicate a higher chance of snow (70-80%) this evening, with skies clearing later. The forecast for today (Friday, March 13, 2026) in Hoboken indicates cloudy conditions during the day, becoming clear at night. Temperatures are expected to range between 30°F (-1°C) and 42°F (6°C). <h4> Running the ADK Web Interface </h4> <p>First- start the ADK interface:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">admin@ip-172-31-70-211:~/adkui$</span><span class="w"> </span>adk web <span class="nt">--host</span> 0.0.0.0 <span class="go">2026-03-13 14:14:12,212 - INFO - service_factory.py:266 - Using in-memory memory service 2026-03-13 14:14:12,212 - INFO - local_storage.py:84 - Using per-agent session storage rooted at /home/admin/adkui 2026-03-13 14:14:12,213 - INFO - local_storage.py:110 - Using file artifact service at /home/admin/adkui/.adk/artifacts /home/admin/.pyenv/versions/3.13.12/lib/python3.13/site-packages/google/adk/cli/fast_api.py:192: UserWarning: [EXPERIMENTAL] InMemoryCredentialService: This feature is experimental and may change or be removed in future versions without notice. It may introduce breaking changes at any time. credential_service = InMemoryCredentialService() /home/admin/.pyenv/versions/3.13.12/lib/python3.13/site-packages/google/adk/auth/credential_service/in_memory_credential_service.py:33: UserWarning: [EXPERIMENTAL] BaseCredentialService: This feature is experimental and may change or be removed in future versions without notice. It may introduce breaking changes at any time. super(). __init__ () INFO: Started server process [6733] INFO: Waiting for application startup. +-----------------------------------------------------------------------------+ | ADK Web Server started | | | | For local testing, access at http://0.0.0.0:8000. | +-----------------------------------------------------------------------------+ INFO: Application startup complete. INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit) </span></code></pre> </div> <h4> Connecting to the ADK </h4> <p>First — validate your public IP address:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">admin@ip-172-31-70-211:~/adkui$</span><span class="w"> </span>gemini <span class="go"> ▝▜▄ Gemini CLI v0.33.1 ▝▜▄ ▗▟▀ Logged in with Google /auth ▝▀ Gemini Code Assist Standard /upgrade </span><span class="gp"> &gt;</span><span class="w"> </span>what is my public IP <span class="go">✦ I will use curl to fetch your public IP address from ifconfig.me. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ Shell curl -s ifconfig.me [current working directory /home/admin/adkui] (Fetch public IP address using ifconfig.me) │ │ │ │ 3.236.173.161 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ Your public IP address is 3.236.173.161. </span></code></pre> </div> <p>Then start a connection on port 8000:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>http://3.236.173.161:8000/dev-ui/ </code></pre> </div> <p>This will bring up the ADK UI:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9aycywsyl37bxgrg9nkq.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9aycywsyl37bxgrg9nkq.png" width="800" height="450"></a></p> <h4> Run a Sub Agent </h4> <p>Connect to the ADK and select “Agent2”. Give the Agent this prompt:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>Create an image of a cat. </code></pre> </div> <p>The sub agent will then generate the cat image:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flm13d2b061i5ugxlbrkp.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flm13d2b061i5ugxlbrkp.png" width="800" height="450"></a></p> <h4> Visual Build an Agent </h4> <p>To use the ADK visual builder- select the pencil Icon next to Agent 2. You can drill down into the Agent design:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkg5jhyn19pqt9qmutuuo.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkg5jhyn19pqt9qmutuuo.png" width="800" height="450"></a></p> <h4> Run a more Complex Agent </h4> <p>The final agent — Agent3 is a more complex agent that uses image generation to generate comic panels.</p> <p>Swtich to Agent3 and use the following prompt:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>Create a Comic Book based on the following story, Title: The Story of Momotaro The story of Momotaro (Peach Boy) is one of Japan's most famous and beloved folktales. It is a classic "hero's journey" that emphasizes the virtues of courage, filial piety, and teamwork. The Miraculous Birth Long, long ago, in a small village in rural Japan, lived an elderly couple. They were hardworking and kind, but they were sad because they had never been blessed with children. One morning, while the old woman was washing clothes by the river, she saw a magnificent, giant peach floating downstream. It was larger than any peach she had ever seen. With great effort, she pulled it from the water and brought it home to her husband for their dinner. As they prepared to cut the fruit open, the peach suddenly split in half on its own. To their astonishment, a healthy, beautiful baby boy stepped out from the pit. "Don't be afraid," the child said. "The Heavens have sent me to be your son." Overjoyed, the couple named him Momotaro (Momo meaning peach, and Taro being a common name for an eldest son). The Call to Adventure Momotaro grew up to be stronger and kinder than any other boy in the village. During this time, the village lived in fear of the Oni—ogres and demons who lived on a distant island called Onigashima. These Oni would often raid the mainland, stealing treasures and kidnapping villagers. When Momotaro reached young adulthood, he approached his parents with a request. "I must go to Onigashima," he declared. "I will defeat the Oni and bring back the stolen treasures to help our people." Though they were worried, his parents were proud. As a parting gift, the old woman prepared Kibi-dango (special millet dumplings), which were said to provide the strength of a hundred men. Gathering Allies Momotaro set off on his journey toward the sea. Along the way, he met three distinct animals: The Spotted Dog: The dog growled at first, but Momotaro offered him one of his Kibi-dango. The dog, tasting the magical dumpling, immediately swore his loyalty. The Monkey: Further down the road, a monkey joined the group in exchange for a dumpling, though he and the dog bickered constantly. The Pheasant: Finally, a pheasant flew down from the sky. After receiving a piece of the Kibi-dango, the bird joined the team as their aerial scout. Momotaro used his leadership to ensure the three animals worked together despite their differences, teaching them that unity was their greatest strength. The Battle of Onigashima The group reached the coast, built a boat, and sailed to the dark, craggy shores of Onigashima. The island was guarded by a massive iron gate. The Pheasant flew over the walls to distract the Oni and peck at their eyes. The Monkey climbed the walls and unbolted the Great Gate from the inside. The Dog and Momotaro charged in, using their immense strength to overpower the demons. The Oni were caught off guard by the coordinated attack. After a fierce battle, the King of the Oni fell to his knees before Momotaro, begging for mercy. He promised to never trouble the villagers again and surrendered all the stolen gold, jewels, and precious silks. The Triumphant Return Momotaro and his three companions loaded the treasure onto their boat and returned to the village. The entire town celebrated their homecoming. Momotaro used the wealth to ensure his elderly parents lived the rest of their lives in comfort and peace. He remained in the village as a legendary protector, and his story was passed down for generations as a reminder that bravery and cooperation can overcome even the greatest evils. </code></pre> </div> <p>This will start the agent process:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyf1vkmehl2iwyy9l11iy.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyf1vkmehl2iwyy9l11iy.png" width="800" height="450"></a></p> <p>Finally when the process is complete:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="c">#go to the project folder</span> <span class="nb">cd</span> ~/adkui <span class="c">#Go to the output folder</span> <span class="nb">cd</span> ~/adkui/output <span class="c">#start local web server</span> python <span class="nt">-m</span> http.server 8000 </code></pre> </div> <p>Then verify the Agent output on the external URL:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>http://3.236.173.161:8000/comic.html </code></pre> </div> <p>This will present the final comic:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx52odi78unyx1kc94cmb.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx52odi78unyx1kc94cmb.png" width="800" height="450"></a></p> <h4> Summary </h4> <p>The Agent Development Kit was used to visually define a basic agent and added the Google Search Tool. This Agent was tested locally with the CLI and then with the ADK web tool. Then, several sample ADK agents were run directly from the EC2 instance from AWS. This approach validates that cross cloud tools can be used — even with more complex agents.</p> </span></code></pre> </div> adkui aws googleadk gemini MCP Development with Amazon Lambda and Gemini CLI xbill Mon, 16 Mar 2026 13:38:46 +0000 https://dev.to/gde/mcp-development-with-amazon-lambda-and-gemini-cli-20kc https://dev.to/gde/mcp-development-with-amazon-lambda-and-gemini-cli-20kc <p>Leveraging Gemini CLI and the underlying Gemini LLM to build Model Context Protocol (MCP) AI applications with Python from a local development environment deployed to the Lambda service on AWS.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuuc80pt2b7foswcdl27l.jpeg" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuuc80pt2b7foswcdl27l.jpeg" width="800" height="436"></a></p> <h4> Aren’t There a Billion Python MCP Demos? </h4> <p>Yes there are.</p> <p>Python has traditionally been the main coding language for ML and AI tools. The goal of this article is to provide a minimal viable basic working MCP stdio server that can be run locally without any unneeded extra code or extensions.</p> <h4> What Is Python? </h4> <p>Python is an interpreted language that allows for rapid development and testing and has deep libraries for working with ML and AI:</p> <p><a href="proxy.php?url=https://www.python.org/" rel="noopener noreferrer">Welcome to Python.org</a></p> <h4> Python Version Management </h4> <p>One of the downsides of the wide deployment of Python has been managing the language versions across platforms and maintaining a supported version.</p> <p>The <strong>pyenv</strong> tool enables deploying consistent versions of Python:</p> <p><a href="proxy.php?url=https://github.com/pyenv/pyenv" rel="noopener noreferrer">GitHub - pyenv/pyenv: Simple Python version management</a></p> <p>As of writing — the mainstream python version is 3.13. To validate your current Python:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">admin@ip-172-31-70-211:~/gemini-cli-aws/mcp-lambda-python-aws$</span><span class="w"> </span>python <span class="nt">--version</span> <span class="go">Python 3.13.12 </span></code></pre> </div> <h4> Gemini CLI </h4> <p>If not pre-installed you can download the Gemini CLI to interact with the source files and provide real-time assistance:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="go">npm install -g @google/gemini-cli </span></code></pre> </div> <h4> Testing the Gemini CLI Environment </h4> <p>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:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="go">gemini </span><span class="gp">admin@ip-172-31-70-211:~/gemini-cli-aws/mcp-lambda-python-aws$</span><span class="w"> </span>gemini <span class="go"> ▝▜▄ Gemini CLI v0.33.1 ▝▜▄ ▗▟▀ Logged in with Google /auth ▝▀ Gemini Code Assist Standard /upgrade ? for shortcuts ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── shift+tab to accept edits 3 GEMINI.md files | 1 MCP server ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── </span><span class="gp"> &gt;</span><span class="w"> </span>Type your message or @path/to/file <span class="go">────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ~/.../mcp-lambda-python-aws (main*) no sandbox (see /docs) /model Auto (Gemini 3) | 239.8 MB </span></code></pre> </div> <h4> Node Version Management </h4> <p>Gemini CLI needs a consistent, up to date version of Node. The <strong>nvm</strong> command can be used to get a standard Node environment:</p> <p><a href="proxy.php?url=https://github.com/nvm-sh/nvm" rel="noopener noreferrer">GitHub - nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions</a></p> <h4> Python MCP Documentation </h4> <p>The official GitHub Repo provides samples and documentation for getting started:</p> <p><a href="proxy.php?url=https://github.com/modelcontextprotocol/python-sdk" rel="noopener noreferrer">GitHub - modelcontextprotocol/python-sdk: The official Python SDK for Model Context Protocol servers and clients</a></p> <p>The most common MCP Python deployment path uses the FASTMCP library:</p> <p><a href="proxy.php?url=https://gofastmcp.com/getting-started/welcome" rel="noopener noreferrer">Welcome to FastMCP - FastMCP</a></p> <h4> Docker Version Management </h4> <p>The AWS Cli tools and Lightsail extensions need current version of Docker. If your environment does not provide a recent docker tool- the Docker Version Manager can be used to downlaod the latest supported Docker:</p> <p><a href="proxy.php?url=https://howtowhale.github.io/dvm/install.html" rel="noopener noreferrer">Install</a></p> <p>To check the version of Docker:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-lambda-python-aws$</span><span class="w"> </span>dvm <span class="nb">install </span>29.3.0 <span class="go">29.3.0 is already installed Now using Docker 29.3.0 </span></code></pre> </div> <h4> Amazon Lamba </h4> <p><a href="proxy.php?url=https://www.serverless.com/aws-lambda" rel="noopener noreferrer">AWS Lambda</a> is a serverless, event-driven compute service that enables users to run code without provisioning or managing servers. With Lambda, developers can focus solely on their code (functions), while AWS handles all underlying infrastructure management, including capacity provisioning, automatic scaling, and operating system maintenance.</p> <p>Full details are here:</p> <p><a href="proxy.php?url=https://aws.amazon.com/pm/lambda" rel="noopener noreferrer">Serverless Computing Service - Free AWS Lambda - AWS</a></p> <h4> AWS CLI </h4> <p>The AWS CLI provides a command line tool to directly access AWS services from your current environment. Full details on the CLI are available here:</p> <p><a href="proxy.php?url=https://docs.aws.amazon.com/lightsail/latest/userguide/amazon-lightsail-install-software.html" rel="noopener noreferrer">Install Docker, AWS CLI, and the Lightsail Control plugin for containers</a></p> <p>You can version check the tool after installation:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~$</span><span class="w"> </span>aws <span class="nt">--version</span> <span class="go">aws-cli/2.34.9 Python/3.13.11 Linux/6.6.99-09128-g14e87a8a9b71 exe/x86_64.debian.12 </span><span class="gp">xbill@penguin:~$</span><span class="w"> </span></code></pre> </div> <h4> Where do I start? </h4> <p>The strategy for starting MCP development is a incremental step by step approach.</p> <p>First, the basic development environment is setup with the required system variables, and a working Gemini CLI configuration.</p> <p>Then, a minimal Hello World Style Python MCP Server is built with HTTP transport. This server is validated with Gemini CLI in the local environment.</p> <p>This setup validates the connection from Gemini CLI to the local process via MCP. The MCP client (Gemini CLI) and the Python MCP server both run in the same local environment.</p> <p>Next- the MCP server is wrapped in a container with docker and deployed to Amazon Lambda. This remote deployment is validated with Gemini CLI running as a MCP client.</p> <h4> Setup the Basic Environment </h4> <p>At this point you should have a working Python interpreter and a working Gemini CLI installation. The next step is to clone the GitHub samples repository with support scripts:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="go">cd ~ git clone https://github.com/xbill9/gemini-cli-aws </span></code></pre> </div> <p>Then run <strong>init.sh</strong> from the cloned directory.</p> <p>The script will attempt to determine your shell environment and set the correct variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="go">cd gemini-cli-aws source init.sh </span></code></pre> </div> <p>If your session times out or you need to re-authenticate- you can run the <strong>set_env.sh</strong> script to reset your environment variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="go">cd gemini-cli-aws source set_env.sh </span></code></pre> </div> <p>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.</p> <h4> Hello World with HTTP Transport </h4> <p>One of the key features that the standard MCP libraries provide is abstracting various transport methods.</p> <p>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.</p> <p>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.</p> <p>The HTTP transport allows the MCP client and server to run in the same environment or distributed over the Internet.</p> <p>The connection over HTTP will look similar to this:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code><span class="n">mcp</span><span class="p">.</span><span class="nf">run</span><span class="p">(</span> <span class="n">transport</span><span class="o">=</span><span class="sh">"</span><span class="s">http</span><span class="sh">"</span><span class="p">,</span> <span class="n">host</span><span class="o">=</span><span class="sh">"</span><span class="s">0.0.0.0</span><span class="sh">"</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="n">port</span><span class="p">,</span> <span class="p">)</span> </code></pre> </div> <h4> Running the Python Code </h4> <p>First- switch the directory with the Python MCP sample code:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="go">cd ~/gemini-cli-aws/mcp-lambda-python-aws </span></code></pre> </div> <p>Refresh the AWS credentials:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-lambda-python-aws$</span><span class="w"> </span>aws login <span class="nt">--remote</span> <span class="go">Browser will not be automatically opened. </span><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-lambda-python-aws$</span><span class="w"> </span><span class="nb">source </span>save-aws-creds.sh <span class="go">Exporting AWS credentials... Successfully saved credentials to .aws_creds The Makefile will now automatically use these for deployments. </span><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-lambda-python-aws$</span><span class="w"> </span></code></pre> </div> <p>Run the deploy version on the local system:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-lambda-python-aws$</span><span class="w"> </span>make deploy <span class="go">Ensuring IAM role McpLambdaExecutionRole exists... Checking if ECR repository exists... Logging in to Amazon ECR... 0.0s </span></code></pre> </div> <p>You can validate the final result by checking the messages:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight json"><code><span class="err">Updating</span><span class="w"> </span><span class="err">existing</span><span class="w"> </span><span class="err">Lambda</span><span class="w"> </span><span class="err">function...</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"FunctionName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"mcp-lambda-python-aws"</span><span class="p">,</span><span class="w"> </span><span class="nl">"FunctionArn"</span><span class="p">:</span><span class="w"> </span><span class="s2">"arn:aws:lambda:us-east-1:106059658660:function:mcp-lambda-python-aws"</span><span class="p">,</span><span class="w"> </span><span class="nl">"Role"</span><span class="p">:</span><span class="w"> </span><span class="s2">"arn:aws:iam::106059658660:role/McpLambdaExecutionRole"</span><span class="p">,</span><span class="w"> </span></code></pre> </div> <p>Once the container is deployed:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-lambda-python-aws$</span><span class="w"> </span>make status <span class="go">Checking AWS Lambda status for mcp-lambda-python-aws... --------------------------------------------------------------------- | GetFunction | +-------------------------------+-------------------------+---------+ | LastModified | Name | Status | +-------------------------------+-------------------------+---------+ | 2026-03-16T00:24:22.000+0000 | mcp-lambda-python-aws | Active | +-------------------------------+-------------------------+---------+ </span><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-lambda-python-aws$</span><span class="w"> </span></code></pre> </div> <p>You can then get the endpoint:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-lambda-python-aws$</span><span class="w"> </span>make endpoint <span class="go">https://exoqnsj6ukb6ym36nmzckgg6g40tzpqn.lambda-url.us-east-1.on.aws/ </span></code></pre> </div> <h4> Gemini CLI settings.json </h4> <p>Once you have the deployed endpoint — update the Gemini CLI MCP settings:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight json"><code><span class="p">{</span><span class="w"> </span><span class="nl">"mcpServers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"mcp-lambda-python-aws"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"httpUrl"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://exoqnsj6ukb6ym36nmzckgg6g40tzpqn.lambda-url.us-east-1.on.aws/mcp"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre> </div> <h4> Remote MCP Server Testing </h4> <p>Restart Gemini CLI and check for the new MCP tools:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-lambda-python-aws$</span><span class="w"> </span>gemini <span class="go"> </span><span class="gp"> &gt;</span><span class="w"> </span>/mcp list <span class="go">Configured MCP servers: 🟢 mcp-lambda-python-aws - Ready (1 tool) Tools: - mcp_mcp-lambda-python-aws_greet </span></code></pre> </div> <p>Then the remote MCP tool in Lambda can be called:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">&gt;</span><span class="w"> </span>greet Lambda! <span class="go">✦ I will call the greet tool with "Lambda!" to get a greeting. ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ Action Required │ │ │ │ ? greet (mcp-lambda-python-aws MCP Server) {"param":"Lambda!"} │ │ │ │ MCP Server: mcp-lambda-python-aws │ │ Tool: greet │ │ │ │ MCP Tool Details: │ │ (press Ctrl+O to expand MCP tool details) │ │ Allow execution of MCP tool "greet" from server "mcp-lambda-python-aws"? │ │ │ │ 1. Allow once │ │ 2. Allow tool for this session │ │ 3. Allow all server tools for this session │ │ ● 4. Allow tool for all future sessions │ │ 5. No, suggest changes (esc) │ │ │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ </span><span class="gp">&gt;</span><span class="w"> </span>greet Lambda! <span class="go">✦ I will call the greet tool with "Lambda!" to get a greeting. ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ greet (mcp-lambda-python-aws MCP Server) {"param":"Lambda!"} │ │ │ │ Hello, Lambda!! │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ OK. Lambda! updated. </span></code></pre> </div> <p>Gemini CLI can also summarize the deployment:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code> &gt; summarize the AWS Lambda deployment ✦ The AWS Lambda deployment for this project is a containerized Python MCP server designed for stateless HTTP operation. Key Deployment Characteristics - Architecture: The server uses the FastMCP SDK with stateless_http=True to ensure compatibility with AWS Lambda's scaling model (avoiding "Session not found" errors common with standard SSE). - Runtime: Deployed as a Docker container using the AWS Lambda Python base image. - Trigger: Exposed via Lambda Function URLs, providing a public HTTPS endpoint without requiring an API Gateway. - Entry Point: Uses Mangum as an ASGI adapter to bridge the FastMCP/Starlette application to the Lambda handler format. Deployment Workflow (via Makefile) 1. IAM Setup: make iam-setup ensures the McpLambdaExecutionRole exists. 2. Containerization: make docker-build builds the image locally. 3. Registry: make push-ecr tags and pushes the image to Amazon ECR. 4. Deployment: make deploy creates or updates the Lambda function and configures the Function URL. Monitoring &amp; Access - Endpoint: make endpoint retrieves the public URL. - Status: make status checks the current state of the Lambda function in AWS. </code></pre> </div> <h4> Summary </h4> <p>The strategy for using Python for MCP development with Gemini CLI on Amazon Lambda was validated with a incremental step by step approach.</p> <p>A minimal HTTP transport MCP Server was started from Python source code and validated with Gemini CLI running as a MCP client in the same local environment.</p> <p>This MCP server was then wrapped in a Docker container and deployed to Amazon Lambda. The local copy of Gemini CLI was used as a MCP client to validate the connection.</p> <p>This approach can be extended to more complex deployments using other MCP transports and Cloud based options.</p> python gemini awslambda mcpserver MCP Development with Gemini CLI and Amazon Fargate xbill Mon, 16 Mar 2026 13:37:01 +0000 https://dev.to/gde/mcp-development-with-gemini-cli-and-amazon-fargate-el8 https://dev.to/gde/mcp-development-with-gemini-cli-and-amazon-fargate-el8 <p>Leveraging Gemini CLI and the underlying Gemini LLM to build Model Context Protocol (MCP) AI applications with Python from a local development environment deployed to the Fargate serverless container system on AWS.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuuc80pt2b7foswcdl27l.jpeg" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuuc80pt2b7foswcdl27l.jpeg" width="800" height="436"></a></p> <h4> Aren’t There a Billion Python MCP Demos? </h4> <p>Yes there are.</p> <p>Python has traditionally been the main coding language for ML and AI tools. The goal of this article is to provide a minimal viable basic working MCP stdio server that can be run locally without any unneeded extra code or extensions.</p> <h4> What Is Python? </h4> <p>Python is an interpreted language that allows for rapid development and testing and has deep libraries for working with ML and AI:</p> <p><a href="proxy.php?url=https://www.python.org/" rel="noopener noreferrer">Welcome to Python.org</a></p> <h4> Python Version Management </h4> <p>One of the downsides of the wide deployment of Python has been managing the language versions across platforms and maintaining a supported version.</p> <p>The <strong>pyenv</strong> tool enables deploying consistent versions of Python:</p> <p><a href="proxy.php?url=https://github.com/pyenv/pyenv" rel="noopener noreferrer">GitHub - pyenv/pyenv: Simple Python version management</a></p> <p>As of writing — the mainstream python version is 3.13. To validate your current Python:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">admin@ip-172-31-70-211:~/gemini-cli-aws/mcp-fargate-python-aws$</span><span class="w"> </span>python <span class="nt">--version</span> <span class="go">Python 3.13.12 </span></code></pre> </div> <h4> Gemini CLI </h4> <p>If not pre-installed you can download the Gemini CLI to interact with the source files and provide real-time assistance:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>npm <span class="nb">install</span> <span class="nt">-g</span> @google/gemini-cli </code></pre> </div> <h4> Testing the Gemini CLI Environment </h4> <p>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:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="go">gemini </span><span class="gp">admin@ip-172-31-70-211:~/gemini-cli-aws/mcp-fargate-python-aws$</span><span class="w"> </span>gemini <span class="go"> ▝▜▄ Gemini CLI v0.33.1 ▝▜▄ ▗▟▀ Logged in with Google /auth ▝▀ Gemini Code Assist Standard /upgrade ? for shortcuts ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── shift+tab to accept edits 3 GEMINI.md files | 1 MCP server ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── </span><span class="gp"> &gt;</span><span class="w"> </span>Type your message or @path/to/file <span class="go">────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ~/.../mcp-fargate-python-aws (main*) no sandbox (see /docs) /model Auto (Gemini 3) | 239.8 MB </span></code></pre> </div> <h4> Node Version Management </h4> <p>Gemini CLI needs a consistent, up to date version of Node. The <strong>nvm</strong> command can be used to get a standard Node environment:</p> <p><a href="proxy.php?url=https://github.com/nvm-sh/nvm" rel="noopener noreferrer">GitHub - nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions</a></p> <h4> Python MCP Documentation </h4> <p>The official GitHub Repo provides samples and documentation for getting started:</p> <p><a href="proxy.php?url=https://github.com/modelcontextprotocol/python-sdk" rel="noopener noreferrer">GitHub - modelcontextprotocol/python-sdk: The official Python SDK for Model Context Protocol servers and clients</a></p> <p>The most common MCP Python deployment path uses the FASTMCP library:</p> <p><a href="proxy.php?url=https://gofastmcp.com/getting-started/welcome" rel="noopener noreferrer">Welcome to FastMCP - FastMCP</a></p> <h4> Docker Version Management </h4> <p>The AWS CLI tools and Fargate extensions need current version of Docker. If your environment does not provide a recent docker tool- the Docker Version Manager can be used to downlaod the latest supported Docker:</p> <p><a href="proxy.php?url=https://howtowhale.github.io/dvm/install.html" rel="noopener noreferrer">Install</a></p> <h4> Amazon Fargate </h4> <p>AWS Fargate is a serverless, pay-as-you-go compute engine for containers that works with <a href="proxy.php?url=https://aws.amazon.com/documentation-overview/fargate/" rel="noopener noreferrer">Amazon Elastic Container Service (ECS)</a> or Elastic Kubernetes Service (EKS). It eliminates the need to manage, patch, or scale underlying <a href="proxy.php?url=https://www.geeksforgeeks.org/devops/introduction-to-aws-fargate/" rel="noopener noreferrer">EC2 virtual machines</a>. Fargate automatically allocates, scales, and manages compute infrastructure, allowing developers to focus solely on designing and operating applications.</p> <p>Details are here:</p> <p><a href="proxy.php?url=https://aws.amazon.com/fargate/" rel="noopener noreferrer">Serverless Compute - AWS Fargate - AWS</a></p> <h4> AWS CLI </h4> <p>The AWS CLI provides a command line tool to directly access AWS services from your current environment. Full details on the CLI are available here:</p> <p><a href="proxy.php?url=https://docs.aws.amazon.com/lightsail/latest/userguide/amazon-lightsail-install-software.html" rel="noopener noreferrer">Install Docker, AWS CLI, and the Lightsail Control plugin for containers</a></p> <h4> Where do I start? </h4> <p>The strategy for starting MCP development is a incremental step by step approach.</p> <p>First, the basic development environment is setup with the required system variables, and a working Gemini CLI configuration.</p> <p>Then, a minimal Hello World Style Python MCP Server is built with HTTP transport. This server is validated with Gemini CLI in the local environment.</p> <p>This setup validates the connection from Gemini CLI to the local process via MCP. The MCP client (Gemini CLI) and the Python MCP server both run in the same local environment.</p> <p>Next- the MCP server is wrapped in a container with Docker and deployed to Amazon Fargate. This remote deployment is validated with Gemini CLI running as a MCP client.</p> <h4> Setup the Basic Environment </h4> <p>At this point you should have a working Python interpreter and a working Gemini CLI installation. The next step is to clone the GitHub samples repository with support scripts:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd</span> ~ git clone https://github.com/xbill9/gemini-cli-aws </code></pre> </div> <p>Then run <strong>init.sh</strong> from the cloned directory.</p> <p>The script will attempt to determine your shell environment and set the correct variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd </span>gemini-cli-aws <span class="nb">source </span>init.sh </code></pre> </div> <p>If your session times out or you need to re-authenticate- you can run the <strong>set_env.sh</strong> script to reset your environment variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd </span>gemini-cli-aws <span class="nb">source </span>set_env.sh </code></pre> </div> <p>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.</p> <h4> Hello World with HTTP Transport </h4> <p>One of the key features that the standard MCP libraries provide is abstracting various transport methods.</p> <p>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.</p> <p>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.</p> <p>The HTTP transport allows the MCP client and server to run in the same environment or distributed over the Internet.</p> <p>The connection over HTTP will look similar to this:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code><span class="n">mcp</span><span class="p">.</span><span class="nf">run</span><span class="p">(</span> <span class="n">transport</span><span class="o">=</span><span class="sh">"</span><span class="s">http</span><span class="sh">"</span><span class="p">,</span> <span class="n">host</span><span class="o">=</span><span class="sh">"</span><span class="s">0.0.0.0</span><span class="sh">"</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="n">port</span><span class="p">,</span> <span class="p">)</span> </code></pre> </div> <h4> Running the Python Code </h4> <p>First- switch the directory with the Python MCP sample code:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd</span> ~/gemini-cli-aws/mcp-fargate-python-aws </code></pre> </div> <p>Refresh the AWS credentials:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-fargate-python-aws$</span><span class="w"> </span>aws login <span class="nt">--remote</span> <span class="go">Browser will not be automatically opened. </span><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-fargate-python-aws$</span><span class="w"> </span><span class="nb">source </span>save-aws-creds.sh <span class="go">Exporting AWS credentials... Successfully saved credentials to .aws_creds The Makefile will now automatically use these for deployments. </span><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-fargate-python-aws$</span><span class="w"> </span></code></pre> </div> <p>Run the deploy version on the local system:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>xbill@penguin:~/gemini-cli-aws/mcp-fargate-python-aws<span class="nv">$ </span>make deploy Ensuring CloudWatch log group /ecs/mcp-fargate-task exists... Ensuring ECS cluster mcp-fargate-cluster exists... Building the Docker image... 0.0s </code></pre> </div> <p>You can validate the final result by checking the messages:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight json"><code><span class="err">Login</span><span class="w"> </span><span class="err">Succeeded</span><span class="w"> </span><span class="err">Tagging</span><span class="w"> </span><span class="err">and</span><span class="w"> </span><span class="err">pushing</span><span class="w"> </span><span class="err">the</span><span class="w"> </span><span class="err">Docker</span><span class="w"> </span><span class="err">image</span><span class="w"> </span><span class="err">to</span><span class="w"> </span><span class="err">ECR...</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"repositories"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"repositoryArn"</span><span class="p">:</span><span class="w"> </span><span class="s2">"arn:aws:ecr:us-east-1:106059658660:repository/mcp-server-image"</span><span class="p">,</span><span class="w"> </span><span class="nl">"registryId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"106059658660"</span><span class="p">,</span><span class="w"> </span><span class="nl">"repositoryName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"mcp-server-image"</span><span class="p">,</span><span class="w"> </span></code></pre> </div> <p>Once the container is deployed:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-fargate-python-aws$</span><span class="w"> </span>make status <span class="go">Checking AWS ECS service status for mcp-fargate-service in cluster mcp-fargate-cluster... --------------------------------------------------------------------------------------------- | DescribeServices | +----------------+--------------------------------------------------------------------------+ | Desired | 1 | | Running | 1 | | ServiceName | mcp-fargate-service | | Status | ACTIVE | | TaskDefinition| arn:aws:ecs:us-east-1:106059658660:task-definition/mcp-fargate-task:4 | +----------------+--------------------------------------------------------------------------+ </span><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-fargate-python-aws$</span><span class="w"> </span></code></pre> </div> <p>You can then get the endpoint:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>xbill@penguin:~/gemini-cli-aws/mcp-fargate-python-aws<span class="nv">$ </span>make endpoint Querying ECS tasks <span class="k">for </span>mcp-fargate-service... 3.94.10.15 </code></pre> </div> <h4> Gemini CLI settings.json </h4> <p>Once you have the deployed endpoint — update the Gemini CLI MCP settings:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight json"><code><span class="p">{</span><span class="w"> </span><span class="nl">"mcpServers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"mcp-fargate-python-aws"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"httpUrl"</span><span class="p">:</span><span class="w"> </span><span class="s2">"http://3.94.10.15:8080/mcp"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre> </div> <h4> Remote MCP Server Testing </h4> <p>Restart Gemini CLI and check for the new MCP tools:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-apprunner-python-aws$</span><span class="w"> </span>gemini <span class="go"> </span><span class="gp"> &gt;</span><span class="w"> </span>/mcp list <span class="go">Configured MCP servers: 🟢 mcp-fargate-python-aws - Ready (1 tool) Tools: - mcp_mcp-fargate-python-aws_greet </span></code></pre> </div> <p>Then the remote MCP tool in Fargate can be called:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">&gt;</span><span class="w"> </span>greet Fargate1 <span class="go">✦ I will call the greet tool with the argument Fargate1. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ Action Required │ │ │ │ ? greet (mcp-fargate-python-aws MCP Server) {"param":"Fargate1"} │ │ │ │ ... first 3 lines hidden (Ctrl+O to show) ... │ │ MCP Tool Details: │ │ (press Ctrl+O to expand MCP tool details) │ │ Allow execution of MCP tool "greet" from server "mcp-fargate-python-aws"? │ │ │ │ 1. Allow once │ │ 2. Allow tool for this session │ │ 3. Allow all server tools for this session │ │ ● 4. Allow tool for all future sessions │ │ 5. No, suggest changes (esc) │ │ │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ I will call the greet tool with the argument Fargate1. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ greet (mcp-fargate-python-aws MCP Server) {"param":"Fargate1"} │ │ │ │ Fargate1 │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ OK. I've greeted Fargate1. </span></code></pre> </div> <p>Gemini CLI can also summarize the deployment:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp"> &gt;</span><span class="w"> </span>summarize the AWS Fargate deployment <span class="k">for </span>the Greet MCP tool <span class="go">✦ I will examine the Makefile and task-definition.json.template to provide a detailed summary of the AWS Fargate deployment process. ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ ReadFile Makefile │ │ │ │ │ │ ✓ ReadFile task-definition.json.template │ │ │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ The AWS Fargate deployment for the Greet MCP tool is a streamlined process managed by a Makefile and containerized via Docker. Architecture Overview * Service Type: AWS ECS with Fargate launch type (Serverless). * Networking: Uses the default VPC, subnets, and security groups with a public IP enabled. * Container Port: Runs on port 8080. * Health Checks: Integrated with ECS, performing a GET request to /health within the container. * Logging: Centralized in AWS CloudWatch Logs under the /ecs/mcp-fargate-task group. * Security: Uses the ecsTaskExecutionRole for task and execution permissions. Deployment Workflow (make deploy) 1. Infrastructure Prep: Ensures the CloudWatch log group and ECS cluster exist. 2. Containerization: Builds a Docker image using the local Dockerfile. 3. ECR Management: Authenticates with Amazon ECR, creates the repository if missing, and pushes the tagged image. 4. Task Registration: Generates a task-definition.json from a template, injecting environment variables (Account ID, ECR URI, etc.), and registers it with ECS. </span><span class="gp"> 5. Service Update/Creation: Checks if the ECS service exists;</span><span class="w"> </span><span class="k">if </span>so, it updates it to the new task definition. <span class="go"> If not, it creates a new service, automatically discovering default VPC networking settings. Key Commands * make status: Displays the current running/desired count and status of the ECS service. * make endpoint: Retrieves the public IP of the running Fargate task. * make logs: Tails real-time logs from CloudWatch. * make delete-service: Safely shuts down and deletes the Fargate service. </span></code></pre> </div> <h4> Summary </h4> <p>The strategy for using Python for MCP development with Gemini CLI on Amazon Fargate was validated with a incremental step by step approach.</p> <p>A minimal HTTP MCP Server was started from Python source code and validated with Gemini CLI running as a MCP client in the same local environment.</p> <p>This MCP server was then wrapped in a Docker container and deployed to Amazon Fargate. The local copy of Gemini CLI was used as a MCP client to validate the connection.</p> <p>This approach can be extended to more complex deployments using other MCP transports and Cloud based options.</p> python gemini aws mcpserver How agentic AI resurrected my "Old" side project Jean-Phi Baconnais Mon, 16 Mar 2026 10:27:33 +0000 https://dev.to/gde/how-agentic-ai-resurrected-my-old-side-project-31hf https://dev.to/gde/how-agentic-ai-resurrected-my-old-side-project-31hf <blockquote> <p><em>A french version of this blog post is available <a href="proxy.php?url=https://jeanphi-baconnais.gitlab.io/" rel="noopener noreferrer">on my website</a>.</em></p> </blockquote> <p>Since I started working (a few years ago), I’ve been launching GitLab projects to test tools, frameworks, build PoCs, or start projects I hope to finish. Spoiler alert: that never happens!</p> <p>However, I have one side project that is a little bit different because it concerns my family: a genealogy tree application. One of my aunts managed to trace our genealogy tree and she found people before 1800!</p> <p>To answer a question I’ve been asked several times: I decided to create this project first to have fun, test, and learn new technologies and, let’s be honest, to avoid paying for a solution that, at the time, was expensive and didn't always fit my needs. But above all, I wanted to play around and learn things.</p> <p>This project is private because it undergoes constant testing. It’s the project that introduced me to Kubernetes and deploying a cluster on Google Cloud Platform. Is there any point in having an app used by one or two people running on Kubernetes? Clearly not. Installing it on a K8s cluster on a Raspberry Pi? Not really, but it’s fun (or not 😂).</p> <p>So, it’s a personal project where the architecture often changes and undergoes my experiments. In fact, those experiments are exactly what made the project so complex and why I regularly procrastinate when it comes to making updates.</p> <h2> 🔎 Architecture details </h2> <p>The project consists of several technical blocks:</p> <p><strong>On the Frontend:</strong></p> <ul> <li>A Vue.js component to visualize the family tree. No actions possible.</li> <li>A second Vue.js component dedicated to managing the tree.</li> </ul> <p><strong>On the Backend:</strong></p> <ul> <li>A "legacy" Node.js block, consisting of a multitude of endpoints to fetch person data and calculate coordinates for links between individuals.</li> <li>A Go backend to handle "heavy" processing for all people in the tree, such as positioning.</li> <li>A Java/Quarkus backend to replace the legacy Node.js code, containing more recent features.</li> <li>A second Java/Quarkus backend, deployed on Cloud Run, which checks for birthdays daily and sends notifications.</li> </ul> <p><strong>On the Infrastructure side:</strong> the Kubernetes parts (both Cloud and Raspberry Pi) mentioned earlier no longer exist. The birthday notification component is the only one deployed in Google Cloud Platform, I’m the only user. A <code>docker-compose</code> configuration allows for quick local deployment.</p> <p>Here is a representation of the project architecture:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjeanphi-baconnais.gitlab.io%2Fimg%2F2026-side-project-revival%2F1-archi-old.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjeanphi-baconnais.gitlab.io%2Fimg%2F2026-side-project-revival%2F1-archi-old.png" alt="Old architecture" width="800" height="542"></a></p> <p>As I mentioned at the beginning of this article, many choices are intentional (and not necessarily the best, I'll grant you that! 😁). I work on this project totally randomly depending on my professional and personal context, and the admin interface clearly leaves much to be desired (CSS and I don't get along), but:</p> <ul> <li>My family gets birthday notifications.</li> <li>I’ve digitized part of my aunt’s work.</li> <li>The GCP deployment costs less than 5 euros a month.</li> </ul> <p>✅ These goals satisfy me, which explains why I invest less time in the project.</p> <h2> 💡 The Arrival of Agentic AI-Powered Dev Environments </h2> <p>The arrival of AI and AI-boosted IDEs was, for me, and I imagine many others, an opportunity to test them and change the way to develop. My favorite tool? <strong>Google Antigravity</strong>. The fact that I am a Google Developer Expert gives me the opportunity to receive updates directly via email or Google Chat and attend presentations. After testing other tools like Cursor or Claude, I am fine with Google's project.</p> <p>Before Antigravity, I was focused on IDX, which has since been integrated into <strong>Firebase Studio</strong> (I talk more about it in this article: <a href="proxy.php?url=https://dev.to/zenika/idx-becames-firebase-studio-be6">https://dev.to/zenika/idx-becames-firebase-studio-be6</a>). Firebase Studio is more focused on applications prototyping, while Antigravity is more to continue a project by positioning the developer as an orchestrator of agents.</p> <p>I’m also a big fan of <strong>GitLab Duo</strong>, which I’ve tested on some projects. A mix of GitLab Duo and Antigravity is possible (and very interesting); I give you this new article: <a href="proxy.php?url=https://dev.to/zenika/how-gilab-duo-agent-platform-antigravity-can-collaborate-to-improve-the-quality-of-our-38bm">https://dev.to/zenika/how-gilab-duo-agent-platform-antigravity-can-collaborate-to-improve-the-quality-of-our-38bm</a> </p> <h2> 🤔 Re-launching My Side Project </h2> <p>Let’s get to the point of this article: how Antigravity relaunched my side project. The project was functional, and I regularly added ancestors found by my aunt. My many attempts at graphical representations impacted the architecture, and new options required a lot of time to adapt the backend components. After several years without writing JS or Node code, their migration was not very exciting. I had migrated a few features, but it represents a few percent of the code.</p> <p>That’s where I thought Antigravity could help. I often gave it technical tasks, like migrating a Java version, reviewing my <code>docker-compose</code> files, or updating documentation. But when I thought to ask it to take over my Merge Request (MR) for migrating my Node component to Quarkus, I was blown away. </p> <p>The "skills" didn't exist yet, but after a few prompts to an agent in "Plan" mode, it proposed a plan that actually made sense. After I validated the plan, the Quarkus component was edited and completed. Of course, I had to review a few things, but it took me a few hours whereas a manual migration would have taken days.</p> <p>Why not continue? I ask Antigravity to delete the Go component and replace it with Quarkus. The code to migrate was much smaller and I have not any modification to do. Great!</p> <blockquote> <p>For me, this is where AI can really help: supporting us in tasks that are clearly less fun to do.</p> </blockquote> <p><strong>Tip:</strong> Discussing with AI agents in <strong>Plan mode</strong> ensures your request is understood and the proposal meets your expectations. If it doesn't, you can adjust it, and only once you agree do you trigger the execution. This is the principle of "AI-Driven Development."</p> <h2> 🚀 A side project re motivated in a few weeks </h2> <p>After migrating my Node and Go components, I now have fewer components, focused on a technical stack I currently use: Quarkus and Vue.js. The application is simpler, and being able to focus on new features has given me a boost to work on this project again.</p> <p>Antigravity also helped me review and harmonize the UI of the admin interface. I’ll admit, I totally trust it when it suggests style changes. Honestly, it can’t be worse than if I did it myself! 😂</p> <p>Another interesting aspect is the long discussions with the agent in "Plan" mode to challenge technical aspects like architecture, even if it's simple, to optimize certain parts or brainstorm improvements and new features.</p> <p>Here is the current architecture: </p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjeanphi-baconnais.gitlab.io%2Fimg%2F2026-side-project-revival%2F2-archi-now.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjeanphi-baconnais.gitlab.io%2Fimg%2F2026-side-project-revival%2F2-archi-now.png" alt="New architecture" width="800" height="665"></a></p> <p>Now, 60% of the project's code is in Java. Unfortunately, I don't have the stats from before this experiment, but Node.js was probably neck-and-neck with Java.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjeanphi-baconnais.gitlab.io%2Fimg%2F2026-side-project-revival%2F3-gitlab-stats.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fjeanphi-baconnais.gitlab.io%2Fimg%2F2026-side-project-revival%2F3-gitlab-stats.png" alt="New architecture" width="800" height="309"></a></p> <h2> 🔑 Key Takeaways </h2> <p>AI clearly allowed me to accelerate my side project by resolving tasks that had no real added value or didn't interest me. I’m not good at frontend, AI helped me improve that part, and it’s much more pleasant to work on a product that looks good, right? 😊 My motivation was boosted now that the migrations I started years ago are finally resolved.</p> <p>Now I’m going to focus on making the tree available to my family, and add new features like photo management.</p> <p>💡 For fans of <strong>gemini-cli</strong>, the Plan mode is now available in the version released on March 11: <a href="proxy.php?url=https://github.com/google-gemini/gemini-cli/discussions/22078" rel="noopener noreferrer">https://github.com/google-gemini/gemini-cli/discussions/22078</a> </p> ai antigravity development Building Aura: A Multimodal Smart Home Operated by Gemini Live 🌌 Karthigayan Devan Mon, 16 Mar 2026 01:42:26 +0000 https://dev.to/gde/building-aura-a-multimodal-smart-home-operated-by-gemini-live-2m31 https://dev.to/gde/building-aura-a-multimodal-smart-home-operated-by-gemini-live-2m31 <h2> 💡 The Problem with Smart Homes </h2> <p>Smart homes today are often fragmented and reactive. You speak into a puck on the wall, and it toggles a light on a screen. There is no continuous awareness. </p> <p>For the <strong>Gemini Live Agent Challenge 2026</strong>, I wanted to build something that feels <strong>alive</strong>. Inspired by futuristic sci-fi interfaces, I built <strong>Aura</strong> — a central AI operating pilot that doesn't just hear you, but <strong>sees your environment concurrently</strong> and translates that intelligence into a living, responsive Ambient Dashboard layout natively.</p> <h2> 🚀 What is Aura? </h2> <p><strong>Aura</strong> is a fully multimodal smart home operating system utilizing <strong>bidirectional WebSockets</strong> over continuous, low-latency backpressure limits. </p> <p>Unlike previous generations of voice assistants that rely on turn-taking (Speech-to-Text ➔ LLM ➔ Text-to-Speech), Aura streams <strong>continuous raw audio and webcam frames</strong> concurrently using the <code>google/genai</code> Node SDK. </p> <h2> 🛠️ The Architecture </h2> <p>I engineered a decoupled <strong>reactive container pipeline</strong> deployed on <strong>Google Cloud Run</strong>:</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1kifhxh682a8iszbdy9.png" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1kifhxh682a8iszbdy9.png" alt=" " width="800" height="258"></a></p> <h2> ⚡ Secret Sauce: Native Visual Concurrency </h2> <p>The biggest challenge I ran into was translating standard 16:9 webcam buffers onto square visual grids without distorting the frame aspect ratio. AI can hallucinate if you squash the context!</p> <p>I fixed this by injecting a continuous Canvas Context buffer scaling calculation on every local-exec push:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight javascript"><code><span class="c1">// Quick glimpse at the frontend scaling preserving 1:1 ratios</span> <span class="kd">const</span> <span class="nx">scale</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nf">min</span><span class="p">(</span><span class="mi">600</span> <span class="o">/</span> <span class="nx">video</span><span class="p">.</span><span class="nx">videoWidth</span><span class="p">,</span> <span class="mi">600</span> <span class="o">/</span> <span class="nx">video</span><span class="p">.</span><span class="nx">videoHeight</span><span class="p">);</span> <span class="kd">const</span> <span class="nx">x</span> <span class="o">=</span> <span class="p">(</span><span class="mi">600</span> <span class="o">-</span> <span class="nx">video</span><span class="p">.</span><span class="nx">videoWidth</span> <span class="o">*</span> <span class="nx">scale</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="kd">const</span> <span class="nx">y</span> <span class="o">=</span> <span class="p">(</span><span class="mi">600</span> <span class="o">-</span> <span class="nx">video</span><span class="p">.</span><span class="nx">videoHeight</span> <span class="o">*</span> <span class="nx">scale</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="nx">ctx</span><span class="p">.</span><span class="nf">drawImage</span><span class="p">(</span><span class="nx">video</span><span class="p">,</span> <span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">,</span> <span class="nx">video</span><span class="p">.</span><span class="nx">videoWidth</span> <span class="o">*</span> <span class="nx">scale</span><span class="p">,</span> <span class="nx">video</span><span class="p">.</span><span class="nx">videoHeight</span> <span class="o">*</span> <span class="nx">scale</span><span class="p">);</span> </code></pre> </div> <h2> 🚨 Visual Ambient States (The "Wow" Factor) </h2> <p>Dashboard views shouldn't just list data. When Aura triggers a smart decision, the full Chrome viewport adapts natively using CSS Variable Overrides:</p> <ul> <li>💡 .lights-off (Ambient Dimming): Absolute viewport drop-shadow shading to deep #06080E with neon frame glowing edges securely.</li> <li>🚨 .emergency-global (Strobe Alerting): Repeating red and white absolute background flashes demanded continuous viewer security attention.</li> <li>🌡️ Thermal Card Shadings: Thermostats pulse with continuous Amber shadings overlays strictly enforcing accurate contextual reading gradients safely.</li> </ul> <p>🎥 Check out the Demo Video!<br> <a href="proxy.php?url=https://www.youtube.com/watch?v=Vm2iGpAuexQ" rel="noopener noreferrer">https://www.youtube.com/watch?v=Vm2iGpAuexQ</a></p> <h2> 📂 Source Code </h2> <p>The code is 100% open-weight and available on GitHub: 👉 <a href="proxy.php?url=https://github.com/karthidec/gemini-agent-challenge.git" rel="noopener noreferrer">https://github.com/karthidec/gemini-agent-challenge.git</a></p> <h2> ⚠️ Contest Disclaimer </h2> <p>This project is an entry for the Google Gemini Live Agent Challenge 2026. Explicitly leveraging @google/genai continuous WebSocket routing modules.</p> <p>What do you think of this continuous audio/vision ambient approach for smart environments? Let me know in the comments below! 🌌✨</p> geminiliveagentchallenge googlecloud gemini discuss MCP Development with Amazon App Runner and Gemini CLI xbill Sun, 15 Mar 2026 19:38:58 +0000 https://dev.to/gde/mcp-development-with-amazon-app-runner-and-gemini-cli-3pb https://dev.to/gde/mcp-development-with-amazon-app-runner-and-gemini-cli-3pb <p>Leveraging Gemini CLI and the underlying Gemini LLM to build Model Context Protocol (MCP) AI applications with Python from a local development environment deployed to the App Runner container service on AWS.</p> <p><a href="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuuc80pt2b7foswcdl27l.jpeg" class="article-body-image-wrapper"><img src="proxy.php?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuuc80pt2b7foswcdl27l.jpeg" width="800" height="436"></a></p> <h4> Aren’t There a Billion Python MCP Demos? </h4> <p>Yes there are.</p> <p>Python has traditionally been the main coding language for ML and AI tools. The goal of this article is to provide a minimal viable basic working MCP stdio server that can be run locally without any unneeded extra code or extensions.</p> <h4> What Is Python? </h4> <p>Python is an interpreted language that allows for rapid development and testing and has deep libraries for working with ML and AI:</p> <p><a href="proxy.php?url=https://www.python.org/" rel="noopener noreferrer">Welcome to Python.org</a></p> <h4> Python Version Management </h4> <p>One of the downsides of the wide deployment of Python has been managing the language versions across platforms and maintaining a supported version.</p> <p>The <strong>pyenv</strong> tool enables deploying consistent versions of Python:</p> <p><a href="proxy.php?url=https://github.com/pyenv/pyenv" rel="noopener noreferrer">GitHub - pyenv/pyenv: Simple Python version management</a></p> <p>As of writing — the mainstream python version is 3.13. To validate your current Python:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">admin@ip-172-31-70-211:~/gemini-cli-aws/mcp-lightsail-python-aws$</span><span class="w"> </span>python <span class="nt">--version</span> <span class="go">Python 3.13.12 </span></code></pre> </div> <h4> Gemini CLI </h4> <p>If not pre-installed you can download the Gemini CLI to interact with the source files and provide real-time assistance:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code>npm <span class="nb">install</span> <span class="nt">-g</span> @google/gemini-cli </code></pre> </div> <h4> Testing the Gemini CLI Environment </h4> <p>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:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="go">gemini </span><span class="gp">admin@ip-172-31-70-211:~/gemini-cli-aws/mcp-apprunner-python-aws$</span><span class="w"> </span>gemini <span class="go"> ▝▜▄ Gemini CLI v0.33.1 ▝▜▄ ▗▟▀ Logged in with Google /auth ▝▀ Gemini Code Assist Standard /upgrade ? for shortcuts ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── shift+tab to accept edits 3 GEMINI.md files | 1 MCP server ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── </span><span class="gp"> &gt;</span><span class="w"> </span>Type your message or @path/to/file <span class="go">────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── ~/.../mcp-apprunner-python-aws (main*) no sandbox (see /docs) /model Auto (Gemini 3) | 239.8 MB </span></code></pre> </div> <h4> Node Version Management </h4> <p>Gemini CLI needs a consistent, up to date version of Node. The <strong>nvm</strong> command can be used to get a standard Node environment:</p> <p><a href="proxy.php?url=https://github.com/nvm-sh/nvm" rel="noopener noreferrer">GitHub - nvm-sh/nvm: Node Version Manager - POSIX-compliant bash script to manage multiple active node.js versions</a></p> <h4> Python MCP Documentation </h4> <p>The official GitHub Repo provides samples and documentation for getting started:</p> <p><a href="proxy.php?url=https://github.com/modelcontextprotocol/python-sdk" rel="noopener noreferrer">GitHub - modelcontextprotocol/python-sdk: The official Python SDK for Model Context Protocol servers and clients</a></p> <p>The most common MCP Python deployment path uses the FASTMCP library:</p> <p><a href="proxy.php?url=https://gofastmcp.com/getting-started/welcome" rel="noopener noreferrer">Welcome to FastMCP - FastMCP</a></p> <h4> Docker Version Management </h4> <p>The AWS Cli tools and Lightsail extensions need current version of Docker. If your environment does not provide a recent docker tool- the Docker Version Manager can be used to downlaod the latest supported Docker:</p> <p><a href="proxy.php?url=https://howtowhale.github.io/dvm/install.html" rel="noopener noreferrer">Install</a></p> <h4> Amazon App Runner </h4> <p>Amazon App Runner provides a hosted container server. More information is available on the official site here:</p> <p><a href="proxy.php?url=https://aws.amazon.com/apprunner/" rel="noopener noreferrer">Managed Container Apps Service - AWS App Runner - AWS</a></p> <p>And this is the direct URL to the console:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>https://us-east-1.console.aws.amazon.com/apprunner/home?region=us-east-1#/services </code></pre> </div> <h4> AWS CLI </h4> <p>The AWS CLI provides a command line tool to directly access AWS services from your current environment. Full details on the CLI are available here:</p> <p><a href="proxy.php?url=https://docs.aws.amazon.com/lightsail/latest/userguide/amazon-lightsail-install-software.html" rel="noopener noreferrer">Install Docker, AWS CLI, and the Lightsail Control plugin for containers</a></p> <h4> Where do I start? </h4> <p>The strategy for starting MCP development is a incremental step by step approach.</p> <p>First, the basic development environment is setup with the required system variables, and a working Gemini CLI configuration.</p> <p>Then, a minimal Hello World Style Python MCP Server is built with HTTP transport. This server is validated with Gemini CLI in the local environment.</p> <p>This setup validates the connection from Gemini CLI to the local process via MCP. The MCP client (Gemini CLI) and the Python MCP server both run in the same local environment.</p> <p>Next- the MCP server is wrapped in a container with docker and deployed to Amazon Lightsail. This remote deployment is validated with Gemini CLI running as a MCP client.</p> <h4> Setup the Basic Environment </h4> <p>At this point you should have a working Python interpreter and a working Gemini CLI installation. The next step is to clone the GitHub samples repository with support scripts:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd</span> ~ git clone https://github.com/xbill9/gemini-cli-aws </code></pre> </div> <p>Then run <strong>init.sh</strong> from the cloned directory.</p> <p>The script will attempt to determine your shell environment and set the correct variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd </span>gemini-cli-aws <span class="nb">source </span>init.sh </code></pre> </div> <p>If your session times out or you need to re-authenticate- you can run the <strong>set_env.sh</strong> script to reset your environment variables:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd </span>gemini-cli-aws <span class="nb">source </span>set_env.sh </code></pre> </div> <p>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.</p> <h4> Hello World with HTTP Transport </h4> <p>One of the key features that the standard MCP libraries provide is abstracting various transport methods.</p> <p>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.</p> <p>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.</p> <p>The HTTP transport allows the MCP client and server to run in the same environment or distributed over the Internet.</p> <p>The connection over HTTP will look similar to this:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight python"><code><span class="n">mcp</span><span class="p">.</span><span class="nf">run</span><span class="p">(</span> <span class="n">transport</span><span class="o">=</span><span class="sh">"</span><span class="s">http</span><span class="sh">"</span><span class="p">,</span> <span class="n">host</span><span class="o">=</span><span class="sh">"</span><span class="s">0.0.0.0</span><span class="sh">"</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="n">port</span><span class="p">,</span> <span class="p">)</span> </code></pre> </div> <h4> Running the Python Code </h4> <p>First- switch the directory with the Python MCP sample code:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight shell"><code><span class="nb">cd</span> ~/gemini-cli-aws/mcp-apprunner-python-aws </code></pre> </div> <p>Refresh the AWS credentials:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-apprunner-python-aws$</span><span class="w"> </span>aws login <span class="nt">--remote</span> <span class="go">Browser will not be automatically opened. </span><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-apprunner-python-aws$</span><span class="w"> </span><span class="nb">source </span>save-aws-creds.sh <span class="go">Exporting AWS credentials... Successfully saved credentials to .aws_creds The Makefile will now automatically use these for deployments. </span><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-apprunner-python-aws$</span><span class="w"> </span></code></pre> </div> <p>Run the deploy version on the local system:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-apprunner-python-aws$</span><span class="w"> </span>make deploy <span class="go">Ensuring IAM role AppRunnerECRAccessRole exists... Checking if ECR repository exists... Logging in to Amazon ECR... 0.0s </span></code></pre> </div> <p>You can validate the final result by checking the messages:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight json"><code><span class="err">Deploying</span><span class="w"> </span><span class="err">to</span><span class="w"> </span><span class="err">App</span><span class="w"> </span><span class="err">Runner...</span><span class="w"> </span><span class="err">Updating</span><span class="w"> </span><span class="err">existing</span><span class="w"> </span><span class="err">App</span><span class="w"> </span><span class="err">Runner</span><span class="w"> </span><span class="err">service</span><span class="w"> </span><span class="err">with</span><span class="w"> </span><span class="err">ARN</span><span class="w"> </span><span class="err">arn:aws:apprunner:us-east</span><span class="mi">-1</span><span class="err">:</span><span class="mi">106059658660</span><span class="err">:service/mcp-apprunner-python-aws/</span><span class="mi">5</span><span class="err">d</span><span class="mi">3</span><span class="err">b</span><span class="mi">4</span><span class="err">b</span><span class="mi">6570</span><span class="err">c</span><span class="mi">14e7884</span><span class="err">b</span><span class="mi">62433163</span><span class="err">b</span><span class="mi">3</span><span class="err">bf</span><span class="mi">2</span><span class="err">...</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"Service"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"ServiceName"</span><span class="p">:</span><span class="w"> </span><span class="s2">"mcp-apprunner-python-aws"</span><span class="p">,</span><span class="w"> </span><span class="nl">"ServiceId"</span><span class="p">:</span><span class="w"> </span><span class="s2">"5d3b4b6570c14e7884b62433163b3bf2"</span><span class="p">,</span><span class="w"> </span><span class="nl">"ServiceArn"</span><span class="p">:</span><span class="w"> </span><span class="s2">"arn:aws:apprunner:us-east-1:106059658660:service/mcp-apprunner-python-aws/5d3b4b6570c14e7884b62433163b3bf2"</span><span class="p">,</span><span class="w"> </span><span class="nl">"ServiceUrl"</span><span class="p">:</span><span class="w"> </span><span class="s2">"mjpa3argby.us-east-1.awsapprunner.com"</span><span class="p">,</span><span class="w"> </span><span class="nl">"CreatedAt"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2026-03-14T14:26:27-04:00"</span><span class="p">,</span><span class="w"> </span><span class="nl">"UpdatedAt"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2026-03-14T14:26:27-04:00"</span><span class="p">,</span><span class="w"> </span><span class="nl">"Status"</span><span class="p">:</span><span class="w"> </span><span class="s2">"RUNNING"</span><span class="p">,</span><span class="w"> </span></code></pre> </div> <p>Once the container is deployed:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-apprunner-python-aws$</span><span class="w"> </span>make status <span class="go">Checking AWS App Runner service status for mcp-apprunner-python-aws... ---------------------------------------------------------------------------------- | ListServices | +---------------------------+----------+-----------------------------------------+ | Name | Status | URL | +---------------------------+----------+-----------------------------------------+ | mcp-apprunner-python-aws | RUNNING | mjpa3argby.us-east-1.awsapprunner.com | +---------------------------+----------+-----------------------------------------+ </span><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-apprunner-python-aws$</span><span class="w"> </span></code></pre> </div> <p>You can then get the endpoint:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-apprunner-python-aws$</span><span class="w"> </span>make endpoint <span class="go">mjpa3argby.us-east-1.awsapprunner.com </span><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-apprunner-python-aws$</span><span class="w"> </span></code></pre> </div> <h4> Gemini CLI settings.json </h4> <p>Once you have the deployed endpoint — update the Gemini CLI MCP settings:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight json"><code><span class="p">{</span><span class="w"> </span><span class="nl">"mcpServers"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"aws-apprunner-python"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"httpUrl"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://mjpa3argby.us-east-1.awsapprunner.com/mcp"</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span><span class="w"> </span></code></pre> </div> <h4> Remote MCP Server Testing </h4> <p>Restart Gemini CLI and check for the new MCP tools:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp">xbill@penguin:~/gemini-cli-aws/mcp-apprunner-python-aws$</span><span class="w"> </span>gemini <span class="go"> </span><span class="gp"> &gt;</span><span class="w"> </span>/mcp list <span class="go">Configured MCP servers: 🟢 aws-apprunner-python - Ready (1 tool) Tools: - mcp_aws-apprunner-python_greet </span></code></pre> </div> <p>Then the remote MCP tool in App Runner can be called:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight console"><code><span class="gp"> &gt;</span><span class="w"> </span>greet App Runner! <span class="go">✦ I will use the mcp_aws-apprunner-python_greet tool to send a greeting to the App Runner service. ✕ MCP ERROR (aws-apprunner-python) ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ Action Required │ │ │ │ ? greet (aws-apprunner-python MCP Server) {"param":"App Runner!"} │ │ │ │ ... first 4 lines hidden (Ctrl+O to show) ... │ │ (press Ctrl+O to expand MCP tool details) │ │ Allow execution of MCP tool "greet" from server "aws-apprunner-python"? │ │ │ │ 1. Allow once │ │ 2. Allow tool for this session │ │ 3. Allow all server tools for this session │ │ ● 4. Allow tool for all future sessions │ │ 5. No, suggest changes (esc) │ │ │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ ✓ greet (aws-apprunner-python MCP Server) {"param":"App Runner!"} │ │ │ │ App Runner! │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ✦ The App Runner service has been greeted with "App Runner!". </span></code></pre> </div> <p>Gemini CLI can also summarize the deployment:<br> </p> <div class="highlight js-code-highlight"> <pre class="highlight plaintext"><code>&gt; summarize the AWS app runner deployment ✦ The AWS App Runner deployment for this project is a containerized Python application (an MCP server) managed through a Makefile. Here is a summary of the deployment architecture and workflow: Deployment Architecture * Service: AWS App Runner (a fully managed service for deploying containerized web applications). * Container Registry: Amazon ECR (Elastic Container Registry) stores the application images. * IAM Role: Uses AppRunnerECRAccessRole to grant App Runner permission to pull images from ECR. * Configuration: The service is configured to run on port 8080 with an HTTP health check at /health. Deployment Workflow (make deploy) 1. IAM Setup: Ensures the necessary access roles exist. 2. Build &amp; Registry: * Checks for/creates the ECR repository. * Builds the Docker image locally from the Dockerfile. * Authenticates with ECR and pushes the image tagged as latest. 3. Service Provisioning: * If the service doesn't exist, it creates a new App Runner service pointing to the ECR image. * If it already exists, it updates the service to deploy the new image. Management Commands * make status: Displays the current deployment status and public URL. * make endpoint: Retrieves the public service URL directly. * make apprunner-status: Specifically queries the AWS API for the service's current state (e.g., RUNNING, OPERATION_IN_PROGRESS). </code></pre> </div> <h4> Summary </h4> <p>The strategy for using Python for MCP development with Gemini CLI on Amazon App Runner was validated with a incremental step by step approach.</p> <p>A minimal HTTP transport MCP Server was started from Python source code and validated with Gemini CLI running as a MCP client in the same local environment.</p> <p>This MCP server was then wrapped in a Docker container and deployed to Amazon App Runner. The local copy of Gemini CLI was used as a MCP client to validate the connection.</p> <p>This approach can be extended to more complex deployments using other MCP transports and Cloud based options.</p> python aws mcps apprunner