File size: 4,034 Bytes
363cda9 d3e5126 363cda9 d3e5126 363cda9 d3e5126 363cda9 d3e5126 363cda9 d3e5126 363cda9 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
import asyncio
import os
import shutil
from pathlib import Path
from pydantic_core import ValidationError
from langchain_core.tools import tool
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import create_agent
from langchain_openai import ChatOpenAI
from src.mcp_servers.examples.gmail.settings import GMailSettings
from src.prompts import get_prompt
# Attempt to find uv executable
#-----------------------------------------------------------------------------
# `Dockerfile.supervisor` installs uv in the base image in `/usr/local/bin/uv`
# `which` attempts to find it in the system PATH and returns the full path to it.
UV_PATH = shutil.which("uv")
SYSTEM_PROMPT = get_prompt(
template_name="GMail",
latest_version=True
)
@tool
def gmail_agent(query: str) -> str:
"""
A tool that acts as a Gmail agent.
It can read, search, label, and send emails using the Gmail MCP server.
Args:
query (str): The natural language request (e.g., "Send an email to X", "Check unread emails").
Returns:
str: The natural language response from the agent confirming the action or providing the requested information.
Example output:
"I have successfully sent the email to X with the subject 'Interview Invitation'."
"""
if not UV_PATH:
return "β Error: 'uv' executable not found. Please ensure uv is installed and in the system PATH."
# Validate required Gmail settings before proceeding
creds_env = os.getenv("GMAIL_CREDS_JSON")
token_env = os.getenv("GMAIL_TOKEN_JSON")
if not creds_env or not token_env:
return "β Gmail credentials not configured. Set GMAIL_CREDS_JSON and GMAIL_TOKEN_JSON environment variables."
try:
import asyncio
async def _run_async():
# Load settings
try:
# Pass env values directly to avoid reliance on env file loading
settings = GMailSettings(creds_json=creds_env, token_json=token_env)
except ValidationError as ve:
return f"β Gmail settings invalid: {ve}"
except Exception as e:
return f"β Gmail settings error: {e}"
creds_path, token_path = settings.materialize_files()
# Initialize model
model = ChatOpenAI(model="gpt-4o", temperature=0)
# Connect to MCP server
client = MultiServerMCPClient(
{
"gmail": {
"command": UV_PATH,
"args": [
"--directory", str(settings.gmail_mcp_dir),
"run", "gmail",
"--creds-file-path", str(creds_path),
"--token-path", str(token_path),
],
"transport": "stdio",
}
}
)
# Fetch tools
try:
tools = await client.get_tools()
except Exception as e:
return f"β Failed to connect to Gmail MCP server: {str(e)}"
if not tools:
return "β No tools available from Gmail MCP server."
# Create agent
agent = create_agent(model, tools)
# Run agent
result = await agent.ainvoke({
"messages": [
{
"role": "system",
"content": SYSTEM_PROMPT,
},
{
"role": "user",
"content": query,
},
]
})
# Extract result
output = result["messages"][-1].content
return output
return asyncio.run(_run_async())
except Exception as e:
import traceback
return f"β Error in gmail_agent: {str(e)}\n{traceback.format_exc()}"
|