<!doctype html>
<html lang="en" x-data="{ darkMode: JSON.parse(localStorage.getItem('darkMode') || 'false') }"
x-bind:class="darkMode ? 'dark' : ''" x-init="$watch('darkMode', val => localStorage.setItem('darkMode', val))">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>MCP Gateway Admin</title>
<!-- Favicon -->
<link rel="icon" type="image/png" sizes="32x32" href="{{ root_path }}/static/favicon.ico" />
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
darkMode: 'class'
}
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.18/codemirror.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.18/mode/javascript/javascript.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js" defer></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="{{ root_path }}/static/admin.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.18/codemirror.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.18/theme/monokai.min.css" rel="stylesheet" />
<link href="{{ root_path }}/static/admin.css" rel="stylesheet" />
</head>
<body class="bg-gray-100 dark:bg-gray-900">
<div class="w-full max-w-screen-2xl mx-auto px-4 py-8">
<header class="mb-8">
<h1 class="text-3xl font-bold text-gray-800 dark:text-gray-200">
MCP Context Forge - Gateway Administration
</h1>
<p class="text-gray-600 dark:text-gray-400">
Manage tools, resources, prompts, servers, and federated gateways
(remote MCP servers)
<span class="mx-2 text-gray-400">|</span>
<a href="https://ibm.github.io/mcp-context-forge/" target="_blank"
class="text-indigo-600 dark:text-indigo-500 hover:underline"> Docs</a>
<span class="mx-2 text-gray-400">|</span>
<a href="https://github.com/IBM/mcp-context-forge" target="_blank"
class="text-indigo-600 dark:text-indigo-500 hover:underline">⭐ Star mcp-context-forge on GitHub</a>
</p>
</header>
<!-- Tabs -->
<div class="mb-8">
<div class="border-b border-gray-200">
<nav class="-mb-px flex space-x-8">
<a href="#catalog" id="tab-catalog"
class="tab-link border-indigo-500 text-indigo-600 dark:text-indigo-500 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">
Virtual Servers Catalog
</a>
<a href="#tools" id="tab-tools"
class="tab-link border-transparent text-gray-500 dark:text-gray-300 hover:text-gray-700 hover:border-gray-300 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">
Global Tools
</a>
<a href="#resources" id="tab-resources"
class="tab-link border-transparent text-gray-500 dark:text-gray-300 hover:text-gray-700 hover:border-gray-300 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">
Global Resources
</a>
<a href="#prompts" id="tab-prompts"
class="tab-link border-transparent text-gray-500 dark:text-gray-300 hover:text-gray-700 hover:border-gray-300 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">
Global Prompts
</a>
<a href="#gateways" id="tab-gateways"
class="tab-link border-transparent text-gray-500 dark:text-gray-300 hover:text-gray-700 hover:border-gray-300 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">
Gateways/MCP Servers
</a>
<a href="#roots" id="tab-roots"
class="tab-link border-transparent text-gray-500 dark:text-gray-300 hover:text-gray-700 hover:border-gray-300 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">
Roots
</a>
<a href="#metrics" id="tab-metrics"
class="tab-link border-transparent text-gray-500 dark:text-gray-300 hover:text-gray-700 hover:border-gray-300 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">
Metrics
</a>
<!-- New Version tab (opens separate /version page) -->
<a href="#version-info" id="tab-version-info"
class="tab-link border-transparent text-gray-500 dark:text-gray-300 hover:text-gray-700 hover:border-gray-300 whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm">
Version and Environment Info
</a>
<button @click="darkMode = !darkMode" class="p-2">
<span x-text="darkMode ? '☀️' : '🌙'"></span>
</button>
</nav>
</div>
</div>
<!-- Version Info Panel -->
<div id="version-info-panel" class="tab-panel hidden"></div>
<!-- Catalog Panel -->
<div id="catalog-panel" class="tab-panel">
<div class="flex justify-between items-center mb-4">
<h2 class="text-2xl font-bold dark:text-gray-200">MCP Servers Catalog</h2>
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">Virtual Servers let you combine Tools, Resources, and
Prompts from the global Tools catalog into a reusable configuration.</p>
<div class="flex items-center">
<input type="checkbox" id="show-inactive-servers" class="mr-2" onchange="toggleInactiveItems('servers')" />
<label for="show-inactive-servers" class="text-sm font-medium text-gray-700 dark:text-gray-300">Show
Inactive</label>
</div>
</div>
<div class="bg-white shadow rounded-lg p-6 mb-8 dark:bg-gray-800">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
Icon
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
S. No.
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
ID
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
Name
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
Description
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
Tools
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
Resources
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
Prompts
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
Actions
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200 dark:bg-gray-900 dark:divide-gray-700">
{% for server in servers %}
<tr>
<td class="px-6 py-4 whitespace-nowrap">
{% if server.icon %}
<img src="{{ server.icon }}" alt="{{ server.name }} Icon" class="h-8 w-8" />
{% else %}
<span class="text-gray-500 dark:text-gray-300">N/A</span>
{% endif %}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100">
{{ loop.index }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100">
{{ server.id }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100">
{{ server.name }}
</td>
<td class="px-6 py-4 whitespace-normal break-words text-sm text-gray-500 dark:text-gray-500">
{{ server.description }}
</td>
<td class="px-6 py-4 max-w-xs break-words text-sm text-gray-500 dark:text-gray-500">
{% if server.associatedTools %} {{ server.associatedTools |
map('string') | join(', ') }} {% else %}
<span class="text-gray-500 dark:text-gray-300">N/A</span>
{% endif %}
</td>
<td class="px-6 py-4 max-w-xs break-words text-sm text-gray-500 dark:text-gray-500">
{% if server.associatedResources %} {{
server.associatedResources | join(', ') }} {% else %}
<span class="text-gray-500 dark:text-gray-300">N/A</span>
{% endif %}
</td>
<td class="px-6 py-4 max-w-xs break-words text-sm text-gray-500 dark:text-gray-500">
{% if server.associatedPrompts %} {{
server.associatedPrompts | join(', ') }} {% else %}
<span class="text-gray-500 dark:text-gray-300">N/A</span>
{% endif %}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
{% if server.isActive %}
<form method="POST" action="{{ root_path }}/admin/servers/{{ server.id }}/toggle" class="inline mr-2"
onsubmit="return handleToggleSubmit(event, 'servers')">
<input type="hidden" name="activate" value="false" />
<button type="submit"
x-tooltip="'💡Temporarily disable this item (can be re-activated).'"
class="text-yellow-600 hover:text-yellow-900">
Deactivate
</button>
</form>
{% else %}
<form method="POST" action="{{ root_path }}/admin/servers/{{ server.id }}/toggle" class="inline mr-2"
onsubmit="return handleToggleSubmit(event, 'servers')">
<input type="hidden" name="activate" value="true" />
<button type="submit"
x-tooltip="'💡Re-enable an inactive item.'"
class="text-blue-600 hover:text-blue-900">
Activate
</button>
</form>
{% endif %}
<button onclick="viewServer('{{ server.id }}')"
class="text-indigo-600 dark:text-indigo-500 hover:text-indigo-900 mr-2">
View
</button>
<button onclick="editServer('{{ server.id }}')" class="text-green-600 hover:text-green-900 mr-2">
Edit
</button>
<form method="POST" action="{{ root_path }}/admin/servers/{{ server.id }}/delete" class="inline"
onsubmit="return handleSubmitWithConfirmation(event, 'servers')">
<button type="submit"
x-tooltip="'💡Permanently delete this item – cannot be undone.'"
class="text-red-600 hover:text-red-900">
Delete
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="bg-white shadow rounded-lg p-6 dark:bg-gray-800">
<h3 class="text-lg font-bold mb-4 dark:text-gray-200">Add New Server</h3>
<form method="POST" action="{{ root_path }}/admin/servers" id="add-server-form"
onsubmit="return handleToggleSubmit(event, 'servers')"
onreset="document.getElementById('associatedTools').selectedIndex = -1;">
<div class="grid grid-cols-1 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Name</label>
<input type="text" name="name" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Description</label>
<textarea name="description"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Icon URL</label>
<input type="url" name="icon"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label for="associatedTools" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
Associated Tools
</label>
<select name="associatedTools" {# same name as before (minus camelCase) #} id="associatedTools" multiple
{# remove if you want single-select #}
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300">
{% for tool in tools %}
{# value can be tool.id, tool.slug, or any key you use later #}
<option value="{{ tool.id }}">{{ tool.name }}</option>
{% endfor %}
</select>
<span id="selectedToolsPills" class="inline-flex flex-wrap gap-1 mt-2"></span> <!-- container -->
<span id="selectedToolsWarning" class="block text-sm font-semibold text-red-600 mt-1"></span>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Associated Resources
(comma-separated IDs)</label>
<input type="text" name="associatedResources"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder="e.g., resource1, resource2" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Associated Prompts
(comma-separated IDs)</label>
<input type="text" name="associatedPrompts"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder="e.g., prompt1, prompt2" />
</div>
</div>
<div class="mt-6">
<button type="submit"
x-tooltip="'💡Creates a new Virtual Server by combining Tools, Resources & Prompts from global catalogs.'"
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Add Server
</button>
</div>
</form>
</div>
</div>
<!-- Tools Panel -->
<div id="tools-panel" class="tab-panel hidden">
<div class="flex justify-between items-center mb-4">
<div>
<h2 class="text-2xl font-bold dark:text-gray-200">Registered Tools</h2>
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">This is the global catalog of Tools available. Create
a Virtual Server using one of these tools.</p>
<div class="mt-2 text-xs text-gray-500 dark:text-gray-400">
<strong>Annotation badges:</strong>
<span
class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-green-100 text-green-800 ml-1">📖
Read-Only</span>
<span
class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-red-100 text-red-800 ml-1">⚠️
Destructive</span>
<span
class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-purple-100 text-purple-800 ml-1">🔄
Idempotent</span>
<span
class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-yellow-100 text-yellow-800 ml-1">🌐
External Access</span>
</div>
</div>
<div class="flex items-center">
<input type="checkbox" id="show-inactive-tools" class="mr-2" onchange="toggleInactiveItems('tools')" />
<label for="show-inactive-tools" class="text-sm font-medium text-gray-700 dark:text-gray-300">Show
Inactive</label>
</div>
</div>
<div class="bg-white shadow rounded-lg p-6 mb-8 dark:bg-gray-800">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th
class="px-2 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider w-12">
S. No.
</th>
<th
class="px-2 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider w-24">
Name
</th>
<th
class="px-2 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider w-24">
URL
</th>
<th
class="px-2 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider w-12">
Type
</th>
<th
class="px-2 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider w-12">
Request Type
</th>
<th
class="px-2 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
Description
</th>
<th
class="px-2 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider w-24">
Annotations
</th>
<th
class="px-2 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider w-12">
Status
</th>
<th
class="px-2 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider w-32">
Actions
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200 dark:bg-gray-900 dark:divide-gray-700">
{% for tool in tools %}
<tr>
<td class="px-2 py-4 whitespace-nowrap text-sm font-medium text-gray-900 w-12 dark:text-gray-100">
{{ loop.index }}
</td>
<td class="px-2 py-4 whitespace-nowrap text-sm font-medium text-gray-900 w-24 dark:text-gray-100">
{{ tool.name }}
</td>
<td class="px-2 py-4 whitespace-normal break-words text-sm text-gray-500 dark:text-gray-500 w-24">
{{ tool.url }}
</td>
<td class="px-2 py-4 whitespace-normal break-words text-sm text-gray-500 dark:text-gray-500 w-12">
{{ tool.integrationType }}
</td>
<td class="px-2 py-4 whitespace-normal break-words text-sm text-gray-500 dark:text-gray-500 w-12">
{{ tool.requestType }}
</td>
<td class="px-2 py-4 whitespace-normal break-words text-sm text-gray-500 dark:text-gray-500">
{{ tool.description }}
</td>
<td class="px-2 py-4 whitespace-nowrap">
{% if tool.annotations %}
{% if tool.annotations.title %}
<span
class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-blue-100 text-blue-800 mr-1 mb-1">{{
tool.annotations.title }}</span>
{% endif %}
{% if tool.annotations.readOnlyHint %}
<span
class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-green-100 text-green-800 mr-1 mb-1">📖</span>
{% endif %}
{% if tool.annotations.destructiveHint %}
<span
class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-red-100 text-red-800 mr-1 mb-1">⚠️</span>
{% endif %}
{% if tool.annotations.idempotentHint %}
<span
class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-purple-100 text-purple-800 mr-1 mb-1">🔄</span>
{% endif %}
{% if tool.annotations.openWorldHint %}
<span
class="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium bg-yellow-100 text-yellow-800 mr-1 mb-1">🌐</span>
{% endif %}
{% else %}
<span class="text-gray-500 dark:text-gray-300 text-xs">None</span>
{% endif %}
</td>
<td class="px-6 py-4 whitespace-nowrap">
{% set enabled = tool.enabled %}
{% set reachable = tool.reachable %}
{% if enabled and reachable %}
{% set bg_class = "bg-green-100 text-green-800" %}
{% elif enabled and not reachable %}
{% set bg_class = "bg-yellow-100 text-yellow-800" %}
{% else %}
{% set bg_class = "bg-red-100 text-red-800" %}
{% endif %}
<div class="relative group inline-block">
<span
class="px-2 inline-flex items-center text-xs leading-5 font-semibold rounded-full {{ bg_class }}">
{% if enabled %}
{% if reachable %}
<!-- Active label with green check -->
Active
<svg class="ml-1 h-4 w-4 text-green-600" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm-1-4.586l5.293-5.293-1.414-1.414L9 11.586 7.121 9.707 5.707 11.121 9 14.414z"
clip-rule="evenodd" />
</svg>
{% else %}
<!-- Offline label with yellow warning -->
Offline
<svg class="ml-1 h-4 w-4 text-yellow-600" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm-1-10h2v4h-2V8zm0 6h2v2h-2v-2z"
clip-rule="evenodd" />
</svg>
{% endif %}
{% else %}
<!-- Inactive label with red cross -->
Inactive
<svg class="ml-1 h-4 w-4 text-red-600" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd"
d="M6.293 6.293a1 1 0 011.414 0L10 8.586l2.293-2.293a1 1 0 111.414 1.414L11.414 10l2.293 2.293a1 1 0 11-1.414 1.414L10 11.414l-2.293 2.293a1 1 0 11-1.414-1.414L8.586 10 6.293 7.707a1 1 0 010-1.414z"
clip-rule="evenodd" />
</svg>
{% endif %}
</span>
<div
class="absolute left-full top-1/2 -translate-y-1/2 ml-2 hidden group-hover:block bg-gray-800 text-white text-xs rounded py-1 px-2 z-10 whitespace-nowrap shadow">
{% if not enabled %}
💡Tool is Manually Deactivated.
{% elif not reachable %}
💡The host gateway for this tool is unreachable.
{% else %}
💡Everything stable.
{% endif %}
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
<button onclick="testTool('{{ tool.id }}')" class="text-purple-600 hover:text-purple-900 mr-2"
x-tooltip="'💡Execute this Tool with sample inputs.'">
Test
</button>
{% if tool.enabled %}
<form method="POST" action="{{ root_path }}/admin/tools/{{ tool.id }}/toggle" class="inline mr-2"
onsubmit="return handleToggleSubmit(event, 'tools')">
<input type="hidden" name="activate" value="false" />
<button type="submit"
x-tooltip="'💡Temporarily disable this item (can be re-activated).'"
class="text-yellow-600 hover:text-yellow-900">
Deactivate
</button>
</form>
{% else %}
<form method="POST" action="{{ root_path }}/admin/tools/{{ tool.id }}/toggle" class="inline mr-2"
onsubmit="return handleToggleSubmit(event, 'tools')">
<input type="hidden" name="activate" value="true" />
<button type="submit"
x-tooltip="'💡Re-enable an inactive item.'"
class="text-blue-600 hover:text-blue-900">
Activate
</button>
</form>
{% endif %}
<button onclick="viewTool('{{ tool.id }}')"
class="text-red-600 dark:text-indigo-500 hover:text-indigo-900 mr-2">
View
</button>
<button onclick="editTool('{{ tool.id }}')" class="text-green-600 hover:text-green-900 mr-2">
Edit
</button>
<form method="POST" action="{{ root_path }}/admin/tools/{{ tool.id }}/delete" class="inline"
onsubmit="return handleSubmitWithConfirmation(event, 'tools')">
<button type="submit"
x-tooltip="'💡Permanently delete this item – cannot be undone.'"
class="text-red-600 hover:text-red-900">
Delete
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="bg-white shadow rounded-lg p-6 dark:bg-gray-800">
<h3 class="text-lg font-bold mb-4 dark:text-gray-200">Add New Tool</h3>
<form id="add-tool-form">
<div class="grid grid-cols-1 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Name</label>
<input type="text" name="name" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">URL</label>
<input type="url" name="url" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Description</label>
<textarea name="description"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Integration Type</label>
<select id="integrationType" name="integrationType"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
onchange="updateRequestTypeOptions()">
<option value="MCP">MCP</option>
<option value="REST">REST</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Request Type</label>
<select id="requestType" name="requestType"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300">
<!-- options will be filled by JS -->
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Headers (JSON)</label>
<textarea name="headers" id="headers-editor"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Input Schema (JSON)</label>
<div class="mb-2">
<label class="mr-4 dark:text-gray-300">
<input type="radio" name="schema_input_mode" value="ui" checked />
Schema Builder
</label>
<label class="dark:text-gray-300">
<input type="radio" name="schema_input_mode" value="json" />
JSON Input
</label>
</div>
<div id="ui-builder" class="border p-4 mb-4">
<div id="parameters-container"></div>
<button type="button" id="add-parameter-btn"
class="mt-2 inline-flex justify-center py-1 px-2 border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-green-600 hover:bg-green-700">
Add New Parameter
</button>
</div>
<div id="json-input-container" style="display: none">
<textarea name="input_schema" id="schema-editor"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Json Path Filter</label>
<input type="text" name="jsonpath_filter"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<!-- Authentication Section -->
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Authentication Type</label>
<select name="auth_type" id="auth-type"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300">
<option value="">None</option>
<option value="basic">Basic</option>
<option value="bearer">Bearer Token</option>
<option value="authheaders">Custom Headers</option>
</select>
</div>
<div id="auth-basic-fields" style="display: none">
<div>
<label class="block text-sm font-medium text-gray-700">Username</label>
<input type="text" name="auth_username"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Password</label>
<input type="password" name="auth_password"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
</div>
<div id="auth-bearer-fields" style="display: none">
<div>
<label class="block text-sm font-medium text-gray-700">Token</label>
<input type="password" name="auth_token"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
</div>
<div id="auth-headers-fields" style="display: none">
<div>
<label class="block text-sm font-medium text-gray-700">Header Key</label>
<input type="text" name="auth_header_key"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Header Value</label>
<input type="password" name="auth_header_value"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder="********" />
</div>
</div>
</div>
<div class="mt-6">
<button type="submit"
x-tooltip="'💡 Registers a new Tool from an existing REST or MCP endpoint.'"
class="inline-flex justify-center py-2 px-4 border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Add Tool
</button>
</div>
</form>
</div>
</div>
<!-- Resources Panel -->
<div id="resources-panel" class="tab-panel hidden">
<div class="flex justify-between items-center mb-4">
<h2 class="text-2xl font-bold dark:text-gray-200">Available Resources</h2>
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">Resources are reusable data assets-like text, code, or
media-that Tools and Prompts can reference by URI.</p>
<div class="flex items-center">
<input type="checkbox" id="show-inactive-resources" class="mr-2"
onchange="toggleInactiveItems('resources')" />
<label for="show-inactive-resources" class="text-sm font-medium text-gray-700 dark:text-gray-300">Show
Inactive</label>
</div>
</div>
<div class="bg-white shadow rounded-lg p-6 mb-8 dark:bg-gray-800">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
ID
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
URI
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
Name
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
Description
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
MIME Type
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
Status
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
Actions
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200 dark:bg-gray-900 dark:divide-gray-700">
{% for resource in resources %}
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100">
{{ resource.id }}
</td>
<td
class="px-6 py-4 whitespace-normal break-words text-sm font-medium text-gray-900 dark:text-gray-100">
{{ resource.uri }}
</td>
<td
class="px-6 py-4 whitespace-normal break-words text-sm font-medium text-gray-900 dark:text-gray-100">
{{ resource.name }}
</td>
<td
class="px-6 py-4 whitespace-normal break-words text-sm font-medium text-gray-900 dark:text-gray-100">
{{ resource.description or "N/A" }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-500">
{{ resource.mimeType or "N/A" }}
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {% if resource.isActive %}bg-green-100 text-green-800{% else %}bg-red-100 text-red-800{% endif %}">
{{ "Active" if resource.isActive else "Inactive" }}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
{% if resource.isActive %}
<form method="POST" action="{{ root_path }}/admin/resources/{{ resource.id }}/toggle"
class="inline mr-2"
onsubmit="return handleToggleSubmit(event, 'resources')">
<input type="hidden" name="activate" value="false" />
<button type="submit"
x-tooltip="'💡Temporarily disable this item (can be re-activated).'"
class="text-yellow-600 hover:text-yellow-900">
Deactivate
</button>
</form>
{% else %}
<form method="POST" action="{{ root_path }}/admin/resources/{{ resource.id }}/toggle"
class="inline mr-2"
onsubmit="return handleToggleSubmit(event, 'resources')">
<input type="hidden" name="activate" value="true" />
<button type="submit"
x-tooltip="'💡Re-enable an inactive item.'"
class="text-blue-600 hover:text-blue-900">
Activate
</button>
</form>
{% endif %}
<button onclick="viewResource('{{ resource.uri }}')"
class="text-indigo-600 dark:text-indigo-500 hover:text-indigo-900 mr-2">
View
</button>
<button onclick="editResource('{{ resource.uri }}')" class="text-green-600 hover:text-green-900 mr-2">
Edit
</button>
<form method="POST" action="{{ root_path }}/admin/resources/{{ resource.uri }}/delete" class="inline"
onsubmit="return handleSubmitWithConfirmation(event, 'resources')">
<button type="submit"
x-tooltip="'💡Permanently delete this item – cannot be undone.'"
class="text-red-600 hover:text-red-900">
Delete
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="bg-white shadow rounded-lg p-6 dark:bg-gray-800">
<h3 class="text-lg font-bold mb-4 dark:text-gray-200">Add New Resource</h3>
<form id="add-resource-form">
<div class="grid grid-cols-1 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">URI</label>
<input type="text" name="uri" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Name</label>
<input type="text" name="name" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Description</label>
<textarea name="description"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">MIME Type</label>
<input type="text" name="mimeType"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder="text/plain" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Content</label>
<textarea name="content" id="resource-content-editor"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder=""></textarea>
</div>
<div id="status-resources"></div>
</div>
<div class="mt-6">
<button type="submit"
x-tooltip="'💡Uploads or links a reusable data asset (file, URI, or text).'"
class="inline-flex justify-center py-2 px-4 border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Add Resource
</button>
</div>
</form>
</div>
</div>
<!-- Prompts Panel -->
<div id="prompts-panel" class="tab-panel hidden">
<div class="flex justify-between items-center mb-4">
<h2 class="text-2xl font-bold dark:text-gray-200">Available Prompts</h2>
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">Prompts define reusable message templates with
parameters, useful for driving LLM interactions or Tool input.</p>
<div class="flex items-center">
<input type="checkbox" id="show-inactive-prompts" class="mr-2" onchange="toggleInactiveItems('prompts')" />
<label for="show-inactive-prompts" class="text-sm font-medium text-gray-700 dark:text-gray-300">Show
Inactive</label>
</div>
</div>
<div class="bg-white shadow rounded-lg p-6 mb-8 dark:bg-gray-800">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-500 uppercase tracking-wider">
ID
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-500 uppercase tracking-wider">
Name
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-500 uppercase tracking-wider">
Description
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-500 uppercase tracking-wider">
Arguments
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-500 uppercase tracking-wider">
Status
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-500 uppercase tracking-wider">
Actions
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200 dark:bg-gray-900 dark:divide-gray-700">
{% for prompt in prompts %}
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100">
{{ prompt.id }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100">
{{ prompt.name }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-500">
{{ prompt.description }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-500">
{% for arg in prompt.arguments %}{{ arg.name }}{% if not
loop.last %}, {% endif %}{% endfor %}
</td>
<td class="px-6 py-4 whitespace-nowrap">
<span
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full {% if prompt.isActive %}bg-green-100 text-green-800{% else %}bg-red-100 text-red-800{% endif %}">
{{ "Active" if prompt.isActive else "Inactive" }}
</span>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
{% if prompt.isActive %}
<form method="POST" action="{{ root_path }}/admin/prompts/{{ prompt.id }}/toggle" class="inline mr-2"
onsubmit="return handleToggleSubmit(event, 'prompts')">
<input type="hidden" name="activate" value="false" />
<button type="submit"
x-tooltip="'💡Temporarily disable this item (can be re-activated).'"
class="text-yellow-600 hover:text-yellow-900">
Deactivate
</button>
</form>
{% else %}
<form method="POST" action="{{ root_path }}/admin/prompts/{{ prompt.id }}/toggle" class="inline mr-2"
onsubmit="return handleToggleSubmit(event, 'prompts')">
<input type="hidden" name="activate" value="true" />
<button type="submit"
x-tooltip="'💡Re-enable an inactive item.'"
class="text-blue-600 hover:text-blue-900">
Activate
</button>
</form>
{% endif %}
<button onclick="viewPrompt('{{ prompt.name }}')"
class="text-indigo-600 dark:text-indigo-500 hover:text-indigo-900 mr-2">
View
</button>
<button onclick="editPrompt('{{ prompt.name }}')" class="text-green-600 hover:text-green-900 mr-2">
Edit
</button>
<form method="POST" action="{{ root_path }}/admin/prompts/{{ prompt.name }}/delete" class="inline"
onsubmit="return handleSubmitWithConfirmation(event, 'prompts')">
<button type="submit"
x-tooltip="'💡Permanently delete this item – cannot be undone.'"
class="text-red-600 hover:text-red-900">
Delete
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="bg-white shadow rounded-lg p-6 dark:bg-gray-800">
<h3 class="text-lg font-bold mb-4 dark:text-gray-200">Add New Prompt</h3>
<form method="POST" action="{{ root_path }}/admin/prompts" id="add-prompt-form"
onsubmit="return handleToggleSubmit(event, 'prompts')">
<div class="grid grid-cols-1 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Name</label>
<input type="text" name="name" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Description</label>
<textarea name="description"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Template</label>
<textarea name="template" id="prompt-template-editor"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder=""></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Arguments (JSON)</label>
<textarea name="arguments" id="prompt-args-editor"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder="[{'name':'arg1','description':'Argument 1','required':true}]"></textarea>
</div>
</div>
<div class="mt-6">
<button type="submit"
x-tooltip="'💡Creates a reusable message template with parameters.'"
class="inline-flex justify-center py-2 px-4 border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Add Prompt
</button>
</div>
</form>
</div>
</div>
<!-- Gateways Panel -->
<div id="gateways-panel" class="tab-panel hidden">
<div class="flex justify-between items-center mb-4">
<h2 class="text-2xl font-bold dark:text-gray-200">Federated Gateways (MCP Registry)</h2>
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">Gateways are where you register external MCP servers to
federate their tools/resources/prompts into your environment.</p>
<div class="flex items-center">
<input type="checkbox" id="show-inactive-gateways" class="mr-2" onchange="toggleInactiveItems('gateways')" />
<label for="show-inactive-gateways" class="text-sm font-medium text-gray-700 dark:text-gray-300">Show
Inactive</label>
</div>
</div>
<div class="bg-white shadow rounded-lg p-6 mb-8 dark:bg-gray-800">
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th
class="px-3 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-500 uppercase tracking-wider">
S. No.
</th>
<th
class="px-3 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-500 uppercase tracking-wider">
Name
</th>
<th
class="px-2 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-500 uppercase tracking-wider w-24">
URL
</th>
<th
class="px-3 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-500 uppercase tracking-wider">
Status
</th>
<th
class="px-3 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-500 uppercase tracking-wider">
Last Seen
</th>
<th
class="px-3 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-500 uppercase tracking-wider">
Actions
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200 dark:bg-gray-900 dark:divide-gray-700">
{% for gateway in gateways %}
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100">
{{ loop.index }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100">
{{ gateway.name }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-500">
{{ gateway.url }}
</td>
<td class="px-6 py-4 whitespace-nowrap">
{% set enabled = gateway.enabled %}
{% set reachable = gateway.reachable %}
{% if enabled and reachable %}
{% set bg_class = "bg-green-100 text-green-800" %}
{% elif enabled and not reachable %}
{% set bg_class = "bg-yellow-100 text-yellow-800" %}
{% else %}
{% set bg_class = "bg-red-100 text-red-800" %}
{% endif %}
<!-- Wrapper for tooltip -->
<div class="relative group inline-block">
<span
class="px-2 inline-flex items-center text-xs leading-5 font-semibold rounded-full {{ bg_class }}">
{% if enabled %}
{% if reachable %}
<!-- Active icon (green check) -->
Active
<svg class="ml-1 h-4 w-4 text-green-600" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm-1-4.586l5.293-5.293-1.414-1.414L9 11.586 7.121 9.707 5.707 11.121 9 14.414z"
clip-rule="evenodd" />
</svg>
{% else %}
<!-- Offline icon (yellow warning) -->
Offline
<svg class="ml-1 h-4 w-4 text-yellow-600" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm-1-10h2v4h-2V8zm0 6h2v2h-2v-2z"
clip-rule="evenodd" />
</svg>
{% endif %}
{% else %}
<!-- Inactive icon (red error) -->
Inactive
<svg class="ml-1 h-4 w-4 text-red-600" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd"
d="M6.293 6.293a1 1 0 011.414 0L10 8.586l2.293-2.293a1 1 0 111.414 1.414L11.414 10l2.293 2.293a1 1 0 11-1.414 1.414L10 11.414l-2.293 2.293a1 1 0 11-1.414-1.414L8.586 10 6.293 7.707a1 1 0 010-1.414z"
clip-rule="evenodd" />
</svg>
{% endif %}
</span>
<div
class="absolute left-full top-1/2 -translate-y-1/2 ml-2 hidden group-hover:block bg-gray-800 text-white text-xs rounded py-1 px-2 z-10 whitespace-nowrap shadow">
{% if not enabled %}
💡Gateway is Manually Deactivated
{% elif not reachable %}
💡Gateway is Not Reachable
{% else %}
💡Everything stable.
{% endif %}
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-500">
{{ gateway.lastSeen.strftime('%Y-%m-%d %H:%M:%S') if
gateway.lastSeen else 'Never' }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
<button onclick="testGateway('{{ gateway.url }}')" class="text-stone-400 hover:text-stone-100 mr-2">
Test
</button>
{% if gateway.enabled %}
<form method="POST" action="{{ root_path }}/admin/gateways/{{ gateway.id }}/toggle"
class="inline mr-2"
onsubmit="return handleToggleSubmit(event, 'gateways')">
<input type="hidden" name="activate" value="false" />
<button type="submit"
x-tooltip="'💡Temporarily disable this item (can be re-activated).'"
class="text-yellow-600 hover:text-yellow-200">
Deactivate
</button>
</form>
{% else %}
<form method="POST" action="{{ root_path }}/admin/gateways/{{ gateway.id }}/toggle"
class="inline mr-2"
onsubmit="return handleToggleSubmit(event, 'gateways')">
<input type="hidden" name="activate" value="true" />
<button type="submit"
x-tooltip="'💡Re-enable an inactive item.'"
class="text-blue-600 hover:text-blue-200">
Activate
</button>
</form>
{% endif %}
<button onclick="viewGateway('{{ gateway.id }}')"
class="text-indigo-600 dark:text-indigo-700 hover:text-indigo-100 mr-2">
View
</button>
<button onclick="editGateway('{{ gateway.id }}')" class="text-green-600 hover:text-green-300 mr-2">
Edit
</button>
<form method="POST" action="{{ root_path }}/admin/gateways/{{ gateway.id }}/delete" class="inline"
onsubmit="return handleSubmitWithConfirmation(event, 'gateways')">
<button type="submit"
x-tooltip="'💡Permanently delete this item – cannot be undone.'"
class="text-red-400 hover:text-red-600">
Delete
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="bg-white shadow rounded-lg p-6 dark:bg-gray-800">
<h3 class="text-lg font-bold mb-4 dark:text-gray-200">Add New Gateway</h3>
<form id="add-gateway-form">
<div class="grid grid-cols-1 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Name</label>
<input type="text" name="name" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">URL</label>
<input type="url" name="url" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Description</label>
<textarea name="description"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Transport Type</label>
<select name="transport"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300">
<option value="SSE" selected>SSE</option>
<option value="STREAMABLEHTTP">Streamable HTTP</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-400">Authentication Type</label>
<select name="auth_type" id="auth-type-gw"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300">
<option value="">None</option>
<option value="basic">Basic</option>
<option value="bearer">Bearer Token</option>
<option value="authheaders">Custom Headers</option>
</select>
</div>
<div id="auth-basic-fields-gw" style="display: none">
<div>
<label class="block text-sm font-medium text-gray-700">Username</label>
<input type="text" name="auth_username"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Password</label>
<input type="password" name="auth_password"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
</div>
<div id="auth-bearer-fields-gw" style="display: none">
<div>
<label class="block text-sm font-medium text-gray-700">Token</label>
<input type="password" name="auth_token"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
</div>
<div id="auth-headers-fields-gw" style="display: none">
<div>
<label class="block text-sm font-medium text-gray-700">Header Key</label>
<input type="text" name="auth_header_key"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Header Value</label>
<input type="password" name="auth_header_value"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder="********" />
</div>
</div>
<div id="add-gateway-loading" style="display: none;">
<div class="spinner"></div>
</div>
<div id="status-gateways"></div>
</div>
<div class="mt-6">
<button type="submit"
x-tooltip="'💡Registers an external MCP server and imports its catalogs - Tools, Prompts, Resources, etc.'"
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Add Gateway
</button>
</div>
</form>
</div>
</div>
<!-- Roots Panel -->
<div id="roots-panel" class="tab-panel hidden">
<!-- List of roots ------------------------------------------------------->
<div class="bg-white shadow rounded-lg p-6 mb-8 dark:bg-gray-800">
<!-- Consistent header -->
<div class="flex justify-between items-center mb-4">
<h2 class="text-2xl font-bold dark:text-gray-200">Root Directories</h2>
<div class="flex items-center">
<input type="checkbox" id="show-inactive-roots" class="mr-2" onchange="toggleInactiveItems('roots')" />
<label for="show-inactive-roots" class="text-sm font-medium text-gray-700 dark:text-gray-300">
Show Inactive
</label>
</div>
</div>
<!-- Description -->
<p class="text-sm text-gray-600 dark:text-gray-400 mb-4">
Roots define the base folders accessible for file-based Resources.
They enable MCP servers to browse local content.
</p>
<!-- Roots table -->
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50 dark:bg-gray-700">
<tr>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
ID
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
URI
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
Name
</th>
<th
class="px-6 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
Actions
</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200 dark:bg-gray-900 dark:divide-gray-700">
{% for root in roots %}
<tr>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100">
{{ root.id }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100s">
{{ root.uri }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 dark:text-gray-500">
{{ root.name }}
</td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
<form method="POST" action="{{ root_path }}/admin/roots/{{ root.uri }}/delete" class="inline"
onsubmit="return handleSubmitWithConfirmation(event, 'roots')">
<button type="submit"
x-tooltip="'💡Permanently delete this item – cannot be undone.'"
class="text-red-600 hover:text-red-900">
Delete
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- Add new root -------------------------------------------------------->
<div class="bg-white shadow rounded-lg p-6 dark:bg-gray-800">
<h3 class="text-lg font-bold mb-4 dark:text-gray-200">Add New Root</h3>
<form method="POST" action="{{ root_path }}/admin/roots" id="add-root-form"
onsubmit="return handleToggleSubmit(event, 'roots')">
<div class="grid grid-cols-1 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700">URI</label>
<input type="text" name="uri" required
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder="file:///path/to/directory" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Name</label>
<input type="text" name="name"
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder="My Project" />
</div>
</div>
<div class="mt-6">
<button type="submit"
x-tooltip="'💡Registers a base directory that MCP servers can browse for files.'"
class="inline-flex justify-center py-2 px-4 border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Add Root
</button>
</div>
</form>
</div>
</div>
<!-- Metrics Panel -->
<div id="metrics-panel" class="tab-panel hidden">
<div class="bg-white shadow rounded-lg p-6 dark:bg-gray-800">
<h2 class="text-2xl font-bold dark:text-gray-200 mb-4">Aggregated Metrics</h2>
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1">Metrics provide visibility into Tool, Resource, Prompt,
and Server usage across your Gateway-helpful for debugging and optimization.</p>
<!-- Refresh button (also auto-refreshes when the tab is selected) -->
<button onclick="loadAggregatedMetrics()" class="mb-4 px-4 py-2 bg-indigo-600 text-white rounded">
Refresh Metrics
</button>
<!-- Aggregated Metrics Table -->
<div id="aggregated-metrics-content" class="overflow-auto mb-6 bg-gray-100"></div>
<!-- Overall Bar Chart for Total Executions -->
<canvas id="metricsChart" width="400" height="200" class="bg-white"></canvas>
<hr class="my-6" />
<!-- Expandable sections for top items -->
<details id="top-tools-details" class="mb-4">
<summary class="text-xl font-semibold cursor-pointer dark:text-gray-200">
Top Tools by Executions
</summary>
<div id="top-tools-content" class="mt-4"></div>
</details>
<details id="top-resources-details" class="mb-4">
<summary class="text-xl font-semibold cursor-pointer dark:text-gray-200">
Top Resources by Executions
</summary>
<div id="top-resources-content" class="mt-4"></div>
</details>
<details id="top-servers-details" class="mb-4">
<summary class="text-xl font-semibold cursor-pointer dark:text-gray-200">
Top Servers by Executions
</summary>
<div id="top-servers-content" class="mt-4"></div>
</details>
<details id="top-prompts-details" class="mb-4">
<summary class="text-xl font-semibold cursor-pointer dark:text-gray-200">
Top Prompts by Executions
</summary>
<div id="top-prompts-content" class="mt-4"></div>
</details>
</div>
</div>
<!-- Modals -->
<!-- Tool Detail Modal -->
<div id="tool-modal" class="fixed z-10 inset-0 overflow-y-auto hidden">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white dark:bg-gray-900 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">Tool Details</h3>
<div class="mt-4 space-y-4 bg-white dark:bg-gray-900" id="tool-details"></div>
</div>
<div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" onclick="closeModal('tool-modal')"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm dark:text-gray-300">
Close
</button>
</div>
</div>
</div>
</div>
<!-- Tool Test Modal -->
<div id="tool-test-modal" class="fixed z-10 inset-0 overflow-y-auto hidden">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<!-- Increased max width (sm:max-w-2xl) for a larger modal -->
<div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-2xl sm:w-full">
<div class="bg-white dark:bg-gray-900 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<h3 id="tool-test-modal-title" class="text-lg font-medium text-gray-900 dark:text-gray-100">
Test Tool
</h3>
<!-- New container to show the tool's description -->
<div id="tool-test-modal-description" class="mb-4 text-gray-700 dark:text-gray-400"></div>
<form id="tool-test-form">
<div id="tool-test-form-fields" class="space-y-4 text-gray-700 dark:text-gray-400">
<!-- Fields will be dynamically inserted here based on the tool's input schema -->
</div>
<div class="mt-4">
<button type="button" onclick="runToolTest()"
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700">
Run Tool
</button>
</div>
<div id="tool-test-loading" style="display: none;">
<div class="spinner"></div>
</div>
</form>
<!-- The result area now uses a fixed height for a larger view -->
<div id="tool-test-result"
class="mt-4 bg-gray-100 p-2 rounded overflow-auto dark:bg-gray-900 dark:text-gray-300"
style="height: 400px"></div>
</div>
<div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" onclick="closeModal('tool-test-modal', 'tool-test-result')"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm dark:text-gray-300">
Close
</button>
</div>
</div>
</div>
</div>
<!-- Tool Edit Modal -->
<div id="tool-edit-modal" class="fixed z-10 inset-0 overflow-y-auto hidden">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white dark:bg-gray-900 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">Edit Tool</h3>
<div class="mt-4">
<form id="edit-tool-form" method="POST">
<div class="grid grid-cols-1 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Name</label>
<input type="text" name="name" required id="edit-tool-name"
class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">URL</label>
<input type="url" name="url" required id="edit-tool-url"
class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Description</label>
<textarea name="description" id="edit-tool-description"
class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Integration Type</label>
<select name="integrationType" id="edit-tool-type"
class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300">
<option value="MCP">MCP</option>
<option value="REST">REST</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Request Type</label>
<select name="requestType" id="edit-tool-request-type"
class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300">
<!-- Will be populated dynamically -->
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Headers (JSON)</label>
<textarea name="headers" id="edit-tool-headers"
class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Input Schema (JSON)</label>
<textarea name="input_schema" id="edit-tool-schema"
class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Annotations (JSON)</label>
<textarea name="annotations" id="edit-tool-annotations"
class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm text-gray-900 placeholder-gray-600 dark:placeholder-gray-400 bg-white dark:bg-gray-800"
placeholder="Annotations are generally provided by the MCP servers"></textarea>
<p class="mt-1 text-xs text-gray-500 dark:text-indigo-300">Annotations like readOnlyHint, destructiveHint are generally provided by
the MCP server.</p>
</div>
<!-- Authentication Section -->
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Authentication Type</label>
<select name="auth_type" id="edit-auth-type"
class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300">
<option value="">None</option>
<option value="basic">Basic</option>
<option value="bearer">Bearer Token</option>
<option value="authheaders">Custom Headers</option>
</select>
</div>
<div id="edit-auth-basic-fields" style="display: none">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Username</label>
<input type="text" name="auth_username" id="edit-auth-username"
class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Password</label>
<input type="password" name="auth_password" id="edit-auth-password"
class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder="********" />
</div>
</div>
<div id="edit-auth-bearer-fields" style="display: none">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Token</label>
<input type="password" name="auth_token" id="edit-auth-token"
class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder="********" />
</div>
</div>
</div>
<div id="edit-auth-headers-fields" style="display: none">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Header Key</label>
<input type="text" name="auth_header_key" id="edit-auth-key"
class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300">Header Value</label>
<input type="password" name="auth_header_value" id="edit-auth-value"
class="mt-1 block w-full rounded-md border border-gray-300 dark:border-gray-600 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder="********" />
</div>
</div>
<div class="mt-6 flex justify-end space-x-3 bg-white dark:bg-gray-900 dark:text-gray-100">
<button type="button" onclick="closeModal('tool-edit-modal')"
class="px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:text-gray-300">
Cancel
</button>
<button type="submit"
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Save Changes
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- Resource Detail Modal -->
<div id="resource-modal" class="fixed z-10 inset-0 overflow-y-auto hidden">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white dark:bg-gray-900 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">Resource Details</h3>
<div class="mt-4 space-y-4 bg-white dark:bg-gray-400" id="resource-details"></div>
</div>
<div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" onclick="closeModal('resource-modal')"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm dark:text-gray-300">
Close
</button>
</div>
</div>
</div>
</div>
<!-- Resource Edit Modal -->
<div id="resource-edit-modal" class="fixed z-10 inset-0 overflow-y-auto hidden">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white dark:bg-gray-900 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">Edit Resource</h3>
<div class="mt-4">
<form id="edit-resource-form" method="POST">
<div class="grid grid-cols-1 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700">URI</label>
<!-- URI is read-only -->
<input type="text" name="uri" required id="edit-resource-uri" readonly
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Name</label>
<input type="text" name="name" required id="edit-resource-name"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Description</label>
<textarea name="description" id="edit-resource-description"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">MIME Type</label>
<input type="text" name="mimeType" id="edit-resource-mime-type"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Content</label>
<!-- Remove required attribute to avoid browser validation issues -->
<textarea name="content" id="edit-resource-content"
class="mt-1 block w-full h-48 rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"></textarea>
</div>
</div>
<div class="mt-6 flex justify-end space-x-3 bg-white dark:bg-gray-900 dark:text-gray-100">
<button type="button" onclick="closeModal('resource-edit-modal')"
class="px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:text-gray-300">
Cancel
</button>
<button type="submit"
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Save Changes
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- Prompt Detail Modal -->
<div id="prompt-modal" class="fixed z-10 inset-0 overflow-y-auto hidden">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white dark:bg-gray-900 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">Prompt Details</h3>
<div class="mt-4 space-y-4 bg-white dark:bg-gray-400" id="prompt-details"></div>
</div>
<div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" onclick="closeModal('prompt-modal')"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm dark:text-gray-300">
Close
</button>
</div>
</div>
</div>
</div>
<!-- Prompt Edit Modal -->
<div id="prompt-edit-modal" class="fixed z-10 inset-0 overflow-y-auto hidden">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white dark:bg-gray-900 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">Edit Prompt</h3>
<div class="mt-4">
<form id="edit-prompt-form" method="POST">
<div class="grid grid-cols-1 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700">Name</label>
<input type="text" name="name" required id="edit-prompt-name"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Description</label>
<textarea name="description" id="edit-prompt-description"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Template</label>
<textarea name="template" id="edit-prompt-template"
class="mt-1 block w-full h-48 rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500"
required></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Arguments (JSON)</label>
<textarea name="arguments" id="edit-prompt-arguments"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
</div>
<div class="mt-6 flex justify-end space-x-3 bg-white dark:bg-gray-900 dark:text-gray-100">
<button type="button" onclick="closeModal('prompt-edit-modal')"
class="px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:text-gray-300">
Cancel
</button>
<button type="submit"
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Save Changes
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- Gateway Detail Modal -->
<div id="gateway-modal" class="fixed z-10 inset-0 overflow-y-auto hidden">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white dark:bg-gray-900 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">Gateway Details</h3>
<div class="mt-4 space-y-4 bg-white dark:bg-gray-400" id="gateway-details"></div>
</div>
<div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" onclick="closeModal('gateway-modal')"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm dark:text-gray-300">
Close
</button>
</div>
</div>
</div>
</div>
<!-- Test Gateway Modal -->
<div id="gateway-test-modal"
class="fixed z-50 inset-0 bg-gray-800 bg-opacity-75 flex items-center justify-center hidden">
<div class="bg-white dark:bg-gray-900 w-full max-w-2xl max-h-[90vh] overflow-y-auto rounded-lg shadow-lg p-6">
<h2 class="text-xl font-bold mb-4 text-gray-800 dark:text-gray-100">Test Gateway Connectivity</h2>
<form id="gateway-test-form" class="space-y-4 text-gray-800 dark:text-gray-100">
<div>
<label for="gateway-test-url" class="block text-sm font-medium text-gray-700 dark:text-gray-300">Server URL</label>
<input required name="url" type="text" id="gateway-test-url" class="mt-1 block w-full rounded-md shadow-sm p-1 bg-gray-200 dark:bg-gray-800" />
</div>
<div>
<label for="gateway-test-method" class="block text-sm font-medium text-gray-700 dark:text-gray-300">Method</label>
<select required name="method" id="gateway-test-method" class="mt-1 block w-full rounded-md shadow-sm p-1 bg-gray-200 dark:bg-gray-800">
<option>GET</option>
<option>POST</option>
<option>PUT</option>
<option>DELETE</option>
<option>PATCH</option>
</select>
</div>
<div>
<label for="gateway-test-path" class="block text-sm font-medium text-gray-700 dark:text-gray-300">Path</label>
<input id="gateway-test-path" name="path" type="text" placeholder="/health"
class="mt-1 block w-full rounded-md shadow-sm p-1 bg-gray-200 dark:bg-gray-800" />
</div>
<div>
<label for="gateway-test-headers" class="block text-sm font-medium text-gray-700 dark:text-gray-300">Headers (JSON)</label>
<textarea id="gateway-test-headers" class="mt-1 block w-full rounded-md shadow-sm p-1 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-300 placeholder-gray-600 dark:placeholder-gray-400" placeholder="Enter request headers as JSON"></textarea>
</div>
<div>
<label for="gateway-test-body" class="block text-sm font-medium text-gray-700 dark:text-gray-300">Body (JSON)</label>
<textarea id="gateway-test-body" class="mt-1 block w-full rounded-md shadow-sm p-1 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-300 placeholder-gray-600 dark:placeholder-gray-400" placeholder="Enter request body as JSON"></textarea>
</div>
<div class="flex">
<button type="submit" id="gateway-test-submit"
class="w-full text-center px-3 py-1 bg-indigo-600 text-white rounded hover:bg-indigo-700">
Test
</button>
<p class="p-1"></p>
<button id="gateway-test-close" type="button"
class="w-full text-center px-3 py-1 border border-blue-600 rounded bg-white text-gray-700 hover:bg-gray-200">
Close
</button>
</div>
<div id="gateway-test-loading" class="mt-4 hidden flex items-center justify-center">
<div class="spinner border-t-4 border-blue-600 w-6 h-6 rounded-full animate-spin"></div>
</div>
<div id="gateway-test-result" class="hidden">
<label class="block text-sm font-medium text-gray-700">Response</label>
<div id="gateway-test-response-json"
class="bg-gray-100 p-2 rounded overflow-auto text-sm text-gray-800 max-h-64"></div>
</div>
</form>
</div>
</div>
<!-- Gateway Edit Modal -->
<div id="gateway-edit-modal" class="fixed z-10 inset-0 overflow-y-auto hidden">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white dark:bg-gray-900 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">Edit Gateway</h3>
<div class="mt-4">
<form id="edit-gateway-form" method="POST">
<div class="grid grid-cols-1 gap-6">
<div>
<label class="block text-sm font-medium text-gray-700">Name</label>
<input type="text" name="name" required id="edit-gateway-name"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">URL</label>
<input type="url" name="url" required id="edit-gateway-url"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Description</label>
<textarea name="description" id="edit-gateway-description"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Transport Type</label>
<select name="transport" id="edit-gateway-transport"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300">
<option value="SSE" selected>SSE</option>
<option value="STREAMABLEHTTP">Streamable HTTP</option>
</select>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Authentication Type</label>
<select name="auth_type" id="auth-type-gw-edit"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300">
<option value="">None</option>
<option value="basic">Basic</option>
<option value="bearer">Bearer Token</option>
<option value="authheaders">Custom Headers</option>
</select>
</div>
<div id="auth-basic-fields-gw-edit" style="display: none">
<div>
<label class="block text-sm font-medium text-gray-700">Username</label>
<input type="text" name="auth_username"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Password</label>
<input type="password" name="auth_password"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
</div>
<div id="auth-bearer-fields-gw-edit" style="display: none">
<div>
<label class="block text-sm font-medium text-gray-700">Token</label>
<input type="password" name="auth_token"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
</div>
<div id="auth-headers-fields-gw-edit" style="display: none">
<div>
<label class="block text-sm font-medium text-gray-700">Header Key</label>
<input type="text" name="auth_header_key"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Header Value</label>
<input type="password" name="auth_header_value"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder="********" />
</div>
</div>
</div>
<div class="mt-6 flex justify-end space-x-3 bg-white dark:bg-gray-900 dark:text-gray-100">
<button type="button" onclick="closeModal('gateway-edit-modal')"
class="px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:text-gray-300">
Cancel
</button>
<button type="submit"
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Save Changes
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- Server Detail Modal -->
<div id="server-modal" class="fixed z-10 inset-0 overflow-y-auto hidden">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white dark:bg-gray-900 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">Server Details</h3>
<div class="mt-4 space-y-4 bg-white dark:bg-gray-900" id="server-details"></div>
</div>
<div class="bg-gray-50 dark:bg-gray-700 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
<button type="button" onclick="closeModal('server-modal')"
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm dark:text-gray-300">
Close
</button>
</div>
</div>
</div>
</div>
<!-- Server Edit Modal -->
<div id="server-edit-modal" class="fixed z-10 inset-0 overflow-y-auto hidden">
<div class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
<div class="absolute inset-0 bg-gray-500 opacity-75"></div>
</div>
<div
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full">
<div class="bg-white dark:bg-gray-900 px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
<h3 class="text-lg font-medium text-gray-900 dark:text-gray-100">Edit Server</h3>
<div class="mt-4">
<form id="edit-server-form" method="POST">
<div class="grid grid-cols-1 gap-6">
<!-- Existing fields -->
<div>
<label class="block text-sm font-medium text-gray-700">Name</label>
<input type="text" name="name" required id="edit-server-name"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Description</label>
<textarea name="description" id="edit-server-description"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"></textarea>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Icon URL</label>
<input type="url" name="icon" id="edit-server-icon"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300" />
</div>
<div>
<label for="edit-server-tools" class="block text-sm font-medium text-gray-700 dark:text-gray-300">
Associated Tools
</label>
<select id="edit-server-tools" name="associatedTools" {# same field name #} multiple
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300">
{% for tool in tools %}
<option value="{{ tool.id }}">{{ tool.name }}</option>
{% endfor %}
</select>
<span id="selectedEditToolsPills" class="inline-flex flex-wrap gap-1 mt-2"></span>
<!-- container -->
<span id="selectedEditToolsWarning" class="block text-sm font-semibold text-red-600 mt-1"></span>
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Associated Resources (comma-separated
IDs)</label>
<input type="text" name="associatedResources" id="edit-server-resources"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder="e.g., 3,4" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700">Associated Prompts (comma-separated
IDs)</label>
<input type="text" name="associatedPrompts" id="edit-server-prompts"
class="mt-1 block w-full rounded-md border border-gray-300 shadow-sm focus:border-indigo-500 focus:ring-indigo-500 dark:bg-gray-900 dark:placeholder-gray-300 dark:text-gray-300"
placeholder="e.g., 5,6" />
</div>
</div>
<div class="mt-6 flex justify-end space-x-3 bg-white dark:bg-gray-900 dark:text-gray-100">
<button type="button" onclick="closeModal('server-edit-modal')"
class="px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 dark:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 dark:text-gray-300">
Cancel
</button>
<button type="submit"
class="inline-flex justify-center py-2 px-4 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
Save Changes
</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Scripts -->
<script>
// Build mapping objects using your existing tools, resources, and prompts arrays
window.toolMapping = {};
{% for tool in tools %}
window.toolMapping["{{ tool.id }}"] = "{{ tool.name }}";
{% endfor %}
window.resourceMapping = {};
{% for resource in resources %}
window.resourceMapping["{{ resource.id }}"] = "{{ resource.name }}";
{% endfor %}
window.promptMapping = {};
{% for prompt in prompts %}
window.promptMapping["{{ prompt.id }}"] = "{{ prompt.name }}";
{% endfor %}
window.ROOT_PATH = {{ root_path | tojson }};
window.GATEWAY_TOOL_NAME_SEPARATOR = {{ gateway_tool_name_separator | tojson }};
</script>
</body>
</html>