返回提交历史
Modified
etc/unittest/__main__.py
+1
-0
Added
etc/unittest/mcp.py
+166
-0
Modified
g4f/cli/__init__.py
+13
-1
Added
g4f/mcp/README.md
+283
-0
Added
g4f/mcp/__init__.py
+13
-0
Added
g4f/mcp/__main__.py
+9
-0
Added
g4f/mcp/claude_desktop_config.example.json
+9
-0
Added
g4f/mcp/server.py
+202
-0
Added
g4f/mcp/tools.py
+264
-0
Modified
setup.py
+4
-1
XFEstudio/gpt4free
Add MCP server implementation with web search, scraping, and image generation tools
Co-authored-by: hlohaus <983577+hlohaus@users.noreply.github.com>
e1214e43
代码差异
10 个文件
+964
-2
@@ -15,5 +15,6 @@ from .retry_provider import *
15
15
from .thinking import *
16
16
from .web_search import *
17
17
from .models import *
18
from .mcp import *
18
19
19
20
unittest.main()
@@ -0,0 +1,166 @@
1
from __future__ import annotations
2
3
import json
4
import unittest
5
6
from g4f.mcp.server import MCPServer, MCPRequest
7
from g4f.mcp.tools import WebSearchTool, WebScrapeTool, ImageGenerationTool
8
9
try:
10
from ddgs import DDGS, DDGSError
11
from bs4 import BeautifulSoup
12
has_requirements = True
13
except ImportError:
14
has_requirements = False
15
16
17
class TestMCPServer(unittest.IsolatedAsyncioTestCase):
18
"""Test cases for MCP server"""
19
20
async def test_server_initialization(self):
21
"""Test that server initializes correctly"""
22
server = MCPServer()
23
self.assertIsNotNone(server)
24
self.assertEqual(server.server_info["name"], "gpt4free-mcp-server")
25
self.assertEqual(len(server.tools), 3)
26
self.assertIn('web_search', server.tools)
27
self.assertIn('web_scrape', server.tools)
28
self.assertIn('image_generation', server.tools)
29
30
async def test_initialize_request(self):
31
"""Test initialize method"""
32
server = MCPServer()
33
request = MCPRequest(
34
jsonrpc="2.0",
35
id=1,
36
method="initialize",
37
params={}
38
)
39
response = await server.handle_request(request)
40
self.assertEqual(response.jsonrpc, "2.0")
41
self.assertEqual(response.id, 1)
42
self.assertIsNotNone(response.result)
43
self.assertEqual(response.result["protocolVersion"], "2024-11-05")
44
self.assertIn("serverInfo", response.result)
45
46
async def test_tools_list(self):
47
"""Test tools/list method"""
48
server = MCPServer()
49
request = MCPRequest(
50
jsonrpc="2.0",
51
id=2,
52
method="tools/list",
53
params={}
54
)
55
response = await server.handle_request(request)
56
self.assertEqual(response.jsonrpc, "2.0")
57
self.assertEqual(response.id, 2)
58
self.assertIsNotNone(response.result)
59
self.assertIn("tools", response.result)
60
self.assertEqual(len(response.result["tools"]), 3)
61
62
# Check tool structure
63
tool_names = [tool["name"] for tool in response.result["tools"]]
64
self.assertIn("web_search", tool_names)
65
self.assertIn("web_scrape", tool_names)
66
self.assertIn("image_generation", tool_names)
67
68
async def test_ping(self):
69
"""Test ping method"""
70
server = MCPServer()
71
request = MCPRequest(
72
jsonrpc="2.0",
73
id=3,
74
method="ping",
75
params={}
76
)
77
response = await server.handle_request(request)
78
self.assertEqual(response.jsonrpc, "2.0")
79
self.assertEqual(response.id, 3)
80
self.assertIsNotNone(response.result)
81
82
async def test_invalid_method(self):
83
"""Test invalid method returns error"""
84
server = MCPServer()
85
request = MCPRequest(
86
jsonrpc="2.0",
87
id=4,
88
method="invalid_method",
89
params={}
90
)
91
response = await server.handle_request(request)
92
self.assertEqual(response.jsonrpc, "2.0")
93
self.assertEqual(response.id, 4)
94
self.assertIsNotNone(response.error)
95
self.assertEqual(response.error["code"], -32601)
96
97
async def test_tool_call_invalid_tool(self):
98
"""Test calling non-existent tool"""
99
server = MCPServer()
100
request = MCPRequest(
101
jsonrpc="2.0",
102
id=5,
103
method="tools/call",
104
params={
105
"name": "nonexistent_tool",
106
"arguments": {}
107
}
108
)
109
response = await server.handle_request(request)
110
self.assertEqual(response.jsonrpc, "2.0")
111
self.assertEqual(response.id, 5)
112
self.assertIsNotNone(response.error)
113
self.assertEqual(response.error["code"], -32601)
114
115
116
class TestMCPTools(unittest.IsolatedAsyncioTestCase):
117
"""Test cases for MCP tools"""
118
119
def setUp(self) -> None:
120
if not has_requirements:
121
self.skipTest('MCP tools requirements not installed')
122
123
async def test_web_search_tool_schema(self):
124
"""Test WebSearchTool schema"""
125
tool = WebSearchTool()
126
self.assertIsNotNone(tool.description)
127
self.assertIsNotNone(tool.input_schema)
128
self.assertEqual(tool.input_schema["type"], "object")
129
self.assertIn("query", tool.input_schema["properties"])
130
self.assertIn("query", tool.input_schema["required"])
131
132
async def test_web_scrape_tool_schema(self):
133
"""Test WebScrapeTool schema"""
134
tool = WebScrapeTool()
135
self.assertIsNotNone(tool.description)
136
self.assertIsNotNone(tool.input_schema)
137
self.assertEqual(tool.input_schema["type"], "object")
138
self.assertIn("url", tool.input_schema["properties"])
139
self.assertIn("url", tool.input_schema["required"])
140
141
async def test_image_generation_tool_schema(self):
142
"""Test ImageGenerationTool schema"""
143
tool = ImageGenerationTool()
144
self.assertIsNotNone(tool.description)
145
self.assertIsNotNone(tool.input_schema)
146
self.assertEqual(tool.input_schema["type"], "object")
147
self.assertIn("prompt", tool.input_schema["properties"])
148
self.assertIn("prompt", tool.input_schema["required"])
149
150
async def test_web_search_missing_query(self):
151
"""Test web search with missing query parameter"""
152
tool = WebSearchTool()
153
result = await tool.execute({})
154
self.assertIn("error", result)
155
156
async def test_web_scrape_missing_url(self):
157
"""Test web scrape with missing url parameter"""
158
tool = WebScrapeTool()
159
result = await tool.execute({})
160
self.assertIn("error", result)
161
162
async def test_image_generation_missing_prompt(self):
163
"""Test image generation with missing prompt parameter"""
164
tool = ImageGenerationTool()
165
result = await tool.execute({})
166
self.assertIn("error", result)
@@ -78,12 +78,22 @@ def run_api_args(args):
78
78
log_config=args.log_config,
79
79
)
80
80
81
def get_mcp_parser():
82
mcp_parser = ArgumentParser(description="Run the MCP (Model Context Protocol) server")
83
mcp_parser.add_argument("--debug", "-d", action="store_true", help="Enable verbose logging.")
84
return mcp_parser
85
86
def run_mcp_args(args):
87
from ..mcp.server import main as mcp_main
88
mcp_main()
89
81
90
def main():
82
91
parser = argparse.ArgumentParser(description="Run gpt4free", exit_on_error=False)
83
92
subparsers = parser.add_subparsers(dest="mode", help="Mode to run the g4f in.")
84
93
subparsers.add_parser("api", parents=[get_api_parser()], add_help=False)
85
94
subparsers.add_parser("gui", parents=[gui_parser()], add_help=False)
86
95
subparsers.add_parser("client", parents=[get_parser()], add_help=False)
96
subparsers.add_parser("mcp", parents=[get_mcp_parser()], add_help=False)
87
97
88
98
try:
89
99
args = parser.parse_args()
@@ -93,8 +103,10 @@ def main():
93
103
run_gui_args(args)
94
104
elif args.mode == "client":
95
105
run_client_args(args)
106
elif args.mode == "mcp":
107
run_mcp_args(args)
96
108
else:
97
raise argparse.ArgumentError(None, "No valid mode specified. Use 'api', 'gui', or 'client'.")
109
raise argparse.ArgumentError(None, "No valid mode specified. Use 'api', 'gui', 'client', or 'mcp'.")
98
110
except argparse.ArgumentError:
99
111
try:
100
112
run_client_args(get_parser(exit_on_error=False).parse_args(), exit_on_error=False)
@@ -0,0 +1,283 @@
1
# gpt4free MCP Server
2
3
A Model Context Protocol (MCP) server implementation for gpt4free that provides AI assistants with access to web search, scraping, and image generation capabilities.
4
5
## Overview
6
7
The gpt4free MCP server exposes three main tools:
8
9
1. **Web Search** - Search the web using DuckDuckGo
10
2. **Web Scraping** - Extract and clean text content from web pages
11
3. **Image Generation** - Generate images from text prompts using various AI providers
12
13
## Installation
14
15
The MCP server is included with gpt4free. No additional installation is required beyond the base gpt4free package.
16
17
```bash
18
pip install -e .
19
```
20
21
## Usage
22
23
### Running the MCP Server
24
25
Start the MCP server using:
26
27
```bash
28
python -m g4f.mcp
29
```
30
31
Or using the g4f command:
32
33
```bash
34
g4f mcp
35
```
36
37
The server communicates over stdin/stdout using JSON-RPC 2.0 protocol.
38
39
### Configuration for AI Assistants
40
41
To use this MCP server with an AI assistant like Claude Desktop, add the following to your MCP configuration:
42
43
**For Claude Desktop** (`claude_desktop_config.json`):
44
45
```json
46
{
47
"mcpServers": {
48
"gpt4free": {
49
"command": "python",
50
"args": ["-m", "g4f.mcp"]
51
}
52
}
53
}
54
```
55
56
**For VS Code with Cline**:
57
58
```json
59
{
60
"mcpServers": {
61
"gpt4free": {
62
"command": "python",
63
"args": ["-m", "g4f.mcp"],
64
"disabled": false
65
}
66
}
67
}
68
```
69
70
## Available Tools
71
72
### web_search
73
74
Search the web for information.
75
76
**Parameters:**
77
- `query` (string, required): The search query
78
- `max_results` (integer, optional): Maximum number of results (default: 5)
79
80
**Example:**
81
```json
82
{
83
"name": "web_search",
84
"arguments": {
85
"query": "latest AI developments 2024",
86
"max_results": 5
87
}
88
}
89
```
90
91
### web_scrape
92
93
Scrape and extract text content from a web page.
94
95
**Parameters:**
96
- `url` (string, required): The URL to scrape
97
- `max_words` (integer, optional): Maximum words to extract (default: 1000)
98
99
**Example:**
100
```json
101
{
102
"name": "web_scrape",
103
"arguments": {
104
"url": "https://example.com/article",
105
"max_words": 1000
106
}
107
}
108
```
109
110
### image_generation
111
112
Generate images from text prompts.
113
114
**Parameters:**
115
- `prompt` (string, required): Description of the image to generate
116
- `model` (string, optional): Image model to use (default: "flux")
117
- `width` (integer, optional): Image width in pixels (default: 1024)
118
- `height` (integer, optional): Image height in pixels (default: 1024)
119
120
**Example:**
121
```json
122
{
123
"name": "image_generation",
124
"arguments": {
125
"prompt": "A serene mountain landscape at sunset",
126
"width": 1024,
127
"height": 1024
128
}
129
}
130
```
131
132
## Protocol Details
133
134
The MCP server implements the Model Context Protocol using JSON-RPC 2.0 over stdio transport.
135
136
### Supported Methods
137
138
- `initialize` - Initialize connection with the server
139
- `tools/list` - List all available tools
140
- `tools/call` - Execute a tool with given arguments
141
- `ping` - Health check
142
143
### Example Request/Response
144
145
**Request:**
146
```json
147
{
148
"jsonrpc": "2.0",
149
"id": 1,
150
"method": "tools/call",
151
"params": {
152
"name": "web_search",
153
"arguments": {
154
"query": "Python programming tutorials",
155
"max_results": 3
156
}
157
}
158
}
159
```
160
161
**Response:**
162
```json
163
{
164
"jsonrpc": "2.0",
165
"id": 1,
166
"result": {
167
"content": [
168
{
169
"type": "text",
170
"text": "{\"query\": \"Python programming tutorials\", \"results\": [...], \"count\": 3}"
171
}
172
]
173
}
174
}
175
```
176
177
## Requirements
178
179
The MCP server requires the following dependencies (included in gpt4free):
180
181
- `aiohttp` - For async HTTP requests
182
- `beautifulsoup4` - For web scraping
183
- `ddgs` - For web search
184
185
These are automatically installed with:
186
187
```bash
188
pip install -r requirements.txt
189
```
190
191
## Error Handling
192
193
The server returns standard JSON-RPC error responses:
194
195
- `-32601`: Method not found
196
- `-32602`: Invalid parameters
197
- `-32603`: Internal error
198
199
Errors specific to tools are returned in the result object with an `error` field.
200
201
## Development
202
203
### Project Structure
204
205
```
206
g4f/mcp/
207
├── __init__.py # Package initialization
208
├── __main__.py # CLI entry point
209
├── server.py # MCP server implementation
210
├── tools.py # Tool implementations
211
└── README.md # This file
212
```
213
214
### Adding New Tools
215
216
To add a new tool:
217
218
1. Create a new class inheriting from `MCPTool` in `tools.py`
219
2. Implement the required properties and methods
220
3. Register the tool in `MCPServer.__init__()` in `server.py`
221
222
Example:
223
224
```python
225
class MyNewTool(MCPTool):
226
@property
227
def description(self) -> str:
228
return "Description of what the tool does"
229
230
@property
231
def input_schema(self) -> Dict[str, Any]:
232
return {
233
"type": "object",
234
"properties": {
235
"param1": {
236
"type": "string",
237
"description": "Parameter description"
238
}
239
},
240
"required": ["param1"]
241
}
242
243
async def execute(self, arguments: Dict[str, Any]) -> Any:
244
# Implementation
245
pass
246
```
247
248
## Troubleshooting
249
250
### Server Won't Start
251
252
Make sure all dependencies are installed:
253
```bash
254
pip install -r requirements.txt
255
```
256
257
### Tools Return Errors
258
259
Check that:
260
- Network connectivity is available for web search and scraping
261
- URLs are valid and accessible
262
- Image generation providers are not rate-limited
263
264
### Debug Mode
265
266
The server writes diagnostic information to stderr. To see debug output:
267
```bash
268
python -m g4f.mcp 2> debug.log
269
```
270
271
## License
272
273
This MCP server is part of the gpt4free project and is licensed under the GNU General Public License v3.0.
274
275
## Contributing
276
277
Contributions are welcome! Please see the main gpt4free repository for contribution guidelines.
278
279
## Related Links
280
281
- [gpt4free Repository](https://github.com/xtekky/gpt4free)
282
- [Model Context Protocol Specification](https://modelcontextprotocol.io/)
283
- [MCP Documentation](https://modelcontextprotocol.io/docs)
@@ -0,0 +1,13 @@
1
"""MCP (Model Context Protocol) Server for gpt4free
2
3
This module provides an MCP server implementation that exposes gpt4free capabilities
4
through the Model Context Protocol standard, allowing AI assistants to access:
5
- Web search functionality
6
- Web scraping capabilities
7
- Image generation using various providers
8
"""
9
10
from .server import MCPServer
11
from .tools import WebSearchTool, WebScrapeTool, ImageGenerationTool
12
13
__all__ = ['MCPServer', 'WebSearchTool', 'WebScrapeTool', 'ImageGenerationTool']
@@ -0,0 +1,9 @@
1
"""Main entry point for gpt4free MCP server
2
3
This module provides the main entry point for running the MCP server.
4
"""
5
6
from .server import main
7
8
if __name__ == "__main__":
9
main()
@@ -0,0 +1,9 @@
1
{
2
"mcpServers": {
3
"gpt4free": {
4
"command": "python",
5
"args": ["-m", "g4f.mcp"],
6
"description": "gpt4free MCP server providing web search, scraping, and image generation"
7
}
8
}
9
}
@@ -0,0 +1,202 @@
1
"""MCP Server implementation using stdio transport
2
3
This module implements a Model Context Protocol (MCP) server that communicates
4
over standard input/output using JSON-RPC 2.0. The server exposes tools for:
5
- Web search
6
- Web scraping
7
- Image generation
8
"""
9
10
from __future__ import annotations
11
12
import sys
13
import json
14
import asyncio
15
from typing import Any, Dict, List, Optional
16
from dataclasses import dataclass, asdict
17
18
from .tools import WebSearchTool, WebScrapeTool, ImageGenerationTool
19
20
21
@dataclass
22
class MCPRequest:
23
"""MCP request following JSON-RPC 2.0 format"""
24
jsonrpc: str = "2.0"
25
id: Optional[int | str] = None
26
method: Optional[str] = None
27
params: Optional[Dict[str, Any]] = None
28
29
30
@dataclass
31
class MCPResponse:
32
"""MCP response following JSON-RPC 2.0 format"""
33
jsonrpc: str = "2.0"
34
id: Optional[int | str] = None
35
result: Optional[Any] = None
36
error: Optional[Dict[str, Any]] = None
37
38
39
class MCPServer:
40
"""Model Context Protocol server for gpt4free
41
42
This server exposes gpt4free capabilities through the MCP standard,
43
allowing AI assistants to utilize web search, scraping, and image generation.
44
"""
45
46
def __init__(self):
47
"""Initialize MCP server with available tools"""
48
self.tools = {
49
'web_search': WebSearchTool(),
50
'web_scrape': WebScrapeTool(),
51
'image_generation': ImageGenerationTool(),
52
}
53
self.server_info = {
54
"name": "gpt4free-mcp-server",
55
"version": "1.0.0",
56
"description": "MCP server providing web search, scraping, and image generation capabilities"
57
}
58
59
def get_tool_list(self) -> List[Dict[str, Any]]:
60
"""Get list of available tools with their schemas"""
61
tool_list = []
62
for name, tool in self.tools.items():
63
tool_list.append({
64
"name": name,
65
"description": tool.description,
66
"inputSchema": tool.input_schema
67
})
68
return tool_list
69
70
async def handle_request(self, request: MCPRequest) -> MCPResponse:
71
"""Handle incoming MCP request"""
72
try:
73
method = request.method
74
params = request.params or {}
75
76
# Handle MCP protocol methods
77
if method == "initialize":
78
result = {
79
"protocolVersion": "2024-11-05",
80
"serverInfo": self.server_info,
81
"capabilities": {
82
"tools": {}
83
}
84
}
85
return MCPResponse(jsonrpc="2.0", id=request.id, result=result)
86
87
elif method == "tools/list":
88
result = {
89
"tools": self.get_tool_list()
90
}
91
return MCPResponse(jsonrpc="2.0", id=request.id, result=result)
92
93
elif method == "tools/call":
94
tool_name = params.get("name")
95
tool_arguments = params.get("arguments", {})
96
97
if tool_name not in self.tools:
98
return MCPResponse(
99
jsonrpc="2.0",
100
id=request.id,
101
error={
102
"code": -32601,
103
"message": f"Tool not found: {tool_name}"
104
}
105
)
106
107
tool = self.tools[tool_name]
108
result = await tool.execute(tool_arguments)
109
110
return MCPResponse(
111
jsonrpc="2.0",
112
id=request.id,
113
result={
114
"content": [
115
{
116
"type": "text",
117
"text": json.dumps(result, indent=2)
118
}
119
]
120
}
121
)
122
123
elif method == "ping":
124
return MCPResponse(jsonrpc="2.0", id=request.id, result={})
125
126
else:
127
return MCPResponse(
128
jsonrpc="2.0",
129
id=request.id,
130
error={
131
"code": -32601,
132
"message": f"Method not found: {method}"
133
}
134
)
135
136
except Exception as e:
137
return MCPResponse(
138
jsonrpc="2.0",
139
id=request.id,
140
error={
141
"code": -32603,
142
"message": f"Internal error: {str(e)}"
143
}
144
)
145
146
async def run(self):
147
"""Run the MCP server with stdio transport"""
148
# Write server info to stderr for debugging
149
sys.stderr.write(f"Starting {self.server_info['name']} v{self.server_info['version']}\n")
150
sys.stderr.flush()
151
152
while True:
153
try:
154
# Read line from stdin
155
line = await asyncio.get_event_loop().run_in_executor(
156
None, sys.stdin.readline
157
)
158
159
if not line:
160
break
161
162
# Parse JSON-RPC request
163
request_data = json.loads(line)
164
request = MCPRequest(
165
jsonrpc=request_data.get("jsonrpc", "2.0"),
166
id=request_data.get("id"),
167
method=request_data.get("method"),
168
params=request_data.get("params")
169
)
170
171
# Handle request
172
response = await self.handle_request(request)
173
174
# Write response to stdout
175
response_dict = {
176
"jsonrpc": response.jsonrpc,
177
"id": response.id
178
}
179
if response.result is not None:
180
response_dict["result"] = response.result
181
if response.error is not None:
182
response_dict["error"] = response.error
183
184
sys.stdout.write(json.dumps(response_dict) + "\n")
185
sys.stdout.flush()
186
187
except json.JSONDecodeError as e:
188
sys.stderr.write(f"JSON decode error: {e}\n")
189
sys.stderr.flush()
190
except Exception as e:
191
sys.stderr.write(f"Error: {e}\n")
192
sys.stderr.flush()
193
194
195
def main():
196
"""Main entry point for MCP server"""
197
server = MCPServer()
198
asyncio.run(server.run())
199
200
201
if __name__ == "__main__":
202
main()
@@ -0,0 +1,264 @@
1
"""MCP Tools for gpt4free
2
3
This module provides MCP tool implementations that wrap gpt4free capabilities:
4
- WebSearchTool: Web search using ddg search
5
- WebScrapeTool: Web page scraping and content extraction
6
- ImageGenerationTool: Image generation using various AI providers
7
"""
8
9
from __future__ import annotations
10
11
import asyncio
12
from typing import Any, Dict
13
from abc import ABC, abstractmethod
14
15
16
class MCPTool(ABC):
17
"""Base class for MCP tools"""
18
19
@property
20
@abstractmethod
21
def description(self) -> str:
22
"""Tool description"""
23
pass
24
25
@property
26
@abstractmethod
27
def input_schema(self) -> Dict[str, Any]:
28
"""JSON schema for tool input parameters"""
29
pass
30
31
@abstractmethod
32
async def execute(self, arguments: Dict[str, Any]) -> Any:
33
"""Execute the tool with given arguments"""
34
pass
35
36
37
class WebSearchTool(MCPTool):
38
"""Web search tool using gpt4free's search capabilities"""
39
40
@property
41
def description(self) -> str:
42
return "Search the web for information using DuckDuckGo. Returns search results with titles, URLs, and snippets."
43
44
@property
45
def input_schema(self) -> Dict[str, Any]:
46
return {
47
"type": "object",
48
"properties": {
49
"query": {
50
"type": "string",
51
"description": "The search query to execute"
52
},
53
"max_results": {
54
"type": "integer",
55
"description": "Maximum number of results to return (default: 5)",
56
"default": 5
57
}
58
},
59
"required": ["query"]
60
}
61
62
async def execute(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
63
"""Execute web search"""
64
from ..tools.web_search import do_search
65
66
query = arguments.get("query", "")
67
max_results = arguments.get("max_results", 5)
68
69
if not query:
70
return {
71
"error": "Query parameter is required"
72
}
73
74
try:
75
# Perform search
76
result, sources = await do_search(
77
prompt=query,
78
query=query,
79
instructions=""
80
)
81
82
# Format results
83
search_results = []
84
if sources:
85
for i, source in enumerate(sources[:max_results]):
86
search_results.append({
87
"title": source.get("title", ""),
88
"url": source.get("url", ""),
89
"snippet": source.get("snippet", "")
90
})
91
92
return {
93
"query": query,
94
"results": search_results,
95
"count": len(search_results)
96
}
97
98
except Exception as e:
99
return {
100
"error": f"Search failed: {str(e)}"
101
}
102
103
104
class WebScrapeTool(MCPTool):
105
"""Web scraping tool using gpt4free's scraping capabilities"""
106
107
@property
108
def description(self) -> str:
109
return "Scrape and extract text content from a web page URL. Returns cleaned text content with optional word limit."
110
111
@property
112
def input_schema(self) -> Dict[str, Any]:
113
return {
114
"type": "object",
115
"properties": {
116
"url": {
117
"type": "string",
118
"description": "The URL of the web page to scrape"
119
},
120
"max_words": {
121
"type": "integer",
122
"description": "Maximum number of words to extract (default: 1000)",
123
"default": 1000
124
}
125
},
126
"required": ["url"]
127
}
128
129
async def execute(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
130
"""Execute web scraping"""
131
from ..tools.fetch_and_scrape import fetch_and_scrape
132
from aiohttp import ClientSession
133
134
url = arguments.get("url", "")
135
max_words = arguments.get("max_words", 1000)
136
137
if not url:
138
return {
139
"error": "URL parameter is required"
140
}
141
142
try:
143
# Scrape the URL
144
async with ClientSession() as session:
145
content = await fetch_and_scrape(
146
session=session,
147
url=url,
148
max_words=max_words,
149
add_source=True
150
)
151
152
if not content:
153
return {
154
"error": "Failed to scrape content from URL"
155
}
156
157
return {
158
"url": url,
159
"content": content,
160
"word_count": len(content.split())
161
}
162
163
except Exception as e:
164
return {
165
"error": f"Scraping failed: {str(e)}"
166
}
167
168
169
class ImageGenerationTool(MCPTool):
170
"""Image generation tool using gpt4free's image generation capabilities"""
171
172
@property
173
def description(self) -> str:
174
return "Generate images from text prompts using AI image generation providers. Returns base64-encoded image data."
175
176
@property
177
def input_schema(self) -> Dict[str, Any]:
178
return {
179
"type": "object",
180
"properties": {
181
"prompt": {
182
"type": "string",
183
"description": "The text prompt describing the image to generate"
184
},
185
"model": {
186
"type": "string",
187
"description": "The image generation model to use (default: flux)",
188
"default": "flux"
189
},
190
"width": {
191
"type": "integer",
192
"description": "Image width in pixels (default: 1024)",
193
"default": 1024
194
},
195
"height": {
196
"type": "integer",
197
"description": "Image height in pixels (default: 1024)",
198
"default": 1024
199
}
200
},
201
"required": ["prompt"]
202
}
203
204
async def execute(self, arguments: Dict[str, Any]) -> Dict[str, Any]:
205
"""Execute image generation"""
206
from ..client import AsyncClient
207
from ..image import to_data_uri
208
import base64
209
210
prompt = arguments.get("prompt", "")
211
model = arguments.get("model", "flux")
212
width = arguments.get("width", 1024)
213
height = arguments.get("height", 1024)
214
215
if not prompt:
216
return {
217
"error": "Prompt parameter is required"
218
}
219
220
try:
221
# Generate image using gpt4free client
222
client = AsyncClient()
223
224
response = await client.images.generate(
225
model=model,
226
prompt=prompt,
227
width=width,
228
height=height
229
)
230
231
# Get the image data
232
if response and hasattr(response, 'data') and response.data:
233
image_data = response.data[0]
234
235
# Convert to base64 if needed
236
if hasattr(image_data, 'url'):
237
image_url = image_data.url
238
239
# Check if it's already a data URI
240
if image_url.startswith('data:'):
241
return {
242
"prompt": prompt,
243
"model": model,
244
"width": width,
245
"height": height,
246
"image": image_url
247
}
248
else:
249
return {
250
"prompt": prompt,
251
"model": model,
252
"width": width,
253
"height": height,
254
"image_url": image_url
255
}
256
257
return {
258
"error": "Image generation failed: No image data in response"
259
}
260
261
except Exception as e:
262
return {
263
"error": f"Image generation failed: {str(e)}"
264
}
@@ -114,7 +114,10 @@ setup(
114
114
install_requires=INSTALL_REQUIRE,
115
115
extras_require=EXTRA_REQUIRE,
116
116
entry_points={
117
'console_scripts': ['g4f=g4f.cli:main'],
117
'console_scripts': [
118
'g4f=g4f.cli:main',
119
'g4f-mcp=g4f.mcp.server:main',
120
],
118
121
},
119
122
url='https://github.com/xtekky/gpt4free', # Link to your GitHub repository
120
123
project_urls={