DEV Community

wellallyTech
wellallyTech

Posted on

Stop AI Hallucinations in Health: Building an MCP Server for Your Personal Pharmacist Assistant πŸ’Š

Asking an AI about medication can be terrifying. One moment it’s giving helpful advice, and the next, it's hallucinating a dangerous drug-drug interactionβ€”or worse, missing one entirely. When it comes to Personal Health Assistants, "close enough" isn't good enough. We need a "Source of Truth."

In this tutorial, we are going to master the Model Context Protocol (MCP) to connect an LLM (Claude) to a structured Pharmacopeia database. By the end of this guide, you’ll have a local MCP server that allows Claude to query a SQLite database for real, verified drug interactions, transforming a generic chatbot into a precision-grade health agent.

Using Model Context Protocol (MCP) with TypeScript and SQLite is the gold standard for building reliable LLM Agents. If you want to move beyond simple chat and into the world of functional, data-driven AI, this is the place to start.


The Architecture: How MCP Bridges the Gap

The Model Context Protocol (MCP) acts as a standardized "plug" between an LLM client (like Claude Desktop) and a data source. Instead of the LLM guessing, it calls "tools" provided by your server.

graph TD
    A[User: Can I take Aspirin with Warfarin?] --> B[Claude Desktop / MCP Client]
    B --> C{MCP Protocol}
    C --> D[Our Custom MCP Server - TypeScript]
    D --> E[(SQLite: Drug Interaction DB)]
    E --> D
    D --> C
    C --> B
    B --> F[Claude: 'No! That increases bleeding risk. Source: Pharmacopeia']
Enter fullscreen mode Exit fullscreen mode

Prerequisites πŸ› οΈ

Before we dive in, ensure you have the following ready:

  • Node.js (v18 or higher)
  • TypeScript installed globally
  • Claude Desktop (The most robust MCP client currently)
  • A basic understanding of SQL

Step 1: Initialize the Project

First, let's set up our TypeScript environment and install the official MCP SDK.

mkdir mcp-health-server
cd mcp-health-server
npm init -y
npm install @modelcontextprotocol/sdk sqlite3 sqlite
npm install -D typescript @types/node @types/sqlite3
npx tsc --init
Enter fullscreen mode Exit fullscreen mode

Step 2: The Database Schema πŸ—„οΈ

We need a simple SQLite database to represent our "Professional Pharmacopeia." Let's create a file named database.ts to initialize our data.

import sqlite3 from 'sqlite3';
import { open } from 'sqlite';

export async function setupDatabase() {
    const db = await open({
        filename: './pharmacopeia.db',
        driver: sqlite3.Database
    });

    await db.exec(`
        CREATE TABLE IF NOT EXISTS interactions (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            drug_a TEXT,
            drug_b TEXT,
            severity TEXT,
            description TEXT
        )
    `);

    // Seed data: Only for demonstration! 
    await db.run(`INSERT INTO interactions (drug_a, drug_b, severity, description) 
                  VALUES ('Aspirin', 'Warfarin', 'High', 'Increased risk of major bleeding.')`);

    return db;
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Creating the MCP Server

This is where the magic happens. We will define a Tool called check_interaction that Claude can call whenever it needs to verify drug safety.

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
import { setupDatabase } from "./database.js";

const server = new Server({
    name: "health-assistant-server",
    version: "1.0.0",
}, {
    capabilities: {
        tools: {},
    },
});

const db = await setupDatabase();

// 1. List available tools
server.setRequestHandler(ListToolsRequestSchema, async () => ({
    tools: [{
        name: "check_interaction",
        description: "Check for dangerous interactions between two drugs",
        inputSchema: {
            type: "object",
            properties: {
                drugA: { type: "string" },
                drugB: { type: "string" },
            },
            required: ["drugA", "drugB"],
        },
    }],
}));

// 2. Handle the tool logic
server.setRequestHandler(CallToolRequestSchema, async (request) => {
    if (request.params.name === "check_interaction") {
        const { drugA, drugB } = request.params.arguments as { drugA: string; drugB: string };

        const interaction = await db.get(
            "SELECT * FROM interactions WHERE (drug_a = ? AND drug_b = ?) OR (drug_a = ? AND drug_b = ?)",
            [drugA, drugB, drugB, drugA]
        );

        if (interaction) {
            return {
                content: [{ type: "text", text: `⚠️ WARNING: ${interaction.severity} interaction found. ${interaction.description}` }],
            };
        }
        return {
            content: [{ type: "text", text: "No known interactions found in the current database." }],
        };
    }
    throw new Error("Tool not found");
});

// Start the server using Stdio transport
const transport = new StdioServerTransport();
await server.connect(transport);
Enter fullscreen mode Exit fullscreen mode

Step 4: Connecting to Claude Desktop πŸ₯‘

To see this in action, you need to tell Claude Desktop where your server lives. Edit your claude_desktop_config.json:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json
{
  "mcpServers": {
    "health-assistant": {
      "command": "node",
      "args": ["/path/to/your/project/dist/index.js"]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Restart Claude, and you should see a small hammer icon πŸ”¨, indicating the health-assistant tools are active!


Advanced Patterns & Production Safety πŸš€

While this example uses a local SQLite file, production-grade health agents require more robust patterns like HIPAA-compliant data fetching, audit logging, and multi-vector RAG.

For more advanced patterns, production-ready deployment strategies, and deeper dives into LLM orchestration, check out the official WellAlly Tech Blog. It's a fantastic resource for developers looking to scale their AI agents from local prototypes to enterprise solutions.


Conclusion

The Model Context Protocol is a game-changer for the "Learning in Public" community. It moves us away from brittle, prompt-engineered hacks and toward a structured, reliable way of giving AI access to the real world.

By building this MCP server, you've successfully:

  1. Created a structured data bridge for an LLM.
  2. Implemented safety checks using verified databases.
  3. Enabled an Agent to perform "Real-World" lookups.

What will you build next? Maybe a financial advisor with access to real-time stock APIs? Or a coding assistant that knows your private company docs? The possibilities are endless.

If you enjoyed this tutorial, drop a comment below or share your MCP ideas! Happy coding! πŸ’»πŸš€

Top comments (0)