8000 feat(OpenAI): Add support for Remote MCP Tool to Responses (#601) · openai-php/client@f35ffdf · GitHub
[go: up one dir, main page]

Skip to content

Commit f35ffdf

Browse files
authored
feat(OpenAI): Add support for Remote MCP Tool to Responses (#601)
* Add support for Remote MCP Tool * feat(OpenAI): Add streaming for ImageGeneration (Responses API) (#602) * feat(OpenAI): Add streaming for ImageGeneration (Responses API) * fix(OpenAI): `model` is missing on stream and partial images is default 0 * test(OpenAI): image generation steaming test * fix(OpenAI): add output item (Image Generation) * fix(OpenAI): add output item (Image Generation) * test(OpenAI): enhanced stream testing * fix(OpenAI): image generation streaming fixes * fix(OpenAI): proper type * chore(OpenAI): align test to stream mock * fix(OpenAI): result is missing on partial image failure * Add support for Remote MCP Tool * fix conflicts * fix merge * fix feedbacks
1 parent 0a29b39 commit f35ffdf

21 files changed

+988
-20
lines changed

src/Responses/Responses/CreateResponse.php

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
use OpenAI\Responses\Responses\Output\OutputFileSearchToolCall;
1414
use OpenAI\Responses\Responses\Output\OutputFunctionToolCall;
1515
use OpenAI\Responses\Responses\Output\OutputImageGenerationToolCall;
16+
use OpenAI\Responses\Responses\Output\OutputMcpApprovalRequest;
17+
use OpenAI\Responses\Responses\Output\OutputMcpCall;
18+
use OpenAI\Responses\Responses\Output\OutputMcpListTools;
1619
use OpenAI\Responses\Responses\Output\OutputMessage;
1720
use OpenAI\Responses\Responses\Output\OutputMessageContentOutputText;
1821
use OpenAI\Responses\Responses\Output\OutputReasoning;
@@ -21,6 +24,7 @@
2124
use OpenAI\Responses\Responses\Tool\FileSearchTool;
2225
use OpenAI\Responses\Responses\Tool\FunctionTool;
2326
use OpenAI\Responses\Responses\Tool\ImageGenerationTool;
27+
use OpenAI\Responses\Responses\Tool\RemoteMcpTool;
2428
use OpenAI\Responses\Responses\Tool\WebSearchTool;
2529
use OpenAI\Responses\Responses\ToolChoice\FunctionToolChoice;
2630
use OpenAI\Responses\Responses\ToolChoice\HostedToolChoice;
@@ -34,10 +38,14 @@
3438
* @phpstan-import-type OutputMessageType from OutputMessage
3539
* @phpstan-import-type OutputReasoningType from OutputReasoning
3640
* @phpstan-import-type OutputWebSearchToolCallType from OutputWebSearchToolCall
41+
* @phpstan-import-type OutputMcpListToolsType from OutputMcpListTools
42+
* @phpstan-import-type OutputMcpApprovalRequestType from OutputMcpApprovalRequest
43+
* @phpstan-import-type OutputMcpCallType from OutputMcpCall
3744
* @phpstan-import-type OutputImageGenerationToolCallType from OutputImageGenerationToolCall
3845
* @phpstan-import-type ComputerUseToolType from ComputerUseTool
3946
* @phpstan-import-type FileSearchToolType from FileSearchTool
4047
* @phpstan-import-type ImageGenerationToolType from ImageGenerationTool
48+
* @phpstan-import-type RemoteMcpToolType from RemoteMcpTool
4149
* @phpstan-import-type FunctionToolType from FunctionTool
4250
* @phpstan-import-type WebSearchToolType from WebSearchTool
4351
* @phpstan-import-type ErrorType from CreateResponseError
@@ -48,8 +56,8 @@
4856
* @phpstan-import-type ReasoningType from CreateResponseReasoning
4957
*
5058
* @phpstan-type ToolChoiceType 'none'|'auto'|'required'|FunctionToolChoiceType|HostedToolChoiceType
51-
* @phpstan-type ToolsType array<int, ComputerUseToolType|FileSearchToolType|FunctionToolType|WebSearchToolType|ImageGenerationToolType>
52-
* @phpstan-type OutputType array<int, OutputComputerToolCallType|OutputFileSearchToolCallType|OutputFunctionToolCallType|OutputMessageType|OutputReasoningType|OutputWebSearchToolCallType|OutputImageGenerationToolCallType>
59+
* @phpstan-type ToolsType array<int, ComputerUseToolType|FileSearchToolType|FunctionToolType|WebSearchToolType|ImageGenerationToolType|RemoteMcpToolType|ImageGenerationToolType>
60+
* @phpstan-type OutputType array<int, OutputComputerToolCallType|OutputFileSearchToolCallType|OutputFunctionToolCallType|OutputMessageType|OutputReasoningType|OutputWebSearchToolCallType|OutputMcpListToolsType|OutputMcpApprovalRequestType|OutputMcpCallType|OutputImageGenerationToolCallType>
5361
* @phpstan-type CreateResponseType array{id: string, object: 'response', created_at: int, status: 'completed'|'failed'|'in_progress'|'incomplete', error: ErrorType|null, incomplete_details: IncompleteDetailsType|null, instructions: string|null, max_output_tokens: int|null, model: string, output: OutputType, output_text: string|null, parallel_tool_calls: bool, previous_response_id: string|null, reasoning: ReasoningType|null, store: bool, temperature: float|null, text: ResponseFormatType, tool_choice: ToolChoiceType, tools: ToolsType, top_p: float|null, truncation: 'auto'|'disabled'|null, usage: UsageType|null, user: string|null, metadata: array<string, string>|null}
5462
*
5563
* @implements ResponseContract<CreateResponseType>
@@ -67,8 +75,8 @@ final class CreateResponse implements ResponseContract, ResponseHasMetaInformati
6775
/**
6876
* @param 'response' $object
6977
* @param 'completed'|'failed'|'in_progress'|'incomplete' $status
70-
* @param array<int, OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputImageGenerationToolCall> $output
71-
* @param array<int, ComputerUseTool|FileSearchTool|FunctionTool|WebSearchTool|ImageGenerationTool> $tools
78+
* @param array<int, OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall> $output
79+
* @param array<int, ComputerUseTool|FileSearchTool|FunctionTool|WebSearchTool|ImageGenerationTool|RemoteMcpTool|ImageGenerationTool> $tools
7280
* @param 'auto'|'disabled'|null $truncation
7381
* @param array<string, string> $metadata
7482
*/
@@ -106,13 +114,16 @@ private function __construct(
106114
public static function from(array $attributes, MetaInformation $meta): self
107115
{
108116
$output = array_map(
109-
fn (array $output): OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputImageGenerationToolCall => match ($output['type']) {
117+
fn (array $output): OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall => match ($output['type']) {
110118
'message' => OutputMessage::from($output),
111119
'file_search_call' => OutputFileSearchToolCall::from($output),
112120
'function_call' => OutputFunctionToolCall::from($output),
113121
'web_search_call' => OutputWebSearchToolCall::from($output),
114122
'computer_call' => OutputComputerToolCall::from($output),
115123
'reasoning' => OutputReasoning::from($output),
124+
'mcp_list_tools' => OutputMcpListTools::from($output),
125+
'mcp_approval_request' => OutputMcpApprovalRequest::from($output),
126+
'mcp_call' => OutputMcpCall::from($output),
116127
'image_generation_call' => OutputImageGenerationToolCall::from($output),
117128
},
118129
$attributes['output'],
@@ -126,12 +137,13 @@ public static function from(array $attributes, MetaInformation $meta): self
126137
: $attributes['tool_choice'];
127138

128139
$tools = array_map(
129-
fn (array $tool): ComputerUseTool|FileSearchTool|FunctionTool|WebSearchTool|ImageGenerationTool => match ($tool['type']) {
140+
fn (array $tool): ComputerUseTool|FileSearchTool|FunctionTool|WebSearchTool|ImageGenerationTool|RemoteMcpTool => match ($tool['type']) {
130141
'file_search' => FileSearchTool::from($tool),
131142
'web_search_preview', 'web_search_preview_2025_03_11' => WebSearchTool::from($tool),
132143
'function' => FunctionTool::from($tool),
133144
'computer_use_preview' => ComputerUseTool::from($tool),
134145
'image_generation' => ImageGenerationTool::from($tool),
146+
'mcp' => RemoteMcpTool::from($tool),
135147
},
136148
$attributes['tools'],
137149
);
@@ -204,7 +216,7 @@ public function toArray(): array
204216
'metadata' => $this->metadata ?? [],
205217
'model' => $this->model,
206218
'output' => array_map(
207-
fn (OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputImageGenerationToolCall $output): array => $output->toArray(),
219+
fn (OutputMessage|OutputComputerToolCall|OutputFileSearchToolCall|OutputWebSearchToolCall|OutputFunctionToolCall|OutputReasoning|OutputMcpListTools|OutputMcpApprovalRequest|OutputMcpCall|OutputImageGenerationToolCall $output): array => $output->toArray(),
208220
$this->output
209221
),
210222
'parallel_tool_calls' => $this->parallelToolCalls,
@@ -217,7 +229,7 @@ public function toArray(): array
217229
? $this->toolChoice
218230
: $this->toolChoice->toArray(),
219231
'tools' => array_map(
220-
fn (ComputerUseTool|FileSearchTool|FunctionTool|WebSearchTool|ImageGenerationTool $tool): array => $tool->toArray(),
232+
fn (ComputerUseTool|FileSearchTool|FunctionTool|WebSearchTool|ImageGenerationTool|RemoteMcpTool $tool): array => $tool->toArray(),
221233
$this->tools
222234
),
223235
'top_p' => $this->topP,

src/Responses/Responses/CreateStreamedResponse.php

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
use OpenAI\Responses\Responses\Streaming\FunctionCallArgumentsDone;
1515
use OpenAI\Responses\Responses\Streaming\ImageGenerationPart;
1616
use OpenAI\Responses\Responses\Streaming\ImageGenerationPartialImage;
17+
use OpenAI\Responses\Responses\Streaming\McpCall;
18+
use OpenAI\Responses\Responses\Streaming\McpCallArgumentsDelta;
19+
use OpenAI\Responses\Responses\Streaming\McpCallArgumentsDone;
20+
use OpenAI\Responses\Responses\Streaming\McpListTools;
21+
use OpenAI\Responses\Responses\Streaming\McpListToolsInProgress;
1722
use OpenAI\Responses\Responses\Streaming\OutputItem;
1823
use OpenAI\Responses\Responses\Streaming\OutputTextAnnotationAdded;
1924
use OpenAI\Responses\Responses\Streaming\OutputTextDelta;
@@ -42,7 +47,7 @@ final class CreateStreamedResponse implements ResponseContract
4247

4348
private function __construct(
4449
public readonly string $event,
45-
public readonly CreateResponse|OutputItem|ContentPart|OutputTextDelta|OutputTextAnnotationAdded|OutputTextDone|RefusalDelta|RefusalDone|FunctionCallArgumentsDelta|FunctionCallArgumentsDone|FileSearchCall|WebSearchCall|ReasoningSummaryPart|ReasoningSummaryTextDelta|ReasoningSummaryTextDone|ImageGenerationPart|ImageGenerationPartialImage|Error $response,
50+
public readonly CreateResponse|OutputItem|ContentPart|OutputTextDelta|OutputTextAnnotationAdded|OutputTextDone|RefusalDelta|RefusalDone|FunctionCallArgumentsDelta|FunctionCallArgumentsDone|FileSearchCall|WebSearchCall|ReasoningSummaryPart|ReasoningSummaryTextDelta|ReasoningSummaryTextDone|McpListTools|McpListToolsInProgress|McpCall|McpCallArgumentsDelta|McpCallArgumentsDone|ImageGenerationPart|ImageGenerationPartialImage|Error $response,
4651
) {}
4752

4853
/**
@@ -81,6 +86,16 @@ public static function from(array $attributes): self
8186
'response.reasoning_summary_part.done' => ReasoningSummaryPart::from($attributes, $meta), // @phpstan-ignore-line
8287
'response.reasoning_summary_text.delta' => ReasoningSummaryTextDelta::from($attributes, $meta), // @phpstan-ignore-line
8388
'response.reasoning_summary_text.done' => ReasoningSummaryTextDone::from($attributes, $meta), // @phpstan-ignore-line
89+
'response.mcp_list_tools.in_progress' => McpListToolsInProgress::from($attributes, $meta), // @phpstan-ignore-line
90+
'response.mcp_list_tools.failed',
91+
'response.mcp_list_tools.completed' => McpListTools::from($attributes, $meta), // @phpstan-ignore-line
92+
'response.mcp_call.in_progress',
93+
'response.mcp_call.failed',
94+
'response.mcp_call.completed' => McpCall::from($attributes, $meta), // @phpstan-ignore-line
95+
'response.mcp_call.arguments.delta',
96+
'response.mcp_call_arguments.delta' => McpCallArgumentsDelta::from($attributes, $meta), // @phpstan-ignore-line
97+
'response.mcp_call.arguments.done',
98+
'response.mcp_call_arguments.done' => McpCallArgumentsDone::from($attributes, $meta), // @phpstan-ignore-line
8499
'response.image_generation_call.completed',
85100
'response.image_generation_call.generating',
86101
'response.image_generation_call.in_progress' => ImageGenerationPart::from($attributes, $meta), // @phpstan-ignore-line
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenAI\Responses\Responses\Output;
6+
7+
use OpenAI\Contracts\ResponseContract;
8+
use OpenAI\Responses\Concerns\ArrayAccessible;
9+
use OpenAI\Testing\Responses\Concerns\Fakeable;
10+
11+
/**
12+
* @phpstan-type OutputMcpApprovalRequestType array{id: string, server_label: string, name: string, arguments: string, type: 'mcp_approval_request'}
13+
*
14+
* @implements ResponseContract<OutputMcpApprovalRequestType>
15+
*/
16+
final class OutputMcpApprovalRequest implements ResponseContract
17+
{
18+
/**
19+
* @use ArrayAccessible<OutputMcpApprovalRequestType>
20+
*/
21+
use ArrayAccessible;
22+
23+
use Fakeable;
24+
25+
/**
26+
* @param 'mcp_approval_request' $type
27+
*/
28+
private function __construct(
29+
public readonly string $id,
30+
public readonly string $serverLabel,
31+
public readonly string $name,
32+
public readonly string $arguments,
33+
public readonly string $type,
34+
) {}
35+
36+
/**
37+
* @param OutputMcpApprovalRequestType $attributes
38+
*/
39+
public static function from(array $attributes): self
40+
{
41+
return new self(
42+
id: $attributes['id'],
43+
serverLabel: $attributes['server_label'],
44+
name: $attributes['name'],
45+
arguments: $attributes['arguments'],
46+
type: $attributes['type'],
47+
);
48+
}
49+
50+
/**
51+
* {@inheritDoc}
52+
*/
53+
public function toArray(): array
54+
{
55+
return [
56+
'id' => $this->id,
57+
'server_label' => $this->serverLabel,
58+
'type' => $this->type,
59+
'arguments' => $this->arguments,
60+
'name' => $this->name,
61+
];
62+
}
63+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenAI\Responses\Responses\Output;
6+
7+
use OpenAI\Contracts\ResponseContract;
8+
use OpenAI\Responses\Concerns\ArrayAccessible;
9+
use OpenAI\Testing\Responses\Concerns\Fakeable;
10+
11+
/**
12+
* @phpstan-type OutputMcpCallType array{id: string, server_label: string, type: 'mcp_call', approval_request_id: ?string, arguments: string, error: ?string, name: string, output: ?string}
13+
*
14+
* @implements ResponseContract<OutputMcpCallType>
15+
*/
16+
final class OutputMcpCall implements ResponseContract
17+
{
18+
/**
19+
* @use ArrayAccessible<OutputMcpCallType>
20+
*/
21+
use ArrayAccessible;
22+
23+
use Fakeable;
24+
25+
/**
26+
* @param 'mcp_call' $type
27+
*/
28+
private function __construct(
29+
public readonly string $id,
30+
public readonly string $serverLabel,
31+
public readonly string $type,
32+
public readonly string $arguments,
33+
public readonly string $name,
34+
public readonly ?string $approvalRequestId = null,
35+
public readonly ?string $error = null,
36+
public readonly ?string $output = null,
37+
) {}
38+
39+
/**
40+
* @param OutputMcpCallType $attributes
41+
*/
42+
public static function from(array $attributes): self
43+
{
44+
return new self(
45+
id: $attributes['id'],
46+
serverLabel: $attributes['server_label'],
47+
type: $attributes['type'],
48+
arguments: $attributes['arguments'],
49+
name: $attributes['name'],
50+
approvalRequestId: $attributes['approval_request_id'],
51+
error: $attributes['error'],
52+
output: $attributes['output'],
53+
);
54+
}
55+
56+
/**
57+
* {@inheritDoc}
58+
*/
59+
public function toArray(): array
60+
{
61+
return [
62+
'id' => $this->id,
63+
'server_label' => $this->serverLabel,
64+
'type' => $this->type,
65+
'arguments' => $this->arguments,
66+
'name' => $this->name,
67+
'approval_request_id' => $this->approvalRequestId,
68+
'error' => $this->error,
69+
'output' => $this->output,
70+
];
71+
}
72+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace OpenAI\Responses\Responses\Output;
6+
7+
use OpenAI\Contracts\ResponseContract;
8+
use OpenAI\Responses\Concerns\ArrayAccessible;
9+
use OpenAI\Testing\Responses\Concerns\Fakeable;
10+
11+
/**
12+
* @phpstan-import-type OutputMcpListToolsToolType from OutputMcpListToolsTool
13+
*
14+
* @phpstan-type OutputMcpListToolsType array{id: string, server_label: string, type: 'mcp_list_tools', tools: array<int, OutputMcpListToolsToolType>}
15+
*
16+
* @implements ResponseContract<OutputMcpListToolsType>
17+
*/
18+
final class OutputMcpListTools implements ResponseContract
19+
{
20+
/**
21+
* @use ArrayAccessible<OutputMcpListToolsType>
22+
*/
23+
use ArrayAccessible;
24+
25+
use Fakeable;
26+
27+
/**
28+
* @param 'mcp_list_tools' $type
29+
* @param array<int, OutputMcpListToolsTool> $tools
30+
*/
31+
private function __construct(
32+
public readonly string $id,
33+
public readonly string $serverLabel,
34+
public readonly string $type,
35+
public readonly array $tools,
36+
) {}
37+
38+
/**
39+
* @param OutputMcpListToolsType $attributes
40+
*/
41+
public static function from(array $attributes): self
42+
{
43+
$tools = array_map(
44+
fn (array $result): OutputMcpListToolsTool => OutputMcpListToolsTool::from($result),
45+
$attributes['tools']
46+
);
47+
48+
return new self(
49+
id: $attributes['id'],
50+
serverLabel: $attributes['server_label'],
51+
type: $attributes['type'],
52+
tools: $tools,
53+
);
54+
}
55+
56+
/**
57+
* {@inheritDoc}
58+
*/
59+
public function toArray(): array
60+
{
61+
return [
62+
'id' => $this->id,
63+
'server_label' => $this->serverLabel,
64+
'type' => $this->type,
65+
'tools' => array_map(
66+
fn (OutputMcpListToolsTool $tool) => $tool->toArray(),
67+
$this->tools
68+
),
69+
];
70+
}
71+
}

0 commit comments

Comments
 (0)
0