Skip to main content
Glama
MiltonPolanco

Clinic Laboratory MCP Server

README.md
# Clinic Laboratory MCP Server

Local Model Context Protocol server for following laboratory results in a small medical clinic. It stores synthetic patient data in SQLite and exposes tools to search patients, review current results, compare measurements over time, record new results, and manage pending exams.

This is the independent public server developed for the first CC3067 Networks project milestone. The console host that consumes it is maintained in a separate private repository.

## Features

- Local MCP communication through the `stdio` transport.
- Persistent SQLite storage with foreign keys, indexes, constraints, and transactions.
- Repeatable synthetic dataset for demonstrations.
- Date, ownership, numeric value, reference interval, and pending-exam validation.
- Audit entries for result and pending-exam creation.
- Automated domain tests.

## MCP specification

The server is started as a local process. It does not expose an HTTP port or REST endpoints. During MCP initialization it publishes six tools and one resource.

### Tools

| Tool | Required parameters | Optional parameters | Result |
| --- | --- | --- | --- |
| `search_patients` | `query: string` | None | Matching record numbers, names, and birth dates. |
| `get_latest_lab_results` | `medical_record: string` | `test_code: string` | Latest result for each test or one selected code. |
| `compare_lab_results` | `medical_record: string`, `test_code: string` | `start_date: string`, `end_date: string` | First and last observations, absolute change, percentage change, and direction. |
| `record_lab_result` | `medical_record: string`, `test_code: string`, `test_name: string`, `value: number`, `unit: string`, `collected_at: string` | `reference_min: number`, `reference_max: number`, `notes: string`, `pending_exam_id: integer` | Created result, reference status, and completed pending exam ID when supplied. |
| `list_pending_exams` | None | `medical_record: string`, `overdue_only: boolean` | Pending exams ordered by due date with an overdue flag. |
| `schedule_lab_exam` | `medical_record: string`, `test_code: string`, `test_name: string`, `ordered_at: string`, `due_date: string` | None | Created pending exam and its identifier. |

Dates use `YYYY-MM-DD`. `collected_at` accepts an ISO 8601 date or timestamp. Test codes are normalized to uppercase and medical record matching is case-insensitive.

Domain validation failures are returned by MCP as tool errors. Examples include an unknown patient, an invalid date range, a future collection date, an inverted reference interval, fewer than two observations for comparison, and a pending exam assigned to another patient.

### Resource

| URI | MIME type | Purpose |
| --- | --- | --- |
| `clinic://catalog/lab-tests` | `text/plain` | Lists the GLU, HBA1C, CHOL, CREA, and TSH codes used in the demonstration dataset. |

## Requirements

- Python 3.11 or newer
- [uv](https://docs.astral.sh/uv/)
- Node.js only when using MCP Inspector

## Installation

Clone the public repository and install its locked environment:

```powershell
git clone https://github.com/MiltonPolanco/clinic-lab-mcp-server.git
cd clinic-lab-mcp-server
uv sync --locked
```

Create or restore the demonstration database:

```powershell
uv run clinic-lab-seed --reset
```

The default database is `data/clinic.db`. It is generated locally and ignored by Git.

## Configuration

Set `CLINIC_DB_PATH` before starting the server to use another SQLite file:

```powershell
$env:CLINIC_DB_PATH = "C:\data\clinic-demo.db"
uv run clinic-lab-seed --reset
uv run clinic-lab-mcp
```

Without this variable, the server uses the database under the repository's `data` directory.

## Running the server

Start it directly over standard input/output:

```powershell
uv run clinic-lab-mcp
```

An MCP host normally starts this process. Example configuration:

```json
{
  "mcpServers": {
    "clinic_labs": {
      "command": "uv",
      "args": [
        "--directory",
        "C:\\absolute\\path\\to\\clinic-lab-mcp-server",
        "run",
        "clinic-lab-mcp"
      ]
    }
  }
}
```

Do not write diagnostic messages to standard output because MCP protocol messages use that stream. Application diagnostics should use standard error.

## Demonstration

After resetting the database, a representative sequence is:

1. Call `search_patients` with `{"query": "Ana"}`. The returned record is `P-1001`.
2. Call `get_latest_lab_results` with `{"medical_record": "P-1001"}`.
3. Call `compare_lab_results` with `{"medical_record": "P-1001", "test_code": "GLU"}`. The seeded glucose values decrease from 112 to 104 mg/dL.
4. Call `list_pending_exams` with `{"medical_record": "P-1001"}` and retain the returned exam ID.
5. Call `record_lab_result` with the patient, GLU result data, and that `pending_exam_id`.
6. Call `list_pending_exams` again and verify that the completed exam is no longer returned.

## MCP Inspector

Initialize the database and open the official Inspector:

```powershell
uv run clinic-lab-seed --reset
npx -y @modelcontextprotocol/inspector uv run clinic-lab-mcp
```

## Tests

Run all automated tests:

```powershell
uv run pytest
```

Run them with branch and line coverage:

```powershell
uv run pytest --cov=clinic_labs_mcp --cov-report=term-missing
```

## Data model

- `patients` identifies each fictional patient by medical record.
- `lab_results` stores dated numeric observations and reference intervals.
- `pending_exams` tracks pending, completed, or cancelled orders and can reference the result that completed an order.
- `audit_log` records creation operations and their associated entity.

SQLite connections enable foreign keys and use transactions so a result and its matching pending-exam update either complete together or are rolled back together.

## Source structure

```text
src/clinic_labs_mcp/
  database.py   SQLite schema and connection setup
  service.py    Validation and domain operations
  server.py     MCP tools, resource, and stdio entry point
  seed.py       Repeatable synthetic demonstration data
tests/
```

## Protocol notes

The implementation uses the official Python MCP SDK. Initialization negotiates capabilities through JSON-RPC 2.0, `tools/list` publishes the tool catalog, and `tools/call` invokes individual operations. The SDK handles protocol serialization while the functions in `server.py` implement the clinic behavior.

## License

This academic project is provided for demonstration and evaluation purposes.

TDQS

A3.6/5.0

Scored across 6 tools

Disambiguation5/5

Each tool targets a distinct action in the lab workflow: scheduling, recording, searching, retrieving, comparing, and listing pending exams. There is no meaningful overlap between tool purposes, so an agent can reliably select the right tool.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern, such as record_lab_result, schedule_lab_exam, and list_pending_exams. Modifiers like 'latest' and 'pending' are used uniformly and do not break the convention.

Tool Count5/5

Six tools is a well-scoped count for a laboratory-focused server. Each tool covers a clear part of the domain without unnecessary duplication or bloat.

Completeness4/5

The core lab workflow is well covered: search patients, schedule exams, record results, list pending exams, and retrieve/compare results. Minor gaps exist, such as no explicit update/cancel flow for scheduled exams or recorded results, but agents can work around these for typical lab tasks.

Maintenance

ActivityMaintained
ResponsivenessNo issues