å¥åº·äžå¥èº«æç»MCPæ¯äžæ¬Ÿç±äººå·¥æºèœé©±åšç绌åå¥èº«è·èžªåºçšçšåºïŒå®éè¿æš¡åäžäžæåè®®ïŒMCPïŒ ïŒåŒ¥åäºäŒ ç»å¥èº«åºçšäžæºèœAIèŸ å©ä¹éŽçå·®è·ã
git clone https://github.com/your-username/health-fitness-coach-mcp.git
cd health-fitness-coach-mcp
npm install
cp env.example .env.local
# æ·»å çšäºAIçæè®¡åçOPENAI_API_KEY
npm run dev
{
"mcpServers": {
"health-fitness-coach": {
"url": "http://localhost:3000/sse"
}
}
}
{
"mcpServers": {
"health-fitness-coach": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://localhost:3000/mcp"]
}
}
}
# çŽæ¥æµè¯MCPå·¥å
·
npm run test:fitness
# æµè¯ç¹å®ç«¯ç¹
curl http://localhost:3000/api/context?userId=default-user
http://localhost:3000 è¿è¡å¯è§åå¥èº«è·èžªâââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â å¥åº·äžå¥èº«æç»çæç³»ç» â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ€
â â
â âââââââââââââââââââââââ âââââââââââââââââââââââ âââââââââââââââââââ â
â â ð Webåºçš â â ð€ MCPæå¡åš â â ð§ AI客æ·ç«¯ â â
â â (Next.js) â â (åè®®å±) â â (Cursor/Claude) â â
â â â â â â â â
â â ⢠å¥èº«ä»ªè¡šç âââââºâ ⢠7䞪æºèœå·¥å
· âââââºâ ⢠èªç¶è¯èšäº€äº â â
â â ⢠掻åšè®°åœ â â â¢ æ°æ®å€ç â â ⢠äžäžææç¥ â â
â â ⢠è¿åºŠè·èžª â â ⢠äžäžæåæ â â ⢠计åçæ â â
â â ⢠计åå¯è§å â â ⢠APIéæ â â ⢠æºèœæ¥è¯¢ â â
â â â¢ å®æ¶æŽæ° â â ⢠åè®®åè§æ§ â â ⢠工å
·è°çš â â
â âââââââââââââââââââââââ âââââââââââââââââââââââ âââââââââââââââââââ â
â â â â â
â âââââââââââââââââââââââââââââŒââââââââââââââââââââââââââââ â
â â â
â âââââââââââââââââââââââââââââââââââââââŒââââââââââââââââââââââââââââââââââââââ â
â â ð ç»äžæ°æ®å± â â
â â â â
â â âââââââââââââââ âââââââââââââââ âââââââââââââââ âââââââââââââââ â â
â â â ðïž é»çŒè®°åœ â â ð è¥å
»è®°åœ â â ð 计åè®°åœ â â ð åéŠè®°åœ â â â
â â â ⢠é»çŒäŒè¯ â â ⢠饮é£è®°åœ â â ⢠AIçæè®¡å â â ⢠è¿åºŠè®°åœ â â â
â â â ⢠æç»æ¶éŽ â â ⢠å¡è·¯éæå
¥â â ⢠æ¯åšè®¡å â â ⢠ç¬è®°è®°åœ â â â
â â â ⢠é»çŒç±»å â â ⢠é£ç©é¡¹ç® â â â¢ æ¯æ¥è®¡å â â ⢠æŽå¯è®°åœ â â â
â â âââââââââââââââ âââââââââââââââ âââââââââââââââ âââââââââââââââ â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
æš¡åäžäžæåè®®ïŒMCPïŒ æ¯AIåºçšçšåºè¿æ¥å°å€éšæ°æ®æºåå·¥å ·çæ ååæ¹åŒãå¯ä»¥å°å ¶è§äžºäžäžªéçšç¿»è¯åšïŒäœ¿Claude DesktopæCursorçAI婿èœå€çè§£åäžäœ çå¥èº«æ°æ®è¿è¡äº€äºã
æä»¬çMCPæå¡åšå åœäžäžªæºèœå¥èº«æ°æ®çœå ³ïŒå ·æä»¥äžåèœïŒ
MCPæå¡åšæäŸäº7䞪æºèœå·¥å ·ïŒæ¹åäºAIäžå¥èº«æ°æ®çäº€äºæ¹åŒïŒ
log-workout - é»çŒäŒè¯è·èžª// åèœïŒäœ¿çšæºèœå类记åœé»çŒäŒè¯
{
tool: "log-workout",
parameters: {
userId: "user123",
date: "2025-01-07",
type: "strength training", // èªåšåç±»ïŒææ°§è¿åšãåéè®ç»ãæé§æ§è®ç»
duration: 45, // æŽ»åšæç»æ¶éŽïŒåéïŒ
distance: 0 // ææ°§è¿åšå¯éåæ°
}
}
// AIäžäžæïŒâæä»å€©è¿è¡äº45åéçåéè®ç»â
log-nutrition - 饮é£äžå¡è·¯éè·èžª// åèœïŒäœ¿çšæºèœè¥å
»åæè®°åœé¥®é£
{
tool: "log-nutrition",
parameters: {
userId: "user123",
date: "2025-01-07",
meal: "breakfast", // èªå𿣿µïŒæ©é€/åé€/æé€/é¶é£
items: ["oatmeal", "banana", "almonds"], // èªç¶è¯èšæè¿°çé£ç©é¡¹ç®
calories: 350 // è®¡ç®æäŒ°ç®çå¡è·¯é
}
}
// AIäžäžæïŒâææ©é€åäºç麊çãéŠèåæä»â
log-feedback - è¿åºŠäžåšåè·èžª// åèœïŒæè·äž»è§çå¥èº«äœéªåè¿åºŠç¬è®°
{
tool: "log-feedback",
parameters: {
userId: "user123",
date: "2025-01-07",
notes: "ç»è¿æç»é»çŒïŒæè§æŽåŒºå£®äºãåå€æææŽéçééïŒ"
}
}
// AIäžäžæïŒè·èžªåšåãèœéæ°Žå¹³åäž»è§è¿åºŠ
generate-plan - AI驱åšçå¥èº«è§å// åèœïŒå建䞪æ§åçé»çŒåè¥å
»è®¡å
{
tool: "generate-plan",
parameters: {
userId: "user123"
}
}
// AIéæ³ïŒåæäœ çåå²è®°åœãå奜åç®æ ïŒå建ïŒ
// - æå€©çé»çŒäŸçš
// - æ¯åšé»çŒè®¡å
// - 饮é£å»ºè®®
// - 鿥å¢å éŸåºŠçè°æŽ
view-context - å
šé¢çå¥èº«åæ// åèœïŒäžºAIå³çæäŸå®æŽçå¥èº«èµæ
{
tool: "view-context",
parameters: {
userId: "user123"
}
}
// è¿åïŒå®æŽçå¥èº«åå²è®°åœãæš¡åŒãç®æ åæŽå¯ä¿¡æ¯
// 䜿AIèœå€ååºææºçæç»å³ç
set-weekly-target - ç®æ 讟å®äžè·èžª// åèœïŒè®Ÿå®åè·èžªå¥èº«ç®æ
{
tool: "set-weekly-target",
parameters: {
userId: "user123",
weekStart: "2025-01-06",
targetRuns: 3, // æ¯åšææ°§è¿åšç®æ
calorieBudget: 2000 // æ¯æ¥å¡è·¯éç®æ
}
}
// AIäžäžæïŒå®ç°ä»¥ç®æ 䞺富åçæç»æå¡åè¿åºŠè·èžª
echo - ç³»ç»å¥åº·äžæµè¯// åèœïŒæµè¯MCPè¿æ¥åç³»ç»å¥åº·ç¶åµ
{
tool: "echo",
parameters: {
message: "Testing MCP connection"
}
}
// 䜿çšåºæ¯ïŒè°è¯åç¡®ä¿MCPæå¡åšååºæ£åžž
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â MCPæ°æ®æµ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ€
â â
â AIå·¥å
·äžççšæ·ïŒâæä»å€©åäº20äžªä¿¯å§æïŒæç»äº15åéâ â
â â â
â ⌠â
â âââââââââââââââââââââââ âââââââââââââââââââââââ âââââââââââââââââââ â
â â ð§ AIå€ç â â ð€ MCPåè®®å± â â ð æ°æ®ååš â â
â â â â â â â â
â â ⢠解ææåŸ âââââºâ ⢠工å
·éæ© âââââºâ ⢠ååšé»çŒè®°åœ â â
â â ⢠æåæ°æ® â â â¢ åæ°æ å° â â â¢ æŽæ°ç»è®¡ä¿¡æ¯ â â
â â â¢ éæ©æäœ â â ⢠æ§è¡å·¥å
·è°çš â â ⢠计ç®è¿åºŠ â â
â â â¢ æ ŒåŒåååº ââââââ ⢠è¿åç»æ ââââââ â â
â âââââââââââââââââââââââ âââââââââââââââââââââââ âââââââââââââââââââ â
â â â
â ⌠â
â AIååºïŒâ倪æ£äºïŒæå·²ç»è®°åœäºäœ 15åéçä¿¯å§æé»çŒãäœ ä»å€©çé»çŒç®æ æ¯60åéïŒç®å已宿15åéãâ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â 忥å£ç³»ç» â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ€
â â
â âââââââââââââââââââââââ âââââââââââââââââââââââ â
â â ð Webçé¢ â â ð€ AIçé¢ â â
â â â â â â
â â ⢠å¯è§å仪衚ç â â ⢠èªç¶è¯èšäº€äº â â
â â ⢠ç¹å»è®°åœåèœ â â ⢠äžäžææ¥è¯¢ â â
â â ⢠è¿åºŠåŸè¡šå±ç€º â â ⢠æºèœè§å â â
â â â¢ è®¡åæŸç€ºåèœ â â ⢠暡åŒåæ â â
â âââââââââââââââââââââââ âââââââââââââââââââââââ â
â â â â
â ⌠⌠â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â ð MCPæå¡åšæ žå¿ â â
â â â â
â â ⢠䞺䞀䞪æ¥å£æäŸç»äžçæ°æ®è®¿é® â â
â â ⢠äžèŽçäžå¡é»èŸåéªè¯æºå¶ â â
â â ⢠WebåAIä¹éŽç宿¶åæ¥ â â
â â ⢠æºèœçŒååæ§èœäŒå â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
ð€ Cursoräžççšæ·ïŒâæåå宿äº30åéçHIITé»çŒâ
ð€ AI + MCPå€çæµçšïŒ
1. AIè¯å«é»çŒè®°åœæåŸ
2. MCPè°çš `log-workout` å·¥å
·
3. ååšïŒé»çŒç±»å="HIIT"ïŒæç»æ¶éŽ=30ïŒæ¥æ=ä»å€©
4. æŽæ°æ¯æ¥è¿åºŠè®¡æ°åš
5. AIåå€éŒå±ä¿¡æ¯å¹¶æŽæ°è¿åºŠ
ð± WebåºçšïŒèªåšæŸç€ºæŽæ°åçé»çŒæ¶é¿åé»çŒå®ææ
åµ
ð€ Claudeäžççšæ·ïŒâæ ¹æ®ææ¬åšçé»çŒæ
åµïŒäžºæå建äžäžªæå€©çé»çŒè®¡åâ
ð€ AI + MCPå€çæµçšïŒ
1. MCPè°çš `view-context` åææ¬åšçé»çŒæŽ»åš
2. AIè¯å«æš¡åŒïŒäž»èŠæ¯äžè¢é»çŒïŒææ°§è¿åšèŸå°
3. MCPè°çš `generate-plan` å¹¶æäŸäžäžæä¿¡æ¯
4. å建äžäžªåŒºè°è
¿éšé»çŒåææ°§è¿åšç平衡计å
5. ååšæå€©çé»çŒè®¡å
ð± WebåºçšïŒæå€©çé»çŒéšåäŒå¡«å
AIçæçé»çŒé¡¹ç®
ð€ AIå·¥å
·äžççšæ·ïŒâææ³ååŸæŽå¥åº·ïŒåé€åºè¯¥åä»ä¹ïŒâ
ð€ AI + MCPå€çæµçšïŒ
1. MCPè°çš `view-context` æ£æ¥ä»å€©ç饮é£åå¡è·¯éç®æ
2. AIåæè¥å
»çŒºå£åå¡è·¯éé¢ç®
3. 建议å
·äœç饮é£å¹¶æäŸå¡è·¯é计æ°
4. çšæ·ç¡®è®€ïŒâæèŠåç€éž¡èæ²æâ
5. MCPè°çš `log-nutrition` è®°åœé¥®é£
ð± WebåºçšïŒæŽæ°è¥å
»è¿åºŠå饮é£åå²è®°åœ
npm run dev å¯åšåŒåæå¡åšhttp://localhost:3000/mcp 访é®http://localhost:3000 访é®// 䜿çšlog-workoutå·¥å
·è®°åœé»çŒ
{
tool: "log-workout",
parameters: {
userId: "user123",
date: "2025-01-07",
type: "strength training",
duration: 45,
distance: 0
}
}
// 䜿çšgenerate-planå·¥å
·çæäžªæ§åé»çŒè®¡å
{
tool: "generate-plan",
parameters: {
userId: "user123"
}
}
// 笊åMCPçå·¥å
·å®ä¹
export const logWorkoutTool = {
name: "log-workout",
description: "è®°åœé»çŒäŒè¯ïŒå
æ¬é»çŒç±»åãæç»æ¶éŽåå¯éçè·çŠ»",
inputSchema: {
type: "object",
properties: {
userId: { type: "string", description: "å¯äžççšæ·æ è¯ç¬Š" },
date: { type: "string", description: "æ¥æïŒæ ŒåŒäžºYYYY-MM-DD" },
type: { type: "string", description: "é»çŒç±»åïŒäŸåŠïŒ'è·æ¥'ã'åéè®ç»'ïŒ" },
duration: { type: "number", description: "æç»æ¶éŽïŒåéïŒ" },
distance: { type: "number", description: "è·çŠ»ïŒå
¬éïŒå¯éïŒ" }
},
required: ["userId", "date", "type", "duration"]
}
}
// 垊ææä¹
åé©åçå
åååš
export const workoutStore = createInMemoryStore<WorkoutEntry>()
export const nutritionStore = createInMemoryStore<NutritionEntry>()
export const planStore = createInMemoryStore<PlanEntry>()
// MCPå·¥å
·å®ç°
export async function logWorkout(params: LogWorkoutParams) {
const entry: WorkoutEntry = {
id: generateId(),
userId: params.userId,
date: params.date,
type: params.type,
duration: params.duration,
distance: params.distance,
timestamp: new Date().toISOString()
}
workoutStore.set(entry.id, entry)
return { success: true, entry }
}
// äžMCPéæçè倩æ¥å£
export async function processFitnessQuery(message: string, userId: string) {
const intent = detectIntent(message)
switch (intent.type) {
case 'log_workout':
return await callMCPTool('log-workout', {
userId,
date: intent.date,
type: intent.workoutType,
duration: intent.duration
})
case 'generate_plan':
return await callMCPTool('generate-plan', { userId })
case 'view_progress':
return await callMCPTool('view-context', { userId })
}
}
# æµè¯ææMCPå·¥å
·
npm run test:fitness
# æµè¯HTTPäŒ èŸ
npm run test:http
# æµè¯MCPéæ
npm run test:mcp
# è°è¯å·¥å
·åèœ
npm run debug:tools
// æµè¯é»çŒè®°åœ
const result = await mcpClient.callTool('log-workout', {
userId: 'test-user',
date: '2025-01-07',
type: 'running',
duration: 30,
distance: 5.0
})
console.log('é»çŒè®°åœæå:', result)
# çšäºAIçæå¥èº«è®¡åçOpenAI APIå¯é¥
OPENAI_API_KEY=your_openai_api_key_here
# å¯éçRedisïŒçšäºæé«æ§èœ
UPSTASH_REDIS_REST_URL=your_redis_url
UPSTASH_REDIS_REST_TOKEN=your_redis_token
# åçšæ·è®Ÿçœ®çèªå®ä¹çšæ·ID
DEFAULT_USER_ID=my-fitness-journey
# è°è¯æ¥å¿çº§å«
LOG_LEVEL=debug
# åŒåçšçèªå®ä¹ç«¯å£
PORT=3000
// åštools/ç®åœäžå建æ°å·¥å
·
export const myCustomTool = {
name: "my-custom-tool",
description: "æ€å·¥å
·çåèœæè¿°",
inputSchema: {
// å®ä¹åæ°
},
handler: async (params) => {
// å®ç°é»èŸ
}
}
// åštools/index.tsäžæ³šå
export const tools = [
// ... ç°æå·¥å
·
myCustomTool
]
components/ ç®åœäžæ·»å æ°ç»ä»¶app/api/ äžå建æ°åèœçAPIè·¯ç±app/page.tsx äžæŽæ°äž»ä»ªè¡šçMIT讞å¯è¯ - äœ å¯ä»¥èªç±äœ¿çšæ€é¡¹ç®äœäžºèªå·±çMCPæå¡åšåå¥èº«åºçšçåºç¡ã
æ¬é¡¹ç®å±ç€ºäºåŠäœæå»ºç产就绪çMCPæå¡åšïŒå°AIå·¥å ·äžç¹å®é¢åçåºçšçšåºè¿æ¥èµ·æ¥ïŒäžºå ¶ä»é¢åçç±»äŒŒéææäŸäºæš¡æ¿ã
ð€ ç±æš¡åäžäžæåè®®æäŸæ¯æ
å°AIæºèœäžç°å®äžççå¥èº«æ°æ®è¿æ¥èµ·æ¥