Connect Agiloft to Claude: NLP Search and Record Lifecycle Operations
Learn how to connect Agiloft to Claude using a managed MCP server. This step-by-step guide covers handling Agiloft's JWT tokens, locks, and async operations.
If you need to connect Agiloft to Claude to automate contract lifecycle management, execute action buttons on records, or perform natural-language queries across your knowledge base, you need a Model Context Protocol (MCP) server. This server acts as the translation layer between Claude's JSON-RPC tool calls and Agiloft's REST APIs. You can either build and maintain this infrastructure yourself, or use a managed integration platform like Truto to dynamically generate a secure, authenticated MCP server URL. If your team uses ChatGPT, check out our guide on /connect-agiloft-to-chatgpt-manage-records-files-and-action-buttons/ or explore our broader architectural overview on /connect-agiloft-to-ai-agents-automate-table-data-and-file-workflows/.
Giving a Large Language Model (LLM) read and write access to a sprawling enterprise system like Agiloft is a heavy engineering lift. You have to handle short-lived JWT token lifecycles, map massive dynamic table schemas to MCP tool definitions, and deal with Agiloft's explicit record-locking constraints. Every time your organization adds a custom table or modifies a choice list, you have to update your server code, redeploy, and test the integration.
This guide breaks down exactly how to use Truto to generate a secure, managed MCP server for Agiloft, connect it natively to Claude Desktop, and execute complex contract and record management workflows using natural language.
The Engineering Reality of the Agiloft API
A custom MCP server is a self-hosted integration layer. While the open MCP standard provides a predictable way for models to discover tools, the reality of implementing it against Agiloft's enterprise APIs is painful. You are not just integrating a simple REST API - you are integrating with a highly customizable, table-driven application platform with strict database-level rules.
If you decide to build a custom MCP server for Agiloft, you own the entire API lifecycle. Here are the specific challenges you will face:
Explicit Record Locking (EWLock)
Unlike many modern SaaS platforms that rely on optimistic concurrency (e.g., ETag headers), Agiloft heavily utilizes explicit record locking to prevent edit conflicts. If Claude attempts to update a contract record that a human user currently has open, the API will reject the request. A robust MCP implementation must give Claude the ability to check lock status (agiloft_record_locks_lookup), acquire a lock (agiloft_record_locks_lock), perform the update, and release the lock (agiloft_record_locks_unlock). If an LLM script fails midway, you must have a mechanism to release orphaned locks.
Asynchronous Action Buttons and Polling
Agiloft allows administrators to define complex "Action Buttons" (EWActionButton) that trigger rules, generate PDFs, or send emails. These operations are inherently asynchronous. When you call an action button via the API, Agiloft returns a 202 Accepted with a callback ID. The operation is queued. Your MCP server must expose a polling mechanism (EWAsyncStatus) so Claude can check if the job completed (200), is still in progress (202), or failed (501).
Database-Level SQL Queries vs NLP Search
Agiloft offers two distinct paradigms for finding records. The first is EWSelect, which allows direct database-level querying but requires writing raw SQL WHERE clauses using internal choice-line IDs instead of human-readable labels. This is notoriously difficult for LLMs to get right without prior schema mapping. The second is EWNLPSearch, which allows natural-language queries (e.g., "Active NDAs submitted last month"). A proper MCP server must expose both, teaching the LLM when to use the NLP engine and when to execute precise ID-based lookups.
Short-Lived JWT Tokens
Authentication in Agiloft via the EWLogin endpoint returns a JWT access token that defaults to a 15-minute lifespan. This means your MCP server cannot just store a long-lived API key. It must actively manage the session, trading the login and password for a new token continuously. If you miss a refresh, the agent's calls will fail mid-workflow.
Step 1: Generating the Agiloft MCP Server
Instead of building a bespoke server to handle Agiloft's JWT tokens, locks, and async polling, you can use Truto to generate a managed MCP server. Truto dynamically reads the Agiloft configuration (handling all endpoints from EWUpsert to EWNLPSearch) and exposes them as strongly typed JSON-RPC tools.
Truto manages the continuous EWLogin refresh cycle every 10 minutes behind the scenes. When Agiloft returns HTTP 429 rate limit errors, Truto does not absorb or retry them. It strictly passes the error to Claude, normalizing the headers into standard IETF formats (ratelimit-limit, ratelimit-remaining, ratelimit-reset). Claude or your agent framework is responsible for handling the backoff.
You can generate your MCP server using either the Truto UI or the API.
Method A: Via the Truto UI
- Log in to your Truto dashboard and navigate to your Integrated Accounts.
- Select your connected Agiloft account.
- Click the MCP Servers tab.
- Click Create MCP Server.
- Configure your server. You can restrict it to
readorwritemethods, or filter by specific tags (e.g.,contracts,attachments). - Copy the generated MCP Server URL (e.g.,
https://api.truto.one/mcp/a1b2c3d4...).
Method B: Via the Truto API
You can dynamically provision MCP servers for your users via a simple API call. This is ideal if you are deploying multi-tenant AI agents.
curl -X POST https://api.truto.one/integrated-account/{account_id}/mcp \
-H "Authorization: Bearer YOUR_TRUTO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Agiloft Contracts MCP",
"config": {
"methods": ["read", "write", "custom"],
"tags": ["records", "attachments", "actions"]
}
}'The response returns a self-contained, authenticated URL containing a hashed cryptographic token. This URL is everything Claude needs to interact with Agiloft.
Step 2: Connecting the MCP Server to Claude
With your MCP server URL in hand, you must register it with your Claude client. The setup depends on which interface you are using.
Method A: Via the Claude UI (or ChatGPT)
If you are using a web-based client that supports native MCP connectors (like ChatGPT Developer Mode or Claude for Enterprise):
- In your AI client, navigate to Settings -> Integrations (or Connectors) -> Add MCP Server.
- Provide a recognizable name (e.g., "Agiloft via Truto").
- Paste the Truto MCP URL into the endpoint configuration.
- Click Add. The client will send an
initializeJSON-RPC handshake to Truto and immediately populate its context window with the available Agiloft tools.
Method B: Via Manual Config File (Claude Desktop)
If you are running Claude Desktop locally, you configure MCP servers by editing the claude_desktop_config.json file. Because Truto's MCP servers are remote HTTP endpoints using Server-Sent Events (SSE), you use the official @modelcontextprotocol/server-sse package to bridge the connection.
Update your config file (typically found at ~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"agiloft": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-sse",
"https://api.truto.one/mcp/a1b2c3d4e5f6..."
]
}
}
}Restart Claude Desktop. The agent will read the config, fetch the Agiloft schemas, and display a plug icon indicating the tools are ready.
Agiloft Hero Tools for Claude
Truto maps the underlying Agiloft endpoints into descriptive, snake_case tools with strict JSON schemas. Here are the highest-leverage tools available for your agent.
agiloft_records_search
This tool executes the EWNLPSearch endpoint, allowing Claude to pass natural-language strings directly to Agiloft's AI search engine. This avoids the complexity of building raw SQL WHERE clauses for ad-hoc queries.
"Find all active NDAs submitted in the last 30 days that are waiting on legal approval, and summarize the counterparty names."
get_single_agiloft_record_by_id
Reads a specific record by its ID across any logical table (e.g., contract, company, employee). This returns the complete field payload.
"Fetch the full contract record for ID 10452 and list all custom fields related to the renewal terms."
create_a_agiloft_record_upsert
Executes an EWUpsert operation. If the provided match_query finds no record, a new one is created. If it finds exactly one, it updates it. If it finds multiple, it throws a 409 conflict. This is perfect for idempotency.
"Update the contract status to 'Approved' for the record where the contract name exactly matches 'Acme Corp Master MSA 2026'."
agiloft_action_buttons_execute
Triggers an internal Agiloft Action Button (EWActionButton) on a specific record. This is vital for triggering business logic like generating PDF summaries, sending routing emails, or converting a lead to an account.
"Execute the 'Generate PDF' action button on contract ID 4099 and let me know the callback ID so we can poll for completion."
agiloft_async_operations_lookup
Checks the status of asynchronous operations (like the action buttons above) using the EWAsyncStatus endpoint. Returns HTTP codes mapping to status (200 = complete, 202 = in progress).
"Check the status of callback ID 'cb-99482-12'. If it is completed, let me know the job is done."
create_a_agiloft_attachment
Uploads a file to a specific file field on an Agiloft record. The file content is passed in the body. This is frequently used after generating documents or saving agent-compiled research.
"Upload this generated risk summary markdown file to the 'compliance_docs' field on company record ID 883."
To view the complete inventory of tools, schemas, and required parameters, visit the Agiloft integration page.
Workflows in Action
Once connected, Claude can string multiple Agiloft tools together to execute complex, multi-step operations that traditionally require a human navigating the UI.
Scenario 1: Contract Discovery and NLP Update
An operations manager needs to locate a specific legacy agreement and update its expiration date, but they only know rough details about the counterparty.
"Search Agiloft for the vendor agreement with 'Stark Industries' from late last year. Once you find it, update the expiration date to December 31, 2027."
How the agent executes this:
- Calls
agiloft_records_searchwith the query "Stark Industries vendor agreement from last year". - Parses the result to identify the correct record ID and table logical name.
- Calls
create_a_agiloft_record_upsertusing the exact record ID to update theexpiration_datefield, successfully executing the change.
Scenario 2: Asynchronous Approval and Generation
A legal team member wants to trigger a complex internal approval flow that generates a final PDF and sends it for signature.
"Run the 'Send for Signature' action button on NDA record 5102. Monitor the job until it's finished and tell me when it's done."
sequenceDiagram
participant Claude as Claude
participant Truto as Truto MCP
participant Agiloft as Agiloft API
Claude->>Truto: agiloft_action_buttons_execute (Record 5102)
Truto->>Agiloft: POST /action_button
Agiloft-->>Truto: 202 Accepted (ID: async-884)
Truto-->>Claude: callback_id: async-884
Claude->>Truto: agiloft_async_operations_lookup (async-884)
Truto->>Agiloft: GET /async_status
Agiloft-->>Truto: 202 In Progress
Truto-->>Claude: Status: 202
Note over Claude: Agent waits internally
Claude->>Truto: agiloft_async_operations_lookup (async-884)
Truto->>Agiloft: GET /async_status
Agiloft-->>Truto: 200 Completed
Truto-->>Claude: Status: 200 CompletedHow the agent executes this:
- Calls
agiloft_action_buttons_executetargeting the NDA record and the specific button name. - Receives the
callback_idindicating the job is queued. - Calls
agiloft_async_operations_lookupusing the callback ID. - If the status is 202, the agent sleeps/waits, then polls again until the status returns 200, notifying the user of success.
Security and Access Control
Exposing a powerful ERP and CRM platform like Agiloft to an LLM requires strict boundary setting. Truto's MCP servers provide granular access controls enforced at the token level:
- Method filtering: You can restrict a server to specific operations. Passing
methods: ["read"]ensures the LLM can search and fetch records, but absolutely cannot executecreate,update,delete, orcustomaction buttons. - Tag filtering: Agiloft endpoints are categorized. You can apply
tags: ["contracts"]to isolate the agent to contract records, preventing it from touching employee data or system config tables. - Expiration controls: By setting an
expires_atISO datetime when creating the MCP server, you can generate ephemeral access. Once the timestamp passes, the server immediately rejects all connections. - Dual Authentication (
require_api_token_auth): By default, the MCP URL acts as a bearer token. By enabling this flag, the connecting client must also pass a valid Truto API token in theAuthorizationheader, ensuring only verified internal systems can interact with the server.
Strategic Wrap-up
Connecting Claude to Agiloft transforms a static knowledge base into an autonomous operations layer. However, attempting to build a custom MCP server means wrestling with Agiloft's specific engineering reality - explicit database locking, asynchronous job polling, and 15-minute JWT refreshes.
By leveraging a managed MCP platform, you skip the infrastructure build and get immediate, secure access to dynamically generated tools. Your AI agents can start running NLP searches, triggering action buttons, and managing the record lifecycle on day one.
FAQ
- How do MCP servers handle Agiloft's short-lived JWT tokens?
- When using a managed platform like Truto, the MCP server handles the EWLogin endpoint automatically, refreshing the JWT access token in the background every 10 minutes so your AI agent maintains a persistent connection.
- Can Claude trigger Agiloft Action Buttons?
- Yes. Using the `agiloft_action_buttons_execute` tool, Claude can trigger action buttons. Because these are asynchronous, the agent must use the `agiloft_async_operations_lookup` tool to poll the callback ID until the job completes.
- How does Truto handle Agiloft API rate limits?
- Truto does not retry or throttle rate limits. When the Agiloft API returns an HTTP 429, Truto passes the error directly to the caller, normalizing the rate limit information into standard IETF headers (ratelimit-limit, ratelimit-remaining, ratelimit-reset).
- How can I prevent Claude from deleting Agiloft records?
- When generating the MCP server URL via Truto, you can configure method filtering by passing `methods: ["read", "update"]`. This enforces strict boundaries at the token level, preventing the LLM from executing delete or destructive operations.