Local MCP Development with Zig and Gemini CLI

Published: (January 31, 2026 at 11:10 AM EST)
5 min read
Source: Dev.to

Source: Dev.to

Overview

  • Python has traditionally dominated ML/AI tooling, but the MCP protocol is language‑agnostic.
  • This guide shows how to use Zig—a modern, open‑source systems language—as the development language for MCP.
  • You’ll end up with a tiny “Hello World”‑style Zig MCP server that communicates with Gemini CLI over stdio.

Resources

ResourceDescription
ZigMCP libraryComprehensive MCP library for Zig
Zig home page
Debian Zig install guide
Gemini CLI (npm)npm install -g @google/gemini-cli
Node Version Manager (nvm)
MCP Zig docs & samples

Prerequisites

  1. Zig (latest stable) – install via your OS package manager or the Debian guide above.

  2. Node.js – a recent, up‑to‑date version. Use nvm to manage it:

    # Install nvm (if not already present)
    curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
    # Load nvm and install Node LTS
    source ~/.bashrc   # or ~/.zshrc
    nvm install --lts
  3. Gemini CLI – install globally with npm:

    npm install -g @google/gemini-cli
  4. Authentication – run gemini once to log in with a Google account or API key.

Setting Up the Development Environment

# Clone the helper repository (contains init scripts and sample code)
cd ~
git clone https://github.com/xbill9/gemini-cli-codeassist
cd gemini-cli-codeassist

# Initialise environment variables for your shell
source init.sh

If your session expires or you need to re‑authenticate later:

source set_env.sh   # resets PROJECT_ID, credentials, etc.

Building the Minimal MCP stdio Server

1. Create the Zig project

The sample project lives under gemini-cli-codeassist/mcp-stdio-zig.
Navigate there and run the default Make target:

cd mcp-stdio-zig
make          # runs `zig build`

You should see something like:

Linked zig-out/bin/mcp-stdio-zig to server

2. Source code highlights

// src/main.zig
const std = @import("std");
const mcp = @import("mcp");

// Run the server using stdio transport
try server.run(.{ .stdio = {} });

The server imports the standard Zig library (std) and the MCP library (mcp), then starts a stdio‑based MCP server.

3. Lint / format

make lint
# → zig fmt --check .
# → zig build -Doptimize=ReleaseFast

4. Test the server

make test
# Output (truncated):
# Testing 'greet' tool...
# ✓ initialize successful
# ✓ notifications/initialized sent
# ✓ tools/list successful
# ✓ tools/call (greet) successful
# All tests passed!

The test harness (python3 test_server.py) validates the greet tool.

Registering the Server with Gemini CLI

Add an entry to ~/.config/gemini-cli/settings.json (or the default location):

{
  "mcpServers": {
    "mcp-stdio-zig": {
      "command": "$HOME/gemini-cli-codeassist/mcp-stdio-zig/server"
    }
  }
}

Restart Gemini CLI to pick up the new configuration.

Using the MCP Server

# Start a Gemini CLI session
gemini
> /mcp schema

Configured MCP servers:

🟢 mcp-stdio-zig - Ready (1 tool)
  Tools:
  - greet
    Get a greeting from a local stdio server.
    Parameters:
    {
      "type": "object"
    }

Now invoke the tool:

> greet Carmen!

✦ I will read the src/main.zig file to understand how the greet tool is implemented and what parameters it expects.
╭─────────────────────────────────────────────────────────────────────╮
│ ✓ ReadFile src/main.zig                                            │
╰─────────────────────────────────────────────────────────────────────╯

The server responds with the greeting, confirming that the MCP stdio transport works end‑to‑end.

Recap & Next Steps

  1. Environment – Zig, Node (via nvm), Gemini CLI installed and authenticated.
  2. Server – Minimal Zig MCP stdio server compiled and tested.
  3. Integration – Registered with Gemini CLI, verified via /mcp schema and a tool call.

From here you can:

  • Add more MCP tools (e.g., summarize, translate).
  • Switch to other transports (TCP, WebSocket) using the same high‑level MCP API.
  • Embed the Gemini LLM directly into Zig code for tighter integration.

Happy coding! 🚀

MCP Tools Extension – Summary

1️⃣ Greeting Test

Command

✦ I will call the greet tool with the parameter param set to "Carmen!".

Tool Invocation

✓ greet (mcp-stdio-zig MCP Server) {"param":"Carmen!"}

Result

Carmen!

Note: The tool returned “Carmen!”, confirming that the basic MCP functionality works.

2️⃣ Adding New MCP Tools

The Zig project was extended with three new tools:

ToolPurpose
zig-infoReturns Zig version, OS, and architecture
server-infoReturns server name and version
current-timeReturns the current system timestamp

Code Diff (added to src/main.zig)

+ fn serverInfoHandler(allocator: std.mem.Allocator, _: ?std.json.Value) mcp.tools.ToolError!mcp.tools.ToolResult {
+     logInfo("Executed server-info tool");
+
+     const info = "Server: mcp-stdio-zig, Version: 0.1.0";
+     var items = allocator.alloc(mcp.types.ContentItem, 1) catch return mcp.tools.ToolError.OutOfMemory;
+     items[0] = .{ .text = .{ .text = try allocator.dupe(u8, info) } };
+
+     return mcp.tools.ToolResult{
+         .content = items,
+         .is_error = false,
+     };
+ }

The changes were committed, and the new tools were verified.

3️⃣ Build & List Tools

xbill@penguin:~/gemini-cli-codeassist/mcp-stdio-zig$ make
zig build
Linked zig-out/bin/mcp-stdio-zig to server

List Available MCP Tools

/mcp list

Configured MCP servers:

🟢 mcp-stdio-zig - Ready (4 tools)
  Tools:
  - current-time
  - greet
  - server-info
  - zig-info

4️⃣ Running the New Tools

current-time

✓ current-time (mcp-stdio-zig MCP Server) {}
Timestamp: 1769875173

zig-info

✓ zig-info (mcp-stdio-zig MCP Server) {}
Zig Version: 0.15.2, OS: linux, Arch: x86_64

Result: Confirmed you are running Zig 0.15.2 on Linux x86_64.

server-info

✓ server-info (mcp-stdio-zig MCP Server) {}
Server: mcp-stdio-zig, Version: 0.1.0

Result: Confirmed the server name and version.

5️⃣ Summarizing the Zig Environment

Using the MCP tools and the codebase:

✓ ReadFile src/main.zig
✓ ReadFile build.zig
✓ ReadFile build.zig.zon

Summary

  • Zig Version: 0.15.2
  • Operating System: Linux (x86_64)
  • MCP Server: mcp-stdio-zig (v0.1.0)
  • Primary Dependency: mcp.zig (v0.0.1) – a Model Context Protocol implementation for Zig.
  • Communication: Standard Input/Output (stdio) with structured JSON logging to stderr.
  • Exposed Tools:
    • greet – Returns a greeting (parameterized).
    • zig-info – Reports Zig version, OS, and architecture.
    • server-info – Returns server name and version.
    • current-time – Provides the current system timestamp.

6️⃣ The Ultimate Showdown: Ferris vs. Carmen

Google Search (for context)

✓ GoogleSearch Searching the web for: "who is carmen programming language mascot"
Search results for "who is carmen programming language mascot" returned.

Result

In a hypothetical smack‑down between Ferris the Rust Crab and Carmen the Zig Allocgator, we get a battle of Safety vs. Control.

Tale of the Tape

ContestantSignature MoveDefenseWeakness
🦀 Ferris (Rust)“Borrow Checker” (Hold) – you can’t move data until it’s proven safe.Very high – the type system makes memory corruption nearly impossible.Long compile times; slower to get ready for the fight.
🐊 Carmen (Zig)“Defer Deinit” (Death Roll) – resources are cleaned up when you explicitly tell her.High – manual control gives power but requires discipline.Requires explicit management; mistakes can lead to leaks or crashes.

Bottom line: Ferris brings ironclad safety, while Carmen offers fine‑grained control. The winner depends on whether you value guaranteed safety (Rust) or deterministic, low‑overhead control (Zig).

Using Zig with MCP Development (Gemini CLI)

The strategy for using Zig with MCP development via the Gemini CLI was validated with an incremental, step‑by‑step approach:

  1. A minimal stdio transport MCP server was started from Zig source code and validated with the Gemini CLI running as an MCP client in the same local environment.
  2. The Gemini CLI was then used to extend the sample Zig code with several MCP tools and to use these tools inside the context for the underlying LLM.
Back to Blog

Related posts

Read more »

New Site For The Old Minimalist

Overview I’m a developer who believes that the ability to build whatever you can imagine is one of the greatest privileges in the world. For me, development is...