Add per-leaf mcpAllow flag for MCP visibility gating (default-deny)
This commit is contained in:
parent
b35a5b282d
commit
6068522ee3
2 changed files with 39 additions and 0 deletions
|
|
@ -12,6 +12,7 @@ import {
|
||||||
setLeafShell,
|
setLeafShell,
|
||||||
changeLabel,
|
changeLabel,
|
||||||
toggleBroadcast,
|
toggleBroadcast,
|
||||||
|
toggleMcpAllow,
|
||||||
adjustFontSize,
|
adjustFontSize,
|
||||||
adjustAllFontSizes,
|
adjustAllFontSizes,
|
||||||
resolveFontSize,
|
resolveFontSize,
|
||||||
|
|
@ -363,6 +364,27 @@ describe("toggleBroadcast", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("toggleMcpAllow", () => {
|
||||||
|
it("default-undefined toggles to true", () => {
|
||||||
|
const leaf = newLeaf();
|
||||||
|
expect(leaf.mcpAllow).toBeUndefined();
|
||||||
|
const on = toggleMcpAllow(leaf, leaf.id) as LeafNode;
|
||||||
|
expect(on.mcpAllow).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("true toggles to false", () => {
|
||||||
|
const leaf = newLeaf({ mcpAllow: true });
|
||||||
|
const off = toggleMcpAllow(leaf, leaf.id) as LeafNode;
|
||||||
|
expect(off.mcpAllow).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("MUST NOT swap the leaf id (metadata-only, no PTY respawn)", () => {
|
||||||
|
const leaf = newLeaf();
|
||||||
|
const next = toggleMcpAllow(leaf, leaf.id) as LeafNode;
|
||||||
|
expect(next.id).toBe(leaf.id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("resolveFontSize", () => {
|
describe("resolveFontSize", () => {
|
||||||
it("returns the default when offset is undefined or 0", () => {
|
it("returns the default when offset is undefined or 0", () => {
|
||||||
expect(resolveFontSize(undefined)).toBe(DEFAULT_FONT_SIZE);
|
expect(resolveFontSize(undefined)).toBe(DEFAULT_FONT_SIZE);
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,13 @@ export interface LeafNode {
|
||||||
* later doesn't require migrating saved workspaces.
|
* later doesn't require migrating saved workspaces.
|
||||||
*/
|
*/
|
||||||
fontSizeOffset?: number;
|
fontSizeOffset?: number;
|
||||||
|
/**
|
||||||
|
* If true, this pane is visible to the MCP server (Claude can list it,
|
||||||
|
* read its scrollback, etc.). Default-DENY: when undefined or false, the
|
||||||
|
* MCP surface filters this pane out entirely. Toggled via the per-pane
|
||||||
|
* MCP chip in the toolbar.
|
||||||
|
*/
|
||||||
|
mcpAllow?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Base xterm.js font size in px. Per-leaf offset adds on top of this. */
|
/** Base xterm.js font size in px. Per-leaf offset adds on top of this. */
|
||||||
|
|
@ -262,6 +269,15 @@ export function toggleBroadcast(root: TreeNode, leafId: NodeId): TreeNode {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Toggle a leaf's mcpAllow flag. Metadata-only — does NOT swap the id.
|
||||||
|
* Drives whether the MCP server includes this pane in its surface. */
|
||||||
|
export function toggleMcpAllow(root: TreeNode, leafId: NodeId): TreeNode {
|
||||||
|
return replaceById(root, leafId, (node) => {
|
||||||
|
if (node.kind !== "leaf") return node;
|
||||||
|
return { ...node, mcpAllow: !node.mcpAllow };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** Compute the actual pixel font size from a leaf's offset, clamped to
|
/** Compute the actual pixel font size from a leaf's offset, clamped to
|
||||||
* [MIN_FONT_SIZE, MAX_FONT_SIZE]. */
|
* [MIN_FONT_SIZE, MAX_FONT_SIZE]. */
|
||||||
export function resolveFontSize(offset: number | undefined): number {
|
export function resolveFontSize(offset: number | undefined): number {
|
||||||
|
|
@ -351,6 +367,7 @@ export function reshapeToPreset(
|
||||||
if (src.label !== undefined) slot.label = src.label;
|
if (src.label !== undefined) slot.label = src.label;
|
||||||
if (src.broadcast !== undefined) slot.broadcast = src.broadcast;
|
if (src.broadcast !== undefined) slot.broadcast = src.broadcast;
|
||||||
if (src.fontSizeOffset !== undefined) slot.fontSizeOffset = src.fontSizeOffset;
|
if (src.fontSizeOffset !== undefined) slot.fontSizeOffset = src.fontSizeOffset;
|
||||||
|
if (src.mcpAllow !== undefined) slot.mcpAllow = src.mcpAllow;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = slots.length; i < existingLeaves.length; i++) {
|
for (let i = slots.length; i < existingLeaves.length; i++) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue