Skip to main content
Once you’ve connected folk MCP, AI assistants can use these tools to search, create, and manage content in your folk workspace. These tools work seamlessly together through prompts, and their real power comes from combining them. With a single prompt, you can search your workspace, create new contacts from the results, and update fields across multiple records.

Workspace

folk_get_current_userRead-onlyIdempotentReturns the identity of the authenticated folk user for this MCP session: their id, email, and fullName. Call once per session when you need to attribute an action to the current user (e.g. assigning a task, filtering by owner). Do not call to look up other workspace members — use the members array from folk_get_workspace_structure instead. Does not return role, permissions, or plan information.
folk_get_workspace_structureRead-onlyRetrieves the complete structure of the folk workspace: groups, entity types per group, native fields (person/company/object), custom field definitions (names, types, allowed values), pipeline views, and workspace members. Call at the start of every fresh session before reading or writing any workspace data — the schema may have changed since the last session (new groups, renamed fields, updated pipeline stages). Do not call again within the same session unless the user explicitly changes the workspace structure. Does not return contact data, notes, or interaction history.Object types (custom objects): Deals, opportunities, projects, partnerships, job applications… are all custom objects: records of an object type defined in a group. When the user talks about “deals” (or “opportunities”, “partnerships”…), they mean the objects of the matching object type in a group. The object type name is chosen by each workspace and is case-sensitive: it can be “Deals”, “deals”, “Opportunities” or anything else. Never assume “Deals”: use the exact name found in the group. An object type that does not exist in the group fails the call, and the error lists the object types of the group. The object types of a group are its objectField custom fields, listed under person and company in customFieldsByEntityType: the name of the field is the object type to pass as objectType. Each object type of a group also appears under its own name in entityTypes and customFieldsByEntityType (with the custom fields of its objects), and in the entityType of its pipelines. Use that name as objectType in the object tools, and as entityType in the custom field tools. An object type named person or company is not listed under its own name, as these names always mean the native entity types here.

Credits

folk_get_creditsRead-onlyGet the credits used and available for each metered feature of the workspace in the current period. Credits reset at the end of the period (periodEnd).Use before a large enrichment with folk_enrich_people: person_enrichment credits are charged per person and per field found. If the workspace doesn’t have enough credits, folk_enrich_people returns an insufficient credits error stating the credits needed and left.For each feature:
  • scope: “workspace” when the whole workspace shares the credits, “user” when each member has their own.
  • used: the credits consumed in the current period. Can exceed limit if the limit was lowered during the period.
  • limit: the credits available per period. null means unlimited, 0 means the feature is not available. New features and values may be added in the future: handle unknown values gracefully.

Companies

folk_search_companiesRead-onlySearch companies in the folk workspace using one or more filters.Use for:
  • finding a specific company (e.g. “Acme Corp”)
  • filtering companies by native fields, groups, creators, or custom fields
Do not call with an empty filter.Filter shape: { "<fieldName>": { "<operator>": <operand> } }Field categories:
  • Text fields (name, description, industry, emails, phones, urls, addresses, custom fields): operators: eq, not_eq, like, not_like, empty, not_empty
  • Numeric/date fields (fundingRaised, lastFundingDate, createdAt, custom fields): operators: eq, not_eq, gt, lt, empty, not_empty
  • Single and multi select fields (custom fields): operators: in, not_in, empty, not_empty
  • Reference fields (groups, createdBy): operators: in, not_in, all, empty, not_empty
Important operand rules:
  • eq / like / gt / lt → operand is usually a plain string Example: { "name": { "eq": "John Doe" } }
  • empty / not_empty → operand MUST be an empty string Example: { "industry": { "empty": "" } }
  • in / not_in / all → operand MUST be an object with a single attribute being a single string or an array of string Example: { "createdBy": { "in": { "id": "usr_123" } } } OR { "groups": { "in": { "id": ["grp_123"] } } }
  • SingleSelect and multiSelect custom fields → operand is a plain string or array of plain strings (NOT an id object) Examples: { "customFieldValues.grp_xxx.Status": { "in": "Active" } } { "customFieldValues.grp_xxx.Tags": { "in": ["B2C","B2B"] } }
  • Relationships / Assign / Deals custom fields → operand MUST be an object with a single id being a single string or an array of string Examples: { "customFieldValues.grp_xxx.Relationships": { "in": { "id": "per_aaa" } } } { "customFieldValues.grp_xxx.Owner": { "in": { "id": "usr_aaa" } } } { "customFieldValues.grp_xxx.Deals": { "in": { "id": "obj_aaa" } } }
  • Date fields → operand is a YYYY-MM-DD date or a relative date: “today”, “yesterday”, "<n>-<unit>-ago", and on date custom fields only “tomorrow” and "in-<n>-<unit>" too (n from 0 to 99, unit: day(s), week(s), month(s), year(s)) Examples: { "lastFundingDate": { "gt": "6-months-ago" } } { "customFieldValues.grp_xxx.Renewal": { "lt": "in-1-month" } }
Custom fields: Use key format customFieldValues.<groupId>.<fieldLabel> Example: { "customFieldValues.grp_xxx.Status": { "in": "Active" } }Use combinator for AND/OR logic. Returns paginated company objects: up to limit companies (default 20, max 100). The response includes nextCursor when more results are available; pass it back as cursor, with the same filter and idsOnly, to get the next page.Acting on many companies: set idsOnly to true to get only the IDs of the matching companies (com_<uuid>) in ids, instead of full objects in companies: up to limit IDs per page (default 100, max 500). Use it before folk_update_companies, which takes up to 100 records per call (one per companyId; addGroupIds and add* / remove* need no current values). Collect every page before acting on the ids: updating the companies can change which ones match the filter and shift the next pages. Use folk_get_company if companyId is already known.
folk_get_companyRead-onlyFetch a single company by companyId. Use when you already have a companyId from a previous search_companies call or from another tool response. Do not use to find or look up a company by name, domain, or other attribute — use search_companies instead. Returns the full company object: native fields (name, description, industry, foundationYear, fundingRaised, lastFundingDate, employeeRange), group memberships, and custom field values per group.
folk_create_companyDeprecatedRead-writeDeprecated: use folk_create_companies. Removed on 2027-04-16. Create a new company in the folk workspace. Provide at least a name to identify the company. Multi-value fields (emails, phones, addresses, urls) accept plain arrays — the first element becomes the primary value. Use groups (array of ) to add the company to one or more groups at creation time. Use customFieldValues to set custom field values, keyed by group id then field name — every group id used there must also be present in groups. Returns the full company object.
folk_update_companyDeprecatedRead-writeDestructiveDeprecated: use folk_update_companies. Removed on 2027-04-16. Update an existing company by id. Partial update — omit any field you don’t want to change. Scalar fields (name, description, industry, foundationYear, fundingRaised, lastFundingDate, employeeRange): provide the new value directly. Multi-value fields (emails, phones, addresses, urls) require a prefixed operation param — add/remove will be mutually exclusive to set operation.
  • add* — append values to the existing list (e.g. addEmails: [‘new@acme.com’])
  • remove* — remove specific values from the existing list
  • set* — replace the entire list with the provided values. To add the company to a group, use addGroupIds. Groups cannot be removed via this tool. Use customFieldValues to update custom field values, keyed by group id then field label. Returns only companyId — call get_company if you need the updated full object.
folk_create_companiesRead-writeCreate several new companies in the folk workspace in one call, each record with at least a name. Multi-value fields (emails, phones, addresses, urls) accept plain arrays — the first element becomes the primary value. customFieldValues are keyed by group id then field name — every group id used there must also be present in the record’s groups. A record naming an existing company, or a company named by an earlier record of the call, returns that company’s id: its fields are kept, but the record’s groups and custom field values are added to it. Accepts at most 100 records per call: split a larger set into several calls, or narrow it down first. Each record is processed on its own: one that fails does not prevent the others from being written. Returns one result per record, in the order of records, with only its id, status and error: call the matching get tool for a full record. Records cannot be deleted through the folk MCP.
folk_update_companiesRead-writeDestructiveUpdate several existing companies in the folk workspace in one call, each record identified by its companyId. Only the fields a record provides are changed. For multi-value fields (emails, phones, addresses, urls) use add* / remove* for incremental changes or set* to replace the full list. addGroupIds is additive only. Several records may update the same company: they apply in order, and every add and remove operation is kept. To update every company matching a filter (e.g. add every company tagged B2B to a group with addGroupIds), collect their IDs with folk_search_companies and idsOnly: true (limit 100 gives one call per page), then send one record per companyId. Collect every page before updating. Accepts at most 100 records per call: split a larger set into several calls, or narrow it down first. Each record is processed on its own: one that fails does not prevent the others from being written. Returns one result per record, in the order of records, with only its id, status and error: call the matching get tool for a full record. Records cannot be deleted through the folk MCP.

People

folk_search_peopleRead-onlySearch people in the folk workspace using one or more filters.Use for:
  • finding a specific person (e.g. “John Doe”)
  • filtering people by native fields, groups, companies, creators, or custom fields
Do not call with an empty filter.Filter shape: { "<fieldName>": { "<operator>": <operand> } }Field categories:
  • Text fields (fullName, firstName, lastName, jobTitle, description, emails, phones, urls, addresses, custom fields): operators: eq, not_eq, like, not_like, empty, not_empty
  • Numeric/date fields (birthday, createdAt, addedToGroupAt, interactionMetadata.workspace.lastInteractedAt, interactionMetadata.user.lastInteractedAt, custom fields): operators: eq, not_eq, gt, lt, empty, not_empty
  • Enum fields (gender): operators: eq, not_eq, empty, not_empty Values: “Male”, “Female”, “Unknown”, “Other” Example: { "gender": { "eq": "Female" } }
  • SingleSelect/MultiSelect fields (custom fields): operators: in, not_in, empty, not_empty
  • Reference fields (groups, companies, createdBy, addedToGroupBy, strongestConnection): operators: in, not_in, all, empty, not_empty createdBy, addedToGroupBy and strongestConnection take workspace members: { "id": "usr_xxx" } or { "email": "jane@example.com" }
Group-scoped fields (addedToGroupAt, addedToGroupBy, strongestConnection) hold when true in at least one group of the person:
  • the groups of a groups filter with “in” or “all”, when the filters are combined with “and”
  • otherwise (no such groups filter, only “not_in”, or combinator “or”), every group you can access Example: { "groups": { "in": { "id": "grp_123" } }, "addedToGroupAt": { "gt": "30-days-ago" } }
Important operand rules:
  • eq / like / gt / lt → operand is usually a plain string Example: { "fullName": { "eq": "John Doe" } }
  • empty / not_empty → operand MUST be an empty string Example: { "jobTitle": { "empty": "" } }
  • in / not_in / all → operand MUST be an object with a single attribute being a single string or an array of string Example: { "createdBy": { "in": { "id": "usr_123" } } } OR { "groups": { "in": { "id": ["grp_123"] } } }
  • SingleSelect and multiSelect custom fields → operand is a plain string or array of plain strings (NOT an id object) Examples: { "customFieldValues.grp_xxx.Status": { "in": "Active" } } { "customFieldValues.grp_xxx.Tags": { "in": ["B2C","B2B"] } }
  • Relationships / Assign / Deals custom fields → operand MUST be an object with a single id being a single string or an array of string Examples: { "customFieldValues.grp_xxx.Relationships": { "in": { "id": "per_aaa" } } } { "customFieldValues.grp_xxx.Owner": { "in": { "id": "usr_aaa" } } } { "customFieldValues.grp_xxx.Deals": { "in": { "id": "obj_aaa" } } }
  • Date fields → operand is a YYYY-MM-DD date or a relative date: “today”, “yesterday”, "<n>-<unit>-ago", and on date custom fields only “tomorrow” and "in-<n>-<unit>" too (n from 0 to 99, unit: day(s), week(s), month(s), year(s)) Examples: { "createdAt": { "gt": "7-days-ago" } } { "customFieldValues.grp_xxx.Renewal": { "lt": "in-1-month" } }
Custom fields: Use key format customFieldValues.<groupId>.<fieldLabel> Example: { "customFieldValues.grp_xxx.Status": { "in": "Active" } }Company fields: filter people on their primary company with the company. prefix.
  • Native fields: company.emails, company.phones, company.urls, company.industry, company.addresses, company.fundingRaised, company.lastFundingDate, company.foundationYear, company.employeeRange (same operators as on companies)
  • Custom fields: company.customFieldValues.<groupId>.<fieldLabel> Example: { "company.industry": { "eq": "Software" } }
Use combinator for AND/OR logic. Returns paginated person objects: up to limit people (default 20, max 100). The response includes nextCursor when more results are available; pass it back as cursor, with the same filter and idsOnly, to get the next page.Acting on many people: set idsOnly to true to get only the IDs of the matching people (per_<uuid>) in ids, instead of full objects in people: up to limit IDs per page (default 100, max 500). Use it before bulk tools: folk_enrich_people takes up to 500 ids per call, folk_update_people up to 100 records per call (one per personId; addGroupIds and addX / removeX need no current values). Collect every page before acting on the ids: updating the people can change which ones match the filter and shift the next pages. Use folk_get_person if personId is already known.
folk_get_personRead-onlyFetch a single person by their folk person id and return the full person payload (names, emails, phones, addresses, urls, companies, groups, custom field values, interaction metadata). Use this only when you already have the person id (e.g. from folk_search_people or a previous folk_create_people). Do not use it to look up a person by name or email — that is what folk_search_people is for.
folk_create_personDeprecatedRead-writeDeprecated: use folk_create_people. Removed on 2027-04-16. Create a new person in the folk workspace and return the full created person. Provide at least a name (fullName, or firstName/lastName) OR at least one email. For every multi-value field (emails, phones, addresses, urls), the first element is treated as the primary value. companies links the person to companies, each given as or (a company named that is created if it does not exist); the first one is the primary company. groups adds the person to groups at creation, each given as . customFieldValues are keyed by group id, then by field name.
folk_update_personDeprecatedRead-writeDestructiveDeprecated: use folk_update_people. Removed on 2027-04-16. Update an existing person in the folk workspace. Only the fields you provide are changed — omitted fields are left untouched. For multi-value fields (emails, phones, addresses, urls, companyIds) use addX / removeX for incremental changes or setX to replace the full list. addGroupIds is additive only (groups are never removed via this tool). customFieldValues are keyed by group id, then by field name.
folk_create_peopleRead-writeCreate several new people in the folk workspace in one call. Each record needs at least a name (fullName, or firstName/lastName) or at least one email. For every multi-value field (emails, phones, addresses, urls), the first element is treated as the primary value. companies links the person to companies, each given as or (a company named that is created if it does not exist); the first one is the primary company. groups adds the person to groups, each given as . customFieldValues are keyed by group id, then by field name. Accepts at most 100 records per call: split a larger set into several calls, or narrow it down first. Each record is processed on its own: one that fails does not prevent the others from being written. Returns one result per record, in the order of records, with only its id, status and error: call the matching get tool for a full record. Records cannot be deleted through the folk MCP.
folk_update_peopleRead-writeDestructiveUpdate several existing people in the folk workspace in one call, each record identified by its personId. Only the fields a record provides are changed. For multi-value fields (emails, phones, addresses, urls, companyIds) use addX / removeX for incremental changes or setX to replace the full list. addGroupIds is additive only. customFieldValues are keyed by group id, then by field name. Several records may update the same person: they apply in order, and every add and remove operation is kept. To update every person matching a filter (e.g. add everyone tagged B2B to a group with addGroupIds), collect their IDs with folk_search_people and idsOnly: true (limit 100 gives one call per page), then send one record per personId. Collect every page before updating. Accepts at most 100 records per call: split a larger set into several calls, or narrow it down first. Each record is processed on its own: one that fails does not prevent the others from being written. Returns one result per record, in the order of records, with only its id, status and error: call the matching get tool for a full record. Records cannot be deleted through the folk MCP.

Person enrichments

folk_enrich_peopleRead-writeInteracts with external systemsStart an enrichment of the emails and/or phones of up to 500 people, using third-party data providers. The data found is added to the people in folk.Enriching people is an asynchronous job: this tool returns right away with the enrichment and its id, usually “pending” (already “completed” when every id is skipped). Then:
  1. Poll folk_get_person_enrichment with the enrichment id until its status is “completed” or “failed”. An enrichment usually takes from a few seconds to a few minutes, depending on the number of people.
  2. Do not request another enrichment of the same people while this one is running.
  3. Once “completed”, the enrichment holds a report for every person of the batch you can access: status, enrichedFields and missingInputs (see folk_get_person_enrichment).
Before retrying people that were not (fully) enriched: a person’s missingInputs lists the data the providers search with that the person was missing. As long as it is not fixed, a new enrichment would most likely give the same result and use credits for nothing. Add the missing data to the person first, then enrich only those people again:
  • “name”, “linkedinUrl” (add a LinkedIn URL to urls) and “company” (link a company with companyIds): folk_update_people.
  • “companyWebsite” (a website on the person’s primary company): folk_update_companies (urls).
Credits: person_enrichment credits are charged per person and per field found: searching the emails of a person costs 1 credit, searching their phones costs 4 credits. The check needs the full cost upfront (every requested field for every person that can be enriched): if the workspace doesn’t have enough credits, nothing is enriched and an “insufficient credits” error states the credits needed and left. Credits are reserved when the job starts and the fields not found are refunded when it finishes, so “used” in folk_get_credits looks higher while a job runs. Call folk_get_credits before a large enrichment.Large batches: only enrich the people missing the requested field, instead of a whole group for instance. Collect their IDs with folk_search_people, idsOnly: true and an “empty” filter on the field, e.g. to enrich the emails of a group: { "filter": { "groups": { "in": { "id": ["grp_<uuid>"] } }, "emails": { "empty": "" } }, "idsOnly": true, "limit": 500 }. Collect every page first (follow nextCursor until there is none), then start one enrichment per page of up to 500 ids.ids: person ids (per_<uuid>), from folk_search_people (with idsOnly: true). Duplicates are enriched once. Ids that don’t match a person you can access and edit (enriching needs the contributor role or above on one of the person’s groups) are not rejected: they are reported with the “skipped” status. Returns the enrichment, usually with status “pending”.
folk_get_person_enrichmentRead-onlyGet an enrichment of people by its id, from folk_enrich_people or folk_list_person_enrichments.Use it to follow an enrichment: enriching people is asynchronous, so poll this tool until status is “completed” or “failed”. Wait a few seconds between calls.
  • “pending”: not started yet. “in_progress”: running. Keep polling.
  • “failed”: the enrichment couldn’t run, see errorReason. “insufficient_credits”: nothing was enriched. “internal_error”: some people may already have been enriched, so check them (e.g. with folk_search_people) before enriching again.
  • “completed”: over. summary counts the people per result, and items holds a report for every person of the batch you can access.
Each item of a completed enrichment:
  • status: “enriched” (every requested field found), “partially_enriched” (some found), “not_enriched” (searched, nothing found), “skipped” (the id doesn’t match a person you can access and edit, not searched), “error” (the providers were unavailable, can be retried later).
  • enrichedFields: the requested fields found during this enrichment.
  • missingInputs: the data the providers search with that the person was missing: “name” (a first or last name), “company” (a company linked to the person), “companyWebsite” (a website on the person’s primary company), “linkedinUrl” (a LinkedIn profile URL in the person’s URLs). Adding it may improve a new enrichment, with no guarantee. Don’t enrich a “not_enriched” or “partially_enriched” person again until its missingInputs are fixed: the result would most likely be the same and use credits for nothing. New values may be added in the future: handle unknown values gracefully.
folk_list_person_enrichmentsRead-onlyList the enrichments of people of the workspace, most recent first, paginated via cursor.Use to find an enrichment without its id, e.g. the enrichments still running before requesting a new one. Use folk_get_person_enrichment if the enrichment id is already known.Filter shape: { "<attribute>": { "<operator>": <operand> } }Examples:
  • running enrichments: { "status": { "in": ["pending", "in_progress"] } }
  • finished enrichments: { "finishedAt": { "not_empty": "" } }
  • requested after a date: { "createdAt": { "gt": "2026-09-01" } }
Use combinator to control AND/OR logic across filters. Omit filter to list every enrichment. Returns up to limit enrichments (default and max 10), each with its report once completed (see folk_get_person_enrichment). The response includes nextCursor when more results are available; pass it back as cursor to get the next page.

Objects

folk_search_objectsRead-onlySearch objects (e.g. deals) of one object type in a group using one or more filters.Deals, opportunities, projects, partnerships, job applications… are all custom objects: records of an object type defined in a group. When the user talks about “deals” (or “opportunities”, “partnerships”…), they mean the objects of the matching object type in a group. The object type name is chosen by each workspace and is case-sensitive: it can be “Deals”, “deals”, “Opportunities” or anything else. Never assume “Deals”: use the exact name found in the group. An object type that does not exist in the group fails the call, and the error lists the object types of the group.Use for:
  • finding a specific object (e.g. “Project Alpha”)
  • filtering objects by name, linked people or companies, creation date, creator, or custom fields
Do not call with an empty filter. Use folk_get_workspace_structure first to discover available groupIds and object types.Filter shape: { "<fieldName>": { "<operator>": <operand> } }Field categories:
  • Text fields (name): operators: eq, not_eq, like, not_like, empty, not_empty
  • Date fields (createdAt): operators: eq, not_eq, gt, lt, empty, not_empty
  • Reference fields (people, companies, createdBy): operators: in, not_in, all, empty, not_empty
Important operand rules:
  • eq / like / gt / lt → operand is usually a plain string Example: { "name": { "eq": "Project Alpha" } }
  • empty / not_empty → operand MUST be an empty string Example: { "name": { "empty": "" } }
  • in / not_in / all → operand MUST be an object with a single attribute being a single string or an array of string Examples: { "createdBy": { "in": { "id": "usr_123" } } } { "companies": { "in": { "id": ["com_123", "com_456"] } } }
  • SingleSelect and multiSelect custom fields → operand is a plain string or array of plain strings (NOT an id object) Examples: { "customFieldValues.Status": { "in": "Active" } } { "customFieldValues.Tags": { "in": ["B2C","B2B"] } }
  • Assign (user) custom fields → operand MUST be an object with a single id being a single string or an array of string Example: { "customFieldValues.Owner": { "in": { "id": "usr_aaa" } } }
  • Date fields → operand is a YYYY-MM-DD date or a relative date: “today”, “yesterday”, "<n>-<unit>-ago", and on date custom fields only “tomorrow” and "in-<n>-<unit>" too (n from 0 to 99, unit: day(s), week(s), month(s), year(s)) Examples: { "createdAt": { "gt": "7-days-ago" } } { "customFieldValues.Close date": { "lt": "in-1-month" } }
Custom fields: use the key format customFieldValues.<fieldName>, without group id: an object belongs to a single group. Example: { "customFieldValues.Status": { "in": "Active" } }Use combinator for AND/OR logic. Returns paginated object payloads with name, people, companies, customFieldValues. Use folk_get_object if objectId is already known.
folk_get_objectRead-onlyFetch a single object (e.g. deal) by its ID within a specific group and object type.Deals, opportunities, projects, partnerships, job applications… are all custom objects: records of an object type defined in a group. When the user talks about “deals” (or “opportunities”, “partnerships”…), they mean the objects of the matching object type in a group. The object type name is chosen by each workspace and is case-sensitive: it can be “Deals”, “deals”, “Opportunities” or anything else. Never assume “Deals”: use the exact name found in the group. An object type that does not exist in the group fails the call, and the error lists the object types of the group.Use when you already have an objectId from a previous folk_search_objects or folk_create_objects call. Returns the full object: name, people, companies, createdAt, createdBy, customFieldValues.
folk_create_objectDeprecatedRead-writeDeprecated: use folk_create_objects. Removed on 2027-04-16. Create a new object (e.g. deal) within a specific group and object type in the folk workspace.Deals, opportunities, projects, partnerships, job applications… are all custom objects: records of an object type defined in a group. When the user talks about “deals” (or “opportunities”, “partnerships”…), they mean the objects of the matching object type in a group. The object type name is chosen by each workspace and is case-sensitive: it can be “Deals”, “deals”, “Opportunities” or anything else. Never assume “Deals”: use the exact name found in the group. An object type that does not exist in the group fails the call, and the error lists the object types of the group.Use folk_get_workspace_structure first to discover available groupIds and object types. If the object type does not exist yet, create it first with folk_create_group_custom_field (type objectField). Provide name, and optionally link people and companies by their folk IDs. People and companies must already be in the group of the object: an unknown id, or one not in the group, is silently ignored. Check the people and companies of the object afterwards to know which ones were linked. customFieldValues is a flat record keyed by field name (e.g. { "Status": "Active" }) — no group nesting needed. A name that is not a custom field of the object type fails the call. Returns the full created object.
folk_update_objectDeprecatedRead-writeDestructiveDeprecated: use folk_update_objects. Removed on 2027-04-16. Update an existing object (e.g. deal) in the folk workspace. Partial update — omit any field you don’t want to change.Deals, opportunities, projects, partnerships, job applications… are all custom objects: records of an object type defined in a group. When the user talks about “deals” (or “opportunities”, “partnerships”…), they mean the objects of the matching object type in a group. The object type name is chosen by each workspace and is case-sensitive: it can be “Deals”, “deals”, “Opportunities” or anything else. Never assume “Deals”: use the exact name found in the group. An object type that does not exist in the group fails the call, and the error lists the object types of the group.name: provide new value to rename. people / companies: providing a list REPLACES all current associations: to add one, call folk_get_object first and send its current list plus the new one. Omit to leave unchanged. People and companies must already be in the group of the object: an unknown id, or one not in the group, is silently ignored. Check the people and companies of the object afterwards to know which ones were linked. customFieldValues: flat record keyed by field name. Passing null or empty array unsets the value. Returns only objectId — call folk_get_object if you need the updated full object.
folk_create_objectsRead-writeCreate several new objects (e.g. deals) of one object type within one group in one call: groupId and objectType are given once for the call.Deals, opportunities, projects, partnerships, job applications… are all custom objects: records of an object type defined in a group. When the user talks about “deals” (or “opportunities”, “partnerships”…), they mean the objects of the matching object type in a group. The object type name is chosen by each workspace and is case-sensitive: it can be “Deals”, “deals”, “Opportunities” or anything else. Never assume “Deals”: use the exact name found in the group. An object type that does not exist in the group fails the call, and the error lists the object types of the group.Each record takes a name, and optionally people and companies linked by their folk IDs. People and companies must already be in the group of the object: an unknown id, or one not in the group, is silently ignored. Check the people and companies of the object afterwards to know which ones were linked. customFieldValues is a flat record keyed by field name (e.g. { "Status": "Active" }) — no group nesting needed. Use folk_get_workspace_structure first to discover available groupIds and object types. An object type that does not exist in the group fails the whole call: create it first with folk_create_group_custom_field (type objectField). Accepts at most 100 records per call: split a larger set into several calls, or narrow it down first. Each record is processed on its own: one that fails does not prevent the others from being written. Returns one result per record, in the order of records, with only its id, status and error: call the matching get tool for a full record. Records cannot be deleted through the folk MCP.
folk_update_objectsRead-writeDestructiveUpdate several existing objects (e.g. deals) of one object type within one group in one call: groupId and objectType are given once for the call, and each record is identified by its objectId. Partial update — omit any field you don’t want to change.Deals, opportunities, projects, partnerships, job applications… are all custom objects: records of an object type defined in a group. When the user talks about “deals” (or “opportunities”, “partnerships”…), they mean the objects of the matching object type in a group. The object type name is chosen by each workspace and is case-sensitive: it can be “Deals”, “deals”, “Opportunities” or anything else. Never assume “Deals”: use the exact name found in the group. An object type that does not exist in the group fails the call, and the error lists the object types of the group.people / companies: providing a list REPLACES all current associations. Omit to leave unchanged. People and companies must already be in the group of the object: an unknown id, or one not in the group, is silently ignored. Check the people and companies of the object afterwards to know which ones were linked. Several records may update the same object: they apply in order, the last value given for a field winning. An object type that does not exist in the group fails the whole call. Accepts at most 100 records per call: split a larger set into several calls, or narrow it down first. Each record is processed on its own: one that fails does not prevent the others from being written. Returns one result per record, in the order of records, with only its id, status and error: call the matching get tool for a full record. Records cannot be deleted through the folk MCP.

Notes

folk_search_notesRead-onlySearch notes in the folk workspace.Use for:
  • listing recent notes across the workspace (no filters needed)
  • finding notes attached to a specific contact or company
  • filtering notes by creation date or content
Parameters:
  • entityId (optional): filter by entity. Format per_<uuid> for a person, com_<uuid> for a company, obj_<uuid> for objects.
  • query (optional): full-text search against note content.
  • createdAfter (optional): ISO 8601 timestamp — return only notes created after this date.
  • createdBefore (optional): ISO 8601 timestamp — return only notes created before this date.
  • limit / cursor: pagination.
Returns paginated note objects with nextCursor when more pages exist.
folk_create_noteRead-writeCreate a new note linked to a person or company in the folk workspace.entity.id: required — the entity to attach the note to. Format: per_<uuid> for a person, com_<uuid> for a company and obj_<uuid> for an object . Obtain entity IDs from folk_search_people, folk_search_companies or folk_search_objects. content: required — note body in markdown (max 100 000 chars). visibility: “public” (visible to all workspace members) or “private” (visible only to you). Defaults to “public”. parentNote.id: optional — attach as a reply to an existing note on the same entity.Returns the full created note object.
folk_update_noteRead-writeDestructiveUpdate the content or visibility of an existing note.Partial update — omit any field you do not want to change. noteId: the note to update (format: nte_<uuid>). Obtain from folk_search_notes. content: new markdown body (optional). visibility: “public” or “private” (optional).Returns only noteId. Call folk_search_notes to retrieve the updated note object. Note: only user-authored notes can be updated.

Groups

folk_list_groupsRead-onlyList the groups in the folk workspace that the caller can access.Use for:
  • listing the workspace’s groups (no filters needed)
  • retrieving group ids to use with other endpoints, such as listing a group’s custom fields.
Parameters:
  • limit / cursor: pagination.
Returns paginated group objects (id, name, visibility, createdBy, emoji) with nextCursor when more pages exist. emoji is a native emoji, or null when the group has none. Group ids are formatted grp_<uuid>.
folk_create_groupRead-writeCreate a new group in the folk workspace.name: required — the name of the group. visibility: “public” (visible to all workspace members) or “private” (visible only to explicitly added group members). emoji: optional — a single native emoji shown next to the group name, e.g. ”🤝”. When omitted, a random default group emoji is used.A default “All people” table view is automatically created for the group. Creation is atomic: if the view cannot be created, the group is not created either.Returns the full created group object.
folk_update_groupRead-writeDestructiveUpdate the name, visibility and/or emoji of an existing group.Partial update — omit any field you do not want to change. groupId: the group to update (format: grp_<uuid>). Obtain from folk_list_groups. name: new name of the group (optional). visibility: “public” or “private” (optional). emoji: a single native emoji, e.g. ”🤝” (optional). The emoji can be changed but not removed.Changing visibility resets group membership: all current members are removed and the caller becomes the sole owner.Returns the full updated group object.
folk_list_group_membersRead-onlyIdempotentList the members of a group, paginated. For a public group, this returns every workspace member as they are all members of the group — role defaults to admin unless the member has an explicit role in the group.
folk_add_group_memberRead-writeAdd a workspace member to a group with the given role.
folk_update_group_member_roleRead-writeDestructiveUpdate the role of an existing group member. Fails on a public group, and when the target user is not an explicit member of the group.
folk_remove_group_memberRead-writeDestructiveRemove a member from a group. Fails on a public group, when the target is not a member, or when the target is the group owner.
folk_list_group_custom_fieldsRead-onlyIdempotentReturns the list of the group’s custom fields for an entity type.The object types of a group are its objectField custom fields on person (or company, which returns the same ones): find them with folk_get_workspace_structure or folk_list_group_custom_fields. The name of the field is the object type to pass as objectType. To create an object type, call folk_create_group_custom_field with type objectField. To list the custom fields of the objects of an object type, pass the name of the object type as entityType.
folk_get_group_custom_fieldRead-onlyIdempotentFetch a single group custom field by group, entity type, and custom field name. Returns the detailed custom field definition (name, type, options, config) for that entity type. Use folk_list_group_custom_fields if the custom field name isn’t already known.
folk_create_group_custom_fieldRead-writeCreates a new group custom field for an entity type (person, company, or the name of an object type of the group).Object types (custom objects): Deals, opportunities, projects, partnerships, job applications… are all custom objects: records of an object type defined in a group. When the user talks about “deals” (or “opportunities”, “partnerships”…), they mean the objects of the matching object type in a group. The object type name is chosen by each workspace and is case-sensitive: it can be “Deals”, “deals”, “Opportunities” or anything else. Never assume “Deals”: use the exact name found in the group. An object type that does not exist in the group fails the call, and the error lists the object types of the group.
  • Create an object type: type objectField, entityType person or company (same result: the object type is shared by people and companies). The object type is named after the field and can be used as objectType right away. person and company are reserved: an object type can’t be named after them, whatever the case.
  • Add a custom field to an object type: pass the name of the object type as entityType. Objects accept textField, numericField, dateField, singleSelect, multipleSelect and userField. An object type can’t have contactField or objectField custom fields.
  • Creating an object type also creates a default status single-select field on it, with five pipeline options from lead to closed-won and closed-lost. Its Pipeline view is grouped by it. Its name and options are written in the language of the user who creates the object type (e.g. Status or Statut), so find it with folk_list_group_custom_fields rather than by name. To track another lifecycle, update that field with folk_update_group_custom_field (rename it, add/update/remove options) instead of creating another select field.
Example, tracking partnerships with their own lifecycle in a group:
  1. { "groupId": "grp_…", "entityType": "company", "type": "objectField", "name": "Partnerships" }
  2. Find the default status field with folk_list_group_custom_fields { "groupId": "grp_…", "entityType": "Partnerships" } (the single-select field created with the object type), and get the ids of its default options with folk_get_group_custom_field { "groupId": "grp_…", "entityType": "Partnerships", "customFieldName": "<status field name>" }.
  3. Turn the status field into your lifecycle with folk_update_group_custom_field { "groupId": "grp_…", "entityType": "Partnerships", "customFieldName": "<status field name>", "name": "Stage", "addOptions": [{ "label": "Prospect", "color": "#879aab" }, { "label": "Active", "color": "#20cea9" }], "removeOptions": ["<ids from step 2>"] }.
  4. Create the partnerships with folk_create_objects, objectType “Partnerships”.
folk_update_group_custom_fieldRead-writeDestructiveIdempotentUpdates a group custom field: rename it, update its numeric config, or add/update/remove its select options. Renaming an objectField custom field renames the object type: its objects are then read and written with the new name as objectType. person and company are reserved: an object type can’t be renamed after them, whatever the case. To update a custom field of an object type, pass the name of the object type as entityType.

Interactions

folk_create_interactionRead-writeLog a past interaction (a recorded touchpoint such as a call, meeting, or message) with a person or company.Use for:
  • recording that a conversation or meeting happened (e.g. “Had a coffee with John Doe”)
Only manually logged interactions can be created here. Imported interactions (email, calendar, WhatsApp, calls) sync automatically from connected sources and cannot be created with this tool.Required:
  • entity.id — the person (per_<uuid>) or company (com_<uuid>) the interaction is linked to
  • dateTime — when the interaction happened, as an ISO 8601 timestamp (e.g. “2025-07-17T09:00:00.000Z”)
  • title — short summary of the interaction
  • content — the multi-line body of the interaction
  • activityType — the kind of interaction: a predefined activity (call, meeting, message, coffee, lunch, event, drink), a messaging app (slack, whatsapp, linkedin, telegram, etc.), or a single emoji
Returns the full created logged interaction.
folk_list_interactionsRead-onlyList past or upcoming interactions for a single person, company, or object.Use for:
  • reviewing the recent communication history with a contact (timeframe “past”)
  • checking what meetings or events are scheduled with a contact (timeframe “upcoming”)
  • finding an interaction’s id to pass to folk_get_interaction or folk_update_interaction
Provide entityId to scope results (this tool always targets one entity — it cannot search across the whole workspace). Returns both imported interactions (email, calendar, WhatsApp, calls) and manually logged ones. Pass importedTypes to keep only some imported types, and userIds to keep only the interactions of some workspace members. Some content may be hidden depending on the workspace’s interaction privacy rules. The response includes nextCursor when more results are available; pass it back as cursor to fetch the next page.
folk_get_interactionRead-onlyFetch a single interaction by its id, including the full email or calendar body, or the call transcript, when interaction privacy rules allow it.Use this when you already have an interactionId (e.g. from folk_list_interactions) and need its full details. To find an interaction in the first place, use folk_list_interactions instead.Both interactionId and entityId are required, and the entityId must match the entity the interaction is linked to.
folk_update_interactionRead-writeDestructiveUpdate an existing manually logged interaction. Partial update — provide only the fields you want to change (title, content, dateTime, activityType).Only logged interactions (id format lit_<uuid>) can be updated; imported interactions (email, calendar, WhatsApp, calls) cannot. Besides interactionId and entity, at least one updatable field must be provided. Returns the full updated interaction.

Tasks

folk_search_tasksRead-onlySearch tasks in the folk workspace with optional attribute filters, paginated via cursor.Use for:
  • listing tasks, optionally filtered by completion state, due date, or attributes
  • finding tasks assigned to specific users, or linked to specific people, companies, or objects
  • finding tasks created, due, or completed within a date range
Filter shape: { "<fieldName>": { "<operator>": <operand> } }Attribute → operator → value table:Operand-shape rules:
  • dueAt / createdAt → operand is a plain date string. Example: { "dueAt": { "gt": "2025-01-01" } }
  • completedAt → empty/not_empty take no operand (task not yet completed / already completed). gt/lt take an ISO 8601 datetime string. Example: { "completedAt": { "not_empty": "" } } Example: { "completedAt": { "gt": "2025-01-01T00:00:00.000Z" } }
  • assigneeUserId → operand is one or more folk-prefixed user ids (usr_...). Obtain ids from folk_get_workspace_structure. Example: { "assigneeUserId": { "in": "usr_7dfc21aa-feb2-40d9-92c9-17ccbe8bbddf" } } Example (exclude): { "assigneeUserId": { "not_in": "usr_7dfc21aa-feb2-40d9-92c9-17ccbe8bbddf" } }
  • entity → operand is one or more folk-prefixed ids, all of the SAME entity type (per_... for people, com_... for companies, obj_... for objects — do not mix types in one filter). Obtain ids from folk_search_people, folk_search_companies, or folk_search_objects. Example: { "entity": { "in": ["per_7dfc21aa-feb2-40d9-92c9-17ccbe8bbddf"] } } Example (exclude): { "entity": { "not_in": ["per_7dfc21aa-feb2-40d9-92c9-17ccbe8bbddf"] } }
Use combinator to control AND/OR logic across multiple filter entries. Omit filter entirely to return every task. onlyAssignedToMe (optional): when true, restricts results to tasks assigned to the current user, combined with any other filters. Returns paginated full task objects: up to limit tasks (default 20, max 100). The response includes nextCursor when more results are available; pass it back as cursor to get the next page. Use folk_get_task if taskId is already known.
folk_create_taskRead-writeCreate a new task linked to a person, company, or object in folk.entity.id format: per_<uuid> | com_<uuid> | obj_<uuid>. Obtain IDs from folk_search_people, folk_search_companies, or folk_search_objects. assignedUsers: accepts user IDs or emails. Defaults to the current user if omitted. Returns the full created task object.
folk_get_taskRead-onlyFetch a single task by its ID. Use when you already have a taskId from a previous folk_search_tasks or folk_create_task call. Do not use to find or look up a task by title, due date, or other attribute — use folk_search_tasks instead. Returns the full task object: title, description, entity, dueAt, dueTime, completedAt, recurrenceFrequency, isPublic, assignedUsers, and createdBy.
folk_update_taskRead-writeDestructiveUpdate an existing task. All fields are optional — omit any to leave unchanged.To update the completion date (to mark a task as done or todo), use folk_update_task_todo_or_done instead.Returns the taskId. Call folk_get_task to retrieve the full updated task.
folk_update_task_todo_or_doneRead-writeMark a task as done or todo. Pass a completedAt datetime to mark as done, or null to mark as todo.Returns the taskId. Call folk_get_task to retrieve the full updated task.

Campaigns

folk_list_campaignsRead-onlyList the email campaigns the user can access, newest first. A campaign is one or more emails (steps), sent to people or companies. Each recipient gets one message per step, with the step’s variables filled in.Use for:
  • finding a campaign’s id to pass to folk_get_campaign or folk_list_campaign_messages
  • checking the status of recent campaigns (draft, processing, in_review, scheduled, sending, finished, cancelled, failed)
Pass groupId to keep only the campaigns of one group. Campaigns created from a selection of contacts have groupId null. Subjects are plain text and bodies are HTML, with variables written {{key}} (for example {{firstName}}, or {{customFieldValues.grp_<uuid>.<field name>}} for a group custom field). A signed body ends with <p>{{signature}}</p>, which stands for the sender’s signature; an unsubscribe link is <a href="{{unsubscribeLink}}">. The response includes nextCursor when more results are available; pass it back as cursor to fetch the next page.
folk_get_campaignRead-onlyFetch a single campaign by its id, with its steps by position: sender, subject, body, cc, bcc, delay and whether it is sent in the same thread. Each step has its own sender; a sender deleted since has id null and keeps the address the step was set up with.Subjects are plain text and bodies are HTML, with variables written {{key}} (for example {{firstName}}, or {{customFieldValues.grp_<uuid>.<field name>}} for a group custom field). A signed body ends with <p>{{signature}}</p>, which stands for the sender’s signature; an unsubscribe link is <a href="{{unsubscribeLink}}">. To see what each recipient receives, use folk_list_campaign_messages.
folk_list_campaign_messagesRead-onlyList the messages of a campaign: one per recipient and per step, ordered by step, with their final subject and body.Use for:
  • reviewing what each recipient receives
  • finding which messages were not sent, and why (status “not_sent” and notSentReason)
Filter with step (1-based position), recipientId (a person or company id) and status (draft, sent, not_sent). A message to a contact deleted since has recipient.contact null. A message’s sender is the address sending used once it was attempted, and its step’s sender before that. The response includes nextCursor when more results are available; pass it back as cursor to fetch the next page.
folk_list_campaign_variablesRead-onlyList the {{variables}} the subjects and bodies of a campaign can use: the fields of its people or companies, the text and numeric custom fields of its group, {{unsubscribeLink}} and {{signature}}.Write each variable’s token exactly as given: custom field names are escaped where needed. A variable without a value for a recipient is removed from their message. {{unsubscribeLink}} is only valid as the whole href of a link in a body, <a href="{{unsubscribeLink}}">, with a custom_domain sender. {{signature}} is only valid alone in the last paragraph of a body, <p>{{signature}}</p>. It inserts the sender’s signature on a new step or message (see folk_list_message_senders): end a body with it to sign it, rather than writing the signature yourself. The response includes nextCursor when more results are available; pass it back as cursor to fetch the next page.
folk_stop_campaignRead-writeDestructiveIdempotentStop a scheduled or sending campaign, or only some of its recipients. Messages already sent stay sent; the others are not sent (status “not_sent”, notSentReason “stopped”). This cannot be undone.Use for:
  • stopping a campaign scheduled or launched by mistake
  • stopping the next steps for recipients who replied elsewhere
Without recipientIds, the whole campaign becomes cancelled. Stopping a cancelled campaign again changes nothing. A campaign whose last step is already sending can only be stopped for some recipients. With recipientIds, the campaign keeps its status and its other recipients still receive their messages. Ids that are not recipients, or have nothing left to send, are listed in warnings. A campaign still processing its messages cannot be stopped yet: retry in a few seconds. A draft or in_review campaign has not been launched: there is nothing to stop.
folk_list_message_sendersRead-onlyList the email addresses the user can send campaigns from, last used first. Senders still waiting for verification are left out.Use for:
  • choosing which sender a campaign or a step sends from
  • checking whether a sender can send follow-up steps (supportsSequences) or an unsubscribe link (provider “custom_domain”)
signature is the sender’s signature as HTML, or null when they have none. It is what {{signature}} inserts on a new step or message: end a body with <p>{{signature}}</p> to sign it, rather than writing the signature yourself. The response includes nextCursor when more results are available; pass it back as cursor to fetch the next page.
folk_create_campaignRead-writeCreate a draft email campaign: one or more steps (the first email, then follow-ups), sent to a list of people or companies, or to the contacts of a group. The draft opens in the folk app like one created there, where the user reviews and launches it. Only target “draft” is supported for now.Each step is an email template sent to every recipient: subject in plain text, body in HTML, both with {{variables}} filled in for each recipient. Variables: For people: {{fullName}}, {{firstName}}, {{lastName}}, {{jobTitle}}, {{description}}, {{urls}}, {{companies.name}}, {{companies.urls}}. For companies: {{name}}, {{description}}, {{fundingRaised}}, {{lastFundingDate}}, {{foundationYear}}, {{industry}}, {{employeeRange}}. Array fields use their first value. A text or numeric custom field of the campaign’s group is {{customFieldValues.grp_<uuid>.<field name>}}. A variable without a value for a recipient is removed. Write \{{ for literal braces. Signature: end the body with <p>{{signature}}</p> to sign it with the sender’s signature. Don’t write the signature yourself: a body without {{signature}} is sent unsigned. Unsubscribe link (SendGrid senders only): <a href="{{unsubscribeLink}}">Unsubscribe</a>. bodyFormat: How body is written. html (default) is read as HTML. text is plain text: a blank line starts a new paragraph, each further blank line adds an empty paragraph, a single newline is a line break, and < and & are literal characters. Bodies always read back as HTML. Follow-ups (steps after the first) take delayDays (1-365, default 1) and sameThread (reply in the first step’s thread, with no subject of their own). More than one step needs sequences on the plan and a sender that is not Gmail. Sender: a root sender for every step, or a sender on every step, as { id } or { email }; not both.Recipients: { type: "contacts", ids } with person (per_) or company (com_) ids, all of the same type; or, with groupId, { type: "group", entityType, filter?, search?, excludeIds? }, with the filter syntax of folk_search_people. A text or numeric custom field of the group can be used as a variable. warnings lists recipients that were skipped or have no email address, and HTML that was simplified.
folk_update_campaignRead-writeDestructiveEdit a draft campaign: its sender, its steps or stopOnReply. steps replaces every step, matched by position: read the campaign with folk_get_campaign, change what you need and send all its steps back. A body read back ends with when signed: keep it to keep the signature as it is, edited or not. A step whose sender changes gets the new sender’s signature.Each step is an email template sent to every recipient: subject in plain text, body in HTML, both with {{variables}} filled in for each recipient. Variables: For people: {{fullName}}, {{firstName}}, {{lastName}}, {{jobTitle}}, {{description}}, {{urls}}, {{companies.name}}, {{companies.urls}}. For companies: {{name}}, {{description}}, {{fundingRaised}}, {{lastFundingDate}}, {{foundationYear}}, {{industry}}, {{employeeRange}}. Array fields use their first value. A text or numeric custom field of the campaign’s group is {{customFieldValues.grp_<uuid>.<field name>}}. A variable without a value for a recipient is removed. Write \{{ for literal braces. Signature: end the body with <p>{{signature}}</p> to sign it with the sender’s signature. Don’t write the signature yourself: a body without {{signature}} is sent unsigned. Unsubscribe link (SendGrid senders only): <a href="{{unsubscribeLink}}">Unsubscribe</a>. bodyFormat: How body is written. html (default) is read as HTML. text is plain text: a blank line starts a new paragraph, each further blank line adds an empty paragraph, a single newline is a line break, and < and & are literal characters. Bodies always read back as HTML. Follow-ups (steps after the first) take delayDays (1-365, default 1) and sameThread (reply in the first step’s thread, with no subject of their own). More than one step needs sequences on the plan and a sender that is not Gmail. Sender: a root sender for every step, or a sender on every step, as { id } or { email }; not both.Recipients, and whether they are people or companies, can’t change.
folk_delete_campaignRead-writeDestructiveDelete a campaign that is a draft or in review, with its messages. Other campaigns cannot be deleted. Confirm with the user first: this cannot be undone.

Deprecated tools

A deprecated tool keeps working exactly as before until its removal date, at least 6 months after it was deprecated, as REST API endpoints do. Its description starts with Deprecated: use <tool>. Removed on <date>., so that an AI assistant reading it calls the replacement instead, and the deprecation is announced in the changelog. If a deprecated tool is still widely used as its removal date approaches, the date may be postponed, and the new date is announced in the changelog. Once removed, the tool is no longer listed and calling it fails.