Token导航 LogoToken导航

MCP Server · AI代理

cfr MCP server

一个基于Python的MCP服务器实现,封装了cfr.jar反编译功能,支持SSE传输协议,用于反编译Java类或JAR文件。

stdio官方级别未说明来源级核验工具 0
开发工具PythonClaudeSSE传输Claude DesktopCursor

快速开始

作者 / 组织
Mr-xn
提供方
Mr-xn

工具数量

0

来源目录标注

资源数量

0

来源目录标注

提示词数量

0

来源目录标注

GitHub Star

3

仓库热度

收录来源

1 个

MCP World

选型结论

cfr MCP server 属于AI代理类 MCP Server,公开资料标注 0 个工具,通过stdio 本地进程接入,适配 Claude Desktop、Claude、Cursor,有可以直接复制的安装命令;接入前要先准备 访问 Token。

分类

AI代理

传输方式

stdio

认证方式

访问 Token

部署方式

公开资料未说明

安装与配置

安装命令

pip install mcp starlette uvicorn

公开命令不是通用的启动方式,拼不出可靠配置示例;请在客户端 MCP 配置里按官方文档填写 command 和 args。

上手步骤

  1. 1

    准备运行环境

    stdio 服务在本地起进程,需要先装好 对应的运行时,再按安装命令拉取依赖。

  2. 2

    安装服务

    复制下面的安装命令执行;命令里带占位符的位置换成自己的密钥或路径。

  3. 3

    写入客户端配置

    在客户端的 MCP 配置里填启动命令和参数,保存后完全退出客户端再打开,让新配置生效。

  4. 4

    验证是否可用

    连接成功后客户端会列出 0 个工具,随便调一个只读工具确认能返回结果。

接入前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

详细介绍

前言

这是一个基于 Python 的 MCP (Model Context Protocol) 服务器实现,封装了 cfr.jar 反编译功能,并支持 SSE (Server-Sent Events) 传输协议。

正文

1. 环境准备

确保当前目录下有 cfr.jar。

安装 Python 依赖:

pip install mcp starlette uvicorn

2. 服务器代码 (cfr_mcp_server.py)

该脚本封装了 cfr.jar,提供了一个名为 decompile 的工具。

需要注意修改 CFR_JAR_PATH (cfr.jar 文件路径)
import os
import re
import asyncio
import logging
import subprocess
import uvicorn
from pathlib import Path
from functools import partial
from starlette.applications import Starlette
from starlette.routing import Route, Mount
from starlette.responses import Response
from mcp.server import Server
from mcp.server.sse import SseServerTransport
import mcp.types as types

# --- Configuration (配置) ---
# Path to the CFR jar file
# CFR jar 文件路径
CFR_JAR_PATH = "/path/to/cfr.jar"

# Server Host and Port
# 服务器主机和端口
HOST = "0.0.0.0"
PORT = 8000

# Command execution timeout in seconds
# 命令执行超时时间(秒)
CMD_TIMEOUT_SECONDS = 30 

# --- Logging (日志) ---
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("cfr_server")

# --- Server Instance (服务器实例) ---
server = Server("cfr-decompiler")

def validate_option_key(key: str) -> bool:
    """
    Allow only alphanumeric keys to prevent injection.
    仅允许字母数字键名以防止注入。
    """
    return bool(re.match(r'^[a-zA-Z0-9]+$', key))

def run_cfr_sync(cmd: list) -> str:
    """
    Sync execution wrapper for thread pool.
    用于线程池的同步执行包装器。
    """
    try:
        logger.info(f"Exec: {' '.join(cmd)}")
        process = subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            check=False,
            timeout=CMD_TIMEOUT_SECONDS
        )
        
        output = process.stdout
        if process.stderr and len(process.stderr.strip()) > 0:
            # Append stderr output as comments
            # 将错误输出作为注释附加
            output += f"\n\n/*\n[CFR STDERR]\n{process.stderr}\n*/"
            
        return output
    except subprocess.TimeoutExpired:
        return "/* Error: Decompilation timed out. File might be too complex or large. (反编译超时,文件可能过大或过于复杂) */"
    except Exception as e:
        return f"/* Error executing CFR (执行 CFR 出错): {str(e)} */"

@server.list_tools()
async def list_tools() -> list[types.Tool]:
    """
    List available tools.
    列出可用工具。
    """
    return [
        types.Tool(
            name="decompile",
            description=(
                "Decompile a Java class/JAR using CFR. "
                "Use this to view the source code of compiled Java files. "
                "使用 CFR 反编译 Java class/JAR 文件。用于查看编译后的 Java 文件的源代码。"
            ),
            inputSchema={
                "type": "object",
                "properties": {
                    "file_path": {
                        "type": "string",
                        "description": "Absolute path to the .class or .jar file. (.class 或 .jar 文件的绝对路径)"
                    },
                    "method_name": {
                        "type": "string",
                        "description": "Only decompile methods with this name (highly recommended for large classes). (仅反编译指定名称的方法,强烈建议用于大类)"
                    },
                    "ignore_exceptions": {
                        "type": "boolean",
                        "description": "Drop try-catch blocks to make logic clearer (CFR --ignoreexceptions true). Default: false. (移除 try-catch 块以使逻辑更清晰)"
                    },
                    "hide_utf": {
                        "type": "boolean",
                        "description": "Hide UTF-8 characters if encoding is messy (CFR --hideutf true). Default: false. (如果编码混乱,隐藏 UTF-8 字符)"
                    },
                    "options": {
                        "type": "object",
                        "description": "Advanced CFR options (e.g. {'sugarboxing': False}). Key must be alphanumeric. (高级 CFR 选项,键必须是字母数字)"
                    }
                },
                "required": ["file_path"]
            }
        )
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
    """
    Handle tool execution.
    处理工具执行。
    """
    if name != "decompile":
        raise ValueError(f"Unknown tool (未知工具): {name}")

    # 1. Validation (验证)
    file_path_str = arguments.get("file_path")
    if not file_path_str:
        raise ValueError("file_path is required (需要 file_path 参数)")
        
    path = Path(file_path_str).resolve()
    if not path.exists():
        return [types.TextContent(type="text", text=f"Error: File not found (文件未找到): {path}")]

    if not Path(CFR_JAR_PATH).exists():
        return [types.TextContent(type="text", text=f"Error: CFR jar not found at (CFR jar 未找到): {CFR_JAR_PATH}")]

    # 2. Build Command (构建命令)
    cmd = ["java", "-jar", CFR_JAR_PATH, str(path)]
    
    if arguments.get("method_name"):
        cmd.extend(["--methodname", arguments.get("method_name")])
        
    if arguments.get("ignore_exceptions"):
        cmd.extend(["--ignoreexceptions", "true"])
        
    if arguments.get("hide_utf"):
        cmd.extend(["--hideutf", "true"])

    # Defaults (默认设置)
    cmd.extend(["--comments", "false"])    # No header comments (无头部注释)
    cmd.extend(["--showversion", "false"]) # No version info (无版本信息)

    # Advanced Options (高级选项)
    extra_options = arguments.get("options", {})
    for key, value in extra_options.items():
        if not validate_option_key(key):
            logger.warning(f"Ignored invalid option key (忽略无效选项键): {key}")
            continue
        val_str = str(value).lower() if isinstance(value, bool) else str(value)
        cmd.extend([f"--{key}", val_str])

    # 3. Async Execution (异步执行)
    # Run synchronous subprocess in a thread pool to avoid blocking the event loop
    # 在线程池中运行同步 subprocess,避免阻塞事件循环
    loop = asyncio.get_running_loop()
    result = await loop.run_in_executor(None, partial(run_cfr_sync, cmd))

    return [types.TextContent(type="text", text=result)]

# --- SSE Transport (SSE 传输) ---
sse = SseServerTransport("/messages")

async def handle_sse(request):
    """
    Handle the initial SSE connection (GET).
    处理初始 SSE 连接 (GET)。
    """
    async with sse.connect_sse(request.scope, request.receive, request._send) as streams:
        await server.run(
            streams[0], 
            streams[1], 
            server.create_initialization_options()
        )
    return Response()

app = Starlette(routes=[
    Route("/sse", endpoint=handle_sse),
    Mount("/messages", app=sse.handle_post_message)
])

if __name__ == "__main__":
    # Log Format Configuration (日志格式配置)
    log_config = uvicorn.config.LOGGING_CONFIG
    log_config["formatters"]["access"]["fmt"] = "%(asctime)s - %(levelname)s - %(message)s"
    log_config["formatters"]["default"]["fmt"] = "%(asctime)s - %(levelname)s - %(message)s"
    log_config["formatters"]["access"]["datefmt"] = "%Y-%m-%d %H:%M:%S"
    log_config["formatters"]["default"]["datefmt"] = "%Y-%m-%d %H:%M:%S"
    
    print(f"Starting Optimized CFR MCP Server on {HOST}:{PORT}")
    print(f"SSE Endpoint: http://{HOST}:{PORT}/sse")
    uvicorn.run(app, host=HOST, port=PORT, log_config=log_config)

核心逻辑:

  • 使用 mcp SDK 和 Starlette 处理 SSE。
  • 使用 subprocess 调用 Java 命令:java -jar cfr.jar [options]。
  • 捕获标准输出返回给 MCP 客户端。

-

3. 启动服务器

运行以下命令启动服务(默认端口 8000):

python cfr_mcp_server.py

输出示例:

➜  cfr_mcp_server python3 cfr_mcp_server.py
Starting CFR MCP Server on 0.0.0.0:8000
SSE Endpoint: http://0.0.0.0:8000/sse
2026-01-09 16:09:56 - INFO - Started server process [1537138]
2026-01-09 16:09:56 - INFO - Waiting for application startup.
2026-01-09 16:09:56 - INFO - Application startup complete.
2026-01-09 16:09:56 - INFO - Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
2026-01-09 16:10:12 - INFO - 127.0.0.1:46308 - "POST /sse HTTP/1.1" 405
2026-01-09 16:10:12 - INFO - 127.0.0.1:46308 - "GET /sse HTTP/1.1" 200
2026-01-09 16:10:12 - INFO - 127.0.0.1:46314 - "POST /messages?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 307
2026-01-09 16:10:12 - INFO - 127.0.0.1:46314 - "POST /messages/?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 202
2026-01-09 16:10:12 - INFO - 127.0.0.1:46314 - "POST /messages?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 307
2026-01-09 16:10:12 - INFO - 127.0.0.1:46314 - "POST /messages/?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 202
2026-01-09 16:10:12 - INFO - 127.0.0.1:46314 - "POST /messages?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 307
2026-01-09 16:10:12 - INFO - 127.0.0.1:46314 - "POST /messages/?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 202
INFO:mcp.server.lowlevel.server:Processing request of type ListToolsRequest
2026-01-09 16:10:15 - INFO - 127.0.0.1:46314 - "POST /messages?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 307
2026-01-09 16:10:15 - INFO - 127.0.0.1:46314 - "POST /messages/?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 202
2026-01-09 16:10:15 - INFO - 127.0.0.1:46320 - "POST /messages?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 307
INFO:mcp.server.lowlevel.server:Processing request of type ListPromptsRequest
2026-01-09 16:10:15 - INFO - 127.0.0.1:46314 - "POST /messages/?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 202
INFO:mcp.server.lowlevel.server:Processing request of type ListResourcesRequest
2026-01-09 16:11:44 - INFO - 127.0.0.1:48686 - "POST /messages?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 307
2026-01-09 16:11:44 - INFO - 127.0.0.1:48686 - "POST /messages/?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 202
INFO:mcp.server.lowlevel.server:Processing request of type ListToolsRequest
2026-01-09 16:11:56 - INFO - 127.0.0.1:56536 - "POST /messages?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 307
2026-01-09 16:11:56 - INFO - 127.0.0.1:56536 - "POST /messages/?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 202
INFO:mcp.server.lowlevel.server:Processing request of type CallToolRequest
2026-01-09 16:11:56 - INFO - Executing CFR command: java -jar /path/to/cfr.jar /path/to/htoa/temp_class/com/oa8000/traceserver/TraceCreateServer.class --comments false
2026-01-09 16:11:57 - INFO - 127.0.0.1:56536 - "POST /messages?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 307
2026-01-09 16:11:57 - INFO - 127.0.0.1:56536 - "POST /messages/?session_id=f951c2ad72a346c18f2c30d1e6d63d9c HTTP/1.1" 202
INFO:mcp.server.lowlevel.server:Processing request of type ListToolsRequest

4. 客户端配置

方式 A: HTTP/SSE 连接 (推荐)

如果你的 MCP 客户端支持通过 URL 连接(如 Cursor 或某些 Web 客户端):

  • Server URL: http://localhost:8000/sse
opencode

比如在opencode里mcp部分配置

"cfr-decompiler": {
      "type": "remote",
      "url": "http://127.0.0.1:8000/sse",
      "enabled": true,
      "timeout": 300,
      "headers": {
        "Authorization": "Bearer MY_API_KEY"
      },
    },

在代码分析过程中,LLM自主决定自动调用反编译class

!

指定调用

!

!

Cherry Studio

在 MCP服务器 部分配置类型为 服务器发送事件(sse)的mcp服务器即可

!

!

方式 B: 本地命令执行 (Claude Desktop)

未测试

在配置文件中添加:

{
  "mcpServers": {
    "cfr-decompiler": {
      "command": "python",
      "args": ["/path/to/cfr_mcp_server.py"],
      "env": {
        "PYTHONUNBUFFERED": "1"
      }
    }
  }
}

5. 工具使用说明

工具名称: decompile

参数说明:

参数名类型必填说明
file_pathstring是目标 .class 或 .jar 文件的绝对路径
method_namestring否指定方法名。只反编译该方法,减少输出干扰。
optionsobject否CFR 的高级选项字典。

调用示例:

  1. 基础反编译:
{
  "file_path": "/path/to/MyClass.class"
}
  1. 反编译特定方法 (忽略异常块):
{
  "file_path": "/path/to/MyClass.class",
  "method_name": "complexCalculation",
  "options": {
    "ignoreexceptions": true
  }
}

工具与能力

工具数量

0

资源数量

0

提示词数量

0

能力标签

Java反编译Python本地部署服务器SSE传输MCP协议开发工具

支持客户端

Claude DesktopClaudeCursor

数量来自来源目录的标注,具体工具清单以官方文档为准。

典型使用场景

多步任务编排

把拆解、检索、执行串成一条链,模型按步骤调用工具。

长期上下文

把会话、笔记和知识放到外部存储,换个会话还能接着做。

接自有流程

把内部系统和模型连起来,让助手调用已有的工作流。

选择建议

值得选的地方

  • 只提供 0 个工具,职责集中,接入后不容易误操作。
  • 有现成的安装命令,不用自己找入口,照着跑就能起服务。
  • 已经适配 Claude Desktop、Claude、Cursor,换客户端不用重新研究配置。

先想清楚的地方

  • stdio 方式要求本地装好 运行环境,换机器要重新装一遍。
  • 需要自备访问 Token,没有凭据没法直接试。
  • 第三方目录整理,版本更新和行为细节以官方仓库为准。

更适合

  • 需要在AI代理场景里让模型直接调用外部能力的人。
  • 已经在用 Claude Desktop 的用户,接入路径最短。
  • 想先快速试一下、能接受在本地跑服务的人。

不太适合

  • 完全不想在本地装环境的人。
  • 暂时拿不到访问 Token的人。
  • 需要厂商级 SLA 和技术支持的生产环境。

同类对比

5 个同类
MCP Server工具数传输方式安装命令收录来源最后核验
cfr MCP server

MCP World · 本页

0stdio有1 个2026-05-17
Everything Claude Code

MCP World

0stdio有1 个2026-05-17
Filesystem 560c4363

MCP World

13未说明未标注2 个2026-05-17
Time 7365cb6d

MCP.so

2SSE有2 个2026-05-17
Server Everything (everything)

MCP World

11stdio有1 个2026-05-17

按同分类和工具数量挑出最接近的几条,字段以各自详情页为准。

常见问题

5 条

cfr MCP server 怎么安装?

公开资料给出的安装命令是 pip install mcp starlette uvicorn,运行环境为 未标注。装完后按客户端要求写进 MCP 配置,重启客户端生效。

cfr MCP server 怎么在 Claude Desktop、Cursor 里配置?

它是stdio 本地进程,客户端配置里要写启动命令和参数,运行环境是 未标注;保存后完全退出客户端再打开,配置才会生效。

cfr MCP server 收费吗?

本站只整理公开资料,不代收费用,也没有标注具体价格。是否收费取决于服务本身和背后的接口额度,正式使用前按官方说明确认。

cfr MCP server 需要 API Key 吗?

公开资料标注的认证方式是访问 Token,也就是要先拿到凭据才能连上;凭据只填在自己本地的配置里,不要写进公开仓库。

cfr MCP server 支持哪些客户端?

公开资料标注支持 Claude Desktop、Claude、Cursor;其他客户端只要能配置 MCP Server,也能用同样的命令或地址接入。

来源信息

继续浏览同类 MCP