> ## Documentation Index
> Fetch the complete documentation index at: https://docs.metabind.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom MCP hosts

> Connect any MCP-compatible client to a Metabind server

Metabind serves a standard Model Context Protocol endpoint. Any client that speaks MCP — your own application, an internal tool, a third-party host not yet covered by a dedicated guide — can connect with the URL and a token.

## What "MCP-compatible" means

A custom MCP host needs to:

1. Speak MCP's JSON-RPC over HTTP transport.
2. Authenticate via Bearer token in the `Authorization` header.
3. List tools (`tools/list`) and call them (`tools/call`).
4. (Optional) Render `mcp-ui` resources if you want Interactive Tool output to render natively.

Most MCP SDKs handle 1–3 out of the box. Step 4 — rendering Interactive Tool UI — depends on what the host is for. CLIs may print JSON; UI hosts can render the BindJS output via `@bindjs/renderer` or its native equivalents.

## Endpoint shape

```
https://mcp.metabind.ai/<organizationId>/<projectId>          # production
https://mcp.metabind.ai/<organizationId>/<projectId>/draft    # draft
```

Both endpoints follow the same MCP transport. Send `Authorization: Bearer <token>` on every request.

## Minimal client example

A barebones MCP client that lists tools and calls one:

```ts theme={null}
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";

const transport = new StreamableHTTPClientTransport(
  new URL("https://mcp.metabind.ai/my-org/oak-and-ivory"),
  {
    requestInit: {
      headers: { Authorization: `Bearer ${process.env.MB_TOKEN}` }
    }
  }
);

const client = new Client({ name: "my-client", version: "1.0.0" }, {});
await client.connect(transport);

const { tools } = await client.listTools();
console.log("Tools:", tools.map(t => t.name));

const result = await client.callTool({
  name: "product_search",
  arguments: { query: "running shoes", limit: 5 }
});
console.log("Result:", result);
```

This is the minimal flow. From here, your host decides how to surface tool results.

## Rendering Interactive Tool output

Interactive Tools return MCP UI resources alongside their structured output. To render natively:

| Platform         | Use                                                                        |
| ---------------- | -------------------------------------------------------------------------- |
| Web              | `@bindjs/renderer` — React renderer                                        |
| iOS              | `bindjs-apple` — SwiftUI renderer (ships with the Assistant SDK)           |
| Android          | `bindjs-android` — Jetpack Compose renderer (ships with the Assistant SDK) |
| Other / fallback | Render the structured JSON output and skip the UI resource                 |

The Assistant SDK packages all three native renderers with auth, transport, and host UI. Use it directly when you want to embed Metabind tools in your own iOS, Android, or web app — see [Assistant SDK overview](/guides/getting-started/embed-an-assistant).

## Authentication patterns

A few patterns for distributing tokens to a custom host:

* **Static token in config.** Simplest. The host stores the token; every call uses it. Right for internal tools and small deployments.
* **Per-user token issued via your own auth.** Your backend mints a Metabind token on behalf of a user and hands it to their host. Right for SaaS products where each user has their own access.

## Token scopes

Tokens are scoped to a single project, with permissions inherited from the user who minted them.

## Tool annotations the host should respect

Tool schemas include annotations the host can use to make better decisions:

| Annotation                            | Host behavior                                                                                  |
| ------------------------------------- | ---------------------------------------------------------------------------------------------- |
| `readOnlyHint: true`                  | Safe to call without confirmation; cache-friendly                                              |
| `openWorldHint: true`                 | Tool reaches third-party services; consider showing a "this calls external services" indicator |
| `taskSupport: required` or `optional` | Tool may return a task token instead of a final result; poll for completion                    |
| `destructiveHint: true`               | Tool changes state; consider requiring user confirmation                                       |

Reading these annotations is optional but improves UX.

## Long-running tools

Data Tools that exceed the 60-second sandbox limit declare task support. The tool returns a task token immediately; your host polls for completion via `tasks/get`. See [Sandboxed execution: task support](/guides/building/sandboxed-execution#task-support-long-running-operations).

For simple hosts that don't need long-running tools, set `taskSupport: forbidden` on every Type and skip task handling.

## Audit and observability

Every call from a custom host appears in the MCP App Studio audit log just like calls from Claude Desktop or ChatGPT. Use the audit log to debug schema mismatches, handler errors, and unexpected inputs.

The custom host can also log locally; the call\_id from MCP can be matched to MCP App Studio's audit log entry for end-to-end tracing.

## When to use the Assistant SDK instead

If your custom host is an iOS, Android, or web application that needs to embed Metabind tools as a chat-style or agent UI, the [Assistant SDK](/guides/getting-started/embed-an-assistant) saves you from re-implementing the host loop. It handles connection, conversation state, and rendering — you provide the LLM key and the host surface.

The Assistant SDK is for *your app* surfacing Metabind tools to your users. A custom MCP client is for *connecting an external host* to a Metabind project. They solve different problems.

## Related

<CardGroup cols={2}>
  <Card title="Assistant SDK overview" icon="rocket" href="/guides/getting-started/embed-an-assistant">
    Embed Metabind in your iOS, Android, or web app.
  </Card>

  <Card title="Sandboxed execution" icon="shield" href="/guides/building/sandboxed-execution">
    What runs in V8, including task support for long-running calls.
  </Card>

  <Card title="REST API" icon="code" href="/rest/introduction">
    The non-MCP HTTP API for project metadata and content.
  </Card>

  <Card title="Audit logs" icon="clipboard-list" href="/guides/operations/audit-logs">
    Observability across all connected hosts.
  </Card>
</CardGroup>
