Skip to content

Agent Integration

Contio publishes a set of machine-readable artifacts alongside the Partner API docs so that coding agents and LLM toolchains can discover and call the API without hand-coding the integration.

Artifacts

Artifact URL Purpose
llms.txt /partner-api/llms.txt Human- and LLM-readable index of every Partner API operation. Drop this URL into an agent's context window for a quick overview of available endpoints.
operations.json /partner-api/agent/operations.json Structured per-operation metadata (parameters, request/response schemas, auth surface) enriched with hand-written sidecars.
mcp.json /partner-api/agent/mcp.json Model Context Protocol tool manifest for building MCP servers.

Quick start

Give your coding agent the llms.txt URL and it will have enough context to explore the API, select the right endpoints, and construct valid requests:

https://docs.contio.ai/partner-api/llms.txt

Pointing a coding agent at the API

Paste the URL into the agent's prompt or context window:

Read https://docs.contio.ai/partner-api/llms.txt and use the
Contio Partner API to list my upcoming meetings.

Fetch operations.json for enriched per-operation metadata:

curl -s https://docs.contio.ai/partner-api/agent/operations.json | jq 'keys'

If the agent supports the Model Context Protocol, register the tool manifest:

import tools from "./mcp.json" assert { type: "json" };

// Return all tools from the manifest
server.setRequestHandler("tools/list", async () => ({ tools: tools.tools }));

Using llms.txt

The llms.txt file follows the llms.txt standard — a convention for providing LLM-readable context about a site or API. It serves as a human-readable index that coding agents can quickly parse to understand available operations.

What's in llms.txt

The file contains:

  1. Header — Links to related resources (OpenAPI spec, operations.json, mcp.json)
  2. Authentication summary — Operation counts per auth surface
  3. Operations by category — Every operation grouped by domain (Meetings, Action Items, etc.)

Each operation entry includes:

- **{operationId}** `{METHOD} {path}` — {summary} ([details](...)) [{auth-surface}]

Using with Coding Agents

Cursor, Windsurf, Copilot, and similar IDE agents:

Add the URL to your project's context or paste it at the start of a conversation:

@https://docs.contio.ai/partner-api/llms.txt

List all meetings for the current user and show their summaries.

Claude, ChatGPT, and similar chat agents:

Include the URL in your prompt:

Read https://docs.contio.ai/partner-api/llms.txt

Help me integrate with the Contio API to:
1. Create a meeting from a calendar event
2. Get the meeting summary when it's ready
3. Create action items for follow-ups

Programmatic context injection:

Fetch and inject into your agent's system prompt:

const llmsTxt = await fetch("https://docs.contio.ai/partner-api/llms.txt").then(r => r.text());

const systemPrompt = `You are an API integration assistant.

Here is the Partner API reference:

${llmsTxt}

Use this information to help the user integrate with the Contio API.`;

When to Use llms.txt vs Other Artifacts

Use Case Recommended Artifact
Quick exploration with a coding agent llms.txt
Building an HTTP client or code generator operations.json
Building an MCP server mcp.json
Full schema validation or SDK generation OpenAPI spec
Pre-built TypeScript/JavaScript client Partner SDK
Manual API testing and exploration Postman collection

llms.txt is for discovery, not execution

llms.txt gives agents enough context to understand what the API can do and select the right operations. For how to call them (schemas, parameter types, auth details), agents should fetch operations.json or the OpenAPI spec.

Using operations.json

The operations.json file provides structured metadata for every Partner API operation, designed for programmatic consumption by HTTP clients, code generators, and agent toolchains.

Structure

Each operation is keyed by its operationId (e.g., listMeetings, createActionItem) and contains:

Field Type Description
id string Operation identifier (same as the key)
method string HTTP method (GET, POST, PUT, DELETE, etc.)
path string URL path with parameter placeholders (e.g., /v1/partner/user/meetings/{id})
summary string Short description of what the operation does
description string Detailed explanation of behavior and requirements
auth object Authentication requirements (see below)
idempotency object Whether Idempotency-Key header is supported
request object Request parameters (path, query, header, body)
responses object Response status codes and their descriptions
flags array Internal flags (e.g., no_sidecar, missing_idempotency_key)

Authentication Surfaces

The auth.surface field indicates which authentication method the operation requires:

Surface Auth Header Description
admin X-API-Key Partner Admin API operations (manage your integration)
user-oauth Authorization: Bearer <token> Partner User API operations (access user data)
public None Public endpoints (OAuth flows, discovery, health checks)

For user-oauth operations, auth.scopes lists required OAuth scopes:

{
  "auth": {
    "surface": "user-oauth",
    "scopes": ["meetings:read"],
    "headers": ["Authorization"]
  }
}

Building an HTTP Client

Use operations.json to dynamically construct API requests:

import operations from "./operations.json" assert { type: "json" };

async function callPartnerApi(
  operationId: string,
  params: Record<string, any>,
  auth: { apiKey?: string; accessToken?: string }
) {
  const op = operations[operationId];
  if (!op) throw new Error(`Unknown operation: ${operationId}`);

  // Build URL with path parameters
  let url = `https://api.contio.ai${op.path}`;
  for (const param of op.request?.parameters ?? []) {
    if (param.in === "path") {
      url = url.replace(`{${param.name}}`, params[param.name]);
    }
  }

  // Build headers based on auth surface
  const headers: Record<string, string> = { "Content-Type": "application/json" };
  if (op.auth.surface === "admin" && auth.apiKey) {
    headers["X-API-Key"] = auth.apiKey;
  } else if (op.auth.surface === "user-oauth" && auth.accessToken) {
    headers["Authorization"] = `Bearer ${auth.accessToken}`;
  }

  // Add idempotency key for mutations if supported
  if (op.idempotency?.supported && op.method !== "GET") {
    headers["Idempotency-Key"] = crypto.randomUUID();
  }

  // Build query string and body
  const queryParams = new URLSearchParams();
  let body: string | undefined;
  for (const param of op.request?.parameters ?? []) {
    if (param.in === "query" && params[param.name] !== undefined) {
      queryParams.set(param.name, params[param.name]);
    }
    if (param.in === "body") {
      body = JSON.stringify(params[param.name]);
    }
  }

  const queryString = queryParams.toString();
  const fullUrl = queryString ? `${url}?${queryString}` : url;

  const response = await fetch(fullUrl, { method: op.method, headers, body });
  return response.json();
}

// Usage
const meetings = await callPartnerApi("listMeetings", {}, { accessToken: "..." });

Idempotency Support

Operations with idempotency.supported: true accept an Idempotency-Key header for safe retries. The response includes:

  • Idempotent-Replayed: true header when returning a cached response
  • 422 with idempotency_key_reuse if the key was used with different parameters
  • 409 with Retry-After header for concurrent requests with the same key

Relationship to Other Artifacts

Artifact Use Case
operations.json Build HTTP clients, code generators, or agent tool implementations
mcp.json Build MCP servers (includes tool schemas derived from this data)
llms.txt Quick context injection for coding agents (human-readable)
OpenAPI spec Full request/response JSON schemas, validation, and SDK generation
Partner SDK Pre-built TypeScript/JavaScript client with high-level resource abstractions
Postman collection Interactive API testing, exploration, and request prototyping

When to use operations.json vs OpenAPI vs SDK

Use operations.json when you need a flat, operation-centric view with pre-computed auth and idempotency metadata. Use the OpenAPI spec when you need full JSON schemas for request validation or response typing. Use the Partner SDK when you want a batteries-included TypeScript client without building your own HTTP layer.

Using MCP with the Partner API

The Model Context Protocol (MCP) enables AI agents to call tools through a standardized interface. To expose Partner API operations as MCP tools, you build an MCP server that translates tool calls into API requests.

Understanding mcp.json

The mcp.json file is a tool manifest containing 120+ tool definitions—one for each Partner API operation. Each tool includes:

  • name — The operation identifier (e.g., listMeetings, createActionItem)
  • description — What the tool does
  • inputSchemaJSON Schema 2020-12 defining the parameters
  • annotations — Behavioral hints per the MCP specification:
    • readOnlyHint — Tool only reads data (safe to call without side effects)
    • destructiveHint — Tool may delete or modify data irreversibly
    • idempotentHint — Repeated calls with same input produce same result

Tool manifest, not server config

mcp.json defines what tools exist, not how to connect to a server. MCP clients expect a server configuration (URL, command, etc.), not a raw tool list. Use mcp.json as input when building your MCP server.

Building an MCP Server

To serve Partner API operations via MCP, implement a server that:

  1. Responds to tools/list — Return the tools from mcp.json
  2. Handles tools/call — Map the tool name to a Partner API endpoint, execute the HTTP request, and return the result

Refer to these MCP resources:

Example: Minimal TypeScript server structure

import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import tools from "./mcp.json" assert { type: "json" };

const server = new Server({ name: "contio-partner", version: "1.0.0" }, {
  capabilities: { tools: {} }
});

// Return all tools from the manifest
server.setRequestHandler("tools/list", async () => ({ tools: tools.tools }));

// Execute tool calls by mapping to Partner API endpoints
server.setRequestHandler("tools/call", async (request) => {
  const { name, arguments: args } = request.params;
  // Map tool name to endpoint, make HTTP request, return result
  const result = await executePartnerApiCall(name, args);
  return { content: [{ type: "text", text: JSON.stringify(result) }] };
});

const transport = new StdioServerTransport();
await server.connect(transport);

Server Configuration

Once you've built and deployed your MCP server, configure your MCP client to connect to it. The configuration format depends on the transport:

Local stdio server:

{
  "mcpServers": {
    "contio-partner": {
      "command": "node",
      "args": ["path/to/your/server.js"]
    }
  }
}

Remote HTTP/SSE server:

{
  "mcpServers": {
    "contio-partner": {
      "url": "https://your-server.example.com/mcp"
    }
  }
}

Authentication

Agents still need valid credentials. See the Authentication guide for how to obtain API keys (admin operations) or OAuth tokens (user operations).