Skip to main content
Glama
therobertmack

mcp-server-demo

README.md
# MCP Server Demo — Node/Express + PostgreSQL + Model Context Protocol

A minimal, **production-pattern** example of an [MCP](https://modelcontextprotocol.io)
server that exposes database-backed tools to an AI client, secured with an OAuth-style
bearer flow. Built to demonstrate the architecture I use in real systems, with demo data
only — no real records, keys, or credentials.

> Author: Robert Mack · Full-stack / AI-automation engineer · Remote, contract/fractional

---

## What this demonstrates

- **MCP server** exposing typed tools an AI model can call (`list_cases`, `get_case`, `add_note`)
- **PostgreSQL** as the backing store, with a clean data-access layer (no SQL in the route handlers)
- **OAuth 2.0–style bearer-token auth** on the protected endpoints (PKCE-ready pattern)
- **Express** REST API with input validation and structured error handling
- **Docker / docker-compose** for one-command local spin-up (API + database)
- Separation of concerns: routes → service layer → db layer

This is the same shape as the production systems I build — an operations platform with an
AI control layer that can act on live data **safely**, because every tool call is
authenticated, validated, and scoped.

---

## Architecture

```
AI client  ──(MCP / bearer token)──>  Express API  ──>  service layer  ──>  PostgreSQL
                                          │
                                          └── tool registry: list_cases, get_case, add_note
```

- `src/server.js` — Express app, auth middleware, MCP endpoint wiring
- `src/mcp.js` — tool registry: each tool's schema + handler
- `src/db.js` — PostgreSQL access layer (parameterized queries only)
- `src/auth.js` — bearer-token validation (OAuth2/PKCE-ready)
- `schema.sql` — demo table + seed data
- `docker-compose.yml` — API + Postgres, one command

---

## Run it locally

```bash
# 1. Start Postgres + API together
docker compose up --build

# 2. The API is now on http://localhost:3000
#    A demo bearer token is printed on startup (demo only — never hardcode real tokens)

# 3. List the MCP tools
curl -H "Authorization: Bearer demo-token-123" http://localhost:3000/mcp/tools

# 4. Call a tool
curl -X POST http://localhost:3000/mcp/call \
  -H "Authorization: Bearer demo-token-123" \
  -H "Content-Type: application/json" \
  -d '{"tool":"list_cases","args":{}}'
```

---

## Notes on production use

In a real deployment the bearer token is issued via a full OAuth 2.0 + PKCE flow (not the
static demo token here), the database runs as a managed/containerized service with secrets
injected at runtime (never committed), and the server runs behind TLS. This repo keeps
those pieces deliberately simple so the **patterns** are readable in one sitting.

## License
MIT — demo/educational use.