---
title: How to Use Model Context Protocol (MCP)
description: Connect DigitalOcean Inference requests to remote Model Context Protocol (MCP) servers so the model can call tools those servers expose.
product: Inference
url: https://docs.digitalocean.com/products/inference/how-to/use-server-side-tools/use-mcp/
last_updated: "2026-08-24"
---

> **For AI agents:** The documentation index is at [https://docs.digitalocean.com/llms.txt](https://docs.digitalocean.com/llms.txt). Markdown versions of pages use the same URL with `index.html.md` in place of the HTML page (for example, append `index.html.md` to the directory path instead of opening the HTML document).

# How to Use Model Context Protocol (MCP)

Inference provides a single control plane for managing inference workflows. It includes a Model Catalog where you can view available foundation models, including both DigitalOcean-hosted and third-party commercial models, compare model capabilities and pricing, use routing to match inference requests to the best-fit model, and run inference using serverless or dedicated deployments.

MCP servers expose tools that the model can call, such as fetching account data, managing schedules, or interacting with third-party APIs. The MCP built-in tool connects the model to remote [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) servers and orchestrates calls to them.

## Connect to an Authenticated MCP Server

You can connect to authenticated MCP servers using bearer token authentication. The following example sends a Chat Completions request that connects to the DigitalOcean Accounts MCP server. Replace `$DIGITALOCEAN_API_TOKEN` with a valid [DigitalOcean personal access token](https://docs.digitalocean.com/reference/api/create-personal-access-token/index.html.md).

### Python

```python
import os
from pydo.inference import Client

client = Client(token=os.environ.get("MODEL_ACCESS_KEY"))

resp = client.chat.completions.create(
    model="openai-gpt-4o",
    messages=[
        {"role": "user", "content": "Fetch my DigitalOcean account information and summarize it in 2 bullets."},
    ],
    tools=[
        {
            "type": "mcp",
            "server_label": "digitalocean",
            "server_url": "https://accounts.mcp.digitalocean.com/mcp",
            "authorization": f"Bearer {os.environ.get('DIGITALOCEAN_API_TOKEN')}",
            "allowed_tools": ["account-get-information"],
        }
    ],
    tool_choice="required",
    stream=False,
    max_tokens=512,
)

print(resp.choices[0].message.content)
```

### JavaScript

```javascript
import { InferenceClient } from "@digitalocean/dots";

const client = new InferenceClient({
    apiKey: process.env.MODEL_ACCESS_KEY,
});

const completion = await client.chat.completions.create({
    model: "openai-gpt-4o",
    messages: [
        { role: "user", content: "Fetch my DigitalOcean account information and summarize it in 2 bullets." },
    ],
    tools: [
        {
            type: "mcp",
            server_label: "digitalocean",
            server_url: "https://accounts.mcp.digitalocean.com/mcp",
            authorization: `Bearer ${process.env.DIGITALOCEAN_API_TOKEN}`,
            allowed_tools: ["account-get-information"],
        },
    ],
    tool_choice: "required",
    stream: false,
    max_tokens: 512,
});

console.log(completion.choices[0].message.content);
```

### cURL

```shell
curl -X POST https://inference.do-ai.run/v1/chat/completions \
  -H "Authorization: Bearer $MODEL_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai-gpt-4o",
    "messages": [
      {
        "role": "user",
        "content": "Fetch my DigitalOcean account information and summarize it in 2 bullets."
      }
    ],
    "tools": [
      {
        "type": "mcp",
        "server_label": "digitalocean",
        "server_url": "https://accounts.mcp.digitalocean.com/mcp",
        "authorization": "Bearer $DIGITALOCEAN_API_TOKEN",
        "allowed_tools": ["account-get-information"]
      }
    ],
    "tool_choice": "required",
    "stream": false,
    "max_tokens": 512
  }'
```

The `allowed_tools` array restricts which tools from the MCP server the model can call. In this example, only the `account-get-information` tool is available. When omitted, the model can use any tool the server exposes. For the full set of MCP tool parameters, see the [Serverless Inference API reference](https://docs.digitalocean.com/products/inference/reference/api/serverless-inference/index.html.md). The response looks like the following:

```text
{
    "choices": [
        {
            "finish_reason": "stop",
            "index": 0,
            "logprobs": null,
            "message": {
                "annotations": [
                    {
                        "type": "tool_use",
                        "tool_use": {
                            "name": "digitalocean__account-get-information",
                            "call_id": "call_xasb9Xk1HAfT564P3bteZZTT",
                            "arguments": "{}",
                            "status": "completed",
                            "output": "{\n  \"droplet_limit\": 100,\n  \"floating_ip_limit\": 75,\n  \"reserved_ip_limit\": 75,\n  \"volume_limit\": 5000,\n  \"email\": \"dev-sammy@example.com\",\n  \"name\": \"dev-sammy\",\n  \"uuid\": \"de55ee97-21ab-452d-aaf0-d4046480xxxx\",\n  \"email_verified\": true,\n  \"status\": \"active\",\n  \"team\": {\n    \"name\": \"My Team\",\n    \"uuid\": \"de55ee97-21ab-452d-aaf0-d4046480xxxx\"\n  }\n}"
                        }
                    }
                ],
                "content": "- Your account (\"dev-sammy\") is active with email \"dev-sammy@example.com\", which is verified. You are part of \"My Team\" with a UUID of \"de55ee97-21ab-452d-aaf0-d4046480xxxx\".\n- You have a resource allocation limit of 100 droplets, 75 floating IPs, 75 reserved IPs, and 5000 volumes.",
                "reasoning_content": null,
                "refusal": null,
                "role": "assistant"
            }
        }
    ],
....    }
}
```

## Connect to an Unauthenticated MCP Server

You can also connect to public MCP servers that do not require authentication. The following example sends a Responses API request:

### Python

```python
import os
from pydo.inference import Client

client = Client(token=os.environ.get("MODEL_ACCESS_KEY"))

resp = client.responses.create(
    model="openai-gpt-4o",
    input="Create a scheduling poll called Team Lunch with two time options for tomorrow at noon and the day after at noon.",
    tools=[
        {
            "type": "mcp",
            "server_label": "timergy",
            "server_url": "https://api.timergy.com/mcp",
        }
    ],
    tool_choice="required",
    stream=False,
    max_output_tokens=512,
)

print(resp)
```

### JavaScript

```javascript
import { InferenceClient } from "@digitalocean/dots";

const client = new InferenceClient({
    apiKey: process.env.MODEL_ACCESS_KEY,
});

const resp = await client.responses.create({
    model: "openai-gpt-4o",
    input: "Create a scheduling poll called Team Lunch with two time options for tomorrow at noon and the day after at noon.",
    tools: [
        {
            type: "mcp",
            server_label: "timergy",
            server_url: "https://api.timergy.com/mcp",
        },
    ],
    tool_choice: "required",
    stream: false,
    max_output_tokens: 512,
});

console.log(resp);
```

### cURL

```shell
curl -X POST https://inference.do-ai.run/v1/responses \
  -H "Authorization: Bearer $MODEL_ACCESS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "openai-gpt-4o",
    "input": "Create a scheduling poll called Team Lunch with two time options for tomorrow at noon and the day after at noon.",
    "tools": [
      {
        "type": "mcp",
        "server_label": "timergy",
        "server_url": "https://api.timergy.com/mcp"
      }
    ],
    "tool_choice": "required",
    "stream": false,
    "max_output_tokens": 512
  }'
```

The response looks like the following:

```text
{
...
  "model": "openai-gpt-4o",
  "object": "response",
  "output": [
    {
      "arguments": "{\"autoFinalize\":false,\"creatorName\":\"Assistant for Team\",\"deadline\":\"2026-04-08T12:00:00-05:00\",\"description\":\"Scheduling poll for a team lunch\",\"invitees\":[],\"location\":\"Office Cafeteria\",\"options\":[{\"end\":\"2026-04-10T13:00:00-05:00\",\"start\":\"2026-04-10T12:00:00-05:00\"},{\"end\":\"2026-04-11T13:00:00-05:00\",\"start\":\"2026-04-11T12:00:00-05:00\"}],\"title\":\"Team Lunch\"}",
      "call_id": "call_uallF71f2THNYsEvZUubSUhQ",
      "name": "timergy__create_poll",
      "status": "completed",
      "type": "function_call"
    },
    {
      "call_id": "call_uallF71f2THNYsEvZUubSUhQ",
      "output": "{\n  \"pollId\": \"fdc8110b-274d-45b4-b791-0149f6cfc4bc\",\n  \"title\": \"Team Lunch\",\n  \"url\": \"https://timergy.com/en/polls/fdc8110b-274d-45b4-b791-0149f6cfc4bc\",\n  \"passphrase\": \"horse-sword-thumb\",\n  \"options\": [\n    {\n      \"id\": \"c8879755-9136-497d-aedc-81b50fafbb13\",\n      \"start\": \"2026-04-10T17:00:00.000Z\",\n      \"end\": \"2026-04-10T18:00:00.000Z\",\n      \"label\": null\n    },\n    {\n      \"id\": \"58c474c6-12b4-42d5-a96e-c6c977d8a3b2\",\n      \"start\": \"2026-04-11T17:00:00.000Z\",\n      \"end\": \"2026-04-11T18:00:00.000Z\",\n      \"label\": null\n    }\n  ],\n  \"expiresAt\": \"2026-04-21T18:00:00.000Z\",\n  \"autoFinalize\": false,\n  \"inviteesSent\": 0,\n  \"note\": \"Share the URL with participants. The passphrase is saved for finalization. Assistant for Team's \\\"yes\\\" votes have been auto-submitted.\"\n}",
      "status": "completed",
      "type": "function_call_output"
    },
    {
      "content": [
        {
          "annotations": [],
          "logprobs": [],
          "text": "The scheduling poll \"Team Lunch\" has been created. You can share the following URL with participants to vote:\n\n**Poll URL:** [Team Lunch Poll](https://timergy.com/en/polls/fdc8110b-274d-45b4-b791-0149f6cfc4bc)\n\nFor admin access and to finalize the poll, you can use the passphrase:\n\n**Passphrase:** `horse-sword-thumb`\n\nThe poll includes two time slot options:\n- April 10, 2026, from 12:00 PM to 1:00 PM (local time)\n- April 11, 2026, from 12:00 PM to 1:00 PM (local time)",
          "type": "output_text"
        }
      ],
...
  "tool_choice": "auto",
  "tools": [
    {
      "type": "mcp",
      "server_label": "timergy",
      "server_url": "https://api.timergy.com/mcp"
    }
  ],
...
  }
}
```