Leveraging Gemini CLI and the underlying Gemini LLM to build Model Context Protocol (MCP) AI applications with the Lisp language in a local development environment.
Why not just use Python?
Python has traditionally been the main coding language for ML and AI tools. One of the strengths of the MCP protocol is that the actual implementation details are independent of the development language. The reality is that not every project is coded in Python- and MCP allows you to use the latest AI approaches with other coding languages.
LISP? That Alien Programming Language works with MCP?
The goal of this article is to provide a minimal viable basic working MCP stdio server in LISP that can be run locally without any unneeded extra code or extensions.
Not a fan of functional programming?
It takes all kinds. The bottom line is different strokes for different folks and the tools can meet you where you are. The Internet has gotten over the Emacs vs Vi flame wars.
Lisp Native MCP Library
There are several available Lisp libraries in GitHub. The Lisp MCP library used in this demo/article is here:
What Is Lisp?
Lisp (historically LISP) is a family of programming languages that is the second-oldest high-level language still in widespread use (after Fortran), known for its unique syntax where both code and data are represented as lists. Its name is an acronym for โLISt Processingโ.
Official Common Lisp Site
There are a few sites with Lisp resources. This site is a good starting point:
Installing Lisp
Lisp comes with a whole eco-system including tooling, utilities, and build management.
There are a few common interpreters. For ease of installationโโโthe Steel Bank Common Lisp variant was used:
This tool comes standard in most Linux distributions. For a basic Debian 12 installation:
sudo apt-get update
sudo apt-get install sbcl
Then check the installation:
xbill@penguin:~$ sbcl --version
SBCL 2.2.9.debian
Lisp Eco-System
The main components of the Lisp eco-system include:
ASDF
ASDF provides a basic build manager and tooling for Lisp:
ASDF - Another System Definition Facility
Quicklisp
Quicklisp allows for automated setup and configuration for your Lisp packages:
Gemini CLI
If not pre-installed you can download the Gemini CLI to interact with the source files and provide real-time assistance:
npm install -g @google/gemini-cli
Testing the Gemini CLI Environment
Once you have all the tools and the correct Node.js version in place- you can test the startup of Gemini CLI. You will need to authenticate with a Key or your Google Account:
gemini
Node Version Management
Gemini CLI needs a consistent, up to date version of Node. The nvm command can be used to get a standard Node environment:
Lisp MCP Documentation
The official MCP Lisp page provides samples and documentation for getting started:
mcp/docs at master ยท 40ants/mcp
Where do I start?
The strategy for starting MCP development is a incremental step by step approach.
First, the basic development environment is setup with the required system variables, and a working Gemini CLI configuration.
Then, a minimal Hello World Style Lisp MCP Server is built with stdio transport. This server is validated with Gemini CLI in the local environment.
This setup validates the connection from Gemini CLI to the local process via MCP. The MCP client (Gemini CLI) and the MCP server both run in the same local environment.
Next- the basic MCP server is extended with Gemini CLI to add several new tools in standard code.
Setup the Basic Environment
At this point you should have a working C build environment, Lisp tools, and a working Gemini CLI installation. The next step is to clone the GitHub samples repository with support scripts:
cd ~
git clone https://github.com/xbill9/gemini-cli-codeassist
Then run init.sh from the cloned directory.
The script will attempt to determine your shell environment and set the correct variables:
cd gemini-cli-codeassist
source init.sh
If your session times out or you need to re-authenticate- you can run the set_env.sh script to reset your environment variables:
cd gemini-cli-codeassist
source set_env.sh
Variables like PROJECT_ID need to be setup for use in the various build scripts- so the set_env script can be used to reset the environment if you time-out.
Hello World with STDIO Transport
One of the key features that the standard MCP libraries provide is abstracting various transport methods.
The high level MCP tool implementation is the same no matter what low level transport channel/method that the MCP Client uses to connect to a MCP Server.
The simplest transport that the SDK supports is the stdio (stdio/stdout) transportโโโwhich connects a locally running process. Both the MCP client and MCP Server must be running in the same environment.
The connection over stdio will look similar to this:
(in-package :40ants-mcp/server/api/tools/list)
(defun make-tool-description-for-method (method-name method-info)
(multiple-value-bind (params required)
Lisp Package Information
The code depends on several standard libraries for MCP and logging:
(defpackage :mcp-server
(:use :cl)
(:import-from :40ants-mcp/tools
:define-tool)
(:import-from :40ants-mcp/server/definition
:start-server
:mcp-server)
(:export :main
:get-greeting))
Installing and Running the Code
Run the install make release target on the local system:
xbill@penguin:~/gemini-cli-codeassist/mcp-stdio-lisp$ make deps
2 dists to check.
You already have the latest version of "quicklisp": 2026-01-01.
You already have the latest version of "ultralisp": 20260118004500.
To load "jsonrpc":
Load 1 ASDF system:
jsonrpc
; Loading "jsonrpc"
.
To load "40ants-mcp":
Load 1 ASDF system:
40ants-mcp
; Loading "40ants-mcp"
..................................................
......
To load "serapeum":
Load 1 ASDF system:
serapeum
; Loading "serapeum"
To load "yason":
Load 1 ASDF system:
yason
; Loading "yason"
To load "local-time":
Load 1 ASDF system:
local-time
; Loading "local-time"
Dependencies installed successfully.
A binary is generated at the end of the process:
xbill@penguin:~/gemini-cli-codeassist/mcp-stdio-lisp$ make
Building mcp-server...
Loading Quicklisp...
Loading system definition...
Loading system...
To load "mcp-stdio-lisp":
Load 1 ASDF system:
mcp-stdio-lisp
; Loading "mcp-stdio-lisp"
..................................................
........
Building binary mcp-server...
compressed 32768 bytes into 555 at level 9
compressed 59539456 bytes into 10259675 at level 9
compressed 23461888 bytes into 4559702 at level 9
compressed 2785280 bytes into 691150 at level 9
compressed 22806528 bytes into 5491627 at level 9
To test the code:
xbill@penguin:~/gemini-cli-codeassist/mcp-stdio-lisp$ make test
To load "mcp-stdio-lisp/tests":
Load 1 ASDF system:
mcp-stdio-lisp/tests
; Loading "mcp-stdio-lisp/tests"
..................................................
........
Testing System mcp-stdio-lisp/tests
;; testing 'mcp-server-tests'
test-greeting
should return a valid greeting
โ Expect (STRING= (GET-GREETING "World") "Hello, World!") to be true.
โ Expect (STRING= (GET-GREETING "Lisp") "Hello, Lisp!") to be true.
โ 1 test completed
Summary:
All 1 test passed.
Gemini CLI settings.json
In this exampleโโโthe Lisp source code uses a compiled binary that can be called directly from Gemini CLI.
The default Gemini CLI settings.json has an entry for the source:
{
"mcpServers": {
"mcp-stdio-lisp": {
"command": "$HOME/gemini-cli-codeassist/mcp-stdio-lisp/mcp-server"
}
}
}
Validation with Gemini CLI
Finally- Gemini CLI is restarted and the MCP connection over stdio to the Code is validated, The full Gemini CLI Session will start:
> /mcp list
Configured MCP servers:
๐ข mcp-stdio-lisp - Ready (2 tools)
Tools:
- add
- greet
> greet Weird Alien!
โฆ I'll call the greet tool with "Weird Alien!" as requested.
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ ? greet (mcp-stdio-lisp MCP Server) {"param":"Weird Alien!"} โ โ
โ โ
โ MCP Server: mcp-stdio-lisp โ
โ Tool: greet โ
โ โ
โ Allow execution of MCP tool "greet" from server "mcp-stdio-lisp"? โ
โ โ
โ 1. Allow once โ
โ 2. Allow tool for this session โ
โ โ 3. Allow all server tools for this session โ
โ 4. No, suggest changes (esc) โ
โ โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ โ greet (mcp-stdio-lisp MCP Server) {"param":"Weird Alien!"} โ
โ โ
โ Hello, Weird Alien!! โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โฆ Hello, Weird Alien!!
> add 2 4
โฆ I'll call the add tool to compute the sum of 2 and 4.
โ ด Pre-heating the servers... (esc to cancel, 2s)
2 GEMINI.md files | 1 MCP server
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ > Type your message or @path/to/file โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
~/.../mcp-stdio-lisp (main*) no sandbox (see /docs) Auto (Gemini 3) /model
<INFO> [15:47:41] 40ants-mcp/stdio-transport stdio-transport.lisp (receive-message stdio-transport form-fun-20) -
RECEIVED: {"method":"tools/call","params":{"name":"add","arguments":{"a":2,"b":4}},"jsonrpc":"2.0","id":3}
<INFO> [15:47:41] 40ants-mcp/server/definition definition.lisp (handle-message) -
โฆ I'll call the add tool to compute the sum of 2 and 4.
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ โ add (mcp-stdio-lisp MCP Server) {"a":2,"b":4} โ
โ โ
โ The sum of 2 and 4 is: 6 โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โฆ The sum of 2 and 4 is: 6
Extending the MCP Server with Gemini CLI
Now that the basic MCP functionality has been tested and verified with Gemini CLI- the C server code can be extended with new MCP tools:
> with the Lisp project add new MCP tools -
one that gets detailled Lisp system information,
one that gets server information
one that generates a Lisp Koan
and one that demonstrates a symbolic AI algorithm
Gemini CLI will get right to work:
โ 161 + (define-tool (user-tools symbolic-differentiate) (expression variable) โ
โ 162 + (:summary "Demonstrates symbolic differentiation (AI). Input a Lisp math expression (e.g. '(+ (* 3 x) 5)') and a variable (e.g. 'x' โ
โ ).") โ
โ 163 + (:param expression string "The math expression in Lisp prefix notation.") โ
โ 164 + (:param variable string "The variable to differentiate with respect to.") โ
โ 165 + (:result (serapeum:soft-list-of 40ants-mcp/content/text:text-content)) โ
โ 166 + (let* ((*read-eval* nil) โ
โ 167 + (expr (read-from-string expression)) โ
โ 168 + (var (read-from-string variable)) โ
โ 169 + (result (deriv expr var))) โ
โ 170 + (list (make-instance '40ants-mcp/content/text:text-content โ
โ 171 + :text (format nil "Derivative of ~A w.r.t ~A is: ~A" โ
โ 172 + expr var result))))) โ
โ 173 + โ
Once completedโโโthe changes will be summarized:
โฆ The requested tools have been successfully added to the MCP server.
Implemented Tools:
1. `get-system-info`: Returns detailed information about the Common Lisp implementation, machine type, and software version.
2. `get-server-info`: Returns information about the Gemini CLI MCP server instance.
3. `get-lisp-koan`: Returns a random Lisp Koan to provide enlightenment (random state is initialized on startup).
4. `symbolic-differentiate`: Demonstrates a symbolic AI algorithm by calculating the derivative of a Lisp mathematical expression with
respect to a given variable.
Verification:
- The new tools were added to src/main.lisp.
- A unit test for the symbolic differentiation logic (deriv function) was added to tests/main.lisp and successfully passed.
- The system was successfully loaded and compiled using SBCL.
You can now rebuild or run the server to use these new capabilities.
Restart Gemini CLI and check for the new MCP tools:
xbill@penguin:~/gemini-cli-codeassist/mcp-stdio-lisp$ make
Building mcp-server...
Loading Quicklisp...
Loading system definition...
Loading system...
To load "mcp-stdio-lisp":
Load 1 ASDF system:
mcp-stdio-lisp
; Loading "mcp-stdio-lisp"
..................................................
........
Building binary mcp-server...
compressed 32768 bytes into 555 at level 9
compressed 59572224 bytes into 10273773 at level 9
compressed 23461888 bytes into 4567968 at level 9
compressed 2785280 bytes into 690996 at level 9
compressed 22806528 bytes into 5492422 at level 9
And list the new MCP Tools:
> /mcp list
Configured MCP servers:
๐ข mcp-stdio-lisp - Ready (6 tools)
Tools:
- add
- get_lisp_koan
- get_server_info
- get_system_info
- greet
- symbolic_differentiate
to run the new tools:
>get_system_info
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ โ get_system_info (mcp-stdio-lisp MCP Server) {} โ
โ โ
โ Implementation: SBCL 2.2.9.debian โ
โ Machine: X86-64 12th Gen Intel(R) Core(TM) i5-1235U โ
โ Software: Linux 6.6.99-09000-gd3ae1caecf39 โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โฆ I've retrieved the system information. What is your first command?
and server information:
โฆ I will retrieve the server information for you.
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ โ get_server_info (mcp-stdio-lisp MCP Server) {} โ
โ โ
โ Gemini CLI MCP Server (Common Lisp / 40ants-mcp).~%Features: Basic Math, System Inspection, Lisp Koans, Symbolic AI Demo. โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โฆ I've retrieved the server information. What would you like to do next?
A Lisp Koan:
โฆ I will retrieve a Lisp Koan for you.
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ โ get_lisp_koan (mcp-stdio-lisp MCP Server) {} โ
โ โ
โ Assertion: Lisp is parentheses. Response: True, but looking at the parentheses is like looking at the quantum foam of the universe. โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โฆ I've retrieved a Lisp Koan for you. What would you like to do next?
Finally -a symbolic function:
> how do I call symbolic_differentiate
โฆ To call symbolic_differentiate, you need to provide a mathematical expression in Lisp prefix notation (s-expression) and the variable to
differentiate with respect to.
Here is an example:
1 symbolic_differentiate expression="'(+ (* 3 x) 5)" variable="'x'"
This would compute the derivative of $3x + 5$ with respect to $x$.
> symbolic_differentiate expression="'(+ (* 3 x) 5)" variable="'x'"
โฆ I will differentiate the expression for you.
โ Validating Parameter Inputs (esc to cancel, 4s)
2 GEMINI.md files | 1 MCP server
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ > Type your message or @path/to/file โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
~/.../mcp-stdio-lisp (main*) no sandbox (see /docs) Auto (Gemini 3) /model
<INFO> [17:18:00] 40ants-mcp/stdio-transport stdio-transport.lisp (receive-message stdio-transport form-fun-20) -
RECEIVED: {"method":"tools/call","params":{"name":"symbolic_differentiate","arguments":{"variable":"x","expression":"(+ (* 3 x) 5)"}},"jsonrpc":"2.0","id":5}
<INFO> [17:18:00] 40ants-mcp/server/definition definition.lisp (handle-message) -
Handling 40ANTS-MCP/SERVER/DEFINITION::MESSAGE: "{\"method\":\"tools/call\",\"params\":{\"name\":\"symbolic_differentiate\",\"arguments\":{\"v
โฆ I will differentiate the expression for you.
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ โ symbolic_differentiate (mcp-stdio-lisp MCP Server) {"variable":"x","expression":"(+ (* 3 x) 5)"} โ
โ โ
โ Derivative of (+ (* 3 X) 5) w.r.t X is: (+ (+ (* 3 1) (* X 0)) 0) โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โฆ The derivative of (+ (* 3 X) 5) with respect to X is (+ (+ (* 3 1) (* X 0)) 0), which simplifies to 3.
Gemini CLI Project Review
Gemini CLI can review and explain the project:
> what does this project do?
โฆ I will read README.md and src/main.lisp to understand the project's purpose and functionality.
โญโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฎ
โ โ ReadFile README.md โ
โ โ
โ โ
โ โ ReadFile src/main.lisp โ
โ โ
โฐโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฏ
โฆ This project is a Model Context Protocol (MCP) server implemented in Common Lisp.
It acts as a bridge that allows MCP clients (like Claude Desktop or Gemini-powered IDEs) to execute local Lisp code. It communicates via
standard input/output (stdio) using JSON-RPC.
Key Features:
* Protocol Compliance: Implements the MCP specification using the 40ants/mcp system (with some custom patches for strict compliance).
* Stdio Transport: Designed to be run as a subprocess by a client.
* Current Tools:
* greet: A simple tool that accepts a name and returns a greeting.
* add: A tool that adds two integers and returns the result.
Tech Stack:
* Language: Common Lisp (SBCL recommended)
* Package Manager: Quicklisp
* Core Library: 40ants/mcp (based on OpenRPC)
You can build it with make build and configure your MCP client to run the resulting executable.
and a code review:
โฆ Here is a code review of the mcp-stdio-lisp project.
Summary
The project is a functional, minimal Common Lisp implementation of an MCP server using stdio. It correctly handles the core constraint of this
architecture: keeping stdout clean for JSON-RPC messages while redirecting all logging/debug info to stderr.
However, the codebase relies heavily on "monkey patching" the underlying 40ants-mcp library to achieve protocol compliance. This makes the
project fragile to upstream updates.
1. Architecture & Structure
* Positives:
* Separation of Streams: The project enforces strict separation of stdout (protocol) and stderr (logging). The Makefile's run target even
intelligently redirects Quicklisp's loading output to stderr to prevent handshake corruption.
* Logging: src/logger.lisp provides a clean, structured JSON logger targeting stderr, which is excellent for observability in production
MCP environments.
* Entry Point: src/main.lisp sets a *debugger-hook* to intercept unhandled conditions. This is best practice for CLI tools to prevent
dropping into the standard Lisp debugger (sldb), which would hang the MCP client.
* Concerns:
* Monkey Patching: src/main.lisp contains significant overrides of 40ants-mcp and openrpc-server internals (lines 3-80).
* 40ants-mcp appears to be missing some standard MCP fields (e.g., renaming is_error to isError, handling inputSchema).
* Risk: These patches depend on private symbols (e.g., openrpc-server/method::method-thunk). Any update to 40ants-mcp could break
this server silently.
2. Code Quality
* Lisp Idioms: The code is generally idiomatic SBCL Common Lisp. Uses handler-case and handler-bind correctly.
* Safety: The add tool defines parameters as integers but performs no runtime type checking inside the body. While the JSON-RPC layer should
handle this validation based on the schema, explicit checks or check-type could be safer.
3. Build & configuration
* Makefile: The run command is robust:
1 --eval '(let ((*standard-output* *error-output*)) (ql:quickload :mcp-stdio-lisp))'
This specific line is crucial and well-implemented.
* Dependencies: yason (JSON), local-time, and serapeum are standard, reliable choices.
4. Testing
* Current State: tests/main.lisp only unit tests the get-greeting Lisp function.
* Gap: There are no integration tests verifying that the server actually speaks valid JSON-RPC over stdio. The heavily patched protocol layer
is currently untested.
Recommendations
1. Refactor Patches: Move the protocol patches (lines 3-80 of src/main.lisp) into a separate file (e.g., src/mcp-patches.lisp). This
separates "framework fixes" from your actual server logic.
2. Pin Dependencies: Since you are relying on internal symbols of 40ants-mcp, you should pin the version in your qlfile (if using Qlot) or
document exactly which commit hash of 40ants-mcp works.
3. Expand Tests: Add an integration test that spawns the binary and sends a raw JSON payload (e.g., {"jsonrpc": "2.0", "method":
"tools/list", "id": 1}) to stdin and asserts the stdout response. This is the only way to verify the patches actually work.
4. Logging Context: In src/logger.lisp, ensure local-time is configured/initialized correctly in the standalone binary to avoid timezone
errors in minimal environments (like containers).
Conclusion:
The code is a solid "Hello World" proof-of-concept, but the heavy reliance on patching the library internals makes it brittle for long-term
maintenance without better isolation or upstreaming those fixes
Summary
The strategy for using Lisp with MCP development with Gemini CLI was validated with an incremental step by step approach.
A minimal stdio transport MCP Server was started from source code and validated with Gemini CLI running as a MCP client in the same local environment.
Gemini CLI was then used to extend the sample Lisp code with several MCP tools and use these tools inside the context for the underlying LLM.


Top comments (0)