Manage your Dex personal CRM — search, create, and update contacts, log interaction notes, set follow-up reminders, organize contacts with tags and groups, and manage custom fields. Use this skill when the user wants to: (1) Find or look up a contact, (2) Add or edit contact details, (3) Log a meeting, call, or interaction note, (4) Set a reminder or follow-up task, (5) Organize contacts into groups or apply tags, (6) Track custom data with custom fields, (7) Merge duplicate contacts, (8) Review their relationship history or prepare for a meeting, or any other personal CRM task involving their professional network.
Dex is a personal CRM that helps users maintain and nurture their professional relationships. It tracks contacts, interaction history, reminders, and organizational structures (groups, tags, custom fields).
Check which access method is available, in this order:
dex_search_contacts and other dex_* tools are in the tool list, use MCP tools directly. This is the preferred method — skip CLI setup entirely.dex command exists (run which dex or dex auth status). If authenticated, use CLI commands.If you can run shell commands but cannot open a browser — you are a sandboxed-compute agent (Grok Bot, OpenClaw, and similar hosted agents that execute on their own machine rather than the user's). Don't expect the host's own MCP connector sign-in to work: its form takes only a URL and static headers, so it never starts an OAuth flow and reports authentication_required with no link to hand the user. Start with Path B (install the CLI) followed by the device code flow below — that terminates in the user signing in on their own device.
Once the device flow has issued a dex_ key, you have both options. Keep using the CLI, or — if the user prefers MCP tools over CLI commands — add https://mcp.getdex.com/mcp as a connector with that key as an Authorization: Bearer dex_… header. Tool calls work either way.
Before you take the connector path, read this — the rule is here, not only in Authentication. A
dex_key carries no scopes: it acts as the user across their whole account and it does not expire, unlike the scoped one-hour OAuth token. Never print it, echo it into chat, or place it in a tool argument the user can see. Nothing in this paragraph relaxes that. If wiring the connector would require you to surface the key anywhere at all, stop and ask the user to mint their own key at Settings → Integrations and paste it into the host's connector field themselves.
The host may still label the connector "unauthenticated" because it tracks OAuth state it never established. That badge on its own is cosmetic — but a 401 or 403 on a tool call is a real failure (revoked key, or an account without a Professional subscription), not a display quirk. Judge by whether tool calls actually succeed, and surface a rejection instead of retrying it.
Path A — Platform supports MCP with OAuth (Claude Desktop, Cursor, VS Code, Gemini CLI, etc.):
This path requires a client that implements the MCP OAuth spec — it must be able to follow a WWW-Authenticate challenge and open a browser or hand the user an authorize URL. A host that only accepts a server URL plus a static Authorization header (Grok Bot, the xAI API remote-MCP tool) cannot complete it; use Path B instead.
If the user already has the Dex MCP server configured, or their platform can add MCP servers:
npx -y add-mcp https://mcp.getdex.com/mcp -y
This auto-detects installed AI clients and configures the Dex MCP server for all of them. User authenticates via browser on first MCP connection.
Path B — Install CLI:
npm install -g @getdex/cli
Works with npm, pnpm, and yarn. No postinstall scripts — the binary is bundled in a platform-specific package.
Keeping the CLI up to date:
The CLI auto-generates commands from the MCP server's tool schemas at build time. When tools are added or updated on the server, users need to update the CLI to get the new commands. If a user reports a missing command or parameter, suggest updating:
npm install -g @getdex/cli@latest
Path C — No Node.js:
Direct the user to follow the setup guide at https://getdex.com/docs/ai/mcp-server — it has client-specific instructions for Claude Desktop, Claude Code, Cursor, VS Code, and other MCP-capable clients.
Triggered by /dex-login or on first use when not authenticated. Prefer MCP browser OAuth when your host supports it, then device code for an interactive CLI session or any sandboxed-compute agent, and API keys for CI or when the user explicitly chooses one.
On Grok Bot, OpenClaw, and similar hosted agents, device code is the first choice, not the fallback — there is no browser on your machine to open, but the user has one on theirs.
Do not trust dex auth status alone. Status is green if any credential file exists. Verify with a real command such as dex dex-list-tags. A 401 unauthorized after a "successful" login almost always means the CLI is still reading a stale token.
Where credentials actually live:
@getdex/cli reads ~/.clihub/credentials.json (auth_type: bearer_token, token: dex_…).~/.dex/api-key. That file is not what the CLI sends on MCP calls.dex … call will 401.Cloudflare: every request to mcp.getdex.com must send User-Agent: dex-cli. Bare curl with no UA returns Cloudflare 1010 (browser_signature_banned). That is not an expired code and not a Dex 401.
Never ask the user to paste an API key into chat. Do not print, log, commit, or include it in tool arguments that will be shown back to the user. dex auth --token <key> puts the secret on the process argv — do not run that from an agent.
Option 1 — API Key:
~/.dex/api-key (chmod 600) and ~/.clihub/credentials.json (chmod 600)Option 2 — Device Code Flow (works on remote/headless machines):
Drive this flow directly via HTTP — no browser needed on the machine. Always send User-Agent: dex-cli.
Request a device code:
curl -s -X POST https://mcp.getdex.com/device/code \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "User-Agent: dex-cli"
Response: { "device_code": "...", "user_code": "ABCD-EFGH", "verification_uri": "https://...", "expires_in": 600, "interval": 5 }
Show the user the user_code and verification_uri. They open the URL on any device with a browser, log in to Dex, and enter the code.
Poll for approval every 5 seconds without logging the successful response:
curl -s -X POST https://mcp.getdex.com/device/token \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "User-Agent: dex-cli" \
-d '{"device_code": "<device_code>"}'
{"error": "authorization_pending"} → keep polling (this is not success){"error": "slow_down"} → wait longer than interval{"error": "expired_token"} → request a new device codeUser-Agent: dex-cli and start overapi_key → stop polling. Do not print the body.Save the key to both locations without printing it:
install -d -m 700 ~/.dex ~/.clihub
umask 077
~/.dex/api-key — raw dex_… bytes, mode 600, no trailing commentary~/.clihub/credentials.json — mode 600, this schema (CLI source of truth):{
"version": 2,
"servers": {
"https://mcp.getdex.com/mcp": {
"type": "bearer",
"auth_type": "bearer_token",
"token": "<api_key>"
}
}
}
If the execution surface cannot keep the successful /device/token response out of chat or tool logs, stop and ask the user to finish in their own terminal.
Verify with dex dex-list-tags (or another read). If that 401s, ~/.clihub/credentials.json was not updated.
There is no dex auth login subcommand in current @getdex/cli (1.0.x) even if some READMEs mention it. Use this HTTP device flow.
For CI/automation with no human present, use the API key method with DEX_API_KEY environment variable and the credentials file above.
Contact
├── Emails, Phone Numbers, Social Profiles
├── Company, Job Title, Birthday, Website
├── Description (rich text notes about the person)
├── Tags (flat labels: "Investor", "College Friend")
├── Groups (collections with emoji + description: "🏢 Acme Team")
├── Custom Fields (user-defined: input, dropdown, datepicker)
├── Notes/Timeline (interaction log: meetings, calls, coffees)
├── Reminders (follow-up tasks with optional recurrence)
└── Starred / Archived status
Call dex_* tools directly. All tools accept and return JSON.
Use the dex command. CLIHub generates subcommands from MCP tool names (replacing _ with -):
dex dex-search-contacts --query "John"
dex dex-list-contacts --limit 100
dex dex-create-contact --first-name "Jane" --last-name "Doe"
dex dex-list-tags
dex dex-create-reminder --text "Follow up" --due-at-date "2026-03-15"
Use --output json for machine-readable output, --output text (default) for human-readable.
Run dex --help for all commands, or dex <command> --help for command-specific help.
See CLI Command Reference for the full mapping table of all 53 tools to CLI commands.
choose search/filter/list → get details (with notes if needed)
dex_search_contacts for keywords or real geographic proximity with near and optional radius_kmnear, keep query for an additional non-location filter; do not repeat the place in both fieldsdex_filter_contacts for structured AND filters such as tags, groups, company, profile presence, dates, archived state, and custom fieldsdex_list_contacts for unfiltered bulk iteration (up to 500 per page, cursor-paginated)include_notes: true when user needs interaction historycreate contact → (optionally) add to groups → apply tags → set reminder
Bulk import (CSV, spreadsheet, list):
batch create contacts → add to group → create note for all
dex_create_contact with the contacts array (up to 100 per call) for batch creationdex_add_contacts_to_groupdex_create_note with contact_ids to log a shared note across all imported contacts(optional) list note types → create note on contact timeline
dex_list_note_types to pick the right one (Meeting, Call, Coffee, Note, etc.)event_time to when the interaction happened, not when logging itcontact_ids (plural) to link a single note to multiple contacts (e.g. a group meeting)set cadence or create reminder → complete/snooze when due
dex_update_contact.keep_in_touch for relationship cadence; use a reminder for a specific taskdue_at_date (ISO format: "2026-03-15")text for the reminder description — there is no separate title fieldweekly, biweekly, monthly, quarterly, biannually, yearlydex_complete_keep_in_touch without snooze_days after a real interaction; use snooze_days to defer without recording a touch"What's coming up?" — for any question about the near future ("whose birthday is next week?", "who should I reach out to this week?", "what do I have coming up?"), call dex_list_upcoming_reminders_and_birthdays rather than stitching several lists together. One call returns birthdays, open reminders and keep-in-touch contacts for a window (default 7 days, days: 30 for a month).
turning_age ONLY when the birth year is known. A birthday with no year returns neither birthday_year nor turning_age — say the date, never a guessed agekeep_in_touch list DOES include people already overdue (is_overdue: true); its reminders list does NOT include overdue reminders — get those from dex_list_reminders with is_overdue: truereminders_truncated / keep_in_touch_truncated before telling the user that is everythingTags — flat labels for cross-cutting categories:
create tag → add to contacts (bulk)
Groups — named collections with emoji and description:
create group → add contacts (bulk)
Best practice: Use tags for attributes ("Investor", "Engineer", "Met at Conference X") and groups for relationship clusters ("Startup Advisors", "Book Club", "Acme Corp Team").
list fields → create field definition → batch set values on contacts
input (free text), autocomplete (dropdown with options), datepickerdex_set_custom_field_values to set values on multiple contacts at oncecategories array with the allowed optionsWhen a user says "I have a meeting with X":
include_notes: truedex_get_contact_research for a stored web research note; offer dex_research_contacts (paid, slow) when there is none and the user wants public backgrounddex_list_calendar_events for a time window or plain-text event search across all connected Google/Microsoft accountsemail as account_email for get/update/deleteaccount_provider when the same address is connected to both providersstart_datetime and end_datetime with explicit offsets; include an IANA timezonestart_date; end_date is exclusive and defaults to the next dayattendees replaces the whole list; fetch the event first and include everyone who should remainidempotency_key before the first attempt and reuse it with identical arguments only to retry that operation within 24 hours. Every new edit or intended new event needs a new key. Without one, update executes again; create deduplicates identical content for 24 hours, so use a new key when recreating a deleted event or intentionally creating another identical event. This does NOT generalise: dex_create_contact, dex_create_group, dex_create_tag and dex_create_custom_field carry a fresh key per call, so a retry of those duplicates. dex_create_note and dex_create_reminder are safe to retry only when you pass your own idempotency_key — reuse the SAME key and the same arguments, within the server's 24-hour window, and the original row comes back instead of a duplicate. dex_create_note additionally requires an explicit event_time whenever idempotency_key is present (it is rejected otherwise), because a defaulted "now" would differ on every attempt and defeat the replay. Set event_time yourself when you intend to retry.An update cannot move an event between connected accounts. To transfer one, fetch the original, confirm creating a replacement on the target account, then separately confirm deleting the original. Preserve the full attendee list and details, and warn that organizer identity, RSVP state, conferencing data, and provider notifications may change.
If a calendar list returns warnings, describe the results as incomplete; do not infer availability from the missing accounts. If all calendars fail, report the error rather than saying there are no meetings.
If a calendar write fails for missing provider scope, direct the user to Settings → Sync & Integrations → Grant calendar access for that account.
dex_search_emails for live, read-only search across all connected Google/Microsoft mailboxesquery; use folder: 'inbox' for received mail. Follow next_cursor while keeping the same folder and date boundsfrom: and to: are neutralizedafter and before for precise date ranges; otherwise the search covers roughly the last six monthsdex_get_contact_research reads the stored note for up to 10 contacts at no cost — check it firstdex_research_contacts runs Dex Research for up to 5 contacts per call: a paid web search + page extraction + LLM summary that takes a minute or more per contact. Confirm with the user before running it on more than a couple of contactsforce: true only when the user explicitly wants a fresh run[[n]] markers resolve into sources) and mention identity_confidence when it is not highlinkedin / website fields itself only from high-confidence findings, reported in applied; it never overwrites an existing value. A lower-confidence linkedin/website finding comes back pending, exactly like every email and phone finding — check each row's status rather than assuming a field was filled. Anything pending needs the user's confirmation, then dex_update_contact to apply itin_progress means another request is already researching that contact: read it back later instead of running againPrefer reversible cleanup:
dex_archive_contacts for contacts the user may want laterdex_filter_contacts and archived_only: truedex_archive_contacts and archived: falseFor duplicates:
search for potential duplicates → confirm with user → merge
mergedContactIds from the response to learn which ID survivedFor multi-contact or multi-step requests, follow this reusable contract:
define scope → inspect current state → preview proposed outcome → confirm writes → execute → verify
Load CRM Workflows for detailed playbooks when the user asks to:
include_notes and include_contacts off unless relationship context is necessarydex_search_emails returns only metadata and snippetsidentity_confidence when the note may describe a different personOnly responses with has_more and next_cursor use cursor pagination:
dex_list_contacts: default 100 per page, max 500dex_filter_contacts: default 50 per page, max 200has_more in responsenext_cursor as cursor while preserving the original filters, sort order, and optional includeshas_more: false to get all resultsdex_search_emails listings (without query) also paginate, with default 25 and maximum 100 messages per page. Searches with query are a single page and reject cursor.
dex_search_contacts and dex_list_calendar_events return a bounded single batch, not a cursor. Narrow the query or date range when necessary.
Respect MCP host confirmations. In CLI mode, explicitly summarize the target and consequence before any operation that deletes, overwrites, removes relationships, archives, completes cadence state, changes external calendar state,
<!-- Content truncated for initial SEO render. Open the source file tab for the full file. -->Category:business