financial_mcp_interface.html•19.9 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Financial MCP Server Interface</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: rgba(255, 255, 255, 0.95);
border-radius: 20px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
backdrop-filter: blur(10px);
overflow: hidden;
}
.header {
background: linear-gradient(135deg, #2c3e50, #3498db);
color: white;
padding: 30px;
text-align: center;
}
.header h1 {
font-size: 2.5rem;
margin-bottom: 10px;
font-weight: 300;
}
.header p {
opacity: 0.9;
font-size: 1.1rem;
}
.main-content {
padding: 30px;
}
.controls {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.control-group {
background: #f8f9fa;
padding: 25px;
border-radius: 15px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.control-group:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.12);
}
.control-group h3 {
color: #2c3e50;
margin-bottom: 15px;
font-size: 1.3rem;
font-weight: 600;
}
.input-group {
margin-bottom: 15px;
}
.input-group label {
display: block;
margin-bottom: 5px;
color: #555;
font-weight: 500;
}
.input-group input,
.input-group select {
width: 100%;
padding: 12px;
border: 2px solid #e1e5e9;
border-radius: 8px;
font-size: 1rem;
transition: border-color 0.3s ease;
}
.input-group input:focus,
.input-group select:focus {
outline: none;
border-color: #3498db;
}
.btn {
background: linear-gradient(135deg, #3498db, #2980b9);
color: white;
border: none;
padding: 12px 25px;
border-radius: 8px;
cursor: pointer;
font-size: 1rem;
font-weight: 500;
transition: all 0.3s ease;
width: 100%;
margin-top: 10px;
}
.btn:hover {
background: linear-gradient(135deg, #2980b9, #3498db);
transform: translateY(-1px);
box-shadow: 0 5px 15px rgba(52, 152, 219, 0.3);
}
.btn:active {
transform: translateY(0);
}
.btn.secondary {
background: linear-gradient(135deg, #95a5a6, #7f8c8d);
}
.btn.secondary:hover {
background: linear-gradient(135deg, #7f8c8d, #95a5a6);
}
.quick-actions {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-bottom: 20px;
}
.quick-btn {
background: rgba(52, 152, 219, 0.1);
color: #3498db;
border: 2px solid #3498db;
padding: 8px 16px;
border-radius: 20px;
cursor: pointer;
font-size: 0.9rem;
transition: all 0.3s ease;
}
.quick-btn:hover {
background: #3498db;
color: white;
}
.results {
background: #f8f9fa;
border-radius: 15px;
padding: 25px;
margin-top: 20px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
}
.results h3 {
color: #2c3e50;
margin-bottom: 15px;
font-size: 1.4rem;
}
.results-content {
background: white;
padding: 20px;
border-radius: 10px;
border-left: 4px solid #3498db;
font-family: 'Courier New', monospace;
white-space: pre-wrap;
max-height: 400px;
overflow-y: auto;
line-height: 1.4;
}
.loading {
display: none;
text-align: center;
padding: 20px;
}
.loading::after {
content: '';
display: inline-block;
width: 20px;
height: 20px;
border: 3px solid #f3f3f3;
border-top: 3px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.error {
background: #e74c3c;
color: white;
padding: 15px;
border-radius: 8px;
margin: 10px 0;
}
.success {
background: #27ae60;
color: white;
padding: 15px;
border-radius: 8px;
margin: 10px 0;
}
.status-bar {
background: #2c3e50;
color: white;
padding: 10px 30px;
font-size: 0.9rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.status-indicator {
display: flex;
align-items: center;
gap: 8px;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: #27ae60;
animation: pulse 2s infinite;
}
@keyframes pulse {
0% { opacity: 1; }
50% { opacity: 0.5; }
100% { opacity: 1; }
}
@media (max-width: 768px) {
.container {
margin: 10px;
border-radius: 15px;
}
.controls {
grid-template-columns: 1fr;
}
.header h1 {
font-size: 2rem;
}
.quick-actions {
justify-content: center;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>📈 Financial MCP Server</h1>
<p>Real-time Financial Data Analysis Interface</p>
</div>
<div class="status-bar">
<div class="status-indicator">
<div class="status-dot"></div>
<span>Server Status: Connected</span>
</div>
<div>
<span id="serverUrl">http://localhost:3001</span>
</div>
</div>
<div class="main-content">
<!-- Quick Actions -->
<div class="quick-actions">
<button class="quick-btn" onclick="getMarketOverview()">📊 Market Overview</button>
<button class="quick-btn" onclick="getEarningsCalendar()">📅 Earnings Calendar</button>
<button class="quick-btn" onclick="getAnalystChanges()">🔍 Analyst Changes</button>
<button class="quick-btn" onclick="loadPortfolio()">💼 Load Portfolio</button>
<button class="quick-btn" onclick="testConnection()">🔧 Test Connection</button>
</div>
<div class="controls">
<!-- Stock Analysis -->
<div class="control-group">
<h3>🔍 Stock Analysis</h3>
<div class="input-group">
<label for="stockSymbol">Stock Symbol:</label>
<input type="text" id="stockSymbol" placeholder="e.g., AAPL, GOOGL, MSFT" value="AAPL">
</div>
<button class="btn" onclick="analyzeStock()">Get Stock Info</button>
<button class="btn secondary" onclick="generateChart()">Generate MACD Chart</button>
</div>
<!-- Portfolio Management -->
<div class="control-group">
<h3>💼 Portfolio Management</h3>
<div class="input-group">
<label for="portfolioName">Portfolio Name:</label>
<input type="text" id="portfolioName" placeholder="e.g., tech_stocks, dividend_portfolio">
</div>
<div class="input-group">
<label for="performancePeriod">Performance Period:</label>
<select id="performancePeriod">
<option value="1d">1 Day</option>
<option value="5d">5 Days</option>
<option value="1mo" selected>1 Month</option>
<option value="3mo">3 Months</option>
<option value="6mo">6 Months</option>
<option value="1y">1 Year</option>
</select>
</div>
<button class="btn" onclick="analyzePortfolio()">Analyze Portfolio</button>
<button class="btn secondary" onclick="getPortfolioPerformance()">Get Performance</button>
</div>
<!-- Market Research -->
<div class="control-group">
<h3>📈 Market Research</h3>
<div class="input-group">
<label for="daysAhead">Earnings Days Ahead:</label>
<select id="daysAhead">
<option value="3">3 Days</option>
<option value="7" selected>7 Days</option>
<option value="14">14 Days</option>
<option value="30">30 Days</option>
</select>
</div>
<div class="input-group">
<label for="daysBack">Analyst Changes Days Back:</label>
<select id="daysBack">
<option value="3">3 Days</option>
<option value="7" selected>7 Days</option>
<option value="14">14 Days</option>
<option value="30">30 Days</option>
</select>
</div>
<button class="btn" onclick="getEarningsCalendar()">Get Earnings</button>
<button class="btn secondary" onclick="getAnalystChanges()">Get Analyst Changes</button>
</div>
</div>
<!-- Results Section -->
<div class="results">
<h3>📊 Results</h3>
<div class="loading" id="loading">Loading...</div>
<div class="results-content" id="results">
Ready to analyze financial data! 🚀
Your MCP server is running and ready to provide real-time financial data.
Click any button above to get started.
✅ Market Overview - Get current market indices
✅ Stock Analysis - Analyze individual stocks
✅ Portfolio Management - Track your investments
✅ Earnings Calendar - Upcoming earnings announcements
✅ Analyst Research - Recent analyst changes
Server: http://localhost:3001
Status: Connected and Ready
</div>
</div>
</div>
</div>
<script>
// Configuration
const MCP_SERVER_URL = 'http://localhost:3001';
// Update the server URL display
document.getElementById('serverUrl').textContent = MCP_SERVER_URL;
// Utility functions
function showLoading() {
document.getElementById('loading').style.display = 'block';
document.getElementById('results').style.opacity = '0.5';
}
function hideLoading() {
document.getElementById('loading').style.display = 'none';
document.getElementById('results').style.opacity = '1';
}
function displayResults(data, title = 'Results') {
hideLoading();
const resultsDiv = document.getElementById('results');
// Format the data nicely
let formattedData;
if (data.content && data.content[0] && data.content[0].text) {
// Extract the actual data from MCP response format
try {
const parsedData = JSON.parse(data.content[0].text);
formattedData = JSON.stringify(parsedData, null, 2);
} catch (e) {
formattedData = data.content[0].text;
}
} else {
formattedData = JSON.stringify(data, null, 2);
}
resultsDiv.innerHTML = `<strong>✅ ${title}</strong>\n\n${formattedData}`;
}
function displayError(error) {
hideLoading();
const resultsDiv = document.getElementById('results');
resultsDiv.innerHTML = `<div class="error">❌ Error: ${error.message || error}</div>`;
}
// API calls
async function callMCPServer(tool, parameters = {}) {
try {
showLoading();
const response = await fetch(`${MCP_SERVER_URL}/tools/${tool}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(parameters)
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (error) {
throw error;
}
}
// Test connection
async function testConnection() {
try {
showLoading();
const response = await fetch(`${MCP_SERVER_URL}/health`);
const data = await response.json();
displayResults(data, '🔧 Connection Test');
} catch (error) {
displayError(error);
}
}
// Main functions
async function getMarketOverview() {
try {
const data = await callMCPServer('get_market_overview');
displayResults(data, '📊 Market Overview');
} catch (error) {
displayError(error);
}
}
async function analyzeStock() {
const symbol = document.getElementById('stockSymbol').value;
if (!symbol) {
displayError(new Error('Please enter a stock symbol'));
return;
}
try {
const data = await callMCPServer('get_stock_info', { symbol: symbol.toUpperCase() });
displayResults(data, `🔍 Analysis for ${symbol.toUpperCase()}`);
} catch (error) {
displayError(error);
}
}
async function generateChart() {
const symbol = document.getElementById('stockSymbol').value;
if (!symbol) {
displayError(new Error('Please enter a stock symbol'));
return;
}
try {
const data = await callMCPServer('generate_macd_chart', {
symbol: symbol.toUpperCase(),
period: '6mo'
});
displayResults(data, `📈 MACD Chart for ${symbol.toUpperCase()}`);
} catch (error) {
displayError(error);
}
}
async function loadPortfolio() {
try {
const data = await callMCPServer('load_portfolio');
displayResults(data, '💼 Portfolio Data');
} catch (error) {
displayError(error);
}
}
async function analyzePortfolio() {
const portfolioName = document.getElementById('portfolioName').value;
if (!portfolioName) {
displayError(new Error('Please enter a portfolio name'));
return;
}
try {
const data = await callMCPServer('analyze_portfolio', {
portfolio_name: portfolioName
});
displayResults(data, `💼 Analysis for ${portfolioName}`);
} catch (error) {
displayError(error);
}
}
async function getPortfolioPerformance() {
const portfolioName = document.getElementById('portfolioName').value;
const period = document.getElementById('performancePeriod').value;
try {
const parameters = { period };
if (portfolioName) {
parameters.portfolio_name = portfolioName;
}
const data = await callMCPServer('portfolio_performance', parameters);
displayResults(data, `📊 Portfolio Performance (${period})`);
} catch (error) {
displayError(error);
}
}
async function getEarningsCalendar() {
const daysAhead = document.getElementById('daysAhead').value;
try {
const data = await callMCPServer('get_earnings_calendar', {
days_ahead: parseInt(daysAhead)
});
displayResults(data, `📅 Upcoming Earnings (${daysAhead} days)`);
} catch (error) {
displayError(error);
}
}
async function getAnalystChanges() {
const daysBack = document.getElementById('daysBack').value;
const symbol = document.getElementById('stockSymbol').value;
try {
const parameters = { days_back: parseInt(daysBack) };
if (symbol) {
parameters.symbol = symbol.toUpperCase();
}
const data = await callMCPServer('get_analyst_changes', parameters);
displayResults(data, `🔍 Analyst Changes (${daysBack} days back)`);
} catch (error) {
displayError(error);
}
}
// Initialize
document.addEventListener('DOMContentLoaded', function() {
// Add enter key support
document.getElementById('stockSymbol').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
analyzeStock();
}
});
document.getElementById('portfolioName').addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
analyzePortfolio();
}
});
console.log('🚀 Financial MCP Interface loaded successfully!');
console.log(`📡 Server: ${MCP_SERVER_URL}`);
// Test connection on load
setTimeout(testConnection, 1000);
});
</script>
</body>
</html>