Result shape
Every tool returns the standard MCP content envelope with a single text part containing pretty-printed JSON:ping is one. The memory tools (morphic_recall, morphic_attachment_recall, morphic_remember) return JSON on success; older integrations that parsed their bare-string output need updating.
Error envelope
Every tool converges on one machine-readable error shape. Branch on
error_code; if your agent simply relays user_message verbatim, the wording is already correct and product-voiced.isError: true and a JSON body:
Error codes
Backend prose never reaches the model:
HTTP {status}: {detail} strings, component names, tenant ids and stack traces are sanitised at a single boundary. Full diagnostics still go to the server’s stderr for operators.
Choosing a workspace per call
Every tool takes an optionalworkspace argument: a workspace slug, on any call.
It only matters when a connection was approved for more than one workspace. Then the server cannot guess which one a request means, and answers workspace_selection_required until one is named. Set workspace and the call proceeds:
list_workspaces for the slugs this connection may use. Omit the argument to use whatever the connection already resolves to — a sole approved workspace, or the ?workspace= on the connect URL.
The argument is a request, not a decision. The server re-checks it against what you approved on the consent screen and your live membership on every call, so a workspace outside the grant is refused no matter what a client sends.
Object-type slugs are plural
Morphic’s default object types arepeople, companies, deals — not person/company/deal. Anywhere a tool takes object_type_slug or entity_type, use the plural form.
Workspaces can define custom object types, so never hard-code the list. Call list_entity_types for the real slugs, then get_entity_type_schema for a type’s field slugs before writing to it.
Task statuses are workspace-configured
create_activity.status and update_activity.status take a workspace task-status slug, not a fixed enum. Call list_task_statuses to get this workspace’s exact slugs.
activity_type and priority are fixed enums, and are enforced at the schema level:
activity_type:task·email·call·meeting·note·stage_changepriority:low·medium·high
create_activity vs create_note
Both attach text to a record; they land in different places.
create_activity(activity_type="note", …)→ a timeline note, ordered chronologically alongside calls, emails and meetings.create_note(…)→ a standalone, editable, pinnable note in the record’s notes panel.
\n sequences into line breaks, so an escaped string arrives escaped.
Bulk tools
Everybulk_* tool takes an array of up to 200 ids and applies the same change to all of them. For per-record different values, loop the single-record tool instead.
Bulk calls return per-id success/failure, so one bad id does not abort the batch. Always inspect the per-id results rather than assuming a 200 means everything applied.
Bulk tools available: bulk_update_entities, bulk_archive_entities, bulk_delete_entities, bulk_link_entities, bulk_unlink_entities, bulk_create_activities, bulk_update_activities, bulk_archive_activities, bulk_delete_activities, bulk_create_notes, bulk_delete_notes.
Linking and unlinking records
link_entities and unlink_entities take the same three arguments — the relation is addressed by attribute slug, not by a relation id:
bulk_link_entities.
Answering a question: start with Context
For any question about this workspace — a named record of any object type, or what people have said or done (Slack, email, meetings, chat, “did anyone mention X”) — callask_context before any search tool. Pass the user’s question verbatim; do not pre-extract names or look up an id first. You do have conversation history; it reaches you through this tool, not through Slack’s or Gmail’s own APIs. Never tell the user you cannot search past messages. If contexts is empty, semantic is still a complete answer — Slack-only workspaces do not auto-create CRM records. Empty semantic too means nothing is indexed yet.
ask_context returns these keys:
It never errors on a question it cannot resolve — an unmatched question still returns
semantic and next_steps.
Only then reach for the deeper layers, and only for the reason next_steps gives:
get_entity/get_entity_with_relations— you need a record’s raw field values.list_activities— you need the chronological timeline itself.search_entities/list_entities—resolvedwas empty or wrong, or you want a ranked list rather than one record’s story.morphic_recall— the question is about durable cross-session memory, not a record.
get_context is the entity-scoped form of the same call.
The same layers are available over REST: POST /api/gold/context/ask (body: question, optional max_entities, include_graph) and GET /api/gold/{entity_id}/context.
Finding records
search_entities is semantic (vector) search. When nothing matches it returns an explicitly empty result rather than an error:
list_entities is the deterministic counterpart and does far more than paginate. Beyond object_type_slug, search, is_archived, page and page_size it accepts:
entity_ids— hydrate a specific set of records in one call.sort_by— a sort expression, e.g.created_at:descordeal_value:asc.filters— field-level conditions keyed by attribute slug, e.g.The 19 operators areis,equals,is_not,not_equals,contains,not_contains,starts_with,ends_with,greater_than,less_than,greater_than_or_equal,less_than_or_equal,after,before,between,is_empty,empty,not_empty,is_not_empty. Omitvaluefor the emptiness operators; passvalue2withbetween.
get_entity_type_schema first so your slugs and operators match the attribute types.
Knowledge base list results are lossy
list_kb_documents deliberately shrinks its payload: each item’s content_markdown is truncated to a ~160-character excerpt and the BlockNote content field is removed entirely. Use it to discover what exists; call get_kb_document for a real body.
fetch_all=true flattens every folder level. page / page_size are still sent alongside it and their interaction with fetch_all is backend-defined — prefer one or the other, not both.
Automations
author_workflow is the only way to build automation logic. No tool exposes raw React Flow graph JSON: authoring is delegated to the same LLM-backed builder the Morphic UI uses, from a natural-language description.
Two current engine limits to plan around:
- Linear only. Condition and branch nodes are not evaluated by the execution engine yet.
- No retries. A failed step aborts the entire run.
create_workflow (draft metadata) → author_workflow (trigger + steps) → publish_workflow (go live) → enqueue_workflow_manual_run (run it now, for real) → list_workflow_runs / get_workflow_run (inspect).
Optional request headers
Where to go next
- Tools Reference — every tool, generated from the server
- Tool Groups — advertise only the tools you need
- Common Workflows — end-to-end worked examples
- Troubleshooting