MCP App Store
by KeenEthics
Business & Operations
4Degrees icon

4Degrees

by 4Degrees

Overview

4Degrees brings your relationship intelligence and deal flow into ChatGPT. Ask about your contacts, companies, and deals in plain English — "who's my warmest path to a CTO at Stripe?", "show me Series B deals by stage", "what needs my attention today?". You can also update your CRM — add tags, log notes, and move deal stages — with a preview-and-confirm step on every change and one-tap undo. Scoped per-teammate via OAuth to the data and permissions your seat already has. Designed for private-markets investors, M&A teams, and search funds.

Tools

act

ChatGPT
Perform a verb-style write operation (snooze, complete, undo, …). Unlike `mutate (which uses a dotted resource.action key), act accepts a plain verb string and resolves it to an ActionSpec via the action registry. Verb lookup order: 1. Universal scope — built-in verbs such as undo that apply across resources. 2. Resource-scoped fallback — verbs registered for a specific target_type (e.g., snooze for reminder). Most verbs follow the same two-call confirmation flow as mutate: 1. Call act without a confirmation_token — the server returns a preview and a confirmation_token. 2. Call act again with the same arguments PLUS the confirmation_token to commit the write. Verbs with min_confirmation: none execute in a single call. Args: verb: The verb to execute, e.g. "snooze", "complete", "undo". payload: Verb-specific payload dict. Schema is validated server-side; an invalid payload returns a validation.schema error. Defaults to {} for verbs with an empty payload schema. target_type: Resource type of the target, e.g. "reminder". Required for resource-scoped verbs when the universal lookup would miss. target_id: Integer ID of the target record. confirmation_token: Token returned by the preview call. Supply this to commit the write after reviewing the preview. idempotency_key: Client-generated unique key (UUID recommended). Required for programmatic clients on create/update/delete verbs. auto_confirm: If True, programmatic clients may skip the confirmation step for single_call_token verbs. Has no effect on preview_required / human_required verbs. Returns: One of: - {confirmation_required: true, confirmation_token, preview, expires_at, fingerprint} — preview step, no write occurred. - {request_id, result, audit_url} — write committed. - {replayed: true, original_request_id, result} — idempotency replay (same result as first execution). - {error: {code, message, http_status, ...}} — error envelope. code="action.unknown_verb"` means the verb is not (yet) registered.

bulk_mutate

ChatGPT
Apply one write action to multiple CRM targets in a single call. For small batches (≤ 50 rows, no external side effects), the call executes inline and returns per-row results synchronously. For larger batches or actions with external side effects, the call enqueues an async job and returns immediately with a `job_id. Poll GET /mcp/jobs/{job_id} to check progress. Each target receives its own mcp_write_request journal entry so that every row is individually auditable and idempotent. Hard limits: - Maximum 5 000 rows per call (bulk.size_exceeded if exceeded). - partial_failure_policy="all_or_nothing" is forbidden for > 20 rows. - The write:bulk scope is required in addition to the per-action scope. Args: action_key: Dotted action identifier applied to every target, e.g. contact.add_tag.v1. targets: List of {type, id} dicts identifying the records to act on. Example:: [{"type": "contact", "id": 42}, {"type": "contact", "id": 99}] payload: Action payload applied to every row (same for all targets). Per-target payload customisation is not supported in Wave 1. idempotency_key: Client-generated unique key for the bulk envelope. Per-row keys are derived as {idempotency_key}:{target_type}:{target_id} so individual rows remain idempotent on retry. confirmation_token: Required when the inline batch requires re-confirmation (> ASYNC_THRESHOLD rows that are still eligible for inline execution). partial_failure_policy: How to handle per-row failures. One of: - "continue" (default) — continue processing remaining rows after a failure. - "abort_on_first" — stop at the first failed row; return results up to that point. - "all_or_nothing" — all rows in a single transaction; forbidden for > 20 rows. auto_confirm: If True, programmatic clients may skip the confirmation step for eligible action tiers. Has no effect on async-path jobs (those were already confirmed at enqueue time). Returns: Inline path (synchronous): {total, succeeded, failed, rows: [{target, status, request_id?, error?, message?}, ...]} Async path (job enqueued): {job_id, state: "pending", total_rows} Error: {error: {code, message, http_status, ...}}`

compare

ChatGPT
Compare and aggregate CRM data — counts, averages, totals grouped by a field. Performs server-side aggregation so you don't need to fetch raw records. Args: resource: What to aggregate — 'contacts', 'deals'. metric: What to measure — 'count'. group_by: How to group — 'pipeline', 'stage', 'owner'. filters: Optional filters (same syntax as query). format: Output format — 'csv' (default), 'markdown', 'json'. Returns: Aggregated results. Much more compact than fetching all records. Examples: compare("deals", metric="count", group_by="pipeline") compare("deals", metric="count", group_by="stage") compare("contacts", metric="count", group_by="owner")

discover

ChatGPT
Discover available CRM resources, fields, and query syntax. Call with no arguments to list all resources. Call with a resource name for detailed field info, your org's custom fields, pipelines, and example queries. Args: resource: Optional — 'contacts', 'companies', 'deals', 'interactions', 'custom_fields', 'team', 'pipelines', 'tags'. Returns: Resource descriptions with example query() calls. Includes your org's custom fields and pipeline names.

inferred_paths

ChatGPT
Find inferred warm introduction paths to a company via shared past employment. Identifies connectors in your network who worked alongside people at the target company at a shared past employer, even if no direct interaction is recorded. Args: company: The target company name to find warm paths to. Returns: Ranked list of inferred paths with connector, confidence, shared context, and a recommended introduction ask. Returns a friendly message when no paths are found. Examples: inferred_paths("Acme Corp") inferred_paths("Middesk")

mutate

ChatGPT
Perform a write action on a CRM resource. Most actions require a two-call confirmation flow: 1. Call `mutate without a confirmation_token — the server returns a preview and a confirmation_token. 2. Call mutate again with the same arguments PLUS the confirmation_token to commit the write. Actions with min_confirmation: none execute in a single call. Programmatic clients (API key / OAuth) may pass auto_confirm=True to skip confirmation for single_call_token actions. Confirmation tier per action (B-15 — discoverable): +-----------------------------------------+------------------------+ | Tier | Actions | +-----------------------------------------+------------------------+ | NONE (single-call, no token needed) | contact.add_tag, | | | contact.remove_tag, | | | contact.add_note, | ← executes immediately | | contact.add_interaction| | | contact.update_*, | | | company.add_tag, | | | company.remove_tag, | | | company.add_note, | | | company.update_note, | | | company.update.v1, | | | deal.add_tag, | | | deal.remove_tag, | | | deal.move_stage, | | | deal.update.v1, | | | deal.add_note, | | | deal.update_note, | | | deal.add_contact, | | | deal.remove_contact, | | | reminder.* (act verbs) | +-----------------------------------------+------------------------+ | SINGLE_CALL_TOKEN (preview + token) | contact.create, | ← returns confirmation_token | | contact.add_email, | ← first call = preview only | | contact.add_phone, | ← second call with token commits | | contact.add_address, | | | contact.add_job, | | | contact.reactivate, | | | contact.remove_email, | | | contact.remove_phone, | | | contact.remove_address,| | | contact.remove_job, | | | contact.remove_interaction, | | | company.create, | | | company.remove_note, | | | deal.create, | | | deal.remove_note, | | | deal.update_record | +-----------------------------------------+------------------------+ | BULK_CLEAR_ESCALATION (dynamic) | *.set_custom_field | ← NONE when <5 clears | | (company/deal) | ← SINGLE_CALL_TOKEN when ≥5 clears +-----------------------------------------+------------------------+ NONE-tier actions do NOT need auto_confirm=True — they always execute on the first call. Only SINGLE_CALL_TOKEN actions need auto_confirm=True (or a confirmation_token from the preview response) to commit. Custom-field payload contract (B-10 — 4D-5250): All *.set_custom_field.v1 actions use ONE payload shape: {<entity>_id, fields: [{custom_field_id: int, value: ...}, ...]} - Only custom_field_id (int) is accepted — field_name / name / id strings are rejected with validation.schema. Enumerate IDs via query("custom_fields", filters={"entity_type":"<entity>"}). - Per-kind value shape: | Kind | Accepted value | |------------------|------------------------------------------------------| | Text / Long Text | str | | URL | str (must be a URL the server accepts) | | Number / Currency| int OR float OR decimal-shaped string | | Date | ISO date "YYYY-MM-DD" OR epoch int | | Select | option_id (int) OR label (str) | | Multi Select | list[int|str] — option_ids OR labels | | Contact Reference| contact_id (int) OR numeric string | | Formula | REJECTED — validation.field_kind_readonly (B-25) | - To clear a field: pass null (or "" / "none" / [] per kind — server normalises). - Max 50 entries per batch, no duplicate custom_field_id. - Idempotency rule: B-1/B-2 (4D-5250) — repeating the same call with the same idempotency_key returns {"replayed": true, "original_request_id": <uuid>, "result": <cached>}. For OAuth clients (Claude Desktop) replay is Valkey-only (24h TTL); PAT clients additionally have a DB backstop. Args: action_key: Dotted action identifier, e.g. contact.add_note.v1. Omit the version suffix to use the latest version. payload: Action-specific payload dict. Schema is validated server-side; an invalid payload returns a validation.schema error. target_type: Resource type of the target, e.g. contact`. Required for actions that operate on a specific record. target_id: Integer ID of the t…

query

ChatGPT
Query CRM data with optional filters, field selection, and format control. Use discover() first to learn available resources and fields. Args: resource: What to query — 'contacts', 'companies', 'deals', 'interactions', 'custom_fields', 'team', 'pipelines', 'tags'. filters: Field-value pairs to filter results. Use {"id": "87"} for a specific record, {"name": "Jason"} for search. fields: Comma-separated field names to return (e.g. "name,email,company"). Default: all fields. sort: Sort field with optional 'Desc' suffix (e.g. "name", "strengthDesc"). limit: Max records (1-100, default 20). offset: Skip N records for pagination (default 0). format: Output format — 'csv' (default, most compact), 'markdown', 'json', 'summary'. Returns: Formatted CRM data. CSV is most token-efficient for follow-up queries. Examples: query("contacts", filters={"name": "Jason"}) query("contacts", filters={"id": "87"}, fields="name,email,company,strength") query("deals", filters={"name": "Acme"}, format="markdown") query("team") query("pipelines") query("tags") query("custom_fields", filters={"entity_type": "deal"})

App Stats

7

Tools

ChatGPT

Platforms

Works with

ChatGPT

Data refreshed daily