Connect Affinity to ChatGPT: Manage Relationships & Track Deals via MCP
Learn how to connect Affinity to ChatGPT using a managed MCP server. Automate CRM workflows, query relationship intelligence, and track deals without custom code.
You want to connect Affinity to ChatGPT so your AI agents can read relationship intelligence, update deal statuses, and draft interaction notes based on historical context (if your team uses Attio instead, check out our guide to the best MCP servers for Attio). Here is exactly how to do it using a Model Context Protocol (MCP) server.
A February 2026 Gartner survey revealed that 91% of sales and customer service leaders are under intense executive pressure to implement AI. The business mandate is clear: automate CRM hygiene, reduce manual data entry, and surface relationship intelligence directly within conversational interfaces. Giving a Large Language Model (LLM) read and write access to your Affinity instance is an engineering challenge.
You either spend weeks building, hosting, and maintaining a custom MCP server, or you use a managed infrastructure layer that handles the boilerplate for you. This guide breaks down exactly how to use Truto to generate a secure, managed MCP server for Affinity, connect it natively to ChatGPT, and execute complex CRM workflows using natural language.
The Engineering Reality of Custom Affinity Connectors
A custom MCP server is a self-hosted integration layer that translates an LLM's tool calls into REST API requests.
OpenAI's rollout of MCP client support in ChatGPT's Developer Mode gave engineers a standardized way to connect models to external systems. The protocol itself is elegant. The reality of implementing it against vendor APIs is painful. If you decide to build a custom MCP server for Affinity, you are responsible for the entire API lifecycle.
Rate Limits and Edge Cases Affinity enforces specific rate limits. If your AI agent gets stuck in a loop or tries to summarize hundreds of interactions at once, the API will return a 429 error. You have to build exponential backoff and circuit breakers into your MCP server to handle this gracefully.
Pagination Cursors When the LLM requests a list of organizations, you have to write the logic to handle pagination cursors. You must explicitly instruct the LLM to pass cursor values back unchanged, otherwise it will hallucinate pagination parameters and break the integration.
Schema Maintenance You have to write and maintain massive JSON schemas for every endpoint you want the LLM to access. When Affinity adds a new field or modifies a resource payload, your custom MCP server breaks until you update the schema.
Maintaining custom MCP servers for fragmented third-party APIs - handling their undocumented rate limits, erratic pagination, and token refreshes - is an engineering nightmare, whether you're building for Affinity, Zendesk, or Pylon.
How Managed MCP Servers Work
Instead of forcing a unified data model, Truto exposes the raw vendor APIs directly to the LLM, but makes them intelligent. We automatically inject the necessary semantic descriptions, parameters, and schemas required to turn a raw API endpoint into a highly reliable MCP tool.
The key design insight is that tool generation is dynamic and documentation-driven. Rather than hand-coding tool definitions for the Affinity integration, the platform derives them from two existing data sources: the integration's resource configurations (which define what API endpoints exist) and documentation records (which provide human-readable descriptions and JSON Schema definitions for each resource method).
When a list method is exposed, the platform automatically injects limit and next_cursor properties into the query schema. The next_cursor description explicitly instructs the LLM to pass cursor values back unchanged, completely solving the AI pagination problem.
graph TD
A[ChatGPT / MCP Client] -->|JSON-RPC over HTTP| B[Truto MCP Router]
B -->|Validates Token| C[Token Storage]
B -->|tools/list| D[Tool Generator]
D -->|Reads Schemas| E[Integration Config & Docs]
B -->|tools/call| F[Proxy API Execution]
F -->|Handles Auth| G[Affinity API]
classDef default fill:#f9f9f9,stroke:#333,stroke-width:1px;
classDef client fill:#e1f5fe,stroke:#03a9f4,stroke-width:2px;
classDef truto fill:#e8f5e9,stroke:#4caf50,stroke-width:2px;
classDef vendor fill:#fff3e0,stroke:#ff9800,stroke-width:2px;
A:::client
B:::truto
C:::truto
D:::truto
E:::truto
F:::truto
G:::vendorWhen an MCP client calls a tool, all arguments arrive as a single flat object. The MCP router splits them into query parameters and body parameters using the schemas' property keys. Execution is then delegated to the proxy API handlers, which manage the actual HTTP request to Affinity and the OAuth lifecycle. If Affinity returns a rate limit error (for example HTTP 429), Truto passes that response through to the MCP client with normalized rate limit headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset), giving your agent the data it needs to implement intelligent backoff.
How to Generate an Affinity MCP Server
Each MCP server is scoped to a single integrated account (a connected instance of Affinity for a specific tenant). The server URL contains a cryptographic token that encodes which account to use, what tools to expose, and optionally when the server expires.
There are two ways to generate this server: via the Truto UI or programmatically via the API.
Method 1: Via the Truto UI
This is the fastest method for internal tooling and testing.
- Navigate to the Integrated Accounts page in your Truto dashboard and select your connected Affinity account.
- Click the MCP Servers tab.
- Click Create MCP Server.
- Select the desired configuration. You can filter by methods (e.g., only allow
readoperations) or tags (e.g., only allow tools related tocrm). - Copy the generated MCP server URL.
Method 2: Via the API
For production workflows where you need to programmatically provision MCP servers for your end-users, use the API.
Make an authenticated POST request to /integrated-account/:id/mcp:
{
"name": "Affinity Sales Assistant",
"config": {
"methods": ["read", "write"],
"tags": ["crm", "sales"]
},
"expires_at": "2026-12-31T23:59:59Z"
}The API validates that the Affinity integration has tools available, generates a secure token, and returns a ready-to-use URL:
{
"id": "mcp_abc123",
"name": "Affinity Sales Assistant",
"config": { "methods": ["read", "write"], "tags": ["crm", "sales"] },
"expires_at": "2026-12-31T23:59:59Z",
"url": "https://api.truto.one/mcp/a1b2c3d4e5f6..."
}Security Note: You can enforce a second layer of authentication by setting require_api_token_auth: true in the config. This requires the MCP client to pass a valid Truto API token in the Authorization header, ensuring that possession of the URL alone is not enough to access the tools.
Connecting the MCP Server to ChatGPT
Once you have the MCP server URL, connecting it to ChatGPT takes less than a minute.
- Open ChatGPT and navigate to Settings -> Apps -> Advanced settings.
- Enable Developer mode (MCP support is currently behind this flag).
- Under MCP servers / Custom connectors, click to add a new server.
- Provide a name (e.g., "Affinity CRM") and paste the Truto MCP URL into the Server URL field.
- Click Save.
ChatGPT will immediately connect to the URL, perform the initialization handshake, and list all available Affinity tools. Your AI agent is now ready to query and update your CRM.
Full Affinity Tool Inventory
The Truto Affinity integration exposes a comprehensive set of tools covering every major resource in the Affinity API. You can view the full documentation on the Affinity integration page.
Below is the complete inventory of tools available to your LLM, grouped by functional area.
Persons & Organizations
These tools manage the core relationship entities within Affinity.
- create_a_affinity_person: Create a new person in Affinity using first_name, last_name, and emails.
- get_single_affinity_person_by_id: Get a specific person in Affinity by id. Returns name, primary_email, and associated metadata.
- update_a_affinity_person_by_id: Update a person in Affinity using id. Returns updated details including name and emails.
- delete_a_affinity_person_by_id: Delete a person in Affinity using id. Removes the person record permanently.
- list_all_affinity_persons: List persons in Affinity that match search criteria. Returns an array of person records.
- create_a_affinity_organization: Create a new organization in Affinity by providing name. Returns id and domain details.
- get_single_affinity_organization_by_id: Get details about a specific organization in Affinity using id. Returns name, domain, and global fields.
- update_a_affinity_organization_by_id: Update organization with id in Affinity. Returns updated fields such as name and domain.
- delete_a_affinity_organization_by_id: Delete an organization in Affinity using id. Returns confirmation of deletion.
- list_all_affinity_organizations: List organizations in Affinity that match search criteria. Returns key fields like organization name and domain.
- list_all_affinity_relationship_strength: Get relationship strength in Affinity for a specific external_id. Returns key metrics such as score.
Example AI Prompt: "Find the organization 'Acme Corp' and tell me our current relationship strength score."
Opportunities & Lists
These tools manage deal pipelines and custom lists.
- create_a_affinity_opportunity: Create a new opportunity in Affinity with required parameters name and list_id.
- get_single_opportunity_by_id: Get a specific opportunity in Affinity using id. Returns name, person_ids, and organization_ids.
- update_a_affinity_opportunity_by_id: Update an existing opportunity in Affinity using id. Returns modified fields such as name and status.
- delete_a_affinity_opportunity_by_id: Delete an opportunity in Affinity. Requires id. Returns confirmation of deletion status.
- list_all_affinity_opportunities: List opportunities in Affinity that match search criteria. Returns id, name, and associated entities.
- create_a_affinity_list: Create a new list in Affinity with specified name, type, and is_public parameters.
- get_single_affinity_list_by_id: Get details about a specific list in Affinity using id. Returns attributes like type and public status.
- list_all_affinity_lists: List all lists visible to the user in Affinity. Returns id, name, type, and owner_id.
- create_a_affinity_list_entry: Create a new list entry in Affinity. Requires list_id and entity_id. Returns id and creator details.
- get_single_affinity_list_entry_by_id: Get a specific list entry by list_id and id in Affinity. Returns id and entity details.
- delete_a_affinity_list_entry_by_id: Delete a specific list entry in Affinity. Requires list_id and id. Returns success status.
- list_all_affinity_list_entries: Get all list entries for a specific list_id in Affinity. Returns an array of list entries.
Example AI Prompt: "List all active opportunities in the 'Enterprise Sales' list and identify any that haven't been updated in the last 14 days."
Interactions & Notes
These tools track the communication history and internal context for deals.
- create_a_affinity_interaction: Create a new interaction in Affinity with required parameters type, person_ids, content, and date.
- get_single_affinity_interaction_by_id: Get details for a specific interaction in Affinity. Requires id and type. Returns fields including date and content.
- update_a_affinity_interaction_by_id: Update an existing interaction in Affinity using id, type, and person_ids. Returns updated interaction fields.
- delete_a_affinity_interaction_by_id: Delete a specific interaction in Affinity using id and type. Returns confirmation of successful deletion.
- list_all_affinity_interactions: List interactions in Affinity filtered by type, start_time, and end_time. Returns key interaction fields.
- create_a_affinity_note: Create a new note in Affinity. Requires content. Returns id and association details.
- get_single_affinity_note_by_id: Get a specific note in Affinity using id. Returns creator_id, content, and person/org associations.
- update_a_affinity_note_by_id: Update a specific note in Affinity by id with new content. Requires id and content.
- delete_a_affinity_note_by_id: Delete a note in Affinity using id. Removes the specified note permanently.
- list_all_affinity_notes: List all notes in Affinity. Returns key fields including creator_id and associated entities.
Example AI Prompt: "Draft a summary note based on the last three interactions with John Doe, and save it to his profile."
Files & Reminders
These tools manage attachments and task scheduling.
- affinity_files_upload: Upload file attachments in Affinity for a specific entity using person_id. Returns uploaded file details.
- affinity_files_download: Download a specific file in Affinity using id. Returns the actual file corresponding to the id.
- get_single_affinity_file_by_id: Get a specific file in Affinity using id. Returns details of the entity file including metadata.
- list_all_affinity_files: List all files in Affinity. Returns entity_files array containing all files within your organization.
- create_a_affinity_reminder: Create a new reminder in Affinity. Requires owner_id, type, and due_date when type=0.
- get_single_affinity_reminder_by_id: Get details of a specific reminder in Affinity using id. Returns id, type, created_at, content, due_date, etc.
- update_a_affinity_reminder_by_id: Update a reminder in Affinity by id. Allows modifying fields such as type, reset_type, reminder_days, etc.
- delete_a_affinity_reminder_by_id: Delete a specific reminder in Affinity. Requires id. Returns confirmation of successful deletion.
- list_all_affinity_reminders: List reminders in Affinity filtered by optional parameters like person_id, organization_id, or opportunity_id.
Fields & Configuration
These tools manage the custom data structures and metadata within your Affinity tenant.
- create_a_affinity_field: Create a new field in Affinity. Requires name, entity_type, and value_type.
- delete_a_affinity_field_by_id: Delete a specific field in Affinity using id. Returns confirmation of deletion.
- list_all_affinity_fields: List all fields in Affinity. Returns id, name, list_id, enrichment_source, and value_type.
- list_all_affinity_person_fields: Get global person fields in Affinity. Returns an array of global fields that exist on people.
- list_all_affinity_organization_fields: List all global organization fields in Affinity. Returns id, name, and value_type.
- create_a_affinity_field_value: Create a new field value in Affinity using required parameters field_id, entity_id, and value.
- update_a_affinity_field_value_by_id: Update a field value in Affinity using id. Requires id. Returns the updated field value object.
- delete_a_affinity_field_value_by_id: Delete a field value in Affinity. Requires id. Returns confirmation of deletion.
- list_all_affinity_field_values: Get all field values attached to a person, organization, opportunity, or list_entry in Affinity.
- list_all_affinity_field_values_changes: List field-values-changes in Affinity for a specific field using field_id. Returns an array of changes.
- list_all_affinity_whoami: Get information about the authenticated user and their Affinity instance. Returns tenant details.
Strategic Next Steps
Connecting Affinity to ChatGPT via MCP transforms how your organization interacts with CRM data. Instead of forcing sales reps to navigate complex UI dashboards to log notes or update deal stages, they can execute these workflows conversationally.
By leveraging a managed infrastructure layer, you bypass the technical debt of maintaining custom JSON schemas, handling pagination cursors, and writing OAuth refresh logic. The integration simply works, allowing your engineering team to focus on building the actual AI agent logic rather than wrestling with vendor APIs.
Ready to automate your relationship intelligence? Review the complete tool definitions on the Affinity integration page and generate your first MCP server today.
Frequently Asked Questions
- How do I connect Affinity to ChatGPT?
- You can connect Affinity to ChatGPT using a Model Context Protocol (MCP) server. Generate a managed MCP server URL via Truto and paste it directly into ChatGPT's Developer Mode settings as a custom connector.
- Does ChatGPT support custom API integrations?
- Yes, through the Model Context Protocol (MCP). By providing an MCP server URL, ChatGPT can natively discover and execute external API operations as tools.
- How do I handle Affinity API rate limits with AI agents?
- Truto does not retry or absorb rate limit errors. When the upstream API returns an HTTP 429, Truto passes that error through to the caller with standardized rate limit headers (`ratelimit-limit`, `ratelimit-remaining`, `ratelimit-reset`), so your agent can read these headers and implement its own retry logic with appropriate backoff. See https://truto.one/docs/api-reference/overview/rate-limits