scrapeless-mcp-server 0.1.4 → 0.3.0
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/LICENSE +21 -0
- package/build/client.js +16 -3
- package/build/config.js +5 -1
- package/build/index.js +14 -2
- package/build/server.js +79 -5
- package/package.json +4 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [year] [fullname]
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/build/client.js
CHANGED
|
@@ -12,15 +12,28 @@ export class ScrapelessClient {
|
|
|
12
12
|
}
|
|
13
13
|
async sendRequest(endpoint, actor, inputData) {
|
|
14
14
|
try {
|
|
15
|
-
const response = await this.api.post(endpoint, {
|
|
15
|
+
const response = await this.api.post(endpoint, {
|
|
16
|
+
actor,
|
|
17
|
+
input: inputData,
|
|
18
|
+
});
|
|
16
19
|
return {
|
|
17
|
-
content: [
|
|
20
|
+
content: [
|
|
21
|
+
{
|
|
22
|
+
type: "text",
|
|
23
|
+
text: `Response:\n\n${JSON.stringify(response.data)}`,
|
|
24
|
+
},
|
|
25
|
+
],
|
|
18
26
|
};
|
|
19
27
|
}
|
|
20
28
|
catch (error) {
|
|
21
29
|
console.error("Scrapeless API Error:", error);
|
|
22
30
|
return {
|
|
23
|
-
content: [
|
|
31
|
+
content: [
|
|
32
|
+
{
|
|
33
|
+
type: "text",
|
|
34
|
+
text: `Failed to fetch data. Error: ${error.message}`,
|
|
35
|
+
},
|
|
36
|
+
],
|
|
24
37
|
};
|
|
25
38
|
}
|
|
26
39
|
}
|
package/build/config.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import { getParamValue } from "@chatmcp/sdk/utils/index.js";
|
|
2
|
+
const API_KEY = process.env.SCRAPELESS_KEY?.trim() || getParamValue("SCRAPELESS_KEY");
|
|
2
3
|
const BASE_URL = process.env.SCRAPELESS_BASE_URL?.trim() || "https://api.scrapeless.com";
|
|
4
|
+
export const ServerMode = getParamValue("mode") || "stdio";
|
|
5
|
+
export const ServerPort = getParamValue("port") || 9593;
|
|
6
|
+
export const ServerEndpoint = getParamValue("endpoint") || "/rest";
|
|
3
7
|
if (!API_KEY) {
|
|
4
8
|
throw new Error("❌ Missing environment variable: SCRAPELESS_KEY");
|
|
5
9
|
}
|
package/build/index.js
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
3
|
import { server } from "./server.js";
|
|
4
|
+
import { RestServerTransport } from "@chatmcp/sdk/server/rest.js";
|
|
5
|
+
import { ServerMode, ServerPort, ServerEndpoint } from "./config.js";
|
|
4
6
|
async function main() {
|
|
5
7
|
try {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
+
if (ServerMode === "rest") {
|
|
9
|
+
const transport = new RestServerTransport({
|
|
10
|
+
port: ServerPort,
|
|
11
|
+
endpoint: ServerEndpoint,
|
|
12
|
+
});
|
|
13
|
+
await server.connect(transport);
|
|
14
|
+
await transport.startServer();
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
const transport = new StdioServerTransport();
|
|
18
|
+
await server.connect(transport);
|
|
19
|
+
}
|
|
8
20
|
}
|
|
9
21
|
catch (error) {
|
|
10
22
|
console.error("Fatal error in main():", error);
|
package/build/server.js
CHANGED
|
@@ -5,19 +5,27 @@ import { SCRAPELESS_CONFIG, TOOL_ENDPOINTS } from "./config.js";
|
|
|
5
5
|
const scrapelessClient = new ScrapelessClient(SCRAPELESS_CONFIG);
|
|
6
6
|
export const server = new McpServer({
|
|
7
7
|
name: "scrapeless-mcp-server",
|
|
8
|
-
version: "0.
|
|
8
|
+
version: "0.2.0",
|
|
9
9
|
capabilities: { resources: {}, tools: {} },
|
|
10
10
|
});
|
|
11
11
|
server.tool("google-search", "Fetch Google Search Results", {
|
|
12
|
-
query: z
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
query: z
|
|
13
|
+
.string()
|
|
14
|
+
.describe("Parameter defines the query you want to search. You can use anything that you would use in a regular Google search. e.g. inurl:, site:, intitle:. We also support advanced search query parameters such as as_dt and as_eq."),
|
|
15
|
+
gl: z
|
|
16
|
+
.string()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe("Parameter defines the country to use for the Google search. It's a two-letter country code. (e.g., us for the United States, uk for United Kingdom, or fr for France)."),
|
|
19
|
+
hl: z
|
|
20
|
+
.string()
|
|
21
|
+
.optional()
|
|
22
|
+
.describe("Parameter defines the language to use for the Google search. It's a two-letter language code. (e.g., en for English, es for Spanish, or fr for French)."),
|
|
15
23
|
}, async ({ query, gl = "us", hl = "en" }) => {
|
|
16
24
|
const response = await scrapelessClient.sendRequest(TOOL_ENDPOINTS.SCRAPER, "scraper.google.search", {
|
|
17
25
|
q: query,
|
|
18
26
|
gl,
|
|
19
27
|
hl,
|
|
20
|
-
location: ""
|
|
28
|
+
location: "",
|
|
21
29
|
});
|
|
22
30
|
return {
|
|
23
31
|
content: response.content.map((item) => ({
|
|
@@ -26,3 +34,69 @@ server.tool("google-search", "Fetch Google Search Results", {
|
|
|
26
34
|
})),
|
|
27
35
|
};
|
|
28
36
|
});
|
|
37
|
+
server.tool("google-flights-search", "Search for flights using Google Flights via Scrapeless API", {
|
|
38
|
+
departure_id: z
|
|
39
|
+
.string()
|
|
40
|
+
.describe("Airport code for departure (e.g., CDG for Paris Charles de Gaulle)"),
|
|
41
|
+
arrival_id: z
|
|
42
|
+
.string()
|
|
43
|
+
.describe("Airport code for arrival (e.g., BCN for Barcelona)"),
|
|
44
|
+
outbound_date: z.string().describe("Departure date in YYYY-MM-DD format"),
|
|
45
|
+
return_date: z
|
|
46
|
+
.string()
|
|
47
|
+
.optional()
|
|
48
|
+
.describe("Return date in YYYY-MM-DD format for round trips"),
|
|
49
|
+
gl: z
|
|
50
|
+
.string()
|
|
51
|
+
.optional()
|
|
52
|
+
.describe("Country code (e.g., us for United States, fr for France)"),
|
|
53
|
+
hl: z
|
|
54
|
+
.string()
|
|
55
|
+
.optional()
|
|
56
|
+
.describe("Language code (e.g., en for English, fr for French)"),
|
|
57
|
+
currency: z.string().optional().describe("Currency code (e.g., USD, EUR)"),
|
|
58
|
+
travel_class: z
|
|
59
|
+
.string()
|
|
60
|
+
.optional()
|
|
61
|
+
.describe("Travel class (1 for Economy, 2 for Business, 3 for First Class)"),
|
|
62
|
+
adults: z.string().optional().describe("Number of adult passengers"),
|
|
63
|
+
children: z.string().optional().describe("Number of children passengers"),
|
|
64
|
+
max_price: z
|
|
65
|
+
.string()
|
|
66
|
+
.optional()
|
|
67
|
+
.describe("Maximum price to filter results"),
|
|
68
|
+
stops: z.string().optional().describe("Filter by number of stops"),
|
|
69
|
+
emissions: z
|
|
70
|
+
.string()
|
|
71
|
+
.optional()
|
|
72
|
+
.describe("Filter for emissions (e.g., 'Less emissions only')"),
|
|
73
|
+
data_type: z
|
|
74
|
+
.string()
|
|
75
|
+
.optional()
|
|
76
|
+
.default("1")
|
|
77
|
+
.describe("Type of flight (1 for Round trip, 2 for One-way)"),
|
|
78
|
+
}, async (params) => {
|
|
79
|
+
const searchParams = {
|
|
80
|
+
departure_id: params.departure_id,
|
|
81
|
+
arrival_id: params.arrival_id,
|
|
82
|
+
outbound_date: params.outbound_date,
|
|
83
|
+
return_date: params.return_date,
|
|
84
|
+
data_type: params.data_type || "1",
|
|
85
|
+
gl: params.gl || "us",
|
|
86
|
+
hl: params.hl || "en",
|
|
87
|
+
currency: params.currency,
|
|
88
|
+
travel_class: params.travel_class,
|
|
89
|
+
adults: params.adults,
|
|
90
|
+
children: params.children,
|
|
91
|
+
max_price: params.max_price,
|
|
92
|
+
stops: params.stops,
|
|
93
|
+
emissions: params.emissions,
|
|
94
|
+
};
|
|
95
|
+
const response = await scrapelessClient.sendRequest(TOOL_ENDPOINTS.SCRAPER, "scraper.google.flights", searchParams);
|
|
96
|
+
return {
|
|
97
|
+
content: response.content.map((item) => ({
|
|
98
|
+
type: "text",
|
|
99
|
+
text: item.text,
|
|
100
|
+
})),
|
|
101
|
+
};
|
|
102
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scrapeless-mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -27,9 +27,10 @@
|
|
|
27
27
|
"license": "ISC",
|
|
28
28
|
"description": "Scrapeless Mcp Server",
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@chatmcp/sdk": "^1.0.5",
|
|
30
31
|
"@modelcontextprotocol/sdk": "^1.8.0",
|
|
31
|
-
"
|
|
32
|
-
"
|
|
32
|
+
"axios": "^1.8.4",
|
|
33
|
+
"zod": "^3.24.2"
|
|
33
34
|
},
|
|
34
35
|
"devDependencies": {
|
|
35
36
|
"@types/node": "^22.13.14",
|