Skip to content

Commit c9d6af6

Browse files
authored
improvement(search): read up to 10 documents per MCP read_document call (#8981)
* improvement(search): read up to 10 documents per MCP read_document call, five at a time * test(search): finish later batched reads first so the order assertion can fail
1 parent d2083a9 commit c9d6af6

3 files changed

Lines changed: 27 additions & 4 deletions

File tree

‎apps/sim/lib/api/contracts/knowledge/mcp.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export const organizationKnowledgeMcpContract = defineRouteContract({
1818

1919
export const liveSearchMcpSchema = searchWorkspaceInputSchema.strict()
2020
/** Documents one read_document call may read; each counts as one read against the rate limit. */
21-
const MAX_MCP_READ_DOCUMENTS = 5
21+
const MAX_MCP_READ_DOCUMENTS = 10
2222

2323
export const readLiveDocumentMcpSchema = readDocumentInputSchema
2424
.extend({

‎apps/sim/lib/knowledge/mcp/server.test.ts‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,24 @@ describe('batched document reads', () => {
208208
expect(mocks.liveRead).toHaveBeenCalledTimes(2)
209209
})
210210

211+
it('reads at most five documents from providers at once, in request order', async () => {
212+
create()
213+
let inFlight = 0
214+
let peak = 0
215+
mocks.liveRead.mockImplementation(async ({ input }: { input: { documentId: string } }) => {
216+
inFlight++
217+
peak = Math.max(peak, inFlight)
218+
const laterFinishesFirst = 10 - Number(input.documentId.slice('doc-'.length))
219+
for (let tick = 0; tick < laterFinishesFirst; tick++) await Promise.resolve()
220+
inFlight--
221+
return readResult(input.documentId)
222+
})
223+
const ids = Array.from({ length: 10 }, (_, index) => `doc-${index}`)
224+
const result = await call('read_document', { documentIds: ids })
225+
expect(peak).toBe(5)
226+
expect(parsedBody(result).documents.map((document) => document.documentId)).toEqual(ids)
227+
})
228+
211229
it('reads nothing when the batch exceeds the remaining rate limit', async () => {
212230
create()
213231
mocks.rateLimit.mockResolvedValueOnce(new Response(null, { status: 429 }))

‎apps/sim/lib/knowledge/mcp/server.ts‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
import type { V2ApiKeyAuthContext } from '@/lib/api/server/routes/v2-api-key-auth'
1313
import { v2RateLimits } from '@/lib/api/server/routes/v2-json-route'
1414
import { afterResponse } from '@/lib/core/utils/after-response'
15+
import { mapWithConcurrency } from '@/lib/core/utils/concurrency'
1516
import { organizationSearchChatOperation } from '@/lib/knowledge/application/chat-operations'
1617
import { knowledgeOperations } from '@/lib/knowledge/application/operations'
1718
import {
@@ -31,6 +32,8 @@ import { v2CaughtOrchestrationError } from '@/app/api/v2/lib/response'
3132
import { ResolvedSecretTraceRegistry } from '@/executor/utils/resolved-secret-trace-registry'
3233

3334
const logger = createLogger('KnowledgeMcp')
35+
/** Provider reads one read_document call runs at once, however many documents it names. */
36+
const READ_DOCUMENT_CONCURRENCY = 5
3437

3538
/** The message a caller may see for an expected failure; undefined for an internal error. */
3639
async function callerErrorMessage(error: unknown): Promise<string | undefined> {
@@ -201,8 +204,10 @@ export function createKnowledgeMcpServer(context: KnowledgeMcpContext): McpServe
201204
})
202205
if (documentId) return projectResult(projectReadResult(await read(documentId)), registry)
203206
/** One unreadable document leaves the others; each failure is reported in its place. */
204-
const documents = await Promise.all(
205-
batch.map(async (id) => {
207+
const documents = await mapWithConcurrency(
208+
batch,
209+
READ_DOCUMENT_CONCURRENCY,
210+
async (id) => {
206211
try {
207212
return projectReadResult(await read(id))
208213
} catch (error) {
@@ -218,7 +223,7 @@ export function createKnowledgeMcpServer(context: KnowledgeMcpContext): McpServe
218223
error: message ?? 'Unable to read this document. Please try again.',
219224
}
220225
}
221-
})
226+
}
222227
)
223228
return projectResult({ documents }, registry)
224229
},

0 commit comments

Comments
 (0)