@juejueeileen/bmi-mcp-server
v1.0.0
Published
A custom MCP server for BMI calculation - built with TypeScript
Maintainers
Readme
BMI MCP Server
一个基于 TypeScript 构建的自定义 MCP (Model Context Protocol) 服务器,提供 BMI 计算、体重单位转换和健康建议功能。
本项目是 MCP Server 开发的完整教程示例。
📋 目录
功能特性
Tools (工具)
| 工具名 | 描述 |
|--------|------|
| calculate-bmi | 根据身高(m)和体重(kg)计算 BMI 值和分类 |
| convert-weight | 在千克(kg)和磅(lb)之间转换体重 |
| get-bmi-recommendations | 根据 BMI 值获取健康建议 |
Resources (资源)
| 资源 URI | 描述 |
|----------|------|
| bmi://categories | BMI 分类参考表 |
Prompts (提示)
| 提示名 | 描述 |
|--------|------|
| analyze-bmi | 生成 BMI 分析提示词 |
快速开始
环境要求
- Node.js >= 18.0.0
- npm 或 yarn
安装与运行
# 1. 克隆项目
git clone https://github.com/opencode/bmi-mcp-server.git
cd bmi-mcp-server
# 2. 安装依赖
npm install
# 3. 直接运行(stdio 模式,用于 opencode 等客户端)
npx tsx src/server.ts接入 OpenCode
在 OpenCode 配置文件中添加 MCP Server:
全局配置 (~/.config/opencode/opencode.json):
{
"$schema": "https://opencode.ai/config.json",
"plugin": ["oh-my-opencode"],
"mcpServers": {
"bmi-mcp-server": {
"command": "npx",
"args": [
"tsx",
"/path/to/bmi-mcp-server/src/server.ts"
],
"type": "stdio"
}
}
}项目配置 (.opencode.json in project root):
{
"mcpServers": {
"bmi-mcp-server": {
"command": "npx",
"args": ["tsx", "./src/server.ts"],
"type": "stdio"
}
}
}配置完成后,重启 OpenCode 即可使用 BMI 计算工具。
项目结构
bmi-mcp-server/
├── src/
│ └── server.ts # 主服务文件(stdio 模式,Tools/Resources/Prompts 定义)
├── dist/ # 编译输出目录
├── package.json # npm 包配置
├── tsconfig.json # TypeScript 配置
├── server.json # MCP Registry 元数据
├── .gitignore # Git 忽略配置
└── README.md # 项目文档注意: 本项目使用 stdio 传输模式(而非 HTTP),适用于与 OpenCode、Claude Desktop 等 MCP 客户端集成。
API 参考
Tool: calculate-bmi
计算身体质量指数 (BMI)。
输入参数:
{
"weightKg": 70, // 体重(千克)
"heightM": 1.75 // 身高(米)
}输出:
{
"bmi": 22.86,
"category": "Normal weight"
}Tool: convert-weight
在千克和磅之间转换体重。
输入参数:
{
"value": 150,
"fromUnit": "lb",
"toUnit": "kg"
}输出:
{
"originalValue": 150,
"originalUnit": "lb",
"convertedValue": 68.04,
"convertedUnit": "kg"
}Tool: get-bmi-recommendations
根据 BMI 值获取健康建议。
输入参数:
{
"bmi": 28.5
}输出:
{
"category": "Overweight",
"recommendations": [
"Aim for gradual weight loss (0.5-1 kg per week)",
"Increase physical activity to 200+ minutes per week",
"Focus on whole foods, reduce processed food intake",
"Monitor portion sizes and practice mindful eating"
]
}完整教程:从零构建 MCP Server
第一部分:理解 MCP 生态
什么是 MCP?
MCP (Model Context Protocol) 是一个开放协议,为 LLM 应用与外部数据源/工具之间提供标准化的连接方式。类似于 USB-C 为设备提供了标准化的连接接口,MCP 为 AI 模型提供了标准化的方式来连接不同的数据源和工具。
核心组件
┌─────────────────────────────────────────────────────────────┐
│ MCP 生态 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ MCP Protocol ┌─────────────┐ │
│ │ │ ◄──────────────────► │ │ │
│ │ MCP Client │ │ MCP Server │ │
│ │ │ │ │ │
│ │ (LLM App) │ │ (Tools/ │ │
│ │ - Copilot │ │ Resources/ │ │
│ │ - Claude │ │ Prompts) │ │
│ │ - Custom │ │ │ │
│ └─────────────┘ └─────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ MCP Registry │ │
│ │ (Server 发现和发布平台) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘| 组件 | 说明 | |------|------| | Server | 暴露工具(Tools)、资源(Resources)、提示(Prompts)给 LLM 使用 | | Client | LLM 应用程序,通过 MCP 协议连接 Server | | Registry | 社区驱动的 MCP Server 发现和发布平台 | | SDK | 官方提供的 TypeScript/Python SDK 用于构建 Server 和 Client |
MCP 的三个核心概念
Tools (工具) - 可被 LLM 调用的操作,类似函数调用
- 例如:搜索、计算、数据库查询
- 类比:REST API 的 POST 端点
Resources (资源) - 只读的数据源,类似 GET 请求
- 例如:文件内容、数据库记录、配置信息
- 类比:REST API 的 GET 端点
Prompts (提示) - 预定义的提示模板
- 例如:代码审查模板、文档生成模板
- 类比:可复用的系统提示
第二部分:项目初始化
2.1 创建项目目录
mkdir bmi-mcp-server
cd bmi-mcp-server2.2 初始化 npm 项目
npm init -y2.3 安装依赖
# 核心依赖
npm install @modelcontextprotocol/server @modelcontextprotocol/express @modelcontextprotocol/node express zod
# 开发依赖
npm install -D typescript ts-node @types/express @types/node2.4 创建 TypeScript 配置
创建 tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "commonjs",
"lib": ["ES2022"],
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"moduleResolution": "node"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}2.5 创建项目结构
bmi-mcp-server/
├── src/
│ └── server.ts # 主服务文件
├── dist/ # 编译输出 (自动生成)
├── package.json
├── tsconfig.json
└── README.md第三部分:实现 MCP Server
3.1 基础框架
创建 src/server.ts:
import { McpServer } from '@modelcontextprotocol/server';
import { createMcpExpressApp } from '@modelcontextprotocol/express';
import { NodeStreamableHTTPServerTransport } from '@modelcontextprotocol/node';
import { z } from 'zod';
// 初始化 MCP Server
const server = new McpServer({
name: 'bmi-mcp-server',
version: '1.0.0',
});
// ... Tools/Resources/Prompts 定义 ...
// 创建 Express 应用并挂载 MCP
const app = createMcpExpressApp();
app.post('/mcp', async (req, res) => {
const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
});
app.listen(3000, () => {
console.log('MCP Server running on http://localhost:3000/mcp');
});3.2 注册 Tool (工具)
server.registerTool(
'calculate-bmi', // 工具 ID
{
title: 'BMI Calculator', // 显示标题
description: 'Calculate Body Mass Index', // 描述
inputSchema: z.object({ // 输入参数 Schema
weightKg: z.number().positive(),
heightM: z.number().positive(),
}),
outputSchema: z.object({ // 输出 Schema
bmi: z.number(),
category: z.string(),
}),
},
async ({ weightKg, heightM }) => { // 实现函数
const bmi = weightKg / (heightM * heightM);
return {
content: [{ type: 'text', text: JSON.stringify({ bmi, category: getBmiCategory(bmi) }) }],
structuredContent: { bmi, category: getBmiCategory(bmi) },
};
}
);3.3 注册 Resource (资源)
server.registerResource(
'bmi-categories', // 资源 ID
'bmi://categories', // 资源 URI
{
title: 'BMI Categories',
description: 'Reference table of BMI categories',
mimeType: 'application/json',
},
async () => ({
contents: [{
uri: 'bmi://categories',
mimeType: 'application/json',
text: JSON.stringify({ categories: [...] }),
}],
})
);3.4 注册 Prompt (提示)
server.registerPrompt(
'analyze-bmi',
{
title: 'Analyze BMI Results',
description: 'Generate a prompt for analyzing BMI results',
},
async () => ({
messages: [{
role: 'user',
content: {
type: 'text',
text: 'Analyze the BMI results and provide health assessment...',
},
}],
})
);第四部分:传输层配置
MCP 支持多种传输方式:
Streamable HTTP (推荐用于 Web 服务)
import { createMcpExpressApp } from '@modelcontextprotocol/express';
const app = createMcpExpressApp();
app.post('/mcp', async (req, res) => {
const transport = new NodeStreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
});stdio (推荐用于 CLI 工具)
import { StdioServerTransport } from '@modelcontextprotocol/server';
const transport = new StdioServerTransport();
await server.connect(transport);DNS 重绑定防护
使用 @modelcontextprotocol/express 提供的 createMcpExpressApp() 可以自动启用主机头验证,防止本地服务被恶意域名劫持。
第五部分:测试 MCP Server
5.1 启动服务器
# 开发模式
npm run dev
# 或构建后运行
npm run build
npm start5.2 使用 MCP Client 测试
可以使用官方的 MCP Inspector 或编写简单的测试脚本:
import { Client } from '@modelcontextprotocol/client';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/client';
const client = new Client({ name: 'test-client', version: '1.0.0' });
const transport = new StreamableHTTPClientTransport({
url: 'http://localhost:3000/mcp',
});
await client.connect(transport);
// 调用 calculate-bmi 工具
const result = await client.callTool({
name: 'calculate-bmi',
arguments: { weightKg: 70, heightM: 1.75 },
});
console.log(result);5.3 健康检查
curl http://localhost:3000/health响应示例:
{
"status": "healthy",
"server": "bmi-mcp-server",
"version": "1.0.0",
"timestamp": "2024-01-15T10:30:00.000Z"
}发布到 MCP Registry
📖 官方文档:Publish Your MCP Server
6.1 部署方式概述
MCP Server 可以通过以下方式发布:
| 方式 | 说明 | |------|------| | 📦 Package Deployment | 发布到 npm/PyPI/NuGet/Docker,运行在客户端本地 | | 🌐 Remote Deployment | 托管为 Web 服务,客户端直接连接 | | 🔄 Hybrid Deployment | 同时支持 Package 和 Remote 方式 |
6.2 安装 mcp-publisher CLI
Windows (PowerShell):
$arch = if ([System.Runtime.InteropServices.RuntimeInformation]::ProcessArchitecture -eq "Arm64") { "arm64" } else { "amd64" }
Invoke-WebRequest -Uri "https://github.com/modelcontextprotocol/registry/releases/download/v1.0.0/mcp-publisher_1.0.0_windows_$arch.tar.gz" -OutFile "mcp-publisher.tar.gz"
tar xf mcp-publisher.tar.gz mcp-publisher.exe
# 将 mcp-publisher.exe 移到 PATH 中的目录macOS/Linux:
brew install mcp-publisher6.3 初始化 server.json
cd /path/to/your/mcp-server
mcp-publisher init这会自动创建带有检测值的 server.json。
6.4 配置 server.json
选择命名空间
io.github.yourname/*- 需要 GitHub 认证com.yourcompany/*- 需要 DNS 验证
Package Deployment (NPM 为例)
1. 更新 package.json 添加 mcpName:
{
"name": "@yourname/bmi-mcp-server",
"version": "1.0.0",
"mcpName": "io.github.yourname/bmi-mcp-server"
}2. 配置 server.json:
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
"name": "io.github.yourname/bmi-mcp-server",
"description": "A custom MCP server for BMI calculation, weight conversion, and health recommendations",
"version": "1.0.0",
"packages": [
{
"registry_type": "npm",
"identifier": "@yourname/bmi-mcp-server",
"version": "1.0.0"
}
]
}Remote Deployment (可选)
如果需要远程部署:
{
"name": "io.github.yourname/bmi-mcp-server",
"description": "Remote BMI MCP Server",
"version": "1.0.0",
"remotes": [
{
"type": "sse",
"url": "https://your-server.example.com/sse"
}
]
}6.5 发布到 npm (Package 方式)
# 登录 npm
npm login
# 发布包
npm publish --access public6.6 认证 MCP Registry
GitHub 认证 (用于 io.github. 命名空间):*
mcp-publisher login github这会打开浏览器进行 OAuth 认证。
6.7 发布服务器
mcp-publisher publish成功输出:
✓ Successfully published6.8 验证发布
curl "https://registry.modelcontextprotocol.io/v0/servers?search=io.github.yourname/bmi-mcp-server"bmi-mcp-server 完整发布配置示例
{
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
"name": "io.github.opencode/bmi-mcp-server",
"description": "A custom MCP server for BMI calculation, weight conversion, and health recommendations. Built with TypeScript.",
"version": "1.0.0",
"packages": [
{
"registry_type": "npm",
"identifier": "@opencode/bmi-mcp-server",
"version": "1.0.0"
}
],
"homepage": "https://github.com/opencode/bmi-mcp-server",
"keywords": ["mcp", "mcp-server", "bmi", "health", "calculator"]
}📖 完整发布指南:modelcontextprotocol.info
最佳实践
安全性
| 实践 | 说明 |
|------|------|
| DNS 重绑定防护 | 使用 createMcpExpressApp() 自动启用主机头验证 |
| 认证 | 为远程服务器配置 OAuth / Token 认证 |
| 输入验证 | 使用 Zod 严格验证所有输入参数 |
类型安全
| 实践 | 说明 |
|------|------|
| Schema 定义 | 为所有 Tools 定义 inputSchema 和 outputSchema |
| 结构化输出 | 返回 structuredContent 便于客户端解析 |
| TypeScript | 使用 TypeScript 保证编译期类型安全 |
可维护性
| 实践 | 说明 |
|------|------|
| 版本管理 | 遵循语义化版本 (SemVer) |
| 文档 | 为每个 Tool/Resource/Prompt 提供清晰的描述 |
| 日志 | 使用 MCP SDK 内置的日志 API |
| 健康检查 | 实现 /health 端点便于监控 |
性能优化
| 实践 | 说明 | |------|------| | 传输选择 | Web 服务用 Streamable HTTP,CLI 用 stdio | | 异步处理 | 所有 Tool 实现使用 async/await | | 资源清理 | 确保 transport 连接正确关闭 |
官方资源
| 资源 | 链接 | |------|------| | MCP 官方文档 | modelcontextprotocol.io | | TypeScript SDK | github.com/modelcontextprotocol/typescript-sdk | | Python SDK | github.com/modelcontextprotocol/python-sdk | | MCP Registry | github.com/modelcontextprotocol/registry | | Server 开发指南 (TS) | typescript-sdk/docs/server.md | | Registry Quickstart | registry/quickstart.mdx | | GitHub MCP Server 文档 | docs.github.com - Set up MCP Server | | SDKs 概览页 | modelcontextprotocol.io/docs/sdk |
BMI 分类参考
| 分类 | BMI 范围 | |------|----------| | 体重不足 (Underweight) | < 18.5 | | 正常体重 (Normal weight) | 18.5 - 24.9 | | 超重 (Overweight) | 25 - 29.9 | | 肥胖 I 级 (Obesity Class I) | 30 - 34.9 | | 肥胖 II 级 (Obesity Class II) | 35 - 39.9 | | 肥胖 III 级 (Obesity Class III) | ≥ 40 |
许可证
MIT License
贡献
欢迎提交 Issue 和 Pull Request!
