---
title: Claude, ChatGPT and other agent platforms
description: Connect agents built outside Veefore through MCP or the REST gateway, and what Veefore can and cannot see on each platform.
---
Step-by-step guides: [Claude and MCP clients](/build/claude),
[ChatGPT](/build/chatgpt), [n8n](/build/n8n), [n8n Cloud](/build/n8n-cloud).
This page is the overview and the adapter contract for other platforms.

Agents built on another platform reach Veefore the same way any agent does:
through the gateway, as a registered agent, with policy, risk, approval and the
credential broker applied. The difference is what Veefore can see of the rest
of the platform, which is usually nothing.

:::warning A Veefore connection does not mediate the platform's other tools
If a user also adds a Gmail connector directly in Claude, or ChatGPT uses a
built-in connector, those actions never reach Veefore. Veefore reports these
runtimes as **Partial** at best and says so on the runtime page.
:::

## Claude and other MCP clients

Veefore serves two MCP endpoints, both authenticated with an agent's **MCP key**
(`Authorization: Bearer vf_mcp_…`, created on the agent page):

| Endpoint | What it exposes |
| --- | --- |
| `https://<gateway>/mcp` | Veefore's own tools: `veefore_list_tools`, `veefore_authorize`, `veefore_execute`, `veefore_action_status`, `veefore_recent_actions`. |
| `https://<gateway>/mcp/<server>` | One brokered MCP server's tools, the authorized ones only. See [MCP clients](/build/mcp-client). |

Support differs by client:

| Client | How | Status |
| --- | --- | --- |
| Claude Code | `claude mcp add --transport http veefore https://<gateway>/mcp --header "Authorization: Bearer vf_mcp_…"` | Supported |
| Cursor, VS Code | Remote server with an `Authorization` header | Supported |
| Claude Desktop | Through `mcp-remote` with the header | Supported |
| claude.ai custom connector, static header | Organization Owner adds the header (Anthropic beta, limited organizations) | Partial |
| claude.ai custom connector, OAuth | Needs an OAuth authorization server with dynamic client registration | **Not implemented by Veefore** |

Register the client under **Integrations → Claude and MCP clients** with the
same agent, so its connection and status are tracked. It shows **Connected**
only once Veefore has seen the agent call it.

`veefore_execute` opens an approval when policy asks for one and answers with
its ID; nothing happens until a person approves and the model calls again with
`approval_id`.

## ChatGPT and API-based platforms

Use the REST gateway as a custom action:

1. `POST /gateway/v1/authorize` — dry run; ALLOW returns a single-use
   authorization bound to the parameters.
2. `POST /gateway/v1/actions` — executes; refuses a request that differs from
   its authorization.
3. `GET /gateway/v1/actions/{id}` — status.

The gateway authenticates agents with a session token from a signed assertion,
and ChatGPT can only send a fixed API key. The **Veefore relay**
(`integrations/veefore-relay`, one file, no dependencies) bridges the two: you
run it with the agent's key, ChatGPT calls it with a relay API key, and it
signs and forwards. The agent's private key never goes to ChatGPT.

1. Run the relay (Docker or `node relay.mjs`) behind HTTPS with
   `VEEFORE_GATEWAY_URL`, the agent's ID, key ID and private key, and
   `RELAY_API_KEYS`. See its README.
2. In the GPT editor, **Actions → Import from URL**:
   `https://<relay>/openapi.json`. Authentication: **API key, Bearer**, one of
   the relay keys.
3. In the GPT's instructions, have it call `authorizeAction`, then
   `executeAction` with the returned `authorization_id`, and treat
   `done: false` as "nothing happened".

A retried call presenting the same authorization or approval is sent with the
same idempotency key, so it does not happen twice. Administrative restrictions
on which actions users may add are configured in ChatGPT, not in Veefore.

## Custom agents

The JavaScript and Python SDKs call the same gateway paths:

```ts
const decision = await client.authorize({ tool: 'send_email', parameters });
if (decision.result === 'ALLOW') {
  await client.act({ tool: 'send_email', parameters, authorizationId: decision.authorizationId! });
}
```

```python
decision = client.authorize(ActionRequest(tool="send_email", parameters=params))
if decision.result == "ALLOW":
    client.act(ActionRequest(tool="send_email", parameters=params, authorization_id=decision.authorization_id))
```

The SDK is not an enforcement point. Code in the agent that calls a provider
directly is invisible to Veefore; brokered HTTP tools keep the provider secret
out of the agent so there is nothing to call it with.

## Other runtimes

A new runtime integrates by translating its requests into the
`veefore.action/v1` envelope (`ActionEnvelopeV1` in `@veefore/types`) and
describing what it can let Veefore verify (`RuntimeCapabilityStatement`). An
adapter has no access to policy, risk, approvals or credentials; the gateway
applies all of them. Register it as **Other runtimes**; with no
runtime-specific verification it is reported Partial at best.
