Content
# 🧠 100% Local MCP Client + SQLite Server (LlamaIndex + Ollama + Qwen2.5 / DeepSeek-R1)
## 🧩 Technology Stack and Principle Explanation
This project implements a **fully locally running MCP (Model Context Protocol) client and server system**.
### 🚀 Tech Stack
* **LlamaIndex**: Used to build agents (FunctionAgent) based on the MCP protocol.
* **Ollama**: Provides a local large language model (recommended to use `Qwen2.5:7b-instruct`, DeepSeek-R1 is for compatibility testing only).
* **LightningAI**: Responsible for running and hosting workflows (optional, remote hosting is not enabled for local runtime).
* **SQLite**: A lightweight local database used as a demonstration backend.
* **MCP Protocol**: Implements a standard communication mechanism between Host ↔ Client ↔ Server (local SSE).
### ⚙️ Workflow Principles
1. The user inputs a natural language query;
2. The agent (FunctionAgent) **determines whether to invoke a tool** based on the prompt and tool description;
3. The MCP client connects to the MCP server via SSE;
4. The server provides tools (such as `add_data` and `read_data`) and executes the corresponding SQL;
5. The execution result is sent back to the agent;
6. The model generates the final natural language response by combining the context.
### 🧠 Project Overall Architecture

---
### 📘 Implementation Steps Overview
| Step | Content | Description |
| ---- | --------------------------- | ------------------------------------------------ |
| #1 | Build SQLite MCP Server | Provides two basic tools: Add Data / Query Data |
| #2 | Set Up LLM | Use Ollama to call the local model (recommended Qwen2.5:7b) |
| #3 | Define System Prompt | Guide the agent on how to judge and use MCP tools |
| #4 | Define Agent | Wrap MCP tools as FunctionAgent using LlamaIndex |
| #5 | Define Agent Interaction | Manage user input, streaming events, and tool calls |
| #6 | Initialize MCP Client and Agent | Load tools and establish SSE connection with the server |
| #7 | Run Agent | User Interaction → Intelligent Agent Decision → Tool Execution → Natural Language Output |
---
This project demonstrates a **fully local** minimal viable example:
* ✅ **MCP Server**: Exposes database read/write tools (based on SQLite)
* ✅ **MCP Client**: Wrapped as LlamaIndex FunctionAgent
* ✅ **LLM**: Calls the local model via Ollama (recommended `qwen2.5:7b-instruct`)
The entire process is completed on the local machine without the need for external APIs.
---
## 📁 Project Structure
```
local-mcp-demo/
├── README_zh.md # Running Instructions (this file)
├── requirements.txt
├── server/
│ └── server.py # #1 SQLite MCP Server (SSE / stdio one of the two)
└── client/
├── ollama_client.py # #2~#7 MCP Client + LlamaIndex Proxy
└── system_prompt.txt # #3 System Prompt (defines tool usage strategy)
```
## ⚙️ Environment Preparation
### 1️⃣ Python Environment
* Python **3.10+**
* It is recommended to use a virtual environment
```bash
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
```
> If the network is slow in China, you can use the Tsinghua mirror:
>
> ```
> pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
> ```
### 2️⃣ Install Ollama (Local Model Runtime)
1. Open your browser and visit [https://ollama.ai/download](https://ollama.ai/download)
2. Download the installation package for your platform and install it (Windows/macOS/Linux)
3. After installation is complete, open the terminal to verify:
```bash
ollama --version
```
If the version number appears, the installation was successful.
### 3️⃣ Pulling Models that Support Function Calling (Very Important)
> ⚠️ **The DeepSeek-R1 official model does not support Function Calling by default**
> Even the `1.5b` / `7b` versions may not allow the agent to automatically trigger MCP tool calls.
> **It is recommended to use the `qwen2.5:7b-instruct` model** (which supports tool calls).
```bash
# Recommendation Model (Supports Function Calling)
ollama pull qwen2.5:7b-instruct
# Can be replaced with other models that support function calls:
# ollama pull llama3.1:8b-instruct
# ollama pull mistral:7b-instruct
```
You can verify if the download was successful:
```bash
ollama list
```
> **Note:**
>
> * DeepSeek-R1:1.5b, although claimed to support tool calls, has proven to be unstable in actual tests;
> * The 7B version of DeepSeek-R1 has higher support under the same conditions, but also consumes more resources;
> * The Qwen2.5:7b-instruct model has the most comprehensive support.
---
## 🚀 Running Steps
### 🧩 Step 1. Start the SQLite MCP Server
`server/server.py` implements two tools:
* `add_data(query: str) -> bool`: Executes `INSERT/UPDATE/DELETE`
* `read_data(query: str = "SELECT * FROM people") -> list`: Executes `SELECT`
#### Startup Command:
```bash
cd server
python server.py --db ../demo.db --transport sse
```
Seeing the following output indicates success:
```
✅ SQLite DB: D:\Projects\MCP\demo.db
🚀 MCP SQLite server running on SSE http://127.0.0.1:8000/sse
```
> ✅ After starting, the example table `people(name, age, profession)` will be created automatically.
### 🧠 Step 2. Set up LLM (Ollama)
Default model in `client/ollama_client.py`:
```python
MODEL_NAME = "qwen2.5:7b-instruct"
```
If you have downloaded other models (for example, DeepSeek-R1), you can modify it accordingly.
### 📜 Step 3. Define System Prompt
The model's **role and tool usage rules** are defined in `client/system_prompt.txt`. For example:
```
- When the user mentions "add"/"insert", call add_data;
- When the user mentions "query"/"retrieve", call read_data;
- After a successful call, please return a concise result without repeating the call;
```
> Deleting this file or clearing its content will prevent the model from determining when to call the tools (see "Principle Explanation" below for details).
### 🤖 Step 4. Define the Agent (FunctionAgent)
`client/ollama_client.py` uses:
* `llama_index.tools.mcp` to wrap the MCP tool as a native LlamaIndex tool;
* `FunctionAgent` to construct a function-calling agent.
The agent is responsible for:
* Deciding whether to call the tool;
* Integrating the results after the call;
* Generating natural language responses.
### 💬 Step 5. Define Agent Interaction
`handle_user_message(...)`:
* Pass the user input to the agent;
* Print the tool call event (`[Event] ToolCall -> ...`);
* Return the natural language result.
### ⚙️ Step 6. Initialize MCP Client and Agent
```python
mcp_client = BasicMCPClient("http://127.0.0.1:8000/sse")
mcp_tool = McpToolSpec(client=mcp_client)
tools = await mcp_tool.to_tool_list_async()
agent = FunctionAgent(tools=tools, llm=llm, system_prompt=SYSTEM_PROMPT)
```
### 🧑💻 Step 7. Start the Client and Model Proxy
Open another terminal while keeping the server running:
```bash
cd client
source ../.venv/bin/activate # For Windows use .venv\Scripts\activate
python ollama_client.py
```
Input example:
```
Add to database: INSERT INTO people(name, age, profession) VALUES('Rafael Nadal', 39, 'Tennis Player')
```
Expected output (partial example):
```
[Event] AgentInput
[Event] AgentStream
[Event] ToolCall -> add_data
[Event] AgentOutput
Agent: Successfully added Rafael Nadal to the database.
```
Then input:
```
Get data
```
or:
```
Query: SELECT * FROM people
```
Output:
```
[Event] ToolCall -> read_data
Agent: Found 1 record:
- Rafael Nadal (39 years old, Tennis Player)
```
## 🪞 Frequently Asked Questions and Solutions
| Question | Cause | Solution |
| ------------------------------- | ----------------------------------------- | ---------------------------------------------- |
| Model keeps calling the tool | No limit on the number of iterations | Set `max_steps=3` in `FunctionAgent` |
| Model makes incorrect judgment (does not call the tool) | `system_prompt` has been deleted or the model does not support tool calling | Restore `system_prompt`, or use `qwen2.5:7b-instruct` |
| Unable to retrieve data | Tool did not execute (only output JSON) | Switch to a model that supports Function Calling |
| Reports "near '*'" SQL error | Model output contains full-width symbols / code fences | Clean SQL on the server side (see `_clean_sql` in `server.py`) |
| LLM outputs garbled Chinese | Ollama console character set issue | Use a UTF-8 terminal or VSCode terminal |
| Insufficient GPU memory | Model is too large | Switch to a smaller parameter model (e.g., `qwen2.5:1.8b`) |
## 💡 Brief Overview of Technical Principles
* **MCP Server**: Encapsulates SQLite tools (add / read) and exposes them as standard MCP interfaces (SSE / stdio).
* **MCP Client**: Communicates with the server through `BasicMCPClient`.
* **LlamaIndex Agent**: Receives user input → Calls local LLM → The LLM determines whether and how to invoke tools.
* **System Prompt**: Guides model decisions (the "manual" for tool invocation).
* **LLM (Ollama)**: Executes inference, outputting function calls or natural language.
> If `system_prompt.txt` is deleted, the model will lose the instructions for tool usage, and thus will no longer be able to "independently determine" function calls.
## 🧩 Our Improvements and Experience Summary
* ✅ Self-built MCP Server for database access;
* ✅ FunctionAgent can automatically select `add_data` / `read_data` based on natural language intent;
* ✅ Qwen2.5:7b-instruct is the best compatible model;
* ⚙️ DeepSeek-R1 1.5b/7b cannot stably support Function Call under the same conditions;
* 🔁 Added limits on the number of calls and prompt restrictions to prevent infinite loops;
* 🧱 Future expansion of more tools (file read/write, knowledge base retrieval, etc.) is possible.
## 🧾 License
MIT License (Free to use, modify, and extend)
## Star History
[](https://www.star-history.com/?utm_source=chatgpt.com#StephenCurry885/100-local-MCP-Client&type=date&legend=top-left)
Connection Info
You Might Also Like
everything-claude-code
Complete Claude Code configuration collection - agents, skills, hooks,...
markitdown
MarkItDown-MCP is a lightweight server for converting URIs to Markdown.
cc-switch
All-in-One Assistant for Claude Code, Codex & Gemini CLI across platforms.
servers
Model Context Protocol Servers
servers
Model Context Protocol Servers
Agent-Reach
Give your AI agent eyes to see the entire internet. Read & search Twitter,...