diff --git a/README.md b/README.md index 462fd43..3f281f8 100644 --- a/README.md +++ b/README.md @@ -276,38 +276,47 @@ X Y coordinate space, based on the provided screenshot. - **browser_snapshot** + - Title: Page snapshot - Description: Capture accessibility snapshot of the current page, this is better than screenshot - Parameters: None + - Read-only: **true** - **browser_click** + - Title: Click - Description: Perform click on a web page - Parameters: - `element` (string): Human-readable element description used to obtain permission to interact with the element - `ref` (string): Exact target element reference from the page snapshot + - Read-only: **false** - **browser_drag** + - Title: Drag mouse - Description: Perform drag and drop between two elements - Parameters: - `startElement` (string): Human-readable source element description used to obtain the permission to interact with the element - `startRef` (string): Exact source element reference from the page snapshot - `endElement` (string): Human-readable target element description used to obtain the permission to interact with the element - `endRef` (string): Exact target element reference from the page snapshot + - Read-only: **false** - **browser_hover** + - Title: Hover mouse - Description: Hover over element on page - Parameters: - `element` (string): Human-readable element description used to obtain permission to interact with the element - `ref` (string): Exact target element reference from the page snapshot + - Read-only: **true** - **browser_type** + - Title: Type text - Description: Type text into editable element - Parameters: - `element` (string): Human-readable element description used to obtain permission to interact with the element @@ -315,54 +324,66 @@ X Y coordinate space, based on the provided screenshot. - `text` (string): Text to type into the element - `submit` (boolean, optional): Whether to submit entered text (press Enter after) - `slowly` (boolean, optional): Whether to type one character at a time. Useful for triggering key handlers in the page. By default entire text is filled in at once. + - Read-only: **false** - **browser_select_option** + - Title: Select option - Description: Select an option in a dropdown - Parameters: - `element` (string): Human-readable element description used to obtain permission to interact with the element - `ref` (string): Exact target element reference from the page snapshot - `values` (array): Array of values to select in the dropdown. This can be a single value or multiple values. + - Read-only: **false** - **browser_take_screenshot** + - Title: Take a screenshot - Description: Take a screenshot of the current page. You can't perform actions based on the screenshot, use browser_snapshot for actions. - Parameters: - `raw` (boolean, optional): Whether to return without compression (in PNG format). Default is false, which returns a JPEG image. - `element` (string, optional): Human-readable element description used to obtain permission to screenshot the element. If not provided, the screenshot will be taken of viewport. If element is provided, ref must be provided too. - `ref` (string, optional): Exact target element reference from the page snapshot. If not provided, the screenshot will be taken of viewport. If ref is provided, element must be provided too. + - Read-only: **true** ### Vision-based Interactions - **browser_screen_capture** + - Title: Take a screenshot - Description: Take a screenshot of the current page - Parameters: None + - Read-only: **true** - **browser_screen_move_mouse** + - Title: Move mouse - Description: Move mouse to a given position - Parameters: - `element` (string): Human-readable element description used to obtain permission to interact with the element - `x` (number): X coordinate - `y` (number): Y coordinate + - Read-only: **true** - **browser_screen_click** + - Title: Click - Description: Click left mouse button - Parameters: - `element` (string): Human-readable element description used to obtain permission to interact with the element - `x` (number): X coordinate - `y` (number): Y coordinate + - Read-only: **false** - **browser_screen_drag** + - Title: Drag mouse - Description: Drag left mouse button - Parameters: - `element` (string): Human-readable element description used to obtain permission to interact with the element @@ -370,143 +391,188 @@ X Y coordinate space, based on the provided screenshot. - `startY` (number): Start Y coordinate - `endX` (number): End X coordinate - `endY` (number): End Y coordinate + - Read-only: **false** - **browser_screen_type** + - Title: Type text - Description: Type text - Parameters: - `text` (string): Text to type into the element - `submit` (boolean, optional): Whether to submit entered text (press Enter after) + - Read-only: **false** ### Tab Management - **browser_tab_list** + - Title: List tabs - Description: List browser tabs - Parameters: None + - Read-only: **true** - **browser_tab_new** + - Title: Open a new tab - Description: Open a new tab - Parameters: - `url` (string, optional): The URL to navigate to in the new tab. If not provided, the new tab will be blank. + - Read-only: **true** - **browser_tab_select** + - Title: Select a tab - Description: Select a tab by index - Parameters: - `index` (number): The index of the tab to select + - Read-only: **true** - **browser_tab_close** + - Title: Close a tab - Description: Close a tab - Parameters: - `index` (number, optional): The index of the tab to close. Closes current tab if not provided. + - Read-only: **false** ### Navigation - **browser_navigate** + - Title: Navigate to a URL - Description: Navigate to a URL - Parameters: - `url` (string): The URL to navigate to + - Read-only: **false** - **browser_navigate_back** + - Title: Go back - Description: Go back to the previous page - Parameters: None + - Read-only: **true** - **browser_navigate_forward** + - Title: Go forward - Description: Go forward to the next page - Parameters: None + - Read-only: **true** ### Keyboard - **browser_press_key** + - Title: Press a key - Description: Press a key on the keyboard - Parameters: - `key` (string): Name of the key to press or a character to generate, such as `ArrowLeft` or `a` + - Read-only: **false** ### Console - **browser_console_messages** + - Title: Get console messages - Description: Returns all console messages - Parameters: None + - Read-only: **true** ### Files and Media - **browser_file_upload** + - Title: Upload files - Description: Upload one or multiple files - Parameters: - `paths` (array): The absolute paths to the files to upload. Can be a single file or multiple files. + - Read-only: **false** - **browser_pdf_save** + - Title: Save as PDF - Description: Save page as PDF - Parameters: None + - Read-only: **true** ### Utilities - **browser_close** + - Title: Close browser - Description: Close the page - Parameters: None + - Read-only: **true** - **browser_wait** + - Title: Wait - Description: Wait for a specified time in seconds - Parameters: - `time` (number): The time to wait in seconds + - Read-only: **true** - **browser_resize** + - Title: Resize browser window - Description: Resize the browser window - Parameters: - `width` (number): Width of the browser window - `height` (number): Height of the browser window + - Read-only: **true** - **browser_install** + - Title: Install the browser specified in the config - Description: Install the browser specified in the config. Call this if you get an error about the browser not being installed. - Parameters: None + - Read-only: **false** - **browser_handle_dialog** + - Title: Handle a dialog - Description: Handle a dialog - Parameters: - `accept` (boolean): Whether to accept the dialog. - `promptText` (string, optional): The text of the prompt in case of a prompt dialog. + - Read-only: **false** + + + +- **browser_network_requests** + - Title: List network requests + - Description: Returns all network requests since loading the page + - Parameters: None + - Read-only: **true** ### Testing - **browser_generate_playwright_test** + - Title: Generate a Playwright test - Description: Generate a Playwright test for given scenario - Parameters: - `name` (string): The name of the test - `description` (string): The description of the test - `steps` (array): The steps of the test + - Read-only: **true** diff --git a/package-lock.json b/package-lock.json index b5dff03..f684c63 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.0.20", "license": "Apache-2.0", "dependencies": { - "@modelcontextprotocol/sdk": "^1.10.1", + "@modelcontextprotocol/sdk": "^1.11.0", "commander": "^13.1.0", "playwright": "1.53.0-alpha-1746218818000", "yaml": "^2.7.1", @@ -228,9 +228,9 @@ } }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.10.1.tgz", - "integrity": "sha512-xNYdFdkJqEfIaTVP1gPKoEvluACHZsHZegIoICX8DM1o6Qf3G5u2BQJHmgd0n4YgRPqqK/u1ujQvrgAxxSJT9w==", + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.11.0.tgz", + "integrity": "sha512-k/1pb70eD638anoi0e8wUGAlbMJXyvdV4p62Ko+EZ7eBe1xMx8Uhak1R5DgfoofsK5IBBnRwsYGTaLZl+6/+RQ==", "license": "MIT", "dependencies": { "content-type": "^1.0.5", diff --git a/package.json b/package.json index df49b9c..65da207 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "license": "Apache-2.0", "scripts": { "build": "tsc", - "lint": "npm run update-readme && eslint .", + "lint": "npm run update-readme && eslint . && tsc --noEmit", "update-readme": "node utils/update-readme.js", "watch": "tsc --watch", "test": "playwright test", @@ -35,7 +35,7 @@ } }, "dependencies": { - "@modelcontextprotocol/sdk": "^1.10.1", + "@modelcontextprotocol/sdk": "^1.11.0", "commander": "^13.1.0", "playwright": "1.53.0-alpha-1746218818000", "yaml": "^2.7.1", diff --git a/src/server.ts b/src/server.ts index 5e7da17..405af78 100644 --- a/src/server.ts +++ b/src/server.ts @@ -15,7 +15,7 @@ */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; -import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js'; +import { CallToolRequestSchema, ListToolsRequestSchema, Tool as McpTool } from '@modelcontextprotocol/sdk/types.js'; import { zodToJsonSchema } from 'zod-to-json-schema'; import { Context } from './context.js'; @@ -43,8 +43,14 @@ export function createServerWithTools(serverOptions: MCPServerOptions, config: C tools: tools.map(tool => ({ name: tool.schema.name, description: tool.schema.description, - inputSchema: zodToJsonSchema(tool.schema.inputSchema) - })), + inputSchema: zodToJsonSchema(tool.schema.inputSchema), + annotations: { + title: tool.schema.title, + readOnlyHint: tool.schema.type === 'readOnly', + destructiveHint: tool.schema.type === 'destructive', + openWorldHint: true, + }, + })) as McpTool[], }; }); diff --git a/src/tools/common.ts b/src/tools/common.ts index a615f0d..40c7e3f 100644 --- a/src/tools/common.ts +++ b/src/tools/common.ts @@ -22,10 +22,12 @@ const wait: ToolFactory = captureSnapshot => defineTool({ schema: { name: 'browser_wait', + title: 'Wait', description: 'Wait for a specified time in seconds', inputSchema: z.object({ time: z.number().describe('The time to wait in seconds'), }), + type: 'readOnly', }, handle: async (context, params) => { @@ -43,8 +45,10 @@ const close = defineTool({ schema: { name: 'browser_close', + title: 'Close browser', description: 'Close the page', inputSchema: z.object({}), + type: 'readOnly', }, handle: async context => { @@ -61,11 +65,13 @@ const resize: ToolFactory = captureSnapshot => defineTool({ capability: 'core', schema: { name: 'browser_resize', + title: 'Resize browser window', description: 'Resize the browser window', inputSchema: z.object({ width: z.number().describe('Width of the browser window'), height: z.number().describe('Height of the browser window'), }), + type: 'readOnly', }, handle: async (context, params) => { diff --git a/src/tools/console.ts b/src/tools/console.ts index b0c58f5..2779e34 100644 --- a/src/tools/console.ts +++ b/src/tools/console.ts @@ -21,8 +21,10 @@ const console = defineTool({ capability: 'core', schema: { name: 'browser_console_messages', + title: 'Get console messages', description: 'Returns all console messages', inputSchema: z.object({}), + type: 'readOnly', }, handle: async context => { const messages = context.currentTabOrDie().console(); diff --git a/src/tools/dialogs.ts b/src/tools/dialogs.ts index 62105cc..348e461 100644 --- a/src/tools/dialogs.ts +++ b/src/tools/dialogs.ts @@ -22,11 +22,13 @@ const handleDialog: ToolFactory = captureSnapshot => defineTool({ schema: { name: 'browser_handle_dialog', + title: 'Handle a dialog', description: 'Handle a dialog', inputSchema: z.object({ accept: z.boolean().describe('Whether to accept the dialog.'), promptText: z.string().optional().describe('The text of the prompt in case of a prompt dialog.'), }), + type: 'destructive', }, handle: async (context, params) => { diff --git a/src/tools/files.ts b/src/tools/files.ts index 4ab6d3f..2dc7837 100644 --- a/src/tools/files.ts +++ b/src/tools/files.ts @@ -22,10 +22,12 @@ const uploadFile: ToolFactory = captureSnapshot => defineTool({ schema: { name: 'browser_file_upload', + title: 'Upload files', description: 'Upload one or multiple files', inputSchema: z.object({ paths: z.array(z.string()).describe('The absolute paths to the files to upload. Can be a single file or multiple files.'), }), + type: 'destructive', }, handle: async (context, params) => { diff --git a/src/tools/install.ts b/src/tools/install.ts index f9b16ad..afa3247 100644 --- a/src/tools/install.ts +++ b/src/tools/install.ts @@ -26,8 +26,10 @@ const install = defineTool({ capability: 'install', schema: { name: 'browser_install', + title: 'Install the browser specified in the config', description: 'Install the browser specified in the config. Call this if you get an error about the browser not being installed.', inputSchema: z.object({}), + type: 'destructive', }, handle: async context => { diff --git a/src/tools/keyboard.ts b/src/tools/keyboard.ts index 0527cbf..521aab2 100644 --- a/src/tools/keyboard.ts +++ b/src/tools/keyboard.ts @@ -22,10 +22,12 @@ const pressKey: ToolFactory = captureSnapshot => defineTool({ schema: { name: 'browser_press_key', + title: 'Press a key', description: 'Press a key on the keyboard', inputSchema: z.object({ key: z.string().describe('Name of the key to press or a character to generate, such as `ArrowLeft` or `a`'), }), + type: 'destructive', }, handle: async (context, params) => { diff --git a/src/tools/navigate.ts b/src/tools/navigate.ts index 1279418..501576e 100644 --- a/src/tools/navigate.ts +++ b/src/tools/navigate.ts @@ -22,10 +22,12 @@ const navigate: ToolFactory = captureSnapshot => defineTool({ schema: { name: 'browser_navigate', + title: 'Navigate to a URL', description: 'Navigate to a URL', inputSchema: z.object({ url: z.string().describe('The URL to navigate to'), }), + type: 'destructive', }, handle: async (context, params) => { @@ -49,8 +51,10 @@ const goBack: ToolFactory = captureSnapshot => defineTool({ capability: 'history', schema: { name: 'browser_navigate_back', + title: 'Go back', description: 'Go back to the previous page', inputSchema: z.object({}), + type: 'readOnly', }, handle: async context => { @@ -73,8 +77,10 @@ const goForward: ToolFactory = captureSnapshot => defineTool({ capability: 'history', schema: { name: 'browser_navigate_forward', + title: 'Go forward', description: 'Go forward to the next page', inputSchema: z.object({}), + type: 'readOnly', }, handle: async context => { const tab = context.currentTabOrDie(); diff --git a/src/tools/network.ts b/src/tools/network.ts index e9499e2..9e1946c 100644 --- a/src/tools/network.ts +++ b/src/tools/network.ts @@ -24,8 +24,10 @@ const requests = defineTool({ schema: { name: 'browser_network_requests', + title: 'List network requests', description: 'Returns all network requests since loading the page', inputSchema: z.object({}), + type: 'readOnly', }, handle: async context => { diff --git a/src/tools/pdf.ts b/src/tools/pdf.ts index 79dca64..ff2465b 100644 --- a/src/tools/pdf.ts +++ b/src/tools/pdf.ts @@ -25,8 +25,10 @@ const pdf = defineTool({ schema: { name: 'browser_pdf_save', + title: 'Save as PDF', description: 'Save page as PDF', inputSchema: z.object({}), + type: 'readOnly', }, handle: async context => { diff --git a/src/tools/screen.ts b/src/tools/screen.ts index 88ca40c..a380311 100644 --- a/src/tools/screen.ts +++ b/src/tools/screen.ts @@ -27,8 +27,10 @@ const screenshot = defineTool({ capability: 'core', schema: { name: 'browser_screen_capture', + title: 'Take a screenshot', description: 'Take a screenshot of the current page', inputSchema: z.object({}), + type: 'readOnly', }, handle: async context => { @@ -59,11 +61,13 @@ const moveMouse = defineTool({ capability: 'core', schema: { name: 'browser_screen_move_mouse', + title: 'Move mouse', description: 'Move mouse to a given position', inputSchema: elementSchema.extend({ x: z.number().describe('X coordinate'), y: z.number().describe('Y coordinate'), }), + type: 'readOnly', }, handle: async (context, params) => { @@ -86,11 +90,13 @@ const click = defineTool({ capability: 'core', schema: { name: 'browser_screen_click', + title: 'Click', description: 'Click left mouse button', inputSchema: elementSchema.extend({ x: z.number().describe('X coordinate'), y: z.number().describe('Y coordinate'), }), + type: 'destructive', }, handle: async (context, params) => { @@ -117,9 +123,9 @@ const click = defineTool({ const drag = defineTool({ capability: 'core', - schema: { name: 'browser_screen_drag', + title: 'Drag mouse', description: 'Drag left mouse button', inputSchema: elementSchema.extend({ startX: z.number().describe('Start X coordinate'), @@ -127,6 +133,7 @@ const drag = defineTool({ endX: z.number().describe('End X coordinate'), endY: z.number().describe('End Y coordinate'), }), + type: 'destructive', }, handle: async (context, params) => { @@ -158,14 +165,15 @@ const drag = defineTool({ const type = defineTool({ capability: 'core', - schema: { name: 'browser_screen_type', + title: 'Type text', description: 'Type text', inputSchema: z.object({ text: z.string().describe('Text to type into the element'), submit: z.boolean().optional().describe('Whether to submit entered text (press Enter after)'), }), + type: 'destructive', }, handle: async (context, params) => { diff --git a/src/tools/snapshot.ts b/src/tools/snapshot.ts index b0a4bd1..b969b88 100644 --- a/src/tools/snapshot.ts +++ b/src/tools/snapshot.ts @@ -26,8 +26,10 @@ const snapshot = defineTool({ capability: 'core', schema: { name: 'browser_snapshot', + title: 'Page snapshot', description: 'Capture accessibility snapshot of the current page, this is better than screenshot', inputSchema: z.object({}), + type: 'readOnly', }, handle: async context => { @@ -50,8 +52,10 @@ const click = defineTool({ capability: 'core', schema: { name: 'browser_click', + title: 'Click', description: 'Perform click on a web page', inputSchema: elementSchema, + type: 'destructive', }, handle: async (context, params) => { @@ -76,6 +80,7 @@ const drag = defineTool({ capability: 'core', schema: { name: 'browser_drag', + title: 'Drag mouse', description: 'Perform drag and drop between two elements', inputSchema: z.object({ startElement: z.string().describe('Human-readable source element description used to obtain the permission to interact with the element'), @@ -83,6 +88,7 @@ const drag = defineTool({ endElement: z.string().describe('Human-readable target element description used to obtain the permission to interact with the element'), endRef: z.string().describe('Exact target element reference from the page snapshot'), }), + type: 'destructive', }, handle: async (context, params) => { @@ -108,8 +114,10 @@ const hover = defineTool({ capability: 'core', schema: { name: 'browser_hover', + title: 'Hover mouse', description: 'Hover over element on page', inputSchema: elementSchema, + type: 'readOnly', }, handle: async (context, params) => { @@ -140,8 +148,10 @@ const type = defineTool({ capability: 'core', schema: { name: 'browser_type', + title: 'Type text', description: 'Type text into editable element', inputSchema: typeSchema, + type: 'destructive', }, handle: async (context, params) => { @@ -184,8 +194,10 @@ const selectOption = defineTool({ capability: 'core', schema: { name: 'browser_select_option', + title: 'Select option', description: 'Select an option in a dropdown', inputSchema: selectOptionSchema, + type: 'destructive', }, handle: async (context, params) => { @@ -221,8 +233,10 @@ const screenshot = defineTool({ capability: 'core', schema: { name: 'browser_take_screenshot', + title: 'Take a screenshot', description: `Take a screenshot of the current page. You can't perform actions based on the screenshot, use browser_snapshot for actions.`, inputSchema: screenshotSchema, + type: 'readOnly', }, handle: async (context, params) => { diff --git a/src/tools/tabs.ts b/src/tools/tabs.ts index f2226da..4133bf1 100644 --- a/src/tools/tabs.ts +++ b/src/tools/tabs.ts @@ -22,8 +22,10 @@ const listTabs = defineTool({ schema: { name: 'browser_tab_list', + title: 'List tabs', description: 'List browser tabs', inputSchema: z.object({}), + type: 'readOnly', }, handle: async context => { @@ -47,10 +49,12 @@ const selectTab: ToolFactory = captureSnapshot => defineTool({ schema: { name: 'browser_tab_select', + title: 'Select a tab', description: 'Select a tab by index', inputSchema: z.object({ index: z.number().describe('The index of the tab to select'), }), + type: 'readOnly', }, handle: async (context, params) => { @@ -72,10 +76,12 @@ const newTab: ToolFactory = captureSnapshot => defineTool({ schema: { name: 'browser_tab_new', + title: 'Open a new tab', description: 'Open a new tab', inputSchema: z.object({ url: z.string().optional().describe('The URL to navigate to in the new tab. If not provided, the new tab will be blank.'), }), + type: 'readOnly', }, handle: async (context, params) => { @@ -99,10 +105,12 @@ const closeTab: ToolFactory = captureSnapshot => defineTool({ schema: { name: 'browser_tab_close', + title: 'Close a tab', description: 'Close a tab', inputSchema: z.object({ index: z.number().optional().describe('The index of the tab to close. Closes current tab if not provided.'), }), + type: 'destructive', }, handle: async (context, params) => { diff --git a/src/tools/testing.ts b/src/tools/testing.ts index 3046cde..9518d19 100644 --- a/src/tools/testing.ts +++ b/src/tools/testing.ts @@ -28,8 +28,10 @@ const generateTest = defineTool({ schema: { name: 'browser_generate_playwright_test', + title: 'Generate a Playwright test', description: 'Generate a Playwright test for given scenario', inputSchema: generateTestSchema, + type: 'readOnly', }, handle: async (context, params) => { diff --git a/src/tools/tool.ts b/src/tools/tool.ts index 84e9bce..4b88c89 100644 --- a/src/tools/tool.ts +++ b/src/tools/tool.ts @@ -22,8 +22,10 @@ import type { ToolCapability } from '../../config.js'; export type ToolSchema = { name: string; + title: string; description: string; inputSchema: Input; + type: 'readOnly' | 'destructive'; }; type InputType = z.Schema; diff --git a/utils/update-readme.js b/utils/update-readme.js index 35d5e63..d0f6cea 100644 --- a/utils/update-readme.js +++ b/utils/update-readme.js @@ -28,6 +28,7 @@ import filesTools from '../lib/tools/files.js'; import installTools from '../lib/tools/install.js'; import keyboardTools from '../lib/tools/keyboard.js'; import navigateTools from '../lib/tools/navigate.js'; +import networkTools from '../lib/tools/network.js'; import pdfTools from '../lib/tools/pdf.js'; import snapshotTools from '../lib/tools/snapshot.js'; import tabsTools from '../lib/tools/tabs.js'; @@ -62,6 +63,7 @@ const categories = { ...commonTools(true), ...installTools, ...dialogsTools(true), + ...networkTools, ], 'Testing': [ ...testTools, @@ -75,74 +77,37 @@ const kStartMarker = ``; const kEndMarker = ``; /** - * @param {ParsedToolSchema} tool + * @param {import('../src/tools/tool.js').ToolSchema} tool * @returns {string} */ function formatToolForReadme(tool) { const lines = /** @type {string[]} */ ([]); lines.push(`\n\n`); lines.push(`- **${tool.name}**\n`); + lines.push(` - Title: ${tool.title}\n`); lines.push(` - Description: ${tool.description}\n`); - if (tool.parameters && tool.parameters.length > 0) { + const inputSchema = /** @type {any} */ (zodToJsonSchema(tool.inputSchema || {})); + const requiredParams = inputSchema.required || []; + if (inputSchema.properties && Object.keys(inputSchema.properties).length) { lines.push(` - Parameters:\n`); - tool.parameters.forEach(param => { + Object.entries(inputSchema.properties).forEach(([name, param]) => { + const optional = !requiredParams.includes(name); const meta = /** @type {string[]} */ ([]); if (param.type) meta.push(param.type); - if (param.optional) + if (optional) meta.push('optional'); - lines.push(` - \`${param.name}\` ${meta.length ? `(${meta.join(', ')})` : ''}: ${param.description}\n`); + lines.push(` - \`${name}\` ${meta.length ? `(${meta.join(', ')})` : ''}: ${param.description}\n`); }); } else { lines.push(` - Parameters: None\n`); } - + lines.push(` - Read-only: **${tool.type === 'readOnly'}**\n`); lines.push('\n'); return lines.join(''); } -/** - * @typedef {{ - * name: any; - * description: any; - * parameters: { - * name: string; - * description: string; - * optional: boolean; - * type: string; - * }[]; - *}} ParsedToolSchema - */ - -/** - * @param {import('../src/tools/tool').ToolSchema} schema - * @returns {ParsedToolSchema} - */ -function processToolSchema(schema) { - const inputSchema = /** @type {import('zod-to-json-schema').JsonSchema7ObjectType} */ (zodToJsonSchema(schema.inputSchema || {})); - if (inputSchema.type !== 'object') - throw new Error(`Tool ${schema.name} input schema is not an object`); - - // In JSON Schema, properties are considered optional unless listed in the required array - const requiredParams = inputSchema?.required || []; - - const parameters = Object.entries(inputSchema.properties).map(([name, prop]) => { - return { - name, - description: prop.description || '', - optional: !requiredParams.includes(name), - type: /** @type {any} */ (prop).type, - }; - }); - - return { - name: schema.name, - description: schema.description, - parameters - }; -} - async function updateReadme() { console.log('Loading tool information from compiled modules...'); @@ -154,10 +119,8 @@ async function updateReadme() { for (const [category, categoryTools] of Object.entries(categories)) { generatedLines.push(`### ${category}\n\n`); - for (const tool of categoryTools) { - const scheme = processToolSchema(tool.schema); - generatedLines.push(formatToolForReadme(scheme)); - } + for (const tool of categoryTools) + generatedLines.push(formatToolForReadme(tool.schema)); } const readmePath = path.join(path.dirname(__filename), '..', 'README.md');