@gatesolve/mcp-server 0.1.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/README.md ADDED
@@ -0,0 +1,61 @@
1
+ # GateSolve MCP Server
2
+
3
+ Model Context Protocol (MCP) server for [GateSolve](https://gatesolve.dev) — CAPTCHA solving for AI agents via x402 micropayments.
4
+
5
+ ## Tools
6
+
7
+ ### `solve_captcha`
8
+ Solve a CAPTCHA (Turnstile, reCAPTCHA v2/v3, hCaptcha). Returns payment requirements or solution token.
9
+
10
+ ### `list_captcha_types`
11
+ List supported CAPTCHA types with pricing, accuracy, and required fields.
12
+
13
+ ### `check_gatesolve_status`
14
+ Check API health and service status.
15
+
16
+ ## Setup
17
+
18
+ ### Claude Desktop / Cursor / Windsurf
19
+
20
+ Add to your MCP config:
21
+
22
+ ```json
23
+ {
24
+ "mcpServers": {
25
+ "gatesolve": {
26
+ "command": "npx",
27
+ "args": ["@gatesolve/mcp-server"]
28
+ }
29
+ }
30
+ }
31
+ ```
32
+
33
+ ### From source
34
+
35
+ ```bash
36
+ git clone https://github.com/arsonx-dev/gatesolve-mcp.git
37
+ cd gatesolve-mcp
38
+ npm install
39
+ npm run build
40
+ npm start
41
+ ```
42
+
43
+ ## Environment Variables
44
+
45
+ | Variable | Default | Description |
46
+ |----------|---------|-------------|
47
+ | `GATESOLVE_API_URL` | `https://gatesolve.dev` | GateSolve API base URL |
48
+
49
+ ## How It Works
50
+
51
+ 1. Agent calls `solve_captcha` with the CAPTCHA type, site key, and page URL
52
+ 2. GateSolve returns a 402 Payment Required with USDC amount
53
+ 3. Agent pays via x402 (USDC on Base network)
54
+ 4. Agent calls `solve_captcha` again with the payment token
55
+ 5. Returns the solved CAPTCHA token
56
+
57
+ No API keys. No accounts. Just x402.
58
+
59
+ ## License
60
+
61
+ MIT
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { z } from "zod";
5
+ const GATESOLVE_API = process.env.GATESOLVE_API_URL || "https://gatesolve.dev";
6
+ const server = new McpServer({
7
+ name: "gatesolve",
8
+ version: "0.1.0",
9
+ });
10
+ // Tool: solve_captcha
11
+ server.tool("solve_captcha", "Solve a CAPTCHA using GateSolve. Supports Cloudflare Turnstile, reCAPTCHA v2/v3, and hCaptcha. Payment is handled via x402 micropayments (USDC on Base network).", {
12
+ type: z
13
+ .enum(["cloudflare-turnstile", "recaptcha-v2", "recaptcha-v3", "hcaptcha"])
14
+ .describe("The type of CAPTCHA to solve"),
15
+ siteKey: z.string().describe("The site key / widget key for the CAPTCHA"),
16
+ pageUrl: z.string().url().describe("The URL of the page containing the CAPTCHA"),
17
+ paymentToken: z
18
+ .string()
19
+ .optional()
20
+ .describe("x402 payment token (USDC on Base). If omitted, returns payment requirements."),
21
+ }, async ({ type, siteKey, pageUrl, paymentToken }) => {
22
+ try {
23
+ const headers = {
24
+ "Content-Type": "application/json",
25
+ };
26
+ if (paymentToken) {
27
+ headers["X-402-Pay"] = paymentToken;
28
+ }
29
+ const response = await fetch(`${GATESOLVE_API}/api/v1/solve`, {
30
+ method: "POST",
31
+ headers,
32
+ body: JSON.stringify({ type, siteKey, pageUrl }),
33
+ });
34
+ const data = await response.json();
35
+ if (response.status === 402) {
36
+ return {
37
+ content: [
38
+ {
39
+ type: "text",
40
+ text: `Payment required to solve this CAPTCHA.\n\nPayment details:\n- Network: ${data.accepts?.network || "base"}\n- Token: ${data.accepts?.token || "USDC"}\n- Amount: ${data.accepts?.amount || "0.02"} USDC\n- Receiver: ${data.accepts?.receiver}\n- Protocol: x402 v${data.x402Version || "1.0"}\n\nProvide the payment token in the 'paymentToken' parameter to complete the solve.`,
41
+ },
42
+ ],
43
+ };
44
+ }
45
+ if (response.status === 200) {
46
+ return {
47
+ content: [
48
+ {
49
+ type: "text",
50
+ text: `CAPTCHA solved successfully!\n\nToken: ${data.token}\nType: ${data.type}\nSolved in: ${data.solvedIn}\nStatus: ${data.status}`,
51
+ },
52
+ ],
53
+ };
54
+ }
55
+ return {
56
+ content: [
57
+ {
58
+ type: "text",
59
+ text: `Error: ${data.message || "Unknown error"} (status: ${response.status})`,
60
+ },
61
+ ],
62
+ isError: true,
63
+ };
64
+ }
65
+ catch (error) {
66
+ return {
67
+ content: [
68
+ {
69
+ type: "text",
70
+ text: `Failed to connect to GateSolve API: ${error instanceof Error ? error.message : "Unknown error"}`,
71
+ },
72
+ ],
73
+ isError: true,
74
+ };
75
+ }
76
+ });
77
+ // Tool: list_captcha_types
78
+ server.tool("list_captcha_types", "List all supported CAPTCHA types with pricing, accuracy, and required fields.", {}, async () => {
79
+ try {
80
+ const response = await fetch(`${GATESOLVE_API}/api/v1/types`);
81
+ const data = await response.json();
82
+ const lines = data.types.map((t) => `**${t.name}** (${t.id})\n Price: ${t.price} USDC | Avg: ${t.avgSolveTime} | Accuracy: ${t.accuracy}\n Required: ${t.requiredFields.join(", ")}\n Optional: ${t.optionalFields.join(", ") || "none"}\n ${t.description}`);
83
+ return {
84
+ content: [
85
+ {
86
+ type: "text",
87
+ text: `GateSolve Supported CAPTCHA Types:\n\n${lines.join("\n\n")}\n\nPayment: x402 micropayments (USDC on ${data.payment.network})`,
88
+ },
89
+ ],
90
+ };
91
+ }
92
+ catch (error) {
93
+ return {
94
+ content: [
95
+ {
96
+ type: "text",
97
+ text: `Failed to fetch captcha types: ${error instanceof Error ? error.message : "Unknown error"}`,
98
+ },
99
+ ],
100
+ isError: true,
101
+ };
102
+ }
103
+ });
104
+ // Tool: check_status
105
+ server.tool("check_gatesolve_status", "Check GateSolve API health and service status.", {}, async () => {
106
+ try {
107
+ const response = await fetch(`${GATESOLVE_API}/api/health`);
108
+ const data = await response.json();
109
+ return {
110
+ content: [
111
+ {
112
+ type: "text",
113
+ text: `GateSolve Status: ${data.status}\n\nServices:\n- API: ${data.services.api}\n- Database: ${data.services.database}\n- Solver: ${data.services.solver}\n\nMetrics:\n- Total solves: ${data.metrics.totalSolves}\n- Last 24h: ${data.metrics.last24hSolves}\n- Avg solve time: ${data.metrics.avgSolveMs ? `${(data.metrics.avgSolveMs / 1000).toFixed(1)}s` : "N/A"}\n\nLatency: ${data.latencyMs}ms | Version: ${data.version}`,
114
+ },
115
+ ],
116
+ };
117
+ }
118
+ catch (error) {
119
+ return {
120
+ content: [
121
+ {
122
+ type: "text",
123
+ text: `GateSolve API unreachable: ${error instanceof Error ? error.message : "Unknown error"}`,
124
+ },
125
+ ],
126
+ isError: true,
127
+ };
128
+ }
129
+ });
130
+ async function main() {
131
+ const transport = new StdioServerTransport();
132
+ await server.connect(transport);
133
+ }
134
+ main().catch(console.error);
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@gatesolve/mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for GateSolve CAPTCHA solving via x402 micropayments",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "gatesolve-mcp": "./dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "start": "node dist/index.js"
13
+ },
14
+ "keywords": [
15
+ "mcp",
16
+ "captcha",
17
+ "gatesolve",
18
+ "x402",
19
+ "ai-agent",
20
+ "turnstile",
21
+ "recaptcha",
22
+ "hcaptcha"
23
+ ],
24
+ "license": "MIT",
25
+ "dependencies": {
26
+ "@modelcontextprotocol/sdk": "^1.0.0"
27
+ },
28
+ "devDependencies": {
29
+ "typescript": "^5.0.0",
30
+ "@types/node": "^20.0.0"
31
+ }
32
+ }
package/src/index.ts ADDED
@@ -0,0 +1,177 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { z } from "zod";
6
+
7
+ const GATESOLVE_API = process.env.GATESOLVE_API_URL || "https://gatesolve.dev";
8
+
9
+ const server = new McpServer({
10
+ name: "gatesolve",
11
+ version: "0.1.0",
12
+ });
13
+
14
+ // Tool: solve_captcha
15
+ server.tool(
16
+ "solve_captcha",
17
+ "Solve a CAPTCHA using GateSolve. Supports Cloudflare Turnstile, reCAPTCHA v2/v3, and hCaptcha. Payment is handled via x402 micropayments (USDC on Base network).",
18
+ {
19
+ type: z
20
+ .enum(["cloudflare-turnstile", "recaptcha-v2", "recaptcha-v3", "hcaptcha"])
21
+ .describe("The type of CAPTCHA to solve"),
22
+ siteKey: z.string().describe("The site key / widget key for the CAPTCHA"),
23
+ pageUrl: z.string().url().describe("The URL of the page containing the CAPTCHA"),
24
+ paymentToken: z
25
+ .string()
26
+ .optional()
27
+ .describe(
28
+ "x402 payment token (USDC on Base). If omitted, returns payment requirements."
29
+ ),
30
+ },
31
+ async ({ type, siteKey, pageUrl, paymentToken }) => {
32
+ try {
33
+ const headers: Record<string, string> = {
34
+ "Content-Type": "application/json",
35
+ };
36
+
37
+ if (paymentToken) {
38
+ headers["X-402-Pay"] = paymentToken;
39
+ }
40
+
41
+ const response = await fetch(`${GATESOLVE_API}/api/v1/solve`, {
42
+ method: "POST",
43
+ headers,
44
+ body: JSON.stringify({ type, siteKey, pageUrl }),
45
+ });
46
+
47
+ const data = await response.json();
48
+
49
+ if (response.status === 402) {
50
+ return {
51
+ content: [
52
+ {
53
+ type: "text" as const,
54
+ text: `Payment required to solve this CAPTCHA.\n\nPayment details:\n- Network: ${data.accepts?.network || "base"}\n- Token: ${data.accepts?.token || "USDC"}\n- Amount: ${data.accepts?.amount || "0.02"} USDC\n- Receiver: ${data.accepts?.receiver}\n- Protocol: x402 v${data.x402Version || "1.0"}\n\nProvide the payment token in the 'paymentToken' parameter to complete the solve.`,
55
+ },
56
+ ],
57
+ };
58
+ }
59
+
60
+ if (response.status === 200) {
61
+ return {
62
+ content: [
63
+ {
64
+ type: "text" as const,
65
+ text: `CAPTCHA solved successfully!\n\nToken: ${data.token}\nType: ${data.type}\nSolved in: ${data.solvedIn}\nStatus: ${data.status}`,
66
+ },
67
+ ],
68
+ };
69
+ }
70
+
71
+ return {
72
+ content: [
73
+ {
74
+ type: "text" as const,
75
+ text: `Error: ${data.message || "Unknown error"} (status: ${response.status})`,
76
+ },
77
+ ],
78
+ isError: true,
79
+ };
80
+ } catch (error) {
81
+ return {
82
+ content: [
83
+ {
84
+ type: "text" as const,
85
+ text: `Failed to connect to GateSolve API: ${error instanceof Error ? error.message : "Unknown error"}`,
86
+ },
87
+ ],
88
+ isError: true,
89
+ };
90
+ }
91
+ }
92
+ );
93
+
94
+ // Tool: list_captcha_types
95
+ server.tool(
96
+ "list_captcha_types",
97
+ "List all supported CAPTCHA types with pricing, accuracy, and required fields.",
98
+ {},
99
+ async () => {
100
+ try {
101
+ const response = await fetch(`${GATESOLVE_API}/api/v1/types`);
102
+ const data = await response.json();
103
+
104
+ const lines = data.types.map(
105
+ (t: {
106
+ id: string;
107
+ name: string;
108
+ price: string;
109
+ avgSolveTime: string;
110
+ accuracy: string;
111
+ requiredFields: string[];
112
+ optionalFields: string[];
113
+ description: string;
114
+ }) =>
115
+ `**${t.name}** (${t.id})\n Price: ${t.price} USDC | Avg: ${t.avgSolveTime} | Accuracy: ${t.accuracy}\n Required: ${t.requiredFields.join(", ")}\n Optional: ${t.optionalFields.join(", ") || "none"}\n ${t.description}`
116
+ );
117
+
118
+ return {
119
+ content: [
120
+ {
121
+ type: "text" as const,
122
+ text: `GateSolve Supported CAPTCHA Types:\n\n${lines.join("\n\n")}\n\nPayment: x402 micropayments (USDC on ${data.payment.network})`,
123
+ },
124
+ ],
125
+ };
126
+ } catch (error) {
127
+ return {
128
+ content: [
129
+ {
130
+ type: "text" as const,
131
+ text: `Failed to fetch captcha types: ${error instanceof Error ? error.message : "Unknown error"}`,
132
+ },
133
+ ],
134
+ isError: true,
135
+ };
136
+ }
137
+ }
138
+ );
139
+
140
+ // Tool: check_status
141
+ server.tool(
142
+ "check_gatesolve_status",
143
+ "Check GateSolve API health and service status.",
144
+ {},
145
+ async () => {
146
+ try {
147
+ const response = await fetch(`${GATESOLVE_API}/api/health`);
148
+ const data = await response.json();
149
+
150
+ return {
151
+ content: [
152
+ {
153
+ type: "text" as const,
154
+ text: `GateSolve Status: ${data.status}\n\nServices:\n- API: ${data.services.api}\n- Database: ${data.services.database}\n- Solver: ${data.services.solver}\n\nMetrics:\n- Total solves: ${data.metrics.totalSolves}\n- Last 24h: ${data.metrics.last24hSolves}\n- Avg solve time: ${data.metrics.avgSolveMs ? `${(data.metrics.avgSolveMs / 1000).toFixed(1)}s` : "N/A"}\n\nLatency: ${data.latencyMs}ms | Version: ${data.version}`,
155
+ },
156
+ ],
157
+ };
158
+ } catch (error) {
159
+ return {
160
+ content: [
161
+ {
162
+ type: "text" as const,
163
+ text: `GateSolve API unreachable: ${error instanceof Error ? error.message : "Unknown error"}`,
164
+ },
165
+ ],
166
+ isError: true,
167
+ };
168
+ }
169
+ }
170
+ );
171
+
172
+ async function main() {
173
+ const transport = new StdioServerTransport();
174
+ await server.connect(transport);
175
+ }
176
+
177
+ main().catch(console.error);
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "declaration": true
12
+ },
13
+ "include": ["src"]
14
+ }