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.
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:
- Change the
providerinprisma/schema.prisma'sdatasourceblock. - Point
DATABASE_URLat the new database. - 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 thelist_contacts/get_directoryendpoints or MCP tools, then re-import after switching). npx prisma generateto 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.publicKeyfield isBytes— MySQL maps this toLONGBLOB, Postgres toBYTEA; both work fine with Prisma's client, no schema changes needed. ApiKey.lastUsedAtand otherDateTime?fields are nullable on all providers. Postgres storestimestamptzunder Prisma's default mapping; MySQL'sDATETIMEhas no timezone awareness — only matters if you care about exact cross-timezone display oflastUsedAt/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 throughoutfamily.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-containerDockerfilesince SQLite needs no separate DB service) and pointDATABASE_URLat the DB service's hostname instead oflocalhost.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。