额外任务2:启用MCP的GitHub分析代理
作者 阿克什塔
概述
奖金作业2重构奖金作业1以供使用 模型上下文协议(MCP) 为了实现现代化、可扩展的架构。该应用程序保留了分配1中的所有功能,同时用MCP工具服务器取代了直接数据库/API调用。
作业1的主要改进
- MCP架构:直接呼叫被MCP工具服务器取代
- 关注点分离:数据库、ETL、分析和向量操作是隔离的
- 可扩展性:工具服务器可以独立运行,并可替换为生产级服务
- 可维护性:使用LangChain/LangGraph工具集成更清晰的代理代码
- 可扩展性:易于添加新的MCP工具以实现其他功能
项目结构
Bonus_Assignment_2_Muthu/
├── src/
│ ├── app.py # Streamlit UI
│ ├── mcp_agent.py # LangGraph agent with MCP tools
│ ├── mcp_postgres_tool.py # PostgreSQL MCP tool server
│ ├── mcp_csv_etl_tool.py # CSV/ETL MCP tool server (GitHub API)
│ ├── mcp_analytics_tool.py # Analytics/Forecasting MCP tool server
│ ├── mcp_vectordb_tool.py # Vector DB MCP tool server
│ ├── requirements.txt # Python dependencies
│ ├── .env.example # Environment variables template
│ └── __init__.py # Package initialization
└── doc/
├── README.md # Installation & usage guide
├── ARCHITECTURE.md # System design document
├── MCP_DESIGN.md # MCP-specific design details
└── demo_link.txt # Panopto demo video link系统架构
MCP工具服务器
该应用程序公开了四个主要的MCP工具服务器:
1. PostgreSQL MCP工具 (mcp_postgres_tool.py)
- 功能:
- execute_query(query) -执行SELECT查询 - execute_mutation(query, params) -执行插入/更新/删除 - get_schema_info() -获取数据库架构 - get_table_stats(table_name) -获取表行数
- 用途: 从PostgreSQL查询缓存的GitHub数据
2. CSV/ETL MCP工具 (mcp_csv_etl_tool.py)
- 功能:
- fetch_repo_stats(owner, repo) -获取回购星/叉 - fetch_issues(owner, repo, days) -从GitHub API获取问题 - fetch_pulls(owner, repo, days) -获取拉取请求 - fetch_commits(owner, repo, days) -获取提交 - to_csv(data, filename) -将数据保存到CSV - from_csv(filename) -从CSV加载数据
- 用途: 从GitHub获取实时数据并转换为CSV格式
3. 分析/预测MCP工具 (mcp_analytics_tool.py)
- 功能:
- create_table(data) -将数据格式化为表格 - create_line_chart(df, x, y, title) -创建折线图 - create_bar_chart(df, x, y, title) -创建条形图 - create_pie_chart(df, values, names, title) -创建饼图 - create_stacked_bar_chart(...) -创建堆叠条形图 - prophet_forecast(df, periods) -Prophet时间序列预测 - statsmodels_forecast(df, periods, method) -统计模型预测
- 用途: 将数据转化为可视化和预测
4. 矢量数据库MCP工具 (mcp_vectordb_tool.py)
- 功能:
- create_embedding(text, doc_id) -创建文本嵌入 - semantic_search(query, top_k) -查找类似文档 - store_vector(doc_id, embedding, metadata) -存储矢量 - get_vector_stats() -获取矢量存储统计信息
- 用途: 高级查询的语义搜索和嵌入
LangGraph代理
这 mcp_agent.py 实现了一个工具调用代理,该代理:
- 从Streamlit UI接收自然语言查询
- 根据查询选择适当的MCP工具
- 将工具调用链接在一起(例如,查询数据库→ 变换→ 可视化)
- 将结构化结果返回给UI
流线型前端
app.py 提供:
- 自然语言查询输入
- 配置选项(数据源、输出格式)
- 快速测试的示例查询
- 结果可视化(表格、图表、预测)
- 错误处理和元数据显示
安装和设置
先决条件
- Python 3.11+
- PostgreSQL 12+(带bonus_assignment数据库)
- GitHub个人访问令牌
- OpenAI API密钥
步骤1:创建虚拟环境
cd Bonus_Assignment_2_Muthu/src
python3 -m venv venv
source venv/bin/activate # macOS/Linux
# or
venv\Scripts\activate # Windows步骤2:安装依赖项
pip install -r requirements.txt步骤3:配置环境变量
cp .env.example .env
# Edit .env with your credentials:
# - GITHUB_TOKEN: Personal access token from GitHub
# - OPENAI_API_KEY: API key from OpenAI
# - DATABASE_URL: PostgreSQL connection string步骤4:设置PostgreSQL数据库
# Create database
createdb bonus_assignment
# Connect to database
psql -d bonus_assignment
# Create tables (run these SQL commands):CREATE TABLE repos (
repo_name VARCHAR(100) PRIMARY KEY,
stars INT,
forks INT
);
CREATE TABLE issues (
id SERIAL PRIMARY KEY,
repo_name VARCHAR(100) REFERENCES repos(repo_name),
issue_number INT,
created_at TIMESTAMP,
closed_at TIMESTAMP,
title TEXT
);
CREATE TABLE pulls (
id SERIAL PRIMARY KEY,
repo_name VARCHAR(100) REFERENCES repos(repo_name),
pull_number INT,
created_at TIMESTAMP,
closed_at TIMESTAMP,
title TEXT
);
CREATE TABLE commits (
id SERIAL PRIMARY KEY,
repo_name VARCHAR(100) REFERENCES repos(repo_name),
commit_sha VARCHAR(200),
commit_date TIMESTAMP,
message TEXT
);步骤5:用GitHub数据填充数据库
创建数据加载脚本(load_data.py):
import os
import json
import psycopg2
from mcp_csv_etl_tool import csv_etl_tool
from dotenv import load_dotenv
load_dotenv()
# Target repositories
repos = [
("meta-llama", "llama3"),
("ollama", "ollama"),
("langchain-ai", "langgraph"),
("openai", "openai-cookbook"),
("milvus-io", "pymilvus"),
]
conn = psycopg2.connect(os.getenv("DATABASE_URL"))
cursor = conn.cursor()
for owner, repo in repos:
# Fetch and insert repo stats
repo_data = csv_etl_tool.fetch_repo_stats(owner, repo)
cursor.execute(
"INSERT INTO repos (repo_name, stars, forks) VALUES (%s, %s, %s) ON CONFLICT DO NOTHING",
(repo_data["repo_name"], repo_data["stars"], repo_data["forks"])
)
# Fetch and insert issues
issues = csv_etl_tool.fetch_issues(owner, repo)
for issue in issues:
cursor.execute(
"INSERT INTO issues (repo_name, issue_number, created_at, closed_at, title) VALUES (%s, %s, %s, %s, %s)",
(issue["repo_name"], issue["issue_number"], issue["created_at"], issue["closed_at"], issue["title"])
)
# Similar for pulls and commits...
conn.commit()
cursor.close()
conn.close()运行脚本:
python load_data.py步骤6:运行应用程序
streamlit run app.py该应用程序将在 http://localhost:8501
使用示例
示例1:哪个回购的发行次数最多?
查询:
Which repo has the highest number of issues created?流量:
- 客服电话
postgres_query使用SQL聚合 - 结果以表格形式显示
示例2:创建问题分布饼图
查询:
What is the percentage distribution of issues created? Create a Pie Chart流量:
- 客服电话
postgres_query按回购获取发行次数 - 呼叫
create_pie_chart与数据 - UI中显示饼图
示例3:预测未来问题
查询:
Use Facebook/Prophet to forecast created issues for every repo流量:
- 客服电话
postgres_query获取历史问题 - 呼叫
run_prophet_forecast对于每个回购 - 显示预测图表
示例4:周分析
查询:
Create a table of total issues created for every repo for every day of the week流量:
- 客服电话
postgres_query使用EXTRACT(DOW FROM created_at)分组 - 呼叫
create_table_from_data格式化结果 - 按回购和日期显示的枢轴表
支持的查询
文本/表格查询
- 哪个Repo创建的问题数量最多?
- 创建一个每天为每个回购创建的总发行量表
- 一周中的哪一天所有回购的总发行量最高?
- 哪一天的总发行量最高?
图表查询
- 绘制随时间推移产生的总问题的折线图
- 已创建问题的百分比分布(饼图)
- 每个回购的星级柱状图
- 每个回购的分叉柱状图
- 已创建与已关闭问题的堆积条形图
预测查询
- Prophet对每个回购创建的发行量的预测
- Prophet对每笔回购已结束发行量的预测
- StatsModels预测每次回购的提款
- StatsModels预测每个仓库的提交
MCP工具集成详细信息
如何调用工具
# Example: Agent calling PostgreSQL tool
agent.invoke("Which repo has the most stars?")
# Agent execution flow:
1. LLM analyzes query
2. Selects postgres_query tool
3. LLM generates SQL: SELECT repo_name, stars FROM repos ORDER BY stars DESC LIMIT 1
4. Tool executes SQL and returns results
5. Results formatted and returned to user工具链
对于复杂的查询,代理会链接多个工具:
Query: "Plot issues over time"
↓
Tool 1: postgres_query (get time-series data)
↓
Tool 2: create_line_chart (visualize data)
↓
Display result配置选项
在Streamlit侧栏中:
- 使用PostgreSQL缓存:查询缓存数据与实时API
- 获取实时GitHub数据:启用实时数据获取
- 首选输出格式:选择表格、图表、文本或预测
故障排除
数据库连接错误
- 验证PostgreSQL是否正在运行
- 检查.env中的DATABASE_URL
- 确保数据库和表存在
GitHub API速率限制
- 验证GITHUB_TOKEN是否已设置且有效
- 等待速率限制重置(1小时)
- 考虑增加分页限制
OpenAI API错误
- 验证OPENAI_API_KEY是否已设置
- 支票账户有可用信用额度
- 确保密钥具有必要的权限
大型数据集的内存问题
- 降低中的分页限制
mcp_csv_etl_tool.py - 使用按日期范围筛选
- 查询数据库而不是实时API
性能注意事项
- 数据库查询:使用PostgreSQL缓存数据(更快)
- 实时API调用:仅在需要新数据时使用
- 大型数据集:实现分页和过滤
- 预测性能:如果频繁使用,则缓存预测结果
- 向量运算:使用批嵌入以获得更好的性能
扩展系统
添加新的MCP工具
- 创建新的工具模块:
mcp_custom_tool.py - 使用文档字符串定义工具函数
- 导入
mcp_agent.py - 创建LangChain工具包装器
- 添加到代理的工具列表
例子:
from langchain_core.tools import tool
@tool
def my_custom_tool(param: str) -> str:
"""Tool description for LLM."""
return perform_operation(param)
# In MCPAgent.__init__:
self.tools.append(my_custom_tool)替换矢量数据库
当前的实现使用内存中的向量存储。要使用松果/织物:
# mcp_vectordb_tool.py modifications:
import pinecone
class VectorDBMCPTool:
def __init__(self):
pinecone.init(api_key=os.getenv("PINECONE_API_KEY"))
self.index = pinecone.Index("github-data")
def semantic_search(self, query: str, top_k: int = 5):
# Use pinecone instead of in-memory search评分检查表
- \[x\] 两个目录:
src和doc - \[x\]
requirements.txt所有依赖项 - \[x\] 包含安装步骤的详细自述文件
- \[x\] 中的所有源代码
src目录 - \[x\] 用于PostgreSQL、ETL、分析、矢量数据库的MCP工具服务器
- \[x\] 使用MCP工具的LangGraph代理
- \[x\] 简化自然语言查询的用户界面
- \[x\] 支持所有必需的查询(表格和图表)
- \[x\] Prophet和StatsModels预测
- \[x\] 环境配置(.env)
- \[x\] 验证代码的完整性和正确性
参考文献
演示视频
泛光链路: \[录制后添加链接\]
演示内容包括:
- 安装和设置
- 运行Streamlit应用程序
- 自然语言查询示例
- 图表和表格生成
- 时间序列预测
- MCP工具执行流程
______________________________________________________________________
启用MCP的GitHub接口 2025年12月
导出UV_LINK_MODE=复制&&&UV pip安装-r要求.txt
