feat: browser_mcp — servidor MCP de control de navegador CDP (33 tools + pool de conexiones)
This commit is contained in:
+110
@@ -0,0 +1,110 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/mark3labs/mcp-go/mcp"
|
||||
"github.com/mark3labs/mcp-go/server"
|
||||
|
||||
"fn-registry/functions/browser"
|
||||
)
|
||||
|
||||
const htmlMax = 200_000
|
||||
|
||||
// registerReadTools wires page_get_html, page_eval_js (MUTA), page_screenshot.
|
||||
func registerReadTools(s *server.MCPServer, d *deps) {
|
||||
s.AddTool(pageGetHTMLTool(), mcp.NewTypedToolHandler(d.handlePageGetHTML))
|
||||
s.AddTool(pageScreenshotTool(), mcp.NewTypedToolHandler(d.handlePageScreenshot))
|
||||
|
||||
if !d.readOnly {
|
||||
s.AddTool(pageEvalJSTool(), mcp.NewTypedToolHandler(d.handlePageEvalJS))
|
||||
}
|
||||
}
|
||||
|
||||
// ---- page_get_html ----
|
||||
|
||||
type pageGetHTMLArgs struct {
|
||||
Port int `json:"port"`
|
||||
}
|
||||
|
||||
func pageGetHTMLTool() mcp.Tool {
|
||||
return mcp.NewTool("page_get_html",
|
||||
mcp.WithDescription("Return the current page's full serialized HTML (outerHTML). Truncated to 200000 chars."),
|
||||
mcp.WithNumber("port", mcp.Description("CDP port. Default 9222.")),
|
||||
)
|
||||
}
|
||||
|
||||
func (d *deps) handlePageGetHTML(_ context.Context, _ mcp.CallToolRequest, a pageGetHTMLArgs) (*mcp.CallToolResult, error) {
|
||||
var html string
|
||||
err := d.withConn(portOr(a.Port), func(c *browser.CDPConn) error {
|
||||
var e error
|
||||
html, e = browser.CdpGetHTML(c)
|
||||
return e
|
||||
})
|
||||
if err != nil {
|
||||
return mcp.NewToolResultError(err.Error()), nil
|
||||
}
|
||||
return mcp.NewToolResultText(truncate(html, htmlMax)), nil
|
||||
}
|
||||
|
||||
// ---- page_eval_js (MUTA) ----
|
||||
|
||||
type pageEvalJSArgs struct {
|
||||
Port int `json:"port"`
|
||||
Expression string `json:"expression"`
|
||||
}
|
||||
|
||||
func pageEvalJSTool() mcp.Tool {
|
||||
return mcp.NewTool("page_eval_js",
|
||||
mcp.WithDescription("Evaluate a JavaScript expression in the page context via Runtime.evaluate. Returns the stringified result."),
|
||||
mcp.WithNumber("port", mcp.Description("CDP port. Default 9222.")),
|
||||
mcp.WithString("expression", mcp.Required(), mcp.Description("JavaScript expression to evaluate.")),
|
||||
)
|
||||
}
|
||||
|
||||
func (d *deps) handlePageEvalJS(_ context.Context, _ mcp.CallToolRequest, a pageEvalJSArgs) (*mcp.CallToolResult, error) {
|
||||
if a.Expression == "" {
|
||||
return mcp.NewToolResultError("expression is required"), nil
|
||||
}
|
||||
var res string
|
||||
err := d.withConn(portOr(a.Port), func(c *browser.CDPConn) error {
|
||||
var e error
|
||||
res, e = browser.CdpEvaluate(c, a.Expression)
|
||||
return e
|
||||
})
|
||||
if err != nil {
|
||||
return mcp.NewToolResultError(err.Error()), nil
|
||||
}
|
||||
return mcp.NewToolResultText(truncate(res, htmlMax)), nil
|
||||
}
|
||||
|
||||
// ---- page_screenshot ----
|
||||
|
||||
type pageScreenshotArgs struct {
|
||||
Port int `json:"port"`
|
||||
Path string `json:"path"`
|
||||
FullPage bool `json:"full_page"`
|
||||
}
|
||||
|
||||
func pageScreenshotTool() mcp.Tool {
|
||||
return mcp.NewTool("page_screenshot",
|
||||
mcp.WithDescription("Capture a screenshot of the current page and write it to a local path (.png/.jpg)."),
|
||||
mcp.WithNumber("port", mcp.Description("CDP port. Default 9222.")),
|
||||
mcp.WithString("path", mcp.Required(), mcp.Description("Output file path (.png or .jpg).")),
|
||||
mcp.WithBoolean("full_page", mcp.Description("Capture the full scroll height instead of just the viewport.")),
|
||||
)
|
||||
}
|
||||
|
||||
func (d *deps) handlePageScreenshot(_ context.Context, _ mcp.CallToolRequest, a pageScreenshotArgs) (*mcp.CallToolResult, error) {
|
||||
if a.Path == "" {
|
||||
return mcp.NewToolResultError("path is required"), nil
|
||||
}
|
||||
opts := browser.CdpScreenshotOpts{FullPage: a.FullPage}
|
||||
err := d.withConn(portOr(a.Port), func(c *browser.CDPConn) error {
|
||||
return browser.CdpScreenshot(c, a.Path, opts)
|
||||
})
|
||||
if err != nil {
|
||||
return mcp.NewToolResultError(err.Error()), nil
|
||||
}
|
||||
return mcp.NewToolResultText("screenshot saved to " + a.Path), nil
|
||||
}
|
||||
Reference in New Issue
Block a user