An intelligent medical appointment scheduling system with doctor search, availability checking, and booking capabilities. Integrates with ChatGPT via OpenAI Apps SDK.
The Medical Appointment application demonstrates the power of combining Large Language Models with healthcare scheduling. It allows users to search for doctors, check availability, and book appointments using natural language (e.g., "Find me a cardiologist in São Paulo and schedule for tomorrow at 9am").
This app integrates with ChatGPT using the OpenAI Apps SDK, providing an interactive widget UI that renders inline with the conversation.
- Doctor Search: Find healthcare professionals by name, specialty, or city.
- Real-time Availability: Check available appointment slots for any doctor.
- Smart Booking: Schedule appointments with automatic slot management.
- Ambiguity Handling: Intelligent disambiguation when multiple doctors match the query.
- Interactive Widget: Rich UI rendered inside ChatGPT with clickable doctor cards and time slots.
The MCP server exposes the following tools to ChatGPT:
| Tool Name | Description | Parameters |
|---|---|---|
search_doctors |
Retrieves a list of doctors based on optional filters. | name?, specialty?, city? |
get_available_slots |
Returns available appointment times for a doctor. | doctorId? | doctorName?, specialty? |
schedule_appointment |
Books an appointment with a doctor. | doctorId? | doctorName?, slotId? | slotTime?, patientName, patientPhone |
The MCP server exposes the following resources:
| URI Pattern | Description |
|---|---|
doctor://list |
Returns all registered doctors |
doctor://{id}/slots |
Returns available slots for a specific doctor |
ui://widget/medical-app.html |
Interactive widget for ChatGPT UI |
- Server: Node.js + TypeScript (MCP SDK)
- Database: Supabase (PostgreSQL)
- Validation: Zod for schema validation
- Transport: HTTP (Streamable HTTP Transport)
- UI: Inline HTML widget with
text/html+skybridgeMIME type
Navigate to the project directory and install dependencies:
cd apps/medical-appointment/server
npm installCreate a .env file with your Supabase credentials:
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your-anon-or-service-role-key- Create a project on Supabase
- Go to the SQL Editor
- Run the SQL from
database/schema.sql - Seed data with
database/seeds/doctors.sql
Development:
npm run devProduction:
npm run build
npm startThe server listens on http://localhost:3001/mcp by default.
This app integrates with ChatGPT using the OpenAI Apps SDK:
- Tool calls return
structuredContent(for the model) and_meta(for the widget) - Widget resource (
ui://widget/medical-app.html) renders interactive UI - Widget reads data from
window.openai.toolOutputandwindow.openai.toolResponseMetadata - User interactions trigger new tool calls via
window.openai.callTool()
| View | Description |
|---|---|
doctors-list |
Shows list of doctors with clickable cards |
slots-list |
Shows available time slots for selected doctor |
confirmation |
Shows booking confirmation |
disambiguation |
Shows options when multiple doctors match |
npx @modelcontextprotocol/inspector node dist/index.jsOr test via HTTP:
# Configure in Inspector:
# Transport Type: Streamable HTTP
# URL: http://localhost:3001/mcp| Intent | Prompt Example | Expected Result |
|---|---|---|
| Doctor Search | "Find cardiologists in São Paulo" | Lists matching doctors |
| Availability Check | "What times does Dr. Silva have available?" | Shows available slots |
| Booking | "Schedule with Dr. Silva at 9am for Maria" | Creates appointment |
| Ambiguous Query | "See slots for Dr. Silva" (multiple exist) | Returns disambiguation options |
Widget Integration
- Tools return
_metaoutsidestructuredContentfor widget-only data - Widget reads from
window.openai.toolResponseMetadata - CSP configured for Supabase and Unsplash image domains
Ambiguity Resolution When multiple doctors match a name query, the system returns all matches with their specialties, allowing the LLM to ask the user for clarification.
Slot Management The booking flow atomically checks availability, marks the slot as booked, and creates the appointment record - preventing double-bookings.
apps/medical-appointment/
├── database/ # SQL scripts
│ ├── schema.sql # Table definitions
│ └── seeds/
│ └── doctors.sql # Sample data
├── docs/ # Project documentation
│ ├── 01-database-setup.md
│ ├── 02-server-architecture.md
│ ├── 03-mcp-tools.md
│ └── 04-mcp-resources.md
├── server/
│ ├── public/
│ │ └── widget.html # Interactive ChatGPT widget
│ └── src/
│ ├── index.ts # HTTP server + MCP setup
│ ├── config.ts # Environment configuration
│ ├── db/ # Data access layer (Supabase)
│ ├── mcp/ # MCP tools, resources, schemas
│ └── types/ # TypeScript interfaces
└── README.md # This file
- Database Setup - Schema and table definitions
- Server Architecture - Code patterns and design decisions
- MCP Tools Reference - Detailed tool documentation
- MCP Resources Reference - Resource URI patterns
The server can be deployed to any Node.js hosting platform:
- Railway: Auto-deploys from GitHub
- Vercel: Serverless functions
- Fly.io: Edge deployment
Ensure PORT environment variable is set by your hosting provider.
MIT