Skip to content

Commit d02852b

Browse files
authored
Merge branch 'main' into main
2 parents 154cb25 + ecf537e commit d02852b

22 files changed

+1826
-21
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# 🐙 MCP GitHub Agent
2+
3+
A Streamlit application that allows you to explore and analyze GitHub repositories using natural language queries through the Model Context Protocol (MCP).
4+
5+
## Features
6+
7+
- **Natural Language Interface**: Ask questions about repositories in plain English
8+
- **Comprehensive Analysis**: Explore issues, pull requests, repository activity, and code statistics
9+
- **Interactive UI**: User-friendly interface with example queries and custom input
10+
- **MCP Integration**: Leverages the Model Context Protocol to interact with GitHub's API
11+
- **Real-time Results**: Get immediate insights on repository activity and health
12+
13+
## Setup
14+
15+
### Requirements
16+
17+
- Python 3.8+
18+
- Node.js and npm (for MCP GitHub server)
19+
- This is a critical requirement! The app uses `npx` to run the MCP GitHub server
20+
- Download and install from [nodejs.org](https://nodejs.org/)
21+
- GitHub Personal Access Token with appropriate permissions
22+
- OpenAI API Key
23+
24+
### Installation
25+
26+
1. Install the required Python packages:
27+
```bash
28+
pip install -r cookbook/examples/apps/github_mcp_agent/requirements.txt
29+
```
30+
31+
2. Verify Node.js and npm are installed:
32+
```bash
33+
node --version
34+
npm --version
35+
npx --version
36+
```
37+
All of these commands should return version numbers. If they don't, please install Node.js.
38+
39+
3. Set up your API keys:
40+
- Set OpenAI API Key as an environment variable:
41+
```bash
42+
export OPENAI_API_KEY=your-openai-api-key
43+
```
44+
- GitHub token will be entered directly in the app interface
45+
46+
4. Create a GitHub Personal Access Token:
47+
- Visit https://github.com/settings/tokens
48+
- Create a new token with `repo` and `user` scopes
49+
- Save the token somewhere secure
50+
51+
### Running the App
52+
53+
1. Start the Streamlit app:
54+
```bash
55+
streamlit run cookbook/examples/apps/github_mcp_agent/app.py
56+
```
57+
58+
2. In the app interface:
59+
- Enter your GitHub token in the sidebar
60+
- Specify a repository to analyze
61+
- Select a query type or write your own
62+
- Click "Run Query"
63+
64+
### Example Queries
65+
66+
#### Issues
67+
- "Show me issues by label"
68+
- "What issues are being actively discussed?"
69+
- "Find issues labeled as bugs"
70+
71+
#### Pull Requests
72+
- "What PRs need review?"
73+
- "Show me recent merged PRs"
74+
- "Find PRs with conflicts"
75+
76+
#### Repository
77+
- "Show repository health metrics"
78+
- "Show repository activity patterns"
79+
- "Analyze code quality trends"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import os
2+
from textwrap import dedent
3+
4+
from agno.agent import Agent
5+
from agno.tools.mcp import MCPTools
6+
from mcp import ClientSession, StdioServerParameters
7+
from mcp.client.stdio import stdio_client
8+
9+
10+
async def run_github_agent(message):
11+
if not os.getenv("GITHUB_TOKEN"):
12+
return "Error: GitHub token not provided"
13+
14+
try:
15+
server_params = StdioServerParameters(
16+
command="npx",
17+
args=["-y", "@modelcontextprotocol/server-github"],
18+
)
19+
20+
# Create client session
21+
async with stdio_client(server_params) as (read, write):
22+
async with ClientSession(read, write) as session:
23+
# Initialize MCP toolkit
24+
mcp_tools = MCPTools(session=session)
25+
await mcp_tools.initialize()
26+
27+
# Create agent
28+
agent = Agent(
29+
tools=[mcp_tools],
30+
instructions=dedent("""\
31+
You are a GitHub assistant. Help users explore repositories and their activity.
32+
- Provide organized, concise insights about the repository
33+
- Focus on facts and data from the GitHub API
34+
- Use markdown formatting for better readability
35+
- Present numerical data in tables when appropriate
36+
- Include links to relevant GitHub pages when helpful
37+
"""),
38+
markdown=True,
39+
show_tool_calls=True,
40+
)
41+
42+
# Run agent
43+
response = await agent.arun(message)
44+
return response.content
45+
except Exception as e:
46+
return f"Error: {str(e)}"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import asyncio
2+
import os
3+
4+
import streamlit as st
5+
from agents import run_github_agent
6+
7+
# Page config
8+
st.set_page_config(page_title="🐙 GitHub MCP Agent", page_icon="🐙", layout="wide")
9+
10+
# Title and description
11+
st.markdown("<h1 class='main-header'>🐙 GitHub MCP Agent</h1>", unsafe_allow_html=True)
12+
st.markdown(
13+
"Explore GitHub repositories with natural language using the Model Context Protocol"
14+
)
15+
16+
# Setup sidebar for API key
17+
with st.sidebar:
18+
st.header("🔑 Authentication")
19+
github_token = st.text_input(
20+
"GitHub Token",
21+
type="password",
22+
help="Create a token with repo scope at github.com/settings/tokens",
23+
)
24+
25+
if github_token:
26+
os.environ["GITHUB_TOKEN"] = github_token
27+
28+
st.markdown("---")
29+
st.markdown("### Example Queries")
30+
31+
st.markdown("**Issues**")
32+
st.markdown("- Show me issues by label")
33+
st.markdown("- What issues are being actively discussed?")
34+
35+
st.markdown("**Pull Requests**")
36+
st.markdown("- What PRs need review?")
37+
st.markdown("- Show me recent merged PRs")
38+
39+
st.markdown("**Repository**")
40+
st.markdown("- Show repository health metrics")
41+
st.markdown("- Show repository activity patterns")
42+
43+
st.markdown("---")
44+
st.caption(
45+
"Note: Always specify the repository in your query if not already selected in the main input."
46+
)
47+
48+
# Query input
49+
col1, col2 = st.columns([3, 1])
50+
with col1:
51+
repo = st.text_input("Repository", value="agno-agi/agno", help="Format: owner/repo")
52+
with col2:
53+
query_type = st.selectbox(
54+
"Query Type", ["Issues", "Pull Requests", "Repository Activity", "Custom"]
55+
)
56+
57+
# Create predefined queries based on type
58+
if query_type == "Issues":
59+
query_template = f"Find issues labeled as bugs in {repo}"
60+
elif query_type == "Pull Requests":
61+
query_template = f"Show me recent merged PRs in {repo}"
62+
elif query_type == "Repository Activity":
63+
query_template = f"Analyze code quality trends in {repo}"
64+
else:
65+
query_template = ""
66+
67+
query = st.text_area(
68+
"Your Query",
69+
value=query_template,
70+
placeholder="What would you like to know about this repository?",
71+
)
72+
73+
# Run button
74+
if st.button("🚀 Run Query", type="primary", use_container_width=True):
75+
if not github_token:
76+
st.error("Please enter your GitHub token in the sidebar")
77+
elif not query:
78+
st.error("Please enter a query")
79+
else:
80+
with st.spinner("Analyzing GitHub repository..."):
81+
# Ensure the repository is explicitly mentioned in the query
82+
if repo and repo not in query:
83+
full_query = f"{query} in {repo}"
84+
else:
85+
full_query = query
86+
87+
result = asyncio.run(run_github_agent(full_query))
88+
89+
# Display results in a nice container
90+
st.markdown("### Results")
91+
st.markdown(result)
92+
93+
# Display help text for first-time users
94+
if "result" not in locals():
95+
st.markdown(
96+
"""<div class='info-box'>
97+
<h4>How to use this app:</h4>
98+
<ol>
99+
<li>Enter your GitHub token in the sidebar</li>
100+
<li>Specify a repository (e.g., agno-agi/agno)</li>
101+
<li>Select a query type or write your own</li>
102+
<li>Click 'Run Query' to see results</li>
103+
</ol>
104+
<p><strong>Important Notes:</strong></p>
105+
<ul>
106+
<li>The Model Context Protocol (MCP) provides real-time access to GitHub repositories</li>
107+
<li>Queries work best when they focus on specific aspects like issues, PRs, or repository info</li>
108+
<li>More specific queries yield better results</li>
109+
<li>This app requires Node.js to be installed (for the npx command)</li>
110+
</ul>
111+
</div>""",
112+
unsafe_allow_html=True,
113+
)
114+
115+
# Footer
116+
st.markdown("---")
117+
st.write("Built with Streamlit, Agno, and Model Context Protocol ❤️")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
3+
############################################################################
4+
# Generate requirements.txt from requirements.in
5+
############################################################################
6+
7+
echo "Generating requirements.txt"
8+
9+
CURR_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10+
11+
UV_CUSTOM_COMPILE_COMMAND="./generate_requirements.sh" \
12+
uv pip compile ${CURR_DIR}/requirements.in --no-cache --upgrade -o ${CURR_DIR}/requirements.txt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
streamlit
2+
agno
3+
mcp
4+
openai
5+
asyncio

0 commit comments

Comments
 (0)