feat: 4 tools nuevas + browser_list enriquecido
Tools nuevas (wrappers finos sobre funciones del registry functions/browser): - page_collect_console -> cdp_collect_console (console + exceptions + log, snapshot) - page_pdf -> cdp_print_pdf (Page.printToPDF a archivo) - dom_select_option -> cdp_select_option (<select> por value/texto + input/change) - dom_set_files -> cdp_set_file_input (subir archivos a <input type=file>) browser_list ahora enriquece cada master con CDP con pages (nº de page targets), active_title y active_url via GET /json (best-effort: si el puerto no responde los campos quedan a cero y el listado de procesos no falla). Total tools: 46 -> 50. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,9 +27,74 @@ func registerDomTools(s *server.MCPServer, d *deps) {
|
||||
s.AddTool(domTypeRefTool(), mcp.NewTypedToolHandler(d.handleDomTypeRef))
|
||||
s.AddTool(domHoverRefTool(), mcp.NewTypedToolHandler(d.handleDomHoverRef))
|
||||
s.AddTool(domClickXYTool(), mcp.NewTypedToolHandler(d.handleDomClickXY))
|
||||
s.AddTool(domSelectOptionTool(), mcp.NewTypedToolHandler(d.handleDomSelectOption))
|
||||
s.AddTool(domSetFilesTool(), mcp.NewTypedToolHandler(d.handleDomSetFiles))
|
||||
}
|
||||
}
|
||||
|
||||
// ---- dom_select_option (MUTA) ----
|
||||
|
||||
type domSelectOptionArgs struct {
|
||||
Port int `json:"port"`
|
||||
Selector string `json:"selector"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
func domSelectOptionTool() mcp.Tool {
|
||||
return mcp.NewTool("dom_select_option",
|
||||
mcp.WithDescription("Select an <option> in a native <select> element (by CSS selector), matching by option value first, then by visible text, and firing input/change events so React/Vue react. For custom (non-<select>) dropdowns use dom_click_ref on the trigger then on the option instead."),
|
||||
mcp.WithNumber("port", mcp.Description("CDP port. Default 9333 (Chrome isolated del MCP); usa 9222 explícito solo para adjuntarte al navegador diario.")),
|
||||
mcp.WithString("selector", mcp.Required(), mcp.Description("CSS selector of the <select> element.")),
|
||||
mcp.WithString("value", mcp.Required(), mcp.Description("Option value (or visible text if no value matches).")),
|
||||
)
|
||||
}
|
||||
|
||||
func (d *deps) handleDomSelectOption(_ context.Context, _ mcp.CallToolRequest, a domSelectOptionArgs) (*mcp.CallToolResult, error) {
|
||||
if a.Selector == "" || a.Value == "" {
|
||||
return mcp.NewToolResultError("selector and value are required"), nil
|
||||
}
|
||||
err := d.withConn(portOr(a.Port), func(c *browser.CDPConn) error {
|
||||
return browser.CdpSelectOption(c, a.Selector, a.Value)
|
||||
})
|
||||
if err != nil {
|
||||
return mcp.NewToolResultError(err.Error()), nil
|
||||
}
|
||||
return mcp.NewToolResultText(fmt.Sprintf("selected %q in %s", a.Value, a.Selector)), nil
|
||||
}
|
||||
|
||||
// ---- dom_set_files (MUTA) ----
|
||||
|
||||
type domSetFilesArgs struct {
|
||||
Port int `json:"port"`
|
||||
Selector string `json:"selector"`
|
||||
Paths []string `json:"paths"`
|
||||
}
|
||||
|
||||
func domSetFilesTool() mcp.Tool {
|
||||
return mcp.NewTool("dom_set_files",
|
||||
mcp.WithDescription("Upload files to an <input type=\"file\"> (by CSS selector) via DOM.setFileInputFiles, without driving the OS file picker. Paths must be absolute and readable by the Chrome process."),
|
||||
mcp.WithNumber("port", mcp.Description("CDP port. Default 9333 (Chrome isolated del MCP); usa 9222 explícito solo para adjuntarte al navegador diario.")),
|
||||
mcp.WithString("selector", mcp.Required(), mcp.Description("CSS selector of the file input element.")),
|
||||
mcp.WithArray("paths", mcp.Required(), mcp.Description("Absolute file paths to attach."), mcp.Items(map[string]any{"type": "string"})),
|
||||
)
|
||||
}
|
||||
|
||||
func (d *deps) handleDomSetFiles(_ context.Context, _ mcp.CallToolRequest, a domSetFilesArgs) (*mcp.CallToolResult, error) {
|
||||
if a.Selector == "" {
|
||||
return mcp.NewToolResultError("selector is required"), nil
|
||||
}
|
||||
if len(a.Paths) == 0 {
|
||||
return mcp.NewToolResultError("paths is required (at least one file)"), nil
|
||||
}
|
||||
err := d.withConn(portOr(a.Port), func(c *browser.CDPConn) error {
|
||||
return browser.CdpSetFileInput(c, a.Selector, a.Paths)
|
||||
})
|
||||
if err != nil {
|
||||
return mcp.NewToolResultError(err.Error()), nil
|
||||
}
|
||||
return mcp.NewToolResultText(fmt.Sprintf("attached %d file(s) to %s", len(a.Paths), a.Selector)), nil
|
||||
}
|
||||
|
||||
// defaultMode es el modo de velocidad cuando ni la llamada ni la sesión fijan uno.
|
||||
// "auto" = rápido (movimiento de ratón mínimo, escritura en un solo evento, settle
|
||||
// breve) — el modo por defecto del MCP. "human" (Bézier + esperas aleatorias) se
|
||||
|
||||
Reference in New Issue
Block a user