# List catalog

URL: https://docs.hanzo.ai/docs/openapi/tool/get-tool-catalog

> Lists the MCP servers the public registries publish, as we hold them: our canonical copy of registry.modelcontextprotocol.io, plus what we decided about each entry.

`GET /v1/tool/catalog`

> [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/catalog` |
| **Method**    | `GET`                                  |
| **Operation** | `get_tool_catalog`                     |
| **Auth**      | `Authorization: Bearer $HANZO_API_KEY` |

Lists the MCP servers the public registries publish, as we hold
them: our canonical copy of registry.modelcontextprotocol.io, plus what we
decided about each entry.

This is the SHELF an org picks from. A listing with a streamable-http endpoint
can be enabled as-is — POST /v1/tool/mcp/servers with its id — and its tools then
join the org's tool plane and the fleet's MCP server. A listing that only ships a
stdio package needs a process to run it, which is why the transports are on
every entry rather than implied.

Hidden entries are absent: they are the ones we took off the shelf. A platform
SuperAdmin sees them, because the same query answers "what is on the shelf" and
"what is in the catalog" and two queries would drift apart.

It is PAGED — 50 by default, 200 at most. The public registry publishes tens of
thousands of servers, so an unbounded answer is a twenty-megabyte response and a
storefront that renders in a minute. total is the whole match, not the page.

It needs no credential: the shelf is a copy of public registries, the same for
every org, and a storefront shows it to a visitor before anyone signs in.

## Request

5 fields.

| Field      | In    | Type    | Required | Description                                                                                                                    |
| ---------- | ----- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `q`        | query | string  | —        | Q matches the name, title or description, case-insensitively.                                                                  |
| `featured` | query | string  | —        | Featured keeps only the listings we put on the front of the shelf, and only when it is exactly the string "true".              |
| `official` | query | string  | —        | Official keeps only the vendors' OWN servers — not third-party copies of them — and only when it is exactly the string "true". |
| `limit`    | query | integer | —        | Limit bounds the page: default 50, maximum 200.                                                                                |
| `offset`   | query | integer | —        | Offset skips that many listings.                                                                                               |

## Response

| Status    | Body            | Meaning |
| --------- | --------------- | ------- |
| `200`     | tool.mcpCatalog | ok      |
| `default` | problem-details | refused |

`200` body — 28 fields.

| Field                             | In   | Type               | Always | Description                                                                                                                         |
| --------------------------------- | ---- | ------------------ | ------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| `catalog`                         | body | tool.MCPListing\[] | —      | Catalog is this page of listings, featured first, then by name.                                                                     |
| `catalog[].description`           | body | string             | —      | Description is the publisher's one-line summary.                                                                                    |
| `catalog[].featured`              | body | boolean            | —      | Featured puts the listing on the front of the shelf.                                                                                |
| `catalog[].hidden`                | body | boolean            | —      | Hidden keeps the listing out of the org-visible catalog.                                                                            |
| `catalog[].id`                    | body | string             | —      | ID addresses the listing in a URL.                                                                                                  |
| `catalog[].logo`                  | body | string             | —      | Logo is the brand mark to render for the listing — the publisher's icon when the entry carries one, or the one an admin set.        |
| `catalog[].name`                  | body | string             | —      | Name is the publisher's reverse-DNS name, e.g. "com.stripe/mcp".                                                                    |
| `catalog[].official`              | body | boolean            | —      | Official is whether this is the vendor's OWN server rather than someone else's copy of it.                                          |
| `catalog[].packages`              | body | tool.MCPPackage\[] | —      | Packages are the runnable package forms — npm, pypi, oci — each with the runtime that launches it and the transport it then speaks. |
| `catalog[].packages[].identifier` | body | string             | —      | Identifier is the package name or download URL.                                                                                     |
| `catalog[].packages[].registry`   | body | string             | —      | Registry is where the package is fetched from: npm, pypi, oci, nuget, mcpb.                                                         |
| `catalog[].packages[].runtime`    | body | string             | —      | Runtime is the publisher's hint for what launches it: npx, uvx, docker.                                                             |
| `catalog[].packages[].transport`  | body | string             | —      | Transport is what the launched process speaks: usually "stdio".                                                                     |
| `catalog[].packages[].version`    | body | string             | —      | Version is the exact published package version.                                                                                     |
| `catalog[].registry`              | body | string             | —      | Registry is the upstream this row was synced from.                                                                                  |
| `catalog[].remotes`               | body | tool.MCPRemote\[]  | —      | Remotes are the hosted endpoints the publisher serves the server at.                                                                |
| `catalog[].remotes[].transport`   | body | string             | —      | Transport is "streamable-http" or "sse".                                                                                            |
| `catalog[].remotes[].url`         | body | string             | —      | URL is the endpoint.                                                                                                                |
| `catalog[].repo`                  | body | string             | —      | Repo is the source repository URL, when the entry names one.                                                                        |
| `catalog[].site`                  | body | string             | —      | Site is the project's homepage, when the entry names one.                                                                           |
| `catalog[].synced`                | body | integer (int64)    | —      | Synced is when this row was last confirmed against upstream, Unix seconds.                                                          |
| `catalog[].title`                 | body | string             | —      | Title is the human-readable display name, when the entry carries one.                                                               |
| `catalog[].transports`            | body | string\[]          | —      | Transports are the distinct transports this server can be reached over, sorted: some of "stdio", "streamable-http", "sse".          |
| `catalog[].vendor`                | body | string             | —      | Vendor is the namespace half of Name — the publisher, e.g. "com.stripe".                                                            |
| `catalog[].version`               | body | string             | —      | Version is the published version of this listing.                                                                                   |
| `limit`                           | body | integer (int64)    | —      | Limit is the page size that was actually applied — the default or the clamp, when the request asked for neither or for too much.    |
| `offset`                          | body | integer (int64)    | —      | Offset is where this page started, so a caller pages from what the server did rather than from what it asked for.                   |
| `total`                           | body | integer (int64)    | —      | Total is how many listings the filter matched, which is more than this page holds whenever there is a next one.                     |

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

## Examples

**CLI**

```bash
hanzo tool catalog list
```

**SDK**

**.ts**

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

const api = new ToolApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.getToolCatalog();
```

**.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).get_tool_catalog()
```

**.go**

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

resp, _, err := client.ToolAPI.GetToolCatalog(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::get_tool_catalog(&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).getToolCatalog();
```

**HTTP**

```bash
curl https://api.hanzo.ai/v1/tool/catalog \
  -H "Authorization: Bearer $HANZO_API_KEY"
```

**MCP**

Tool `tool`, op `get_tool_catalog` — POST the JSON-RPC envelope to `https://api.hanzo.ai/v1/mcp`.

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

---

[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)
