# MCP servers for an integrated account

> Source: https://truto.one/docs/guides/integrated-accounts/mcp-servers/

Create an MCP server for one connected account and hand its URL to an AI agent. The agent sees that account's Proxy APIs as tools, and nothing else: no other accounts, no other tenants.

This page covers the **per-integrated-account MCP server**. For the workspace-wide server that calls the Truto platform API, see [Platform MCP server](/docs/guides/assistant/platform-mcp-server).

:::skip-reading{cli="truto mcp-tokens create <integrated_account_id> --name support-agent" skill="truto"}
:::

## Before you start

- **Plan.** MCP servers are a plan feature. On a plan without them, creating one fails with `MCP server creation is not available on your current plan`. Contact support@truto.one to change your plan.
- **Described tools.** The server exposes the account's [tools](/docs/guides/tools/overview): Proxy API methods that have a description. If the account has none, creating a server fails with `This integration is not yet AI-ready`. Add descriptions to the integration's methods (see [Adding tools to an integration](/docs/guides/tools/overview#adding-tools-to-an-integration)) or contact support.
- **Limit.** Each integrated account can have up to 10 MCP servers. Delete one you no longer use to make room.

## 1. Create the server

### From the console

1. Open the account at **Integrated Accounts → your account → MCP Servers** (`app.truto.one/integrated-accounts/<id>/mcp-servers`).
2. Click **Create MCP Server**.
3. Fill in the modal:
   - **Name of the MCP Server** (required) — a label to identify it.
   - **Method** — leave empty for all methods, or pick `read`, `write`, or individual method names such as `list` or `search`.
   - **Tags** — leave empty for all tools, or pick resource tags to narrow the tool set.
   - **Tool exposure** — **All tools** or **Discovery (3 meta-tools)**. See [Tool exposure](#tool-exposure).
   - **Expires At** — optional date and time after which the server stops working.
   - **Require Auth** — when on, every request must also carry a Truto API token. See [Requiring an API token](#requiring-an-api-token).
4. Click **Create MCP Server**, copy the URL, tick **I have copied my MCP Server URL shown above**, and click **Done**.

:::callout{type="warning"}
The URL contains the server's secret token and is shown once. Truto stores only a hash of it, so it can't be shown again. If you lose it, delete the server and create a new one.
:::

### From the API

`POST /integrated-account/:id/mcp` creates a server. Only `name` is required.

| Field | Type | Meaning |
| --- | --- | --- |
| `name` | string | Label for the server. Required. |
| `config.methods` | string[] | Allowed methods. Use a method name (`list`, `get`, `create`, `update`, `delete`, or a custom one such as `search`) or a group: `read` (`get`, `list`), `write` (`create`, `update`, `delete`), `custom` (every other method). Empty or omitted means all. |
| `config.tags` | string[] | Only tools carrying at least one of these tags. Empty or omitted means all. Combined with `methods`: a tool must match both. |
| `config.tool_exposure` | `all` \| `discovery` | How tools appear to the agent. Defaults to `all`. |
| `config.require_api_token_auth` | boolean | Require a Truto API token on every MCP request. Defaults to `false`. |
| `expires_at` | ISO 8601 string or `null` | When the server stops working. Must be more than 60 seconds in the future. |

Every method you list must match at least one tool on the account, and the combination of methods and tags must match at least one tool; otherwise the request returns `400` and names the methods and tags that are available.

:::code-tabs

```bash label="cURL"
curl -X POST https://api.truto.one/integrated-account/<integrated_account_id>/mcp \
  -H "Authorization: Bearer <API token>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Support agent (read-only)",
    "config": {
      "methods": ["read"],
      "tags": ["support"],
      "tool_exposure": "all",
      "require_api_token_auth": false
    },
    "expires_at": "2026-12-31T23:59:59.000Z"
  }'
```

```bash label="CLI"
truto mcp-tokens create <integrated_account_id> \
  --body '{"name":"Support agent (read-only)","config":{"methods":["read"],"tags":["support"]},"expires_at":"2026-12-31T23:59:59.000Z"}'
```

```python label="Python"
server = await truto_api.integrated_accounts.create_mcp_server(
    "<integrated_account_id>",
    {
        "name": "Support agent (read-only)",
        "config": {"methods": ["read"], "tags": ["support"]},
        "expires_at": "2026-12-31T23:59:59.000Z",
    },
)
print(server["url"])
```

:::

The response is the server record plus two fields that are only returned here:

```json
{
  "id": "2ba1f401-7183-47c5-9e39-e8e257e3c796",
  "name": "Support agent (read-only)",
  "integrated_account_id": "1ba1f401-7183-47c5-9e39-e8e257e3c795",
  "config": { "methods": ["read"], "tags": ["support"] },
  "expires_at": "2026-12-31T23:59:59.000Z",
  "created_by": "0c1a2b3c-4d5e-6f70-8192-a3b4c5d6e7f8",
  "created_at": "2026-11-02T10:00:00.000Z",
  "updated_at": "2026-11-02T10:00:00.000Z",
  "token": "4f1c5e0b6c2d4f8a9b3c5d7e9f0a1b2c",
  "url": "https://api.truto.one/mcp/4f1c5e0b6c2d4f8a9b3c5d7e9f0a1b2c"
}
```

Store `url` (or `token`) as a secret. Anyone holding it can call the account's tools, unless the server requires an API token.

## 2. Connect an MCP client

The server speaks JSON-RPC over HTTP `POST` to `https://api.truto.one/mcp/<token>` (the Streamable HTTP transport). Paste the URL into any client that supports remote HTTP MCP servers.

:::code-tabs

```bash label="Claude Code"
claude mcp add --transport http hubspot-support https://api.truto.one/mcp/<token>
```

```json label="Cursor"
{
  "mcpServers": {
    "hubspot-support": {
      "url": "https://api.truto.one/mcp/<token>"
    }
  }
}
```

```json label="Claude Desktop"
{
  "mcpServers": {
    "hubspot-support": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://api.truto.one/mcp/<token>"]
    }
  }
}
```

:::

For Cursor, put the config in `.cursor/mcp.json` or `~/.cursor/mcp.json`. For Claude Desktop, put it in `claude_desktop_config.json` and restart the app.

To check the server from code before handing it to an agent, send `tools/list` yourself:

:::code-tabs

```bash label="cURL"
curl -X POST https://api.truto.one/mcp/<token> \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}'
```

```ts label="TypeScript"
import TrutoApi from '@truto/truto-ts-sdk'

const trutoApi = new TrutoApi({ token: process.env.TRUTO_API_TOKEN })

const tools = await trutoApi.mcp.listTools('<token>')
const result = await trutoApi.mcp.callTool('<token>', '<tool_name>', {})
```

```python label="Python"
tools = await truto_api.mcp.list_tools("<token>")
result = await truto_api.mcp.call_tool("<token>", "<tool_name>", {})
```

:::

Take tool names and their input schemas from `tools/list`. A tool call returns a text block holding JSON with `result`, `next_cursor`, `prev_cursor`, and `request_id`.

## Tool exposure

- **`all`** — `tools/list` returns every tool that matches the server's methods and tags, each with its input schema. Simple, but a large integration can fill the agent's context with schemas.
- **`discovery`** — `tools/list` returns three tools, and the agent finds the rest on demand:
  - `search_tools` — takes a `query` (for example `"list contacts"`) and an optional `limit` (default 5, max 20). An empty query browses every tool grouped by resource. Returns names, descriptions, and tags.
  - `get_tool_schema` — takes `tool_names`, up to 5 names from `search_tools`, and returns their input schemas.
  - `call_tool` — takes `tool_name` and `arguments` and runs the tool.

Discovery still respects `config.methods` and `config.tags`: the agent can only find and call tools the server allows.

## Requiring an API token

With `config.require_api_token_auth` set to `true` (**Require Auth** in the console), every request to the server URL must also send a Truto [API token](/docs/guides/api-tokens/creating-api-tokens):

```bash
curl -X POST https://api.truto.one/mcp/<token> \
  -H "Authorization: Bearer <API token>" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}'
```

Integrated account tokens are rejected; use an API token. Clients that can't send headers (Cursor's `url` config, for example) need a bridge such as `mcp-remote` with `--header`, as shown in [Platform MCP server → Cursor](/docs/guides/assistant/platform-mcp-server#cursor).

## Manage servers

| Action | Route | CLI |
| --- | --- | --- |
| List | `GET /integrated-account/:id/mcp` | `truto mcp-tokens list <account_id>` |
| Get | `GET /integrated-account/:id/mcp/:mcp_server_id` | `truto mcp-tokens get <account_id> <mcp_server_id>` |
| Update | `PATCH /integrated-account/:id/mcp/:mcp_server_id` | `truto mcp-tokens update <account_id> <mcp_server_id> --body '<json>'` |
| Delete | `DELETE /integrated-account/:id/mcp/:mcp_server_id` | `truto mcp-tokens delete <account_id> <mcp_server_id>` |

List and get never return the token or URL. `PATCH` accepts `name`, `config`, and `expires_at`, and changes apply to the existing URL; the token stays the same. `config` is merged key by key, so `{"config": {"tool_exposure": "discovery"}}` keeps the server's methods and tags. Send `"expires_at": null` to remove an expiry.

:::code-tabs

```bash label="cURL"
curl -X PATCH https://api.truto.one/integrated-account/<integrated_account_id>/mcp/<mcp_server_id> \
  -H "Authorization: Bearer <API token>" \
  -H "Content-Type: application/json" \
  -d '{"config": {"tool_exposure": "discovery"}}'
```

```bash label="CLI"
truto mcp-tokens update <integrated_account_id> <mcp_server_id> --tool-exposure discovery
```

```python label="Python"
await truto_api.integrated_accounts.update_mcp_server(
    "<integrated_account_id>",
    "<mcp_server_id>",
    {"config": {"tool_exposure": "discovery"}},
)
```

:::

In the console, click a server's name to open **Edit MCP Server**, or the trash icon to delete it. Deleting is permanent and the URL stops working. `truto mcp-tokens delete` asks for confirmation unless you pass `--force`.

When `expires_at` passes, Truto removes the server and its URL returns `404` with `MCP Token not found or expired.` Create a new server to restore access.

## Debug with logs

Every request to a per-integrated-account MCP server is logged. Open **Logs → MCP** (`app.truto.one/logs/mcp`) and filter by integrated account, MCP server, and date range to see each MCP method, the tool called, the client name, and timings. See [Viewing logs](/docs/guides/logs/viewing-logs).

## Next

Narrow what the agent can do by giving each use case its own server: a read-only server for a support assistant, a `write` server with a short `expires_at` for a one-off migration. To shape the tools themselves, edit method descriptions and schemas in the integration; see [Tools overview](/docs/guides/tools/overview). Full request and response schemas are in the [MCP API reference](/docs/api-reference/admin/mcp).
