Skip to content

Commit 5f52c67

Browse files
authored
Merge pull request #119 from brightdata/feat/add-timeout-retries
Feat/add timeout retries
2 parents 020b5b8 + 4dffc76 commit 5f52c67

File tree

5 files changed

+47
-9
lines changed

5 files changed

+47
-9
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,8 @@ Try the Web MCP without any setup:
428428
| `WEB_UNLOCKER_ZONE` | Custom Web Unlocker zone name | `mcp_unlocker` | `my_custom_zone` |
429429
| `BROWSER_ZONE` | Custom Browser zone name | `mcp_browser` | `my_browser_zone` |
430430
| `POLLING_TIMEOUT` | Timeout for web_data_* tools polling (seconds) | `600` | `300`, `1200` |
431+
| `BASE_TIMEOUT` | Request timeout for base tools in seconds (search & scrape) | No limit | `60`, `120` |
432+
| `BASE_MAX_RETRIES` | Max retries for base tools on transient errors (0-3) | `0` | `1`, `3` |
431433
| `GROUPS` | Comma-separated tool group IDs | - | `ecommerce,browser` |
432434
| `TOOLS` | Comma-separated individual tool names | - | `extract,scrape_as_html` |
433435

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@brightdata/mcp",
3-
"version": "2.9.1",
3+
"version": "2.9.2",
44
"description": "An MCP interface into the Bright Data toolset",
55
"type": "module",
66
"main": "./server.js",

server.js

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ const unlocker_zone = process.env.WEB_UNLOCKER_ZONE || 'mcp_unlocker';
1616
const browser_zone = process.env.BROWSER_ZONE || 'mcp_browser';
1717
const pro_mode = process.env.PRO_MODE === 'true';
1818
const polling_timeout = parseInt(process.env.POLLING_TIMEOUT || '600', 10);
19+
const base_timeout = process.env.BASE_TIMEOUT
20+
? parseInt(process.env.BASE_TIMEOUT, 10) * 1000 : 0;
21+
const base_max_retries = Math.min(
22+
parseInt(process.env.BASE_MAX_RETRIES || '0', 10), 3);
1923
const pro_mode_tools = ['search_engine', 'scrape_as_markdown',
2024
'search_engine_batch', 'scrape_batch'];
2125
const tool_groups = process.env.GROUPS ?
@@ -64,6 +68,24 @@ const rate_limit_config = parse_rate_limit(process.env.RATE_LIMIT);
6468
if (!api_token)
6569
throw new Error('Cannot run MCP server without API_TOKEN env');
6670

71+
async function base_request(config){
72+
let last_err;
73+
for (let attempt = 0; attempt <= base_max_retries; attempt++)
74+
{
75+
try {
76+
return await axios({...config, timeout: base_timeout});
77+
} catch(e){
78+
last_err = e;
79+
if (e.response?.status && e.response.status >= 400
80+
&& e.response.status < 500)
81+
{
82+
throw e;
83+
}
84+
}
85+
}
86+
throw last_err;
87+
}
88+
6789
const api_headers = (clientName=null, tool_name=null)=>({
6890
'user-agent': `${package_json.name}/${package_json.version}`,
6991
authorization: `Bearer ${api_token}`,
@@ -202,7 +224,7 @@ addTool({
202224
{
203225
const is_google = engine=='google';
204226
const url = search_url(engine, query, cursor, geo_location);
205-
let response = await axios({
227+
let response = await base_request({
206228
url: 'https://api.brightdata.com/request',
207229
method: 'POST',
208230
data: {
@@ -241,7 +263,7 @@ addTool({
241263
},
242264
parameters: z.object({url: z.string().url()}),
243265
execute: tool_fn('scrape_as_markdown', async({url}, ctx)=>{
244-
let response = await axios({
266+
let response = await base_request({
245267
url: 'https://api.brightdata.com/request',
246268
method: 'POST',
247269
data: {
@@ -292,7 +314,7 @@ addTool({
292314
const url = search_url(engine || 'google', query, cursor,
293315
geo_location);
294316

295-
return axios({
317+
return base_request({
296318
url: 'https://api.brightdata.com/request',
297319
method: 'POST',
298320
data: {
@@ -350,7 +372,7 @@ addTool({
350372
}),
351373
execute: tool_fn('scrape_batch', async ({urls}, ctx)=>{
352374
const scrapePromises = urls.map(url =>
353-
axios({
375+
base_request({
354376
url: 'https://api.brightdata.com/request',
355377
method: 'POST',
356378
data: {

server.json

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
"url": "https://github.com/brightdata/brightdata-mcp",
77
"source": "github"
88
},
9-
"version": "2.9.1",
9+
"version": "2.9.2",
1010
"packages": [
1111
{
1212
"registryType": "npm",
1313
"registryBaseUrl": "https://registry.npmjs.org",
1414
"identifier": "@brightdata/mcp",
15-
"version": "2.9.1",
15+
"version": "2.9.2",
1616
"transport": {
1717
"type": "stdio"
1818
},
@@ -65,6 +65,20 @@
6565
"isRequired": false,
6666
"isSecret": false,
6767
"format": "number"
68+
},
69+
{
70+
"name": "BASE_TIMEOUT",
71+
"description": "Request timeout in seconds for base tools (search & scrape). No limit if unset",
72+
"isRequired": false,
73+
"isSecret": false,
74+
"format": "number"
75+
},
76+
{
77+
"name": "BASE_MAX_RETRIES",
78+
"description": "Max retries for base tools on transient errors (0-3, default: 0)",
79+
"isRequired": false,
80+
"isSecret": false,
81+
"format": "number"
6882
}
6983
]
7084
}

0 commit comments

Comments
 (0)