OpenAI Realtime 工具与 MCP
可以向 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;它负责配置访问、监听生命周期事件,并在请求时回复批准。
典型流程如下:
- 发送
session.update或response.create,其中tools包含type: "mcp"。 - 服务器开始导入工具,发出
mcp_list_tools.in_progress。 - 列表仍在加载时,模型不能调用尚未载入的工具。依赖这些工具的轮次可等待
mcp_list_tools.completed。item.type: "mcp_list_tools"的conversation.item.done表明实际导入的工具名;失败则收到mcp_list_tools.failed。 - 用户讲话或发文字后,由客户端或会话配置创建响应。
- 模型选择 MCP 工具时,发出
response.mcp_call_arguments.delta和response.mcp_call_arguments.done。 - 需要批准时,服务器添加
mcp_approval_request对话项,客户端必须用mcp_approval_response回答。 - 执行工具时收到
response.mcp_call.in_progress。成功后收到item.type: "mcp_call"的response.output_item.done;失败则为response.mcp_call.failed。 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 定义以导入工具列表。

TRAE-AI编程


更多建议: