> ## 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.

# Publish to ChatGPT as a plugin

> Give your project a ChatGPT sidebar entry, its own icon, and a permanent address, all set up in Metabind Studio with no server to deploy

A ChatGPT plugin is your Metabind project set up for ChatGPT users at large. It opens from the ChatGPT sidebar or as a tab in a conversation and renders your Interactive Tools inline or fullscreen. You configure all of it in Metabind Studio. There's no server to deploy and no DNS to set up.

The **ChatGPT Plugin** card on the **Server** tab walks through the setup and tracks which steps are done. This guide covers the setup, testing the plugin in your own ChatGPT, and submitting it to OpenAI's plugin directory.

To try your tools in your own ChatGPT account first, you don't need any of this. See [Connect to ChatGPT](/guides/connecting-to-mcp-hosts/chatgpt).

## Prerequisites

* A Metabind project with at least one Interactive Tool that has no required inputs. ChatGPT opens entrypoints without arguments, so this is the tool users will see first. See [Interactive Tools](/guides/building/interactive-tools).
* Permission to change the project's MCP server settings. Organization admins have it, and so does any role that can update MCP settings. Members without it can open the card in read-only mode with **View**.
* A ChatGPT account you can add custom MCP servers to, for testing. See [Connect to ChatGPT](/guides/connecting-to-mcp-hosts/chatgpt).
* To submit to the directory, a verified developer organization on the [OpenAI Platform](https://platform.openai.com).

## How ChatGPT opens your app

A plugin can appear in ChatGPT in three ways. You choose which in Metabind Studio:

| How it opens | Where users find it | Where you set it |
| - | - | - |
| **Global entrypoint** | The ChatGPT sidebar | **ChatGPT Plugin** card → **Global entrypoint** |
| **Thread entrypoint** | A tab in a conversation's side panel, with its own instance per conversation | The tool's **ChatGPT Host** section → **Thread Entrypoint** |
| **Model call** | Inline in the conversation, or fullscreen beside it | The tool's **ChatGPT Host** section → **Display Mode** |

Entrypoints open with empty arguments, without the model calling the tool. That's why an entrypoint tool can't have required inputs.

> [!NOTE]
>
> Design entrypoint components to render well with no inputs at all. Property default values aren't applied when ChatGPT opens an entrypoint, so give any text or images the component needs a fallback in the component code itself.

## Open the ChatGPT Plugin card

1. Open the project in Metabind Studio.
2. On the **Server** tab, find the **ChatGPT Plugin** card below the server URL.
3. Click **Configure**.

The card's status shows how far along you are: **Not set up**, a step count such as **2 of 5 steps**, or **Needs attention** when a check fails. The last step, **Domain verification**, is needed only to submit to OpenAI's plugin directory; see [Verify your domain and submit](#verify-your-domain-and-submit). Once all five steps are done, the card runs its readiness checks and shows **Ready** or **Needs attention**.

![The ChatGPT Plugin dialog in Metabind Studio, with Global entrypoint and Sidebar icon under Plugin, and Plugin address, Public access, and Domain verification under Submission](https://mintcdn.com/yapstudios/bhk1k0cvxLF1J1JO/images/connecting/chatgpt-plugin-configure.png?fit=max\&auto=format\&n=bhk1k0cvxLF1J1JO\&q=85\&s=6e01ee18bbda8a1881e233efd6cb0bb0)

The dialog groups the steps under **Plugin** (how the app looks in ChatGPT) and **Submission** (how ChatGPT reaches your server). The sections below follow the same order.

## Choose a global entrypoint

The global entrypoint is the Interactive Tool users open from the ChatGPT sidebar, such as a home screen, a catalog, or a dashboard.

1. Next to **Global entrypoint**, click **Choose**.
2. Pick a tool under **Available**. Tools under **Has Required Inputs** can't be entrypoints until you make those inputs optional.

A project has one global entrypoint. To switch, click **Change** and pick another tool. ChatGPT shows the entrypoint by the tool's title, so give the tool a clear title in its settings.

## Add thread entrypoints and display modes

These settings are per tool, and both are optional. Open an Interactive Tool (listed under **UI Tools** in the Studio sidebar), click **Edit**, and scroll to **ChatGPT Host**:

* **Thread Entrypoint** lets users open the tool as a tab in a conversation without the model calling it. Each conversation gets its own instance. Turn it on for as many tools as you like, as long as none of them has required inputs.
* **Display Mode** sets where the view appears when the model calls the tool. Turn it on, then enable **Inline** (in the conversation, scrolling with it), **Fullscreen** (a persistent tab beside the conversation), or both, then set **Preferred** to the one ChatGPT should use first.

![The ChatGPT Host section of an Interactive Tool's settings in Metabind Studio, with Thread Entrypoint and Display Mode switched on, and the Inline, Fullscreen, and Preferred display mode options below](https://mintcdn.com/yapstudios/bhk1k0cvxLF1J1JO/images/connecting/chatgpt-host-section.png?fit=max\&auto=format\&n=bhk1k0cvxLF1J1JO\&q=85\&s=3f041282ea6bffff3f71e5828c17f845)

The tool's page also shows a read-only **Host Integrations** summary of these settings. It reflects your saved changes, which reach ChatGPT only after you [publish](#publish-the-server).

## Add a sidebar icon

ChatGPT draws an entrypoint with the sidebar icon when the entrypoint's tool has no icon of its own. In the **ChatGPT Plugin** dialog, click **Choose** next to **Sidebar icon** and pick an image from your project's assets.

The icon must be:

* An SVG. Raster images show a **Not an SVG** badge and may render blurry or in the wrong color.
* Monochrome, drawn with `currentColor` so it can follow the user's theme. ChatGPT's desktop app recolors it for light and dark mode. The iOS app in dark mode currently draws it near-black, so it's hard to see there.
* On a transparent background, with a 20×20 viewport and 1.33px strokes.

Click **Preview** to check the icon against each requirement. The icon goes live as soon as you choose it, without a publish. You can also manage it in **Project Settings**, under **General → MCP Icons**, where it's listed as the **ChatGPT** sidebar icon.

> [!TIP]
>
> This is a different icon from the optional PNG on ChatGPT's own **Add custom MCP server** form. The Metabind sidebar icon is the one that ships with your server.

## Declare Data Tool annotations

ChatGPT needs every tool to say what it does to the world, and the card's readiness check requires it. For each Data Tool, open its settings and set each of these deliberately:

* **Read Only**: the tool doesn't change anything.
* **Destructive**: the tool may delete or overwrite data.
* **Open-World**: the tool reaches external or third-party services.

If you leave a hint unset, Metabind describes the tool as read-only, non-destructive, and closed-world, which misdescribes a tool that writes data or calls other services. ChatGPT shows these hints to users and groups a server's tools by permission, such as **Read**, so set each one to match what the tool does.

The card's readiness check names any Data Tool that's missing one.

A switch that you never touch isn't saved, even though it shows as off. Turning **Read Only** on also hides the **Destructive** switch, so a read-only tool can still fail the check. To save every hint on a read-only tool:

1. Turn **Open-World** on, then off, or leave it on if the tool calls external services.
2. Turn **Read Only** off, so the **Destructive** switch appears.
3. Turn **Destructive** on, then off.
4. Turn **Read Only** back on, then click **Done**.

## Make the project public

ChatGPT users can't sign in to a private project, so a plugin's server must be public.

1. Click the gear icon at the top right (**Project Settings**), and choose **General**.
2. Under **Access**, click **Change** and choose **Public**.
3. Confirm with **I understand the impact**.

> [!WARNING]
>
> A public project's production endpoint is open to anyone with the URL. Tool calls don't require a sign-in, and they count toward your organization's usage. Draft stays private either way.

## Assign a plugin address

A plugin gets its own permanent address, separate from the shared `mcp.metabind.ai` URL, so ChatGPT always reaches it at the same origin.

In the **ChatGPT Plugin** dialog, click **Assign** next to **Plugin address**. The address is built from your project and organization slugs:

```
https://<project-slug>-<organization-slug>.mcp.metabind.ai/
```

For example, project `banking` in organization `acme` gets `https://banking-acme.mcp.metabind.ai/`. Click the copy button to copy it.

> [!WARNING]
>
> A plugin address is permanent. Renaming the project keeps it, it can't be changed or reassigned, and it stays reserved even if you delete the project. Make sure the project's slug is the one you want before you click **Assign**.

The project slug is the **Identifier** you set when you created the project. The combined `<project-slug>-<organization-slug>` must be 63 characters or fewer, and it can't match an address that another project has reserved. If either rule fails, Metabind doesn't assign an address.

The production URL keeps working after you assign the address. Both serve the same tools, but only the plugin address gives your views their own origin: its UI resources declare it as their widget domain, which OpenAI requires to submit a plugin with UI. Views opened through the production URL use ChatGPT's default sandbox origin.

## Publish the server

The global entrypoint, thread entrypoints, and display modes are saved as part of each tool, so ChatGPT sees them only after you publish. If your components changed, click **Publish Components** at the bottom of the **Components** sidebar. Then click **Publish Server** at the bottom of the **MCP** sidebar. See [Publish the MCP server](/guides/publishing/publishing-the-server).

## Test the plugin in ChatGPT

Add the plugin to your own ChatGPT account the way you would any project: follow [Connect to ChatGPT](/guides/connecting-to-mcp-hosts/chatgpt), paste the **plugin address** as the **Server URL**, and choose **No authentication**. If you haven't assigned a plugin address yet, you can test with the project's production URL instead.

Then check each way the app opens:

* **Global entrypoint.** In the sidebar, open **Explore** on chatgpt.com and in the iOS and Android apps, or **More** in the desktop app. Your entrypoint is listed by its title, with your sidebar icon. Choosing it opens the view full-page.
* **Thread entrypoint.** In a conversation on chatgpt.com, open the conversation's **⋯** menu and choose **Plugins**. In the desktop app, open a new tab in the side panel, then choose **Tools → More tools…**; your thread entrypoints are listed under **Plugins and MCPs**. Choosing one opens the view in the side panel.
* **Model call.** Ask ChatGPT to use the app. The view opens in its preferred display mode.

![ChatGPT on the web with the sidebar's Explore menu open, listing the Metabind global entrypoint Interior Designer with the project's monochrome sidebar icon, below Finances and Maps](https://mintcdn.com/yapstudios/bhk1k0cvxLF1J1JO/images/connecting/chatgpt-sidebar-entrypoint.png?fit=max\&auto=format\&n=bhk1k0cvxLF1J1JO\&q=85\&s=085fefb367ff44384d2bc3703b35c7c5)

## Verify your domain and submit

To list your plugin in ChatGPT's directory, submit it on the OpenAI Platform. OpenAI checks that you control the plugin address by fetching a token from it, and Metabind serves that token for you.

### Build the plugin package

OpenAI takes a plugin as a ZIP file. Metabind doesn't generate it, so create one with two files at its root:

* `plugin.json`: the plugin's name, version, and listing details, such as its display name, descriptions, developer name, and category.
* `mcp.json`: your server, using the plugin address with no authentication.

```json mcp.json theme={null}
{
  "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
  "mcpServers": {
    "<project-slug>": {
      "type": "streamable-http",
      "url": "https://<project-slug>-<organization-slug>.mcp.metabind.ai/",
      "extensions": { "com.openai": { "auth": { "type": "none" } } }
    }
  }
}
```

For every `plugin.json` field, see OpenAI's [submission guide](https://developers.openai.com/plugins/deploy/submission). Before review, OpenAI also requires website, support, privacy policy, and terms of service URLs and an app icon. If any are missing, the uploaded plugin lists them under **Findings**.

### Verify the domain

1. On the OpenAI Platform, open **Plugins** and upload the ZIP.
2. In the uploaded plugin, open the **MCPs** tab and click **Connect**. OpenAI shows a verification token.
3. In Metabind Studio, in the **ChatGPT Plugin** dialog, click **Add** next to **Domain verification**.
4. Paste the token into **Verification Token** and click **Save**.
5. Return to OpenAI and finish connecting. The server shows **Domain verified** and lists your published tools.

Metabind serves the token at `<plugin address>/.well-known/openai-apps-challenge`, shown under **Served At**. To rotate the token, click **Edit**; to stop serving it, click **Remove**.

### Submit for review

When every step is done and the checks pass, the **ChatGPT Plugin** dialog shows **All set. Ready to submit as a ChatGPT plugin.** After you connect the MCP server on OpenAI's side, OpenAI scans your tools and lists anything to fix under **Findings**, such as a tool with no description. Finish the rest of the submission on OpenAI's side, including listing details, test cases, and review, by following OpenAI's [submission guide](https://developers.openai.com/plugins/deploy/submission) and [plugin guidelines](https://developers.openai.com/plugins/plugin-guidelines).

> [!NOTE]
>
> **Ready** means your Metabind server meets the checks below. It doesn't guarantee OpenAI's approval, which follows OpenAI's own requirements and timeline.

## Troubleshooting

When the card shows **Needs attention**, the dialog lists what's missing. Each message maps to a fix:

| Message | Fix |
| - | - |
| Enable public MCP access; customer-user OAuth is not available for submission | [Make the project public](#make-the-project-public) |
| Allocate a permanent project hostname | [Assign a plugin address](#assign-a-plugin-address) |
| Save the verification token from your OpenAI developer organization | [Add the verification token](#verify-the-domain) |
| Challenge response does not match the stored token exactly | Copy the token from OpenAI again, paste it into **Verification Token** with nothing added, and save |
| Configure and publish a global or thread entrypoint | Choose an entrypoint, then [publish](#publish-the-server) |
| Remove required inputs from entrypoint tools | Make every input on your entrypoint tools optional, then publish |
| Add HTTPS icons to every entrypoint or configure project sidebar icons | [Add a sidebar icon](#add-a-sidebar-icon) |
| Declare readOnlyHint, destructiveHint and openWorldHint for every Data Tool | [Declare Data Tool annotations](#declare-data-tool-annotations), then publish |
| Publish a UI tool; the project hostname lists none | Publish at least one Interactive Tool, then [publish the server](#publish-the-server) |
| The project hostname did not return its resources in time; retry the check | Close and reopen the dialog to run the check again |

Other problems:

| Symptom | Likely cause |
| - | - |
| A tool is grayed out under **Has Required Inputs** | It has at least one required input. Make the inputs optional |
| **Thread Entrypoint** doesn't turn on | Same cause: the tool requires inputs. Make them optional, or use a tool listed under **Available** |
| Entrypoint or display mode changes don't show up in ChatGPT | You haven't published since changing them |
| Text or images missing when the app opens from the sidebar | The component relies on property defaults, which aren't applied for entrypoints. Add fallbacks in the component |
| The desktop app shows an old version of a view after you publish | Open **Settings → Plugins → MCPs**, choose **Clear all app data**, and relaunch ChatGPT |
| **Assign** returns a validation error | The address is already taken, or the combined slugs are longer than 63 characters |
| OpenAI's **Findings** say a tool's description is missing, blank, or unclear | The tool has no description of its own. Add one in the tool's settings, then [publish](#publish-the-server) |

## Related

> **[Connect to ChatGPT](/guides/connecting-to-mcp-hosts/chatgpt)**
>
> Add a project to your own ChatGPT as a custom MCP server.

> **[Interactive Tools](/guides/building/interactive-tools)**
>
> Build the views your entrypoints open.

> **[Publish the MCP server](/guides/publishing/publishing-the-server)**
>
> What publishing does and when changes go live.

> **[Project visibility](/guides/operations/project-visibility)**
>
> Public and private access, and what each allows.

> **[OpenAI plugin submission](https://developers.openai.com/plugins/deploy/submission)**
>
> OpenAI's guide to uploading, reviewing, and publishing a plugin.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.