Skip to content

Commit 6f57a9e

Browse files
committed
fix(app): reserve chat request slots during MCP discovery
1 parent 216c311 commit 6f57a9e

2 files changed

Lines changed: 29 additions & 3 deletions

File tree

‎packages/app/src/runtime/server/request-queue.test.ts‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,32 @@ describe("createRequestQueue", () => {
102102
expect(input.queue.inflight()).toBe(0)
103103
})
104104

105+
test("MCP discovery cannot occupy every slot ahead of chat reads", async () => {
106+
for (const path of ["/api/command", "/api/mcp", "/api/mcp/resource"]) {
107+
const input = setup({ limit: 4, slowLimit: 2 })
108+
const discovery = Array.from({ length: 4 }, (_, index) =>
109+
input.queue.fetch(`http://server${path}?location[directory]=%2Fproject-${index}`),
110+
)
111+
const chat = input.queue.fetch("http://server/api/session/ses_1/message")
112+
try {
113+
expect(input.pending.map((item) => new URL(item.url).pathname)).toEqual([
114+
path,
115+
path,
116+
"/api/session/ses_1/message",
117+
])
118+
expect(input.queue.inflight()).toBe(3)
119+
expect(input.queue.queued()).toBe(2)
120+
} finally {
121+
input.pending.forEach((item) => item.resolve())
122+
await input.settle()
123+
input.pending.forEach((item) => item.resolve())
124+
await Promise.all([...discovery, chat])
125+
}
126+
expect(input.queue.inflight()).toBe(0)
127+
expect(input.queue.queued()).toBe(0)
128+
}
129+
})
130+
105131
test("never counts the event stream against the budget", async () => {
106132
const input = setup({ limit: 1 })
107133
void input.queue.fetch("http://server/api/session")

‎packages/app/src/runtime/server/request-queue.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ type Entry = { method: string; url: string; at: number; slow: boolean }
55
// a burst stalls probes and user actions inside the browser where nothing can observe it.
66
export const requestQueueLimit = 4
77

8-
// Endpoints that shell out to git or walk the filesystem take seconds on a large repository. They
9-
// may hold at most this many slots, so a session mount's small reads never queue behind them.
8+
// Git/filesystem endpoints and MCP catalogs can take seconds, including MCP startup and discovery.
9+
// They may hold at most this many slots, so a session mount's small reads never queue behind them.
1010
export const requestQueueSlowLimit = 2
1111

12-
export const slowRequestPaths = ["/api/vcs", "/api/worktree"]
12+
export const slowRequestPaths = ["/api/vcs", "/api/worktree", "/api/command", "/api/mcp"]
1313

1414
// A mount legitimately fires a dozen requests at once; only a request that has waited this long
1515
// for a slot indicates the server is not keeping up.

0 commit comments

Comments
 (0)