Skip to content
Confirm MCP server compatibility
Public Preview

MCP compatibility, call contract, and Tool catalog API

MCP compatibility, the synchronous call contract, fixed platform limits, and the Tool catalog API define how Duale AI connects to and invokes remote Tools.

Reference for MCP server compatibility, synchronous call behavior, fixed platform limits, and the organization Tool catalog API for SDK and MCP Tool Sources.

  • MCP Connections require Streamable HTTP at one public HTTPS URL with specific MCP protocol versions.
  • This release supports only synchronous MCP calls returning complete text or structured results.
  • After three failures for one Tool, Duale AI pauses that Connection-and-Tool pair for 30 seconds.
  • The Tool catalog API uses cursor pagination and requires user tokens bound via DPoP.
  • Platform limits cap remote responses at 4 MiB and accepted Tool Results at 2 MiB.

Summaries were generated by AI.

Use this page to check MCP server compatibility, synchronous call behavior, and fixed limits. It also documents the organization Tool catalog API for SDK and MCP Tool Sources. For setup, connect an MCP server. For status, naming, Analytics, and recovery, operate Tools.

Confirm MCP server compatibility

An MCP Connection supports Streamable HTTP at one exact public HTTPS URL. The server must negotiate MCP 2025-06-18, 2025-11-25, or 2026-07-28 and answer catalog and Tool requests at that URL. Duale AI uses HTTP/1.1, does not follow redirects, does not retain server cookies, requests an uncompressed response, and rejects a compressed response. A server that negotiates an older MCP revision, or that depends on a redirect, cookie state, compression, or HTTP/2, is not compatible with this release.

Choose one authentication mode: no authentication, one bearer token, or one API key in an allowed custom header. The same credential applies to catalog checks and Tool Calls for that named Connection.

Understand the MCP call contract

This release supports synchronous MCP calls that return a complete text or structured result. It does not continue interactive input_required responses, queued MCP Tasks, or a task handle returned for later retrieval. Image, audio, embedded resource, and resource-link result blocks are not supported.

Duale AI cannot guarantee exactly-once execution for a remote MCP Tool. When Duale AI cannot rule out that the server received a request, it does not intentionally retry that logical call. If it also cannot prove the response, the call ends as Outcome unknown. Make state-changing remote operations idempotent where possible. Check the destination system before any manual retry or compensation.

After three transport, timeout, or invalid-result failures for one Tool, Duale AI pauses that Connection-and-Tool pair for 30 seconds. Catalog checks and other Tools on the Connection continue. The next call after the pause can test the Tool again.

Check MCP Connection limits

These Platform limits are not configurable per Connection.

BoundaryLimit
Connection100-character name and 1,000 assigned Agent Identities
Complete catalog check30 seconds, 128 pages, 4,096 Tools, and 4 MiB of Tool definitions
One Tool definition512 KiB; 128-character native name; 4,096-character description
Tool JSON Schemas64 levels and 100,000 total JSON nodes across the input and optional output schemas
Tool Call arguments256 top-level properties
Remote HTTP response4 MiB before protocol projection
Accepted Tool Result2 MiB; at most 32 text blocks, each no more than 1 MiB
  • Boundary
    Connection
    Limit
    100-character name and 1,000 assigned Agent Identities
  • Boundary
    Complete catalog check
    Limit
    30 seconds, 128 pages, 4,096 Tools, and 4 MiB of Tool definitions
  • Boundary
    One Tool definition
    Limit
    512 KiB; 128-character native name; 4,096-character description
  • Boundary
    Tool JSON Schemas
    Limit
    64 levels and 100,000 total JSON nodes across the input and optional output schemas
  • Boundary
    Tool Call arguments
    Limit
    256 top-level properties
  • Boundary
    Remote HTTP response
    Limit
    4 MiB before protocol projection
  • Boundary
    Accepted Tool Result
    Limit
    2 MiB; at most 32 text blocks, each no more than 1 MiB

If a catalog check exceeds a limit, the whole check fails and does not replace the active catalog. If a Tool Result exceeds a limit, Duale AI rejects that result.

Tool limits covers the same boundaries for an SDK Tool Host, and how many Tools one Agent Identity can hold across every Source.

Read the organization Tool catalog API

The API reads the same retained repository shown in the Dashboard. These user-authenticated routes require a user access token bound with Demonstrating Proof of Possession (DPoP), an acr claim of 2, and the permission shown below. They do not accept an Agent Identity API token. The Dashboard obtains the user credential; this preview does not document a standalone command-line sign-in flow. Tenant access policies explains how permissions combine.

For managed beta, use https://api.beta.duale.ai/orgraph as the base URL. For another deployment, use the Orgraph base URL supplied with that deployment.

RequestPermissionResult and filters
GET /tenants/{tenant_id}/tool-sourcestools:read_catalog on the TenantSource states; optional source_kind=sdk|mcp
GET /tenants/{tenant_id}/tool-sources/toolstools:read_catalog on the TenantRetained Tools; optional source_kind, source_id, and freshness=active|expired|all; freshness defaults to all
GET /tenants/{tenant_id}/agents/{agent_id}/toolsagent:read on the Agent IdentityAssigned Tools, offered first then recently lost; required order_by_name=native|model; optional freshness=active|expired|all (default active) and expired_within_days (default 7, maximum 30)
  • Request
    GET /tenants/{tenant_id}/tool-sources
    Permission
    tools:read_catalog on the Tenant
    Result and filters
    Source states; optional source_kind=sdk|mcp
  • Request
    GET /tenants/{tenant_id}/tool-sources/tools
    Permission
    tools:read_catalog on the Tenant
    Result and filters
    Retained Tools; optional source_kind, source_id, and freshness=active|expired|all; freshness defaults to all
  • Request
    GET /tenants/{tenant_id}/agents/{agent_id}/tools
    Permission
    agent:read on the Agent Identity
    Result and filters
    Assigned Tools, offered first then recently lost; required order_by_name=native|model; optional freshness=active|expired|all (default active) and expired_within_days (default 7, maximum 30)

This illustrative request asks for one active Tool assigned to an Agent Identity. Replace the user token and DPoP proof with values issued for your signed-in session.

GET /orgraph/tenants/tenant_a/agents/agent_research/tools?order_by_name=native&freshness=active&limit=1 HTTP/1.1
Host: api.beta.duale.ai
Authorization: DPoP <user-access-token>
DPoP: <proof>

A successful response is a JSON object:

{
  "agent_id": "agent_research",
  "tools": [
    {
      "source_kind": "mcp",
      "source_id": "0199d7df-40f8-7000-8000-000000000001",
      "source_name": "CRM Production",
      "native_tool_name": "search_contacts",
      "model_tool_name": "mcp_search_contacts",
      "description": "Search contacts",
      "reasons": [],
      "freshness": "active",
      "last_observed_at": "2026-09-14T10:00:00Z",
      "expires_at": "2026-09-14T10:07:00Z"
    }
  ],
  "next_cursor": null
}

Each collection uses opaque cursor pagination. limit defaults to 100 and accepts 1 through 500. Send the returned next_cursor unchanged with the same Tenant and filters. A null value marks the final page. These are live reads, not a cross-page snapshot. If the catalog changes while you paginate and you need one consistent current traversal, restart from the first page. The Agent Identity read pins the instant its first page was evaluated against and carries it in the cursor, so every page of one traversal reports freshness against that instant. A different order_by_name, freshness, or expired_within_days is a different traversal, and the earlier cursor is refused.

The response shapes are:

RequestResponse body
Tool Source listsources: Source state objects; next_cursor: string or null
Retained Tool listtools: retained Tool objects; next_cursor: string or null
Tools assigned to one Agent Identityagent_id: requested identity; tools: assigned Tool objects; next_cursor: string or null
  • Request
    Tool Source list
    Response body
    sources: Source state objects; next_cursor: string or null
  • Request
    Retained Tool list
    Response body
    tools: retained Tool objects; next_cursor: string or null
  • Request
    Tools assigned to one Agent Identity
    Response body
    agent_id: requested identity; tools: assigned Tool objects; next_cursor: string or null

The item fields are:

ItemFields
Source statesource_kind, source_id, source_name, freshness, last_observed_at, expires_at, assigned_agent_count, retained_tool_count
Toolsource_kind, source_id, source_name, native_tool_name, model_tool_name, optional description, reasons, freshness, last_observed_at, expires_at
  • Item
    Source state
    Fields
    source_kind, source_id, source_name, freshness, last_observed_at, expires_at, assigned_agent_count, retained_tool_count
  • Item
    Tool
    Fields
    source_kind, source_id, source_name, native_tool_name, model_tool_name, optional description, reasons, freshness, last_observed_at, expires_at

The retained Tool list and the Agent Identity list return the same Tool object. reasons states compatibility: it is empty for a Tool the Platform can expose to a model, and an incompatible Tool has model_tool_name: null and one or more entries in it. description is present only when the Source reports one. The Agent Identity response includes only compatible Tools under the selected freshness filter, so its reasons is always empty.

Errors use application/problem+json. A malformed cursor, or a cursor reused with another Tenant or filter set, returns 400. Missing or insufficient user authentication returns 401. A caller without the required permission receives 403. An invalid path or query value returns 422.