Laboratory Inventory HTTP Server
这是一个独立的 HTTP 服务器,用于提供实验室库存数据的 REST API 接口。通过 HTTP 端点查询 MongoDB 中的库存数据,可被任何 HTTP 客户端调用。
功能特性
✅ RESTful API - 标准的 HTTP GET 端点,易于集成 ✅ Token 优化 - 只查询需要的数据,节省 80-98% 的 Token 消耗 ✅ MongoDB 集成 - 直接查询 MongoDB 数据库 ✅ 独立运行 - 不依赖主应用,可单独部署 ✅ 灵活查询 - 提供多种查询方式,支持按条件筛选
可用 API 端点
| 端点 | 描述 | 使用场景 |
|---|---|---|
GET /tools/inventory-summary | 获取库存统计摘要 | 查看整体库存状况 |
GET /tools/expired-items | 获取已过期耗材 | 查找过期耗材 |
GET /tools/expiring-items | 获取即将过期耗材 | 查找快过期的耗材 |
GET /tools/low-stock-items | 获取库存不足耗材 | 查找低库存耗材 |
GET /tools/out-of-stock-items | 获取缺货耗材 | 查找缺货项目 |
GET /tools/search-inventory | 根据关键词搜索耗材 | 搜索特定耗材 |
GET /tools/check-item | 检查耗材可用性 | 查询特定耗材详情 |
GET /tools/purchase-suggestions | 获取采购建议 | 获取采购推荐 |
GET /health | 健康检查 | 检查服务状态 |
快速开始
1. 安装依赖
cd mcp
npm install
2. 配置环境变量
复制示例配置文件并修改:
# 复制示例配置文件
cp .env.example .env
# 编辑 .env 文件,设置你的 MongoDB 连接
.env 文件内容:
MONGODB_URI=mongodb://localhost:27017/test
PORT=3001
⚠️ 重要: .env 文件包含敏感信息,已在 .gitignore 中,不会提交到 git。
3. 启动服务器
npm start
服务器将在 http://localhost:3001 上运行(默认端口)。
HTTP API 使用指南
基础 URL
http://localhost:3001
端点详解
1. 获取库存统计摘要
GET /tools/inventory-summary?labName=<实验室名>
示例:
curl "http://localhost:3001/tools/inventory-summary?labName=实验室A"
响应:
{
"success": true,
"queryType": "summary",
"data": {
"totalItems": 128,
"normalItems": 98,
"expired": 5,
"expiringSoon": 12,
"lowStock": 8,
"outOfStock": 5,
"issueItems": [
{
"name": "胰蛋白酶",
"quantity": 3,
"minQuantity": 5,
"expiryDate": "2024-03-15",
"status": "库存不足"
}
]
}
}
2. 获取已过期耗材
GET /tools/expired-items?labName=<实验室名>&limit=5
示例:
curl "http://localhost:3001/tools/expired-items?labName=实验室A&limit=10"
响应:
{
"success": true,
"queryType": "expired",
"count": 3,
"items": [
{
"name": "PBS缓冲液",
"quantity": 2,
"expiryDate": "2024-01-15"
}
]
}
3. 获取即将过期耗材
GET /tools/expiring-items?labName=<实验室名>&days=30&limit=10
参数:
days: 天数范围(默认30天)limit: 返回数量限制(默认10)
示例:
curl "http://localhost:3001/tools/expiring-items?labName=实验室A&days=30&limit=10"
响应:
{
"success": true,
"queryType": "expiring",
"count": 5,
"items": [
{
"name": "胎牛血清",
"quantity": 8,
"expiryDate": "2024-04-01",
"daysLeft": 15
}
]
}
4. 获取库存不足耗材
GET /tools/low-stock-items?labName=<实验室名>&limit=10
示例:
curl "http://localhost:3001/tools/low-stock-items?labName=实验室A"
响应:
{
"success": true,
"queryType": "low_stock",
"count": 8,
"items": [
{
"name": "胰蛋白酶",
"current": 3,
"min": 5,
"deficit": 2
}
]
}
5. 获取缺货耗材
GET /tools/out-of-stock-items?labName=<实验室名>&limit=5
示例:
curl "http://localhost:3001/tools/out-of-stock-items?labName=实验室A"
响应:
{
"success": true,
"queryType": "out_of_stock",
"count": 5,
"items": [
{"name": "细胞培养板"}
]
}
6. 搜索库存
GET /tools/search-inventory?labName=<实验室名>&keyword=<关键词>&limit=5
参数:
keyword: 搜索关键词(匹配名称、编码、规格)limit: 返回数量限制(默认5)
示例:
curl "http://localhost:3001/tools/search-inventory?labName=实验室A&keyword=胰蛋白"
响应:
{
"success": true,
"queryType": "specific",
"count": 2,
"items": [
{
"name": "胰蛋白酶",
"quantity": 3,
"minQuantity": 5,
"expiryDate": "2024-06-01",
"status": "low_stock"
}
]
}
7. 检查特定耗材
GET /tools/check-item?labName=<实验室名>&itemName=<耗材名>
示例:
curl "http://localhost:3001/tools/check-item?labName=实验室A&itemName=胰蛋白酶"
响应:
{
"success": true,
"found": true,
"queryType": "check",
"item": {
"name": "胰蛋白酶",
"quantity": 3,
"minQuantity": 5,
"expiryDate": "2024-06-01",
"status": "low_stock",
"statusMessage": "库存不足"
}
}
8. 获取采购建议
GET /tools/purchase-suggestions?labName=<实验室名>
示例:
curl "http://localhost:3001/tools/purchase-suggestions?labName=实验室A"
响应:
{
"success": true,
"queryType": "purchase",
"summary": {
"totalItems": 128
},
"lowStock": [
{
"name": "胰蛋白酶",
"current": 3,
"min": 5,
"deficit": 2
}
],
"expiringSoon": [
{
"name": "胎牛血清",
"quantity": 8,
"expiryDate": "2024-04-01",
"daysLeft": 15
}
]
}
9. 健康检查
GET /health
示例:
curl "http://localhost:3001/health"
响应:
{
"status": "ok",
"service": "MCP HTTP Server for Lab Inventory",
"timestamp": "2024-03-11T08:00:00.000Z"
}
错误处理
所有端点在发生错误时返回统一格式:
{
"success": false,
"error": "错误信息描述"
}
常见错误:
- 400 Bad Request: 缺少必需参数(如
labName) - 500 Internal Server Error: 数据库连接或查询错误
与 AI 助手集成
由于本服务提供 HTTP REST API,任何支持 HTTP 请求的 AI 助手都可以调用。
与 AI 助手集成的步骤
-
启动本服务
npm start -
配置 AI 助手使用 Function Calling
告诉 AI 助手可用的 API 端点,让它根据用户问题自动选择合适的端点调用。
-
示例对话流程
用户:"库存怎么样?"
AI 助手分析 → 决定调用
/tools/inventory-summary?labName=实验室AAPI 返回:
{ "success": true, "data": { "totalItems": 128, "normalItems": 98, "expired": 5, "expiringSoon": 12, "lowStock": 8, "outOfStock": 5 } }AI 助手回复:"实验室A目前共有128件耗材,其中98件正常。需要注意:5件已过期,12件即将过期(30天内),8件库存不足,5件缺货。"
AI 助手集成示例代码
// AI 助手中的集成示例
async function queryInventory(userQuery, labName) {
// 根据用户问题决定调用哪个端点
let endpoint;
const baseUrl = 'http://localhost:3001';
if (userQuery.includes('过期')) {
endpoint = `${baseUrl}/tools/expired-items?labName=${encodeURIComponent(labName)}`;
} else if (userQuery.includes('库存') && userQuery.includes('怎么样')) {
endpoint = `${baseUrl}/tools/inventory-summary?labName=${encodeURIComponent(labName)}`;
} else if (userQuery.includes('还有多少')) {
const itemName = extractItemName(userQuery);
endpoint = `${baseUrl}/tools/check-item?labName=${encodeURIComponent(labName)}&itemName=${encodeURIComponent(itemName)}`;
}
const response = await fetch(endpoint);
return await response.json();
}
开发说明
项目结构
mcp/
├── http-server.js # HTTP 服务器主文件
├── package.json # 依赖配置
├── .env # 环境变量(不提交到 git)
├── .gitignore # Git 忽略文件
├── README.md # 本文档
└── CLAUDE.md # Claude Code 工作指南
数据库 Schema
库存数据表 (inventory collection) 结构:
{
name: String, // 耗材名称
code: String, // 耗材编码
category: String, // 分类
specification: String, // 规格
quantity: Number, // 当前数量
unit: String, // 单位
minQuantity: Number, // 最小库存量
expiryDate: Date, // 过期日期
labName: String, // 实验室名称(必需,用于数据隔离)
status: String, // 状态
createdAt: Date, // 创建时间
updatedAt: Date // 更新时间
}
添加新端点
- 在
http-server.js中添加新的 Express 路由:
app.get('/tools/your-new-endpoint', async (req, res) => {
try {
const { labName, otherParam } = req.query;
// 验证必需参数
if (!labName) {
return res.status(400).json({
success: false,
error: 'labName 参数必填'
});
}
// 执行数据库查询
const items = await Inventory.find({ labName, /* 其他条件 */ })
.select('field1 field2') // 只选择需要的字段
.limit(parseInt(limit || 10))
.lean(); // 返回普通 JS 对象
// 返回结果
res.json({
success: true,
queryType: 'your_type',
count: items.length,
items: items
});
} catch (error) {
res.status(500).json({
success: false,
error: error.message
});
}
});
- 更新启动日志(可选):
在 main() 函数中的 console.log 部分添加新端点的说明。
测试
测试服务器是否启动:
curl http://localhost:3001/health
测试特定端点:
curl "http://localhost:3001/tools/inventory-summary?labName=实验室A"
故障排查
问题 1:无法连接 MongoDB
错误信息:MongooseServerError: connect ECONNREFUSED
解决方法:
- 检查 MongoDB 是否运行:
# Windows mongosh # 或检查服务状态 net stat -ano | findstr :27017 - 检查
.env文件中的连接字符串是否正确 - 检查网络连接和防火墙设置
问题 2:端口被占用
错误信息:Error: listen EADDRINUSE: address already in use :::3001
解决方法:
# Windows - 查找占用端口的进程
netstat -ano | findstr :3001
# 终止进程(替换 PID)
taskkill /PID <进程ID> /F
# 或修改 .env 文件中的 PORT
PORT=3002
问题 3:找不到实验室数据
现象:查询返回 totalItems: 0 或 items: []
解决方法:
- 确认
labName参数拼写正确(区分大小写) - 连接 MongoDB 检查数据:
mongosh use test db.inventory.find({ labName: "实验室A" }) - 检查数据库中是否有该实验室的数据
- 查看所有实验室名称:
db.inventory.distinct("labName")
问题 4:依赖安装失败
错误信息:npm ERR! 或 ENOENT
解决方法:
# 清除缓存
npm cache clean --force
# 删除 node_modules 重新安装
rm -rf node_modules
npm install
# Windows 使用
rmdir /s /q node_modules
npm install
问题 5:响应速度慢
可能原因:
- MongoDB 查询未使用索引
- 返回数据量过大
解决方法:
- 为常用查询字段添加索引:
// 在 MongoDB 中创建索引 db.inventory.createIndex({ labName: 1 }) db.inventory.createIndex({ expiryDate: 1 }) db.inventory.createIndex({ name: "text", code: "text", specification: "text" }) - 使用
limit参数限制返回数量 - 使用
.select()只选择需要的字段
性能优化
Token 消耗对比
| 查询类型 | 传统方式 | MCP 方式 | 节省 |
|---|---|---|---|
| 库存摘要 | 5000 tokens | 100 tokens | 98% |
| 已过期 | 5000 tokens | 200 tokens | 96% |
| 特定耗材 | 5000 tokens | 300 tokens | 94% |
查询限制
所有查询都有 limit 参数,防止返回过多数据:
- 默认限制:5-10 条
- 可通过参数调整
安全说明
数据安全
- 环境变量 -
.env文件包含敏感信息(MongoDB 连接字符串),已加入.gitignore,不要提交到 git - 数据隔离 - 所有查询都需要
labName参数,确保不同实验室的数据隔离 - 只读操作 - 本服务只提供查询功能,不会修改数据库中的数据
生产环境部署建议
如果需要在生产环境部署,建议添加以下安全措施:
-
添加认证机制:
// 简单 API Key 验证示例 app.use((req, res, next) => { const apiKey = req.headers['x-api-key']; if (apiKey !== process.env.API_KEY) { return res.status(401).json({ success: false, error: 'Unauthorized' }); } next(); }); -
启用 CORS 限制:
app.use(cors({ origin: ['https://your-domain.com'], // 限制来源 credentials: true })); -
添加速率限制:
npm install express-rate-limitimport rateLimit from 'express-rate-limit'; const limiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 分钟 max: 100 // 限制每个 IP 100 次请求 }); app.use('/tools/', limiter); -
使用 HTTPS:在生产环境中使用反向代理(如 Nginx)提供 HTTPS
性能优化
已实现的优化
- 字段选择 - 使用
.select()只返回需要的字段 - 数量限制 - 所有查询都有
limit参数,默认限制 5-10 条 - 并行查询 - 使用
Promise.all()同时执行多个查询 - 精简响应 - 返回最少必要的数据
Token 消耗对比
| 查询类型 | 返回全部数据 | 本服务 | 节省 |
|---|---|---|---|
| 库存摘要 | ~5000 tokens | ~100 tokens | 98% |
| 已过期 | ~5000 tokens | ~200 tokens | 96% |
| 特定耗材 | ~5000 tokens | ~300 tokens | 94% |
查询限制
所有查询都有 limit 参数,防止返回过多数据:
- 默认限制:5-10 条
- 可通过 URL 参数调整(如
?limit=20) - 建议不超过 100 条
后续优化建议
-
添加缓存层
- 使用 Redis 缓存常用查询结果
- 设置合理的过期时间(如 5 分钟)
-
添加日志系统
- 记录查询历史和性能指标
- 使用 Winston 或 Pino 等日志库
-
添加监控
- 集成 Prometheus 监控
- 添加健康检查和告警
-
API 文档
- 使用 Swagger/OpenAPI 生成交互式文档
- 提供 API 调试界面
-
批量查询支持
- 支持一次查询多个实验室
- 支持批量检查多个耗材
-
WebSocket 支持
- 对于需要实时更新的场景
- 推送库存变化通知
测试
手动测试
使用以下命令测试各个端点:
# 健康检查
curl http://localhost:3001/health
# 库存摘要
curl "http://localhost:3001/tools/inventory-summary?labName=实验室A"
# 搜索耗材
curl "http://localhost:3001/tools/search-inventory?labName=实验室A&keyword=胰蛋白"
# 检查特定耗材
curl "http://localhost:3001/tools/check-item?labName=实验室A&itemName=胰蛋白酶"
使用 Postman 或 Insomnia
导入以下环境变量:
base_url:http://localhost:3001labName:实验室A
相关文档
技术栈
- Node.js - JavaScript 运行环境 (>= 18.0.0)
- Express.js - Web 应用框架
- Mongoose - MongoDB ODM
- MongoDB - NoSQL 数据库
- CORS - 跨域资源共享支持
许可证
MIT
贡献
欢迎提交 Issue 和 Pull Request!
更新日志
v1.0.0 (2024-03-11)
- 初始版本发布
- 提供 8 个 REST API 端点
- 支持库存查询、过期检查、低库存警告等功能
- 完整的错误处理和日志记录