A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 14, 04:15 UTC
[Frontend] [gpt-oss] Mcp type bug (#27689)
Signed-off-by: Jialin Ouyang <Jialin.Ouyang@gmail.com> Signed-off-by: Alec Solder <alecs@fb.com> Signed-off-by: Ye (Charlotte) Qi <yeq@meta.com> Co-authored-by: Jialin Ouyang <Jialin.Ouyang@gmail.com> Co-authored-by: Alec Solder <alecs@fb.com> Co-authored-by: Ye (Charlotte) Qi <yeq@meta.com>
Alec S committed
Oct 29, 2025 at 06:01 UTC
ab2eb27b74da0e6846749c11a68179d27a78d963
7 files changed
+293
-44
tests/entrypoints/openai/test_response_api_mcp_tools.py
+68
-19
@@ -26,6 +26,8 @@ def mcp_disabled_server(monkeypatch_module: pytest.MonkeyPatch):
26
with monkeypatch_module.context() as m:
27
m.setenv("VLLM_ENABLE_RESPONSES_API_STORE", "1")
28
m.setenv("PYTHON_EXECUTION_BACKEND", "dangerously_use_uv")
29
+ # Helps the model follow instructions better
30
+ m.setenv("VLLM_GPT_OSS_HARMONY_SYSTEM_INSTRUCTIONS", "1")
31
with RemoteOpenAIServer(MODEL_NAME, args) as remote_server:
32
yield remote_server
33
@@ -37,7 +39,9 @@ def mcp_enabled_server(monkeypatch_module: pytest.MonkeyPatch):
39
with monkeypatch_module.context() as m:
40
m.setenv("VLLM_ENABLE_RESPONSES_API_STORE", "1")
41
m.setenv("PYTHON_EXECUTION_BACKEND", "dangerously_use_uv")
40
- m.setenv("GPT_OSS_SYSTEM_TOOL_MCP_LABELS", "code_interpreter,container")
42
+ m.setenv("VLLM_GPT_OSS_SYSTEM_TOOL_MCP_LABELS", "code_interpreter,container")
43
+ # Helps the model follow instructions better
44
+ m.setenv("VLLM_GPT_OSS_HARMONY_SYSTEM_INSTRUCTIONS", "1")
45
with RemoteOpenAIServer(MODEL_NAME, args) as remote_server:
46
yield remote_server
47
@@ -56,18 +60,15 @@ async def mcp_enabled_client(mcp_enabled_server):
60
61
@pytest.mark.asyncio
62
@pytest.mark.parametrize("model_name", [MODEL_NAME])
59
-@pytest.mark.skip(reason="Code interpreter tool is not available in CI yet.")
63
async def test_mcp_tool_env_flag_enabled(mcp_enabled_client: OpenAI, model_name: str):
64
response = await mcp_enabled_client.responses.create(
65
model=model_name,
63
- # TODO: Ideally should be able to set max tool calls
64
- # to prevent multi-turn, but it is not currently supported
65
- # would speed up the test
66
input=(
67
- "What's the first 4 digits after the decimal point of "
68
- "cube root of `19910212 * 20250910`? "
69
- "Show only the digits. The python interpreter is not stateful "
70
- "and you must print to see the output."
67
+ "Execute the following code: "
68
+ "import random; print(random.randint(1, 1000000))"
69
+ ),
70
+ instructions=(
71
+ "You must use the Python tool to execute code. Never simulate execution."
72
),
73
tools=[
74
{
@@ -77,26 +78,47 @@ async def test_mcp_tool_env_flag_enabled(mcp_enabled_client: OpenAI, model_name:
78
"server_url": "http://localhost:8888",
79
}
80
],
81
+ extra_body={"enable_response_messages": True},
82
)
83
assert response is not None
84
assert response.status == "completed"
83
- assert response.usage.output_tokens_details.tool_output_tokens > 0
85
+ # Verify output messages: Tool calls and responses on analysis channel
86
+ tool_call_found = False
87
+ tool_response_found = False
88
+ for message in response.output_messages:
89
+ recipient = message.get("recipient")
90
+ if recipient and recipient.startswith("python"):
91
+ tool_call_found = True
92
+ assert message.get("channel") == "analysis", (
93
+ "Tool call should be on analysis channel"
94
+ )
95
+ author = message.get("author", {})
96
+ if (
97
+ author.get("role") == "tool"
98
+ and author.get("name")
99
+ and author.get("name").startswith("python")
100
+ ):
101
+ tool_response_found = True
102
+ assert message.get("channel") == "analysis", (
103
+ "Tool response should be on analysis channel"
104
+ )
105
+
106
+ assert tool_call_found, "Should have found at least one Python tool call"
107
+ assert tool_response_found, "Should have found at least one Python tool response"
108
+ for message in response.input_messages:
109
+ assert message.get("author").get("role") != "developer", (
110
+ "No developer messages should be present with valid mcp tool"
111
+ )
112
113
114
@pytest.mark.asyncio
115
@pytest.mark.parametrize("model_name", [MODEL_NAME])
88
-@pytest.mark.skip(reason="Code interpreter tool is not available in CI yet.")
116
async def test_mcp_tool_env_flag_disabled(mcp_disabled_client: OpenAI, model_name: str):
117
response = await mcp_disabled_client.responses.create(
118
model=model_name,
92
- # TODO: Ideally should be able to set max tool calls
93
- # to prevent multi-turn, but it is not currently supported
94
- # would speed up the test
119
input=(
96
- "What's the first 4 digits after the decimal point of "
97
- "cube root of `19910212 * 20250910`? "
98
- "Show only the digits. The python interpreter is not stateful "
99
- "and you must print to see the output."
120
+ "Execute the following code if the tool is present: "
121
+ "import random; print(random.randint(1, 1000000))"
122
),
123
tools=[
124
{
@@ -106,7 +128,34 @@ async def test_mcp_tool_env_flag_disabled(mcp_disabled_client: OpenAI, model_nam
128
"server_url": "http://localhost:8888",
129
}
130
],
131
+ extra_body={"enable_response_messages": True},
132
)
133
assert response is not None
134
assert response.status == "completed"
112
- assert response.usage.output_tokens_details.tool_output_tokens == 0
135
+ # Verify output messages: No tool calls and responses
136
+ tool_call_found = False
137
+ tool_response_found = False
138
+ for message in response.output_messages:
139
+ recipient = message.get("recipient")
140
+ if recipient and recipient.startswith("python"):
141
+ tool_call_found = True
142
+ assert message.get("channel") == "analysis", (
143
+ "Tool call should be on analysis channel"
144
+ )
145
+ author = message.get("author", {})
146
+ if (
147
+ author.get("role") == "tool"
148
+ and author.get("name")
149
+ and author.get("name").startswith("python")
150
+ ):
151
+ tool_response_found = True
152
+ assert message.get("channel") == "analysis", (
153
+ "Tool response should be on analysis channel"
154
+ )
155
+
156
+ assert not tool_call_found, "Should not have a python call"
157
+ assert not tool_response_found, "Should not have a tool response"
158
+ for message in response.input_messages:
159
+ assert message.get("author").get("role") != "developer", (
160
+ "No developer messages should be present without a valid tool"
161
+ )
tests/entrypoints/openai/test_serving_responses.py
+49
-1
@@ -6,10 +6,19 @@ from unittest.mock import MagicMock
6
7
import pytest
8
import pytest_asyncio
9
+from openai.types.responses.tool import (
10
+ CodeInterpreterContainerCodeInterpreterToolAuto,
11
+ LocalShell,
12
+ Mcp,
13
+ Tool,
14
+)
15
16
from vllm.entrypoints.context import ConversationContext
17
from vllm.entrypoints.openai.protocol import ErrorResponse, ResponsesRequest
12
-from vllm.entrypoints.openai.serving_responses import OpenAIServingResponses
18
+from vllm.entrypoints.openai.serving_responses import (
19
+ OpenAIServingResponses,
20
+ extract_tool_types,
21
+)
22
from vllm.entrypoints.tool_server import ToolServer
23
from vllm.inputs.data import TokensPrompt as EngineTokensPrompt
24
@@ -62,6 +71,45 @@ def mock_exit_stack():
71
return MagicMock(spec=AsyncExitStack)
72
73
74
+def test_extract_tool_types(monkeypatch: pytest.MonkeyPatch) -> None:
75
+ tools: list[Tool] = []
76
+ assert extract_tool_types(tools) == set()
77
+
78
+ tools.append(LocalShell(type="local_shell"))
79
+ assert extract_tool_types(tools) == {"local_shell"}
80
+
81
+ tools.append(CodeInterpreterContainerCodeInterpreterToolAuto(type="auto"))
82
+ assert extract_tool_types(tools) == {"local_shell", "auto"}
83
+
84
+ tools.extend(
85
+ [
86
+ Mcp(type="mcp", server_label="random", server_url=""),
87
+ Mcp(type="mcp", server_label="container", server_url=""),
88
+ Mcp(type="mcp", server_label="code_interpreter", server_url=""),
89
+ Mcp(type="mcp", server_label="web_search_preview", server_url=""),
90
+ ]
91
+ )
92
+ # When envs.VLLM_GPT_OSS_SYSTEM_TOOL_MCP_LABELS is not set,
93
+ # mcp tool types are all ignored.
94
+ assert extract_tool_types(tools) == {"local_shell", "auto"}
95
+
96
+ # container is allowed, it would be extracted
97
+ monkeypatch.setenv("VLLM_GPT_OSS_SYSTEM_TOOL_MCP_LABELS", "container")
98
+ assert extract_tool_types(tools) == {"local_shell", "auto", "container"}
99
+
100
+ # code_interpreter and web_search_preview are allowed,
101
+ # they would be extracted
102
+ monkeypatch.setenv(
103
+ "VLLM_GPT_OSS_SYSTEM_TOOL_MCP_LABELS", "code_interpreter,web_search_preview"
104
+ )
105
+ assert extract_tool_types(tools) == {
106
+ "local_shell",
107
+ "auto",
108
+ "code_interpreter",
109
+ "web_search_preview",
110
+ }
111
+
112
+
113
class TestInitializeToolSessions:
114
"""Test class for _initialize_tool_sessions method"""
115
tests/entrypoints/test_harmony_utils.py
+13
-1
@@ -3,7 +3,10 @@
3
4
from openai_harmony import Role
5
6
-from vllm.entrypoints.harmony_utils import parse_input_to_harmony_message
6
+from vllm.entrypoints.harmony_utils import (
7
+ has_custom_tools,
8
+ parse_input_to_harmony_message,
9
+)
10
11
12
class TestParseInputToHarmonyMessage:
@@ -252,3 +255,12 @@ class TestParseInputToHarmonyMessage:
255
assert len(messages[0].content) == 2
256
assert messages[0].content[0].text == ""
257
assert messages[0].content[1].text == "actual text"
258
+
259
+
260
+def test_has_custom_tools() -> None:
261
+ assert not has_custom_tools(set())
262
+ assert not has_custom_tools({"web_search_preview", "code_interpreter", "container"})
263
+ assert has_custom_tools({"others"})
264
+ assert has_custom_tools(
265
+ {"web_search_preview", "code_interpreter", "container", "others"}
266
+ )
tests/test_envs.py
+108
@@ -10,6 +10,7 @@ import vllm.envs as envs
10
from vllm.envs import (
11
enable_envs_cache,
12
env_list_with_choices,
13
+ env_set_with_choices,
14
env_with_choices,
15
environment_variables,
16
)
@@ -257,3 +258,110 @@ class TestEnvListWithChoices:
258
with patch.dict(os.environ, {"TEST_ENV": "option1,option1,option2"}):
259
env_func = env_list_with_choices("TEST_ENV", [], ["option1", "option2"])
260
assert env_func() == ["option1", "option1", "option2"]
261
+
262
+
263
+class TestEnvSetWithChoices:
264
+ """Test cases for env_set_with_choices function."""
265
+
266
+ def test_default_list_returned_when_env_not_set(self):
267
+ """Test that default list is returned when env var is not set."""
268
+ env_func = env_set_with_choices(
269
+ "NONEXISTENT_ENV", ["default1", "default2"], ["option1", "option2"]
270
+ )
271
+ assert env_func() == {"default1", "default2"}
272
+
273
+ def test_empty_default_list_returned_when_env_not_set(self):
274
+ """Test that empty default list is returned when env not set."""
275
+ env_func = env_set_with_choices("NONEXISTENT_ENV", [], ["option1", "option2"])
276
+ assert env_func() == set()
277
+
278
+ def test_single_valid_value_parsed_correctly(self):
279
+ """Test that single valid value is parsed correctly."""
280
+ with patch.dict(os.environ, {"TEST_ENV": "option1"}):
281
+ env_func = env_set_with_choices("TEST_ENV", [], ["option1", "option2"])
282
+ assert env_func() == {"option1"}
283
+
284
+ def test_multiple_valid_values_parsed_correctly(self):
285
+ """Test that multiple valid values are parsed correctly."""
286
+ with patch.dict(os.environ, {"TEST_ENV": "option1,option2"}):
287
+ env_func = env_set_with_choices("TEST_ENV", [], ["option1", "option2"])
288
+ assert env_func() == {"option1", "option2"}
289
+
290
+ def test_values_with_whitespace_trimmed(self):
291
+ """Test that values with whitespace are trimmed correctly."""
292
+ with patch.dict(os.environ, {"TEST_ENV": " option1 , option2 "}):
293
+ env_func = env_set_with_choices("TEST_ENV", [], ["option1", "option2"])
294
+ assert env_func() == {"option1", "option2"}
295
+
296
+ def test_empty_values_filtered_out(self):
297
+ """Test that empty values are filtered out."""
298
+ with patch.dict(os.environ, {"TEST_ENV": "option1,,option2,"}):
299
+ env_func = env_set_with_choices("TEST_ENV", [], ["option1", "option2"])
300
+ assert env_func() == {"option1", "option2"}
301
+
302
+ def test_empty_string_returns_default(self):
303
+ """Test that empty string returns default."""
304
+ with patch.dict(os.environ, {"TEST_ENV": ""}):
305
+ env_func = env_set_with_choices(
306
+ "TEST_ENV", ["default"], ["option1", "option2"]
307
+ )
308
+ assert env_func() == {"default"}
309
+
310
+ def test_only_commas_returns_default(self):
311
+ """Test that string with only commas returns default."""
312
+ with patch.dict(os.environ, {"TEST_ENV": ",,,"}):
313
+ env_func = env_set_with_choices(
314
+ "TEST_ENV", ["default"], ["option1", "option2"]
315
+ )
316
+ assert env_func() == {"default"}
317
+
318
+ def test_case_sensitive_validation(self):
319
+ """Test case sensitive validation."""
320
+ with patch.dict(os.environ, {"TEST_ENV": "option1,OPTION2"}):
321
+ env_func = env_set_with_choices(
322
+ "TEST_ENV", [], ["option1", "option2"], case_sensitive=True
323
+ )
324
+ with pytest.raises(ValueError, match="Invalid value 'OPTION2' in TEST_ENV"):
325
+ env_func()
326
+
327
+ def test_case_insensitive_validation(self):
328
+ """Test case insensitive validation."""
329
+ with patch.dict(os.environ, {"TEST_ENV": "OPTION1,option2"}):
330
+ env_func = env_set_with_choices(
331
+ "TEST_ENV", [], ["option1", "option2"], case_sensitive=False
332
+ )
333
+ assert env_func() == {"OPTION1", "option2"}
334
+
335
+ def test_invalid_value_in_list_raises_error(self):
336
+ """Test that invalid value in list raises ValueError."""
337
+ with patch.dict(os.environ, {"TEST_ENV": "option1,invalid,option2"}):
338
+ env_func = env_set_with_choices("TEST_ENV", [], ["option1", "option2"])
339
+ with pytest.raises(ValueError, match="Invalid value 'invalid' in TEST_ENV"):
340
+ env_func()
341
+
342
+ def test_callable_choices_resolved_correctly(self):
343
+ """Test that callable choices are resolved correctly."""
344
+
345
+ def get_choices():
346
+ return ["dynamic1", "dynamic2"]
347
+
348
+ with patch.dict(os.environ, {"TEST_ENV": "dynamic1,dynamic2"}):
349
+ env_func = env_set_with_choices("TEST_ENV", [], get_choices)
350
+ assert env_func() == {"dynamic1", "dynamic2"}
351
+
352
+ def test_callable_choices_with_invalid_value(self):
353
+ """Test that callable choices raise error for invalid values."""
354
+
355
+ def get_choices():
356
+ return ["dynamic1", "dynamic2"]
357
+
358
+ with patch.dict(os.environ, {"TEST_ENV": "dynamic1,invalid"}):
359
+ env_func = env_set_with_choices("TEST_ENV", [], get_choices)
360
+ with pytest.raises(ValueError, match="Invalid value 'invalid' in TEST_ENV"):
361
+ env_func()
362
+
363
+ def test_duplicate_values_deduped(self):
364
+ """Test that duplicate values in the list are deduped."""
365
+ with patch.dict(os.environ, {"TEST_ENV": "option1,option1,option2"}):
366
+ env_func = env_set_with_choices("TEST_ENV", [], ["option1", "option2"])
367
+ assert env_func() == {"option1", "option2"}
vllm/entrypoints/harmony_utils.py
+7
-3
@@ -61,15 +61,19 @@ _harmony_encoding = None
61
# they are available and requested by the user.
62
# Tool args are provided by MCP tool descriptions. Output
63
# of the tools are stringified.
64
-BUILTIN_TOOLS = {
64
+MCP_BUILTIN_TOOLS: set[str] = {
65
"web_search_preview",
66
"code_interpreter",
67
"container",
68
}
69
70
71
-def has_custom_tools(tool_types: list[str]) -> bool:
72
- return not set(tool_types).issubset(BUILTIN_TOOLS)
71
+def has_custom_tools(tool_types: set[str]) -> bool:
72
+ """
73
+ Checks if the given tool types are custom tools
74
+ (i.e. any tool other than MCP buildin tools)
75
+ """
76
+ return not tool_types.issubset(MCP_BUILTIN_TOOLS)
77
78
79
def get_encoding():
vllm/entrypoints/openai/serving_responses.py
+20
-12
@@ -48,6 +48,7 @@ from openai.types.responses.response_output_text import Logprob, LogprobTopLogpr
48
from openai.types.responses.response_reasoning_item import (
49
Content as ResponseReasoningTextContent,
50
)
51
+from openai.types.responses.tool import Tool
52
from openai_harmony import Message as OpenAIHarmonyMessage
53
54
from vllm import envs
@@ -106,6 +107,23 @@ from vllm.utils import random_uuid
107
logger = init_logger(__name__)
108
109
110
+def extract_tool_types(tools: list[Tool]) -> set[str]:
111
+ """
112
+ Extracts the tool types from the given tools.
113
+ """
114
+ tool_types: set[str] = set()
115
+ for tool in tools:
116
+ if tool.type == "mcp":
117
+ # Allow the MCP Tool type to enable built in tools if the
118
+ # server_label is allowlisted in
119
+ # envs.VLLM_GPT_OSS_SYSTEM_TOOL_MCP_LABELS
120
+ if tool.server_label in envs.VLLM_GPT_OSS_SYSTEM_TOOL_MCP_LABELS:
121
+ tool_types.add(tool.server_label)
122
+ else:
123
+ tool_types.add(tool.type)
124
+ return tool_types
125
+
126
+
127
class OpenAIServingResponses(OpenAIServing):
128
def __init__(
129
self,
@@ -879,7 +897,7 @@ class OpenAIServingResponses(OpenAIServing):
897
return messages
898
899
def _construct_harmony_system_input_message(
882
- self, request: ResponsesRequest, with_custom_tools: bool, tool_types: list[str]
900
+ self, request: ResponsesRequest, with_custom_tools: bool, tool_types: set[str]
901
) -> OpenAIHarmonyMessage:
902
reasoning_effort = request.reasoning.effort if request.reasoning else None
903
enable_browser = (
@@ -927,17 +945,7 @@ class OpenAIServingResponses(OpenAIServing):
945
messages: list[OpenAIHarmonyMessage] = []
946
if prev_response is None:
947
# New conversation.
930
- tool_types = [tool.type for tool in request.tools]
931
- # Allow the MCP Tool type to enable built in tools if the
932
- # server_label is allowlisted in
933
- # envs.GPT_OSS_SYSTEM_TOOL_MCP_LABELS
934
- if envs.GPT_OSS_SYSTEM_TOOL_MCP_LABELS:
935
- for tool in request.tools:
936
- if (
937
- tool.type == "mcp"
938
- and tool.server_label in envs.GPT_OSS_SYSTEM_TOOL_MCP_LABELS
939
- ):
940
- tool_types.append(tool.server_label)
948
+ tool_types = extract_tool_types(request.tools)
949
with_custom_tools = has_custom_tools(tool_types)
950
951
sys_msg = self._construct_harmony_system_input_message(
vllm/envs.py
+28
-8
@@ -198,6 +198,7 @@ if TYPE_CHECKING:
198
VLLM_USE_FLASHINFER_MOE_MXFP4_MXFP8_CUTLASS: bool = False
199
VLLM_ALLREDUCE_USE_SYMM_MEM: bool = False
200
VLLM_TUNED_CONFIG_FOLDER: str | None = None
201
+ VLLM_GPT_OSS_SYSTEM_TOOL_MCP_LABELS: set[str] = set()
202
VLLM_GPT_OSS_HARMONY_SYSTEM_INSTRUCTIONS: bool = False
203
VLLM_TOOL_JSON_ERROR_AUTOMATIC_RETRY: bool = False
204
VLLM_CUSTOM_SCOPES_FOR_PROFILING: bool = False
@@ -209,7 +210,6 @@ if TYPE_CHECKING:
210
VLLM_DEEPEP_LOW_LATENCY_ALLOW_NVLINK: bool = True
211
VLLM_DEEPEP_LOW_LATENCY_USE_MNNVL: bool = False
212
VLLM_DBO_COMM_SMS: int = 20
212
- GPT_OSS_SYSTEM_TOOL_MCP_LABELS: list[str] = []
213
VLLM_PATTERN_MATCH_DEBUG: str | None = None
214
VLLM_DEBUG_DUMP_PATH: str | None = None
215
VLLM_ENABLE_INDUCTOR_MAX_AUTOTUNE: bool = True
@@ -354,6 +354,24 @@ def env_list_with_choices(
354
return _get_validated_env_list
355
356
357
+def env_set_with_choices(
358
+ env_name: str,
359
+ default: list[str],
360
+ choices: list[str] | Callable[[], list[str]],
361
+ case_sensitive: bool = True,
362
+) -> Callable[[], set[str]]:
363
+ """
364
+ Creates a lambda which that validates environment variable
365
+ containing comma-separated values against allowed choices which
366
+ returns choices as a set.
367
+ """
368
+
369
+ def _get_validated_env_set() -> set[str]:
370
+ return set(env_list_with_choices(env_name, default, choices, case_sensitive)())
371
+
372
+ return _get_validated_env_set
373
+
374
+
375
def get_vllm_port() -> int | None:
376
"""Get the port from VLLM_PORT environment variable.
377
@@ -1328,6 +1346,15 @@ environment_variables: dict[str, Callable[[], Any]] = {
1346
),
1347
# Allows vllm to find tuned config under customized folder
1348
"VLLM_TUNED_CONFIG_FOLDER": lambda: os.getenv("VLLM_TUNED_CONFIG_FOLDER", None),
1349
+ # Valid values are container,code_interpreter,web_search_preview
1350
+ # ex VLLM_GPT_OSS_SYSTEM_TOOL_MCP_LABELS=container,code_interpreter
1351
+ # If the server_label of your mcp tool is not in this list it will
1352
+ # be completely ignored.
1353
+ "VLLM_GPT_OSS_SYSTEM_TOOL_MCP_LABELS": env_set_with_choices(
1354
+ "VLLM_GPT_OSS_SYSTEM_TOOL_MCP_LABELS",
1355
+ default=[],
1356
+ choices=["container", "code_interpreter", "web_search_preview"],
1357
+ ),
1358
# Allows harmony instructions to be injected on system messages
1359
"VLLM_GPT_OSS_HARMONY_SYSTEM_INSTRUCTIONS": lambda: bool(
1360
int(os.getenv("VLLM_GPT_OSS_HARMONY_SYSTEM_INSTRUCTIONS", "0"))
@@ -1379,13 +1406,6 @@ environment_variables: dict[str, Callable[[], Any]] = {
1406
# The number of SMs to allocate for communication kernels when running DBO
1407
# the rest of the SMs on the device will be allocated to compute
1408
"VLLM_DBO_COMM_SMS": lambda: int(os.getenv("VLLM_DBO_COMM_SMS", "20")),
1382
- # Valid values are container,code_interpreter,web_search_preview
1383
- # ex GPT_OSS_SYSTEM_TOOL_MCP_LABELS=container,code_interpreter
1384
- "GPT_OSS_SYSTEM_TOOL_MCP_LABELS": env_list_with_choices(
1385
- "GPT_OSS_SYSTEM_TOOL_MCP_LABELS",
1386
- [],
1387
- ["container", "code_interpreter", "web_search_preview"],
1388
- ),
1409
# Enable max_autotune & coordinate_descent_tuning in inductor_config
1410
# to compile static shapes passed from compile_sizes in compilation_config
1411
# If set to 1, enable max_autotune; By default, this is enabled (1)