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

# ChatGPT

> A connector in the chat UI, and the Responses API mcp tool.

<img src="https://mintcdn.com/mahadev/-gWik8vU43pna0pu/images/harnesses/chatgpt.svg?fit=max&auto=format&n=-gWik8vU43pna0pu&q=85&s=a8dda8c64066b70ef994980d378002e6" alt="ChatGPT" width="48" height="48" noZoom data-path="images/harnesses/chatgpt.svg" />

**Preview.** ChatGPT reaches the server two ways, and they authenticate
differently: the chat UI drives a full **OAuth 2.1** flow, while the Responses
API takes a **bearer key** you supply.

## In the ChatGPT app

Connectors are added under **Settings → Connectors → Create**, and on the
plans where custom connectors are available you paste the URL there:

```
https://api.impellabs.tech/mcp
```

<Steps>
  <Step title="Add the connector">
    Name it, paste the MCP server URL, and choose OAuth as the authentication
    method. The server advertises everything ChatGPT needs to discover the flow
    on its own — RFC 9728 protected-resource metadata at
    `/.well-known/oauth-protected-resource`, and RFC 8414 authorization-server
    metadata at `/.well-known/oauth-authorization-server`.
  </Step>

  <Step title="Sign in and consent">
    You are sent to the dashboard to sign in, then shown a consent screen naming
    ChatGPT and the exact scopes it is asking for. Read them — this is the point
    at which you decide what a model may do with your workspace.
  </Step>

  <Step title="Use it">
    The connector appears in the composer. Ask for something a tool answers.
  </Step>
</Steps>

<Note>
  ChatGPT's research and connector surfaces expect a server to expose two tools
  with **fixed schemas**: `search(query)` returning `{results: [{id, title,
      url}]}`, and `fetch(id)` returning `{id, title, text, url, metadata}`. The
  server provides both, mapped onto knowledge search and document fetch, and
  returns them as `structuredContent` **and** JSON-encoded text because clients
  differ on which they read. They are the same two tools every other client sees
  — nothing about them is ChatGPT-only except the shape.
</Note>

<Warning>
  A connector URL is pasted into somebody else's product and lives in your
  settings indefinitely. Every OAuth token the server issues is bound to this
  exact resource URI (RFC 8707), so a token minted for
  `https://api.impellabs.tech/mcp` is refused anywhere else — including by us,
  if the audience is not us. Use the URL exactly as written.
</Warning>

## From the Responses API

The `mcp` tool takes the server URL and a bearer credential directly. No OAuth,
no connector — this is the path for backend code.

<CodeGroup>
  ```python python theme={null}
  from openai import OpenAI

  client = OpenAI()

  resp = client.responses.create(
      model="gpt-5",
      input="List the agents in my ImpelLabs workspace.",
      tools=[{
          "type": "mcp",
          "server_label": "impellabs",
          "server_url": "https://api.impellabs.tech/mcp",
          "headers": {"Authorization": "Bearer tgcc_xxxxxxxxxxxx"},
          "require_approval": "never",
      }],
  )
  print(resp.output_text)
  ```

  ```typescript typescript theme={null}
  import OpenAI from "openai";

  const client = new OpenAI();

  const resp = await client.responses.create({
    model: "gpt-5",
    input: "List the agents in my ImpelLabs workspace.",
    tools: [{
      type: "mcp",
      server_label: "impellabs",
      server_url: "https://api.impellabs.tech/mcp",
      headers: { Authorization: "Bearer tgcc_xxxxxxxxxxxx" },
      require_approval: "never",
    }],
  });
  console.log(resp.output_text);
  ```

  ```bash curl theme={null}
  curl https://api.openai.com/v1/responses \
    -H "Authorization: Bearer $OPENAI_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "model": "gpt-5",
      "input": "List the agents in my ImpelLabs workspace.",
      "tools": [{
        "type": "mcp",
        "server_label": "impellabs",
        "server_url": "https://api.impellabs.tech/mcp",
        "headers": {"Authorization": "Bearer tgcc_xxxxxxxxxxxx"},
        "require_approval": "never"
      }]
    }'
  ```
</CodeGroup>

<Warning>
  `"require_approval": "never"` lets the model call any tool the key's scopes
  allow, unattended. Combine it with `allowed_tools` and a narrowly scoped key
  — a key holding only `agents:read` cannot be talked into spending credits,
  and that is a stronger guarantee than an approval prompt nobody reads.
</Warning>

## Two credentials, and they are not interchangeable

|                  | Used for       | Where it lives                                           |
| ---------------- | -------------- | -------------------------------------------------------- |
| `OPENAI_API_KEY` | Calling OpenAI | Your environment                                         |
| `tgcc_…`         | Calling **us** | The `headers` block above, or the OAuth grant in the app |

The Responses API forwards your `headers` to our server verbatim. OpenAI never
sees a scope decision; the key does.

## If it does not connect

<AccordionGroup>
  <Accordion title="The connector will not save">
    ChatGPT fetches `/.well-known/oauth-protected-resource` before it will
    accept a URL. Confirm it answers, and that you pasted the endpoint
    (`/mcp`) and not the dashboard.
  </Accordion>

  <Accordion title="Tools are listed but every call fails">
    The grant carries `mcp:connect` and nothing else. Scopes are per tool; see
    [Authentication](/connect/authentication).
  </Accordion>

  <Accordion title="A call returns an error the model reads out loud">
    That is the design. Out of credit, not found and validation failures come
    back as tool errors with readable text, not as HTTP faults, so the model can
    tell you what went wrong instead of stalling. See
    [Credits](/connect/credits).
  </Accordion>
</AccordionGroup>
