# Create servers

URL: https://docs.hanzo.ai/docs/openapi/tool/post-tool-mcp-servers

> Gives the caller's org one more external MCP server, so its tools join the org's tool plane and the fleet's MCP server.

`POST /v1/tool/mcp/servers`

> [Tool →](https://docs.hanzo.ai/docs/openapi/tool) · [All API references →](https://docs.hanzo.ai/docs/openapi) · [Get started →](https://docs.hanzo.ai/docs/guides)

|               |                                            |
| ------------- | ------------------------------------------ |
| **Address**   | `https://api.hanzo.ai/v1/tool/mcp/servers` |
| **Method**    | `POST`                                     |
| **Operation** | `post_tool_mcp_servers`                    |
| **Auth**      | `Authorization: Bearer $HANZO_API_KEY`     |

Gives the caller's org one more external MCP server, so its tools
join the org's tool plane and the fleet's MCP server. It is the ONE way an org
gains a server, whether it typed the URL in or enabled a catalog listing: both
write the SAME record, and `source` says which it was. A second registration
path would be a second place for a server to exist, and then a second place to
forget to check the credential.

The credential VALUE is sealed in KMS under a per-org ref; the row keeps only
the URL, the header name to inject it into, and a has-secret flag — so a secret
with no KMS configured is refused 503 rather than stored in the clear. The URL
is SSRF-validated here and re-checked by the dialer at connect time, which is
the DNS-rebinding defense.

Enabling a listing the org already enabled REVISES that server rather than
adding a near-duplicate beside it, so a retried enable is the same one server.
Answers 201 with the stored record.

A server and the tools of it the org activates are carried into every agent run
in the org, so registering one — or revising one, credential included — takes
an admin of the org or a SuperAdmin; a member is refused 403. The registration
is on the org's audit trail before it is made, and one the trail cannot record
is refused 503.

## Request

5 fields, body `application/json` (required).

| Field        | In   | Type   | Required | Description                                                                             |
| ------------ | ---- | ------ | -------- | --------------------------------------------------------------------------------------- |
| `authHeader` | body | string | —        | AuthHeader is the request header the credential is injected into, e.g. "Authorization". |
| `listing`    | body | string | —        | Listing enables a CATALOG entry instead — the id from GET /v1/tool/catalog.             |
| `name`       | body | string | —        | Name labels the server for the org.                                                     |
| `secret`     | body | string | —        | Secret is the credential VALUE.                                                         |
| `url`        | body | string | —        | URL is the server's JSON-RPC endpoint.                                                  |

## Response

| Status    | Body            | Meaning |
| --------- | --------------- | ------- |
| `201`     | tool.MCPServer  | created |
| `default` | problem-details | refused |

`201` body — 13 fields.

| Field        | In   | Type            | Always | Description                                                                                                                            |
| ------------ | ---- | --------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------- |
| `admitted`   | body | boolean         | —      | Admitted is whether an admin of the org, or a SuperAdmin, registered the server.                                                       |
| `authHeader` | body | string          | —      | AuthHeader is the request header the KMS-held credential is injected into, e.g. "Authorization".                                       |
| `createdAt`  | body | integer (int64) | —      | CreatedAt is when the server was registered, Unix seconds.                                                                             |
| `hasSecret`  | body | boolean         | —      | HasSecret is whether a credential is sealed in KMS for this server.                                                                    |
| `id`         | body | string          | —      | ID is the server's id within the org.                                                                                                  |
| `listing`    | body | string          | —      | Listing is the catalog entry this server was enabled from, when it was.                                                                |
| `name`       | body | string          | —      | Name is the org's label for the server.                                                                                                |
| `org`        | body | string          | —      | Org is the org that registered the server — the validated caller's.                                                                    |
| `reason`     | body | string          | —      | Reason says why a server that is not "ok" is not, in words any member may be shown: never the server's address.                        |
| `source`     | body | string          | —      | Source is where the registration came from: "catalog" when it was enabled off the shelf, "org" when the org registered the URL itself. |
| `status`     | body | string          | —      | Status is whether the server's tools could be listed when the org's servers were read: "ok", "unreachable", "refused" or "error".      |
| `tools`      | body | integer (int64) | —      | Tools is how many tools the server listed, when it listed them.                                                                        |
| `url`        | body | string          | —      | URL is the server's JSON-RPC endpoint.                                                                                                 |

Failure carries the platform error shape — see [Errors](https://docs.hanzo.ai/docs/errors).

## Examples

**CLI**

```bash
hanzo tool mcp servers create
```

**SDK**

**.ts**

```ts
import { Configuration, ToolApi } from 'hanzoai';

const api = new ToolApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postToolMcpServers({ authHeader: "<authHeader>", listing: "<listing>" });
```

**.py**

```python
from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import ToolApi

client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = ToolApi(client).post_tool_mcp_servers(auth_header="<authHeader>", listing="<listing>")
```

**.go**

```go
cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.ToolAPI.PostToolMcpServers(context.Background()).Execute()
if err != nil {
	return err
}
```

**.rs**

```rust
use hanzo_client::apis::{configuration::Configuration, tool_api};

let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();

let result = tool_api::post_tool_mcp_servers(&cfg, Default::default()).await?;
```

**.java**

```java
import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.ToolApi;

ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));

var result = new ToolApi(client).postToolMcpServers();
```

**HTTP**

```bash
curl -X POST https://api.hanzo.ai/v1/tool/mcp/servers \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "authHeader": "<authHeader>",
       "listing": "<listing>"
     }'
```

**MCP**

MCP reaches **tool** through the `tool` tool, which names its 17 operations with its own verbs — this one among them, under a name only MCP declares. `describe` explains any of them:

```bash
curl -X POST https://api.hanzo.ai/v1/mcp \
  -H "Content-Type: application/json" \
  -d '{
       "jsonrpc": "2.0",
       "id": 1,
       "method": "tools/call",
       "params": {
         "name": "describe",
         "arguments": {
           "op": "list_tools"
         }
       }
     }'
```

---

[Tool API](https://docs.hanzo.ai/docs/openapi/tool) · [All Hanzo APIs](https://docs.hanzo.ai/docs/openapi) · [Interactive reference](https://docs.hanzo.ai/docs/openapi/reference)
