前言
相信大部分程序員都有這樣的經(jīng)歷:周一到周五忙的天昏地暗但是到了周五下班前寫周報時又回憶不起來具體干了點啥,像是做了很多事但好像又什么也沒做。為了應(yīng)對這種情況我會在每天完成一件任務(wù)或需求時將其記錄下來,但是有時候忘記了就不得不再去需求池里翻了。
與其他職業(yè)不同,程序員的工作大部分還是和代碼打交道的,我們一周內(nèi)的具體工作內(nèi)容都反映在項目中的git提交記錄里,所以我們可以基于一周內(nèi)的git提交記錄按照周報模版promp生成周報,先給大家看下效果:

開發(fā)準備
安裝python3.12和uv,使用Homebrew安裝非常簡單,執(zhí)行兩個命令即可:
- 安裝python
brew install python@3.12
- 安裝uv
brew install uv
新建項目 mcp-git-weekly-report并創(chuàng)建weekly_report.py文件
在weekly_report.py中安裝fastmcp依賴并創(chuàng)建mcp
使用uv pip install fastmcp或pip install fastmcp安裝依賴后創(chuàng)建mcp:
from fastmcp import FastMCP
#默認是Stdio協(xié)議,所以我們這個mcp服務(wù)器實際上是在本地運行的
mcp = FastMCP("weekly-report")
這里簡單的介紹下FastMCP框架,FastMCP 是一個 Python 框架,它極大地簡化了 MCP 服務(wù)器的開發(fā)過程。 它的名字中的 “Fast” 就暗示了其目標:讓開發(fā)者能夠快速構(gòu)建 MCP 服務(wù)器。
FastMCP 的核心特點和優(yōu)勢:
極簡的 API:使用裝飾器(如 @mcp.tool)將普通的 Python 函數(shù)直接“變成” MCP 工具。你幾乎不需要關(guān)心底層的協(xié)議細節(jié)。
基于 Pydantic:天然支持使用 Pydantic 模型來定義工具輸入輸出的數(shù)據(jù)類型,確保類型安全和清晰的文檔。
資源管理:提供了簡單的方式來管理資源(如數(shù)據(jù)庫連接),可以在服務(wù)器啟動時建立連接,并在結(jié)束時自動關(guān)閉。
-
內(nèi)置常用功能:它預(yù)置了許多常見的 MCP 服務(wù)器功能,例如:
文件系統(tǒng)訪問:讓 AI 可以讀寫指定目錄的文件。 SQL 數(shù)據(jù)庫查詢:讓 AI 可以直接查詢數(shù)據(jù)庫。 代碼執(zhí)行:提供安全的代碼執(zhí)行環(huán)境。 HTTP 請求:簡化了對外部 API 的調(diào)用。 開發(fā)友好:支持簡單的命令行指令來運行和測試服務(wù)器。
如果你想要對mcp服務(wù)做出更精準的控制和定制,可以使用官方提供的更底層的sdk,詳情請見官方文檔:https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#tools
開發(fā)
設(shè)計思路
我們使用git log命令獲取提交記錄,完整的指令格式形如:
git log --author=cube.li --since='3 days ago' --pretty='format:%ad|%s' --date=short
為了能夠成功執(zhí)行這條指令,我們需要知道以下參數(shù):
1、 項目地址,由于周報mcp服務(wù)是運行在本地的,所以項目地址是一個本地絕對路徑,項目地址要做成可配置的且能夠靈活更改,所以我們將其作為mcp服務(wù)器的環(huán)境變量注入,并使用“|”作為分隔符以支持多項目
2、git 用戶名稱,用戶名可通過git config user.name獲取,不需要傳入
3、日期范圍,周報默認是當前周(7天內(nèi)),但是我們也支持指定日期范圍內(nèi)的工作總結(jié),例如:寫3天內(nèi)的工作總結(jié),寫15天內(nèi)的工作總結(jié),所以我們將其使用大模型識別作為參數(shù)傳遞到mcp服務(wù)器中
當我們具備以上信息后就能夠成功獲取到git提交記錄并返回到AI應(yīng)用了,但是只做到這一步還無法對周報內(nèi)容、格式、字數(shù)進行限制,AI應(yīng)用獲取到提交記錄后會自己發(fā)揮生成周報,當然我們可以在要求寫周報時再輸入特定的要求,但這樣使用不夠方便,所以我們要在mcp服務(wù)器中預(yù)制好周報模版prompt,返回AI應(yīng)用時將 周報模版prompt+提交記錄 一并返回給AI應(yīng)用,這樣既不用每次輸入周報要求也能夠生成符合要求的周報了。
周報模版prompt內(nèi)容如下:
你是一個專業(yè)的周報生成器,根據(jù) Git 提交記錄生成一份專業(yè)的工作周報。
## ?? 要求
1. **分類整理**:將提交按功能開發(fā)、Bug修復(fù)、性能優(yōu)化、文檔更新等分類,如果提交記錄不涉及某一個分類則周報不需要體現(xiàn)出該分類
2. **提煉要點**:從 commit message 中提煉關(guān)鍵工作內(nèi)容,如果多個commit message內(nèi)容相似,你需要使用簡潔、清晰的語言對其進行匯總而不是使用冗余的方式表達
3. **專業(yè)表述**:使用專業(yè)的技術(shù)語言,簡潔明了
4. **格式規(guī)范**:使用清晰的 Markdown 格式
5. **跨項目視角**:總結(jié)跨項目的技術(shù)積累和工作思路
6. **字數(shù)限制**:字數(shù)控制在100-300字,務(wù)必要使用簡潔、精煉但明確的方式進行總結(jié)
輸出格式如下:
## 一、工作概述
[用2-3句話總結(jié)本周主要工作內(nèi)容和成果]
## 二、詳細工作內(nèi)容
### 2.1 功能開發(fā)
- [功能1]:[詳細描述功能內(nèi)容和技術(shù)實現(xiàn)]
- [功能2]:[詳細描述]
### 2.2 Bug修復(fù)
- [問題1]:[問題描述] → [解決方案]
- [問題2]:[問題描述] → [解決方案]
### 2.3 性能優(yōu)化
- [優(yōu)化項1]:[優(yōu)化內(nèi)容和效果]
### 2.4 其他工作
- [文檔更新、代碼重構(gòu)等]
## 三、技術(shù)總結(jié)
[本周工作中的技術(shù)亮點、經(jīng)驗總結(jié)或遇到的技術(shù)挑戰(zhàn)]
##git提交記錄:
為了方便調(diào)試開發(fā)中的mcp,可以安裝官方提供的MCP Inspector,也可以使用Claude Desktop或cursor進行調(diào)試。由于我是cursor的重度用戶,所以后面我會基于cursor給出周報mcp的效果展示及使用示例。
代碼實現(xiàn)
- 從環(huán)境變量中獲取項目地址
def get_projects() -> List[Dict[str, str]]:
"""
從環(huán)境變量讀取項目配置
Returns:
項目列表,每個項目包含 name 和 path
"""
paths_str = os.getenv("PROJECT_PATHS", "")
if not paths_str:
return []
projects = []
for path in paths_str.split("|"):
path = path.strip()
if not path:
continue
# 驗證路徑存在且是 Git 倉庫
if os.path.exists(path) and os.path.exists(os.path.join(path, ".git")):
projects.append({
"name": os.path.basename(path),
"path": path
})
else:
print(f"Warning: {path} 不是有效的 Git 倉庫", file=sys.stderr)
return projects
- 獲取提交記錄
def get_git_commits(repo_path: str, days: int = 7) -> Dict[str, str]:
"""
獲取指定倉庫的 Git 提交記錄
Args:
repo_path: 倉庫路徑
days: 查詢最近幾天的提交
Returns:
包含 author, commits, repo_path 的字典
"""
# 獲取作者名
result = subprocess.run(
["git", "config", "user.name"],
cwd=repo_path,
capture_output=True,
text=True,
check=False
)
author = result.stdout.strip() or "Unknown"
# 獲取提交記錄
result = subprocess.run(
["git", "log", f"--author={author}",
f"--since='{days} days ago'",
"--pretty=format:%ad|%s", "--date=short"],
cwd=repo_path,
capture_output=True,
text=True,
check=False
)
commits = result.stdout.strip()
# 統(tǒng)計提交次數(shù)
commit_count = len([line for line in commits.split('\n') if line.strip()]) if commits else 0
return {
"author": author,
"commits": commits or "(無提交記錄)",
"commit_count": commit_count,
"repo_path": repo_path
}
- 定義git_commits_report方法并將其作為mcp.tool暴露
#注意這個裝飾器,使用@mcp.tool()修飾后將其作為mcp的tool暴露給AI應(yīng)用
@mcp.tool()
def git_commits_report(days: int = 7) -> str:
"""根據(jù)指定項目的git提交記錄生成周報
Args:
days: 統(tǒng)計最近幾天的工作(默認為當前天往過去推6天也就是days=7,如果用戶明確了時間例如三天內(nèi)則days=3)
"""
projects: List[Dict[str, str]] = get_projects()
commit_str: str = ''
for proj in projects:
commit_str += get_git_commits(proj['path'], days).get('commits', '')
return f"{report_prompt_template}\n{commit_str}"
這里需要注意的有兩點:
1、方法注釋一定要寫詳細,這樣在AI應(yīng)用中就能夠看到關(guān)于這個mcp工具的詳細信息,在cursor中的效果如下:

2、@mcp.tool()
實際上,MCP服務(wù)器有三種對外暴露能力的方式:
tool 允許模型執(zhí)行操作或檢索信息的可執(zhí)行函數(shù),使用裝飾器
@mcp.tool(),一般而言,涉及到數(shù)據(jù)處理的能力適合作為tool對外暴露-
prompt 預(yù)設(shè)模板或指令,引導(dǎo)語言模型互動,使用裝飾器
@mcp.prompt(),例如我們可以使用@mcp.prompt()裝飾git_commits_report,當我們重啟mcp服務(wù)時,在cursor對話框中輸入/時cursor會自動給出已有的mcp prompt列表:
image.png
通過使用@mcp.prompt(),一方面提高了人與AI應(yīng)用的交互效率,另一方面為 AI 應(yīng)用提供可組合、可管理、可解釋的提示上下文機制 resource 為模型提供額外上下文的結(jié)構(gòu)化數(shù)據(jù)或內(nèi)容 ,使用裝飾器
@mcp.resource()
需要注意的是,一個mcp服務(wù)器可以提供多種類型多個mcp工具(tool、prompt、resource)
配置
在cursor中的mcp.json中添加以下配置:
{
"mcpServers": {
"weekly-report": {
"command": "uv",
"args": [
"run",
"--directory",
"/Users/ltb/PycharmProjects/mcp-git-weekly-report/src/mcp_git_weekly_report",
"weekly_report.py"
],
"env": {
"PROJECT_PATHS": "/Users/ltb/PycharmProjects/mcp-git-weekly-report"
}
}
}
}
將其中的mcp_git_weekly_report絕對路徑改成自己本地項目地址,將PROJECT_PATHS環(huán)境變量改成自己的項目地址即可,如果是多個項目使用|分割。
使用示例:



完整代碼地址:https://gitee.com/li-cube/mcp-git-weekly-report
當然你也可以使用如下配置,從遠端自動拉取代碼啟動mcp服務(wù):
{
"mcpServers": {
"weekly-report": {
"command": "uvx",
"args": [
"--from",
"git+https://gitee.com/li-cube/mcp-git-weekly-report.git",
"mcp-git-weekly-report"
],
"env": {
"PROJECT_PATHS": "項目1絕對路徑|項目2絕對路徑"
}
}
}
}
