fix(mcp-server): get_selection lists every selected id, with detail for the first 100

This commit is contained in:
dayuan.jiang
2026-10-11 20:56:07 +09:00
parent e93f7547c2
commit c9c610e929
2 changed files with 14 additions and 8 deletions
+7 -6
View File
@@ -69,14 +69,15 @@ export function parseSelectionAnswer(value: unknown): SelectionAnswer | null {
return { pageId: text(given.pageId), pageName: text(given.pageName), cells }
}
/** describeSelection lists at most this many cells; the rest are counted */
/** describeSelection details at most this many cells; the rest by id only */
export const MAX_LISTED_CELLS = 100
/**
* The get_selection result text. `externalDrawio` names the draw.io origin
* when the preview loads it from another origin, where the page cannot
* read the editor. A selection of a whole large diagram is counted, not
* listed in full: the model needs the ids of a few hundred cells at most.
* read the editor. A selection of a whole large diagram would fill the
* model's context with labels and geometry: the first cells get them, the
* rest are listed by id alone (an edit on the selection needs every id).
*/
export function describeSelection(
answer: SelectionAnswer,
@@ -110,10 +111,10 @@ export function describeSelection(
const parent = cell.parent ? ` inside "${cell.parent}"` : ""
return `- id="${cell.id}" shape ${label}${where}${parent}`
})
const more = answer.cells.length - listed.length
if (more > 0) {
const rest = answer.cells.slice(MAX_LISTED_CELLS)
if (rest.length > 0) {
lines.push(
`- and ${more} more cells not listed here; call get_diagram for the rest`,
`- and ${rest.length} more cells, listed by id only: ${rest.map((c) => `"${c.id}"`).join(", ")}`,
)
}
const count =
+7 -2
View File
@@ -53,7 +53,7 @@ describe("get_selection text", () => {
expect(text).toContain('edit_diagram (page_id="p1")')
})
it("counts a large selection instead of listing every cell", () => {
it("details the first cells of a large selection and lists the rest by id", () => {
const cells = (n: number) =>
Array.from({ length: n }, (_, i) => ({
id: `c${i + 1}`,
@@ -67,8 +67,13 @@ describe("get_selection text", () => {
)
expect(text).toContain(`${MAX_LISTED_CELLS + 5} cells selected`)
expect(text).toContain(`id="c${MAX_LISTED_CELLS}"`)
// No detail past the cap, but every id: the model acts on all of
// them, and get_diagram cannot tell which cells were selected
expect(text).not.toContain(`id="c${MAX_LISTED_CELLS + 1}"`)
expect(text).toContain("and 5 more cells not listed here")
expect(text).not.toContain(`shape "Cell ${MAX_LISTED_CELLS + 1}"`)
expect(text).toContain(
`- and 5 more cells, listed by id only: "c${MAX_LISTED_CELLS + 1}", "c${MAX_LISTED_CELLS + 2}", "c${MAX_LISTED_CELLS + 3}", "c${MAX_LISTED_CELLS + 4}", "c${MAX_LISTED_CELLS + 5}"`,
)
const exact = describeSelection(
{ ...page, cells: cells(MAX_LISTED_CELLS) },
null,