nestjs-xiaozhi-mcp-server
by ShiroTamada
README.md
# NestJS Xiaozhi MCP Server
[](https://github.com/ShiroTamada/nestjs-xiaozhi-mcp-server/actions/workflows/ci-cd.yml)
[](https://github.com/ShiroTamada/nestjs-xiaozhi-mcp-server/pkgs/container/nestjs-xiaozhi-mcp-server)
> A high-performance Model Context Protocol (MCP) Hub & Gateway built with NestJS (v12) for the [Xiaozhi ESP32](https://github.com/xinnan-tech/xiaozhi-esp32-server) AI assistant ecosystem.
---
## 🌟 Overview
**NestJS Xiaozhi MCP Server** acts as a unified central bridge between the Xiaozhi AI voice assistant (ESP32) and external capabilities. It aggregates:
1. **7 Local Business Tools**: Daily schedule, alarm/reminders, real-time stock quotes (FTS, SSI, VND, AAPL, TSLA), and task/todo management.
2. **37 Dynamic OmniRoute Agentic Tools**: Persistent Long-Term Memory, AgentSkills, OmniSkills sandbox execution, webhooks, and advanced automations retrieved dynamically via SSE from OmniRoute (`https://ai.tuanphongoto.com/api/mcp/sse`).
3. **Dual Protocol Transports**: Full support for standard **MCP SSE Transport** (recommended for Xiaozhi) and legacy single-turn **HTTP JSON-RPC**.
4. **Production-Ready Docker Setup**: Multi-stage build on Alpine, non-root execution, strictly bounded resource consumption (512MB RAM / 1.0 CPU), V8 GC tuning, log rotation, and native healthchecks.
---
## 🏗️ System Architecture
```mermaid
graph TD
subgraph Edge Layer [Hardware & Voice]
ESP32[📻 ESP32 XiaoZhi Robot / Speaker]
end
subgraph Core AI Server [XiaoZhi Core]
XiaozhiBackend[🖥️ XiaoZhi Backend Server<br/>STT / TTS / WebSocket Protocol]
LLM[🤖 LLM via OmniProxy / OpenAI]
end
subgraph MCP Hub [NestJS Xiaozhi MCP Server - Port 3000]
HealthCtrl[💓 /health Monitoring]
McpCtrl[🔌 McpController<br/>GET /mcp/sse & POST /mcp/messages]
McpEngine[⚙️ McpServer Engine<br/>Factory Pattern Sessions]
Business[💼 Business Services<br/>Schedule / Finance / Todo]
OmniBridge[⚡ OmniRouteClientService<br/>Auto-reconnect & Sync]
end
subgraph Remote Cloud [AI Gateway]
OmniRoute[🌐 OmniRoute MCP Server<br/>37 Agentic Tools / Memory / Skills]
end
ESP32 <-->|Opus Frames / WebSocket| XiaozhiBackend
XiaozhiBackend <-->|Prompt & Tools List| LLM
XiaozhiBackend <-->|MCP SSE Transport| McpCtrl
McpCtrl --> McpEngine
McpEngine --> Business
McpEngine <-->|Dynamic Remote Tools| OmniBridge
OmniBridge <-->|SSE Client Transport| OmniRoute
```
---
## 🛠️ Tech Stack
- **Framework**: NestJS (v12)
- **Protocol**: Model Context Protocol via `@modelcontextprotocol/sdk` (v1.30+)
- **Runtime**: Node.js 22 LTS (ESM syntax)
- **Package Manager**: pnpm
- **Language**: TypeScript (Strict Mode)
- **Testing**: Vitest
- **Linting**: Oxlint & Prettier
- **Containerization**: Docker & Docker Compose (Multi-stage Alpine, non-root user `node`)
---
## 🧰 Available MCP Tools (Total: 44 Tools)
### 1. Local Business Tools (7 Tools)
| Tool Name | Description |
| :--- | :--- |
| `get_daily_plan` | Lấy danh sách lịch trình, kế hoạch công việc và cuộc hẹn trong ngày của người dùng. |
| `add_schedule_item` | Thêm cuộc hẹn, sự kiện hoặc công việc mới vào lịch trình. |
| `set_alarm_schedule` | Đặt báo thức hoặc nhắc nhở vào khung giờ cụ thể. |
| `get_stock_info` | Tra cứu giá và thông tin thị trường cổ phiếu thực tế (FTS, SSI, VND, AAPL, TSLA). |
| `get_todo_list` | Lấy danh sách việc cần làm (Todo List) theo trạng thái (all, pending, completed). |
| `add_todo` | Thêm việc cần làm mới với các mức ưu tiên (low, medium, high). |
| `complete_todo` | Đánh dấu việc cần làm đã hoàn thành theo ID hoặc nội dung. |
### 2. OmniRoute Agentic Tools (37 Dynamic Tools)
When `OMNIROUTE_ENABLED=true`, the server connects to OmniRoute and dynamically surfaces 37 agentic tools across 13 scopes, including:
- **Persistent Agent Memory**: `memory_set`, `memory_get`, `memory_search` (Allows XiaoZhi to remember user preferences across sessions).
- **AgentSkills & OmniSkills**: Dynamic skill registry and sandbox execution.
- **Chaos Mode & A2A**: Multi-model parallel execution and agent-to-agent protocol triggers.
- **System Webhooks & Utilities**: Remote execution and automation integrations.
---
## 📡 Protocol & Endpoints
| Endpoint | Method | Transport | Description |
| :--- | :---: | :--- | :--- |
| `/mcp/sse` | `GET` | **MCP SSE** | Khởi tạo phiên kết nối SSE (Server-Sent Events) cho Xiaozhi. |
| `/mcp/messages` | `POST` | **MCP SSE** | Gửi các thông điệp JSON-RPC theo session id (`?sessionId=...`). |
| `/mcp/message` | `POST` | **HTTP RPC** | Endpoint JSON-RPC đơn lượt truyền thống (Backward compatible). |
| `/ota` | `GET`/`POST`| **HTTP JSON** | Cấp cấu hình WebSocket (`ws://...`) và thời gian hệ thống cho ESP32. |
| `/health` | `GET` | **HTTP** | Kiểm tra trạng thái hoạt động (uptime, status) cho Docker/Kubernetes. |
---
## ⚙️ Environment Variables
Create a `.env` file in the root directory (see [.env.example](file:///.env.example)):
| Variable | Type | Default | Description |
| :--- | :---: | :--- | :--- |
| `PORT` | Number | `3000` | Port máy chủ NestJS lắng nghe |
| `MCP_SERVER_NAME` | String | `nestjs-xiaozhi-mcp` | Tên định danh của MCP Server |
| `MCP_SERVER_VERSION`| String | `0.0.1` | Phiên bản của MCP Server |
| `MCP_API_KEY` | String | _(optional)_ | Khóa bảo vệ endpoint (Header `Authorization: Bearer <key>` hoặc `X-API-Key`) |
| `OMNIROUTE_ENABLED` | Boolean | `true` | Bật/tắt kết nối đến OmniRoute MCP Server |
| `OMNIROUTE_SSE_URL` | String | `https://ai.tuanphongoto.com/api/mcp/sse` | URL SSE endpoint của OmniRoute |
| `OMNIROUTE_API_KEY` | String | _(optional)_ | Bearer API Key xác thực với OmniRoute |
| `XIAOZHI_WEBSOCKET_URL` | String | `ws://192.168.1.170:8000/ws` | Địa chỉ WebSocket server cấp cho ESP32 khi gọi `/ota` |
| `XIAOZHI_WEBSOCKET_TOKEN` | String | _(optional)_ | Token xác thực WebSocket (nếu có) |
---
## 🚀 Deployment & Running
### Option 1: Production Deployment with Docker Compose (`docker-compose.prod.yml`)
The production Compose configuration ([docker-compose.prod.yml](file:///docker-compose.prod.yml)) pulls the pre-built, multi-architecture image directly from GitHub Container Registry (GHCR). On production servers, **no source code or build dependencies are needed**—only `.env` and `docker-compose.prod.yml`:
```bash
# 1. Pull the latest production image
docker compose -f docker-compose.prod.yml pull
# 2. Start container in detached mode
docker compose -f docker-compose.prod.yml up -d
# 3. Check health and real-time logs
docker compose -f docker-compose.prod.yml ps
docker compose -f docker-compose.prod.yml logs -f
# 4. Graceful stop
docker compose -f docker-compose.prod.yml down
```
> [!TIP]
> You can pin a specific image version by setting `IMAGE_TAG=v1.0.0` in your `.env` or shell environment before running `docker compose -f docker-compose.prod.yml up -d`.
### Option 2: Run Directly with Docker CLI
```bash
# Pull and run directly from GHCR
docker pull ghcr.io/shirotamada/nestjs-xiaozhi-mcp-server:latest
docker run -d \
--name nestjs-xiaozhi-mcp-prod \
-p 3000:3000 \
--env-file .env \
--restart always \
ghcr.io/shirotamada/nestjs-xiaozhi-mcp-server:latest
```
### Option 3: Local Build & Development with Docker Compose (`docker-compose.yml`)
The included [Dockerfile](file:///Dockerfile) and [docker-compose.yml](file:///docker-compose.yml) feature:
- **Strict Resource Boundaries**: Maximum `512MB` RAM and `1.0` CPU core limit to safeguard host resources.
- **Node.js Memory Tuning**: `NODE_OPTIONS="--max-old-space-size=384"` triggers V8 Garbage Collection proactively before hitting the 512MB container ceiling.
- **Security**: Runs under unprivileged user `node` (non-root).
- **Log Rotation**: Capped at 3 files $\times$ 20MB to prevent disk exhaustion.
- **Automated Healthcheck**: Pings `GET /health` every 30s.
```bash
# 1. Pull & run (or build locally if needed)
docker compose up -d
# 2. Inspect container status and health
docker compose ps
# 3. View real-time logs
docker compose logs -f
# 4. Check health endpoint
curl http://localhost:3000/health
# 5. Stop container
docker compose down
```
### Option 4: Local Development (Without Docker)
```bash
# Install dependencies
pnpm install
# Run in watch mode (development)
pnpm run start:dev
# Run in production mode
pnpm run build
pnpm run start:prod
```
---
## 📻 Integration with XiaoZhi ESP32 Server
1. Open your XiaoZhi backend server configuration (`config.yaml` or `data/.config.yaml`).
2. Add `nestjs-xiaozhi-hub` under `mcp.global.servers`:
```yaml
mcp:
global:
enabled: true
servers:
- name: "nestjs-xiaozhi-hub"
sse_url: "http://<SERVER_IP>:3000/mcp/sse"
enabled: true
reconnect_interval: 5
max_reconnect_attempts: 10
# headers:
# Authorization: "Bearer your-secret-api-key" # Uncomment if MCP_API_KEY is configured
```
> A ready-to-use template is available at [templates/xiaozhi-config.yaml](file:///templates/xiaozhi-config.yaml).
3. Restart the XiaoZhi server. XiaoZhi will discover all 44 tools automatically!
---
## 🧪 Testing & Code Quality
```bash
# Run unit tests
pnpm run test
# Run tests with coverage
pnpm run test:cov
# Run fast code linter (Oxlint)
pnpm run lint
# Format codebase (Prettier)
pnpm run format
```
---
## 📄 License
UNLICENSED
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues