-
Notifications
You must be signed in to change notification settings - Fork 455
fix: cap MCP tool-call concurrency via MCP_TOOL_CALL_CONCURRENCY (default 4) #767
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
eeef0b8
49e242e
c0bd94c
fcbabf7
57dc3b2
9e68c61
d3df9f2
c865252
ee677e1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| "@truefoundry/trueforge-core": patch | ||
| "@truefoundry/trueforge": patch | ||
| --- | ||
|
|
||
| Cap parallel MCP tool execution at 4 in-flight calls (MCP_TOOL_CALL_CONCURRENCY). |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -506,6 +506,7 @@ export class AgentThread { | |
| private sandbox?: Sandbox | undefined; | ||
| private readonly tracing: AgentTracing; | ||
| private readonly logger: Logger; | ||
| private readonly mcpToolCallConcurrency: number; | ||
|
|
||
| private metrics: AgentThreadMetrics = createEmptyAgentThreadMetrics(); | ||
| private tfyManagedServerNames = new Set<string>(); | ||
|
|
@@ -521,6 +522,7 @@ export class AgentThread { | |
| constructor(input: AgentThreadConstructorInput) { | ||
| this.tracing = input.tracing; | ||
| this.logger = input.logger.child({ module: 'AgentThread' }); | ||
| this.mcpToolCallConcurrency = input.mcpToolCallConcurrency; | ||
| this.threadId = input.threadId; | ||
| this.definition = input.definition; | ||
| this.context = input.context ? [...input.context] : []; | ||
|
|
@@ -1146,6 +1148,7 @@ export class AgentThread { | |
|
|
||
| private async *stepToolResponse( | ||
| toolMapping: Map<string, MappedMCPTool>, | ||
| signal?: AbortSignal, | ||
| ): AsyncGenerator<AgentThreadEvent, StepOutcome, unknown> { | ||
| const assistantMessage = lastAssistantInContext(this.context); | ||
| if (!assistantMessage) { | ||
|
|
@@ -1174,6 +1177,8 @@ export class AgentThread { | |
| toolMapping, | ||
| threadId: this.threadId, | ||
| approvalDecisions: decisions, | ||
| concurrency: this.mcpToolCallConcurrency, | ||
| signal, | ||
| }); | ||
| void clientSideToolCalls; | ||
| if (approvalRequiredToolCalls.length > 0) { | ||
|
|
@@ -1376,7 +1381,7 @@ export class AgentThread { | |
| if (signal?.aborted) { | ||
| return; | ||
| } | ||
| outcome = yield* this.stepToolResponse(toolMapping); | ||
| outcome = yield* this.stepToolResponse(toolMapping, signal); | ||
| break; | ||
| } | ||
| case 'user-input-required': { | ||
|
|
@@ -1389,7 +1394,10 @@ export class AgentThread { | |
| throw new Error('unreachable'); | ||
| } | ||
| } | ||
| if (outcome === 'exit') { | ||
| // After a step, abort must return before the next deriveState(). | ||
| // A partial tool batch leaves open calls; tool-response-required → tool-response-required is invalid. | ||
| // Do not check at the top of the loop: user-input-required must still emit. | ||
| if (outcome === 'exit' || signal?.aborted) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Abort skips user-input eventsMedium Severity The new post-step Reviewed by Cursor Bugbot for commit ee677e1. Configure here. |
||
| return; | ||
| } | ||
| } | ||
|
|
||


Uh oh!
There was an error while loading. Please reload this page.