OpenAI Realtime 工具与 MCP

2026-11-06 12:39 更新

可以向 Realtime 会话附加工具,让模型在实时对话中查数据、执行操作或调用服务。客户端无论使用 WebRTC 数据通道还是 WebSocket,都使用相同工具配置事件。

工具由应用执行并返回结果时,使用函数工具;希望 Realtime API 代为连接远程工具服务器时,使用 MCP 工具。

选择工具类型

类型 适用情况 执行者
function 业务逻辑、批准检查或私有系统访问由应用负责。 客户端或服务器收到调用,返回 function_call_output。
带 server_url 的 mcp 希望调用远程 MCP 服务器公开的工具。 Realtime API 调用远程服务器。
带 connector_id 的 mcp 在既有模型中使用旧版内置连接器。 Realtime API 使用提供的授权调用连接器。

工具可以放在两个位置之一:

  • 会话级:通过 session.update 的 session.tools,让整段会话可用。
  • 响应级:通过 response.create 的 response.tools,只为一个轮次提供。

配置函数工具

工具应在应用中执行时,函数工具通常是合适选择。模型发出函数参数,应用执行操作,再通过 function_call_output 项目返回结果。

用 session.update 配置函数工具:

来源示例 1(javascript):

程序文字译释78:按订单号查询订单。

程序文字译释79:面向客户显示的订单号。

// [中文] 示例 1:配置函数工具;以下保留本语言原始示例。
// [中文] 原代码明确设置的模型值:gpt-realtime-2.1;各值的作用按其所在配置对象区分。
// [中文] 本段构造的事件类型:session.update;不要将构造载荷等同于收到成功确认。
// [中文] 沿原示例执行这些方法:ws.send;异步调用及事件接收顺序保留。
const event = {
  type: "session.update",
  session: {
    type: "realtime",
    model: "gpt-realtime-2.1",
    tools: [
      {
        type: "function",
        name: "lookup_order",
        description: "Look up an order by its order number.",
        parameters: {
          type: "object",
          properties: {
            order_number: {
              type: "string",
              description: "The customer-facing order number.",
            },
          },
          required: ["order_number"],
        },
      },
    ],
    tool_choice: "auto",
  },
};

ws.send(JSON.stringify(event));

来源示例 2(python):

沿用程序文字译释78。

沿用程序文字译释79。

## [中文] 示例 2:配置函数工具;以下保留本语言原始示例。
## [中文] 本段构造的事件类型:session.update;不要将构造载荷等同于收到成功确认。
## [中文] 沿原示例执行这些方法:ws.send;异步调用及事件接收顺序保留。
event = {
    "type": "session.update",
    "session": {
        "type": "realtime",
        "model": "gpt-realtime-2.1",
        "tools": [
            {
                "type": "function",
                "name": "lookup_order",
                "description": "Look up an order by its order number.",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "order_number": {
                            "type": "string",
                            "description": "The customer-facing order number.",
                        }
                    },
                    "required": ["order_number"],
                },
            }
        ],
        "tool_choice": "auto",
    },
}

ws.send(json.dumps(event))

// [中文] 定义会话启动配置,区分Live语音模型与委派后端设置;配置对象本身不会建立连接、执行工具或自动运行后端。
// [中文] 本段为配置或调用片段,需结合外层程序与已建立连接使用;不作为独立完整程序宣称编译通过。
if err := conn.Send(ctx, realtime.RealtimeClientEventParamOfSessionUpdate(realtime.RealtimeSessionCreateRequestParam{
    Model: "gpt-realtime-2.1",
    ToolChoice: realtime.RealtimeToolChoiceConfigUnionParam{
        OfToolChoiceMode: param.NewOpt[responses.ToolChoiceOptions]("auto"),
    },
    Tools: realtime.RealtimeToolsConfigParam{
        realtime.RealtimeToolsConfigUnionParam{
            OfFunction: &realtime.RealtimeFunctionToolParam{
                Description: openai.String("Look up an order by its order number."),
                Name:        openai.String("lookup_order"),
                Parameters: map[string]any{
                    "properties": map[string]any{
                        "order_number": map[string]any{
                            "description": "The customer-facing order number.",
                            "type":        "string",
                        },
                    },
                    "required": []any{"order_number"},
                    "type":     "object",
                },
                Type: "function",
            },
        },
    },
})); err != nil {
    return err
}

来源示例 3(java):

沿用程序文字译释78。

沿用程序文字译释79。

// [中文] 示例 3:配置函数工具;以下保留本语言原始示例。
// [中文] 原代码明确设置的模型值:gpt-realtime-2.1;各值的作用按其所在配置对象区分。
// [中文] 沿原示例执行这些方法:connection.send;异步调用及事件接收顺序保留。
import com.openai.client.okhttp.OkHttpClient;
import com.openai.core.ClientOptions;
import com.openai.core.JsonValue;
import com.openai.helpers.RealtimeConnection;
import com.openai.helpers.RealtimeWebSocketOptions;
import com.openai.models.realtime.*;
import java.util.List;
import java.util.Map;

connection.send(
    RealtimeClientEvent.ofSessionUpdate(
        SessionUpdateEvent.builder()
            .session(
                RealtimeSessionCreateRequest.builder()
                    .model("gpt-realtime-2.1")
                    .addTool(
                        RealtimeFunctionTool.builder()
                            .type(RealtimeFunctionTool.Type.FUNCTION)
                            .name("lookup_order")
                            .description("Look up an order by its order number.")
                            .parameters(
                                JsonValue.from(
                                    Map.of(
                                        "type",
                                        "object",
                                        "properties",
                                        Map.of(
                                            "order_number",
                                            Map.of(
                                                "type",
                                                "string",
                                                "description",
                                                "The customer-facing order number.")),
                                        "required",
                                        List.of("order_number"))))
                            .build())
                    .toolChoice(com.openai.models.responses.ToolChoiceOptions.AUTO)
                    .build())
            .build()));

来源示例 4(csharp):

沿用程序文字译释78。

沿用程序文字译释79。

// [中文] 示例 4:配置函数工具;以下保留本语言原始示例。
// [中文] 原代码明确设置的模型值:gpt-realtime-2.1;各值的作用按其所在配置对象区分。
// [中文] 沿原示例执行这些方法:session.SendCommandAsync;异步调用及事件接收顺序保留。
using OpenAI.Realtime;

#pragma warning disable OPENAI002

await session.SendCommandAsync(new RealtimeClientCommandSessionUpdate(new RealtimeConversationSessionOptions
{
    Model = "gpt-realtime-2.1",
    Tools =
    {
        new RealtimeFunctionTool("lookup_order")
        {
            FunctionDescription = "Look up an order by its order number.",
            FunctionParameters = BinaryData.FromObjectAsJson(new { type = "object", properties = new { order_number = new { type = "string", description = "The customer-facing order number." } }, required = (string[])["order_number"] })
        }
    },
    ToolChoice = RealtimeDefaultToolChoice.Auto
}), timeout.Token);

来源示例 5(ruby):

沿用程序文字译释78。

沿用程序文字译释79。

## [中文] 定义会话启动配置,区分Live语音模型与委派后端设置;配置对象本身不会建立连接、执行工具或自动运行后端。
connection.session.update(
  type: :realtime,
  model: "gpt-realtime-2.1",
  tools: [
    {
      type: :function,
      name: "lookup_order",
      description: "Look up an order by its order number.",
      parameters: {
        type: "object",
        properties: {
          order_number: {
            type: "string",
            description: "The customer-facing order number."
          }
        },
        required: ["order_number"]
      }
    }
  ],
  tool_choice: :auto
)

updated = connection.find do |event|
  raise event.error.message if event.is_a?(OpenAI::Realtime::RealtimeErrorEvent)

  event.is_a?(OpenAI::Realtime::SessionUpdatedEvent)
end
raise "Connection closed before the session update was acknowledged" unless updated

模型调用时,监听函数调用项、运行应用逻辑,再返回输出:

来源示例 6(javascript):

// [中文] 定义会话启动配置,区分Live语音模型与委派后端设置;配置对象本身不会建立连接、执行工具或自动运行后端。
const event = {
  type: "conversation.item.create",
  item: {
    type: "function_call_output",
    call_id: functionCall.call_id,
    output: JSON.stringify({
      status: "shipped",
      delivery_date: "2026-05-09",
    }),
  },
};

ws.send(JSON.stringify(event));
ws.send(
  JSON.stringify({
    type: "response.create",
    response: { output_modalities: ["text"], tool_choice: "none" },
  })
);

来源示例 7(python):

## [中文] 定义会话启动配置,区分Live语音模型与委派后端设置;配置对象本身不会建立连接、执行工具或自动运行后端。
event = {
    "type": "conversation.item.create",
    "item": {
        "type": "function_call_output",
        "call_id": function_call["call_id"],
        "output": json.dumps(
            {
                "status": "shipped",
                "delivery_date": "2026-05-09",
            }
        ),
    },
}

ws.send(json.dumps(event))
ws.send(
    json.dumps(
        {
            "type": "response.create",
            "response": {"output_modalities": ["text"], "tool_choice": "none"},
        }
    )
)

来源示例 8(java):

// [中文] 定义会话启动配置,区分Live语音模型与委派后端设置;配置对象本身不会建立连接、执行工具或自动运行后端。
// [中文] 本段为配置或调用片段,需结合外层程序与已建立连接使用;不作为独立完整程序宣称编译通过。
// callID comes from the model's function_call item.
if err := conn.Send(ctx, realtime.RealtimeClientEventParamOfConversationItemCreate(realtime.RealtimeConversationItemFunctionCallOutputParam{
    CallID: callID,
    Output: "{\"status\":\"shipped\",\"delivery_date\":\"2026-05-09\"}",
})); err != nil {
    return err
}

if err := conn.Send(ctx, realtime.RealtimeClientEventUnionParam{
    OfResponseCreate: &realtime.ResponseCreateEventParam{
        Response: realtime.RealtimeResponseCreateParams{
            OutputModalities: []string{"text"},
            ToolChoice: realtime.RealtimeResponseCreateParamsToolChoiceUnion{
                OfToolChoiceMode: param.NewOpt[responses.ToolChoiceOptions]("none"),
            },
        },
    },
}); err != nil {
    return err
}

来源示例 9(csharp):

// [中文] 定义会话启动配置,区分Live语音模型与委派后端设置;配置对象本身不会建立连接、执行工具或自动运行后端。
// [中文] 本段为配置或调用片段,需结合外层程序与已建立连接使用;不作为独立完整程序宣称编译通过。
import com.openai.client.okhttp.OkHttpClient;
import com.openai.core.ClientOptions;
import com.openai.core.JsonMissing;
import com.openai.core.JsonValue;
import com.openai.helpers.RealtimeConnection;
import com.openai.helpers.RealtimeWebSocketOptions;
import com.openai.models.realtime.*;
import com.openai.models.responses.ToolChoiceFunction;
import com.openai.models.responses.ToolChoiceOptions;
import java.util.Map;

static void sendFunctionCallOutput(RealtimeConnection connection, String callId)
    throws Exception {
  send(
      connection,
      RealtimeClientEvent.ofConversationItemCreate(
          ConversationItemCreateEvent.builder()
              .item(
                  RealtimeConversationItemFunctionCallOutput.builder()
                      .object_(JsonMissing.of())
                      .callId(callId)
                      .output("{\"status\":\"shipped\",\"delivery_date\":\"2026-05-09\"}")
                      .build())
              .build()));
  send(
      connection,
      RealtimeClientEvent.ofResponseCreate(
          ResponseCreateEvent.builder()
              .response(
                  RealtimeResponseCreateParams.builder()
                      .metadata(
                          RealtimeResponseCreateParams.Metadata.builder()
                              .putAdditionalProperty(
                                  "topic", JsonValue.from("lookup_order_followup"))
                              .build())
                      .addOutputModality(RealtimeResponseCreateParams.OutputModality.TEXT)
                      .toolChoice(ToolChoiceOptions.NONE)
                      .build())
              .build()));
}

// Retry only explicit admission rejections; these guarantee nothing was sent.
private static void send(RealtimeConnection connection, RealtimeClientEvent event)
    throws Exception {
  long deadline = System.nanoTime() + java.util.concurrent.TimeUnit.SECONDS.toNanos(5);
  while (true) {
    try {
      connection.send(event);
      return;
    } catch (com.openai.core.http.WebSocketWriteNotAttempted.Busy busy) {
      if (System.nanoTime() >= deadline) throw busy;
      Thread.sleep(10);
    }
  }
}

来源示例 10(ruby):

// [中文] 定义会话启动配置,区分Live语音模型与委派后端设置;配置对象本身不会建立连接、执行工具或自动运行后端。
using OpenAI.Realtime;

#pragma warning disable OPENAI002

internal static async Task SendFunctionCallOutputAsync(RealtimeSessionClient session, string callId, CancellationToken cancellationToken)
{
    string output = System.Text.Json.JsonSerializer.Serialize(new { status = "shipped", delivery_date = "2026-05-09" });
    await session.SendCommandAsync(new RealtimeClientCommandConversationItemCreate(new RealtimeFunctionCallOutputItem(callId, output)), cancellationToken);
    await session.SendCommandAsync(new RealtimeClientCommandResponseCreate
    {
        ResponseOptions = new()
        {
            OutputModalities = { RealtimeOutputModality.Text },
            Metadata = new Dictionary<string, BinaryData> { ["topic"] = BinaryData.FromObjectAsJson("lookup_order_followup") },
            ToolChoice = RealtimeDefaultToolChoice.None
        }
    }, cancellationToken);
}

## [中文] 定义会话启动配置,区分Live语音模型与委派后端设置;配置对象本身不会建立连接、执行工具或自动运行后端。
connection.conversation.items.create(
  type: :function_call_output,
  call_id: call_id,
  output: JSON.generate(status: "shipped", delivery_date: "2026-05-09")
)
connection.response.create(output_modalities: [:text], tool_choice: :none)

逐事件的完整流程见管理对话。

配置 MCP 工具

工具已由远程 MCP 服务器提供,或既有模型使用旧内置连接器时,可使用 MCP。与函数工具不同,MCP 工具由 Realtime API 自身执行。

Realtime MCP 工具结构包含:

  • type: "mcp"。
  • server_label。
  • server_url 或 connector_id 之一。
  • 可选 authorization、headers。
  • 可选 allowed_tools。
  • 可选 require_approval。
  • 可选 server_description。

以下为整个会话提供文档 MCP 服务器:

来源示例 11(javascript):

// [中文] 示例 11:配置 MCP 工具;以下保留本语言原始示例。
// [中文] 原代码明确设置的模型值:gpt-realtime-2.1;各值的作用按其所在配置对象区分。
// [中文] 本段构造的事件类型:session.update;不要将构造载荷等同于收到成功确认。
// [中文] 沿原示例执行这些方法:ws.send;异步调用及事件接收顺序保留。
const event = {
  type: "session.update",
  session: {
    type: "realtime",
    model: "gpt-realtime-2.1",
    output_modalities: ["text"],
    tools: [
      {
        type: "mcp",
        server_label: "openai_docs",
        server_url: "https://developers.openai.com/mcp",
        allowed_tools: ["search_openai_docs", "fetch_openai_doc"],
        require_approval: "never",
      },
    ],
  },
};

ws.send(JSON.stringify(event));

来源示例 12(python):

## [中文] 示例 12:配置 MCP 工具;以下保留本语言原始示例。
## [中文] 本段构造的事件类型:session.update;不要将构造载荷等同于收到成功确认。
## [中文] 沿原示例执行这些方法:ws.send;异步调用及事件接收顺序保留。
event = {
    "type": "session.update",
    "session": {
        "type": "realtime",
        "model": "gpt-realtime-2.1",
        "output_modalities": ["text"],
        "tools": [
            {
                "type": "mcp",
                "server_label": "openai_docs",
                "server_url": "https://developers.openai.com/mcp",
                "allowed_tools": ["search_openai_docs", "fetch_openai_doc"],
                "require_approval": "never",
            }
        ],
    },
}

ws.send(json.dumps(event))

// [中文] 定义会话启动配置,区分Live语音模型与委派后端设置;配置对象本身不会建立连接、执行工具或自动运行后端。
// [中文] 本段为配置或调用片段,需结合外层程序与已建立连接使用;不作为独立完整程序宣称编译通过。
if err := conn.Send(ctx, realtime.RealtimeClientEventParamOfSessionUpdate(realtime.RealtimeSessionCreateRequestParam{
    Model:            "gpt-realtime-2.1",
    OutputModalities: []string{"text"},
    Tools: realtime.RealtimeToolsConfigParam{
        {
            OfMcp: &realtime.RealtimeToolsConfigUnionMcpParam{
                ServerLabel: "openai_docs",
                ServerURL:   openai.String("https://developers.openai.com/mcp"),
                AllowedTools: realtime.RealtimeToolsConfigUnionMcpAllowedToolsParam{
                    OfMcpAllowedTools: []string{"search_openai_docs", "fetch_openai_doc"},
                },
                RequireApproval: realtime.RealtimeToolsConfigUnionMcpRequireApprovalParam{
                    OfMcpToolApprovalSetting: openai.String("never"),
                },
            },
        },
    },
})); err != nil {
    return err
}

来源示例 13(java):

// [中文] 示例 13:配置 MCP 工具;以下保留本语言原始示例。
// [中文] 原代码明确设置的模型值:gpt-realtime-2.1;各值的作用按其所在配置对象区分。
// [中文] 沿原示例执行这些方法:connection.send;异步调用及事件接收顺序保留。
import com.openai.client.okhttp.OkHttpClient;
import com.openai.core.ClientOptions;
import com.openai.helpers.RealtimeConnection;
import com.openai.helpers.RealtimeWebSocketOptions;
import com.openai.models.realtime.*;
import java.util.List;

connection.send(
    RealtimeClientEvent.ofSessionUpdate(
        SessionUpdateEvent.builder()
            .session(
                RealtimeSessionCreateRequest.builder()
                    .model("gpt-realtime-2.1")
                    .addOutputModality(RealtimeSessionCreateRequest.OutputModality.TEXT)
                    .addTool(
                        RealtimeToolsConfigUnion.Mcp.builder()
                            .serverLabel("openai_docs")
                            .serverUrl("https://developers.openai.com/mcp")
                            .allowedToolsOfMcp(
                                List.of("search_openai_docs", "fetch_openai_doc"))
                            .requireApproval(
                                RealtimeToolsConfigUnion.Mcp.RequireApproval
                                    .McpToolApprovalSetting.NEVER)
                            .build())
                    .build())
            .build()));

来源示例 14(csharp):

// [中文] 示例 14:配置 MCP 工具;以下保留本语言原始示例。
// [中文] 原代码明确设置的模型值:gpt-realtime-2.1;各值的作用按其所在配置对象区分。
// [中文] 沿原示例执行这些方法:session.SendCommandAsync;异步调用及事件接收顺序保留。
using OpenAI.Realtime;

#pragma warning disable OPENAI002

await session.SendCommandAsync(new RealtimeClientCommandSessionUpdate(new RealtimeConversationSessionOptions
{
    Model = "gpt-realtime-2.1",
    OutputModalities =
    {
        RealtimeOutputModality.Text
    },
    Tools =
    {
        new RealtimeMcpTool("openai_docs", new Uri("https://developers.openai.com/mcp"))
        {
            AllowedTools = new()
            {
                ToolNames =
                {
                    "search_openai_docs",
                    "fetch_openai_doc"
                }
            },
            ToolCallApprovalPolicy = RealtimeDefaultMcpToolCallApprovalPolicy.NeverRequireApproval
        }
    }
}), timeout.Token);

来源示例 15(ruby):

## [中文] 示例 15:配置 MCP 工具;以下保留本语言原始示例。
## [中文] 原代码明确设置的模型值:gpt-realtime-2.1;各值的作用按其所在配置对象区分。
## [中文] 沿原示例执行这些方法:connection.session.update;异步调用及事件接收顺序保留。
connection.session.update(
  type: :realtime,
  model: "gpt-realtime-2.1",
  output_modalities: [:text],
  tools: [
    {
      type: :mcp,
      server_label: "openai_docs",
      server_url: "https://developers.openai.com/mcp",
      allowed_tools: ["search_openai_docs", "fetch_openai_doc"],
      require_approval: :never
    }
  ]
)

旧版连接器

对 2026年9月1日之后发布的模型,connector_id 已弃用。远程 MCP 使用 server_url,通过安全 MCP 隧道连接本地服务器使用 tunnel_id。既有模型保留连接器支持,下例的 gpt-realtime-1.5 发布于该日期之前。

内置连接器采用同样 MCP 结构,只把 server_url 换为 connector_id。例如 Google Calendar 使用 connector_googlecalendar。Realtime 中,这些内置连接器用于搜索、读取事件或邮件等读取操作。把用户 OAuth 访问令牌放在 authorization,尽可能用 allowed_tools 限定工具范围:

来源示例 16(javascript):

// [中文] 示例 16:旧版连接器;以下保留本语言原始示例。
// [中文] 原代码明确设置的模型值:gpt-realtime-1.5;各值的作用按其所在配置对象区分。
// [中文] 本段构造的事件类型:session.update;不要将构造载荷等同于收到成功确认。
// [中文] 沿原示例执行这些方法:ws.send;异步调用及事件接收顺序保留。
const event = {
  type: "session.update",
  session: {
    type: "realtime",
    model: "gpt-realtime-1.5",
    output_modalities: ["text"],
    tools: [
      {
        type: "mcp",
        server_label: "google_calendar",
        connector_id: "connector_googlecalendar",
        authorization: "<google-oauth-access-token>",
        allowed_tools: ["search_events", "read_event"],
        require_approval: "never",
      },
    ],
  },
};

ws.send(JSON.stringify(event));

来源示例 17(python):

## [中文] 示例 17:旧版连接器;以下保留本语言原始示例。
## [中文] 本段构造的事件类型:session.update;不要将构造载荷等同于收到成功确认。
## [中文] 沿原示例执行这些方法:ws.send;异步调用及事件接收顺序保留。
import os

connector_authorization = os.environ["OPENAI_CONNECTOR_AUTHORIZATION"]

event = {
    "type": "session.update",
    "session": {
        "type": "realtime",
        "model": "gpt-realtime-1.5",
        "output_modalities": ["text"],
        "tools": [
            {
                "type": "mcp",
                "server_label": "google_calendar",
                "connector_id": "connector_googlecalendar",
                "authorization": connector_authorization,
                "allowed_tools": ["search_events", "read_event"],
                "require_approval": "never",
            }
        ],
    },
}

ws.send(json.dumps(event))

// [中文] 保留原例中客户端、输入和返回值的处理顺序;本段需结合所在小节的连接前提使用,未通过真实API调用验证。
// [中文] 本段为配置或调用片段,需结合外层程序与已建立连接使用;不作为独立完整程序宣称编译通过。
accessToken := os.Getenv("OPENAI_MCP_ACCESS_TOKEN")
if accessToken == "" {
    return fmt.Errorf("OPENAI_MCP_ACCESS_TOKEN is required")
}

if err := conn.Send(ctx, realtime.RealtimeClientEventParamOfSessionUpdate(realtime.RealtimeSessionCreateRequestParam{
    Model:            "gpt-realtime-1.5",
    OutputModalities: []string{"text"},
    Tools: realtime.RealtimeToolsConfigParam{
        {
            OfMcp: &realtime.RealtimeToolsConfigUnionMcpParam{
                ServerLabel:   "google_calendar",
                ConnectorID:   "connector_googlecalendar",
                Authorization: param.NewOpt(accessToken),
                AllowedTools: realtime.RealtimeToolsConfigUnionMcpAllowedToolsParam{
                    OfMcpAllowedTools: []string{"search_events", "read_event"},
                },
                RequireApproval: realtime.RealtimeToolsConfigUnionMcpRequireApprovalParam{
                    OfMcpToolApprovalSetting: openai.String("never"),
                },
            },
        },
    },
})); err != nil {
    return err
}

来源示例 18(java):

// [中文] 示例 18:旧版连接器;以下保留本语言原始示例。
// [中文] 原代码明确设置的模型值:gpt-realtime-1.5;各值的作用按其所在配置对象区分。
// [中文] 沿原示例执行这些方法:connection.send;异步调用及事件接收顺序保留。
import com.openai.client.okhttp.OkHttpClient;
import com.openai.core.ClientOptions;
import com.openai.helpers.RealtimeConnection;
import com.openai.helpers.RealtimeWebSocketOptions;
import com.openai.models.realtime.*;
import java.util.List;

connection.send(
    RealtimeClientEvent.ofSessionUpdate(
        SessionUpdateEvent.builder()
            .session(
                RealtimeSessionCreateRequest.builder()
                    .model("gpt-realtime-1.5")
                    .addOutputModality(RealtimeSessionCreateRequest.OutputModality.TEXT)
                    .addTool(
                        RealtimeToolsConfigUnion.Mcp.builder()
                            .serverLabel("google_calendar")
                            .connectorId(
                                RealtimeToolsConfigUnion.Mcp.ConnectorId
                                    .CONNECTOR_GOOGLECALENDAR)
                            .authorization(System.getenv("OPENAI_CONNECTOR_AUTHORIZATION"))
                            .allowedToolsOfMcp(List.of("search_events", "read_event"))
                            .requireApproval(
                                RealtimeToolsConfigUnion.Mcp.RequireApproval
                                    .McpToolApprovalSetting.NEVER)
                            .build())
                    .build())
            .build()));

来源示例 19(csharp):

// [中文] 示例 19:旧版连接器;以下保留本语言原始示例。
// [中文] 原代码明确设置的模型值:gpt-realtime-1.5;各值的作用按其所在配置对象区分。
// [中文] 沿原示例执行这些方法:session.SendCommandAsync;异步调用及事件接收顺序保留。
using OpenAI.Realtime;

#pragma warning disable OPENAI002

await session.SendCommandAsync(new RealtimeClientCommandSessionUpdate(new RealtimeConversationSessionOptions
{
    Model = "gpt-realtime-1.5",
    OutputModalities =
    {
        RealtimeOutputModality.Text
    },
    Tools =
    {
        new RealtimeMcpTool("google_calendar", RealtimeMcpToolConnectorId.GoogleCalendar)
        {
            AuthorizationToken = Environment.GetEnvironmentVariable("OPENAI_CONNECTOR_AUTHORIZATION")!,
            AllowedTools = new()
            {
                ToolNames =
                {
                    "search_events",
                    "read_event"
                }
            },
            ToolCallApprovalPolicy = RealtimeDefaultMcpToolCallApprovalPolicy.NeverRequireApproval
        }
    }
}), timeout.Token);

来源示例 20(ruby):

## [中文] 示例 20:旧版连接器;以下保留本语言原始示例。
## [中文] 原代码明确设置的模型值:gpt-realtime-1.5;各值的作用按其所在配置对象区分。
## [中文] 沿原示例执行这些方法:connection.session.update;异步调用及事件接收顺序保留。
access_token = ENV.fetch("OPENAI_MCP_ACCESS_TOKEN")

connection.session.update(
  type: :realtime,
  model: "gpt-realtime-1.5",
  output_modalities: [:text],
  tools: [
    {
      type: :mcp,
      server_label: "google_calendar",
      connector_id: "connector_googlecalendar",
      authorization: access_token,
      allowed_tools: ["search_events", "read_event"],
      require_approval: :never
    }
  ]
)

远程 MCP 不会自动收到完整对话上下文,但能看到模型在工具调用中发送的任何数据。应通过 allowed_tools 缩小工具范围,并为不应自动运行的操作要求批准。

Realtime MCP 流程

远程 MCP 由 Realtime API 本身执行。客户端不运行远程工具,也不返回 function_call_output;它负责配置访问、监听生命周期事件,并在请求时回复批准。

典型流程如下:

  1. 发送 session.update 或 response.create,其中 tools 包含 type: "mcp"。
  2. 服务器开始导入工具,发出 mcp_list_tools.in_progress。
  3. 列表仍在加载时,模型不能调用尚未载入的工具。依赖这些工具的轮次可等待 mcp_list_tools.completed。item.type: "mcp_list_tools" 的 conversation.item.done 表明实际导入的工具名;失败则收到 mcp_list_tools.failed。
  4. 用户讲话或发文字后,由客户端或会话配置创建响应。
  5. 模型选择 MCP 工具时,发出 response.mcp_call_arguments.delta 和 response.mcp_call_arguments.done。
  6. 需要批准时,服务器添加 mcp_approval_request 对话项,客户端必须用 mcp_approval_response 回答。
  7. 执行工具时收到 response.mcp_call.in_progress。成功后收到 item.type: "mcp_call" 的 response.output_item.done;失败则为 response.mcp_call.failed。
  8. response.done 可能早于 MCP 调用结束。响应和它的全部 MCP 调用都完成后,再发送 response.create,让模型使用结果并继续对话。若又产生 MCP 调用,重复该步骤。Realtime API 不会自动创建这些后续响应。

以下处理器只记录主要 MCP 生命周期事件,不管理后续响应:

来源示例 21(javascript):

程序文字译释80:正在为该项目列出MCP工具。

程序文字译释81:该项目MCP工具列表加载完成。

程序文字译释82:该项目MCP工具列表加载失败。

程序文字译释83:所示服务器的MCP工具已就绪,后接工具名称。

程序文字译释84:以下操作需要批准。

程序文字译释85:MCP调用的最终参数。

程序文字译释86:正在为该项目执行MCP工具。

程序文字译释87:该项目MCP调用失败。

程序文字译释88:显示指定服务器和工具的MCP输出。

程序文字译释89:Realtime轮次完成。

// [中文] 示例 21:Realtime MCP 流程;以下保留本语言原始示例。
// [中文] 沿原示例执行这些方法:ws.on;异步调用及事件接收顺序保留。
function parseRealtimeEvent(rawMessage) {
  if (typeof rawMessage === "string") {
    return JSON.parse(rawMessage);
  }

  if (typeof rawMessage?.data === "string") {
    return JSON.parse(rawMessage.data);
  }

  return JSON.parse(rawMessage.toString());
}

function getOutputText(item) {
  if (item.type !== "message") return "";

  return (item.content ?? [])
    .filter((part) => part.type === "output_text")
    .map((part) => part.text)
    .join("");
}

ws.on("message", (rawMessage) => {
  const event = parseRealtimeEvent(rawMessage);

  switch (event.type) {
    case "mcp_list_tools.in_progress":
      console.log("Listing MCP tools for item:", event.item_id);
      break;

    case "mcp_list_tools.completed":
      console.log("MCP tool listing complete for item:", event.item_id);
      break;

    case "mcp_list_tools.failed":
      console.error("MCP tool listing failed for item:", event.item_id);
      break;

    case "conversation.item.done":
      if (event.item.type === "mcp_list_tools") {
        const names = event.item.tools.map((tool) => tool.name).join(", ");
        console.log(`MCP tools ready on ${event.item.server_label}: ${names}`);
      }

      if (event.item.type === "mcp_approval_request") {
        console.log(
          "Approval required for:",
          event.item.name,
          event.item.arguments
        );
      }
      break;

    case "response.mcp_call_arguments.done":
      console.log("Final MCP call arguments:", event.arguments);
      break;

    case "response.mcp_call.in_progress":
      console.log("Running MCP tool for item:", event.item_id);
      break;

    case "response.mcp_call.failed":
      console.error("MCP tool call failed for item:", event.item_id);
      break;

    case "response.output_item.done":
      if (event.item.type === "mcp_call") {
        console.log(
          `MCP output from ${event.item.server_label}.${event.item.name}:`,
          event.item.output
        );
      }

      if (event.item.type === "message") {
        console.log("Assistant:", getOutputText(event.item));
      }
      break;

    case "response.done":
      console.log("Realtime turn complete.");
      break;
  }
});

来源示例 22(python):

沿用程序文字译释80。

沿用程序文字译释81。

沿用程序文字译释82。

沿用程序文字译释84。

沿用程序文字译释85。

沿用程序文字译释86。

沿用程序文字译释87。

沿用程序文字译释89。

程序文字译释90:所示服务器的MCP工具已就绪,后接名称。

程序文字译释91:显示指定服务器与工具的输出。

## [中文] 示例 22:Realtime MCP 流程;以下保留本语言原始示例。
## [中文] 按事件类型记录 MCP 工具列表的导入进度、完成或失败,以及批准请求、最终参数与调用结果。
## [中文] conversation.item.done 中读取实际导入的工具名;response.output_item.done 中分别处理 mcp_call 结果和助手文字。
## [中文] 此处理器只记录事件,不提交批准、不执行远程工具,也不自动发送后续 response.create;续接由外层工作流负责。
def on_message(ws, message):
    event = json.loads(message)
    event_type = event["type"]

    if event_type == "mcp_list_tools.in_progress":
        print("Listing MCP tools for item:", event["item_id"])
        return

    if event_type == "mcp_list_tools.completed":
        print("MCP tool listing complete for item:", event["item_id"])
        return

    if event_type == "mcp_list_tools.failed":
        print("MCP tool listing failed for item:", event["item_id"])
        return

    if event_type == "conversation.item.done":
        item = event["item"]

        if item["type"] == "mcp_list_tools":
            names = ", ".join(tool["name"] for tool in item["tools"])
            print(f"MCP tools ready on {item['server_label']}: {names}")
            return

        if item["type"] == "mcp_approval_request":
            print("Approval required for:", item["name"], item["arguments"])
            return

    if event_type == "response.mcp_call_arguments.done":
        print("Final MCP call arguments:", event["arguments"])
        return

    if event_type == "response.mcp_call.in_progress":
        print("Running MCP tool for item:", event["item_id"])
        return

    if event_type == "response.mcp_call.failed":
        print("MCP tool call failed for item:", event["item_id"])
        return

    if event_type == "response.output_item.done":
        item = event["item"]

        if item["type"] == "mcp_call":
            print(
                f"MCP output from {item['server_label']}.{item['name']}:",
                item.get("output"),
            )
            return

        if item["type"] == "message":
            text_parts = [
                part["text"]
                for part in item.get("content", [])
                if part["type"] == "output_text"
            ]
            print("Assistant:", "".join(text_parts))
            return

    if event_type == "response.done":
        print("Realtime turn complete.")

来源示例 23(ruby):

沿用程序文字译释89。

程序文字译释92:正在列出该项目MCP工具。

程序文字译释93:该项目MCP工具加载失败。

程序文字译释94:该项目MCP工具已就绪。

程序文字译释95:浏览器客户端应使用哪种Realtime API传输方式?

程序文字译释96:所示服务器的MCP工具已就绪。

程序文字译释97:需要批准,显示工具名与参数。

程序文字译释98:MCP最终调用参数。

程序文字译释99:正在执行该项目MCP工具。

程序文字译释100:MCP工具调用完成。

程序文字译释101:MCP工具调用失败。

程序文字译释102:显示服务器、工具名及工具输出。

程序文字译释103:Realtime API错误,后接错误消息。

// [中文] 保留原例中客户端、输入和返回值的处理顺序;本段需结合所在小节的连接前提使用,未通过真实API调用验证。
// [中文] 本段为配置或调用片段,需结合外层程序与已建立连接使用;不作为独立完整程序宣称编译通过。
// Call for each received event. Tool results can arrive after response.done.
func logMCPEvent(event realtime.RealtimeServerEventUnion) error {
    switch e := event.AsAny().(type) {
    case realtime.RealtimeErrorEvent:
        return fmt.Errorf("Realtime API error: %s", e.Error.Message)
    case realtime.McpListToolsFailed, realtime.ResponseMcpCallFailed:
        return fmt.Errorf("MCP failed: %s", event.Type)
    case realtime.ResponseOutputItemDoneEvent:
        item := e.Item.OfRealtimeMcpToolCall
        if item.Type == "mcp_call" {
            if item.JSON.Error.Valid() || !item.JSON.Output.Valid() {
                return fmt.Errorf("MCP call failed or has no output")
            }
            fmt.Fprintln(log.Writer(), "Tool output:", item.Output)
        }
    }
    return nil
}

常见失败

  • mcp_list_tools.failed:无法从远程服务器或连接器导入工具。检查 server_url、connector_id、认证、连通性及 allowed_tools 中的名称。
  • response.mcp_call.failed:模型选中了工具,但调用未完成。检查事件载荷与后续 mcp_call 项目中的 MCP 协议、执行或传输错误。
  • mcp_approval_request 没有匹配 mcp_approval_response:客户端明确批准或拒绝前无法继续。
  • mcp_list_tools.in_progress 仍活动时开启轮次:该轮只能使用已加载完成的工具。
  • tool_choice: "required" 但当前无工具可用:模型无可调用项。等待 mcp_list_tools.completed,确认至少导入一个工具,或为无需工具的轮次改用其他 tool_choice。
  • 导入前工具定义验证失败:常见原因是同一 tools 数组出现重复 server_label,同时设置 server_url 和 connector_id,首次创建会话时两者都没提供,connector_id 无效,或同时发送 authorization 和 headers.Authorization。内置连接器完全不应发送 headers.Authorization。

批准或拒绝 MCP 调用

需要批准时,Realtime API 插入 mcp_approval_request。要继续,发送新的 conversation.item.create,将 item.type 设为 mcp_approval_response。

批准请求:

来源示例 24(javascript):

## [中文] 显式请求创建或继续响应,使用本段实际设置的模态、上下文与工具字段;发送请求不等同于收到完成事件。
completed_events = {}
expected_calls = []
completed_calls = {}
complete = connection.find do |event|
  case event
  when OpenAI::Realtime::McpListToolsInProgress
    puts("Listing MCP tools for item: #{event.item_id}")
  when OpenAI::Realtime::McpListToolsFailed
    raise "MCP tool listing failed for item: #{event.item_id}"
  when OpenAI::Realtime::McpListToolsCompleted
    puts("MCP tools ready for item: #{event.item_id}")
    connection.response.create(
      output_modalities: [:text],
      input: [
        {
          type: :message,
          role: :user,
          content: [
            {
              type: :input_text,
              text: "Which Realtime API transport should browser clients use?"
            }
          ]
        }
      ],
      tool_choice: :required,
      parallel_tool_calls: false
    )
  when OpenAI::Realtime::ConversationItemDone
    item = event.item
    case item
    when OpenAI::Realtime::RealtimeMcpListTools
      names = item.tools.map(&:name).join(", ")
      puts("MCP tools ready on #{item.server_label}: #{names}")
    when OpenAI::Realtime::RealtimeMcpApprovalRequest
      puts("Approval required for: #{item.name} #{item.arguments}")
    end
  when OpenAI::Realtime::ResponseMcpCallArgumentsDone
    puts("Final MCP call arguments: #{event.arguments}")
  when OpenAI::Realtime::ResponseMcpCallInProgress
    puts("Running MCP tool for item: #{event.item_id}")
  when OpenAI::Realtime::ResponseMcpCallCompleted
    puts("MCP tool call completed: #{event.item_id}")
  when OpenAI::Realtime::ResponseMcpCallFailed
    raise "MCP tool call failed: #{event.item_id}"
  when OpenAI::Realtime::ResponseOutputItemDoneEvent
    item = event.item
    case item
    when OpenAI::Realtime::RealtimeMcpToolCall
      raise "MCP tool call failed" if item.error || item.output.nil?

      completed_calls[item.id] = true
      puts("MCP output from #{item.server_label}.#{item.name}: #{item.output}")
    when OpenAI::Realtime::RealtimeConversationItemAssistantMessage
      text = item.content.filter_map do |content|
        content.text if content.type == :output_text
      end.join
      puts("Assistant: #{text}")
    end
  when OpenAI::Realtime::RealtimeErrorEvent
    raise "Realtime API error: #{event.error.message}"
  when OpenAI::Realtime::ResponseDoneEvent
    raise "Realtime response did not complete" unless event.response.status == :completed

    expected_calls.replace(Array(event.response.output).grep(OpenAI::Realtime::RealtimeMcpToolCall).map(&:id))
    raise "The response did not call an MCP tool" if expected_calls.empty?

    completed_events[:response] = true
  end
  if completed_events[:response] && expected_calls.all? { |id| completed_calls[id] }
    puts("Realtime turn complete.")
    true
  else
    false
  end
end
raise "Connection closed before the MCP tool result arrived" unless complete

来源示例 25(python):

// [中文] 保留原例中客户端、输入和返回值的处理顺序;本段需结合所在小节的连接前提使用,未通过真实API调用验证。
function approveMcpRequest(approvalRequestId) {
  const event = {
    type: "conversation.item.create",
    item: {
      type: "mcp_approval_response",
      approval_request_id: approvalRequestId,
      approve: true,
    },
  };

  ws.send(JSON.stringify(event));
}

来源示例 26(java):

## [中文] 按原代码构造或处理这些事件:conversation.item.create、mcp_approval_response;保留请求与服务端确认的区别。
## Use the ID from the received MCP approval-request item.
def approve_mcp_request(ws, approval_request_id):
    event = {
        "type": "conversation.item.create",
        "item": {
            "type": "mcp_approval_response",
            "approval_request_id": approval_request_id,
            "approve": True,
        },
    }

    ws.send(json.dumps(event))

来源示例 27(csharp):

// [中文] 保留原例中客户端、输入和返回值的处理顺序;本段需结合所在小节的连接前提使用,未通过真实API调用验证。
// [中文] 本段为配置或调用片段,需结合外层程序与已建立连接使用;不作为独立完整程序宣称编译通过。
// Call with the approval request received in conversation.item.done.
func approveDocumentationSearch(
    ctx context.Context,
    conn *realtime.RealtimeConnection,
    request realtime.RealtimeMcpApprovalRequest,
) error {
    // This example permits only a read-only search of the OpenAI documentation.
    if request.ID == "" || request.ServerLabel != "openai_docs" || request.Name != "search_openai_docs" {
        return fmt.Errorf("unapproved tool requested")
    }
    // Derive a distinct item ID within the API's 32-character limit.
    approvalID := sha256.Sum256([]byte(request.ID))
    return conn.Send(ctx, realtime.RealtimeClientEventParamOfConversationItemCreate(realtime.RealtimeMcpApprovalResponseParam{
        ID:                fmt.Sprintf("%x", approvalID[:16]),
        ApprovalRequestID: request.ID,
        Approve:           true,
    }))
}

来源示例 28(ruby):

// [中文] 保留原例中客户端、输入和返回值的处理顺序;本段需结合所在小节的连接前提使用,未通过真实API调用验证。
// [中文] 本段为配置或调用片段,需结合外层程序与已建立连接使用;不作为独立完整程序宣称编译通过。
import com.openai.client.okhttp.OkHttpClient;
import com.openai.core.ClientOptions;
import com.openai.core.JsonMissing;
import com.openai.helpers.RealtimeConnection;
import com.openai.helpers.RealtimeWebSocketOptions;
import com.openai.models.realtime.*;
import com.openai.models.responses.ToolChoiceOptions;

// Replace https://mcp.example.com/mcp with your company's MCP server URL.

static void approveMcpRequest(RealtimeConnection connection, String approvalRequestId)
    throws Exception {
  send(
      connection,
      RealtimeClientEvent.ofConversationItemCreate(
          ConversationItemCreateEvent.builder()
              .item(
                  RealtimeMcpApprovalResponse.builder()
                      .id(java.util.UUID.randomUUID().toString().replace("-", ""))
                      .approvalRequestId(approvalRequestId)
                      .approve(true)
                      .build())
              .build()));
}

// Retry only explicit admission rejections; these guarantee nothing was sent.
private static void send(RealtimeConnection connection, RealtimeClientEvent event)
    throws Exception {
  long deadline = System.nanoTime() + java.util.concurrent.TimeUnit.SECONDS.toNanos(5);
  while (true) {
    try {
      connection.send(event);
      return;
    } catch (com.openai.core.http.WebSocketWriteNotAttempted.Busy busy) {
      if (System.nanoTime() >= deadline) throw busy;
      Thread.sleep(10);
    }
  }
}

拒绝时,把 approve 设为 false,并可提供 reason。

只为一次响应提供 MCP

只希望单轮使用 MCP 时,将相同工具对象放到 response.tools,而非 session.tools:

来源示例 29(javascript):

程序文字译释104:在Realtime API中,浏览器客户端应该用哪种传输?

// [中文] 保留原例中客户端、输入和返回值的处理顺序;本段需结合所在小节的连接前提使用,未通过真实API调用验证。
using System.Text.Json;
using OpenAI.Realtime;

#pragma warning disable OPENAI002
// Connect to the official OpenAI documentation MCP server.

internal static async Task ApproveMcpRequestAsync(RealtimeSessionClient session, string approvalRequestId, CancellationToken cancellationToken)
{
    await session.SendCommandAsync(new RealtimeClientCommandConversationItemCreate(new RealtimeMcpToolCallApprovalResponseItem(approvalRequestId, true)
    {
        Id = Guid.NewGuid().ToString("N")
    }), cancellationToken);
}

来源示例 30(python):

沿用程序文字译释104。

## [中文] 保留原例中客户端、输入和返回值的处理顺序;本段需结合所在小节的连接前提使用,未通过真实API调用验证。
## Use the ID from the received MCP approval-request item.
approval_request_id = item.id

connection.conversation.items.create(
  type: :mcp_approval_response,
  id: "approval_#{SecureRandom.hex(8)}",
  approval_request_id: approval_request_id,
  approve: true
)

来源示例 31(java):

沿用程序文字译释104。

// [中文] 显式请求创建或继续响应,使用本段实际设置的模态、上下文与工具字段;发送请求不等同于收到完成事件。
const event = {
  type: "response.create",
  response: {
    output_modalities: ["text"],
    tool_choice: "required",
    parallel_tool_calls: false,
    input: [
      {
        type: "message",
        role: "user",
        content: [
          {
            type: "input_text",
            text: "Which transport should I use for browser clients in the Realtime API?",
          },
        ],
      },
    ],
    tools: [
      {
        type: "mcp",
        server_label: "openai_docs",
        server_url: "https://developers.openai.com/mcp",
        allowed_tools: ["search_openai_docs", "fetch_openai_doc"],
        require_approval: "never",
      },
    ],
  },
};

ws.send(JSON.stringify(event));

来源示例 32(csharp):

沿用程序文字译释104。

## [中文] 显式请求创建或继续响应,使用本段实际设置的模态、上下文与工具字段;发送请求不等同于收到完成事件。
event = {
    "type": "response.create",
    "response": {
        "output_modalities": ["text"],
        "tool_choice": "required",
        "parallel_tool_calls": False,
        "input": [
            {
                "type": "message",
                "role": "user",
                "content": [
                    {
                        "type": "input_text",
                        "text": "Which transport should I use for browser clients in the Realtime API?",
                    }
                ],
            }
        ],
        "tools": [
            {
                "type": "mcp",
                "server_label": "openai_docs",
                "server_url": "https://developers.openai.com/mcp",
                "allowed_tools": ["search_openai_docs", "fetch_openai_doc"],
                "require_approval": "never",
            }
        ],
    },
}

ws.send(json.dumps(event))

来源示例 33(ruby):

沿用程序文字译释95。

// [中文] 显式请求创建或继续响应,使用本段实际设置的模态、上下文与工具字段;发送请求不等同于收到完成事件。
// [中文] 本段为配置或调用片段,需结合外层程序与已建立连接使用;不作为独立完整程序宣称编译通过。
// input contains the conversation items for this response.
if err := conn.Send(ctx, realtime.RealtimeClientEventUnionParam{
    OfResponseCreate: &realtime.ResponseCreateEventParam{
        Response: realtime.RealtimeResponseCreateParams{
            ParallelToolCalls: openai.Bool(false),
            Input:             input,
            OutputModalities:  []string{"text"},
            ToolChoice: realtime.RealtimeResponseCreateParamsToolChoiceUnion{
                OfToolChoiceMode: param.NewOpt[responses.ToolChoiceOptions]("required"),
            },
            Tools: []realtime.RealtimeResponseCreateParamsToolUnion{
                {
                    OfMcp: &realtime.RealtimeResponseCreateMcpToolParam{
                        ServerLabel: "openai_docs",
                        ServerURL:   openai.String("https://developers.openai.com/mcp"),
                        AllowedTools: realtime.RealtimeResponseCreateMcpToolAllowedToolsUnionParam{
                            OfMcpAllowedTools: []string{"search_openai_docs", "fetch_openai_doc"},
                        },
                        RequireApproval: realtime.RealtimeResponseCreateMcpToolRequireApprovalUnionParam{
                            OfMcpToolApprovalSetting: openai.String("never"),
                        },
                    },
                },
            },
        },
    },
}); err != nil {
    return err
}

// [中文] 显式请求创建或继续响应,使用本段实际设置的模态、上下文与工具字段;发送请求不等同于收到完成事件。
// [中文] 本段为配置或调用片段,需结合外层程序与已建立连接使用;不作为独立完整程序宣称编译通过。
import com.openai.client.okhttp.OkHttpClient;
import com.openai.core.ClientOptions;
import com.openai.core.JsonMissing;
import com.openai.helpers.RealtimeConnection;
import com.openai.helpers.RealtimeWebSocketOptions;
import com.openai.models.realtime.*;
import java.util.List;

connection.send(
    RealtimeClientEvent.ofResponseCreate(
        ResponseCreateEvent.builder()
            .response(
                RealtimeResponseCreateParams.builder()
                    .toolChoice(com.openai.models.responses.ToolChoiceOptions.REQUIRED)
                    .parallelToolCalls(false)
                    .metadata(
                        RealtimeResponseCreateParams.Metadata.builder()
                            .putAdditionalProperty(
                                "topic", com.openai.core.JsonValue.from("mcp_initial"))
                            .build())
                    .addOutputModality(RealtimeResponseCreateParams.OutputModality.TEXT)
                    .addInput(
                        RealtimeConversationItemUserMessage.builder()
                            .object_(JsonMissing.of())
                            .addContent(
                                RealtimeConversationItemUserMessage.Content.builder()
                                    .type(
                                        RealtimeConversationItemUserMessage.Content.Type
                                            .INPUT_TEXT)
                                    .text(
                                        "Which transport should I use for browser clients in the Realtime API?")
                                    .build())
                            .build())
                    .addTool(
                        RealtimeResponseCreateMcpTool.builder()
                            .serverLabel("openai_docs")
                            .serverUrl("https://developers.openai.com/mcp")
                            .allowedToolsOfMcp(
                                List.of("search_openai_docs", "fetch_openai_doc"))
                            .requireApproval(
                                RealtimeResponseCreateMcpTool.RequireApproval
                                    .McpToolApprovalSetting.NEVER)
                            .build())
                    .build())
            .build()));

// [中文] 显式请求创建或继续响应,使用本段实际设置的模态、上下文与工具字段;发送请求不等同于收到完成事件。
using System.Text.Json;
using OpenAI.Realtime;

#pragma warning disable OPENAI002

await session.SendCommandAsync(new RealtimeClientCommandResponseCreate
{
    ResponseOptions = new()
    {
        Metadata = new Dictionary<string, BinaryData> { ["topic"] = BinaryData.FromObjectAsJson("mcp_initial") },
        ToolChoice = RealtimeDefaultToolChoice.Required,
        OutputModalities =
        {
            RealtimeOutputModality.Text
        },
        InputItems =
        {
            RealtimeItem.CreateUserMessageItem("Which transport should I use for browser clients in the Realtime API?")
        },
        Tools =
        {
            new RealtimeMcpTool("openai_docs", new Uri("https://developers.openai.com/mcp"))
            {
                AllowedTools = new()
                {
                    ToolNames =
                    {
                        "search_openai_docs",
                        "fetch_openai_doc"
                    }
                },
                ToolCallApprovalPolicy = RealtimeDefaultMcpToolCallApprovalPolicy.NeverRequireApproval
            }
        }
    }
}, timeout.Token);

## [中文] 显式请求创建或继续响应,使用本段实际设置的模态、上下文与工具字段;发送请求不等同于收到完成事件。
connection.response.create(
  output_modalities: [:text],
  tool_choice: :required,
  parallel_tool_calls: false,
  input: [
    {
      type: :message,
      role: :user,
      content: [
        {
          type: :input_text,
          text: "Which Realtime API transport should browser clients use?"
        }
      ]
    }
  ],
  tools: [
    {
      type: :mcp,
      server_label: "openai_docs",
      server_url: "https://developers.openai.com/mcp",
      allowed_tools: ["search_openai_docs", "fetch_openai_doc"],
      require_approval: :never
    }
  ]
)

适用于仅一个响应需要外部上下文,或不同轮次应使用不同服务器的情形。

复用已定义的服务器标签

server_label 是当前 Realtime 会话中工具定义的稳定标识。首次用 server_label 加 server_url 或 connector_id 定义后,后续 session.update、response.create 可只引用同一标签,API 会复用定义,无需重发完整工具对象。

复用既有连接器:

来源示例 34(javascript):

程序文字译释105:查看我今天下午的日程。

// [中文] 示例 34:复用已定义的服务器标签;以下保留本语言原始示例。
// [中文] 本段构造的事件类型:response.create;不要将构造载荷等同于收到成功确认。
// [中文] 沿原示例执行这些方法:ws.send;异步调用及事件接收顺序保留。
const event = {
  type: "response.create",
  response: {
    output_modalities: ["text"],
    input: [
      {
        type: "message",
        role: "user",
        content: [
          {
            type: "input_text",
            text: "Check my schedule for this afternoon.",
          },
        ],
      },
    ],
    // Reuses the google_calendar connector defined earlier in this session.
    tools: [
      {
        type: "mcp",
        server_label: "google_calendar",
      },
    ],
  },
};

ws.send(JSON.stringify(event));

来源示例 35(python):

沿用程序文字译释105。

## [中文] 示例 35:复用已定义的服务器标签;以下保留本语言原始示例。
## [中文] 本段构造的事件类型:response.create;不要将构造载荷等同于收到成功确认。
## [中文] 沿原示例执行这些方法:ws.send;异步调用及事件接收顺序保留。
event = {
    "type": "response.create",
    "response": {
        "output_modalities": ["text"],
        "input": [
            {
                "type": "message",
                "role": "user",
                "content": [
                    {
                        "type": "input_text",
                        "text": "Check my schedule for this afternoon.",
                    }
                ],
            }
        ],
        # Reuses the google_calendar connector defined earlier in this session.
        "tools": [
            {
                "type": "mcp",
                "server_label": "google_calendar",
            }
        ],
    },
}

ws.send(json.dumps(event))

// [中文] 显式请求创建或继续响应,使用本段实际设置的模态、上下文与工具字段;发送请求不等同于收到完成事件。
// [中文] 本段为配置或调用片段,需结合外层程序与已建立连接使用;不作为独立完整程序宣称编译通过。
// input contains the conversation items for this response.
if err := conn.Send(ctx, realtime.RealtimeClientEventUnionParam{
    OfResponseCreate: &realtime.ResponseCreateEventParam{
        Response: realtime.RealtimeResponseCreateParams{
            OutputModalities: []string{"text"},
            Input:            input,
            Tools: []realtime.RealtimeResponseCreateParamsToolUnion{
                {
                    OfMcp: &realtime.RealtimeResponseCreateMcpToolParam{
                        ServerLabel: "google_calendar",
                    },
                },
            },
            ToolChoice: realtime.RealtimeResponseCreateParamsToolChoiceUnion{
                OfToolChoiceMode: param.NewOpt(responses.ToolChoiceOptions("required")),
            },
        },
    },
}); err != nil {
    return err
}

来源示例 36(java):

沿用程序文字译释105。

// [中文] 示例 36:复用已定义的服务器标签;以下保留本语言原始示例。
// [中文] 沿原示例执行这些方法:connection.send;异步调用及事件接收顺序保留。
import com.openai.client.okhttp.OkHttpClient;
import com.openai.core.ClientOptions;
import com.openai.helpers.RealtimeConnection;
import com.openai.helpers.RealtimeWebSocketOptions;
import com.openai.models.realtime.*;
import java.util.List;

send(
    connection,
    RealtimeClientEvent.ofResponseCreate(
        ResponseCreateEvent.builder()
            .response(
                RealtimeResponseCreateParams.builder()
                    .metadata(
                        RealtimeResponseCreateParams.Metadata.builder()
                            .putAdditionalProperty(
                                "topic", com.openai.core.JsonValue.from("mcp_initial"))
                            .build())
                    .addOutputModality(RealtimeResponseCreateParams.OutputModality.TEXT)
                    .addInput(
                        RealtimeConversationItemUserMessage.builder()
                            .addContent(
                                RealtimeConversationItemUserMessage.Content.builder()
                                    .type(
                                        RealtimeConversationItemUserMessage.Content.Type
                                            .INPUT_TEXT)
                                    .text("Check my schedule for this afternoon.")
                                    .build())
                            .build())
                    .addTool(
                        RealtimeResponseCreateMcpTool.builder()
                            .serverLabel("google_calendar")
                            .build())
                    .build())
            .build()));

// Retry only explicit admission rejections; these guarantee nothing was sent.
private static void send(RealtimeConnection connection, RealtimeClientEvent event)
    throws Exception {
  long deadline = System.nanoTime() + java.util.concurrent.TimeUnit.SECONDS.toNanos(5);
  while (true) {
    try {
      connection.send(event);
      return;
    } catch (com.openai.core.http.WebSocketWriteNotAttempted.Busy busy) {
      if (System.nanoTime() >= deadline) throw busy;
      Thread.sleep(10);
    }
  }
}

来源示例 37(csharp):

沿用程序文字译释105。

// [中文] 示例 37:复用已定义的服务器标签;以下保留本语言原始示例。
// [中文] 沿原示例执行这些方法:session.SendCommandAsync;异步调用及事件接收顺序保留。
using OpenAI.Realtime;

#pragma warning disable OPENAI002

await session.SendCommandAsync(new RealtimeClientCommandResponseCreate
{
    ResponseOptions = new()
    {
        Metadata = new Dictionary<string, BinaryData> { ["topic"] = BinaryData.FromObjectAsJson("mcp_initial") },
        OutputModalities =
        {
            RealtimeOutputModality.Text
        },
        InputItems =
        {
            RealtimeItem.CreateUserMessageItem("Check my schedule for this afternoon.")
        },
        Tools =
        {
            new RealtimeMcpTool
            {
                ServerLabel = "google_calendar"
            }
        }
    }
}, timeout.Token);

来源示例 38(ruby):

程序文字译释106:查看今天下午的日程。

## [中文] 示例 38:复用已定义的服务器标签;以下保留本语言原始示例。
## [中文] 沿原示例执行这些方法:connection.response.create;异步调用及事件接收顺序保留。
connection.response.create(
  output_modalities: [:text],
  input: [
    {
      type: :message,
      role: :user,
      content: [
        {
          type: :input_text,
          text: "Check my schedule this afternoon."
        }
      ]
    }
  ],
  tools: [
    {
      type: :mcp,
      server_label: "google_calendar"
    }
  ]
)

复用仅在本会话有效。新建 Realtime 会话后,必须重新发送完整 MCP 定义以导入工具列表。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号