@olib-ai/owl-browser-mcp 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +258 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22529,6 +22529,204 @@ var openapi_default = {
|
|
|
22529
22529
|
}
|
|
22530
22530
|
}
|
|
22531
22531
|
},
|
|
22532
|
+
"/api/execute/browser_extract_site": {
|
|
22533
|
+
post: {
|
|
22534
|
+
summary: "Browser Extract Site",
|
|
22535
|
+
description: "Extract content from multiple pages of a website. Crawls links starting from a URL and extracts content in the specified format. Returns a job_id immediately for async progress tracking. Use browser_extract_site_progress to monitor and browser_extract_site_result to get output.",
|
|
22536
|
+
tags: [
|
|
22537
|
+
"General"
|
|
22538
|
+
],
|
|
22539
|
+
requestBody: {
|
|
22540
|
+
required: true,
|
|
22541
|
+
content: {
|
|
22542
|
+
"application/json": {
|
|
22543
|
+
schema: {
|
|
22544
|
+
type: "object",
|
|
22545
|
+
properties: {
|
|
22546
|
+
context_id: {
|
|
22547
|
+
type: "string",
|
|
22548
|
+
description: "The unique identifier of the browser context (e.g., 'ctx_000001')"
|
|
22549
|
+
},
|
|
22550
|
+
url: {
|
|
22551
|
+
type: "string",
|
|
22552
|
+
description: "Starting URL to begin extraction from"
|
|
22553
|
+
},
|
|
22554
|
+
depth: {
|
|
22555
|
+
type: "integer",
|
|
22556
|
+
description: "How many link levels to follow from the starting page. Default: 2. Higher values extract more pages but take longer"
|
|
22557
|
+
},
|
|
22558
|
+
max_pages: {
|
|
22559
|
+
type: "integer",
|
|
22560
|
+
description: "Maximum number of pages to extract. Default: 5. Limits total extraction to prevent runaway crawling"
|
|
22561
|
+
},
|
|
22562
|
+
follow_external: {
|
|
22563
|
+
type: "boolean",
|
|
22564
|
+
description: "Whether to follow links to external domains. Default: false. When false, only links within the same domain are followed"
|
|
22565
|
+
},
|
|
22566
|
+
output_format: {
|
|
22567
|
+
type: "string",
|
|
22568
|
+
description: "Output format for extracted content: 'markdown' (default), 'text', or 'json'. Markdown preserves structure, text is plain, JSON includes metadata",
|
|
22569
|
+
enum: [
|
|
22570
|
+
"markdown",
|
|
22571
|
+
"text",
|
|
22572
|
+
"json"
|
|
22573
|
+
]
|
|
22574
|
+
},
|
|
22575
|
+
include_images: {
|
|
22576
|
+
type: "boolean",
|
|
22577
|
+
description: "Include resolved image URLs in output. Default: true"
|
|
22578
|
+
},
|
|
22579
|
+
include_metadata: {
|
|
22580
|
+
type: "boolean",
|
|
22581
|
+
description: "Include page title and description metadata. Default: true"
|
|
22582
|
+
},
|
|
22583
|
+
exclude_patterns: {
|
|
22584
|
+
type: "string",
|
|
22585
|
+
description: `JSON array of URL patterns to skip (glob patterns). Example: '["*/login*", "*/admin/*"]'`
|
|
22586
|
+
},
|
|
22587
|
+
timeout_per_page: {
|
|
22588
|
+
type: "integer",
|
|
22589
|
+
description: "Timeout per page in milliseconds. Default: 10000 (10 seconds)"
|
|
22590
|
+
}
|
|
22591
|
+
},
|
|
22592
|
+
required: [
|
|
22593
|
+
"context_id",
|
|
22594
|
+
"url"
|
|
22595
|
+
]
|
|
22596
|
+
}
|
|
22597
|
+
}
|
|
22598
|
+
}
|
|
22599
|
+
},
|
|
22600
|
+
responses: {
|
|
22601
|
+
"200": {
|
|
22602
|
+
description: "Successful response"
|
|
22603
|
+
},
|
|
22604
|
+
"400": {
|
|
22605
|
+
description: "Bad request"
|
|
22606
|
+
},
|
|
22607
|
+
"401": {
|
|
22608
|
+
description: "Unauthorized"
|
|
22609
|
+
}
|
|
22610
|
+
}
|
|
22611
|
+
}
|
|
22612
|
+
},
|
|
22613
|
+
"/api/execute/browser_extract_site_progress": {
|
|
22614
|
+
post: {
|
|
22615
|
+
summary: "Browser Extract Site Progress",
|
|
22616
|
+
description: "Get progress of a site extraction job. Returns pages_completed, pages_total, current_url, and status. Status can be: 'running', 'completed', 'cancelled', or 'error'.",
|
|
22617
|
+
tags: [
|
|
22618
|
+
"General"
|
|
22619
|
+
],
|
|
22620
|
+
requestBody: {
|
|
22621
|
+
required: true,
|
|
22622
|
+
content: {
|
|
22623
|
+
"application/json": {
|
|
22624
|
+
schema: {
|
|
22625
|
+
type: "object",
|
|
22626
|
+
properties: {
|
|
22627
|
+
job_id: {
|
|
22628
|
+
type: "string",
|
|
22629
|
+
description: "The job ID returned from browser_extract_site"
|
|
22630
|
+
}
|
|
22631
|
+
},
|
|
22632
|
+
required: [
|
|
22633
|
+
"job_id"
|
|
22634
|
+
]
|
|
22635
|
+
}
|
|
22636
|
+
}
|
|
22637
|
+
}
|
|
22638
|
+
},
|
|
22639
|
+
responses: {
|
|
22640
|
+
"200": {
|
|
22641
|
+
description: "Successful response"
|
|
22642
|
+
},
|
|
22643
|
+
"400": {
|
|
22644
|
+
description: "Bad request"
|
|
22645
|
+
},
|
|
22646
|
+
"401": {
|
|
22647
|
+
description: "Unauthorized"
|
|
22648
|
+
}
|
|
22649
|
+
}
|
|
22650
|
+
}
|
|
22651
|
+
},
|
|
22652
|
+
"/api/execute/browser_extract_site_result": {
|
|
22653
|
+
post: {
|
|
22654
|
+
summary: "Browser Extract Site Result",
|
|
22655
|
+
description: "Get the result of a completed site extraction job. Returns the formatted content based on the output_format specified when starting the job (markdown, text, or json).",
|
|
22656
|
+
tags: [
|
|
22657
|
+
"General"
|
|
22658
|
+
],
|
|
22659
|
+
requestBody: {
|
|
22660
|
+
required: true,
|
|
22661
|
+
content: {
|
|
22662
|
+
"application/json": {
|
|
22663
|
+
schema: {
|
|
22664
|
+
type: "object",
|
|
22665
|
+
properties: {
|
|
22666
|
+
job_id: {
|
|
22667
|
+
type: "string",
|
|
22668
|
+
description: "The job ID returned from browser_extract_site"
|
|
22669
|
+
}
|
|
22670
|
+
},
|
|
22671
|
+
required: [
|
|
22672
|
+
"job_id"
|
|
22673
|
+
]
|
|
22674
|
+
}
|
|
22675
|
+
}
|
|
22676
|
+
}
|
|
22677
|
+
},
|
|
22678
|
+
responses: {
|
|
22679
|
+
"200": {
|
|
22680
|
+
description: "Successful response"
|
|
22681
|
+
},
|
|
22682
|
+
"400": {
|
|
22683
|
+
description: "Bad request"
|
|
22684
|
+
},
|
|
22685
|
+
"401": {
|
|
22686
|
+
description: "Unauthorized"
|
|
22687
|
+
}
|
|
22688
|
+
}
|
|
22689
|
+
}
|
|
22690
|
+
},
|
|
22691
|
+
"/api/execute/browser_extract_site_cancel": {
|
|
22692
|
+
post: {
|
|
22693
|
+
summary: "Browser Extract Site Cancel",
|
|
22694
|
+
description: "Cancel a running site extraction job. Returns success status.",
|
|
22695
|
+
tags: [
|
|
22696
|
+
"General"
|
|
22697
|
+
],
|
|
22698
|
+
requestBody: {
|
|
22699
|
+
required: true,
|
|
22700
|
+
content: {
|
|
22701
|
+
"application/json": {
|
|
22702
|
+
schema: {
|
|
22703
|
+
type: "object",
|
|
22704
|
+
properties: {
|
|
22705
|
+
job_id: {
|
|
22706
|
+
type: "string",
|
|
22707
|
+
description: "The job ID to cancel"
|
|
22708
|
+
}
|
|
22709
|
+
},
|
|
22710
|
+
required: [
|
|
22711
|
+
"job_id"
|
|
22712
|
+
]
|
|
22713
|
+
}
|
|
22714
|
+
}
|
|
22715
|
+
}
|
|
22716
|
+
},
|
|
22717
|
+
responses: {
|
|
22718
|
+
"200": {
|
|
22719
|
+
description: "Successful response"
|
|
22720
|
+
},
|
|
22721
|
+
"400": {
|
|
22722
|
+
description: "Bad request"
|
|
22723
|
+
},
|
|
22724
|
+
"401": {
|
|
22725
|
+
description: "Unauthorized"
|
|
22726
|
+
}
|
|
22727
|
+
}
|
|
22728
|
+
}
|
|
22729
|
+
},
|
|
22532
22730
|
"/api/execute/browser_extract_json": {
|
|
22533
22731
|
post: {
|
|
22534
22732
|
summary: "Browser Extract Json",
|
|
@@ -26797,6 +26995,7 @@ var openapi_default = {
|
|
|
26797
26995
|
var API_ENDPOINT = process.env.OWL_API_ENDPOINT || "http://127.0.0.1:8080";
|
|
26798
26996
|
var API_TOKEN = process.env.OWL_API_TOKEN || "";
|
|
26799
26997
|
var activeContexts = /* @__PURE__ */ new Map();
|
|
26998
|
+
var toolIntegerFields = /* @__PURE__ */ new Map();
|
|
26800
26999
|
function convertOpenAPIToMCPTools(schema) {
|
|
26801
27000
|
const tools = [];
|
|
26802
27001
|
for (const [path, pathItem] of Object.entries(schema.paths)) {
|
|
@@ -26810,6 +27009,7 @@ function convertOpenAPIToMCPTools(schema) {
|
|
|
26810
27009
|
};
|
|
26811
27010
|
if (requestSchema?.properties) {
|
|
26812
27011
|
const properties = {};
|
|
27012
|
+
const integerFields = /* @__PURE__ */ new Set();
|
|
26813
27013
|
for (const [propName, propDef] of Object.entries(requestSchema.properties)) {
|
|
26814
27014
|
const prop = {};
|
|
26815
27015
|
if (propDef.type === "string") {
|
|
@@ -26821,6 +27021,9 @@ function convertOpenAPIToMCPTools(schema) {
|
|
|
26821
27021
|
prop.type = "boolean";
|
|
26822
27022
|
} else if (propDef.type === "number" || propDef.type === "integer") {
|
|
26823
27023
|
prop.type = "number";
|
|
27024
|
+
if (propDef.type === "integer") {
|
|
27025
|
+
integerFields.add(propName);
|
|
27026
|
+
}
|
|
26824
27027
|
} else if (propDef.type === "array") {
|
|
26825
27028
|
prop.type = "array";
|
|
26826
27029
|
if (propDef.items) {
|
|
@@ -26838,6 +27041,9 @@ function convertOpenAPIToMCPTools(schema) {
|
|
|
26838
27041
|
properties[propName] = prop;
|
|
26839
27042
|
}
|
|
26840
27043
|
inputSchema.properties = properties;
|
|
27044
|
+
if (integerFields.size > 0) {
|
|
27045
|
+
toolIntegerFields.set(toolName, integerFields);
|
|
27046
|
+
}
|
|
26841
27047
|
}
|
|
26842
27048
|
if (requestSchema?.required && requestSchema.required.length > 0) {
|
|
26843
27049
|
inputSchema.required = requestSchema.required;
|
|
@@ -26850,6 +27056,19 @@ function convertOpenAPIToMCPTools(schema) {
|
|
|
26850
27056
|
}
|
|
26851
27057
|
return tools;
|
|
26852
27058
|
}
|
|
27059
|
+
function coerceIntegerFields(toolName, args) {
|
|
27060
|
+
const integerFields = toolIntegerFields.get(toolName);
|
|
27061
|
+
if (!integerFields || integerFields.size === 0) {
|
|
27062
|
+
return args;
|
|
27063
|
+
}
|
|
27064
|
+
const coerced = { ...args };
|
|
27065
|
+
for (const field of integerFields) {
|
|
27066
|
+
if (field in coerced && typeof coerced[field] === "number") {
|
|
27067
|
+
coerced[field] = Math.round(coerced[field]);
|
|
27068
|
+
}
|
|
27069
|
+
}
|
|
27070
|
+
return coerced;
|
|
27071
|
+
}
|
|
26853
27072
|
async function callBrowserAPI(toolName, args) {
|
|
26854
27073
|
const url2 = `${API_ENDPOINT}/api/execute/${toolName}`;
|
|
26855
27074
|
const headers = {
|
|
@@ -26858,11 +27077,12 @@ async function callBrowserAPI(toolName, args) {
|
|
|
26858
27077
|
if (API_TOKEN) {
|
|
26859
27078
|
headers["Authorization"] = `Bearer ${API_TOKEN}`;
|
|
26860
27079
|
}
|
|
27080
|
+
const coercedArgs = coerceIntegerFields(toolName, args);
|
|
26861
27081
|
try {
|
|
26862
27082
|
const response = await fetch(url2, {
|
|
26863
27083
|
method: "POST",
|
|
26864
27084
|
headers,
|
|
26865
|
-
body: JSON.stringify(
|
|
27085
|
+
body: JSON.stringify(coercedArgs)
|
|
26866
27086
|
});
|
|
26867
27087
|
const contentType = response.headers.get("content-type") || "";
|
|
26868
27088
|
let data;
|
|
@@ -26890,8 +27110,18 @@ async function callBrowserAPI(toolName, args) {
|
|
|
26890
27110
|
};
|
|
26891
27111
|
}
|
|
26892
27112
|
}
|
|
27113
|
+
function isContextLimitError(result) {
|
|
27114
|
+
if (typeof result === "object" && result !== null) {
|
|
27115
|
+
const obj = result;
|
|
27116
|
+
return obj.error === true && obj.code === "CONTEXT_LIMIT_EXCEEDED";
|
|
27117
|
+
}
|
|
27118
|
+
return false;
|
|
27119
|
+
}
|
|
26893
27120
|
function trackContext(toolName, args, result) {
|
|
26894
27121
|
if (toolName === "browser_create_context" && typeof result === "object" && result !== null) {
|
|
27122
|
+
if (isContextLimitError(result)) {
|
|
27123
|
+
return;
|
|
27124
|
+
}
|
|
26895
27125
|
const contextId = result.context_id;
|
|
26896
27126
|
if (contextId) {
|
|
26897
27127
|
activeContexts.set(contextId, { createdAt: /* @__PURE__ */ new Date() });
|
|
@@ -26921,6 +27151,33 @@ function formatResponse(toolName, result) {
|
|
|
26921
27151
|
};
|
|
26922
27152
|
}
|
|
26923
27153
|
const data = result.data;
|
|
27154
|
+
if (typeof data === "object" && data !== null) {
|
|
27155
|
+
const dataObj = data;
|
|
27156
|
+
if (dataObj.success === true && typeof dataObj.result === "object" && dataObj.result !== null) {
|
|
27157
|
+
const innerResult = dataObj.result;
|
|
27158
|
+
if (innerResult.error === true && innerResult.code === "CONTEXT_LIMIT_EXCEEDED") {
|
|
27159
|
+
const details = innerResult.details || {};
|
|
27160
|
+
const errorMsg = innerResult.message || `Developer license context limit reached (${details.max_contexts || "unknown"} contexts). Close existing contexts or upgrade license.`;
|
|
27161
|
+
return {
|
|
27162
|
+
content: [
|
|
27163
|
+
{
|
|
27164
|
+
type: "text",
|
|
27165
|
+
text: JSON.stringify({
|
|
27166
|
+
success: false,
|
|
27167
|
+
error: errorMsg,
|
|
27168
|
+
code: "CONTEXT_LIMIT_EXCEEDED",
|
|
27169
|
+
details: {
|
|
27170
|
+
current_contexts: details.current_contexts,
|
|
27171
|
+
max_contexts: details.max_contexts,
|
|
27172
|
+
license_type: details.license_type || "developer"
|
|
27173
|
+
}
|
|
27174
|
+
}, null, 2)
|
|
27175
|
+
}
|
|
27176
|
+
]
|
|
27177
|
+
};
|
|
27178
|
+
}
|
|
27179
|
+
}
|
|
27180
|
+
}
|
|
26924
27181
|
const isImageTool = toolName === "browser_screenshot" || toolName === "browser_get_live_frame";
|
|
26925
27182
|
if (isImageTool) {
|
|
26926
27183
|
let base64Data = null;
|