@crmy/core
v0.6.0
Published
CRMy — the agent-first open source CRM
Downloads
301
Readme
CRMy
The context backend for sales agents. Deploy CRMy alongside your AI agent to give it typed, versioned memory about every contact, account, and deal — and a single briefing_get call that assembles everything it needs before each action.
MCP-native. PostgreSQL-backed. Open source.
The problem
Your agent takes an action — sends an email, advances a deal, books a follow-up call. Before it acts, it needs to know:
- Who is this contact? What's their lifecycle stage?
- What happened last week? Last quarter?
- What did prior agent turns learn about this account?
- Are there open assignments on this contact right now?
- What context is stale and might be wrong?
Assembling that from raw queries is 5–10 API calls, schema knowledge, and brittle glue code. CRMy's briefing_get returns it in one shot — via MCP, CLI, or REST.
Quickstart
Choose your deploy path:
Path A — Try it in 60 seconds (Railway)
One click. No local setup. Demo data loads automatically.
Path B — Docker (local, recommended for dev)
# Clone and start PostgreSQL + server together
git clone https://github.com/crmy-ai/crmy.git && cd crmy
CRMY_SEED_DEMO=true docker compose -f docker/docker-compose.yml up -dSet CRMY_ADMIN_EMAIL and CRMY_ADMIN_PASSWORD in docker/docker-compose.yml to create your admin account on first boot.
Path C — npm (bring your own Postgres)
npm install -g @crmy/cli
npx @crmy/cli init # connect to PostgreSQL, run migrations, create admin, seed demo data
npx @crmy/cli server # starts on :3000Try it
Regardless of how you deployed, run these to see CRMy in action with the demo data:
crmy briefing contact:d0000000-0000-4000-c000-000000000001 # Sarah Chen at Acme Corp
crmy briefing account:d0000000-0000-4000-b000-000000000001 # Acme Corp — full account context
crmy assignments list --mine # Open assignments queue2. Connect via MCP
Add CRMy as an MCP server so any agent or IDE can call it directly:
Claude Code
claude mcp add crmy -- npx @crmy/cli mcpClaude Desktop
{
"mcpServers": {
"crmy": {
"command": "npx",
"args": ["@crmy/cli", "mcp"]
}
}
}Cursor / Windsurf
Add to .cursor/mcp.json or equivalent:
{
"mcpServers": {
"crmy": {
"command": "npx",
"args": ["@crmy/cli", "mcp"]
}
}
}Once connected, your agent has access to 100+ MCP tools. No API calls, no auth wiring — just tool calls.
3. Get a briefing before every action
Via MCP (natural language):
Get me a full briefing on contact
<id>before I reach out.
Via CLI:
crmy briefing contact:<id>Response:
{
"record": { "first_name": "Sarah", "lifecycle_stage": "prospect", ... },
"related": { "account": { "name": "Acme Corp", "health_score": 72, ... } },
"activities": [ ... ],
"open_assignments": [ ... ],
"context": {
"objection": [{ "body": "Concerned about procurement timeline", "confidence": 0.9, ... }],
"competitive_intel": [ ... ]
},
"stale_warnings": [{ "context_type": "research", "valid_until": "2026-01-15", ... }]
}Works on contacts, accounts, opportunities, and use cases.
4. Write activities after every interaction
Via MCP (natural language):
Log a discovery call with Sarah Chen today. We discussed budget and technical fit. Champion identified, pricing concern raised.
Via CLI:
crmy activities createCRMy auto-extracts context entries from activities when an LLM backend is configured.
5. Add context explicitly
Via MCP (natural language):
Add an objection for contact
<id>: concerned about procurement timeline, deal may slip to Q3. Confidence 0.85, valid until end of April, tags: pricing, timeline.
Via CLI:
crmy context addContext entries are typed, tagged, versioned (supersede when beliefs change), and full-text searchable.
6. Escalate to a human when needed
Via MCP (natural language):
Submit a HITL request to send a $180K proposal to Sarah Chen at Acme Corp. Auto-approve after 1 hour if no response.
Via CLI:
crmy hitl list
crmy hitl approve <id>Poll hitl_check_status or check the HITL queue in the web UI. Proceed only on approved.
7. Register your agent
Agents self-register — no admin setup required. Via MCP (natural language):
Register me as an agent called "Outreach Agent" with identifier outreach-v1. I need contacts:read, activities:write, context:write, and assignments:create scopes.
Via CLI:
crmy actors registerCall again with the same agent_identifier and you get the same actor back — idempotent. Admins can adjust scopes from Settings → Actors.
Agent workflow example
1. agent: "Get me a full briefing on contact abc."
← record + recent activities + open assignments + typed context + stale warnings
2. agent: "Log a discovery call with abc — champion identified, pricing concern raised."
→ activity logged; extraction pipeline creates context entries automatically
3. agent: "Add an objection for abc: budget approval needed from CFO. Confidence 0.9."
→ stored, tagged, searchable; visible in future briefings
4. agent: "Create an assignment for rep Sarah to send the proposal."
→ appears in the rep's assignment queue
5. human: "Get me a briefing on contact abc."
← same context the agent built, plus the open assignment
6. human: "Mark assignment 123 complete — proposal sent."
→ logged to audit trail; context entry writtenContext Engine
Four primitives that form the agent's shared workspace:
| Primitive | What it does |
|-----------|-------------|
| Actors | First-class identity for humans and AI agents. Every action is attributed to an actor. Agents self-register — no admin setup. Query actor_expertise to route reviews to the person who knows most about an account. |
| Activities | Everything that happened — calls, emails, meetings. Structured detail payloads, polymorphic subjects, retroactive occurred_at timestamps, and auto-extraction into context entries. Bulk-ingest raw documents with context_ingest. |
| Assignments | Structured handoffs. Agents create assignments for humans; humans create assignments for agents. Stateful lifecycle: pending → accepted → in_progress → completed. Stale context entries automatically generate review assignments. |
| Context Entries | The memory layer. Typed, tagged, versioned knowledge attached to any CRM object. Priority weights and confidence half-life decay ensure the most important, fresh context surfaces first. context_radius expands briefings to adjacent entities. Token-budget-aware packing fits context into any LLM context window. |
MCP Tools (80+)
| Category | Tools |
|---|---|
| Briefing | briefing_get — with context_radius (direct/adjacent/account_wide) and token_budget |
| Context | context_add, context_get, context_list, context_supersede, context_search, context_review, context_stale, context_diff, context_ingest, context_extract, context_stale_assign |
| Actors | actor_register, actor_get, actor_list, actor_update, actor_whoami, actor_expertise |
| Assignments | assignment_create, assignment_get, assignment_list, assignment_update, assignment_accept, assignment_complete, assignment_decline, assignment_start, assignment_block, assignment_cancel |
| HITL | hitl_submit_request, hitl_check_status, hitl_list_pending, hitl_resolve |
| Activities | activity_create, activity_get, activity_search, activity_complete, activity_update, activity_get_timeline |
| Contacts | contact_create, contact_get, contact_search, contact_update, contact_set_lifecycle, contact_log_activity, contact_get_timeline, contact_delete |
| Accounts | account_create, account_get, account_search, account_update, account_set_health_score, account_get_hierarchy, account_delete |
| Opportunities | opportunity_create, opportunity_get, opportunity_search, opportunity_advance_stage, opportunity_update, opportunity_delete, pipeline_summary |
| Use Cases | use_case_create, use_case_get, use_case_search, use_case_update, use_case_delete, use_case_advance_stage, use_case_update_consumption, use_case_set_health, use_case_link_contact, use_case_unlink_contact, use_case_list_contacts, use_case_get_timeline, use_case_summary |
| Registries | activity_type_list, activity_type_add, activity_type_remove, context_type_list, context_type_add, context_type_remove |
| Notes | note_create, note_get, note_update, note_delete, note_list |
| Workflows | workflow_create, workflow_get, workflow_update, workflow_delete, workflow_list, workflow_run_list |
| Webhooks | webhook_create, webhook_get, webhook_update, webhook_delete, webhook_list, webhook_list_deliveries |
| Emails | email_create, email_get, email_search |
| Custom Fields | custom_field_create, custom_field_update, custom_field_delete, custom_field_list |
| Analytics | crm_search, pipeline_forecast, account_health_report |
| Meta | schema_get, tenant_get_stats |
CLI Reference
Setup & Server
npx @crmy/cli init Interactive setup (DB, migrations, admin account)
npx @crmy/cli server [--port 3000] Start HTTP server + Web UI
npx @crmy/cli mcp Start stdio MCP server
Authentication
crmy auth setup [url] Configure server URL
crmy auth login Sign in (stores JWT)
crmy auth status Show auth state + token expiry
crmy auth logout Clear stored credentials
Contacts
crmy contacts list [--q <query>] List contacts
crmy contacts create Interactive create
crmy contacts get <id> Get contact details
crmy contacts delete <id> Delete (admin/owner only)
Accounts
crmy accounts list List accounts
crmy accounts create Interactive create
crmy accounts get <id> Get account + contacts + opps
crmy accounts delete <id> Delete (admin/owner only)
Opportunities
crmy opps list [--stage <s>] List opportunities
crmy opps get <id> Get opportunity details
crmy opps create Interactive create
crmy opps advance <id> <stage> Advance opportunity stage
crmy opps delete <id> Delete (admin/owner only)
Use Cases
crmy use-cases list List use cases
crmy use-cases get <id> Get use case details
crmy use-cases create Interactive create
crmy use-cases summary Use case summary
crmy use-cases delete <id> Delete (admin/owner only)
Actors
crmy actors list [--type <t>] List actors (humans & agents)
crmy actors register Interactive actor registration
crmy actors get <id> Get actor details
crmy actors whoami Show current actor identity
Assignments
crmy assignments list [--mine] List assignments
crmy assignments create Interactive create
crmy assignments get <id> Get assignment details
crmy assignments accept <id> Accept a pending assignment
crmy assignments start <id> Start working on an assignment
crmy assignments complete <id> Complete an assignment
crmy assignments decline <id> Decline an assignment
crmy assignments block <id> Mark as blocked
crmy assignments cancel <id> Cancel an assignment
Context
crmy context list [--subject-type <t>] [--subject-id <id>]
crmy context add Add context about a CRM object
crmy context get <id> Get context entry
crmy context supersede <id> Supersede with updated content
crmy context search <query> Full-text search across context
crmy context review <id> Mark entry as still accurate
crmy context stale List stale entries needing review
Briefing
crmy briefing <type:UUID> Get a full briefing for an object
HITL
crmy hitl list Pending HITL requests
crmy hitl approve <id> Approve request
crmy hitl reject <id> [--note] Reject request
Workflows
crmy workflows list List automation workflows
crmy workflows get <id> Get workflow + recent runs
crmy workflows create Interactive create
crmy workflows delete <id> Delete workflow
crmy workflows runs <id> Execution history
Webhooks
crmy webhooks list List webhook endpoints
crmy webhooks create Register new webhook
crmy webhooks delete <id> Remove webhook
crmy webhooks deliveries Delivery log
Other
crmy pipeline Pipeline summary
crmy search <query> Cross-entity search
crmy events [--object <id>] Audit log
crmy config show Show config
crmy migrate run Run migrations
crmy migrate status Migration statusREST API
All MCP tools have a corresponding REST endpoint at /api/v1/*. Use the API directly for integrations that can't run MCP, or when building custom tooling.
Server URLs when running:
Web UI → http://localhost:3000/app
REST API → http://localhost:3000/api/v1
MCP HTTP → http://localhost:3000/mcp
Health → http://localhost:3000/healthAll endpoints require:
Authorization: Bearer <jwt-token> # human login
Authorization: Bearer crmy_<api-key> # agent or integrationCreate scoped API keys for agents and integrations:
POST /auth/api-keys { "label": "my-agent", "scopes": ["contacts:read", "activities:write"] }The key is shown once. Store it securely.
HTTP MCP transport (remote agents)
POST /mcp
Authorization: Bearer crmy_<key>
Content-Type: application/jsonScope reference
| Scope | Grants access to |
|-------|-----------------|
| * | Everything |
| read | All read operations |
| write | All write operations |
| contacts:read / contacts:write | Contact records |
| accounts:read / accounts:write | Account records |
| opportunities:read / opportunities:write | Pipeline and deals |
| activities:read / activities:write | Activities |
| assignments:create / assignments:update | Assignment lifecycle |
| context:read / context:write | Context entries and briefings |
API key scopes are checked before every tool handler. JWT users (human login) bypass scoping and always have full access.
Architecture
packages/
shared/ @crmy/shared TypeScript types, Zod schemas
server/ @crmy/server Express + PostgreSQL + MCP Streamable HTTP
cli/ @crmy/cli Local CLI + stdio MCP server
web/ @crmy/web React SPA at /app
docker/ Dockerfile + docker-compose.ymlDesign decisions
- MCP-first — All CRM operations are MCP tools. REST API and CLI are thin wrappers around the same handlers.
- Raw SQL — No ORM. Every query is readable and auditable.
- Event sourcing — Every mutation appends to an
eventstable. Full audit trail, never overwritten. - Scope enforcement — API key scopes checked before every handler. JWT users always have full access.
- Governor limits — Plan-based quotas on actors, activities, and context entries. Prevents runaway agents.
- Plugins — Extensible lifecycle hooks for custom integrations.
- Workflows — Event-driven automation with configurable triggers and actions.
Environment variables
| Variable | Required | Default | Description |
|---|---|---|---|
| DATABASE_URL | Yes | — | PostgreSQL connection string |
| JWT_SECRET | Yes | — | JWT signing secret |
| PORT | No | 3000 | HTTP port |
| CRMY_TENANT_ID | No | default | Tenant slug |
| CRMY_API_KEY | No | — | API key for CLI auth |
| CRMY_SERVER_URL | No | — | Remote server URL for CLI |
Web UI
Available at /app when the server is running. Useful for human review, HITL approvals, and managing agents — not the primary interface for agent builders.
| Page | What it does | |------|-------------| | Dashboard | Pipeline stats, recent activity feed | | Contacts / Accounts / Pipeline | Standard CRM views | | Use Cases | Consumption-based workload tracking (discovery → poc → production → scaling → sunset) | | Assignments | Work queue with My Queue / Delegated / All tabs | | HITL Queue | Approve or reject pending agent action requests | | Settings | API keys, actors, webhooks, custom fields |
First-run setup (Docker): There are no default credentials. After docker compose up, create your first admin account using one of these methods:
# Option A — CLI wizard (recommended)
npx @crmy/cli init
# Option B — REST API
curl -X POST http://localhost:3000/auth/register \
-H 'Content-Type: application/json' \
-d '{"email":"[email protected]","password":"...","name":"Your Name","tenant_name":"My Org"}'
# Option C — Environment variables (headless / CI)
# Set CRMY_ADMIN_EMAIL, CRMY_ADMIN_PASSWORD (and optionally CRMY_ADMIN_NAME)
# in docker-compose.yml before starting the serverDevelop from source
git clone https://github.com/codycharris/crmy.git
cd crmy
npm install
npm run build
npm run dev # starts server with tsx watchDocumentation
See docs/guide.md for the complete developer reference: agent builder quickstart, Context Engine deep dive, REST API reference, scope enforcement, governor limits, plugin development, workflow configuration, and more.
License
Apache-2.0
