关于MCP

mcp是什么?它解决了什么?

按照anthropic的说法,MCP解决了数据的隔离,提供了一个通用的开放标准,使得AI系统访问数据更加容易

我有这么一个使用场景:

我在一名叫luogu的文件夹里面写了很多算法题,想要总结到特定文件夹的一个特定markdown文件里面,我可以使用mcp来解决这个问题吗?

首先需要解决的就是让mcp可以做到读取文件,然后写入文件

动手构建MCP

开始动手写一个mcp的sevrer

按照官方的流程,需要安装uv(一个由Rust编写的python包管理客户端)

我是windows系统,所以用下面的命令

1
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

如果是macos或者linux系统,可以用下面的命令

1
curl -LsSf https://astral.sh/uv/install.sh | sh

之后进行项目的初始化,我将这个sever命名为algomd

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Create a new directory for our project
uv init algomd

# Create virtual environment and activate it
uv venv
source .venv/bin/activate

# Install dependencies
uv add "mcp[cli]"

# Create our server file
new-item algomd.py

具体server端的开发可以按照这个MCP官方文档

我这里写了一个简单的server,用来实现我想要的功能

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP
import os
from pathlib import Path
from datetime import datetime
from typing import Optional


# Initialize FastMCP server
mcp = FastMCP("algomd")


@mcp.tool()
async def read_algo() -> dict:
    """Read the content of all .cpp files in D:\\code\\luogu directory."""
    # Set the target path
    cpp_files_path = Path("D:\\code\\luogu")
    
    # Check if the path exists
    if not cpp_files_path.exists():
        return {"error": f"Path {cpp_files_path} does not exist"}
    
    # Dictionary to store file paths and their contents
    cpp_files_content = {}
    
    # Find all .cpp files
    cpp_files = list(cpp_files_path.glob("**/*.cpp"))
    
    # Process files
    for i, cpp_file in enumerate(cpp_files):
        try:
            # 直接使用 print 或日志记录进度,不再使用 ctx
            print(f"Reading file ({i+1}/{len(cpp_files)}): {cpp_file}")
            
            # Read the content of each file with UTF-8 encoding
            with open(cpp_file, 'r', encoding='utf-8') as file:
                content = file.read()
                # Store the file path as string and its content
                cpp_files_content[str(cpp_file)] = content
        except Exception as e:
            # Handle potential errors (like encoding issues)
            cpp_files_content[str(cpp_file)] = f"Error reading file: {str(e)}"
    
    return cpp_files_content

@mcp.tool()
def save_to_markdown(
    content: str, 
    prompt: Optional[str] = None,
    filename: Optional[str] = None
) -> dict:
    """
    Save LLM-generated content to a markdown file.
    
    Args:
        content: The text content to save in the markdown file
        prompt: Optional prompt that generated the content
        filename: Optional custom filename (without extension)
        
    Returns:
        Dictionary with status information
    """
    # 固定的保存路径
    save_dir = Path("D:/code/ai_outputs")
    
    # 创建目录(如果不存在)
    save_dir.mkdir(parents=True, exist_ok=True)
    
    # 生成文件名(如果未提供)
    if not filename:
        timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
        filename = f"llm-output-{timestamp}"
    
    # 确保文件名有.md扩展名
    if not filename.endswith(".md"):
        filename = f"{filename}.md"
    
    # 完整的文件路径
    file_path = save_dir / filename
    
    try:
        # 准备文件内容
        file_content = []
        
        # 添加元数据部分
        file_content.append("---")
        file_content.append(f"created: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
        file_content.append(f"user: {os.getenv('USERNAME') or 'LOTUSSSB'}")
        
        if prompt:
            file_content.append(f"prompt: |\n  {prompt.replace(chr(10), chr(10) + '  ')}")
        
        file_content.append("---")
        file_content.append("")  # 空行分隔元数据和内容
        
        # 添加正文内容
        file_content.append(content)
        
        # 写入文件
        with open(file_path, "w", encoding="utf-8") as f:
            f.write("\n".join(file_content))
        
        return {
            "success": True,
            "file_path": str(file_path),
            "file_size": os.path.getsize(file_path),
            "message": f"Content successfully saved to {file_path}"
        }
    
    except Exception as e:
        return {
            "success": False,
            "error": str(e),
            "message": f"Failed to save content: {str(e)}"
        }


if __name__ == "__main__":
    # Initialize and run the server
    mcp.run(transport='stdio')

看到有说可以测试mcp服务器的功能(官方文档里面没这个指南),我就尝试了一下

调试mcp的时候出现了没有npx的报错

查看报错的cli.py文件原来是如果要用dev服务器,需要安装npx

安装后进入流程

再次启动dev服务器,在浏览器中输入 http://localhost:5173 即可进入dev页面

点击左侧的connect按钮,如果一切安好,就能正常连接到你写的mcp server了

注意:如果你这一步有问题,可能出现显示到连接的文件路径有问题,一般是server代码的问题

连接成功后,在上方的Tools就能看到你写的server功能了

不过这个dev界面我没有过多探索

直接上cladue desktop吧!(急迫

用命令行输入(windows系统)

1
code $env:AppData\Claude\claude_desktop_config.json

打开的这个就是claude desktop的配置文件,按照官方文档的说法,需要在这个文件中添加一个新的配置项,这个配置项是你的mcp server的地址

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{
  "mcpServers": {
      "algomd": {
          "command": "uv",
          "args": [
              "--directory",
              "D:\\code\\mcp\\algomd",
              "run",
              "algomd.py"
          ]
      }
  }
}

这里的algomd是我项目初始化的时候的文件夹名以及server的名字

D:\code\mcp\algomd 是我的mcp server的文件夹路径,algomd.py是我的mcp server的文件名,这样就添加好了mcp tools

打开claude desktop,就会对话栏右下角多了个锤子并且显示了MCP的Tool可用状态

点开可以看到你的mcp tools的功能,里面内含有你写的prompt

我发起询问:你可以读取我的 D:\code\luogu 里面的文件吗?

这时候LLM就会很聪明地请求调用MCP server,请求权限,通过后就可以他就可以读取文件了

当我再次发起询问:请使用 save_to_markdown 工具将 P8225.cpp 和 CF504E.cpp 的内容(包括它们的时间复杂度和空间复杂度)总结成一篇博客文章,并输出到指定文件

这时候,他会再次请求tools的权限,通过后就可以使用tools来写博客了

他的输出如下

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
---
created: 2025-03-21 21:24:18
user: LOTUS
prompt: |
  Create a detailed analysis of P8225.cpp and CF504E.cpp, including their algorithms, implementations, and time/space complexity.
---


# Analysis of Advanced Algorithms: CF504E and P8225

This blog post provides a detailed analysis of two competitive programming solutions focusing on their algorithms, implementations, and complexity.

## P8225: Genius Numbers Problem

### Problem Overview
The P8225.cpp file solves a problem involving "genius numbers" - numbers that consist entirely of 9s with a specific length pattern. A k-th level genius number is defined as a number that consists of all 9s, where the length of the number is a multiple of k.

For example:
- 1st level genius numbers: 9, 99, 999, ...
- 2nd level genius numbers: 99, 9999, ...
- 3rd level genius numbers: 999, 999999, ...

The problem asks whether a given number `n` can be represented as a sum of one or more k-th level genius numbers.

### Algorithm Analysis

The solution uses two approaches:

1. **Initial approach (not used in final solution)**: Dynamic programming
   ```cpp
   bool checkForKGreaterThan1(ll n, int k) {
       // Generate all possible k-level genius numbers
       vector<ll> geniusNumbers;
       for (int len = k; len <= 18; len += k) {
           ll num = generateNines(len);
           if (num > n) break;
           geniusNumbers.push_back(num);
       }
       
       // DP approach: can we make sum n using these numbers?
       vector<bool> dp(n + 1, false);
       dp[0] = true;
       
       for (ll num : geniusNumbers) {
           for (ll i = num; i <= n; i++) {
               if (dp[i - num]) {
                   dp[i] = true;
               }
           }
       }
       
       return dp[n];
   }

由于太长我就不放完了,总之出来的效果还是不错的,写好这个mcp server后,可以帮我节省不少时间

以后写好的算法题,只需要调用这个mcp server,就可以自动生成博客文章了

参考:

vscode agent模式 https://code.visualstudio.com/blogs/2025/02/24/introducing-copilot-agent-mode

claude mcp https://www.anthropic.com/news/model-context-protocol

mcp官方手册 https://modelcontextprotocol.io/quickstart/user

https://modelcontextprotocol.io/docs/concepts/tools

https://modelcontextprotocol.io/quickstartserver#why-claude-for-desktop-and-not-claude-ai

https://zhuanlan.zhihu.com/p/29001189476

https://xjzsq.ren/2018/07/18/luogu/