AI-RVC / mcp /server.py
mason369's picture
Release v1.2.1
a9536c4 verified
# -*- coding: utf-8 -*-
"""
MCP 服务器 - 为 Claude Code 提供 AI 翻唱工具
"""
import asyncio
import json
from pathlib import Path
from typing import Any
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
from mcp.tools import (
list_models,
convert_voice,
download_model,
get_model_status
)
# 创建 MCP 服务器
server = Server("rvc-voice-conversion")
@server.list_tools()
async def list_tools() -> list[Tool]:
"""列出可用工具"""
return [
Tool(
name="list_voice_models",
description="列出所有可用的 RVC 语音模型",
inputSchema={
"type": "object",
"properties": {},
"required": []
}
),
Tool(
name="convert_voice",
description="使用 RVC 模型进行 AI 翻唱",
inputSchema={
"type": "object",
"properties": {
"input_path": {
"type": "string",
"description": "输入音频文件的绝对路径"
},
"output_path": {
"type": "string",
"description": "输出音频文件的绝对路径"
},
"model_name": {
"type": "string",
"description": "要使用的语音模型名称"
},
"pitch_shift": {
"type": "number",
"description": "音调偏移 (半音),正数升调,负数降调",
"default": 0
},
"index_ratio": {
"type": "number",
"description": "索引混合比率 (0-1)",
"default": 0.5
}
},
"required": ["input_path", "output_path", "model_name"]
}
),
Tool(
name="download_base_models",
description="下载 RVC 所需的基础模型 (HuBERT, RMVPE)",
inputSchema={
"type": "object",
"properties": {},
"required": []
}
),
Tool(
name="get_model_status",
description="获取基础模型的下载状态",
inputSchema={
"type": "object",
"properties": {},
"required": []
}
)
]
@server.call_tool()
async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]:
"""执行工具调用"""
if name == "list_voice_models":
models = list_models()
result = {
"models": models,
"count": len(models)
}
return [TextContent(type="text", text=json.dumps(result, ensure_ascii=False, indent=2))]
elif name == "convert_voice":
result = convert_voice(
input_path=arguments["input_path"],
output_path=arguments["output_path"],
model_name=arguments["model_name"],
pitch_shift=arguments.get("pitch_shift", 0),
index_ratio=arguments.get("index_ratio", 0.5),
filter_radius=arguments.get("filter_radius", 3),
rms_mix_rate=arguments.get("rms_mix_rate", 0.25),
protect=arguments.get("protect", 0.33)
)
return [TextContent(type="text", text=json.dumps(result, ensure_ascii=False, indent=2))]
elif name == "download_base_models":
result = download_model()
return [TextContent(type="text", text=json.dumps(result, ensure_ascii=False, indent=2))]
elif name == "get_model_status":
status = get_model_status()
return [TextContent(type="text", text=json.dumps(status, ensure_ascii=False, indent=2))]
else:
return [TextContent(type="text", text=f"未知工具: {name}")]
async def main():
"""启动 MCP 服务器"""
async with stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
server.create_initialization_options()
)
if __name__ == "__main__":
asyncio.run(main())