<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LumenX-MCP Interactive Structure</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
}
.card-container {
perspective: 1000px;
}
.card {
transition: transform 0.5s, box-shadow 0.5s;
transform-style: preserve-3d;
}
.card.is-flipped {
transform: rotateY(180deg);
}
.card .front, .card .back {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.card .back {
transform: rotateY(180deg);
}
.code-block {
background-color: #1E293B; /* slate-800 */
border-radius: 0.5rem;
padding: 1rem;
color: #E2E8F0; /* slate-200 */
font-family: 'Courier New', Courier, monospace;
font-size: 0.875rem;
white-space: pre-wrap;
word-break: break-all;
}
</style>
</head>
<body class="bg-gray-900 text-gray-200">
<div class="container mx-auto p-4 md:p-8">
<header class="text-center mb-12">
<h1 class="text-4xl md:text-5xl font-bold text-white mb-2">LumenX-MCP</h1>
<p class="text-xl text-blue-300">Interactive Structure</p>
<p class="text-gray-400 mt-4 max-w-3xl mx-auto">
Explore the callable functions (Tools) and data objects (Resources) available in the LumenX Legal Spend MCP Server. Click on any card to see more details, including sample requests and responses.
</p>
</header>
<!-- Tools Section -->
<section class="mb-16">
<h2 class="text-3xl font-bold text-white mb-8 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 mr-3 text-green-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"/></svg>
Tools (Callable Functions)
</h2>
<div id="tools-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<!-- Tool cards will be injected here -->
</div>
</section>
<!-- Resources Section -->
<section>
<h2 class="text-3xl font-bold text-white mb-8 flex items-center">
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 mr-3 text-yellow-400" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4M4 7s0 0 0 0m16 0s0 0 0 0"/></svg>
Resources (Data Objects)
</h2>
<div id="resources-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<!-- Resource cards will be injected here -->
</div>
</section>
</div>
<script>
const mcpData = {
tools: [
{
name: "get_legal_spend_summary",
description: "Get aggregated spend data with filtering options.",
params: ["start_date", "end_date", "department", "practice_area", "vendor", "data_source"],
sampleRequest: `{
"tool": "get_legal_spend_summary",
"params": {
"start_date": "2024-01-01",
"end_date": "2024-03-31",
"department": "Legal"
}
}`,
sampleResponse: `{
"period": "2024-01-01 to 2024-03-31",
"total_amount": 450000.50,
"currency": "USD",
"record_count": 120,
"top_vendors": [...],
"by_department": {"Legal": 450000.50}
}`
},
{
name: "get_vendor_performance",
description: "Analyze performance metrics for a specific vendor.",
params: ["vendor_name", "start_date", "end_date", "include_benchmarks"],
sampleRequest: `{
"tool": "get_vendor_performance",
"params": {
"vendor_name": "Smith & Associates",
"start_date": "2024-01-01",
"end_date": "2024-06-30"
}
}`,
sampleResponse: `{
"vendor_name": "Smith & Associates",
"total_spend": 150000.0,
"invoice_count": 12,
"average_invoice_amount": 12500.0,
"spend_trend": {"trend": "stable", ...}
}`
},
{
name: "get_budget_vs_actual",
description: "Compare actual spending against budgeted amounts.",
params: ["department", "start_date", "end_date", "budget_amount"],
sampleRequest: `{
"tool": "get_budget_vs_actual",
"params": {
"department": "Compliance",
"start_date": "2024-01-01",
"end_date": "2024-03-31",
"budget_amount": 100000.0
}
}`,
sampleResponse: `{
"department": "Compliance",
"budget_analysis": {
"budget_amount": 100000.0,
"actual_spend": 85000.0,
"variance": -15000.0,
"status": "under_budget"
},
"recommendations": [...]
}`
},
{
name: "search_legal_transactions",
description: "Search for specific transactions across all data sources.",
params: ["search_term", "start_date", "end_date", "min_amount", "max_amount", "limit"],
sampleRequest: `{
"tool": "search_legal_transactions",
"params": {
"search_term": "acquisition",
"min_amount": 5000.0
}
}`,
sampleResponse: `[
{
"transaction_id": "INV-2024-001",
"date": "2024-01-15",
"vendor_name": "Smith & Associates",
"amount": 25000.0,
"description": "Due diligence for ABC Corp Acquisition"
},
...
]`
}
],
resources: [
{
name: "legal_vendors",
description: "Get a list of all legal vendors across all data sources.",
sampleResponse: `{
"vendors": [
{"id": "V1", "name": "Smith & Associates", "type": "Law Firm"},
{"id": "V2", "name": "Jones Legal", "type": "Law Firm"}
],
"total_count": 2,
"data_sources": ["legaltracker", "sap_erp"]
}`
},
{
name: "data_sources",
description: "Get the status and configuration of connected data sources.",
sampleResponse: `{
"data_sources": [
{"name": "legaltracker", "status": "active"},
{"name": "sap_erp", "status": "disconnected"}
],
"active_count": 1
}`
},
{
name: "spend_categories",
description: "Get available spend categories, practice areas, and departments.",
sampleResponse: `{
"expense_categories": ["Legal Services", "Expert Witness", ...],
"practice_areas": ["Corporate", "Litigation", ...],
"departments": ["Legal", "Compliance", "HR", ...]
}`
},
{
name: "spend_overview://recent",
description: "Get a high-level overview of spend activity from the last 30 days.",
sampleResponse: `{
"period": "Last 30 days...",
"total_spend": 125340.75,
"transaction_count": 42,
"active_vendors": 15,
"alerts": [{"type": "spike", "message": "Unusual spend..."}]
}`
}
]
};
function createCard(item, type) {
const isTool = type === 'tool';
const iconColor = isTool ? 'green' : 'yellow';
const iconSvg = isTool
? `<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"/></svg>`
: `<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 mr-2" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 7v10c0 2.21 3.582 4 8 4s8-1.79 8-4V7M4 7c0-2.21 3.582-4 8-4s8 1.79 8 4M4 7s0 0 0 0m16 0s0 0 0 0"/></svg>`;
const front = `
<div class="front absolute w-full h-full bg-gray-800 border border-gray-700 rounded-lg shadow-lg p-6 flex flex-col justify-between cursor-pointer hover:shadow-blue-500/20 hover:border-blue-500">
<div>
<h3 class="text-xl font-bold text-white flex items-center text-${iconColor}-400">${iconSvg} ${item.name}</h3>
<p class="text-gray-400 mt-2">${item.description}</p>
</div>
${isTool ? `
<div class="mt-4">
<h4 class="text-sm font-semibold text-gray-300 mb-2">Parameters:</h4>
<div class="flex flex-wrap gap-2">
${item.params.map(p => `<span class="bg-gray-700 text-blue-300 text-xs font-mono px-2 py-1 rounded">${p}</span>`).join('')}
</div>
</div>
` : ''}
<div class="text-center text-xs text-gray-500 mt-4">Click to flip for sample</div>
</div>
`;
const back = `
<div class="back absolute w-full h-full bg-gray-800 border border-gray-600 rounded-lg shadow-lg p-6 flex flex-col justify-start cursor-pointer">
<h3 class="text-xl font-bold text-white mb-4 flex items-center text-${iconColor}-400">${iconSvg} ${item.name}</h3>
${isTool ? `<h4 class="text-md font-semibold text-gray-300 mb-2">Sample Request:</h4><div class="code-block mb-4">${item.sampleRequest}</div>` : ''}
<h4 class="text-md font-semibold text-gray-300 mb-2">Sample Response:</h4>
<div class="code-block overflow-auto">${item.sampleResponse}</div>
<div class="text-center text-xs text-gray-500 mt-auto">Click to flip back</div>
</div>
`;
const cardContainer = document.createElement('div');
cardContainer.className = 'card-container h-full';
cardContainer.innerHTML = `<div class="card relative w-full h-full">${front}${back}</div>`;
cardContainer.querySelector('.card').addEventListener('click', function() {
this.classList.toggle('is-flipped');
});
return cardContainer;
}
function renderCards() {
const toolsGrid = document.getElementById('tools-grid');
const resourcesGrid = document.getElementById('resources-grid');
mcpData.tools.forEach(tool => {
const cardWrapper = document.createElement('div');
cardWrapper.style.minHeight = '280px';
const card = createCard(tool, 'tool');
cardWrapper.appendChild(card);
toolsGrid.appendChild(cardWrapper);
});
mcpData.resources.forEach(resource => {
const cardWrapper = document.createElement('div');
cardWrapper.style.minHeight = '280px';
const card = createCard(resource, 'resource');
cardWrapper.appendChild(card);
resourcesGrid.appendChild(cardWrapper);
});
}
document.addEventListener('DOMContentLoaded', renderCards);
</script>
</body>
</html>