Skip to main content
Glama

MCP Glucose Server

by lucas-1000
index.ts6.53 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { ListToolsRequestSchema, CallToolRequestSchema, Tool, } from '@modelcontextprotocol/sdk/types.js'; import { HealthDataAPI } from './api-client.js'; import dotenv from 'dotenv'; dotenv.config(); // Configuration const STORAGE_API_URL = process.env.STORAGE_API_URL || ''; const API_SECRET = process.env.API_SECRET || ''; const DEFAULT_USER_ID = process.env.USER_ID || ''; if (!STORAGE_API_URL || !API_SECRET) { console.error('❌ Error: STORAGE_API_URL and API_SECRET environment variables are required'); process.exit(1); } // Initialize API client const api = new HealthDataAPI(STORAGE_API_URL, API_SECRET); // Define MCP tools const tools: Tool[] = [ { name: 'get_glucose_readings', description: 'Get glucose/blood sugar readings for a user within a date range. Returns glucose values in mg/dL with timestamps and sources.', inputSchema: { type: 'object', properties: { userId: { type: 'string', description: `User identifier. Defaults to ${DEFAULT_USER_ID || 'configured user'} if not specified.`, }, startDate: { type: 'string', description: 'Start date in ISO 8601 format (e.g., 2025-10-01T00:00:00Z). Optional.', }, endDate: { type: 'string', description: 'End date in ISO 8601 format (e.g., 2025-10-22T23:59:59Z). Optional.', }, limit: { type: 'number', description: 'Maximum number of readings to return (default: 1000)', }, }, required: [], }, }, { name: 'get_latest_glucose', description: 'Get the most recent glucose/blood sugar reading for a user. Returns value, unit, timestamp, and source.', inputSchema: { type: 'object', properties: { userId: { type: 'string', description: `User identifier. Defaults to ${DEFAULT_USER_ID || 'configured user'} if not specified.`, }, }, required: [], }, }, { name: 'get_glucose_stats', description: 'Get glucose statistics (count, average, min, max) for a user within a date range. Useful for understanding glucose trends and patterns.', inputSchema: { type: 'object', properties: { userId: { type: 'string', description: `User identifier. Defaults to ${DEFAULT_USER_ID || 'configured user'} if not specified.`, }, startDate: { type: 'string', description: 'Start date in ISO 8601 format. Optional.', }, endDate: { type: 'string', description: 'End date in ISO 8601 format. Optional.', }, }, required: [], }, }, ]; // Create MCP server const server = new Server( { name: 'mcp-glucose', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); // List available tools server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools }; }); // Handle tool calls server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; const userId = (args?.userId as string) || DEFAULT_USER_ID; if (!userId) { return { content: [ { type: 'text', text: 'Error: userId is required. Either provide it in the tool call or set USER_ID environment variable.', }, ], isError: true, }; } try { switch (name) { case 'get_glucose_readings': { const readings = await api.getGlucoseReadings({ userId, startDate: args?.startDate as string | undefined, endDate: args?.endDate as string | undefined, limit: (args?.limit as number) || 1000, }); return { content: [ { type: 'text', text: JSON.stringify( { count: readings.length, readings: readings.map((r) => ({ value: r.value, unit: r.unit, date: r.date, source: r.source, })), }, null, 2 ), }, ], }; } case 'get_latest_glucose': { const reading = await api.getLatestGlucose(userId); if (!reading) { return { content: [ { type: 'text', text: 'No glucose readings found for this user.', }, ], }; } return { content: [ { type: 'text', text: JSON.stringify( { value: reading.value, unit: reading.unit, date: reading.date, source: reading.source, }, null, 2 ), }, ], }; } case 'get_glucose_stats': { const stats = await api.getGlucoseStats({ userId, startDate: args?.startDate as string | undefined, endDate: args?.endDate as string | undefined, }); if (!stats) { return { content: [ { type: 'text', text: 'No glucose data found for the specified time range.', }, ], }; } return { content: [ { type: 'text', text: JSON.stringify(stats, null, 2), }, ], }; } default: throw new Error(`Unknown tool: ${name}`); } } catch (error: any) { console.error('❌ Error calling tool:', error); return { content: [ { type: 'text', text: `Error: ${error.message}`, }, ], isError: true, }; } }); // Start server async function main() { const transport = new StdioServerTransport(); await server.connect(transport); console.error('✅ MCP Glucose Server running on stdio'); console.error(`📊 Connected to storage API: ${STORAGE_API_URL}`); console.error(`👤 Default user: ${DEFAULT_USER_ID || '(none - must specify in tool calls)'}`); } main();

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/lucas-1000/mcp-glucose'

If you have feedback or need assistance with the MCP directory API, please join our Discord server