> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://developer.jelliu.co/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://developer.jelliu.co/_mcp/server.

# Create an MCP server

POST https://api.jelliu.co/api/mcp-servers
Content-Type: application/json

Registers an MCP server with the voice engine and stores it for the workspace.
There are two ways to create one.

A **custom server** needs `name` and `serverUrl`. Its approval mode defaults to `always_ask`
and its transport to the voice engine's default (SSE) unless you send `transport`. Most
hosted MCP servers speak streamable HTTP: with the wrong transport the server registers but
never answers a tool call. A custom server reaches no agent until you call
`POST /api/agents/{agentId}/mcp-servers`.

A **hosted provider** (`provider`: `zapier`, `alegra` or `make`; see
`GET /api/mcp-servers/providers`) needs only its token in `secretToken`: name, description,
endpoint, transport (`STREAMABLE_HTTP`) and approval mode (`no_approval`) come from the
catalogue. Make hosts per region, so `serverUrl` is required for it. Alegra authenticates
with HTTP Basic: send `usuario:token` as `secretToken`. A provider URL pasted without
`provider` is recognised from its host and held to the same rules; a token found in its query
string or path is moved into the secret so the stored URL never carries a credential. A
hosted provider server is attached to every provisioned agent right away (agents at their
plan cap, or still provisioning, are skipped silently).

Refused with `400` and the field in `details.fieldErrors`: a `transport` other than the
provider's, a missing token, a `serverUrl` on another host than the provider's, a malformed
Alegra secret, or a URL that is not `http(s)` or targets a private/internal address.
`toolOverrides` requires `approvalMode: fine_grained`, accepts at most 50 entries and rejects
`disabled` (these three answer `400` without `details`). When decisions are sent, the
response carries `toolOverridesSync`; if any failed to apply the status is `207` instead of
`201`, the server is still created, and `toolOverrides` shows only what was applied.

**Side effects.** Creates the server in the voice engine and pushes per-tool approval
decisions; with a hosted provider, also updates every agent's MCP server list in the voice
engine. The token and custom headers are stored encrypted. Writes an `mcp.manage` audit entry.

**Idempotency.** Not idempotent. A retry registers a second, independent server (and, for a
hosted provider, attaches that copy to every agent too, using another slot of each agent's
cap). After a timeout, check `GET /api/mcp-servers` before retrying.

**Webhook events.** `audit.log_recorded` for the audit entry, if you subscribe to it. See [Webhooks](/webhooks).

**Access**

* **Required scope:** `write`. Any workspace role.
* **Rate limit:** General API — 120 (Starter), 200 (Growth), 300 (Business) or 600 (Enterprise) requests/min per workspace, checked by two counters of the same size. See [Rate limits](/rate-limits).
* **Plan:** Available on every plan. Automatic attachment of a hosted provider respects the MCP-servers-per-agent cap (Starter 1, Growth 3, Business 10).

Reference: https://developer.jelliu.co/api-reference/mcp-servers/post-mcp-servers

## Authentication

- `Authorization` header (bearer token, required) — Workspace API key: `jl_` followed by 64 lowercase hex characters, created by the workspace owner in the dashboard (**Settings → API Keys**) and sent as `Authorization: Bearer jl_...`. The plaintext is shown once, at creation; Jelliu stores only a SHA-256 hash. A workspace can hold up to 25 active keys. | Scope | GET / HEAD | POST / PUT / PATCH / DELETE | Admin-only routes | | --- | --- | --- | --- | | `read` | Yes | No | No | | `write` | Yes | Yes | No | | `full` | Yes | Yes | Yes | Operations restricted to admins or owners reject keys without the `full` scope with `403`, and say so in their description. No key, whatever its scope, can mint or revoke API keys or rotate a webhook secret — that requires a signed-in owner session. A revoked key stops authenticating within about 10 seconds. See [Authentication](/authentication).

## Request

### Body (application/json)

This endpoint expects an object.

- `provider` (enum, optional) — Hosted provider preset: `zapier`, `alegra` or `make`. When set, `name` and `description` are optional and default to the provider's.
  - Allowed values: `zapier`, `alegra`, `make`
- `name` (string, optional) — Display name, trimmed. Required without `provider`.
- `description` (string, optional) — Sent to the voice engine and read by the agent to decide when to use the server's tools. Defaults to the provider's agent-facing description when `provider` is set.
- `serverUrl` (string, optional) — The server's MCP endpoint (`http` or `https`). Required without `provider`, and for `make`. Must not target localhost or private/internal addresses; with a provider it must be on the provider's host.
- `secretToken` (string, optional) — Credential, stored encrypted and never returned. Sent to the server as `Authorization: Bearer <token>`, or as HTTP Basic for `alegra` (send `usuario:token`). Required with a provider unless `customHeaders` already carries `Authorization`.
- `customHeaders` (map from string to string, optional, default: {}) — Extra HTTP headers sent to the server on every request (at most 20; names up to 200 characters, values up to 2000). Stored encrypted and never returned.
- `approvalMode` (enum, optional) — Approval policy for the server's tools: `always_ask`, `fine_grained` or `no_approval`. Defaults to `always_ask` for a custom server and to `no_approval` with a provider.
  - Allowed values: `always_ask`, `fine_grained`, `no_approval`
- `transport` (enum, optional) — `SSE` or `STREAMABLE_HTTP`. Fixed to `STREAMABLE_HTTP` for providers (a different value is refused). Omitted on a custom server, the voice engine's default (SSE) applies and `transport` is stored as `null`.
  - Allowed values: `SSE`, `STREAMABLE_HTTP`
- `toolOverrides` (map from string to enum, optional, default: {}) — Per-tool approval keyed by the tool name the server advertises: `auto_approved` or `requires_approval`. Only with `approvalMode: fine_grained`; at most 50 entries; `disabled` is rejected with 400 (remove the assignment instead). A tool the server does not advertise is reported in `toolOverridesSync.failures`.
  - Allowed values: `auto_approved`, `requires_approval`, `disabled`

## Response

### 201

Created. `toolOverridesSync` is present only when per-tool decisions were sent.

- `data` (object, required) — A single MCP server as returned by the create, retrieve and update endpoints: the summary fields plus `deleted_at` and the applied per-tool decisions. `secret_token` and `custom_headers` are never returned.
  - `id` (string, optional) — Unique identifier of the server.
  - `tenant_id` (string, optional) — The workspace that owns the server.
  - `agent_id` (string, optional, nullable) — `null` for workspace servers (always `null` in the workspace list, which excludes per-agent gateway rows). Can be set on `GET /api/mcp-servers/{mcpServerId}` for such a row.
  - `name` (string, optional) — Display name.
  - `description` (string, optional, nullable) — Agent-facing description of what the server's tools do.
  - `server_url` (string, optional) — The MCP endpoint. Tokens pasted in a provider URL are stripped before saving.
  - `approval_mode` (enum, optional) — Approval policy — `always_ask`, `fine_grained` or `no_approval`.
    - Allowed values: `always_ask`, `fine_grained`, `no_approval`
  - `transport` (enum, optional) — `SSE`, `STREAMABLE_HTTP`, or `null` when the voice engine's default (SSE) applies.
    - Allowed values: `SSE`, `STREAMABLE_HTTP`
  - `provider` (enum, optional) — Hosted provider recognised from the URL host (`zapier`, `alegra`, `make`); `null` for a custom server. Computed on every read, not stored.
    - Allowed values: `zapier`, `alegra`, `make`
  - `created_at` (datetime, optional) — When the server was created.
  - `updated_at` (datetime, optional) — Last change to the server.
  - `deleted_at` (datetime, optional, nullable) — Always `null` on these endpoints (deleted servers answer 404).
  - `toolOverrides` (map from string to enum, optional) — Per-tool approval decisions currently applied in the voice engine, keyed by tool name: `auto_approved` (runs without asking) or `requires_approval` (asks first). Only what actually landed is shown. Empty unless `approval_mode` is `fine_grained`.
    - Allowed values: `auto_approved`, `requires_approval`
- `toolOverridesSync` (object, optional) — What happened when per-tool decisions were pushed to the voice engine. Present only when decisions were sent, or re-applied after a re-registration or cleanup of legacy values.
  - `synced` (integer, optional) — Decisions applied in the voice engine.
  - `removed` (integer, optional) — Previously applied decisions that were withdrawn because they are no longer in the requested set.
  - `failed` (integer, optional) — Decisions that could not be applied or withdrawn. When greater than 0, create answers 207 and update answers 502.
  - `failures` (list of object, optional) — One entry per failed decision.
    - `tool` (string, optional) — The tool name the decision was for.
    - `stage` (enum, optional) — `push` (applying failed) or `retire` (withdrawing an old decision failed).
      - Allowed values: `push`, `retire`
    - `reason` (string, optional) — Why it failed, e.g. the server does not advertise the tool, or the voice engine's tool catalogue was unavailable.

### 207

Created, but at least one per-tool decision could not be applied (see `toolOverridesSync.failures`). `data.toolOverrides` lists only the decisions that landed; retry the rest with `PATCH /api/mcp-servers/{mcpServerId}`.

- `data` (object, required) — A single MCP server as returned by the create, retrieve and update endpoints: the summary fields plus `deleted_at` and the applied per-tool decisions. `secret_token` and `custom_headers` are never returned.
  - `id` (string, optional) — Unique identifier of the server.
  - `tenant_id` (string, optional) — The workspace that owns the server.
  - `agent_id` (string, optional, nullable) — `null` for workspace servers (always `null` in the workspace list, which excludes per-agent gateway rows). Can be set on `GET /api/mcp-servers/{mcpServerId}` for such a row.
  - `name` (string, optional) — Display name.
  - `description` (string, optional, nullable) — Agent-facing description of what the server's tools do.
  - `server_url` (string, optional) — The MCP endpoint. Tokens pasted in a provider URL are stripped before saving.
  - `approval_mode` (enum, optional) — Approval policy — `always_ask`, `fine_grained` or `no_approval`.
    - Allowed values: `always_ask`, `fine_grained`, `no_approval`
  - `transport` (enum, optional) — `SSE`, `STREAMABLE_HTTP`, or `null` when the voice engine's default (SSE) applies.
    - Allowed values: `SSE`, `STREAMABLE_HTTP`
  - `provider` (enum, optional) — Hosted provider recognised from the URL host (`zapier`, `alegra`, `make`); `null` for a custom server. Computed on every read, not stored.
    - Allowed values: `zapier`, `alegra`, `make`
  - `created_at` (datetime, optional) — When the server was created.
  - `updated_at` (datetime, optional) — Last change to the server.
  - `deleted_at` (datetime, optional, nullable) — Always `null` on these endpoints (deleted servers answer 404).
  - `toolOverrides` (map from string to enum, optional) — Per-tool approval decisions currently applied in the voice engine, keyed by tool name: `auto_approved` (runs without asking) or `requires_approval` (asks first). Only what actually landed is shown. Empty unless `approval_mode` is `fine_grained`.
    - Allowed values: `auto_approved`, `requires_approval`
- `toolOverridesSync` (object, required) — What happened when per-tool decisions were pushed to the voice engine. Present only when decisions were sent, or re-applied after a re-registration or cleanup of legacy values.
  - `synced` (integer, optional) — Decisions applied in the voice engine.
  - `removed` (integer, optional) — Previously applied decisions that were withdrawn because they are no longer in the requested set.
  - `failed` (integer, optional) — Decisions that could not be applied or withdrawn. When greater than 0, create answers 207 and update answers 502.
  - `failures` (list of object, optional) — One entry per failed decision.
    - `tool` (string, optional) — The tool name the decision was for.
    - `stage` (enum, optional) — `push` (applying failed) or `retire` (withdrawing an old decision failed).
      - Allowed values: `push`, `retire`
    - `reason` (string, optional) — Why it failed, e.g. the server does not advertise the tool, or the voice engine's tool catalogue was unavailable.

## Errors

### 400 Bad Request Error

Invalid input. Schema and provider-rule failures carry `details` (`formErrors` / `fieldErrors`); `toolOverrides` rule failures carry only the message.

- `error` (object, required) — The error object. Always has `code` and `message`.
  - `code` (string, required) — Stable machine-readable error code (for example `VALIDATION_FAILED`, `UNAUTHORIZED`, `FORBIDDEN`, `NOT_FOUND`, `BILLING_ERROR`, `COMPLIANCE_BLOCKED`, `RATE_LIMIT_EXCEEDED`, `INTERNAL_ERROR`). Switch on this, not on `message`. See [Errors](/errors).
  - `message` (string, required) — Human-readable explanation. English or Spanish depending on the route; may change without notice.
  - `details` (object or list of object, optional) — Present on `VALIDATION_FAILED` only. Its shape depends on how the route validates: * a field map, either Zod's `flatten()` output (`{ "formErrors": [], "fieldErrors": { "name": ["..."] } }`) or just its `fieldErrors` part (`{ "name": ["..."] }`); * an issue list, where each issue has at least `path`, `message` and `code`. `path` is a dot-separated string on routes that let the schema throw, and an array of keys on routes that forward Zod's raw issues (those also carry Zod's extra issue fields).
    - Field map
      - `formErrors` (list of string, optional)
      - `fieldErrors` (map from string to list of string, optional)
  - `metadata` (map from string to any, optional) — Structured detail exposed for a small allowlist of codes only — for example `BILLING_ERROR` carries `limit`, `current` and `tier` (resource caps) or `tier` and `feature` (feature gates).

### 401 Unauthorized Error

No usable credential. Either the `Authorization` header is missing or is not a well-formed `Bearer jl_…` key, or the key is unknown, revoked or expired. Do not retry with the same key. See [Authentication](/authentication#401-unauthorized).

- `error` (object, required) — The error object. Always has `code` and `message`.
  - `code` (string, required) — Stable machine-readable error code (for example `VALIDATION_FAILED`, `UNAUTHORIZED`, `FORBIDDEN`, `NOT_FOUND`, `BILLING_ERROR`, `COMPLIANCE_BLOCKED`, `RATE_LIMIT_EXCEEDED`, `INTERNAL_ERROR`). Switch on this, not on `message`. See [Errors](/errors).
  - `message` (string, required) — Human-readable explanation. English or Spanish depending on the route; may change without notice.
  - `details` (object or list of object, optional) — Present on `VALIDATION_FAILED` only. Its shape depends on how the route validates: * a field map, either Zod's `flatten()` output (`{ "formErrors": [], "fieldErrors": { "name": ["..."] } }`) or just its `fieldErrors` part (`{ "name": ["..."] }`); * an issue list, where each issue has at least `path`, `message` and `code`. `path` is a dot-separated string on routes that let the schema throw, and an array of keys on routes that forward Zod's raw issues (those also carry Zod's extra issue fields).
    - Field map
      - `formErrors` (list of string, optional)
      - `fieldErrors` (map from string to list of string, optional)
  - `metadata` (map from string to any, optional) — Structured detail exposed for a small allowlist of codes only — for example `BILLING_ERROR` carries `limit`, `current` and `tier` (resource caps) or `tier` and `feature` (feature gates).

### 403 Forbidden Error

The API key lacks `write`, or the workspace is suspended.

- `error` (object, required) — The error object. Always has `code` and `message`.
  - `code` (string, required) — Stable machine-readable error code (for example `VALIDATION_FAILED`, `UNAUTHORIZED`, `FORBIDDEN`, `NOT_FOUND`, `BILLING_ERROR`, `COMPLIANCE_BLOCKED`, `RATE_LIMIT_EXCEEDED`, `INTERNAL_ERROR`). Switch on this, not on `message`. See [Errors](/errors).
  - `message` (string, required) — Human-readable explanation. English or Spanish depending on the route; may change without notice.
  - `details` (object or list of object, optional) — Present on `VALIDATION_FAILED` only. Its shape depends on how the route validates: * a field map, either Zod's `flatten()` output (`{ "formErrors": [], "fieldErrors": { "name": ["..."] } }`) or just its `fieldErrors` part (`{ "name": ["..."] }`); * an issue list, where each issue has at least `path`, `message` and `code`. `path` is a dot-separated string on routes that let the schema throw, and an array of keys on routes that forward Zod's raw issues (those also carry Zod's extra issue fields).
    - Field map
      - `formErrors` (list of string, optional)
      - `fieldErrors` (map from string to list of string, optional)
  - `metadata` (map from string to any, optional) — Structured detail exposed for a small allowlist of codes only — for example `BILLING_ERROR` carries `limit`, `current` and `tier` (resource caps) or `tier` and `feature` (feature gates).

### 429 Too Many Requests Error

General API rate limit exceeded.

- `error` (object, required) — The error object. Always has `code` and `message`.
  - `code` (string, required) — Stable machine-readable error code (for example `VALIDATION_FAILED`, `UNAUTHORIZED`, `FORBIDDEN`, `NOT_FOUND`, `BILLING_ERROR`, `COMPLIANCE_BLOCKED`, `RATE_LIMIT_EXCEEDED`, `INTERNAL_ERROR`). Switch on this, not on `message`. See [Errors](/errors).
  - `message` (string, required) — Human-readable explanation. English or Spanish depending on the route; may change without notice.
  - `details` (object or list of object, optional) — Present on `VALIDATION_FAILED` only. Its shape depends on how the route validates: * a field map, either Zod's `flatten()` output (`{ "formErrors": [], "fieldErrors": { "name": ["..."] } }`) or just its `fieldErrors` part (`{ "name": ["..."] }`); * an issue list, where each issue has at least `path`, `message` and `code`. `path` is a dot-separated string on routes that let the schema throw, and an array of keys on routes that forward Zod's raw issues (those also carry Zod's extra issue fields).
    - Field map
      - `formErrors` (list of string, optional)
      - `fieldErrors` (map from string to list of string, optional)
  - `metadata` (map from string to any, optional) — Structured detail exposed for a small allowlist of codes only — for example `BILLING_ERROR` carries `limit`, `current` and `tier` (resource caps) or `tier` and `feature` (feature gates).

### 500 Internal Server Error

The URL's host resolves to a private or internal address (checked after DNS resolution, beyond the syntactic 400 check). Currently answered as a generic 500.

- `error` (object, required) — The error object. Always has `code` and `message`.
  - `code` (string, required) — Stable machine-readable error code (for example `VALIDATION_FAILED`, `UNAUTHORIZED`, `FORBIDDEN`, `NOT_FOUND`, `BILLING_ERROR`, `COMPLIANCE_BLOCKED`, `RATE_LIMIT_EXCEEDED`, `INTERNAL_ERROR`). Switch on this, not on `message`. See [Errors](/errors).
  - `message` (string, required) — Human-readable explanation. English or Spanish depending on the route; may change without notice.
  - `details` (object or list of object, optional) — Present on `VALIDATION_FAILED` only. Its shape depends on how the route validates: * a field map, either Zod's `flatten()` output (`{ "formErrors": [], "fieldErrors": { "name": ["..."] } }`) or just its `fieldErrors` part (`{ "name": ["..."] }`); * an issue list, where each issue has at least `path`, `message` and `code`. `path` is a dot-separated string on routes that let the schema throw, and an array of keys on routes that forward Zod's raw issues (those also carry Zod's extra issue fields).
    - Field map
      - `formErrors` (list of string, optional)
      - `fieldErrors` (map from string to list of string, optional)
  - `metadata` (map from string to any, optional) — Structured detail exposed for a small allowlist of codes only — for example `BILLING_ERROR` carries `limit`, `current` and `tier` (resource caps) or `tier` and `feature` (feature gates).

### 502 Bad Gateway Error

The voice engine refused or did not answer the registration. Nothing was created. As with every 5xx, the body carries a generic message; the code identifies the cause.

- `error` (object, required) — The error object. Always has `code` and `message`.
  - `code` (string, required) — Stable machine-readable error code (for example `VALIDATION_FAILED`, `UNAUTHORIZED`, `FORBIDDEN`, `NOT_FOUND`, `BILLING_ERROR`, `COMPLIANCE_BLOCKED`, `RATE_LIMIT_EXCEEDED`, `INTERNAL_ERROR`). Switch on this, not on `message`. See [Errors](/errors).
  - `message` (string, required) — Human-readable explanation. English or Spanish depending on the route; may change without notice.
  - `details` (object or list of object, optional) — Present on `VALIDATION_FAILED` only. Its shape depends on how the route validates: * a field map, either Zod's `flatten()` output (`{ "formErrors": [], "fieldErrors": { "name": ["..."] } }`) or just its `fieldErrors` part (`{ "name": ["..."] }`); * an issue list, where each issue has at least `path`, `message` and `code`. `path` is a dot-separated string on routes that let the schema throw, and an array of keys on routes that forward Zod's raw issues (those also carry Zod's extra issue fields).
    - Field map
      - `formErrors` (list of string, optional)
      - `fieldErrors` (map from string to list of string, optional)
  - `metadata` (map from string to any, optional) — Structured detail exposed for a small allowlist of codes only — for example `BILLING_ERROR` carries `limit`, `current` and `tier` (resource caps) or `tier` and `feature` (feature gates).

## Examples

### Zapier created

**Request**

```json
undefined
```

**Response**

```json
{
  "data": {
    "id": "3c2b1a09-8f7e-4d6c-b5a4-938271605f4e",
    "tenant_id": "0e9d7c3b-8a1f-4c55-b7a2-3c4d5e6f7a8b",
    "agent_id": null,
    "name": "Zapier",
    "description": "Actions in the apps this business has connected through Zapier (CRM, calendar, email, spreadsheets, messaging, and thousands more). To act: call inspect_zapier_actions to see what is already enabled.",
    "server_url": "https://mcp.zapier.com/api/v1/connect",
    "approval_mode": "no_approval",
    "transport": "STREAMABLE_HTTP",
    "provider": "zapier",
    "created_at": "2026-09-14T15:02:11.000Z",
    "updated_at": "2026-09-14T15:02:11.000Z",
    "deleted_at": null,
    "toolOverrides": {}
  }
}
```

**SDK Code**

```python Zapier created
import requests

url = "https://api.jelliu.co/api/mcp-servers"

headers = {"Authorization": "Bearer <token>"}

response = requests.post(url, headers=headers)

print(response.json())
```

```javascript Zapier created
const url = 'https://api.jelliu.co/api/mcp-servers';
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Zapier created
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.jelliu.co/api/mcp-servers"

	req, _ := http.NewRequest("POST", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Zapier created
require 'uri'
require 'net/http'

url = URI("https://api.jelliu.co/api/mcp-servers")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java Zapier created
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.jelliu.co/api/mcp-servers")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php Zapier created
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.jelliu.co/api/mcp-servers', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp Zapier created
using RestSharp;

var client = new RestClient("https://api.jelliu.co/api/mcp-servers");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift Zapier created
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.jelliu.co/api/mcp-servers")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Custom server with decisions applied

**Request**

```json
undefined
```

**Response**

```json
{
  "data": {
    "id": "6e5d4c3b-2a19-4807-b6f5-e4d3c2b1a098",
    "tenant_id": "0e9d7c3b-8a1f-4c55-b7a2-3c4d5e6f7a8b",
    "agent_id": null,
    "name": "Inventario Ferretería El Tornillo",
    "description": "Consulta de existencias y precios por referencia.",
    "server_url": "https://mcp.eltornillo.com.co/mcp",
    "approval_mode": "fine_grained",
    "transport": "STREAMABLE_HTTP",
    "provider": null,
    "created_at": "2026-09-11T09:30:00.000Z",
    "updated_at": "2026-09-11T09:30:00.000Z",
    "deleted_at": null,
    "toolOverrides": {
      "consultar_existencias": "auto_approved",
      "crear_pedido": "requires_approval"
    }
  },
  "toolOverridesSync": {
    "synced": 2,
    "removed": 0,
    "failed": 0,
    "failures": []
  }
}
```

**SDK Code**

```python Custom server with decisions applied
import requests

url = "https://api.jelliu.co/api/mcp-servers"

headers = {"Authorization": "Bearer <token>"}

response = requests.post(url, headers=headers)

print(response.json())
```

```javascript Custom server with decisions applied
const url = 'https://api.jelliu.co/api/mcp-servers';
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Custom server with decisions applied
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.jelliu.co/api/mcp-servers"

	req, _ := http.NewRequest("POST", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Custom server with decisions applied
require 'uri'
require 'net/http'

url = URI("https://api.jelliu.co/api/mcp-servers")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java Custom server with decisions applied
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.jelliu.co/api/mcp-servers")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php Custom server with decisions applied
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.jelliu.co/api/mcp-servers', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp Custom server with decisions applied
using RestSharp;

var client = new RestClient("https://api.jelliu.co/api/mcp-servers");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift Custom server with decisions applied
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.jelliu.co/api/mcp-servers")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### MCP Servers_postMcpServers_example

**Request**

```json
undefined
```

**Response**

```json
{
  "data": {
    "id": "6e5d4c3b-2a19-4807-b6f5-e4d3c2b1a098",
    "tenant_id": "0e9d7c3b-8a1f-4c55-b7a2-3c4d5e6f7a8b",
    "agent_id": null,
    "name": "Inventario Ferretería El Tornillo",
    "description": "Consulta de existencias y precios por referencia.",
    "server_url": "https://mcp.eltornillo.com.co/mcp",
    "approval_mode": "fine_grained",
    "transport": "STREAMABLE_HTTP",
    "provider": null,
    "created_at": "2026-09-11T09:30:00.000Z",
    "updated_at": "2026-09-11T09:30:00.000Z",
    "deleted_at": null,
    "toolOverrides": {
      "consultar_existencias": "auto_approved"
    }
  },
  "toolOverridesSync": {
    "synced": 1,
    "removed": 0,
    "failed": 1,
    "failures": [
      {
        "tool": "crear_pedidos",
        "stage": "push",
        "reason": "the MCP server does not advertise a tool with this name"
      }
    ]
  }
}
```

**SDK Code**

```python MCP Servers_postMcpServers_example
import requests

url = "https://api.jelliu.co/api/mcp-servers"

headers = {"Authorization": "Bearer <token>"}

response = requests.post(url, headers=headers)

print(response.json())
```

```javascript MCP Servers_postMcpServers_example
const url = 'https://api.jelliu.co/api/mcp-servers';
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go MCP Servers_postMcpServers_example
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://api.jelliu.co/api/mcp-servers"

	req, _ := http.NewRequest("POST", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby MCP Servers_postMcpServers_example
require 'uri'
require 'net/http'

url = URI("https://api.jelliu.co/api/mcp-servers")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java MCP Servers_postMcpServers_example
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.jelliu.co/api/mcp-servers")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php MCP Servers_postMcpServers_example
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.jelliu.co/api/mcp-servers', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp MCP Servers_postMcpServers_example
using RestSharp;

var client = new RestClient("https://api.jelliu.co/api/mcp-servers");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift MCP Servers_postMcpServers_example
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.jelliu.co/api/mcp-servers")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Hosted provider (Zapier)

**Request**

```json
{
  "provider": "zapier",
  "secretToken": "zpk_live_2f9c1e7a8b"
}
```

**Response**

```json
{
  "data": {
    "id": "3c2b1a09-8f7e-4d6c-b5a4-938271605f4e",
    "tenant_id": "0e9d7c3b-8a1f-4c55-b7a2-3c4d5e6f7a8b",
    "agent_id": null,
    "name": "Zapier",
    "description": "Actions in the apps this business has connected through Zapier (CRM, calendar, email, spreadsheets, messaging, and thousands more). To act: call inspect_zapier_actions to see what is already enabled.",
    "server_url": "https://mcp.zapier.com/api/v1/connect",
    "approval_mode": "no_approval",
    "transport": "STREAMABLE_HTTP",
    "provider": "zapier",
    "created_at": "2026-09-14T15:02:11.000Z",
    "updated_at": "2026-09-14T15:02:11.000Z",
    "deleted_at": null,
    "toolOverrides": {}
  }
}
```

**SDK Code**

```python Hosted provider (Zapier)
import requests

url = "https://api.jelliu.co/api/mcp-servers"

payload = {
    "provider": "zapier",
    "secretToken": "zpk_live_2f9c1e7a8b"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Hosted provider (Zapier)
const url = 'https://api.jelliu.co/api/mcp-servers';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"provider":"zapier","secretToken":"zpk_live_2f9c1e7a8b"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Hosted provider (Zapier)
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.jelliu.co/api/mcp-servers"

	payload := strings.NewReader("{\n  \"provider\": \"zapier\",\n  \"secretToken\": \"zpk_live_2f9c1e7a8b\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Hosted provider (Zapier)
require 'uri'
require 'net/http'

url = URI("https://api.jelliu.co/api/mcp-servers")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"provider\": \"zapier\",\n  \"secretToken\": \"zpk_live_2f9c1e7a8b\"\n}"

response = http.request(request)
puts response.read_body
```

```java Hosted provider (Zapier)
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.jelliu.co/api/mcp-servers")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"provider\": \"zapier\",\n  \"secretToken\": \"zpk_live_2f9c1e7a8b\"\n}")
  .asString();
```

```php Hosted provider (Zapier)
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.jelliu.co/api/mcp-servers', [
  'body' => '{
  "provider": "zapier",
  "secretToken": "zpk_live_2f9c1e7a8b"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Hosted provider (Zapier)
using RestSharp;

var client = new RestClient("https://api.jelliu.co/api/mcp-servers");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"provider\": \"zapier\",\n  \"secretToken\": \"zpk_live_2f9c1e7a8b\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Hosted provider (Zapier)
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "provider": "zapier",
  "secretToken": "zpk_live_2f9c1e7a8b"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.jelliu.co/api/mcp-servers")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Hosted provider (Alegra, HTTP Basic)

**Request**

```json
{
  "provider": "alegra",
  "secretToken": "contabilidad@eltornillo.com.co:a1b2c3d4e5f6"
}
```

**Response**

```json
{
  "data": {
    "id": "3c2b1a09-8f7e-4d6c-b5a4-938271605f4e",
    "tenant_id": "0e9d7c3b-8a1f-4c55-b7a2-3c4d5e6f7a8b",
    "agent_id": null,
    "name": "Zapier",
    "description": "Actions in the apps this business has connected through Zapier (CRM, calendar, email, spreadsheets, messaging, and thousands more). To act: call inspect_zapier_actions to see what is already enabled.",
    "server_url": "https://mcp.zapier.com/api/v1/connect",
    "approval_mode": "no_approval",
    "transport": "STREAMABLE_HTTP",
    "provider": "zapier",
    "created_at": "2026-09-14T15:02:11.000Z",
    "updated_at": "2026-09-14T15:02:11.000Z",
    "deleted_at": null,
    "toolOverrides": {}
  }
}
```

**SDK Code**

```python Hosted provider (Alegra, HTTP Basic)
import requests

url = "https://api.jelliu.co/api/mcp-servers"

payload = {
    "provider": "alegra",
    "secretToken": "contabilidad@eltornillo.com.co:a1b2c3d4e5f6"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Hosted provider (Alegra, HTTP Basic)
const url = 'https://api.jelliu.co/api/mcp-servers';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"provider":"alegra","secretToken":"contabilidad@eltornillo.com.co:a1b2c3d4e5f6"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Hosted provider (Alegra, HTTP Basic)
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.jelliu.co/api/mcp-servers"

	payload := strings.NewReader("{\n  \"provider\": \"alegra\",\n  \"secretToken\": \"contabilidad@eltornillo.com.co:a1b2c3d4e5f6\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Hosted provider (Alegra, HTTP Basic)
require 'uri'
require 'net/http'

url = URI("https://api.jelliu.co/api/mcp-servers")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"provider\": \"alegra\",\n  \"secretToken\": \"contabilidad@eltornillo.com.co:a1b2c3d4e5f6\"\n}"

response = http.request(request)
puts response.read_body
```

```java Hosted provider (Alegra, HTTP Basic)
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.jelliu.co/api/mcp-servers")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"provider\": \"alegra\",\n  \"secretToken\": \"contabilidad@eltornillo.com.co:a1b2c3d4e5f6\"\n}")
  .asString();
```

```php Hosted provider (Alegra, HTTP Basic)
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.jelliu.co/api/mcp-servers', [
  'body' => '{
  "provider": "alegra",
  "secretToken": "contabilidad@eltornillo.com.co:a1b2c3d4e5f6"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Hosted provider (Alegra, HTTP Basic)
using RestSharp;

var client = new RestClient("https://api.jelliu.co/api/mcp-servers");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"provider\": \"alegra\",\n  \"secretToken\": \"contabilidad@eltornillo.com.co:a1b2c3d4e5f6\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Hosted provider (Alegra, HTTP Basic)
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "provider": "alegra",
  "secretToken": "contabilidad@eltornillo.com.co:a1b2c3d4e5f6"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.jelliu.co/api/mcp-servers")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Hosted provider (Make, regional URL)

**Request**

```json
{
  "provider": "make",
  "serverUrl": "https://us2.make.com/mcp/stateless",
  "secretToken": "mk_8d3f0a2b-6c1e-4f95-9b7a-2e4d6c8a0f13"
}
```

**Response**

```json
{
  "data": {
    "id": "3c2b1a09-8f7e-4d6c-b5a4-938271605f4e",
    "tenant_id": "0e9d7c3b-8a1f-4c55-b7a2-3c4d5e6f7a8b",
    "agent_id": null,
    "name": "Zapier",
    "description": "Actions in the apps this business has connected through Zapier (CRM, calendar, email, spreadsheets, messaging, and thousands more). To act: call inspect_zapier_actions to see what is already enabled.",
    "server_url": "https://mcp.zapier.com/api/v1/connect",
    "approval_mode": "no_approval",
    "transport": "STREAMABLE_HTTP",
    "provider": "zapier",
    "created_at": "2026-09-14T15:02:11.000Z",
    "updated_at": "2026-09-14T15:02:11.000Z",
    "deleted_at": null,
    "toolOverrides": {}
  }
}
```

**SDK Code**

```python Hosted provider (Make, regional URL)
import requests

url = "https://api.jelliu.co/api/mcp-servers"

payload = {
    "provider": "make",
    "serverUrl": "https://us2.make.com/mcp/stateless",
    "secretToken": "mk_8d3f0a2b-6c1e-4f95-9b7a-2e4d6c8a0f13"
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Hosted provider (Make, regional URL)
const url = 'https://api.jelliu.co/api/mcp-servers';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"provider":"make","serverUrl":"https://us2.make.com/mcp/stateless","secretToken":"mk_8d3f0a2b-6c1e-4f95-9b7a-2e4d6c8a0f13"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Hosted provider (Make, regional URL)
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.jelliu.co/api/mcp-servers"

	payload := strings.NewReader("{\n  \"provider\": \"make\",\n  \"serverUrl\": \"https://us2.make.com/mcp/stateless\",\n  \"secretToken\": \"mk_8d3f0a2b-6c1e-4f95-9b7a-2e4d6c8a0f13\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Hosted provider (Make, regional URL)
require 'uri'
require 'net/http'

url = URI("https://api.jelliu.co/api/mcp-servers")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"provider\": \"make\",\n  \"serverUrl\": \"https://us2.make.com/mcp/stateless\",\n  \"secretToken\": \"mk_8d3f0a2b-6c1e-4f95-9b7a-2e4d6c8a0f13\"\n}"

response = http.request(request)
puts response.read_body
```

```java Hosted provider (Make, regional URL)
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.jelliu.co/api/mcp-servers")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"provider\": \"make\",\n  \"serverUrl\": \"https://us2.make.com/mcp/stateless\",\n  \"secretToken\": \"mk_8d3f0a2b-6c1e-4f95-9b7a-2e4d6c8a0f13\"\n}")
  .asString();
```

```php Hosted provider (Make, regional URL)
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.jelliu.co/api/mcp-servers', [
  'body' => '{
  "provider": "make",
  "serverUrl": "https://us2.make.com/mcp/stateless",
  "secretToken": "mk_8d3f0a2b-6c1e-4f95-9b7a-2e4d6c8a0f13"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Hosted provider (Make, regional URL)
using RestSharp;

var client = new RestClient("https://api.jelliu.co/api/mcp-servers");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"provider\": \"make\",\n  \"serverUrl\": \"https://us2.make.com/mcp/stateless\",\n  \"secretToken\": \"mk_8d3f0a2b-6c1e-4f95-9b7a-2e4d6c8a0f13\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Hosted provider (Make, regional URL)
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "provider": "make",
  "serverUrl": "https://us2.make.com/mcp/stateless",
  "secretToken": "mk_8d3f0a2b-6c1e-4f95-9b7a-2e4d6c8a0f13"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.jelliu.co/api/mcp-servers")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Custom server with per-tool approvals

**Request**

```json
{
  "name": "Inventario Ferretería El Tornillo",
  "description": "Consulta de existencias y precios por referencia.",
  "serverUrl": "https://mcp.eltornillo.com.co/mcp",
  "secretToken": "sk_eltornillo_9f2c4e",
  "approvalMode": "fine_grained",
  "transport": "STREAMABLE_HTTP",
  "toolOverrides": {
    "consultar_existencias": "auto_approved",
    "crear_pedido": "requires_approval"
  }
}
```

**Response**

```json
{
  "data": {
    "id": "3c2b1a09-8f7e-4d6c-b5a4-938271605f4e",
    "tenant_id": "0e9d7c3b-8a1f-4c55-b7a2-3c4d5e6f7a8b",
    "agent_id": null,
    "name": "Zapier",
    "description": "Actions in the apps this business has connected through Zapier (CRM, calendar, email, spreadsheets, messaging, and thousands more). To act: call inspect_zapier_actions to see what is already enabled.",
    "server_url": "https://mcp.zapier.com/api/v1/connect",
    "approval_mode": "no_approval",
    "transport": "STREAMABLE_HTTP",
    "provider": "zapier",
    "created_at": "2026-09-14T15:02:11.000Z",
    "updated_at": "2026-09-14T15:02:11.000Z",
    "deleted_at": null,
    "toolOverrides": {}
  }
}
```

**SDK Code**

```python Custom server with per-tool approvals
import requests

url = "https://api.jelliu.co/api/mcp-servers"

payload = {
    "name": "Inventario Ferretería El Tornillo",
    "description": "Consulta de existencias y precios por referencia.",
    "serverUrl": "https://mcp.eltornillo.com.co/mcp",
    "secretToken": "sk_eltornillo_9f2c4e",
    "approvalMode": "fine_grained",
    "transport": "STREAMABLE_HTTP",
    "toolOverrides": {
        "consultar_existencias": "auto_approved",
        "crear_pedido": "requires_approval"
    }
}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript Custom server with per-tool approvals
const url = 'https://api.jelliu.co/api/mcp-servers';
const options = {
  method: 'POST',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"name":"Inventario Ferretería El Tornillo","description":"Consulta de existencias y precios por referencia.","serverUrl":"https://mcp.eltornillo.com.co/mcp","secretToken":"sk_eltornillo_9f2c4e","approvalMode":"fine_grained","transport":"STREAMABLE_HTTP","toolOverrides":{"consultar_existencias":"auto_approved","crear_pedido":"requires_approval"}}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Custom server with per-tool approvals
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.jelliu.co/api/mcp-servers"

	payload := strings.NewReader("{\n  \"name\": \"Inventario Ferretería El Tornillo\",\n  \"description\": \"Consulta de existencias y precios por referencia.\",\n  \"serverUrl\": \"https://mcp.eltornillo.com.co/mcp\",\n  \"secretToken\": \"sk_eltornillo_9f2c4e\",\n  \"approvalMode\": \"fine_grained\",\n  \"transport\": \"STREAMABLE_HTTP\",\n  \"toolOverrides\": {\n    \"consultar_existencias\": \"auto_approved\",\n    \"crear_pedido\": \"requires_approval\"\n  }\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Custom server with per-tool approvals
require 'uri'
require 'net/http'

url = URI("https://api.jelliu.co/api/mcp-servers")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"name\": \"Inventario Ferretería El Tornillo\",\n  \"description\": \"Consulta de existencias y precios por referencia.\",\n  \"serverUrl\": \"https://mcp.eltornillo.com.co/mcp\",\n  \"secretToken\": \"sk_eltornillo_9f2c4e\",\n  \"approvalMode\": \"fine_grained\",\n  \"transport\": \"STREAMABLE_HTTP\",\n  \"toolOverrides\": {\n    \"consultar_existencias\": \"auto_approved\",\n    \"crear_pedido\": \"requires_approval\"\n  }\n}"

response = http.request(request)
puts response.read_body
```

```java Custom server with per-tool approvals
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.jelliu.co/api/mcp-servers")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"name\": \"Inventario Ferretería El Tornillo\",\n  \"description\": \"Consulta de existencias y precios por referencia.\",\n  \"serverUrl\": \"https://mcp.eltornillo.com.co/mcp\",\n  \"secretToken\": \"sk_eltornillo_9f2c4e\",\n  \"approvalMode\": \"fine_grained\",\n  \"transport\": \"STREAMABLE_HTTP\",\n  \"toolOverrides\": {\n    \"consultar_existencias\": \"auto_approved\",\n    \"crear_pedido\": \"requires_approval\"\n  }\n}")
  .asString();
```

```php Custom server with per-tool approvals
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.jelliu.co/api/mcp-servers', [
  'body' => '{
  "name": "Inventario Ferretería El Tornillo",
  "description": "Consulta de existencias y precios por referencia.",
  "serverUrl": "https://mcp.eltornillo.com.co/mcp",
  "secretToken": "sk_eltornillo_9f2c4e",
  "approvalMode": "fine_grained",
  "transport": "STREAMABLE_HTTP",
  "toolOverrides": {
    "consultar_existencias": "auto_approved",
    "crear_pedido": "requires_approval"
  }
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Custom server with per-tool approvals
using RestSharp;

var client = new RestClient("https://api.jelliu.co/api/mcp-servers");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"name\": \"Inventario Ferretería El Tornillo\",\n  \"description\": \"Consulta de existencias y precios por referencia.\",\n  \"serverUrl\": \"https://mcp.eltornillo.com.co/mcp\",\n  \"secretToken\": \"sk_eltornillo_9f2c4e\",\n  \"approvalMode\": \"fine_grained\",\n  \"transport\": \"STREAMABLE_HTTP\",\n  \"toolOverrides\": {\n    \"consultar_existencias\": \"auto_approved\",\n    \"crear_pedido\": \"requires_approval\"\n  }\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Custom server with per-tool approvals
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [
  "name": "Inventario Ferretería El Tornillo",
  "description": "Consulta de existencias y precios por referencia.",
  "serverUrl": "https://mcp.eltornillo.com.co/mcp",
  "secretToken": "sk_eltornillo_9f2c4e",
  "approvalMode": "fine_grained",
  "transport": "STREAMABLE_HTTP",
  "toolOverrides": [
    "consultar_existencias": "auto_approved",
    "crear_pedido": "requires_approval"
  ]
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.jelliu.co/api/mcp-servers")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```