import React, { useState, useEffect } from 'react'; import { ShieldCheck, Key, Lock, Unlock, Plus, Trash2, Copy, Check, AlertCircle, RefreshCw, Layers } from 'lucide-react'; interface AgentKey { id: string; name: string; key: string; scope: 'full' | 'read_only' | 'restricted'; rateLimitPerMin: number; requestCount: number; lastUsedAt?: string; createdAt: string; } export const SecurityGatewayTab: React.FC = () => { const [authRequired, setAuthRequired] = useState(false); const [keys, setKeys] = useState([]); const [loading, setLoading] = useState(true); const [newKeyName, setNewKeyName] = useState(''); const [newKeyScope, setNewKeyScope] = useState<'full' | 'read_only'>('full'); const [newRateLimit, setNewRateLimit] = useState(120); const [copiedKey, setCopiedKey] = useState(null); const fetchSecurityState = async () => { setLoading(true); try { const res = await fetch('/api/v1/mcp/security/keys'); if (res.ok) { const data = await res.json(); setAuthRequired(data.authRequired); setKeys(data.keys || []); } } catch (e) { console.error(e); } finally { setLoading(false); } }; useEffect(() => { fetchSecurityState(); }, []); const handleToggleAuth = async () => { try { const res = await fetch('/api/v1/mcp/security/toggle-auth', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ required: !authRequired }), }); if (res.ok) { const data = await res.json(); setAuthRequired(data.authRequired); } } catch (e) { console.error(e); } }; const handleCreateKey = async (e: React.FormEvent) => { e.preventDefault(); if (!newKeyName.trim()) return; try { const res = await fetch('/api/v1/mcp/security/keys', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: newKeyName, scope: newKeyScope, rateLimitPerMin: newRateLimit, }), }); if (res.ok) { setNewKeyName(''); fetchSecurityState(); } } catch (e) { console.error(e); } }; const handleRevokeKey = async (id: string) => { if (!confirm('Are you sure you want to revoke this Agent Access Key?')) return; try { await fetch(`/api/v1/mcp/security/keys/${id}`, { method: 'DELETE' }); fetchSecurityState(); } catch (e) { console.error(e); } }; const copyKey = (key: string) => { navigator.clipboard.writeText(key); setCopiedKey(key); setTimeout(() => setCopiedKey(null), 2000); }; return (
{/* Header Banner */}
MCP Security Gateway

Agent Authentication & Security Gateway

Manage Bearer tokens and access security policies for AI agents connecting to your self-hosted MCP Hub. Enforce rate limiting per agent and restrict permissions to protect sensitive internal tools.

{/* Auth Toggle Banner */}
{authRequired ? : }

Security Enforcement Mode

{authRequired ? 'STRICT (Bearer Key Required)' : 'OPEN LOCAL ACCESS'}

{authRequired ? 'All incoming requests to /mcp must supply a valid Authorization: Bearer header.' : 'Local and internal requests to /mcp are accepted without token header check.'}

{/* Keys Management */}
{/* Create Key Form */}

Issue Agent Key

setNewKeyName(e.target.value)} placeholder="e.g. Cursor IDE Prod Agent" className="w-full rounded-lg border border-slate-300 p-2.5 text-xs text-slate-900 focus:outline-none focus:ring-2 focus:ring-indigo-500" />
setNewRateLimit(Number(e.target.value))} className="w-full rounded-lg border border-slate-300 p-2.5 text-xs text-slate-900 focus:outline-none focus:ring-2 focus:ring-indigo-500" />
{/* Keys List */}

Active Agent Access Keys

{loading ? (
Loading keys...
) : keys.length === 0 ? (
No keys generated yet
) : (
{keys.map((k) => (
{k.name} {k.scope} ({k.rateLimitPerMin} req/m)
{k.key}
Requests handled: {k.requestCount} • Last used: {k.lastUsedAt ? new Date(k.lastUsedAt).toLocaleTimeString() : 'Never'}
))}
)}
); };