scrapeless-mcp-server 0.4.4 → 0.4.5
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/README.md +11 -0
- package/build/cf.js +2 -2
- package/build/context.js +2 -2
- package/build/server.js +8 -8
- package/build/session-manager.js +15 -2
- package/build/transport.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -98,6 +98,17 @@ Scrapeless MCP Server supports both **Stdio** and **Streamable HTTP** transport
|
|
|
98
98
|
}
|
|
99
99
|
```
|
|
100
100
|
|
|
101
|
+
#### Advanced Options
|
|
102
|
+
|
|
103
|
+
Customize browser session behavior with optional parameters. These can be set via environment variables (for Stdio) or HTTP headers (for Streamable HTTP):
|
|
104
|
+
|
|
105
|
+
| Stdio (Env Var) | Streamable HTTP (HTTP Header) | Description |
|
|
106
|
+
| ----------------------- | ----------------------------- | ------------------------------------------------------------ |
|
|
107
|
+
| BROWSER_PROFILE_ID | x-browser-profile-id | Specifies a reusable browser profile ID for session continuity. |
|
|
108
|
+
| BROWSER_PROFILE_PERSIST | x-browser-profile-persist | Enables persistent storage for cookies, local storage, etc. |
|
|
109
|
+
| BROWSER_SESSION_TTL | x-browser-session-ttl | Defines the **maximum session timeout** in seconds. The session will automatically expire after this duration of inactivity. |
|
|
110
|
+
|
|
111
|
+
|
|
101
112
|
## Integration with Claude Desktop
|
|
102
113
|
|
|
103
114
|
1. Open **Claude Desktop**
|
package/build/cf.js
CHANGED
|
@@ -5,7 +5,7 @@ import { API_KEY_NAME } from "./config.js";
|
|
|
5
5
|
export class CfMcpServer extends McpAgent {
|
|
6
6
|
server = new McpServer(serverOptions);
|
|
7
7
|
async init() {
|
|
8
|
-
initMcpTools(this.server, this.props.apiKey);
|
|
8
|
+
initMcpTools(this.server, this.props.headers, this.props.apiKey);
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
export default {
|
|
@@ -15,7 +15,7 @@ export default {
|
|
|
15
15
|
if (!apiKeyHeader) {
|
|
16
16
|
return new Response(`Unauthorized: Missing ${API_KEY_NAME} header`, { status: 401 });
|
|
17
17
|
}
|
|
18
|
-
ctx.props = { apiKey: apiKeyHeader };
|
|
18
|
+
ctx.props = { apiKey: apiKeyHeader, headers: request.headers };
|
|
19
19
|
if (url.pathname === "/sse" || url.pathname === "/sse/message") {
|
|
20
20
|
return CfMcpServer.serveSSE("/sse").fetch(request, env, ctx);
|
|
21
21
|
}
|
package/build/context.js
CHANGED
|
@@ -11,7 +11,7 @@ export class Context {
|
|
|
11
11
|
getSession(id) {
|
|
12
12
|
return this.sessionManager.getSession(`${id ?? this.currentSessionId}-${this.apiKey}`);
|
|
13
13
|
}
|
|
14
|
-
async run(tool, params) {
|
|
14
|
+
async run(tool, params, headers) {
|
|
15
15
|
if (!this.apiKey) {
|
|
16
16
|
return {
|
|
17
17
|
content: [
|
|
@@ -29,7 +29,7 @@ export class Context {
|
|
|
29
29
|
if (toolName === "browser_create") {
|
|
30
30
|
const newSessionId = uuid();
|
|
31
31
|
try {
|
|
32
|
-
await this.sessionManager.createSession(`${newSessionId}-${this.apiKey}`, this.apiKey);
|
|
32
|
+
await this.sessionManager.createSession(`${newSessionId}-${this.apiKey}`, this.apiKey, headers);
|
|
33
33
|
return {
|
|
34
34
|
content: [
|
|
35
35
|
{
|
package/build/server.js
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { ScrapelessClient } from "@scrapeless-ai/sdk";
|
|
3
3
|
import { SCRAPELESS_CONFIG, API_KEY } from "./config.js";
|
|
4
|
-
import * as toolsList from
|
|
5
|
-
import * as browserTools from
|
|
6
|
-
import { Context } from
|
|
4
|
+
import * as toolsList from "./tools/index.js";
|
|
5
|
+
import * as browserTools from "./tools/browser/browser.js";
|
|
6
|
+
import { Context } from "./context.js";
|
|
7
7
|
export const serverOptions = {
|
|
8
8
|
name: "scrapeless-mcp-server",
|
|
9
9
|
version: "0.2.0",
|
|
10
10
|
capabilities: { resources: {}, tools: {} },
|
|
11
11
|
};
|
|
12
|
-
export const createMcpServer = (
|
|
12
|
+
export const createMcpServer = (options) => {
|
|
13
13
|
const server = new McpServer(serverOptions);
|
|
14
|
-
initMcpTools(server, apiKey);
|
|
14
|
+
initMcpTools(server, options?.headers, options?.apiKey);
|
|
15
15
|
return server.server;
|
|
16
16
|
};
|
|
17
|
-
export const initMcpTools = (server, apiKey) => {
|
|
17
|
+
export const initMcpTools = (server, headers, apiKey) => {
|
|
18
18
|
const getScrapelessClient = () => {
|
|
19
19
|
if (apiKey) {
|
|
20
20
|
return new ScrapelessClient({
|
|
@@ -32,7 +32,7 @@ export const initMcpTools = (server, apiKey) => {
|
|
|
32
32
|
const context = new Context(apiKey ?? API_KEY);
|
|
33
33
|
Object.values(browserTools).forEach((tool) => {
|
|
34
34
|
server.tool(tool.name, tool.description, tool.inputSchema, async (params) => {
|
|
35
|
-
const result = await context.run(tool, params);
|
|
35
|
+
const result = await context.run(tool, params, headers);
|
|
36
36
|
return result;
|
|
37
37
|
});
|
|
38
38
|
});
|
|
@@ -55,6 +55,6 @@ export class ServerList {
|
|
|
55
55
|
await server.close();
|
|
56
56
|
}
|
|
57
57
|
async closeAll() {
|
|
58
|
-
await Promise.all(this._servers.map(server => server.close()));
|
|
58
|
+
await Promise.all(this._servers.map((server) => server.close()));
|
|
59
59
|
}
|
|
60
60
|
}
|
package/build/session-manager.js
CHANGED
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
import { Scrapeless } from "@scrapeless-ai/sdk";
|
|
2
|
+
import { getParamValue } from "@chatmcp/sdk/utils/index.js";
|
|
2
3
|
import puppeteer from "puppeteer-core";
|
|
3
4
|
export class SessionManager {
|
|
4
5
|
sessions;
|
|
5
6
|
constructor() {
|
|
6
7
|
this.sessions = new Map();
|
|
7
8
|
}
|
|
8
|
-
async createSession(id, apiKey) {
|
|
9
|
+
async createSession(id, apiKey, headers) {
|
|
9
10
|
if (!this.sessions.has(id)) {
|
|
10
11
|
this.sessions.set(id, { browser: null, page: null, closed: true });
|
|
11
12
|
}
|
|
12
13
|
const scrapelessClient = new Scrapeless({ apiKey });
|
|
13
14
|
const session = this.sessions.get(id);
|
|
14
|
-
const { browserWSEndpoint } = scrapelessClient.browser.create(
|
|
15
|
+
const { browserWSEndpoint } = scrapelessClient.browser.create({
|
|
16
|
+
session_ttl: Number(process.env.BROWSER_SESSION_TTL ||
|
|
17
|
+
getParamValue("BROWSER_SESSION_TTL") ||
|
|
18
|
+
headers?.["x-browser-session-ttl"] ||
|
|
19
|
+
30000),
|
|
20
|
+
profile_id: process.env.BROWSER_PROFILE_ID ||
|
|
21
|
+
getParamValue("BROWSER_PROFILE_ID") ||
|
|
22
|
+
headers?.["x-browser-profile-id"] ||
|
|
23
|
+
"",
|
|
24
|
+
profile_persist: Boolean(process.env.BROWSER_PROFILE_PERSIST ||
|
|
25
|
+
getParamValue("BROWSER_PROFILE_PERSIST") ||
|
|
26
|
+
headers?.["x-browser-profile-persist"]),
|
|
27
|
+
});
|
|
15
28
|
const browser = await puppeteer.connect({
|
|
16
29
|
browserWSEndpoint,
|
|
17
30
|
defaultViewport: null,
|
package/build/transport.js
CHANGED
|
@@ -115,6 +115,6 @@ function createRemoteServerList(req, res) {
|
|
|
115
115
|
res.end("Unauthorized: Missing x-api-token header");
|
|
116
116
|
return null;
|
|
117
117
|
}
|
|
118
|
-
const serverList = new ServerList(async () => createMcpServer(apiKey));
|
|
118
|
+
const serverList = new ServerList(async () => createMcpServer({ headers: req.headers, apiKey }));
|
|
119
119
|
return serverList;
|
|
120
120
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scrapeless-mcp-server",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@chatmcp/sdk": "^1.0.5",
|
|
33
33
|
"@modelcontextprotocol/sdk": "^1.8.0",
|
|
34
|
-
"@scrapeless-ai/sdk": "^1.
|
|
34
|
+
"@scrapeless-ai/sdk": "^1.8.0",
|
|
35
35
|
"agents": "^0.0.101",
|
|
36
36
|
"axios": "^1.8.4",
|
|
37
37
|
"express": "^5.1.0",
|