RAG × MCP橋渡しサーバーの作成
Python - RAG-MCPブリッジ
# rag_mcp_bridge.py
import mcp
from openai import OpenAI
import pinecone
import os
# 初期化
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
pinecone.init(
api_key=os.environ.get("PINECONE_API_KEY"),
environment=os.environ.get("PINECONE_ENVIRONMENT")
)
index = pinecone.Index("devin-code-index")
@mcp.tool()
def search_codebase(query: str, top_k: int = 5) -> str:
"""
コードベースからクエリに関連するコードを検索します。
Args:
query: 検索クエリ文字列
top_k: 返す結果の数
Returns:
関連コードの説明とコード片
"""
# クエリをエンベディングに変換
response = client.embeddings.create(
input=query,
model="text-embedding-3-small"
)
query_embedding = response.data[0].embedding
# Pineconeで類似検索を実行
results = index.query(
vector=query_embedding,
top_k=top_k,
include_metadata=True
)
# 結果を整形
output = f"## 「{query}」に関連するコード\n\n"
for i, match in enumerate(results['matches'], 1):
metadata = match['metadata']
file_path = metadata['file_path']
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# 大きなファイルの場合は、該当チャンク部分だけを抽出
if metadata.get('total_chunks', 1) > 1:
chunk_idx = metadata.get('chunk_idx', 0)
total_chunks = metadata.get('total_chunks', 1)
chunk_size = len(content) // total_chunks
start_pos = chunk_idx * chunk_size
end_pos = start_pos + chunk_size
content = content[start_pos:end_pos]
output += f"### {i}. {os.path.basename(file_path)} (類似度: {match['score']:.2f})\n"
output += f"パス: {file_path}\n"
output += f"言語: {metadata.get('language', '不明')}\n"
output += f"```{metadata.get('language', '')}\n{content[:1500]}... (省略)\n```\n\n"
except Exception as e:
output += f"### {i}. {os.path.basename(file_path)} (エラー)\n"
output += f"ファイルの読み込み中にエラーが発生しました: {e}\n\n"
return output
@mcp.tool()
def generate_devin_prompt(query: str, task_type: str = "implementation") -> str:
"""
クエリに基づいて、RAGを活用したDevin用のプロンプトを生成します。
Args:
query: 検索クエリとタスクの説明
task_type: タスクの種類 (implementation, bug_fix, refactoring, test)
Returns:
Devin用のプロンプト
"""
# コードベース検索
code_context = search_codebase(query)
# タスクタイプに基づいたテンプレートの選択
templates = {
"implementation": """
@Devin
【タスク】新機能の実装
【機能概要】
{query}
【参考コード】
{code_context}
上記のコードを参考にして、同じスタイルと設計パターンに沿った実装をお願いします。
""",
"bug_fix": """
@Devin
【タスク】バグ修正
【バグの概要】
{query}
【関連コード】
{code_context}
上記のコードを参考に、バグの原因を特定して修正してください。
""",
"refactoring": """
@Devin
【タスク】コードリファクタリング
【リファクタリングの目的】
{query}
【対象コード】
{code_context}
上記のコードをリファクタリングして、保守性と可読性を向上させてください。
""",
"test": """
@Devin
【タスク】テストコードの作成
【テスト対象】
{query}
【関連コード】
{code_context}
上記のコードを参考に、適切なテストコードを作成してください。
"""
}
# 指定されたタスクタイプのテンプレートを使用
if task_type in templates:
prompt_template = templates[task_type]
else:
prompt_template = templates["implementation"] # デフォルト
# テンプレートにクエリとコードコンテキストを挿入
prompt = prompt_template.format(query=query, code_context=code_context)
return prompt
if __name__ == "__main__":
mcp.run(transport="stdio")