Default MCP tab tools to the active tab
Requiring an explicit tab_id forced every navigate or close through a preceding tabs_list call, which costs an MCP client a full round trip just to learn the ID the browser already considers current. navigate and tabs_close now resolve the active tab when tab_id is omitted, matching the screenshot tool. Resolution is explicit rather than forwarding None into the SDK, so the acting tool knows which tab it touched; tabs_close reports it, since closing the wrong tab is not recoverable. This stays in the MCP layer: the SDK and CLI signatures are unchanged.
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
// @ts-nocheck
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { WindowsCommands } from '../src/commands/windows';
|
||||
import { makeChromeMock } from './chrome-mock';
|
||||
|
||||
function makeWindowsChromeMock(windows) {
|
||||
const chrome = makeChromeMock();
|
||||
chrome.windows = {
|
||||
getAll: async () => windows,
|
||||
remove: async () => {},
|
||||
create: async () => ({ id: 99 }),
|
||||
};
|
||||
return chrome;
|
||||
}
|
||||
|
||||
test('windows.list prunes aliases for closed windows', async () => {
|
||||
globalThis.chrome = makeWindowsChromeMock([
|
||||
{ id: 1, focused: true, state: 'normal', tabs: [{ id: 10 }] },
|
||||
{ id: 2, focused: false, state: 'minimized', tabs: [] },
|
||||
]);
|
||||
globalThis.chrome.storage.local._store.windowAliases = {
|
||||
1: 'main',
|
||||
2: 'side',
|
||||
999: 'closed',
|
||||
};
|
||||
|
||||
const commands = new WindowsCommands({ jobs: {} });
|
||||
const result = await commands.commands['windows.list']({});
|
||||
|
||||
assert.deepEqual(result.map(w => [w.id, w.alias]), [[1, 'main'], [2, 'side']]);
|
||||
assert.deepEqual(globalThis.chrome.storage.local._store.windowAliases, { 1: 'main', 2: 'side' });
|
||||
});
|
||||
|
||||
test('windows.rename prunes stale aliases before saving the new name', async () => {
|
||||
globalThis.chrome = makeWindowsChromeMock([
|
||||
{ id: 1, focused: true, state: 'normal', tabs: [] },
|
||||
{ id: 2, focused: false, state: 'normal', tabs: [] },
|
||||
]);
|
||||
globalThis.chrome.storage.local._store.windowAliases = {
|
||||
1: 'main',
|
||||
999: 'closed',
|
||||
};
|
||||
|
||||
const commands = new WindowsCommands({ jobs: {} });
|
||||
await commands.commands['windows.rename']({ windowId: 2, name: 'work' });
|
||||
|
||||
assert.deepEqual(globalThis.chrome.storage.local._store.windowAliases, { 1: 'main', 2: 'work' });
|
||||
});
|
||||
|
||||
test('windows.close removes the closed window alias immediately', async () => {
|
||||
let removed = null;
|
||||
globalThis.chrome = makeWindowsChromeMock([
|
||||
{ id: 1, focused: true, state: 'normal', tabs: [] },
|
||||
{ id: 2, focused: false, state: 'normal', tabs: [] },
|
||||
]);
|
||||
globalThis.chrome.windows.remove = async id => { removed = id; };
|
||||
globalThis.chrome.storage.local._store.windowAliases = {
|
||||
1: 'main',
|
||||
2: 'side',
|
||||
999: 'closed',
|
||||
};
|
||||
|
||||
const commands = new WindowsCommands({ jobs: {} });
|
||||
await commands.commands['windows.close']({ windowId: 2 });
|
||||
|
||||
assert.equal(removed, 2);
|
||||
assert.deepEqual(globalThis.chrome.storage.local._store.windowAliases, { 1: 'main' });
|
||||
});
|
||||
Reference in New Issue
Block a user