Generative AIBuilding with foundation modelsOpenAI platform

Using MCP resources with the Responses API

10 minutes read

You've already used function calling and built-in tools to extend model capabilities. Now, let's see how you can use MCP resources to take this integration even further.

Setting up MCP resources

The Responses API supports remote MCP servers that support the Streamable HTTP or the HTTP/SSE transport protocols. To use them in your requests, you need to provide the server's URL (server_url) and an OAuth authorization parameter containing an access token if the server needs it. Here's an example for the Hugging Face MCP server (you need an OAuth token from Hugging Face for this):

response = client.responses.create(
    model="gpt-5.1",
    tools=[
        {
            "type": "mcp",
            "server_label": "HuggingFace",
            "server_description": "Hugging Face MCP Server",
            "server_url": "https://huggingface.co/mcp?login",
            "authorization": os.getenv("HF_TOKEN"),
            "require_approval": "never",
        },
    ],
    input="What tools are available from the configured MCP server?",
)

print(response.output)

You can also use connectors, which are pre-built integrations for popular tools like Dropbox, Gmail, SharePoint, and other business applications. For these, you need a connector_id and an OAuth authorization access token:

response = client.responses.create(
    model="gpt-5.1",
    tools=[
        {
            "type": "mcp",
            "server_label": "Dropbox",
            "connector_id": "connector_dropbox",
            "authorization": "<oauth_access_token>",
            "require_approval": "never",
        },
    ],
    input="Summarize the Q2 earnings report.",
)

print(response.output_text)

Your application must manage the process of acquiring, refreshing, and storing OAuth access tokens from the integration provider as well as their required permissions. For example, a Google Calendar connector needs OAuth tokens with the appropriate scope and permissions to read calendar events, create appointments, or modify schedules.

Available tools

Both MCP servers and connectors expose tools that let models perform specific actions or retrieve particular types of data from external systems. Unlike generic API calls, MCP servers and connectors are semantically rich interfaces. They give models a clear understanding of available operations, required parameters, and expected results. This semantic clarity lets models make intelligent decisions about when and how to use them.

Based on your request, the model might decide to use a connector or an MCP server. But first, it will request a list of the available tools. You can see this in the mcp_list_tools item of the model's response.

{
  "type": "mcp_list_tools",
  "id": "mcpl_01a6f631c7b7216b00696e09a523808193ab2a0097cfbd1c02",
  "server_label": "HuggingFace",
  "tools": [
    {
      "name": "model_search",
      "description": "Find Machine Learning models hosted on Hugging Face...",
      "annotations": { "read_only": true },
      "input_schema": {
        "type": "object",
        "properties": {
          "query": { "type": "string" },
          "author": { "type": "string" },
          "task": { "type": "string" },
          "library": { "type": "string" },
          "sort": {
            "type": "string",
            "enum": ["trendingScore", "downloads", "likes", "createdAt", "lastModified"]
          },
          "limit": { "type": "number", "default": 20 }
        }
      }
    }, 
      
    # <more tools>
  ],
  "error": null
}

Each tool includes detailed schemas that specify required and optional inputs, data types, validation rules, and default values. These schemas ensure that models provide appropriate inputs while letting servers validate requests before execution. Clear parameter documentation helps models understand how to construct valid requests and what data format to expect in responses.

In some cases, you don't want the model to see all the tools that a particular MCP server offers. If your use case only requires a subset of tools, you can specify that in the allowed_tools parameter only to import those tools. This can prevent unnecessary costs and reduce latency in cases where a server exposes many tools.

response = client.responses.create(
    model="gpt-5.1",
    tools=[
        {
            "type": "mcp",
            "server_label": "HuggingFace",
            "server_description": "Hugging Face MCP Server",
            "server_url": "https://huggingface.co/mcp?login",
            "authorization": os.getenv("HF_TOKEN"),
            "require_approval": "never",
            "allowed_tools": ["model_search", "dataset_search"],
        },
    ],
    input="What tools are available from the configured MCP server?",
)

print(response)

Calling tools

If the model finds a tool that can help complete your request, it will call that tool with the required parameters. This decision-making process depends on the descriptions and parameter schemas for that tool. You can see which tool the model called, which inputs it passed to it, and the output from the tool in the mcp_call output item.

{
  "type": "mcp_call",
  "id": "mcp_01a6f631c7b7216b00696e09a735b08193a4a2034b9feb0560",
  "server_label": "HuggingFace",
  "name": "hub_repo_details",
  "arguments": "{\\"repo_ids\\":[\\"google/translategemma-4b-it\\"],\\"repo_type\\":\\"model\\"}",
  "status": "completed",
  "output": "# google/translategemma-4b-it\\n\\n## Overview\\n- **Author:** google\\n- **Task:** image-text-to-text\\n- **Library:** transformers\\n- **Downloads:** 17.6K | **Likes:** 327\\n...",
  "error": null
}

You may have noticed that the previous snippets we used set "require_approval": "never". This means the model will not request approval to perform actions or share data with a connector or MCP server. In some cases, especially when dealing with tools that modify important data or trigger significant operations, you may want to require approval.

If you set "require_approval": "always", the model's response will include an mcp_approval_request item:

{
  "id": "mcpr_08fce5b7e46e94e50069707a10bbc0819b89332bcdfba5b6ea",
  "arguments": {
    "query": "translategemma-4b-it",
    "author": "google",
    "task": "",
    "library": "",
    "sort": "downloads",
    "limit": 5
  },
  "name": "model_search",
  "server_label": "HuggingFace",
  "type": "mcp_approval_request"
}

In the next request, include an mcp_approval_response input item to approve it:

response = client.responses.create(
        model="gpt-5.1",
        tools=[mcp_tool],
        previous_response_id=response.id,
        input=[{
            "type": "mcp_approval_response",
            "approve": True,
            "approval_request_id": "mcpr_08fce5b7e46e94e50069707a10bbc0819b89332bcdfba5b6ea"
        }],
    )
Full code
# MCP tool configuration
mcp_tool = {
    "type": "mcp",
    "server_label": "HuggingFace",
    "server_description": "Hugging Face MCP Server",
    "server_url": "https://huggingface.co/mcp?login",
    "authorization": os.getenv("HF_TOKEN"),
    "require_approval": "always",
}

# Initial request
print("Sending initial request...")
response = client.responses.create(
    model="gpt-5.1",
    tools=[mcp_tool],
    input="Does the google/translategemma-4b-it support image inputs?",
)

# Extract approval request ID dynamically
approval_id = None
if hasattr(response, 'output') and isinstance(response.output, list):
    for item in response.output:
        if getattr(item, 'type', None) == 'mcp_approval_request':
            approval_id = getattr(item, 'id', None)
            print(f"Approval required. Request ID: {approval_id}")
            break

# Continue with approval if needed
if approval_id:
    print("Sending approval...")
    final_response = client.responses.create(
        model="gpt-5.1",
        tools=[mcp_tool],
        previous_response_id=response.id,
        input=[{
            "type": "mcp_approval_response",
            "approve": True,
            "approval_request_id": approval_id
        }],
    )

    print("\\nFinal Response:")
    print(final_response.output_text)
else:
    print("\\nResponse:")
    print(response.output_text)

When you run this code, you get the following output:

Sending initial request...
Approval required. Request ID: mcpr_0ba0c79ef390430a0069708213a93481979a827db2673fb888

Sending approval...

Final Response:
Yes, the model **google/translategemma-4b-it** supports image inputs as it is designed for **image-text-to-text** tasks. This can be useful for tasks involving image captioning or translating text within images. 

You can find more information and access the model [here](<https://hf.co/google/translategemma-4b-it>).

You can also avoid approval for safe or read-only operations as follows:

mcp_tool = {
    "type": "mcp",
    "server_label": "HuggingFace",
    "server_description": "Hugging Face MCP Server",
    "server_url": "https://huggingface.co/mcp?login",
    "authorization": os.getenv("HF_TOKEN"),
    "require_approval": {
        "never": {
            "tool_names": ["hf_whoami"] # always allow the HF user info tool
        }
    },
}

Best practices

To make the most out of MCP, it's important to follow some best practices. For example, carefully design approval workflows that balance security requirements with user experience for potentially sensitive operations. Consider implementing different approval levels for different tool categories, and provide clear approval interfaces that don't interrupt application flow.

You also need to implement robust authentication and authorization mechanisms that follow security best practices. Use OAuth2 for third-party services, implement proper token refresh logic, and store credentials securely. Never expose sensitive authentication information in logs or error messages.

Anything can go wrong when executing an MCP tool or connector. Design comprehensive error handling that gracefully manages various failure scenarios. Provide meaningful error messages that help models understand what went wrong and potentially suggest alternative approaches. Implement retry logic for transient failures while avoiding infinite retry loops.

When choosing MCP servers, use an official server from the service provider. If one doesn't exist, make sure to thoroughly review and test any third-party server you need to use to avoid potential data leakage. This is especially important for applications with strict data processing requirements.

Finally, implement comprehensive monitoring that tracks tool usage, performance metrics, error rates, and user satisfaction. Develop thorough testing strategies that cover normal operation, edge cases, error conditions, and integration scenarios. Test with various model types and usage patterns to ensure robust operation across different application contexts. Use this data to optimize tool design, identify problematic patterns, optimize resource usage, and guide future development priorities.

Conclusion

MCP transforms models from isolated text processors into capable agents that can interact with the broader software ecosystem through standardized interfaces. You've learned how to set up MCP resources, use pre-built connectors, leverage available tools, and execute tool calls effectively with OpenAI models in your applications.

2 learners liked this piece of theory. 0 didn't like it. What about you?
Report a typo