Getting started

MCP Server

Qualy runs a remote Model Context Protocol (MCP) server that lets AI agents work with your Qualy data through a curated set of tools. Connect a client such as Claude Desktop, Cursor, or Windsurf — or build your own agent — and it can look up contacts, create payment requests, search your data, and more, all scoped to your tenant.

Beta

The MCP server is new and in beta. The set of tools will grow over time, and tool names or inputs may still change while we iterate.


Endpoint

The server speaks the Streamable HTTP MCP transport at:

https://api.qualyhq.com/v1/mcp

Authenticate with a single header — your Qualy API key as a bearer token:

HeaderValue
AuthorizationBearer <your-api-key>

The tenant is encoded in the key, so MCP needs no X-TENANT-ID header. (Authorization: ApiKey <key> is also accepted, and if your client happens to send X-TENANT-ID it's cross-checked against the key.) Every tool call runs with the permissions of the API key's user and is scoped to its tenant.


Connect a client

Most MCP clients connect by adding an entry to their MCP configuration.

Clients with native remote MCP support

Cursor, Windsurf, and similar clients can point at the remote server directly:

{
  "mcpServers": {
    "qualy": {
      "url": "https://api.qualyhq.com/v1/mcp",
      "headers": {
        "Authorization": "Bearer pk_prod_your-api-key"
      }
    }
  }
}

Claude Desktop and stdio-only clients

Clients that only launch local (stdio) servers can bridge to the remote server with mcp-remote:

{
  "mcpServers": {
    "qualy": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://api.qualyhq.com/v1/mcp",
        "--header",
        "Authorization: Bearer pk_prod_your-api-key"
      ]
    }
  }
}

After saving the configuration and restarting your client, the Qualy tools appear in its tool list.

Other clients

Any MCP-compatible client connects the same way: point it at https://api.qualyhq.com/v1/mcp and set Authorization: Bearer <your-api-key>. ChatGPT, Claude.ai, Replit, Zed and others each have their own "add MCP server" / connectors screen — follow your client's MCP instructions (for example, Cursor's MCP install links). A hosted one-click Connect Qualy (OAuth) flow is on the roadmap.

Keep your key safe

Your MCP configuration stores the API key in plain text on your machine. Treat it like any other secret — see API key best practices.


Available tools

All tools are scoped to your tenant. Reads are safe to call freely; writes are rate-limited and de-duplicated.

Contacts

ToolWhat it does
contact_listList contacts (customers / leads / students), newest first; filter by email.
contact_getGet one contact by id or email.
contact_createCreate a contact. Returns the existing contact if the email is already on file.
contact_updateUpdate a contact's name, phone, or email.

Payment intents

ToolWhat it does
payment_intent_listList payment requests; filter by contact or status.
payment_intent_getGet one payment intent, including its shareable payment link.
payment_intent_createCreate a payment request for a contact.
payment_intent_cancelCancel a payment intent.

Transactions

ToolWhat it does
transaction_listList transactions (charges and refunds); filter by contact, payment intent, or status.
transaction_getGet one transaction by its id.

Orders

ToolWhat it does
order_listList orders; filter by contact.
order_getGet one order by its id.

Partnerships

ToolWhat it does
partnership_listList partnerships (agents / institutions / suppliers).
partnership_getGet one partnership by id, code, or name.
partnership_createCreate a partnership.
ToolWhat it does
searchFuzzy search across contacts or partnerships by name, email, or keyword.

What's not exposed

For safety, moving money — capturing charges and issuing refunds — is not available through MCP. Those operations still go through the API or the Dashboard. The MCP server is read-heavy with a few safe writes.


Smart references

Wherever a tool takes a contact or partnership, you can pass a natural identifier instead of a Mongo ObjectId — Qualy resolves it to the right record before the tool runs. An agent that only knows a student's email or a partner's name doesn't need to look up an id first. This is the same Smart references resolution the REST API uses, applied to the MCP tools' reference fields.

FieldAccepts
contacta contact id, or the contact's email (case-insensitive)
partnershipa partnership id, code, exact name, or a unique name prefix

Examples

Get a contact by email instead of an id — contact_get:

{ "contact": "camila@example.com" }

Raise a payment request straight from the payer's email, with no lookup step — payment_intent_create:

{
  "contact": "camila@example.com",
  "currency": "AUD",
  "items": [{ "name": "Tuition — Semester 1", "amount": 12000 }]
}

Fetch a partner by name (or its code) — partnership_get:

{ "partnership": "Sydney English College" }

The same contact resolution applies to the contact filter on payment_intent_list, transaction_list, and order_list.

When a reference is ambiguous

If a name or prefix matches more than one record, the tool returns an AGENT_TOOL_AMBIGUOUS_REFERENCE error listing the candidate records, so the agent can retry with something more specific (an exact name, the partnership code, or an id). If nothing matches, it returns AGENT_TOOL_REFERENCE_NOT_FOUND.

For automated flows, prefer stable identifiers — email, partnership code, or id — over name prefixes, which can drift into ambiguity as new records are added.


When to use MCP vs the API

The MCP server and the REST API run on the same platform, the same data, and the same API-key auth — they're two front doors to the same back office. Pick by how your integration is driven:

Use the MCP server when an AI assistant is your interface. A person or agent asks in natural language and the model decides which tools to call, in what order, with you approving anything that writes. It exposes a curated, tenant-scoped subset of the platform — ideal for the long tail of ad-hoc questions and tasks ("find this student, draft a plan, chase that invoice") without writing or maintaining integration code.

Use the REST API when you're building a programmatic integration. You get the full endpoint surface, deterministic control over every call, webhooks, idempotency keys, and conveniences like Smart references — sending a contact email, partnership code, or service name where an endpoint expects an ObjectId. (MCP tools accept Smart references too, so this isn't a reason to choose one over the other.)

Many teams use both — an assistant for day-to-day operators, the API for their own product surface. They never conflict: every call, from either door, runs through the same tenant scoping, permissions, and platform controls.


Build your own agent

To drive the server from your own agent, connect with any MCP-compatible client library. With the official TypeScript SDK:

import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';

const transport = new StreamableHTTPClientTransport(
  new URL('https://api.qualyhq.com/v1/mcp'),
  {
    requestInit: {
      headers: {
        Authorization: 'Bearer pk_prod_your-api-key',
      },
    },
  },
);

const client = new Client({ name: 'my-agent', version: '1.0.0' });
await client.connect(transport);

// Discover the tools…
const { tools } = await client.listTools();

// …and call one.
const result = await client.callTool({
  name: 'contact_list',
  arguments: { limit: 5 },
});

console.log(result);

Behavior and limits

  • Tenant scoping — every call runs against your tenant only; the tenant is taken from your credentials.
  • Rate limits — calls are rate-limited per tool. Reads have a generous budget; writes are tighter. Exceeding a limit returns an AGENT_TOOL_RATE_LIMITED error with a retry hint.
  • Idempotency — write tools (create / update / cancel) are idempotent: repeating the same call with the same input within 24 hours returns the original result instead of creating a duplicate.
  • Structured errors — tool errors come back with a code and message so your agent can react — for example, retry on a rate limit or re-prompt on invalid input.
Previous
Terminology