httpx-mcp 1.0.0__tar.gz

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.
@@ -0,0 +1,164 @@
1
+ Metadata-Version: 2.4
2
+ Name: httpx-mcp
3
+ Version: 1.0.0
4
+ Summary: A MCP tool for HTTP request testing using httpx
5
+ Author-email: ZHEFOX <zhefox@outlook.com>
6
+ Requires-Python: >=3.10
7
+ Requires-Dist: httpx>=0.27.0
8
+ Requires-Dist: mcp>=1.0.0
9
+ Description-Content-Type: text/markdown
10
+
11
+ # HTTPX MCP
12
+
13
+ An MCP tool for HTTP interface testing, built on the httpx library, designed for AI.
14
+
15
+ ## Features
16
+
17
+ - 🚀 **Full HTTP Method Support**: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
18
+ - 📝 **Multiple Request Formats**: JSON, form data, raw text
19
+ - 🔧 **Custom Headers**: Support for arbitrary HTTP headers
20
+ - 📋 **Raw Request Parsing**: Directly paste Burp Suite captured requests
21
+ - ⏱️ **Response Details**: Status code, response headers, response body, timing statistics
22
+ - 🔒 **SSL Control**: Optional SSL certificate verification
23
+
24
+ ## Installation
25
+
26
+ ```bash
27
+ cd httpx-mcp
28
+ pip install -e .
29
+ ```
30
+
31
+ ## MCP Configuration
32
+
33
+ Add to your MCP configuration file:
34
+
35
+ ```json
36
+ {
37
+ "mcpServers": {
38
+ "httpx-mcp": {
39
+ "command": "python",
40
+ "args": ["-m", "httpx_mcp.server"],
41
+ "cwd": "c:/Users/ZHEFOX/Desktop/mcptools/httpx-mcp"
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ Or use directly after installation:
48
+
49
+ ```json
50
+ {
51
+ "mcpServers": {
52
+ "httpx-mcp": {
53
+ "command": "httpx-mcp"
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ ## Available Tools
60
+
61
+ ### 1. `http_request` - General HTTP Request
62
+
63
+ Send any HTTP request, switch request method via the `method` parameter.
64
+
65
+ **Parameters:**
66
+ | Parameter | Type | Required | Default | Description |
67
+ |-----------|------|----------|---------|-------------|
68
+ | `url` | string | ✅ | - | Full URL |
69
+ | `method` | string | - | GET | HTTP method: GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS |
70
+ | `params` | string | - | - | URL query parameters, JSON or key=value format |
71
+ | `headers` | string | - | - | Request headers, JSON format |
72
+ | `body` | string | - | - | Request body |
73
+ | `content_type` | string | - | application/json | Content-Type |
74
+ | `timeout` | number | - | 30 | Timeout in seconds |
75
+ | `follow_redirects` | boolean | - | true | Whether to follow redirects |
76
+ | `verify_ssl` | boolean | - | true | Whether to verify SSL |
77
+ | `include_headers` | boolean | - | true | Whether response includes headers |
78
+
79
+ **Examples:**
80
+
81
+ ```
82
+ # GET request
83
+ method="GET", url="https://httpbin.org/get"
84
+
85
+ # GET with query parameters
86
+ method="GET", url="https://httpbin.org/get", params='{"page": "1", "size": "10"}'
87
+
88
+ # POST JSON
89
+ method="POST", url="https://httpbin.org/post", body='{"name": "test", "value": 123}'
90
+
91
+ # PUT update
92
+ method="PUT", url="https://httpbin.org/put", body='{"id": 1, "name": "updated"}'
93
+
94
+ # DELETE
95
+ method="DELETE", url="https://httpbin.org/delete"
96
+
97
+ # With authentication header
98
+ method="GET", url="https://api.example.com/users", headers='{"Authorization": "Bearer token123"}'
99
+
100
+ # POST form
101
+ method="POST", url="https://httpbin.org/post", body="username=admin&password=123", content_type="application/x-www-form-urlencoded"
102
+
103
+ # Disable SSL verification
104
+ method="GET", url="https://self-signed.example.com", verify_ssl=false
105
+ ```
106
+
107
+ ### 2. `http_raw` - Raw HTTP Request
108
+
109
+ Directly parse raw HTTP requests captured by tools like Burp Suite.
110
+
111
+ **Parameters:**
112
+ | Parameter | Type | Required | Default | Description |
113
+ |-----------|------|----------|---------|-------------|
114
+ | `raw_request` | string | ✅ | - | Raw HTTP request text |
115
+ | `base_url` | string | - | - | Base URL (if request doesn't contain full URL) |
116
+ | `verify_ssl` | boolean | - | true | Whether to verify SSL |
117
+
118
+ **Example:**
119
+
120
+ ```
121
+ raw_request="""
122
+ POST /api/login HTTP/1.1
123
+ Host: example.com
124
+ Content-Type: application/json
125
+ Cookie: session=abc123
126
+
127
+ {"username":"admin","password":"123456"}
128
+ """
129
+ base_url="https://example.com"
130
+ ```
131
+
132
+ ## Response Format
133
+
134
+ The tool returns formatted response information:
135
+
136
+ ```
137
+ HTTP/1.1 200 OK
138
+
139
+ === Response Headers ===
140
+ content-type: application/json
141
+ date: Mon, 01 Jan 2024 00:00:00 GMT
142
+ ...
143
+
144
+ === Response Body ===
145
+ {
146
+ "result": "success",
147
+ "data": {...}
148
+ }
149
+
150
+ === Request Info ===
151
+ Time: 0.234s
152
+ Size: 1024 bytes
153
+ ```
154
+
155
+ ## Use Cases
156
+
157
+ 1. **API Testing**: Quickly test REST API endpoints
158
+ 2. **Security Testing**: Send custom payloads for security testing
159
+ 3. **Interface Debugging**: View detailed request/response information
160
+ 4. **Request Replay**: Directly use Burp captured content to replay requests
161
+
162
+ ## License
163
+
164
+ MIT
@@ -0,0 +1,154 @@
1
+ # HTTPX MCP
2
+
3
+ An MCP tool for HTTP interface testing, built on the httpx library, designed for AI.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Full HTTP Method Support**: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
8
+ - 📝 **Multiple Request Formats**: JSON, form data, raw text
9
+ - 🔧 **Custom Headers**: Support for arbitrary HTTP headers
10
+ - 📋 **Raw Request Parsing**: Directly paste Burp Suite captured requests
11
+ - ⏱️ **Response Details**: Status code, response headers, response body, timing statistics
12
+ - 🔒 **SSL Control**: Optional SSL certificate verification
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ cd httpx-mcp
18
+ pip install -e .
19
+ ```
20
+
21
+ ## MCP Configuration
22
+
23
+ Add to your MCP configuration file:
24
+
25
+ ```json
26
+ {
27
+ "mcpServers": {
28
+ "httpx-mcp": {
29
+ "command": "python",
30
+ "args": ["-m", "httpx_mcp.server"],
31
+ "cwd": "c:/Users/ZHEFOX/Desktop/mcptools/httpx-mcp"
32
+ }
33
+ }
34
+ }
35
+ ```
36
+
37
+ Or use directly after installation:
38
+
39
+ ```json
40
+ {
41
+ "mcpServers": {
42
+ "httpx-mcp": {
43
+ "command": "httpx-mcp"
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ ## Available Tools
50
+
51
+ ### 1. `http_request` - General HTTP Request
52
+
53
+ Send any HTTP request, switch request method via the `method` parameter.
54
+
55
+ **Parameters:**
56
+ | Parameter | Type | Required | Default | Description |
57
+ |-----------|------|----------|---------|-------------|
58
+ | `url` | string | ✅ | - | Full URL |
59
+ | `method` | string | - | GET | HTTP method: GET/POST/PUT/DELETE/PATCH/HEAD/OPTIONS |
60
+ | `params` | string | - | - | URL query parameters, JSON or key=value format |
61
+ | `headers` | string | - | - | Request headers, JSON format |
62
+ | `body` | string | - | - | Request body |
63
+ | `content_type` | string | - | application/json | Content-Type |
64
+ | `timeout` | number | - | 30 | Timeout in seconds |
65
+ | `follow_redirects` | boolean | - | true | Whether to follow redirects |
66
+ | `verify_ssl` | boolean | - | true | Whether to verify SSL |
67
+ | `include_headers` | boolean | - | true | Whether response includes headers |
68
+
69
+ **Examples:**
70
+
71
+ ```
72
+ # GET request
73
+ method="GET", url="https://httpbin.org/get"
74
+
75
+ # GET with query parameters
76
+ method="GET", url="https://httpbin.org/get", params='{"page": "1", "size": "10"}'
77
+
78
+ # POST JSON
79
+ method="POST", url="https://httpbin.org/post", body='{"name": "test", "value": 123}'
80
+
81
+ # PUT update
82
+ method="PUT", url="https://httpbin.org/put", body='{"id": 1, "name": "updated"}'
83
+
84
+ # DELETE
85
+ method="DELETE", url="https://httpbin.org/delete"
86
+
87
+ # With authentication header
88
+ method="GET", url="https://api.example.com/users", headers='{"Authorization": "Bearer token123"}'
89
+
90
+ # POST form
91
+ method="POST", url="https://httpbin.org/post", body="username=admin&password=123", content_type="application/x-www-form-urlencoded"
92
+
93
+ # Disable SSL verification
94
+ method="GET", url="https://self-signed.example.com", verify_ssl=false
95
+ ```
96
+
97
+ ### 2. `http_raw` - Raw HTTP Request
98
+
99
+ Directly parse raw HTTP requests captured by tools like Burp Suite.
100
+
101
+ **Parameters:**
102
+ | Parameter | Type | Required | Default | Description |
103
+ |-----------|------|----------|---------|-------------|
104
+ | `raw_request` | string | ✅ | - | Raw HTTP request text |
105
+ | `base_url` | string | - | - | Base URL (if request doesn't contain full URL) |
106
+ | `verify_ssl` | boolean | - | true | Whether to verify SSL |
107
+
108
+ **Example:**
109
+
110
+ ```
111
+ raw_request="""
112
+ POST /api/login HTTP/1.1
113
+ Host: example.com
114
+ Content-Type: application/json
115
+ Cookie: session=abc123
116
+
117
+ {"username":"admin","password":"123456"}
118
+ """
119
+ base_url="https://example.com"
120
+ ```
121
+
122
+ ## Response Format
123
+
124
+ The tool returns formatted response information:
125
+
126
+ ```
127
+ HTTP/1.1 200 OK
128
+
129
+ === Response Headers ===
130
+ content-type: application/json
131
+ date: Mon, 01 Jan 2024 00:00:00 GMT
132
+ ...
133
+
134
+ === Response Body ===
135
+ {
136
+ "result": "success",
137
+ "data": {...}
138
+ }
139
+
140
+ === Request Info ===
141
+ Time: 0.234s
142
+ Size: 1024 bytes
143
+ ```
144
+
145
+ ## Use Cases
146
+
147
+ 1. **API Testing**: Quickly test REST API endpoints
148
+ 2. **Security Testing**: Send custom payloads for security testing
149
+ 3. **Interface Debugging**: View detailed request/response information
150
+ 4. **Request Replay**: Directly use Burp captured content to replay requests
151
+
152
+ ## License
153
+
154
+ MIT
@@ -0,0 +1,3 @@
1
+ """HTTPX MCP - A MCP tool for HTTP request testing using httpx."""
2
+
3
+ __version__ = "1.0.0"
@@ -0,0 +1,362 @@
1
+ """
2
+ HTTPX MCP Server - HTTP Request Testing Tool
3
+
4
+ Provides the following MCP tools:
5
+ - http_request: Send HTTP requests (GET, POST, PUT, DELETE, PATCH, etc.)
6
+ - http_raw: Parse raw HTTP requests (supports Burp Suite capture format)
7
+ """
8
+
9
+ import json
10
+ import sys
11
+ from typing import Any
12
+
13
+ import httpx
14
+ from mcp.server import Server
15
+ from mcp.server.stdio import stdio_server
16
+ from mcp.types import Tool, TextContent
17
+
18
+ # Create MCP server
19
+ server = Server("httpx-mcp")
20
+
21
+
22
+ def format_response(response: httpx.Response, include_headers: bool = True) -> str:
23
+ """Format HTTP response into a readable string"""
24
+ result_parts = []
25
+
26
+ # Status line
27
+ result_parts.append(f"HTTP/{response.http_version} {response.status_code} {response.reason_phrase}")
28
+ result_parts.append("")
29
+
30
+ # Response headers
31
+ if include_headers:
32
+ result_parts.append("=== Response Headers ===")
33
+ for name, value in response.headers.items():
34
+ result_parts.append(f"{name}: {value}")
35
+ result_parts.append("")
36
+
37
+ # Response body
38
+ result_parts.append("=== Response Body ===")
39
+
40
+ content_type = response.headers.get("content-type", "")
41
+ body = response.text
42
+
43
+ # Try to format JSON
44
+ if "application/json" in content_type:
45
+ try:
46
+ parsed = json.loads(body)
47
+ body = json.dumps(parsed, indent=2, ensure_ascii=False)
48
+ except json.JSONDecodeError:
49
+ pass
50
+
51
+ result_parts.append(body)
52
+
53
+ # Add response time
54
+ result_parts.append("")
55
+ result_parts.append(f"=== Request Info ===")
56
+ result_parts.append(f"Time: {response.elapsed.total_seconds():.3f}s")
57
+ result_parts.append(f"Size: {len(response.content)} bytes")
58
+
59
+ return "\n".join(result_parts)
60
+
61
+
62
+ def parse_headers(headers_input: str | dict | list | None) -> dict:
63
+ """Parse request headers, supports multiple formats"""
64
+ if headers_input is None:
65
+ return {}
66
+
67
+ if isinstance(headers_input, dict):
68
+ return headers_input
69
+
70
+ if isinstance(headers_input, list):
71
+ result = {}
72
+ for item in headers_input:
73
+ if isinstance(item, str) and ":" in item:
74
+ key, value = item.split(":", 1)
75
+ result[key.strip()] = value.strip()
76
+ elif isinstance(item, dict):
77
+ result.update(item)
78
+ return result
79
+
80
+ if isinstance(headers_input, str):
81
+ # Try to parse as JSON
82
+ try:
83
+ parsed = json.loads(headers_input)
84
+ if isinstance(parsed, dict):
85
+ return parsed
86
+ elif isinstance(parsed, list):
87
+ return parse_headers(parsed)
88
+ except json.JSONDecodeError:
89
+ pass
90
+
91
+ # Parse line by line "Key: Value" format
92
+ result = {}
93
+ for line in headers_input.strip().split("\n"):
94
+ line = line.strip()
95
+ if ":" in line:
96
+ key, value = line.split(":", 1)
97
+ result[key.strip()] = value.strip()
98
+ return result
99
+
100
+ return {}
101
+
102
+
103
+ def parse_params(params_input: str | dict | None) -> dict | None:
104
+ """Parse URL query parameters"""
105
+ if params_input is None:
106
+ return None
107
+
108
+ if isinstance(params_input, dict):
109
+ return params_input
110
+
111
+ if isinstance(params_input, str):
112
+ try:
113
+ return json.loads(params_input)
114
+ except json.JSONDecodeError:
115
+ # Parse key=value&key2=value2 format
116
+ result = {}
117
+ for pair in params_input.split("&"):
118
+ if "=" in pair:
119
+ key, value = pair.split("=", 1)
120
+ result[key.strip()] = value.strip()
121
+ return result if result else None
122
+
123
+ return None
124
+
125
+
126
+ @server.list_tools()
127
+ async def list_tools() -> list[Tool]:
128
+ """List all available MCP tools"""
129
+ return [
130
+ Tool(
131
+ name="http_request",
132
+ description="""Send HTTP request to specified URL. Supports all HTTP methods (GET/POST/PUT/DELETE/PATCH, etc.).
133
+
134
+ Usage examples:
135
+ - GET request: method="GET", url="https://api.example.com/users"
136
+ - GET with params: method="GET", url="...", params='{"page":"1","size":"10"}'
137
+ - POST JSON: method="POST", url="...", body='{"key":"value"}'
138
+ - PUT update: method="PUT", url="...", body='{"id":1,"name":"test"}'
139
+ - DELETE: method="DELETE", url="https://api.example.com/users/1"
140
+ - Custom headers: headers='{"Authorization":"Bearer xxx"}'
141
+ - Form submit: body="name=test&age=18", content_type="application/x-www-form-urlencoded" """,
142
+ inputSchema={
143
+ "type": "object",
144
+ "properties": {
145
+ "method": {
146
+ "type": "string",
147
+ "description": "HTTP method: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS",
148
+ "enum": ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"],
149
+ "default": "GET"
150
+ },
151
+ "url": {
152
+ "type": "string",
153
+ "description": "Full URL for the request"
154
+ },
155
+ "params": {
156
+ "type": "string",
157
+ "description": "URL query parameters, JSON format or key=value&key2=value2 format"
158
+ },
159
+ "headers": {
160
+ "type": "string",
161
+ "description": "Request headers, JSON format, e.g.: {\"Authorization\": \"Bearer xxx\"}"
162
+ },
163
+ "body": {
164
+ "type": "string",
165
+ "description": "Request body, can be JSON string, form data, or raw text"
166
+ },
167
+ "content_type": {
168
+ "type": "string",
169
+ "description": "Content-Type, e.g.: application/json, application/x-www-form-urlencoded",
170
+ "default": "application/json"
171
+ },
172
+ "timeout": {
173
+ "type": "number",
174
+ "description": "Request timeout in seconds",
175
+ "default": 30
176
+ },
177
+ "follow_redirects": {
178
+ "type": "boolean",
179
+ "description": "Whether to follow redirects",
180
+ "default": True
181
+ },
182
+ "verify_ssl": {
183
+ "type": "boolean",
184
+ "description": "Whether to verify SSL certificate",
185
+ "default": True
186
+ },
187
+ "include_headers": {
188
+ "type": "boolean",
189
+ "description": "Whether to include response headers in the output",
190
+ "default": True
191
+ }
192
+ },
193
+ "required": ["url"]
194
+ }
195
+ ),
196
+ Tool(
197
+ name="http_raw",
198
+ description="""Send raw HTTP request. Supports pasting request format directly from Burp Suite or other capture tools.
199
+
200
+ Raw request format example:
201
+ POST /api/login HTTP/1.1
202
+ Host: example.com
203
+ Content-Type: application/json
204
+
205
+ {"username":"admin","password":"123"}""",
206
+ inputSchema={
207
+ "type": "object",
208
+ "properties": {
209
+ "raw_request": {
210
+ "type": "string",
211
+ "description": "Raw HTTP request text (including request line, headers, blank line, body)"
212
+ },
213
+ "base_url": {
214
+ "type": "string",
215
+ "description": "Base URL (if raw_request doesn't contain full URL), e.g.: https://example.com"
216
+ },
217
+ "verify_ssl": {
218
+ "type": "boolean",
219
+ "description": "Whether to verify SSL certificate",
220
+ "default": True
221
+ }
222
+ },
223
+ "required": ["raw_request"]
224
+ }
225
+ )
226
+ ]
227
+
228
+
229
+ @server.call_tool()
230
+ async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]:
231
+ """Execute MCP tool call"""
232
+ try:
233
+ if name == "http_request":
234
+ return await handle_http_request(arguments)
235
+ elif name == "http_raw":
236
+ return await handle_http_raw(arguments)
237
+ else:
238
+ return [TextContent(type="text", text=f"Unknown tool: {name}")]
239
+ except Exception as e:
240
+ return [TextContent(type="text", text=f"Error: {type(e).__name__}: {str(e)}")]
241
+
242
+
243
+ async def handle_http_request(args: dict[str, Any]) -> list[TextContent]:
244
+ """Handle general HTTP request"""
245
+ method = args.get("method", "GET").upper()
246
+ url = args["url"]
247
+ params = parse_params(args.get("params"))
248
+ headers = parse_headers(args.get("headers"))
249
+ body = args.get("body")
250
+ content_type = args.get("content_type", "application/json")
251
+ timeout = args.get("timeout", 30)
252
+ follow_redirects = args.get("follow_redirects", True)
253
+ verify_ssl = args.get("verify_ssl", True)
254
+ include_headers = args.get("include_headers", True)
255
+
256
+ # Set Content-Type
257
+ if body and "content-type" not in {k.lower() for k in headers}:
258
+ headers["Content-Type"] = content_type
259
+
260
+ async with httpx.AsyncClient(
261
+ timeout=timeout,
262
+ follow_redirects=follow_redirects,
263
+ verify=verify_ssl
264
+ ) as client:
265
+ response = await client.request(
266
+ method=method,
267
+ url=url,
268
+ params=params,
269
+ headers=headers,
270
+ content=body.encode() if body else None
271
+ )
272
+
273
+ result = format_response(response, include_headers)
274
+ return [TextContent(type="text", text=result)]
275
+
276
+
277
+ def parse_raw_request(raw: str, base_url: str | None = None) -> tuple[str, str, dict, str | None]:
278
+ """Parse raw HTTP request text"""
279
+ lines = raw.strip().replace("\r\n", "\n").split("\n")
280
+
281
+ # Parse request line
282
+ request_line = lines[0]
283
+ parts = request_line.split()
284
+ method = parts[0].upper()
285
+ path = parts[1] if len(parts) > 1 else "/"
286
+
287
+ # Parse request headers
288
+ headers = {}
289
+ body_start = len(lines)
290
+
291
+ for i, line in enumerate(lines[1:], 1):
292
+ if line.strip() == "":
293
+ body_start = i + 1
294
+ break
295
+ if ":" in line:
296
+ key, value = line.split(":", 1)
297
+ headers[key.strip()] = value.strip()
298
+
299
+ # Parse request body
300
+ body = None
301
+ if body_start < len(lines):
302
+ body = "\n".join(lines[body_start:])
303
+
304
+ # Build full URL
305
+ if path.startswith("http://") or path.startswith("https://"):
306
+ url = path
307
+ else:
308
+ host = headers.get("Host", "")
309
+ if base_url:
310
+ url = base_url.rstrip("/") + path
311
+ elif host:
312
+ # Determine protocol based on SSL-related headers
313
+ protocol = "https" if "443" in host else "http"
314
+ url = f"{protocol}://{host}{path}"
315
+ else:
316
+ url = path
317
+
318
+ return method, url, headers, body
319
+
320
+
321
+ async def handle_http_raw(args: dict[str, Any]) -> list[TextContent]:
322
+ """Handle raw HTTP request"""
323
+ raw_request = args["raw_request"]
324
+ base_url = args.get("base_url")
325
+ verify_ssl = args.get("verify_ssl", True)
326
+
327
+ method, url, headers, body = parse_raw_request(raw_request, base_url)
328
+
329
+ async with httpx.AsyncClient(
330
+ timeout=30,
331
+ follow_redirects=True,
332
+ verify=verify_ssl
333
+ ) as client:
334
+ response = await client.request(
335
+ method=method,
336
+ url=url,
337
+ headers=headers,
338
+ content=body.encode() if body else None
339
+ )
340
+
341
+ result = format_response(response)
342
+ return [TextContent(type="text", text=result)]
343
+
344
+
345
+ async def run_server():
346
+ """Run MCP server"""
347
+ async with stdio_server() as (read_stream, write_stream):
348
+ await server.run(
349
+ read_stream,
350
+ write_stream,
351
+ server.create_initialization_options()
352
+ )
353
+
354
+
355
+ def main():
356
+ """Main entry point"""
357
+ import asyncio
358
+ asyncio.run(run_server())
359
+
360
+
361
+ if __name__ == "__main__":
362
+ main()
@@ -0,0 +1,23 @@
1
+ [project]
2
+ name = "httpx-mcp"
3
+ version = "1.0.0"
4
+ description = "A MCP tool for HTTP request testing using httpx"
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ dependencies = [
8
+ "mcp>=1.0.0",
9
+ "httpx>=0.27.0",
10
+ ]
11
+ authors = [
12
+ {name = "ZHEFOX", email = "zhefox@outlook.com"},
13
+ ]
14
+
15
+ [project.scripts]
16
+ httpx-mcp = "httpx_mcp.server:main"
17
+
18
+ [build-system]
19
+ requires = ["hatchling"]
20
+ build-backend = "hatchling.build"
21
+
22
+ [tool.hatch.build.targets.wheel]
23
+ packages = ["httpx_mcp"]