# Using the MCP Tool to Connect External Services in the OpenAI Responses API

> Learn to connect external services like custom search engines or databases to the OpenAI Responses API using the MCP tool. Integrate JSON results seamlessly into model reasoning by hosting your own MCP server.

- Repository: [OpenAI/openai-cookbook](https://github.com/openai/openai-cookbook)
- Tags: how-to-guide
- Published: 2026-03-02

---

**The Model Context Protocol (MCP) tool lets the OpenAI Responses API invoke external services—such as custom search engines, databases, or internal APIs—by forwarding tool calls to an MCP server you host, then injecting the returned JSON back into the model's reasoning flow.**

The `openai/openai-cookbook` repository provides production-ready examples demonstrating how to bridge the Responses API with external data sources using the MCP tool. This integration pattern allows models to access real-time information from vector stores, enterprise databases, or proprietary search indexes without hardcoding credentials or logic into your client application.

## How the MCP Tool Works in the Responses API

When you include an MCP tool in a `responses.create` call, the OpenAI service treats it like any other function tool. The key difference is that execution happens on your infrastructure rather than inside OpenAI's environment.

The flow follows this architecture:

1. Your client sends a request to `responses.create` with a `tools` array containing an entry where `"type": "mcp"`
2. The model decides to call the tool and emits a tool-call message
3. The Responses service forwards the call via HTTP POST to your MCP server's SSE endpoint
4. Your server executes the registered Python function (e.g., `search` or `fetch`) and returns JSON
5. The model receives the result and continues reasoning, potentially making additional calls

This pattern is implemented in the Deep Research example within the cookbook, where the model uses an MCP server to query a vector store before generating citations.

## Setting Up an MCP Server for the Responses API

To enable MCP tool calls, you must run a compatible server that exposes your custom logic through standardized tool definitions. The cookbook uses the `FastMCP` framework to handle protocol details.

### Registering Tools with FastMCP

In [`examples/deep_research_api/how_to_build_a_deep_research_mcp_server/main.py`](https://github.com/openai/openai-cookbook/blob/main/examples/deep_research_api/how_to_build_a_deep_research_mcp_server/main.py), the server registers two tools using the `@mcp.tool()` decorator:

```python
from fastmcp import FastMCP
from openai import OpenAI

openai_client = OpenAI(api_key="YOUR_KEY")
VECTOR_STORE_ID = "vs_123"

def create_server():
    mcp = FastMCP(
        name="Sample Deep Research MCP Server",
        instructions="Use `search` to find relevant docs then `fetch` to retrieve full content."
    )
    
    @mcp.tool()
    async def search(query: str):
        resp = openai_client.vector_stores.search(
            vector_store_id=VECTOR_STORE_ID, 
            query=query
        )
        return {
            "results": [
                {
                    "id": r.file_id, 
                    "title": r.filename, 
                    "text": r.content[0].text[:200]
                } for r in resp.data
            ]
        }

    @mcp.tool()
    async def fetch(id: str):
        file = openai_client.vector_stores.files.content(
            vector_store_id=VECTOR_STORE_ID, 
            file_id=id
        )
        meta = openai_client.vector_stores.files.retrieve(
            vector_store_id=VECTOR_STORE_ID, 
            file_id=id
        )
        return {
            "id": id, 
            "title": meta.filename, 
            "text": "\n".join(c.text for c in file.data)
        }
    
    return mcp

```

Each `@mcp.tool()` decorated function becomes available to the model. The function signatures define the JSON schema that the model will use when generating tool calls.

### Exposing the Server via SSE Transport

The Responses API communicates with MCP servers using Server-Sent Events (SSE) over HTTP. You must start the server with the SSE transport enabled and bind it to an accessible host:

```python
if __name__ == "__main__":
    server = create_server()
    server.run(transport="sse", host="0.0.0.0", port=8000)

```

According to the README in [`examples/deep_research_api/how_to_build_a_deep_research_mcp_server/README.md`](https://github.com/openai/openai-cookbook/blob/main/examples/deep_research_api/how_to_build_a_deep_research_mcp_server/README.md), the server listens on `http://0.0.0.0:8000/sse/` and expects POST requests for tool invocations.

## Configuring the MCP Tool in Your Responses Request

To connect your MCP server to the Responses API, add a tool definition with `"type": "mcp"` to the `tools` array in your `responses.create` call. The configuration requires the `server_url` pointing to your SSE endpoint and a `server_label` for identification:

```python
import os
from openai import OpenAI

client = OpenAI()

system_message = """You are a researcher. Use the internal file lookup tool to search 
and fetch documents from our vector store before answering."""

response = client.responses.create(
    model="o3-deep-research-2025-06-26",
    input=[
        {
            "role": "developer", 
            "content": [{"type": "input_text", "text": system_message}]
        },
        {
            "role": "user", 
            "content": [{"type": "input_text", "text": "Research the economic impact of semaglutide."}]
        }
    ],
    reasoning={"summary": "auto"},
    tools=[
        {"type": "web_search_preview"},
        {
            "type": "mcp",
            "server_label": "internal_file_lookup",
            "server_url": "http://localhost:8000/sse/",
            "require_approval": "never"
        }
    ]
)

print(response.output)

```

The `require_approval` parameter controls whether the user must manually approve each tool invocation. Setting it to `"never"` allows autonomous operation, suitable for trusted internal tools.

## Real-World Example: Deep Research with Vector Search

The Deep Research implementation demonstrates how to combine the MCP tool with OpenAI's vector store search capabilities. This pattern lets models retrieve proprietary documents that are not accessible via public web search.

### The MCP Server Implementation

As shown in [`examples/deep_research_api/how_to_build_a_deep_research_mcp_server/main.py`](https://github.com/openai/openai-cookbook/blob/main/examples/deep_research_api/how_to_build_a_deep_research_mcp_server/main.py), the server wraps the Vector Stores API. The `search` tool performs semantic lookup, while the `fetch` tool retrieves full document content. This two-step approach minimizes token usage by fetching only the specific documents the model needs.

### Invoking the MCP Tool from the Client

When the model receives a research query, it automatically calls the `search` tool with relevant keywords. The MCP server returns document metadata, and if the model needs deeper context, it calls `fetch` with the specific document ID. All results flow back into the model's context window as JSON content, allowing it to cite sources accurately.

## Advanced Pattern: Databricks MCP Integration

For enterprise scenarios, the cookbook includes a supply chain copilot example in [`examples/mcp/building-a-supply-chain-copilot-with-agent-sdk-and-databricks-mcp/main.py`](https://github.com/openai/openai-cookbook/blob/main/examples/mcp/building-a-supply-chain-copilot-with-agent-sdk-and-databricks-mcp/main.py). This implementation exposes Databricks Vector Search and Unity Catalog functions as MCP tools:

```python
@function_tool
async def vector_search(query: str):
    ws, token, base = await _ctx()
    url = f"{base}/api/2.0/mcp/vector-search/{CATALOG}/{SCHEMA}"
    async with httpx.AsyncClient(timeout=30.0) as client:
        r = await client.post(
            url, 
            json={"query": query}, 
            headers={"Authorization": f"Bearer {token}"}
        )
        r.raise_for_status()
        return r.json()

@function_tool
async def uc_function(name: str, params: dict):
    ws, token, base = await _ctx()
    url = f"{base}/api/2.0/mcp/functions/{FUNCTIONS_PATH}"
    async with httpx.AsyncClient(timeout=30.0) as client:
        r = await client.post(
            url, 
            json={"function": name, "params": params},
            headers={"Authorization": f"Bearer {token}"}
        )
        r.raise_for_status()
        return r.json()

```

This pattern allows the Responses API to query enterprise data lakes and execute custom SQL functions through the same MCP interface, extending the model's capabilities to internal business systems.

## Summary

- **The MCP tool** enables the Responses API to call external services through a standardized protocol, bridging the gap between the model and your infrastructure.
- **Server setup** requires defining tools with `@mcp.tool()` and exposing them via SSE transport on an HTTP endpoint, as demonstrated in [`examples/deep_research_api/how_to_build_a_deep_research_mcp_server/main.py`](https://github.com/openai/openai-cookbook/blob/main/examples/deep_research_api/how_to_build_a_deep_research_mcp_server/main.py).
- **Client configuration** involves adding a JSON object with `"type": "mcp"`, `server_url`, and `server_label` to the `tools` array in `responses.create`.
- **Execution flow** is automatic: the model generates the tool call, the Responses service forwards it to your server, and the JSON result returns to the model's context.
- **Enterprise patterns** can wrap existing APIs (like Databricks Vector Search) behind MCP endpoints to give models secure access to proprietary data.

## Frequently Asked Questions

### What transport protocol does the MCP tool use?

The MCP tool uses **Server-Sent Events (SSE)** over HTTP. Your MCP server must expose an SSE endpoint (typically at `/sse/`) that the OpenAI Responses service can reach via POST requests. The cookbook examples use FastMCP's `run(transport="sse")` configuration to handle protocol compliance automatically.

### How does authentication work with MCP servers?

Authentication is handled between your client and your MCP server directly. The OpenAI service forwards the tool call but does not manage credentials for your infrastructure. In the Databricks example, the server obtains OAuth tokens using the Databricks SDK and passes them in HTTP headers, keeping secrets within your security perimeter.

### Can I use multiple MCP servers in one Responses API call?

Yes. The `tools` array accepts multiple MCP tool entries, each pointing to different `server_url` endpoints. You can combine internal file lookup, external database queries, and web search in a single request by including multiple objects with `"type": "mcp"` and distinct `server_label` values.

### What is the difference between MCP tools and standard function tools?

**Standard function tools** execute within your client code after the model returns a tool-call message; you handle the API call and send results back in a follow-up request. **MCP tools** delegate execution to a remote MCP server; the OpenAI service forwards the call and returns the result automatically, reducing client-side complexity and enabling stateless integrations with external services.