# Custom connectors

Not every service your agent needs is in the catalog. Any MCP server can give it tools as a connector of your own: a public one, one behind an API key, or one each user signs in to.

`$STREAM_ACCELERATION_URL` is your router's URL, and `$SERVER_TOKEN` is a [server token](https://getstream.io/agents/docs/flutter/auth/): an HS256 JWT of `{"server": true}` signed with your API secret.

## Add a public MCP server

DeepWiki answers questions about public GitHub repositories, and nobody signs in to it. Your backend creates a connector for its URL and connects it once. Then `agent.yaml` uses it like any connector in the catalog.

### Your backend: create the DeepWiki connector

`"schemes": ["none"]` means the server takes no credential:

```bash
curl -X POST "$STREAM_ACCELERATION_URL/v1/agents/connectors" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "custom_deepwiki",
    "name": "DeepWiki",
    "description": "Answers questions about public GitHub repositories",
    "endpoint": "https://mcp.deepwiki.com/mcp",
    "schemes": ["none"]
  }'
```

### Your backend: connect DeepWiki

Create the app's connection:

```bash
curl -X POST "$STREAM_ACCELERATION_URL/v1/agents/connections" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"connector_id": "custom_deepwiki", "owner": {"type": "app"}, "label": "deepwiki"}'
```

It returns the connection, `pending`, with its `id`. Use that `id` as `$CONNECTION_ID`, and save empty credentials to connect it:

```bash
curl -X PUT "$STREAM_ACCELERATION_URL/v1/agents/connections/$CONNECTION_ID/credentials" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"expected_revision": 1}'
```

The connection is now `connected`.

### Use DeepWiki in agent.yaml

```yaml title="agents/assistant/agent.yaml"
name: assistant # an internal assistant for your team
mode: text
llm: llm-fast
connectors:
  - name: deepwiki
    connector: custom_deepwiki # the connector's id
    connection: deepwiki # the label of its connection
```

```sh
getstream agents test assistant --sync
```

Ask: "What is the vercel/next.js repository?" to see the agent answer with `deepwiki__ask_wiki_question`. See [Choosing tools](https://getstream.io/agents/docs/flutter/connectors/choosing-tools/) to offer only some of its tools.

Keep `connection`. Without it, the agent gets no DeepWiki tools, and a test in the terminal leaves it out.

## Add an MCP server that needs a key

An MCP server that needs an API key becomes a connector of your own. Your backend creates the connector, creates the app's connection to it, and saves the key. Then `agent.yaml` uses it like any connector in the catalog.

### Your backend: create the key connector

```bash
curl -X POST "$STREAM_ACCELERATION_URL/v1/agents/connectors" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "custom_search",
    "name": "Exa search",
    "description": "Searches the web",
    "category": "Search",
    "endpoint": "https://mcp.exa.ai/mcp",
    "schemes": ["api_key"]
  }'
```

| Field         | What it sets                                               | Required |
| ------------- | ---------------------------------------------------------- | -------- |
| `id`          | Starts with `custom_`, such as `custom_search`             | Yes      |
| `name`        | The name people see                                        | Yes      |
| `endpoint`    | The MCP server, over Streamable HTTP: a public `https` URL | Yes      |
| `schemes`     | How a connection signs in: `["api_key"]`                   | Yes      |
| `description` | What it does                                               | No       |
| `category`    | A group for it, such as `Search`                           | No       |

### Your backend: create the key connection

```bash
curl -X POST "$STREAM_ACCELERATION_URL/v1/agents/connections" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"connector_id": "custom_search", "owner": {"type": "app"}, "label": "search"}'
```

It returns the connection, `pending`, with its `id`.

### Your backend: save the key

Use that `id` as `$CONNECTION_ID`. `header` is required: it names the HTTP header the router sends the key in, and it can't be `Authorization`:

```bash
curl -X PUT "$STREAM_ACCELERATION_URL/v1/agents/connections/$CONNECTION_ID/credentials" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"expected_revision": 1, "values": {"api_key": "...", "header": "x-api-key"}}'
```

The connection is now `connected`, and the key is never shown again.

### Use the key connector in agent.yaml

```yaml title="agents/assistant/agent.yaml"
name: assistant # an internal assistant for your team
mode: text
llm: llm-fast
connectors:
  - name: search
    connector: custom_search # the connector's id
    connection: search # the label of its connection
```

```sh
getstream agents test assistant --sync
```

Ask: "Find the Vision Agents page on getstream.io" to see the agent search with `search__web_search_exa`.

## Add an MCP server each user signs in to

A server that acts in each user's own account has users sign in to it. Create its connector with `"schemes": ["oauth2_code"]`:

```bash
curl -X POST "$STREAM_ACCELERATION_URL/v1/agents/connectors" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "custom_notes",
    "name": "Notes",
    "description": "Notes your team shares",
    "endpoint": "https://mcp.example.com/mcp",
    "schemes": ["oauth2_code"],
    "client": {"registration": ["cimd", "dcr"]}
  }'
```

Set `endpoint` to your server's MCP URL, and `id`, `name` and `description` to your own.

`registration` lets the router register its own OAuth client with the server, so you set none up. The server has to publish its OAuth protected resource metadata ([RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728)). Without it, the sign-in can't start.

Name it without `connection`, so each user signs in to their own account:

```yaml title="agents/assistant/agent.yaml"
name: assistant # an internal assistant for your team
mode: text
llm: llm-fast
connectors:
  - name: notes
    connector: custom_notes # each user signs in
```

Each user connects it from your app, as in [Connect from your app](https://getstream.io/agents/docs/flutter/connectors/each-user-account/#connect-from-your-app), with `"connector_id": "custom_notes"`.

## Change or delete a connector

To change a connector, create it again with the same `id`, then save each connection's credentials again.

To delete a connector, first delete its connections and remove it from your agents:

```bash
curl -X DELETE "$STREAM_ACCELERATION_URL/v1/agents/connectors/custom_search" \
  -H "api_key: $STREAM_API_KEY" -H "stream-auth-type: jwt" \
  -H "Authorization: Bearer $SERVER_TOKEN"
```

## Going further

- [Shared account](https://getstream.io/agents/docs/flutter/connectors/shared-account/): One account the app owns, for every conversation.
- [Choosing tools](https://getstream.io/agents/docs/flutter/connectors/choosing-tools/): Offer only the tools the agent needs.
- [Creating an agent](https://getstream.io/agents/docs/flutter/creating-an-agent/): The agent folder, and every key of agent.yaml.
- [Tool calling & dispatch](https://getstream.io/agents/docs/flutter/tool-calling-and-dispatch/): Your own functions, run in your process.
- [Troubleshooting](https://getstream.io/agents/docs/flutter/connectors/troubleshooting/): Errors you may see, why, and what to do.

---

For the most recent version of this documentation, visit [https://getstream.io/agents/docs/flutter/connectors/mcp/](https://getstream.io/agents/docs/flutter/connectors/mcp/).