Yassir LMD行动副驾驶
Yassir最后一英里交付团队的人工智能操作助理。使用带有30个连接到MongoDB的专用工具的LLM,通过聊天界面实时回答操作问题。
目标受众: 项目经理、运营、利益相关者和开发人员。 访问模式: 只读。没有写入,没有突变,没有删除。
______________________________________________________________________
目录
______________________________________________________________________
架构概述
┌──────────────────────────────────────────────────────┐
│ Web UI (index.html) │
│ Chat interface + Charts + Dev Mode │
└────────────────────────┬─────────────────────────────┘
│ SSE (Server-Sent Events)
▼
┌──────────────────────────────────────────────────────┐
│ Express API Server (api-server.ts) │
│ Helmet CSP │ CORS │ Rate Limit │ API Key Auth │
│ │
│ POST /api/chat ──► LLM (tool calling loop) │
│ │ │
│ ▼ │
│ 30 Read-Only Tools │
│ ┌──────────┬──────────┬──────────┐ │
│ │ MongoDB │ Redis │ In-Memory│ │
│ │ (yacool) │(optional)│ (alerts) │ │
│ └──────────┴──────────┴──────────┘ │
└──────────────────────────────────────────────────────┘| 组件 | 技术 |
|---|---|
| 后端 | Node.js+Express+TypeScript |
| LLM | OpenAI兼容的API(Cerebras、Groq、Qwen、Gemini、OpenAI) |
| 数据库 | MongoDB(Mongoose,只读,首选二级) |
| 缓存 | Redis(可选,用于调度队列) |
| 协议 | stdio客户端的MCP(模型上下文协议) |
| 前端 | 单个HTML文件、vanilla JS、Chart.JS、marked.JS |
______________________________________________________________________
它是如何工作的(代理流)
User question
│
▼
Express backend receives message via POST /api/chat
│
▼
Backend sends message + system prompt + 30 tool definitions to LLM
│
▼
LLM decides which tool(s) to call (function calling)
│
▼
Backend executes tool → READ-ONLY MongoDB query
│
▼
Tool result sent back to LLM
│
▼
LLM formulates human-friendly response (tables, charts, summaries)
│
▼
Response streams back to user via SSE步骤3-6可以循环到 12轮 对于复杂的问题。A. 服务器端超时2分钟 以及a 客户端超时90秒 防止请求失控。
______________________________________________________________________
快速开始
# 1. Install dependencies
npm install
# 2. Configure environment
cp .env.example .env
# Edit .env with your DB_URI and at least one LLM API key
# 3. Build TypeScript
npm run build
# 4. Start the web server
npm run web
# → http://localhost:3737可用脚本
| 脚本 | 命令 | 描述 |
|---|---|---|
npm run build | tsc | 将TypeScript编译为 dist/ |
npm run dev | tsc --watch | 开发观看模式 |
npm run web | node dist/web/api-server.js | 启动网络聊天服务器 |
npm run start | node dist/index.js | 启动MCP stdio服务器(用于MCP客户端) |
npm run typecheck | tsc --noEmit | 不发射的类型检查 |
______________________________________________________________________
环境变量
| 变量 | 必填 | 描述 |
|---|---|---|
DB_URI | 是 | MongoDB连接字符串(预编译/暂存) |
DB_NAME | 否 | 数据库名称覆盖(默认:来自URI)。设置为 yacool |
| 法学硕士(选一个) | ||
CEREBRAS_API_KEY | - | Cerebras API密钥(100万代币/天免费) |
GEMINI_API_KEY | - | Google Gemini API密钥(1500请求/天免费) |
GROQ_API_KEY | - | Groq API密钥(10万代币/天免费) |
QWEN_API_KEY | - | 阿里云/DashScope API密钥 |
OPENAI_API_KEY | - | OpenAI API密钥(付费) |
QWEN_MODEL | 否 | 覆盖Qwen模型(默认值: qwen-plus) |
OPENAI_MODEL | 否 | 覆盖任何提供者的模型 |
| Redis(可选) | ||
REDIS_HOST | 否 | 用于调度队列监控的Redis主机 |
REDIS_PORT | 无 | Redis端口(默认:6379) |
REDIS_PASSWORD | 否 | Redis密码 |
| 安全 | ||
API_KEY | 否 | 如果设置,则需要 X-Api-Key 页眉打开 /api/chat 和 /api/export |
CORS_ORIGIN | 无 | CORS来源(默认:允许所有) |
RATE_LIMIT_RPM | 否 | 每分钟最大聊天请求数(默认值:60) |
| 服务器 | ||
WEB_PORT | 否 | HTTP端口(默认值:3737) |
______________________________________________________________________
大语言模型提供商
服务器从环境变量中自动检测提供者(找到的第一个密钥获胜):
| 优先级 | 提供商 | 环境变量 | 自由层 | 默认模型 |
|---|---|---|---|---|
| 1 | 大脑 | CEREBRAS_API_KEY | 100万代币/天 | qwen-3-32b |
| 2 | 双子座 | GEMINI_API_KEY | 每天1500次 | 双子座-2.0闪光 |
| 3 | Groq | GROQ_API_KEY | 100K代币/天 | 骆驼-3.3-70b-多功能 |
| 4 | Qwen(DashScope) | QWEN_API_KEY | 慷慨的免费配额 | qwen plus |
| 5 | OpenAI | OPENAI_API_KEY | 付费 | gpt-4o-mini |
所有供应商都使用 兼容OpenAI的API 格式。终端中的每个请求都会记录令牌使用情况。
______________________________________________________________________
项目结构
lmd-mcp-mvp/
├── public/
│ ├── index.html # Web chat UI (single file)
│ ├── favicon.svg # Yassir 'Y' favicon
│ └── yassir-logo.svg # Full Yassir logo
├── src/
│ ├── connections/
│ │ ├── mongodb.ts # MongoDB connection (secondaryPreferred)
│ │ └── redis.ts # Redis connection (optional, graceful fallback)
│ ├── constants/
│ │ └── order-status.ts # Status code → label mapping
│ ├── resources/
│ │ └── collection-schemas.ts # Field guides for LLM context
│ ├── schemas/ # Mongoose schema definitions
│ │ ├── order.schema.ts
│ │ ├── driver.schema.ts
│ │ ├── restaurant.schema.ts
│ │ └── city.schema.ts
│ ├── tools/ # All 30 tools organized by domain
│ │ ├── alerts/ # set_alert
│ │ ├── analytics/ # 9 analytics tools
│ │ ├── config/ # city_config_lookup
│ │ ├── dispatch/ # rejection_analysis, dispatch_queue
│ │ ├── fleet/ # fleet_status, supply_demand, ghost_drivers, lookup_driver
│ │ ├── general/ # flexible_query, describe_collection, list_collections
│ │ ├── infra/ # shift_report, scheduled_reports
│ │ ├── orders/ # query_orders, needs_attention, sla_status, lookup/investigate
│ │ ├── restaurant/ # restaurant_health, auto_busy, lookup_restaurant
│ │ ├── users/ # lookup_user
│ │ └── registry.ts # Single source of truth for all tool definitions
│ ├── utils/
│ │ ├── cache.ts # In-memory cache with TTL
│ │ ├── currency.ts # Country → currency resolver
│ │ ├── fact-check.ts # Debug query formatting
│ │ ├── query-logger.ts # Query logging utility
│ │ └── tool-error.ts # Structured tool errors
│ ├── web/
│ │ ├── api-server.ts # Express server (main entry for web mode)
│ │ ├── tool-registry.ts # OpenAI function calling adapter
│ │ ├── csv-export.ts # JSON → CSV export utility
│ │ └── conversation-store.ts # File-based conversation persistence (legacy)
│ ├── server.ts # MCP server setup
│ └── index.ts # MCP stdio entry point
├── schema/ # Original backend Mongoose schemas (reference)
├── system-prompt.txt # LLM system prompt with rules and tool routing
├── package.json
└── tsconfig.json______________________________________________________________________
工具参考(30个工具)
订单(6个工具)
| 工具 | 说明 |
|---|---|
query_orders | 按国家、城市、状态和时间范围使用筛选器计数和列出订单 |
get_needs_attention | 查找没有司机或延迟提货的订单 |
get_order_sla_status | 检查哪些活动订单违反了交货时间SLA |
lookup_order | 通过以下方式深入了解单个订单 _id 具有完整的生命周期时间表,按货币计费 |
investigate_order | 自动发现订单的根本原因分析 |
lookup_user | 通过电话、电子邮件、user_id或带有订单统计信息和货币的姓名查找客户 |
车队(4个工具)
| 工具 | 说明 |
|---|---|
fleet_status | 驾驶员车队细分:在线、繁忙、幽灵、离线计数 |
supply_demand_balance | 比较有效订单与可用驱动程序以检测短缺 |
ghost_drivers | 在线查找驾驶员,但GPS陈旧导致调度失败 |
lookup_driver | 通过ID、电话或用户名查找驾驶员,并查看今天的统计数据 |
餐厅(3工具)
| 工具 | 说明 |
|---|---|
restaurant_health | 餐厅绩效:接受率、拒绝率、准备时间 |
auto_busy_predictions | 预测哪些餐厅将自动禁用连续拒绝 |
lookup_restaurant | 按ID或名称查找餐厅,包括可用性、统计数据和货币 |
分析(9个工具)
| 工具 | 说明 |
|---|---|
compare_periods | 比较两个时间段之间的指标(支持 group_by_country) |
top_bottom_performers | 按指标对城市、餐馆、司机或用户进行排名 |
detect_anomalies | 通过比较当前小时与7天基线来检测异常模式 |
revenue_metrics | GMV、运费、平均篮子大小——按国家货币列出 |
eta_accuracy | 预计到达时间准确性:准时率、平均交货时间、按城市细分 |
geo_analysis | 按地理区域划分的驾驶员和订单密度 |
ratings_analysis | 与餐厅/司机相关的低评级订单 |
promo_performance | 促销/优惠券性能:兑换率,顶级优惠券 |
shift_report | 全班次报告:订单、交货率、车队、餐厅绩效 |
调度(2个工具)
| 工具 | 说明 |
|---|---|
rejection_analysis | 分析驾驶员拒绝模式和大多数被拒绝的订单 |
dispatch_queue | 监控Redis调度队列深度和卡住订单(需要Redis) |
配置和基础设施(4个工具)
| 工具 | 说明 |
|---|---|
city_config_lookup | 查询并比较市级运营设置 |
scheduled_reports | 管理基于webhook的计划报告时间表 |
set_alert | 配置基于阈值的主动警报 |
概述(3个工具)
| 工具 | 说明 |
|---|---|
flexible_query | 在上运行只读查询 任何 MongoDB集合(计数、查找、区分) |
describe_collection | 发现任何集合的字段和结构 |
list_collections | 列出所有可用的MongoDB集合及其文档计数 |
______________________________________________________________________
API终点
| 方法 | 路径 | 身份验证 | 描述 |
|---|---|---|---|
GET | /api/health | 否 | 健康检查(数据库状态、提供者、型号、工具计数) |
POST | /api/chat | API密钥 | SSE流式聊天端点 |
POST | /api/export | API密钥 | 将工具结果导出为CSV |
GET | /api/stats | 否 | 使用统计数据(独立访客、总聊天次数、正常运行时间) |
SSE事件类型(/api/chat)
| 事件 | 有效载荷 | 描述 |
|---|---|---|
tool_call | { name } | 工具执行已开始 |
tool_result | { name } | 工具执行已完成 |
content | { text } | LLM最终回复 |
meta | { queries, tokens } | 调试查询和令牌使用情况 |
error | { message } | 发生错误 |
______________________________________________________________________
Web UI功能
- 聊天界面 使用markdown渲染(表格、粗体、链接)
- 图表渲染 --问“显示为图表”,AI输出交互式chart.js可视化(条形图、线条、饼图、甜甜圈)
- 快速操作 --常用查询的预设按钮(活动订单、车队状态、班次报告等)
- 国家聚焦 --侧边栏下拉菜单,用于查询特定国家的范围
- 开发模式 --切换以显示每个工具使用的原始MongoDB查询(用于事实检查)
- 会话持久性 --聊天记录保存在
localStorage,可从侧边栏恢复 - 停止按钮 --取消飞行中的请求(退出键或单击停止按钮)
- 深色主题 --Yassir品牌颜色
______________________________________________________________________
安全和数据保护
1.只读数据库访问
- MongoDB连接使用
readPreference: "secondaryPreferred" - 所有工具仅执行
find,countDocuments,distinct,以及aggregate运营 - 无法执行插入、更新、删除或删除操作
- 所有模式都使用
strict: false具有读取灵活性,但不存在写入模式
2.敏感场阻断
所有查询结果为 递归消毒 在发送给LLM或用户之前。
全球封锁模式 (任何包含这些字符串的字段名都会被编辑):
password, token, secret, credit_card, card_number, cvv, pin, otp,
refresh_token, access_token, api_key, apikey, client_secret, auth_code,
approval_code, transaction_id, payment_order_id, action_id, device_token特定于收藏的编辑 对于收款:
| 集合 | 已编辑字段 |
|---|---|
cart_payment_transactions | CLIENT_SECRET_KEY, PAYMENT_ORDER_ID, MICRO_SERVICE_TRANSACTION_ID, YASSIR_ACTION_ID, AUTH_CODE, APPROVAL_CODE, TRACKER, END_MESSAGES,错误消息 |
courier_payments | 相同的支付秘密 |
payment_gateway | 相同的支付秘密 |
temp_payment | 相同的支付秘密 |
被阻止的字段显示为 "[REDACTED]" 结果。
3.查询安全
- 被阻止的操作员:
$where,$function,$accumulator(无任意代码执行) - 最大过滤深度:3个层次的嵌套
- 最大结果数:每个查询50个文档
- 被阻止的收藏:
system.views,system.profile,system.js
4.API安全
- API密钥验证 --何时
API_KEY设置,/api/chat和/api/export需要X-Api-Key头球 - 速率限制 —
express-rate-limit上/api/chat(默认值:60需求/分钟) - 头盔CSP --限制脚本、样式和连接的内容安全策略
- 跨域资源共享 --可配置的原点限制
- Webhook URL验证 --定时报告阻止内部/私有IP(防止SSRF)
5.AI能看到什么和看不到什么
| 看得见 | 看不见 |
|---|---|
| 订单状态、时间戳、城市、国家 | 密码、令牌、机密 |
| 客户姓名、电话、电子邮件(运营部门需要这些) | 信用卡号码、CVV |
| 账单金额(含货币) | 支付网关交易ID |
| 驾驶员姓名、电话、位置 | 授权码、批准码 |
| 餐厅名称、电话、状态 | 客户密钥 |
______________________________________________________________________
货币处理
每个国家都有自己的货币。该系统确保货币值始终以正确的货币符号显示。
| 国家 | 代码 | 货币 | 符号 |
|---|---|---|---|
| 阿尔及利亚 DZ DZDJ | |||
| 摩洛哥 | MA | MAD | DH |
| 突尼斯 | TN | TND | DT |
| 法国 | 法国 | 欧元 | 欧元 |
| 塞内加尔 | SN | XOF | CFA |
| 南非 | ZA | ZAR | R |
它是如何工作的:
src/utils/currency.ts解决country_code→{ currency_code, currency_symbol }从countrycurrency集合(缓存5分钟,硬编码回退)- 所有货币工具(
revenue_metrics,lookup_order,lookup_user,lookup_restaurant,promo_performance)包括currency_code和currency_symbol在他们的回答中 - 当收入按国家分组时, 不计算跨货币总计 --您不能将DZD+MAD+EUR相加
- 系统提示指示AI始终显示货币符号,从不跨货币求和
______________________________________________________________________
缓存
内存缓存(src/utils/cache.ts)减少频繁访问数据的数据库负载。
| 数据 | TTL | 描述 |
|---|---|---|
| 货币地图 | 5分钟 | 国家→ 货币映射 |
| 收入指标 | 1分钟 | 收入汇总结果 |
| 异常基线 | 1小时 | 7天历史计数 |
| 采集现场样本 | 30秒 | describe_collection 结果 |
- 最大缓存条目数:200(LRU驱逐)
- 每个进程都有缓存,重启时重置
______________________________________________________________________
Redis(可选)
Redis是 可选的 并且仅由 dispatch_queue 用于监控调度队列的工具。
- 如果未配置Redis:该工具返回一条明确的错误消息,而不是崩溃
- 如果Redis关闭:重试前冷却60秒,没有应用程序崩溃
- 如果Redis可用:提供调度队列深度、卡住订单和处理计数
通过配置 REDIS_HOST, REDIS_PORT, REDIS_PASSWORD 环境变量。
______________________________________________________________________
对话存储
聊天对话存储在浏览器的 localStorage 在钥匙下面 yassir_conversations.
- 自动保存 每位助理回复后
- 可恢复的 从侧边栏(最多30个最近的对话)
- 可删除的 通过每个对话旁边的×按钮
- 每个浏览器 --对话在设备之间不同步
- 幸存者部署 --与服务器端存储不同,localStorage在服务器重启后仍然存在
______________________________________________________________________
部署
渲染(自由层)
该应用程序旨在在Render的免费层上运行:
- 不需要持久文件系统(对话在本地存储中)
- 单
npm run build && npm run web命令 - 优雅降级:Redis、警报和计划报告在内存中工作,并优雅降级
- 通过Render仪表板配置的环境变量
生成命令
npm install && npm run build开始命令
npm run web健康检查
GET /api/health退货 200 如果MongoDB已连接, 503 如果退化。
______________________________________________________________________
常见问题解答
它是只读的吗?
是的,100%。 服务器仅运行 find, countDocuments, distinct,以及 aggregate MongoDB操作。没有写模式,没有插入/更新/删除处理程序,连接使用 readPreference: "secondaryPreferred" 哪些路由到副本集次级。
它会泄露密码或支付信息吗?
号码 所有查询结果都通过两层进行递归清理:全局 BLOCKED_FIELDS (字段名称的模式匹配)以及 COLLECTION_REDACTED_KEYS (收款的确切字段名称)。被阻止的值显示为 "[REDACTED]".
如果LLM对字段名产生幻觉怎么办?
这 flexible_query 工具有一个 现场自动校正 系统。它对集合的实际字段进行采样,并将LLM请求的字段与最接近的实际字段模糊匹配。还有一个静态 FIELD_ALIASES 常见失配的映射(例如。, total_price → billings.amount.grand_total).
如果LLM试图写入数据库怎么办?
它不能。工具层只公开读取操作。没有注册写入工具。甚至 flexible_query 仅支持 count, find,以及 distinct 行动。
如果Redis宕机了怎么办?
应用程序继续工作。仅 dispatch_queue 使用Redis。如果Redis不可用,该工具会立即返回错误消息,而不会挂起。该应用程序从未因Redis故障而崩溃。
我可以将其用于MCP客户端(Claude、Cursor等)吗?
对。跑 npm run start 启动MCP stdio服务器。这通过模型上下文协议公开了所有30个工具,供任何兼容MCP的客户端使用。
代币是如何计算的?
每 /api/chat 请求将令牌使用情况记录到终端:
[llm] user query | input+output=total tokens | N tools | Xms支持哪些国家?
DZ(阿尔及利亚)、MA(摩洛哥)、TN(突尼斯)、FR(法国)、SN(塞内加尔)、ZA(南非)。每个都有自己的货币、时区和操作配置。
我可以添加新工具吗?
- 创建新
.tool.ts文件在适当的src/tools/子目录 - 导出Zod模式和处理程序函数
- 将工具添加到
src/tools/registry.ts - 向添加路由提示
system-prompt.txt - 重建与
npm run build
______________________________________________________________________
依赖项
| 包装 | 版本 | 用途 |
|---|---|---|
@modelcontextprotocol/sdk | ^1.27.0 | MCP服务器协议 |
express | ^5.2.1 | HTTP服务器 |
mongoose | ^6.13.8 | MongoDB ODM |
openai | ^6.27.0 | LLM API客户端(兼容OpenAI) |
zod | ^3.25.0 | 工具输入的模式验证 |
zod-to-json-schema | ^3.25.1 | 将Zod模式转换为JSON模式以进行函数调用 |
helmet | ^8.1.0 | 安全标头(CSP等) |
cors | ^2.8.6 | 跨源资源共享 |
express-rate-limit | ^8.3.0 | 速率限制 |
ioredis | ^5.10.0 | Redis客户端(可选) |
dotenv | ^16.4.5 | 环境变量加载 |
______________________________________________________________________
