Connect Affinity to Claude: Automate Activity Logs & Notes via MCP
Learn how to connect Affinity to Claude using a managed MCP server. Automate relationship intelligence, deal tracking, and interaction notes without building custom integrations.
You want to connect Affinity to Claude so your AI agents can read relationship intelligence, update deal statuses, and draft interaction notes based on historical context (if your team uses OpenAI, check out our guide on connecting Affinity to ChatGPT). 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 recent 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 Claude Desktop, 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.
Anthropic's rollout of MCP client support 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 retry logic into your MCP server to prevent the agent from crashing.
The Flat Namespace Problem When an MCP client like Claude calls a tool, all arguments arrive as a single flat JSON object. REST APIs, however, expect specific parameters in the query string and others in the request body. You have to write custom mapping logic for every single Affinity endpoint to route the LLM's flat arguments to the correct HTTP locations.
OAuth Token Expiration Authentication is not a set-it-and-forget-it process. OAuth tokens expire. If your AI agent is running a long background task analyzing relationship strength across 50 accounts, and the token expires halfway through, the job fails. You must build a background scheduling system to proactively refresh tokens before they expire.
How Truto's Managed MCP Server Works
Truto eliminates this engineering overhead by exposing your connected Affinity account as a fully managed MCP server.
The system is dynamic and documentation-driven. Rather than hand-coding tool definitions, Truto derives them directly from the integration's resource definitions and schema documentation. A tool only appears in the MCP server if it has a corresponding documentation entry - acting as a quality gate to ensure Claude only sees well-described, predictable endpoints.
When Claude calls a tool, Truto's MCP router dynamically splits the flat input namespace into the correct query parameters and body payloads based on the underlying schema. It routes the request through a proxy API layer that handles authentication and pagination automatically. Rate limit responses from Affinity are passed through to the client with normalized rate limit headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset)—your agent or orchestration layer should implement retries with backoff when needed. Truto even schedules background tasks to proactively refresh OAuth tokens shortly before they expire, ensuring your agents never encounter an invalid_grant error mid-task.
Step 1: Create the Affinity MCP Server
You can generate a secure MCP server URL for your connected Affinity account using either the Truto UI or the REST API.
Method A: Via the Truto UI
This is the fastest method for internal testing and manual agent configuration.
- Navigate to the Integrated Accounts page in your Truto dashboard.
- Select your connected Affinity account.
- Click the MCP Servers tab.
- Click Create MCP Server.
- Configure your server. You can restrict access by selecting specific HTTP methods (e.g.,
readonly) or specific resource tags to limit the blast radius of your AI agent. - Copy the generated MCP server URL.
Method B: Via the API
If you are provisioning AI agents programmatically for your users, you should generate the MCP server via the API. The endpoint validates that the integration is AI-ready, generates a cryptographically secure token, and returns a ready-to-use URL.
Endpoint: POST https://api.truto.one/integrated-account/{integrated_account_id}/mcp
Request Body:
{
"name": "Claude Affinity Server",
"config": {
"methods": ["read", "write"],
"tags": ["crm", "interactions"]
},
"expires_at": "2026-12-31T23:59:59Z"
}Response:
{
"id": "mcp_123456789",
"name": "Claude Affinity Server",
"config": {
"methods": ["read", "write"],
"tags": ["crm", "interactions"]
},
"expires_at": "2026-12-31T23:59:59Z",
"url": "https://api.truto.one/mcp/a1b2c3d4e5f67890"
}Security Note: The generated URL contains a cryptographic token that authenticates the request. Treat this URL like a password. If you need an extra layer of security, you can set require_api_token_auth: true in the config, which forces the client to pass a valid Truto API token in the Authorization header alongside the URL.
Step 2: Connect the MCP Server to Claude Desktop
Once you have the Truto MCP URL, connecting it to Claude Desktop takes less than a minute.
- Open Claude Desktop.
- Navigate to Settings -> Connectors -> Add custom connector.
- Paste the Truto MCP server URL and click Add.
Claude will immediately ping the server, execute the initialization handshake, and request the list of available tools. No additional configuration is required.
Step 3: Executing Affinity Workflows with Claude
With the server connected, Claude can now interact directly with your Affinity data.
Example Workflow: Meeting Prep & Note Generation
User Prompt:
"I have a meeting with the CEO of Acme Corp tomorrow. Pull their relationship strength score, summarize our last three interactions, and draft a new reminder for me to send a follow-up email on Friday."
How Claude Executes This via MCP:
sequenceDiagram
participant C as Claude Desktop
participant M as Truto MCP Server
participant A as Affinity API
C->>M: tools/call (list_all_affinity_organizations)<br>{"query": "Acme Corp"}
M->>A: GET /organizations?term=Acme%20Corp
A-->>M: Organization Data
M-->>C: Organization ID: 98765
C->>M: tools/call (list_all_affinity_relationship_strength)<br>{"external_id": 98765}
M->>A: GET /relationship-strengths?external_id=98765
A-->>M: Score Data
M-->>C: Score: 85 (Strong)
C->>M: tools/call (list_all_affinity_interactions)<br>{"organization_id": 98765, "limit": 3}
M->>A: GET /interactions?organization_id=98765
A-->>M: Interaction History
M-->>C: Last 3 interactions
C->>M: tools/call (create_a_affinity_reminder)<br>{"owner_id": 123, "type": 0, "due_date": "2026-10-23"}
M->>A: POST /reminders
A-->>M: Reminder Created
M-->>C: Success ConfirmationClaude orchestrates the entire multi-step process autonomously, handling IDs, formatting dates, and parsing the JSON responses into a natural language summary for the user.
Complete Affinity Tool Inventory
When you connect Affinity via Truto, you get immediate access to a massive library of pre-configured tools. You can view the full documentation and schemas on the Affinity integration page.
Here is the complete inventory of tools available to your AI agents:
Reminders & Interactions
- 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 using its id. Returns id, type, created_at, content, due_date, etc.
- update_a_affinity_reminder_by_id: Update a reminder by id. Allows modifying fields such as type, reset_type, reminder_days, etc.
- delete_a_affinity_reminder_by_id: Delete a specific reminder. Requires id. Returns confirmation of successful deletion.
- list_all_affinity_reminders: List reminders filtered by optional parameters like person_id, organization_id, or opportunity_id.
- create_a_affinity_interaction: Create a new interaction with required parameters type, person_ids, content, and date.
- get_single_affinity_interaction_by_id: Get details for a specific interaction. Requires id and type. Returns fields including date and content.
- update_a_affinity_interaction_by_id: Update an existing interaction using id, type, and person_ids. Returns updated interaction fields.
- delete_a_affinity_interaction_by_id: Delete a specific interaction using id and type. Returns confirmation of successful deletion.
- list_all_affinity_interactions: List interactions filtered by type, start_time, and end_time. Returns key interaction fields.
- list_all_affinity_relationship_strength: Get relationship strength for a specific external_id. Returns key metrics such as score.
Notes & Files
- create_a_affinity_note: Create a new note. Requires content. Returns id and association details.
- get_single_affinity_note_by_id: Get a specific note using id. Returns creator_id, content, and person/org associations.
- update_a_affinity_note_by_id: Update a specific note by id with new content. Requires id and content.
- delete_a_affinity_note_by_id: Delete a note using id. Removes the specified note permanently.
- list_all_affinity_notes: List all notes. Returns key fields including creator_id and associated entities.
- affinity_files_upload: Upload file attachments for a specific entity using person_id. Returns uploaded file details.
- affinity_files_download: Download a specific file using id. Returns the actual file corresponding to the id.
- get_single_affinity_file_by_id: Get a specific file using id. Returns details of the entity file including metadata.
- list_all_affinity_files: List all files. Returns entity_files array containing all files within your organization.
People & Organizations
- create_a_affinity_person: Create a new person using first_name, last_name, and emails.
- get_single_affinity_person_by_id: Get a specific person by id. Returns name, primary_email, and associated metadata.
- update_a_affinity_person_by_id: Update a person using id. Returns updated details including name and emails.
- delete_a_affinity_person_by_id: Delete a person using id. Removes the person record permanently.
- list_all_affinity_persons: List persons that match search criteria. Returns an array of person records.
- create_a_affinity_organization: Create a new organization by providing name. Returns id and domain details.
- get_single_affinity_organization_by_id: Get details about a specific organization using id. Returns name, domain, and global fields.
- update_a_affinity_organization_by_id: Update organization with id. Returns updated fields such as name and domain.
- delete_a_affinity_organization_by_id: Delete an organization using id. Returns confirmation of deletion.
- list_all_affinity_organizations: List organizations that match search criteria. Returns key fields like organization name and domain.
Opportunities & Lists
- create_a_affinity_opportunity: Create a new opportunity with required parameters name and list_id.
- get_single_opportunity_by_id: Get a specific opportunity using id. Returns name, person_ids, and organization_ids.
- update_a_affinity_opportunity_by_id: Update an existing opportunity using id. Returns modified fields such as name and status.
- delete_a_affinity_opportunity_by_id: Delete an opportunity. Requires id. Returns confirmation of deletion status.
- list_all_affinity_opportunities: List opportunities that match search criteria. Returns id, name, and associated entities.
- create_a_affinity_list: Create a new list with specified name, type, and is_public parameters.
- get_single_affinity_list_by_id: Get details about a specific list using id. Returns attributes like type and public status.
- list_all_affinity_lists: List all lists visible to the user. Returns id, name, type, and owner_id.
- create_a_affinity_list_entry: Create a new list entry. 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. Returns id and entity details.
- delete_a_affinity_list_entry_by_id: Delete a specific list entry. Requires list_id and id. Returns success status.
- list_all_affinity_list_entries: Get all list entries for a specific list_id. Returns an array of list entries.
Fields & Configuration
- create_a_affinity_field: Create a new field. Requires name, entity_type, and value_type.
- delete_a_affinity_field_by_id: Delete a specific field using id. Returns confirmation of deletion.
- list_all_affinity_fields: List all fields. Returns id, name, list_id, enrichment_source, and value_type.
- list_all_affinity_person_fields: Get global person fields. Returns an array of global fields that exist on people.
- list_all_affinity_organization_fields: List all global organization fields. Returns id, name, and value_type.
- create_a_affinity_field_value: Create a new field value using required parameters field_id, entity_id, and value.
- update_a_affinity_field_value_by_id: Update a field value using id. Requires id. Returns the updated field value object.
- delete_a_affinity_field_value_by_id: Delete a field value. Requires id. Returns confirmation of deletion.
- list_all_affinity_field_values: Get all field values attached to a person, organization, opportunity, or list_entry.
- list_all_affinity_field_values_changes: List field-values-changes 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 Wrap-up
The future of CRM management is agentic. Forcing sales teams to manually log interactions, update deal stages, and hunt down relationship context is an outdated paradigm. By connecting Affinity directly to Claude via a managed MCP server, you transform a static database into an active participant in your sales process.
Stop wasting engineering cycles building custom integration layers and managing OAuth tokens. Use Truto to instantly generate MCP servers for Affinity, Salesforce, HubSpot, Jira, Ashby, Pylon, and 100+ other SaaS platforms, and focus your team on building intelligent agent workflows.
Frequently Asked Questions
- How do I connect Affinity to Claude?
- You can connect Affinity to Claude using a Model Context Protocol (MCP) server. Truto generates a secure, managed MCP server URL that you plug directly into Claude Desktop or ChatGPT.
- Can Claude update records in Affinity?
- Yes. By exposing write-enabled tools through an MCP server, Claude can create notes, update opportunities, and log interactions directly in your Affinity CRM.
- How does Truto handle Affinity API rate limits?
- 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