Skip to content

Commit f8b8b5d

Browse files
committed
Added multiple examples of mcp servers
1 parent e37d661 commit f8b8b5d

File tree

2 files changed

+511
-0
lines changed

2 files changed

+511
-0
lines changed
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
"""
2+
Code Review Assistant - MCP Integration Example
3+
4+
This example demonstrates how to integrate multiple MCP providers with AI to create
5+
a practical code review assistant. It shows:
6+
7+
1. GitHub MCP - Fetch code from repositories
8+
2. OpenAI Integration - AI-powered code analysis
9+
3. Browserbase MCP - Check repository documentation
10+
4. Filesystem MCP - Save review reports
11+
12+
Usage:
13+
python code_review_assistant.py
14+
15+
Requirements:
16+
- OpenAI API key (set OPENAI_API_KEY environment variable)
17+
- GitHub token (set GITHUB_TOKEN environment variable)
18+
- Browserbase credentials (set BROWSERBASE_API_KEY and BROWSERBASE_PROJECT_ID)
19+
"""
20+
21+
import asyncio
22+
import logging
23+
import os
24+
from python_a2a.client.llm import OpenAIA2AClient
25+
from python_a2a.mcp.providers import GitHubMCPServer, BrowserbaseMCPServer, FilesystemMCPServer
26+
from python_a2a import create_text_message
27+
28+
# Hide INFO logs for cleaner output
29+
logging.getLogger('python_a2a').setLevel(logging.ERROR)
30+
logging.getLogger('httpx').setLevel(logging.WARNING)
31+
32+
class CodeReviewAssistant:
33+
"""AI-powered code review assistant using multiple MCP providers"""
34+
35+
def __init__(self, openai_api_key=None, github_token=None, browserbase_api_key=None, browserbase_project_id=None):
36+
# Get credentials from environment variables or parameters
37+
openai_key = openai_api_key or os.getenv('OPENAI_API_KEY')
38+
github_token = github_token or os.getenv('GITHUB_TOKEN')
39+
browserbase_key = browserbase_api_key or os.getenv('BROWSERBASE_API_KEY')
40+
browserbase_project = browserbase_project_id or os.getenv('BROWSERBASE_PROJECT_ID')
41+
42+
if not openai_key:
43+
raise ValueError("OpenAI API key required. Set OPENAI_API_KEY environment variable or pass openai_api_key parameter.")
44+
if not github_token:
45+
raise ValueError("GitHub token required. Set GITHUB_TOKEN environment variable or pass github_token parameter.")
46+
if not browserbase_key or not browserbase_project:
47+
raise ValueError("Browserbase credentials required. Set BROWSERBASE_API_KEY and BROWSERBASE_PROJECT_ID environment variables.")
48+
49+
# AI reviewer
50+
self.ai = OpenAIA2AClient(api_key=openai_key)
51+
52+
# MCP providers - clean and simple
53+
self.github = GitHubMCPServer(token=github_token)
54+
self.browser = BrowserbaseMCPServer(
55+
api_key=browserbase_key,
56+
project_id=browserbase_project
57+
)
58+
# Allow filesystem access to current directory
59+
current_dir = os.getcwd()
60+
self.files = FilesystemMCPServer(allowed_directories=[current_dir])
61+
62+
async def review_code(self, repo_owner, repo_name, file_path):
63+
"""Review a specific file in a repository"""
64+
65+
async with self.github, self.browser, self.files:
66+
67+
# 1. GitHub MCP: Get code from repository
68+
print(f"🐙 GitHub MCP: Fetching {file_path} from {repo_owner}/{repo_name}")
69+
code = await self.github.get_file_contents(repo_owner, repo_name, file_path)
70+
print(f" ✓ Retrieved {len(str(code))} characters of code")
71+
72+
# 2. OpenAI: AI reviews the code
73+
print("🤖 OpenAI: Analyzing code quality...")
74+
review_message = create_text_message(f"""
75+
Review this code for quality, bugs, and improvements:
76+
77+
{code}
78+
79+
Give me 3 key points: issues, suggestions, rating (1-10).
80+
""")
81+
response = self.ai.send_message(review_message)
82+
review = response.content.text
83+
print(f" ✓ AI analysis completed")
84+
85+
# 3. Browserbase MCP: Check repository documentation
86+
print("🌐 Browserbase MCP: Checking repository documentation...")
87+
await self.browser.navigate(f"https://github.com/{repo_owner}/{repo_name}")
88+
await self.browser.wait_time(1)
89+
readme_text = await self.browser.get_text("article")
90+
has_docs = "readme" in readme_text.lower()
91+
print(f" ✓ Documentation {'found' if has_docs else 'not found'}")
92+
93+
# 4. Filesystem MCP: Save review report to current directory
94+
print("📁 Filesystem MCP: Saving review report...")
95+
report = f"""# Code Review: {repo_owner}/{repo_name}/{file_path}
96+
97+
## AI Review
98+
{review}
99+
100+
## Documentation Status
101+
{'✅ Has README documentation' if has_docs else '❌ Missing documentation'}
102+
103+
## Summary
104+
- Repository: {repo_owner}/{repo_name}
105+
- File reviewed: {file_path}
106+
- Code length: {len(str(code))} characters
107+
- Documentation: {'Present' if has_docs else 'Missing'}
108+
"""
109+
110+
# Save to current directory for easy access
111+
current_dir = os.getcwd()
112+
report_filename = f"review_{repo_name}_{file_path.replace('/', '_')}.md"
113+
report_path = f"{current_dir}/{report_filename}"
114+
await self.files.write_file(report_path, report)
115+
print(f" ✓ Report saved as: {report_filename} (in current directory)")
116+
117+
return {
118+
"repository": f"{repo_owner}/{repo_name}",
119+
"file_reviewed": file_path,
120+
"code_length": len(str(code)),
121+
"ai_rating": "Analysis completed",
122+
"documentation_status": "Present" if has_docs else "Missing",
123+
"report_file": report_filename
124+
}
125+
126+
# Demo
127+
async def demo():
128+
"""Demo the code review assistant"""
129+
print("🚀 Code Review Assistant Demo")
130+
print("=" * 50)
131+
132+
try:
133+
assistant = CodeReviewAssistant()
134+
135+
# Review a file from a public repository
136+
result = await assistant.review_code("octocat", "Hello-World", "README")
137+
138+
print("\n📊 Review Summary:")
139+
print("=" * 30)
140+
print(f"Repository: {result['repository']}")
141+
print(f"File: {result['file_reviewed']}")
142+
print(f"Code length: {result['code_length']} characters")
143+
print(f"Documentation: {result['documentation_status']}")
144+
print(f"Report: {result['report_file']}")
145+
146+
print(f"\n✅ Complete! All MCP providers worked together seamlessly.")
147+
print(f"📄 Check {result['report_file']} for the full AI analysis.")
148+
149+
except ValueError as e:
150+
print(f"❌ Configuration error: {e}")
151+
print("\n📋 Setup required:")
152+
print("export OPENAI_API_KEY='your-openai-key'")
153+
print("export GITHUB_TOKEN='your-github-token'")
154+
print("export BROWSERBASE_API_KEY='your-browserbase-key'")
155+
print("export BROWSERBASE_PROJECT_ID='your-project-id'")
156+
157+
except Exception as e:
158+
print(f"❌ Error: {e}")
159+
160+
if __name__ == "__main__":
161+
asyncio.run(demo())

0 commit comments

Comments
 (0)