Graph CRM MCP Server

Graph CRM MCP Server

Enables AI assistants like Claude to read and write contacts, relationships, and interactions in a personal CRM via a graph-based API.

Category
Visit Server

README

Graph CRM

A personal, single-user CRM that visualizes contacts and their relationships as a graph. Node/Express + Prisma backend (SQLite by default), vanilla JS frontend (no build step), WebAuthn passkey login, and an MCP server exposing the full API so Claude can read/write the CRM directly.

Setup

npm install
cp .env.example .env
npx prisma migrate deploy
npm start              # http://localhost:3000

First visit walks you through creating a passkey (Face ID / Touch ID / security key / device screen lock). See .env.example for optional configuration (custom port, RP_ID/ORIGIN if not running on localhost:3000, etc).

npm run dev             # auto-restart on file changes
npx prisma migrate dev --name <name>   # after editing prisma/schema.prisma

There's no test suite or linter — see CLAUDE.md for architecture notes if you're working on this codebase.

Docker

docker build -t graph-crm .
docker run -p 3000:3000 -v graph-crm-data:/app/data graph-crm

The /app/data volume holds everything stateful: the SQLite database, the session store, and generated secrets (session secret, passkey data lives in the DB itself). Without a mounted volume, all of that is lost when the container is removed.

If you're serving this behind a domain other than localhost:3000, set RP_ID and ORIGIN (see .env.example) — WebAuthn passkeys are bound to the origin they were created on and won't work if it changes.

Swapping the database backend

The app uses Prisma, so moving off SQLite doesn't require touching any application code — only prisma/schema.prisma and the connection string. Everything else (family.js, the REST API, mcp-server.js, the frontend) talks to Prisma's generated client, not to SQLite directly.

General steps, then Postgres/MySQL specifics below:

  1. Change the provider in prisma/schema.prisma's datasource block.
  2. Point DATABASE_URL at the new database.
  3. Delete prisma/migrations/ and generate a fresh initial migration against the new provider (npx prisma migrate dev --name init) — the existing migration history was written for SQLite's SQL dialect and won't replay cleanly on a different engine. There's no automatic data carry-over; if you need existing contacts, export them first (Settings → API keys → generate one → pull data via the list_contacts/get_directory endpoints or MCP tools, then re-import after switching).
  4. npx prisma generate to rebuild the client.

Postgres

docker run -d --name graph-crm-pg -e POSTGRES_PASSWORD=devpass -e POSTGRES_DB=graphcrm -p 5432:5432 postgres:16

prisma/schema.prisma:

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

.env:

DATABASE_URL="postgresql://postgres:devpass@localhost:5432/graphcrm"
rm -rf prisma/migrations
npx prisma migrate dev --name init
npm start

For a hosted Postgres (Supabase, Neon, RDS, etc.), just swap the connection string — most give you a ready-made postgresql://... URL. Neon/Supabase's pooled connection strings work fine with Prisma; if you hit prepared-statement errors behind a pooler, add ?pgbouncer=true to the URL (Prisma's documented workaround).

MySQL

docker run -d --name graph-crm-mysql -e MYSQL_ROOT_PASSWORD=devpass -e MYSQL_DATABASE=graphcrm -p 3306:3306 mysql:8

prisma/schema.prisma:

datasource db {
  provider = "mysql"
  url      = env("DATABASE_URL")
}

.env:

DATABASE_URL="mysql://root:devpass@localhost:3306/graphcrm"
rm -rf prisma/migrations
npx prisma migrate dev --name init
npm start

Provider-specific things worth checking after switching

  • The Credential.publicKey field is Bytes — MySQL maps this to LONGBLOB, Postgres to BYTEA; both work fine with Prisma's client, no schema changes needed.
  • ApiKey.lastUsedAt and other DateTime? fields are nullable on all providers. Postgres stores timestamptz under Prisma's default mapping; MySQL's DATETIME has no timezone awareness — only matters if you care about exact cross-timezone display of lastUsedAt/createdAt.
  • Both Postgres and MySQL enforce foreign keys and unique constraints the same way SQLite does here (onDelete: Cascade, @@unique), so the cascade-delete behavior used throughout family.js/server.js (deleting a contact cleans up their relationships, interactions, credentials, etc.) carries over unchanged.
  • Running Postgres/MySQL in Docker alongside the app: add both as services in a docker-compose.yml (not included here — this repo ships a single-container Dockerfile since SQLite needs no separate DB service) and point DATABASE_URL at the DB service's hostname instead of localhost.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured