231 lines
7.5 KiB
Python
231 lines
7.5 KiB
Python
import streamlit as st
|
|
import asyncio
|
|
import os
|
|
import json
|
|
from dotenv import load_dotenv
|
|
# from langchain_ollama import ChatOllama
|
|
from langchain_openai import ChatOpenAI
|
|
from mcp_use import MCPAgent, MCPClient
|
|
import mcp_use
|
|
import warnings
|
|
import base64
|
|
|
|
# Suppress warnings
|
|
warnings.filterwarnings("ignore")
|
|
mcp_use.set_debug(0)
|
|
|
|
# Load environment variables
|
|
load_dotenv()
|
|
|
|
# Page configuration
|
|
st.set_page_config(
|
|
page_title="MCP-powered Perplexity Clone",
|
|
page_icon="🤖",
|
|
layout="wide",
|
|
initial_sidebar_state="expanded"
|
|
)
|
|
|
|
# Initialize session state
|
|
if "messages" not in st.session_state:
|
|
st.session_state.messages = []
|
|
|
|
if "mcp_client" not in st.session_state:
|
|
st.session_state.mcp_client = None
|
|
|
|
if "agent" not in st.session_state:
|
|
st.session_state.agent = None
|
|
|
|
def reset_chat():
|
|
st.session_state.messages = []
|
|
st.session_state.mcp_client = None
|
|
st.session_state.agent = None
|
|
|
|
def create_mcp_client(config_dict):
|
|
"""Create MCPClient from configuration dictionary."""
|
|
try:
|
|
client = MCPClient.from_dict(config_dict)
|
|
return client
|
|
except Exception as e:
|
|
st.error(f"Error creating MCP client: {str(e)}")
|
|
return None
|
|
|
|
def create_agent(client):
|
|
"""Create MCPAgent with the client."""
|
|
try:
|
|
# Create LLM - you can switch between Ollama and OpenAI
|
|
llm = ChatOpenAI(model="gpt-4o")
|
|
# llm = ChatOllama(model="qwen3:1.7b")
|
|
|
|
agent = MCPAgent(llm=llm, client=client, max_steps=100)
|
|
return agent
|
|
except Exception as e:
|
|
st.error(f"Error creating agent: {str(e)}")
|
|
return None
|
|
|
|
async def run_agent_query(agent, query):
|
|
"""Run a query through the MCP agent."""
|
|
try:
|
|
result = await agent.run(query)
|
|
return result
|
|
except Exception as e:
|
|
return f"Error running query: {str(e)}"
|
|
|
|
# Main title
|
|
st.markdown("""
|
|
# 100% local Ultimate AI Assistant using mcp-use
|
|
""", unsafe_allow_html=True)
|
|
|
|
st.markdown("Configure your MCP servers and chat with them using natural language!")
|
|
|
|
# Sidebar for configuration
|
|
with st.sidebar:
|
|
st.header("MCP Configuration")
|
|
|
|
# Configuration text area
|
|
config_text = st.text_area(
|
|
"Enter MCP Configuration (JSON)",
|
|
height=400,
|
|
placeholder='''{
|
|
"mcpServers": {
|
|
"stagehand": {
|
|
"command": "node",
|
|
"args": ["/path/to/mcp-server-browserbase/stagehand/dist/index.js"],
|
|
"env": {
|
|
"OPENAI_API_KEY": "your-api-key",
|
|
"LOCAL_CDP_URL": "http://localhost:9222"
|
|
}
|
|
}
|
|
}
|
|
}''',
|
|
help="Enter your MCP server configuration in JSON format"
|
|
)
|
|
|
|
# Load example configuration
|
|
if st.button("Load Example Config"):
|
|
example_config = {
|
|
"mcpServers": {
|
|
"stagehand": {
|
|
"command": "node",
|
|
"args": ["/path/to/mcp-server-browserbase/stagehand/dist/index.js"],
|
|
"env": {
|
|
"OPENAI_API_KEY": os.getenv("OPENAI_API_KEY"),
|
|
"LOCAL_CDP_URL": "http://localhost:9222",
|
|
"DOWNLOADS_DIR": "/path/to/downloads/stagehand"
|
|
}
|
|
},
|
|
"mcp-server-firecrawl": {
|
|
"command": "npx",
|
|
"args": ["-y", "firecrawl-mcp"],
|
|
"env": {
|
|
"FIRECRAWL_API_KEY": os.getenv("FIRECRAWL_API_KEY")
|
|
}
|
|
},
|
|
"ragie": {
|
|
"command": "npx",
|
|
"args": ["-y", "@ragieai/mcp-server", "--partition", "default"],
|
|
"env": {
|
|
"RAGIE_API_KEY": os.getenv("RAGIE_API_KEY")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
st.session_state.example_config = json.dumps(example_config, indent=2)
|
|
st.rerun()
|
|
|
|
# Display example config if loaded
|
|
if 'example_config' in st.session_state:
|
|
st.text_area("Example Configuration", st.session_state.example_config, height=200, disabled=True)
|
|
|
|
st.divider()
|
|
|
|
# Activate configuration button
|
|
if st.button("Activate Configuration", type="primary"):
|
|
if config_text.strip():
|
|
try:
|
|
# Parse JSON configuration
|
|
config_dict = json.loads(config_text)
|
|
|
|
# Create MCP client
|
|
client = create_mcp_client(config_dict)
|
|
if client:
|
|
st.session_state.mcp_client = client
|
|
|
|
# Create agent
|
|
agent = create_agent(client)
|
|
if agent:
|
|
st.session_state.agent = agent
|
|
st.success("✅ Configuration activated successfully!")
|
|
|
|
# Show available tools
|
|
try:
|
|
tools_info = "Available MCP tools:\n"
|
|
for server_name, server_info in config_dict.get("mcpServers", {}).items():
|
|
tools_info += f"- {server_name}\n"
|
|
st.info(tools_info)
|
|
except Exception as e:
|
|
st.warning(f"Could not display tools info: {str(e)}")
|
|
else:
|
|
st.error("Failed to create agent")
|
|
else:
|
|
st.error("Failed to create MCP client")
|
|
except json.JSONDecodeError as e:
|
|
st.error(f"Invalid JSON configuration: {str(e)}")
|
|
except Exception as e:
|
|
st.error(f"Error activating configuration: {str(e)}")
|
|
else:
|
|
st.warning("Please enter a configuration first")
|
|
|
|
# Clear button
|
|
if st.button("Clear Chat & Config"):
|
|
reset_chat()
|
|
st.rerun()
|
|
|
|
# Status indicator
|
|
st.divider()
|
|
st.subheader("Status")
|
|
if st.session_state.mcp_client and st.session_state.agent:
|
|
st.success("✅ MCP Client Active")
|
|
st.success("✅ Agent Ready")
|
|
else:
|
|
st.warning("⚠️ Configuration not activated")
|
|
|
|
# Main chat interface
|
|
|
|
|
|
# Display chat messages
|
|
for message in st.session_state.messages:
|
|
with st.chat_message(message["role"]):
|
|
st.markdown(message["content"])
|
|
|
|
# Chat input
|
|
if prompt := st.chat_input("Ask about your MCP tools..."):
|
|
# Add user message to chat
|
|
st.session_state.messages.append({"role": "user", "content": prompt})
|
|
with st.chat_message("user"):
|
|
st.markdown(prompt)
|
|
|
|
# Check if agent is available
|
|
if not st.session_state.agent:
|
|
with st.chat_message("assistant"):
|
|
st.error("Please activate the MCP configuration first!")
|
|
else:
|
|
with st.chat_message("assistant"):
|
|
with st.spinner("Processing your request..."):
|
|
try:
|
|
# Run the query asynchronously
|
|
loop = asyncio.new_event_loop()
|
|
asyncio.set_event_loop(loop)
|
|
result = loop.run_until_complete(run_agent_query(st.session_state.agent, prompt))
|
|
loop.close()
|
|
|
|
# Display result
|
|
st.markdown(result)
|
|
st.session_state.messages.append({"role": "assistant", "content": result})
|
|
except Exception as e:
|
|
error_msg = f"Error processing request: {str(e)}"
|
|
st.error(error_msg)
|
|
st.session_state.messages.append({"role": "assistant", "content": error_msg})
|
|
|
|
# Footer
|
|
st.markdown("---")
|
|
st.markdown("Built using mcp-use and Streamlit") |