Skip to content

Commit 401739a

Browse files
[MCP] include assistant tool call before tool response + bug fix (#1618)
Fixes #1614. Also, while experimenting with tiny-agents using OpenAI's gpt-4o, I noticed that the assistant's tool call wasn t being appended to the message list before the tool call result. This didn't cause issues before, _likely_ because the models inferred the missing function call context from the tool response. However, it seems that OpenAI is stricter about message ordering and expect the assistant's tool call to be explicitly in the conversation history. Note: the fix is already implemented in Python tiny-agents : huggingface/huggingface_hub#3159
1 parent 57cb42b commit 401739a

File tree

1 file changed

+31
-10
lines changed

1 file changed

+31
-10
lines changed

packages/mcp-client/src/McpClient.ts

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,14 +125,18 @@ export class McpClient {
125125
): AsyncGenerator<ChatCompletionStreamOutput | ChatCompletionInputMessageTool> {
126126
debug("start of single turn");
127127

128-
const stream = this.client.chatCompletionStream({
129-
provider: this.provider,
130-
model: this.model,
131-
messages,
132-
tools: opts.exitLoopTools ? [...opts.exitLoopTools, ...this.availableTools] : this.availableTools,
133-
tool_choice: "auto",
134-
signal: opts.abortSignal,
135-
});
128+
const stream = this.client.chatCompletionStream(
129+
{
130+
provider: this.provider,
131+
model: this.model,
132+
messages,
133+
tools: opts.exitLoopTools ? [...opts.exitLoopTools, ...this.availableTools] : this.availableTools,
134+
tool_choice: "auto",
135+
},
136+
{
137+
signal: opts.abortSignal,
138+
}
139+
);
136140

137141
const message = {
138142
role: "unknown",
@@ -181,9 +185,26 @@ export class McpClient {
181185
yield chunk;
182186
}
183187

184-
messages.push(message);
188+
const assistantMessage: ChatCompletionInputMessage = {
189+
role: "assistant",
190+
content: message.content,
191+
};
192+
193+
const finalToolCallValues = Object.values(finalToolCalls);
194+
195+
if (finalToolCallValues.length > 0) {
196+
assistantMessage.tool_calls = finalToolCallValues.map((toolCall) => ({
197+
id: toolCall.id,
198+
type: "function",
199+
function: {
200+
name: toolCall.function.name ?? "unknown",
201+
arguments: toolCall.function.arguments,
202+
},
203+
}));
204+
}
205+
messages.push(assistantMessage);
185206

186-
for (const toolCall of Object.values(finalToolCalls)) {
207+
for (const toolCall of finalToolCallValues) {
187208
const toolName = toolCall.function.name ?? "unknown";
188209
/// TODO(Fix upstream type so this is always a string)^
189210
const toolMessage: ChatCompletionInputMessageTool = {

0 commit comments

Comments
 (0)