http-mcp-client-server 0.1.0__py3-none-any.whl
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.
- http_mcp_client/__init__.py +4 -0
- http_mcp_client/server.py +356 -0
- http_mcp_client_server-0.1.0.dist-info/METADATA +272 -0
- http_mcp_client_server-0.1.0.dist-info/RECORD +7 -0
- http_mcp_client_server-0.1.0.dist-info/WHEEL +4 -0
- http_mcp_client_server-0.1.0.dist-info/entry_points.txt +2 -0
- http_mcp_client_server-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""
|
|
3
|
+
HTTP MCP Server - 提供视频增强功能的 MCP 服务
|
|
4
|
+
|
|
5
|
+
通过 MCP 协议暴露 tools,内部调用 FastAPI HTTP Server。
|
|
6
|
+
支持 URL 上传和本地文件上传(base64)。
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import argparse
|
|
10
|
+
import asyncio
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Any
|
|
15
|
+
|
|
16
|
+
import httpx
|
|
17
|
+
from mcp.server import Server
|
|
18
|
+
from mcp.server.stdio import stdio_server
|
|
19
|
+
from mcp.types import TextContent, Tool
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class VideoEnhancementMCPServer:
|
|
23
|
+
"""MCP Server for video enhancement"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, base_url: str, api_key: str):
|
|
26
|
+
self.base_url = base_url.rstrip("/")
|
|
27
|
+
self.api_key = api_key
|
|
28
|
+
self.server = Server("video-enhancement")
|
|
29
|
+
|
|
30
|
+
# 注册 tools
|
|
31
|
+
self.server.list_tools()(self.list_tools)
|
|
32
|
+
self.server.call_tool()(self.call_tool)
|
|
33
|
+
|
|
34
|
+
# HTTP 客户端
|
|
35
|
+
self._client = httpx.AsyncClient(
|
|
36
|
+
base_url=self.base_url,
|
|
37
|
+
headers={
|
|
38
|
+
"Authorization": f"Bearer {api_key}",
|
|
39
|
+
"Content-Type": "application/json",
|
|
40
|
+
},
|
|
41
|
+
timeout=60.0,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
async def list_tools(self) -> list[Tool]:
|
|
45
|
+
"""列出所有可用的 tools"""
|
|
46
|
+
return [
|
|
47
|
+
Tool(
|
|
48
|
+
name="create_task",
|
|
49
|
+
description="""创建视频增强任务(异步)
|
|
50
|
+
|
|
51
|
+
支持两种上传方式:
|
|
52
|
+
1. URL 上传:提供视频 URL
|
|
53
|
+
2. 本地上传:提供本地文件路径,MCP Server 自动读取并转为 base64
|
|
54
|
+
|
|
55
|
+
参数说明:
|
|
56
|
+
- video_source: 视频 URL 或本地文件路径
|
|
57
|
+
- type: "url" 或 "local"
|
|
58
|
+
- resolution: 目标分辨率
|
|
59
|
+
""",
|
|
60
|
+
inputSchema={
|
|
61
|
+
"type": "object",
|
|
62
|
+
"properties": {
|
|
63
|
+
"video_source": {
|
|
64
|
+
"type": "string",
|
|
65
|
+
"description": "视频URL地址或本地文件路径",
|
|
66
|
+
},
|
|
67
|
+
"type": {
|
|
68
|
+
"type": "string",
|
|
69
|
+
"enum": ["url", "local"],
|
|
70
|
+
"default": "url",
|
|
71
|
+
"description": "上传类型:url=网络视频,local=本地文件",
|
|
72
|
+
},
|
|
73
|
+
"resolution": {
|
|
74
|
+
"type": "string",
|
|
75
|
+
"enum": ["480p", "540p", "720p", "1080p", "2k"],
|
|
76
|
+
"default": "720p",
|
|
77
|
+
"description": "目标分辨率,默认720p",
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
"required": ["video_source"],
|
|
81
|
+
},
|
|
82
|
+
),
|
|
83
|
+
Tool(
|
|
84
|
+
name="get_task_status",
|
|
85
|
+
description="查询视频增强任务状态",
|
|
86
|
+
inputSchema={
|
|
87
|
+
"type": "object",
|
|
88
|
+
"properties": {
|
|
89
|
+
"task_id": {
|
|
90
|
+
"type": "string",
|
|
91
|
+
"description": "任务ID",
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
"required": ["task_id"],
|
|
95
|
+
},
|
|
96
|
+
),
|
|
97
|
+
Tool(
|
|
98
|
+
name="enhance_video_sync",
|
|
99
|
+
description="""同步增强视频(阻塞等待完成)
|
|
100
|
+
|
|
101
|
+
支持两种上传方式:
|
|
102
|
+
1. URL 上传:提供视频 URL
|
|
103
|
+
2. 本地上传:提供本地文件路径,MCP Server 自动读取并转为 base64
|
|
104
|
+
|
|
105
|
+
参数说明:
|
|
106
|
+
- video_source: 视频 URL 或本地文件路径
|
|
107
|
+
- type: "url" 或 "local"
|
|
108
|
+
- resolution: 目标分辨率
|
|
109
|
+
- poll_interval: 轮询间隔(秒)
|
|
110
|
+
- timeout: 超时时间(秒)
|
|
111
|
+
""",
|
|
112
|
+
inputSchema={
|
|
113
|
+
"type": "object",
|
|
114
|
+
"properties": {
|
|
115
|
+
"video_source": {
|
|
116
|
+
"type": "string",
|
|
117
|
+
"description": "视频URL地址或本地文件路径",
|
|
118
|
+
},
|
|
119
|
+
"type": {
|
|
120
|
+
"type": "string",
|
|
121
|
+
"enum": ["url", "local"],
|
|
122
|
+
"default": "url",
|
|
123
|
+
"description": "上传类型:url=网络视频,local=本地文件",
|
|
124
|
+
},
|
|
125
|
+
"resolution": {
|
|
126
|
+
"type": "string",
|
|
127
|
+
"enum": ["480p", "540p", "720p", "1080p", "2k"],
|
|
128
|
+
"default": "720p",
|
|
129
|
+
"description": "目标分辨率,默认720p",
|
|
130
|
+
},
|
|
131
|
+
"poll_interval": {
|
|
132
|
+
"type": "number",
|
|
133
|
+
"default": 5,
|
|
134
|
+
"description": "轮询间隔(秒),默认5",
|
|
135
|
+
},
|
|
136
|
+
"timeout": {
|
|
137
|
+
"type": "number",
|
|
138
|
+
"default": 600,
|
|
139
|
+
"description": "超时时间(秒),默认600",
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
"required": ["video_source"],
|
|
143
|
+
},
|
|
144
|
+
),
|
|
145
|
+
]
|
|
146
|
+
|
|
147
|
+
async def call_tool(self, name: str, arguments: dict[str, Any]) -> list[TextContent]:
|
|
148
|
+
"""调用 tool"""
|
|
149
|
+
try:
|
|
150
|
+
if name == "create_task":
|
|
151
|
+
result = await self._create_task(
|
|
152
|
+
video_source=arguments["video_source"],
|
|
153
|
+
source_type=arguments.get("type", "url"),
|
|
154
|
+
resolution=arguments.get("resolution", "720p"),
|
|
155
|
+
)
|
|
156
|
+
elif name == "get_task_status":
|
|
157
|
+
result = await self._get_task_status(
|
|
158
|
+
task_id=arguments["task_id"],
|
|
159
|
+
)
|
|
160
|
+
elif name == "enhance_video_sync":
|
|
161
|
+
result = await self._enhance_video_sync(
|
|
162
|
+
video_source=arguments["video_source"],
|
|
163
|
+
source_type=arguments.get("type", "url"),
|
|
164
|
+
resolution=arguments.get("resolution", "720p"),
|
|
165
|
+
poll_interval=arguments.get("poll_interval", 5),
|
|
166
|
+
timeout=arguments.get("timeout", 600),
|
|
167
|
+
)
|
|
168
|
+
else:
|
|
169
|
+
result = {"success": False, "error": f"未知工具: {name}"}
|
|
170
|
+
|
|
171
|
+
return [TextContent(type="text", text=json.dumps(result, ensure_ascii=False, indent=2))]
|
|
172
|
+
|
|
173
|
+
except Exception as e:
|
|
174
|
+
return [
|
|
175
|
+
TextContent(
|
|
176
|
+
type="text", text=json.dumps({"success": False, "error": str(e)}, ensure_ascii=False, indent=2)
|
|
177
|
+
)
|
|
178
|
+
]
|
|
179
|
+
|
|
180
|
+
def _read_local_file(self, file_path: str) -> tuple[str, str]:
|
|
181
|
+
"""
|
|
182
|
+
读取本地文件并转为 base64
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
file_path: 本地文件路径
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
(base64_data, file_name)
|
|
189
|
+
"""
|
|
190
|
+
import base64
|
|
191
|
+
|
|
192
|
+
path = Path(file_path)
|
|
193
|
+
if not path.exists():
|
|
194
|
+
raise FileNotFoundError(f"文件不存在: {file_path}")
|
|
195
|
+
|
|
196
|
+
# 检查文件大小(最大 100MB)
|
|
197
|
+
max_size = 100 * 1024 * 1024
|
|
198
|
+
file_size = path.stat().st_size
|
|
199
|
+
if file_size > max_size:
|
|
200
|
+
raise ValueError("文件大小超过 100MB 限制")
|
|
201
|
+
|
|
202
|
+
# 读取并编码
|
|
203
|
+
with open(path, "rb") as f:
|
|
204
|
+
file_data = f.read()
|
|
205
|
+
|
|
206
|
+
base64_data = base64.b64encode(file_data).decode("utf-8")
|
|
207
|
+
return base64_data, path.name
|
|
208
|
+
|
|
209
|
+
async def _create_task(self, video_source: str, source_type: str, resolution: str) -> dict:
|
|
210
|
+
"""创建任务"""
|
|
211
|
+
# 根据类型构建请求
|
|
212
|
+
if source_type == "local":
|
|
213
|
+
# 本地上传:读取文件转 base64
|
|
214
|
+
file_data, file_name = self._read_local_file(video_source)
|
|
215
|
+
content_item = {
|
|
216
|
+
"type": "video_file",
|
|
217
|
+
"file_data": file_data,
|
|
218
|
+
"file_name": file_name,
|
|
219
|
+
}
|
|
220
|
+
else:
|
|
221
|
+
# URL 上传
|
|
222
|
+
content_item = {
|
|
223
|
+
"type": "video_url",
|
|
224
|
+
"video_url": {"url": video_source},
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
payload = {
|
|
228
|
+
"model": "avc-enhance",
|
|
229
|
+
"content": [content_item],
|
|
230
|
+
"resolution": resolution,
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
response = await self._client.post(
|
|
234
|
+
"/api/v3/contents/generations/tasks",
|
|
235
|
+
json=payload,
|
|
236
|
+
)
|
|
237
|
+
response.raise_for_status()
|
|
238
|
+
|
|
239
|
+
data = response.json()
|
|
240
|
+
if data.get("code", 0) != 0:
|
|
241
|
+
return {"success": False, "error": data.get("message", "Unknown error")}
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
"success": True,
|
|
245
|
+
"task_id": data["data"]["task_id"],
|
|
246
|
+
"status": data["data"]["status"],
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
async def _get_task_status(self, task_id: str) -> dict:
|
|
250
|
+
"""查询任务状态"""
|
|
251
|
+
response = await self._client.get(
|
|
252
|
+
f"/api/v3/contents/generations/tasks/{task_id}",
|
|
253
|
+
)
|
|
254
|
+
response.raise_for_status()
|
|
255
|
+
|
|
256
|
+
data = response.json()
|
|
257
|
+
if data.get("code", 0) != 0:
|
|
258
|
+
return {"success": False, "error": data.get("message", "Unknown error")}
|
|
259
|
+
|
|
260
|
+
result = data["data"]
|
|
261
|
+
return {
|
|
262
|
+
"success": True,
|
|
263
|
+
"task_id": result["task_id"],
|
|
264
|
+
"status": result["status"],
|
|
265
|
+
"progress": result.get("progress", 0),
|
|
266
|
+
"video_url": result.get("video_url"),
|
|
267
|
+
"error_message": result.get("error_message"),
|
|
268
|
+
"created_at": result.get("created_at"),
|
|
269
|
+
"updated_at": result.get("updated_at"),
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
async def _enhance_video_sync(
|
|
273
|
+
self,
|
|
274
|
+
video_source: str,
|
|
275
|
+
source_type: str,
|
|
276
|
+
resolution: str,
|
|
277
|
+
poll_interval: int,
|
|
278
|
+
timeout: int,
|
|
279
|
+
) -> dict:
|
|
280
|
+
"""同步增强视频"""
|
|
281
|
+
# 创建任务
|
|
282
|
+
create_result = await self._create_task(video_source, source_type, resolution)
|
|
283
|
+
if not create_result["success"]:
|
|
284
|
+
return create_result
|
|
285
|
+
|
|
286
|
+
task_id = create_result["task_id"]
|
|
287
|
+
|
|
288
|
+
# 轮询等待完成
|
|
289
|
+
start_time = asyncio.get_event_loop().time()
|
|
290
|
+
while True:
|
|
291
|
+
status = await self._get_task_status(task_id)
|
|
292
|
+
if not status["success"]:
|
|
293
|
+
return status
|
|
294
|
+
|
|
295
|
+
if status["status"] in ("completed", "failed"):
|
|
296
|
+
return status
|
|
297
|
+
|
|
298
|
+
elapsed = asyncio.get_event_loop().time() - start_time
|
|
299
|
+
if elapsed >= timeout:
|
|
300
|
+
return {
|
|
301
|
+
"success": False,
|
|
302
|
+
"error": f"任务超时: {task_id}",
|
|
303
|
+
"task_id": task_id,
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
await asyncio.sleep(poll_interval)
|
|
307
|
+
|
|
308
|
+
async def run(self):
|
|
309
|
+
"""运行 MCP Server (stdio mode)"""
|
|
310
|
+
async with stdio_server() as (read_stream, write_stream):
|
|
311
|
+
await self.server.run(
|
|
312
|
+
read_stream,
|
|
313
|
+
write_stream,
|
|
314
|
+
self.server.create_initialization_options(),
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
async def close(self):
|
|
318
|
+
"""关闭客户端"""
|
|
319
|
+
await self._client.aclose()
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def main():
|
|
323
|
+
"""主入口"""
|
|
324
|
+
parser = argparse.ArgumentParser(description="HTTP MCP Server for video enhancement")
|
|
325
|
+
parser.add_argument(
|
|
326
|
+
"--base-url",
|
|
327
|
+
default=os.getenv("HTTP_API_BASE_URL", "http://localhost:8000"),
|
|
328
|
+
help="FastAPI HTTP Server base URL",
|
|
329
|
+
)
|
|
330
|
+
parser.add_argument(
|
|
331
|
+
"--api-key",
|
|
332
|
+
default=os.getenv("HTTP_API_KEY", ""),
|
|
333
|
+
help="API key for authentication",
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
args = parser.parse_args()
|
|
337
|
+
|
|
338
|
+
if not args.api_key:
|
|
339
|
+
print("错误: 需要提供 --api-key 或设置 HTTP_API_KEY 环境变量", flush=True)
|
|
340
|
+
exit(1)
|
|
341
|
+
|
|
342
|
+
server = VideoEnhancementMCPServer(
|
|
343
|
+
base_url=args.base_url,
|
|
344
|
+
api_key=args.api_key,
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
try:
|
|
348
|
+
asyncio.run(server.run())
|
|
349
|
+
except KeyboardInterrupt:
|
|
350
|
+
print("\n服务已停止", flush=True)
|
|
351
|
+
finally:
|
|
352
|
+
asyncio.run(server.close())
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
if __name__ == "__main__":
|
|
356
|
+
main()
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: http-mcp-client-server
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: HTTP MCP Client-Server for video enhancement API
|
|
5
|
+
Project-URL: Homepage, https://github.com/yourusername/http-mcp-client-server
|
|
6
|
+
Project-URL: Repository, https://github.com/yourusername/http-mcp-client-server
|
|
7
|
+
Project-URL: Issues, https://github.com/yourusername/http-mcp-client-server/issues
|
|
8
|
+
Author-email: Your Name <your.email@example.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: client,enhancement,fastapi,http,mcp,server,video
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Multimedia :: Video
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: httpx>=0.27.0
|
|
23
|
+
Requires-Dist: mcp>=1.0.0
|
|
24
|
+
Requires-Dist: pydantic>=2.0.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: build>=1.0.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff>=0.6.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: twine>=5.0.0; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# http-mcp-client-server (Python)
|
|
34
|
+
|
|
35
|
+
[](https://pypi.org/project/http-mcp-client-server/)
|
|
36
|
+
[](https://www.python.org/downloads/)
|
|
37
|
+
[](https://opensource.org/licenses/MIT)
|
|
38
|
+
|
|
39
|
+
基于 MCP 协议的视频增强服务,作为 MCP Client-Server 与 FastAPI HTTP Server 交互。
|
|
40
|
+
|
|
41
|
+
## 功能
|
|
42
|
+
|
|
43
|
+
提供以下 MCP Tools:
|
|
44
|
+
- `create_task` - 创建视频增强任务(支持 URL 或本地文件上传)
|
|
45
|
+
- `get_task_status` - 查询任务状态
|
|
46
|
+
- `enhance_video_sync` - 同步增强视频(阻塞等待)
|
|
47
|
+
|
|
48
|
+
## 安装
|
|
49
|
+
|
|
50
|
+
### 从 PyPI 安装(推荐)
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# 使用 pip 安装
|
|
54
|
+
pip install http-mcp-client-server
|
|
55
|
+
|
|
56
|
+
# 或使用 uv 安装
|
|
57
|
+
uv pip install http-mcp-client-server
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 从源码安装
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
git clone https://github.com/yourusername/http-mcp-client-server.git
|
|
64
|
+
cd python_client
|
|
65
|
+
|
|
66
|
+
# 使用 uv 安装(推荐)
|
|
67
|
+
uv pip install -e ".[dev]"
|
|
68
|
+
|
|
69
|
+
# 或使用 pip 安装
|
|
70
|
+
pip install -e ".[dev]"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## 使用方法
|
|
74
|
+
|
|
75
|
+
### 1. 命令行启动
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# 直接运行(安装后)
|
|
79
|
+
http-mcp-client-server --base-url http://localhost:8000 --api-key your-api-key
|
|
80
|
+
|
|
81
|
+
# 或使用环境变量
|
|
82
|
+
export HTTP_API_BASE_URL=http://localhost:8000
|
|
83
|
+
export HTTP_API_KEY=your-api-key
|
|
84
|
+
http-mcp-client-server
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 2. 在 Claude Desktop 中配置
|
|
88
|
+
|
|
89
|
+
编辑 Claude Desktop 配置文件:
|
|
90
|
+
|
|
91
|
+
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
92
|
+
|
|
93
|
+
**Windows**: `%APPDATA%/Claude/claude_desktop_config.json`
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"mcpServers": {
|
|
98
|
+
"video-enhancement": {
|
|
99
|
+
"command": "http-mcp-client-server",
|
|
100
|
+
"args": [
|
|
101
|
+
"--base-url",
|
|
102
|
+
"http://localhost:8000",
|
|
103
|
+
"--api-key",
|
|
104
|
+
"your-api-key"
|
|
105
|
+
]
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 3. 使用 uv run 运行(开发模式)
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
uv run http-mcp-client-server --base-url http://localhost:8000 --api-key your-api-key
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## 提供的 Tools
|
|
118
|
+
|
|
119
|
+
### create_task
|
|
120
|
+
|
|
121
|
+
创建视频增强任务(异步)。
|
|
122
|
+
|
|
123
|
+
**参数:**
|
|
124
|
+
- `video_source` (string, required): 视频 URL 或本地文件路径
|
|
125
|
+
- `type` (string, optional): 上传类型,默认 "url"
|
|
126
|
+
- 可选值: `"url"` - 网络视频URL, `"local"` - 本地文件路径
|
|
127
|
+
- `resolution` (string, optional): 目标分辨率,默认 720p
|
|
128
|
+
- 可选值: 480p, 540p, 720p, 1080p, 2k
|
|
129
|
+
|
|
130
|
+
**使用示例:**
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
# URL 方式
|
|
134
|
+
{
|
|
135
|
+
"video_source": "https://example.com/video.mp4",
|
|
136
|
+
"type": "url",
|
|
137
|
+
"resolution": "1080p"
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
# 本地文件方式
|
|
141
|
+
{
|
|
142
|
+
"video_source": "/path/to/local/video.mp4",
|
|
143
|
+
"type": "local",
|
|
144
|
+
"resolution": "1080p"
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**返回值:**
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"success": true,
|
|
152
|
+
"task_id": "xxx",
|
|
153
|
+
"status": "wait"
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### get_task_status
|
|
158
|
+
|
|
159
|
+
查询任务状态。
|
|
160
|
+
|
|
161
|
+
**参数:**
|
|
162
|
+
- `task_id` (string, required): 任务ID
|
|
163
|
+
|
|
164
|
+
**使用示例:**
|
|
165
|
+
```python
|
|
166
|
+
{
|
|
167
|
+
"task_id": "task-123-abc"
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**返回值:**
|
|
172
|
+
```json
|
|
173
|
+
{
|
|
174
|
+
"success": true,
|
|
175
|
+
"task_id": "xxx",
|
|
176
|
+
"status": "completed",
|
|
177
|
+
"progress": 100,
|
|
178
|
+
"video_url": "https://...",
|
|
179
|
+
"error_message": null,
|
|
180
|
+
"created_at": "2024-01-01T00:00:00Z",
|
|
181
|
+
"updated_at": "2024-01-01T00:01:00Z"
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### enhance_video_sync
|
|
186
|
+
|
|
187
|
+
同步增强视频(阻塞等待完成)。
|
|
188
|
+
|
|
189
|
+
**参数:**
|
|
190
|
+
- `video_source` (string, required): 视频 URL 或本地文件路径
|
|
191
|
+
- `type` (string, optional): 上传类型,默认 "url"
|
|
192
|
+
- 可选值: `"url"` - 网络视频URL, `"local"` - 本地文件路径
|
|
193
|
+
- `resolution` (string, optional): 目标分辨率,默认 720p
|
|
194
|
+
- `poll_interval` (number, optional): 轮询间隔(秒),默认 5
|
|
195
|
+
- `timeout` (number, optional): 超时时间(秒),默认 600
|
|
196
|
+
|
|
197
|
+
**使用示例:**
|
|
198
|
+
```python
|
|
199
|
+
{
|
|
200
|
+
"video_source": "https://example.com/video.mp4",
|
|
201
|
+
"type": "url",
|
|
202
|
+
"resolution": "1080p",
|
|
203
|
+
"poll_interval": 5,
|
|
204
|
+
"timeout": 600
|
|
205
|
+
}
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**返回值:**
|
|
209
|
+
```json
|
|
210
|
+
{
|
|
211
|
+
"success": true,
|
|
212
|
+
"task_id": "xxx",
|
|
213
|
+
"status": "completed",
|
|
214
|
+
"progress": 100,
|
|
215
|
+
"video_url": "https://..."
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## 文件上传说明
|
|
220
|
+
|
|
221
|
+
当 `type` 设置为 `"local"` 时,MCP Server 会:
|
|
222
|
+
1. 读取本地文件
|
|
223
|
+
2. 将文件转为 base64 编码
|
|
224
|
+
3. 上传到视频增强服务
|
|
225
|
+
|
|
226
|
+
**限制:**
|
|
227
|
+
- 最大文件大小:100MB
|
|
228
|
+
|
|
229
|
+
## 环境变量
|
|
230
|
+
|
|
231
|
+
| 变量名 | 说明 | 默认值 |
|
|
232
|
+
|--------|------|--------|
|
|
233
|
+
| `HTTP_API_BASE_URL` | FastAPI HTTP Server 地址 | `http://localhost:8000` |
|
|
234
|
+
| `HTTP_API_KEY` | API 认证密钥 | 无 |
|
|
235
|
+
|
|
236
|
+
## 开发
|
|
237
|
+
|
|
238
|
+
```bash
|
|
239
|
+
# 克隆仓库
|
|
240
|
+
git clone https://github.com/yourusername/http-mcp-client-server.git
|
|
241
|
+
cd python_client
|
|
242
|
+
|
|
243
|
+
# 安装开发依赖
|
|
244
|
+
uv pip install -e ".[dev]"
|
|
245
|
+
|
|
246
|
+
# 运行测试
|
|
247
|
+
pytest
|
|
248
|
+
|
|
249
|
+
# 代码格式化
|
|
250
|
+
ruff format .
|
|
251
|
+
ruff check --fix .
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## 发布到 PyPI
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
# 安装构建工具
|
|
258
|
+
uv pip install build twine
|
|
259
|
+
|
|
260
|
+
# 构建分发包
|
|
261
|
+
python -m build
|
|
262
|
+
|
|
263
|
+
# 上传到 PyPI(测试)
|
|
264
|
+
python -m twine upload --repository testpypi dist/*
|
|
265
|
+
|
|
266
|
+
# 上传到 PyPI(正式)
|
|
267
|
+
python -m twine upload dist/*
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## License
|
|
271
|
+
|
|
272
|
+
MIT License - 详见 [LICENSE](LICENSE) 文件
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
http_mcp_client/__init__.py,sha256=K7O3bmQwEKwkYvMsIwxLexqH4Kz2TzpsWTrGeSj8dkE,105
|
|
2
|
+
http_mcp_client/server.py,sha256=J8f98ldu_EcfYcxadOcnwm_1oRloQB27Jyy7qDBB4vU,11916
|
|
3
|
+
http_mcp_client_server-0.1.0.dist-info/METADATA,sha256=X6Y0BeiHXZrSNwdms0k2rUBXK6rNttCWf910GCsG3P0,6298
|
|
4
|
+
http_mcp_client_server-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
|
|
5
|
+
http_mcp_client_server-0.1.0.dist-info/entry_points.txt,sha256=gnHpFJTKA7FGjMB1MqRALn6iD87wA7LO3Cv9dS0MIhw,71
|
|
6
|
+
http_mcp_client_server-0.1.0.dist-info/licenses/LICENSE,sha256=QvyDolqEVJoMgCxrNb823xH5hJDH0ifntw7vzN-VGD4,1079
|
|
7
|
+
http_mcp_client_server-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 http-mcp-client-server
|
|
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.
|