Skip to main content
Perplexity

Search documentation

Type to search this documentation.

On this pageOverview

Connectors

Connectors are integrations that you configure once on your Project connectors page. Choose a managed connector from the catalog, or add a custom connector for your own remote Model Context Protocol (MCP) server. Perplexity stores the connection settings and credentials for your Project. Your application references the connector by ID, so it does not need to store or send the MCP server's token with each request. You still use your Perplexity API key to authenticate Agent API requests. Any API key in the same Project can use the connector. Some managed connectors also make their credentials available to Sandbox commands. This lets an agent combine service access with code changes and other local work in one run.

The current set of connectors includes:

Service Connector ID
GitHub connector_github
Slack connector_slack
Google Drive connector_googledrive
Datadog connector_datadog
Linear connector_linear
Notion connector_notion

You must be a Project administrator to connect a service.

  1. Open your Project connectors page.
  2. Select a service and complete its connection setup.
  3. Copy the connector ID from the service card.
  4. Use the connector in an Agent API request.

Register your remote MCP server once and let Perplexity store its API key. Your application only needs the connector ID to use the saved connection, with no separate MCP credential to manage in your application. Custom connectors are available to all Projects and require a Project administrator to set up.

Open your Project connectors page and select Add custom connector. Add your server's name, MCP URL, authentication (API Key or None), and transport (Streamable HTTP or SSE), then copy its connector ID.

Use that ID with type: "connector" in requests authenticated with an API key from the same Project. The saved connection supplies the server URL and authentication.

Managed and custom connectors use the same request fields. Add a connector entry to the tools array.

The following request uses a connected Slack workspace to summarize recent messages about AI. Use the connector ID copied from the API Console.

Python
from perplexity import Perplexity

client = Perplexity()

response = client.responses.create(
    model="openai/gpt-5.6-terra",
    input="Find and summarize recent messages about AI in my Slack workspace.",
    max_steps=6,
    tools=[
        {
            "type": "connector",
            "id": "connector_slack",
            "server_label": "slack",
        }
    ],
)

print(response.output_text)
Typescript
import Perplexity from '@perplexity-ai/perplexity_ai';

const client = new Perplexity();

const response = await client.responses.create({
  model: 'openai/gpt-5.6-terra',
  input: 'Find and summarize recent messages about AI in my Slack workspace.',
  max_steps: 6,
  tools: [
    {
      type: 'connector',
      id: 'connector_slack',
      server_label: 'slack',
    },
  ],
});

console.log(response.output_text);
cURL
curl https://api.perplexity.ai/v1/agent \
  -H "Authorization: Bearer $PERPLEXITY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.6-terra",
    "input": "Find and summarize recent messages about AI in my Slack workspace.",
    "max_steps": 6,
    "tools": [
      {
        "type": "connector",
        "id": "connector_slack",
        "server_label": "slack"
      }
    ]
  }' | jq

The response output array lists the connector's tools, the model's search of that catalog, each tool call, and the final message. Connectors are deferred by default, so the model searches the catalog (tool_search_output) before it calls a tool.

Response output (truncated)
JSON
[
  {
    "type": "mcp_list_tools",
    "id": "mcpl_4826e99b-cae4-4c44-a613-d205823c2bc0",
    "connector_id": "connector_slack",
    "server_label": "slack",
    "tools": [
      {
        "name": "slack_search_public",
        "description": "Searches for messages, files in public Slack channels ...",
        "input_schema": {
          "type": "object",
          "properties": { "query": { "type": "string" } },
          "required": ["query"]
        }
      },
      {
        "name": "slack_send_message",
        "description": "Sends a message to a Slack channel or user ...",
        "input_schema": {
          "type": "object",
          "properties": {
            "channel_id": { "type": "string" },
            "message": { "type": "string" },
            "thread_ts": { "type": "string" }
          },
          "required": ["channel_id", "message"]
        }
      }
    ]
  },
  {
    "type": "tool_search_output",
    "id": "tso_call_opbSkWX14DwhfWlPdAE9wfH0",
    "call_id": null,
    "status": "completed",
    "execution": "server",
    "arguments": "{\"paths\":[\"slack\"],\"queries\":[\"search\",\"messages\"]}",
    "tools": [
      {
        "type": "namespace",
        "name": "slack",
        "tools": [
          { "type": "function", "name": "slack_search_public", "description": "..." }
        ]
      }
    ]
  },
  {
    "type": "mcp_call",
    "id": "call_DUjlg6jMJoU92GMfrmD8SVcS",
    "connector_id": "connector_slack",
    "server_label": "slack",
    "name": "slack_search_public",
    "arguments": "{\"query\":\"AI\",\"content_types\":\"messages\",\"sort\":\"timestamp\", ...}",
    "output": "{\"results\": ...}",
    "error": null
  },
  {
    "type": "message",
    "id": "msg_...",
    "role": "assistant",
    "status": "completed",
    "content": [
      { "type": "output_text", "text": "Here is a summary of recent messages about AI ...", "annotations": [] }
    ]
  }
]

A connector can expose many tools, and loading every schema up front would waste tokens. Connector tools are discovered lazily instead: the model receives the connector namespace, searches it, loads only the schemas it needs, and calls them — all automatically. You only add the connector to tools.

The mcp_list_tools item still records the full catalog; deferred discovery controls what enters the model's context, not what the response reports.

Field Type Required Description
type string Yes Must be "connector".
id string Yes The managed or custom connector ID copied from the API Console.
server_label string Yes A request-local label for the connector.
server_description string No A model-facing description of the connector namespace.
allowed_tools array No An exact-name allowlist. Omit or leave empty to expose every available tool.

Some connectors make their credentials available to sandbox commands. GitHub is a key example.

The GitHub connector lets the model use the GitHub tools that belong to your connected GitHub account. You can use it in two ways.

Without the sandbox, GitHub works like any other connector: the model discovers tools from the GitHub catalog and calls them as mcp_call items. The catalog covers repositories, files, commits, issues, and pull requests. For example, get_file_contents reads the current contents of a file by owner, repo, and path, or lists a directory when path points to a folder. Pass ref to read from a specific branch, tag, or commit; without it, the tool reads the default branch.

Use this mode for targeted lookups, such as reading a file, checking a commit, or listing pull requests, when you want each call recorded in the response. To see the full tool set, send a request with only the connector and read the mcp_list_tools item in the output.

Pair the connector with Sandbox when the task needs the git or gh CLI. With both tools enabled, the agent can clone private repositories, read and search files, diff branches, change code, commit, push a branch, and create or update a pull request. It uses the git and gh CLIs in the sandbox with the GitHub credentials from the connector. The agent can access only repositories and perform only actions that your connected GitHub account permits.

With the sandbox enabled and no allowed_tools, GitHub runs through the CLIs: the response has sandbox_results items instead of mcp_list_tools or mcp_call items, and failures appear as git or gh output. Set allowed_tools or omit the sandbox to use GitHub as a regular connector with mcp_call items.

Python
from perplexity import Perplexity

client = Perplexity()

stream = client.responses.create(
    model="openai/gpt-5.6-terra",
    input="Clone the GitHub repository perplexityai/perplexity-py. Review README.md and make one small, factual documentation improvement. Do not modify any other files. Report the changed file. Create a pull request with a clear title and return its URL.",
    max_steps=12,
    stream=True,
    tools=[
        {"type": "sandbox"},
        {
            "type": "connector",
            "id": "connector_github",
            "server_label": "github",
        },
    ],
)

for event in stream:
    print(event)
Typescript
import Perplexity from '@perplexity-ai/perplexity_ai';

const client = new Perplexity();

const stream = await client.responses.create({
  model: 'openai/gpt-5.6-terra',
  input: 'Clone the GitHub repository perplexityai/perplexity-py. Review README.md and make one small, factual documentation improvement. Do not modify any other files. Report the changed file. Create a pull request with a clear title and return its URL.',
  max_steps: 12,
  stream: true,
  tools: [
    { type: 'sandbox' },
    {
      type: 'connector',
      id: 'connector_github',
      server_label: 'github',
    },
  ],
});

for await (const event of stream) {
  console.log(event);
}
cURL
curl -N --no-buffer --fail-with-body https://api.perplexity.ai/v1/agent \
  -H "Authorization: Bearer $PERPLEXITY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "model": "openai/gpt-5.6-terra",
    "input": "Clone the GitHub repository perplexityai/perplexity-py. Review README.md and make one small, factual documentation improvement. Do not modify any other files. Report the changed file. Create a pull request with a clear title and return its URL.",
    "max_steps": 12,
    "stream": true,
    "tools": [
      { "type": "sandbox" },
      {
        "type": "connector",
        "id": "connector_github",
        "server_label": "github"
      }
    ]
  }' \
  | awk '/^data: / { sub(/^data: /, ""); sub(/\r$/, ""); if ($0 != "[DONE]") print }' \
  | jq --unbuffered .

The sandbox is a general-purpose execution environment, not a dedicated coding agent. It is a good fit for scoped repository tasks that complete in one run: read or review a set of files, explain a diff, make a focused change, or open a pull request. Repository-wide code review and multi-stage development work that depends on a persistent development environment, project-specific test setup, or long iteration loops are outside what a single sandbox run is designed for. For that kind of work, split it into scoped requests and give each one a clear, verifiable outcome.

Both connectors and MCP servers let the Agent API call external tools. Use a managed or custom connector to reuse a connection configured for your Project. Use MCP to provide a remote server's URL and authentication in each request.

Connector MCP server
Setup Connect a catalog service or add your own server once in the API Console. Reference it with type: "connector" and id. Use type: "mcp" and provide a remote server_url in each request.
Credentials Perplexity stores the server credential for your Project. Your application sends the connector ID. Your application supplies the server credential in each request.
Custom server transport Streamable HTTP or SSE. Streamable HTTP only.
Sandbox integration Some managed connectors make their credentials available to Sandbox commands. For example, use the GitHub connector with git and gh. MCP server credentials are not available to Sandbox commands.
Best for Reusing managed integrations or your own MCP server across Project requests. Choosing a server and credentials separately for each request.

A connector tool call can fail as an mcp_call item with an error field. This does not fail the request: the run continues and the error is passed to the model in-band, so the model still answers — it just cannot use that connector.

The main case to handle is AUTH_REQUIRED: the connector's authorization went stale or an administrator revoked it. Your requests keep working — the connector is just unavailable to the model until it is reconnected, which you can do later.

For example:

JSON
{
  "type": "mcp_call",
  "id": "call_h2rK8I109IvZC038Wcuudzhc",
  "connector_id": "connector_slack",
  "server_label": "slack",
  "name": "slack_search_public",
  "arguments": "{\"query\":\"AI\",\"content_types\":\"messages\", ...}",
  "error": "AUTH_REQUIRED"
}

Because the request still succeeds, this is easy to miss. Detect it in your harness and send it to your logging or alerting so an operator can reconnect the connector on the Project connectors page.

Your harness can branch on the error value:

Value Meaning Suggested handling
AUTH_REQUIRED The connector's authorization has lapsed or been revoked. Ask a Project administrator to reconnect it in the API Console.
INVALID_ARGUMENTS The model called the tool with arguments it rejected. Recoverable. The error is returned to the model, which can retry with corrected arguments.
POLICY_DENIED A policy blocked the tool call. Do not retry. The call is not allowed.
CONNECTOR_UNAVAILABLE The connector service could not be reached. Transient. Retry later.
CONNECTOR_INTERNAL_ERROR The connector returned a response that could not be used. Transient. Retry later.
TOOL_ERROR The tool failed for another reason. Treat as a tool failure.

The error field is a free-form string, so treat any other value as a tool failure. A connector that is not connected lists no tools ("tools": []) and produces no error, so also watch for an empty tool list.

Python
from perplexity import Perplexity

client = Perplexity()

CONNECTORS_URL = "https://console.perplexity.ai/group/connectors"

response = client.responses.create(
    model="openai/gpt-5.6-terra",
    input="Find and summarize recent messages about AI in my Slack workspace.",
    max_steps=6,
    tools=[
        {
            "type": "connector",
            "id": "connector_slack",
            "server_label": "slack",
        }
    ],
)

for item in response.output:
    if getattr(item, "type", None) != "mcp_call" or not getattr(item, "error", None):
        continue
    if item.error == "AUTH_REQUIRED":
        print(f"Ask an administrator to reconnect the {item.server_label} connector at {CONNECTORS_URL}")
    else:
        raise RuntimeError(f"Connector tool {item.name} failed: {item.error}")
Typescript
import Perplexity from '@perplexity-ai/perplexity_ai';

const client = new Perplexity();

const CONNECTORS_URL = 'https://console.perplexity.ai/group/connectors';

const response = await client.responses.create({
  model: 'openai/gpt-5.6-terra',
  input: 'Find and summarize recent messages about AI in my Slack workspace.',
  max_steps: 6,
  tools: [
    {
      type: 'connector',
      id: 'connector_slack',
      server_label: 'slack',
    },
  ],
});

for (const item of response.output) {
  if (item.type !== 'mcp_call' || !item.error) continue;
  if (item.error === 'AUTH_REQUIRED') {
    console.log(`Ask an administrator to reconnect the ${item.server_label} connector at ${CONNECTORS_URL}`);
  } else {
    throw new Error(`Connector tool ${item.name} failed: ${item.error}`);
  }
}
cURL
curl https://api.perplexity.ai/v1/agent \
  -H "Authorization: Bearer $PERPLEXITY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai/gpt-5.6-terra",
    "input": "Find and summarize recent messages about AI in my Slack workspace.",
    "max_steps": 6,
    "tools": [
      { "type": "connector", "id": "connector_slack", "server_label": "slack" }
    ]
  }' \
  | jq '.output[] | select(.type == "mcp_call" and .error != null) | {connector_id, server_label, name, error}'
Suggest an edit

Propose a replacement for this page. The site team reviews it before applying any changes.

Export
Documentation menu