
Gateway open-source che protegge, governa e osserva le chiamate agli strumenti MCP e il traffico LLM degli agenti AI, con autenticazione tramite API key e una console di amministrazione per il monitoraggio.
Console di amministrazione per il Tuskira AI Agent Gateway. React 19 + Vite + TypeScript (strict) + Tailwind CSS 4 + shadcn/ui.
Richiede Node 26+ e npm 11+ (non pnpm).
npm install
npm run dev
Il dev server inoltra /api a http://localhost:8081 (vedi vite.config.ts), quindi
esegui il gateway sulla porta :8081 insieme all'interfaccia utente. Accedi a /login con una chiave API
(gk_…) emessa dal gateway.
Dalla radice del repository puoi invece eseguire:
make ui-install
make ui-dev
npm run build
Genera un bundle di produzione in dist/. In produzione il gateway stesso serve questo
bundle su / sulla porta :8081, quindi l'app comunica con l'API in same-origin — non è necessario alcun proxy.
make ui-build # from the repo root
La console è anche distribuita come pacchetto @tuskira/gateway-web, così puoi montare le sue pagine
all'interno della tua app React. Il pacchetto non è presente nel registry npm. Ogni release di GitHub
lo include come tarball, e la sua versione corrisponde sempre al tag di release del gateway. React,
React DOM, React Router (react-router-dom 7) e TanStack Query 5 sono peer dependency;
tutto il resto viene installato con il pacchetto.
npm install https://github.com/Tuskira/ai-agent-gateway/releases/download/v<version>/tuskira-gateway-web-<version>.tgz \
react react-dom react-router-dom @tanstack/react-query
npm registra l'hash di integrità del tarball in package-lock.json.
import {
AppShell, AuthProvider, RequireAuth, LoginPage, Toaster, TooltipProvider,
configureGateway, gatewayPageRoutes,
} from '@tuskira/gateway-web'
import '@tuskira/gateway-web/style.css' // Tailwind output + design tokens
import '@tuskira/gateway-web/fonts.css' // optional: self-hosted Inter / JetBrains Mono
configureGateway({
apiBase: '/gw/api/v1', // default '/api/v1'
mcpBase: 'https://gw.example.com/mcp', // default: guessed from the page origin
onUnauthenticated: () => router.navigate('/login'), // default: window.location.assign('/login')
})
const router = createBrowserRouter(
[
{ path: '/login', element: <LoginPage /> },
{ element: <RequireAuth />, children: [{ element: <AppShell />, children: gatewayPageRoutes() }] },
],
{ basename: '/gateway' },
)
Avvolgi il router in QueryClientProvider, AuthProvider e TooltipProvider, e renderizza
<Toaster /> una volta, come fa src/App.tsx. gatewayRoutes() restituisce l'albero completo
(login, docs, change-password, shell e il redirect catch-all) se vuoi che la console
gestisca l'intero router. È supportato solo ciò che esporta @tuskira/gateway-web; non
importare da src/.
Passa un extension per inserire i tuoi gruppi di sidebar e pagine all'interno della shell della console e
della protezione di accesso:
gatewayRoutes({ extension: { navGroups: [...], routes: [...] } })
import { Plug } from 'lucide-react'
import { AppShell, gatewayPageRoutes, type ConsoleExtension } from '@tuskira/gateway-web'
const extension: ConsoleExtension = {
navGroups: [
// New group, placed before the core "Observe" group (appended without `before`).
{ label: 'Billing', before: 'Observe', items: [
{ label: 'Invoices', path: '/invoices', icon: Plug, description: 'Invoices and usage.' },
] },
// Same label as a core group: the items are added to that group.
{ label: 'Access', items: [
{ label: 'Audit', path: '/audit', icon: Plug, description: 'Audit trail.' },
] },
],
routes: [
{ path: '/invoices', Component: InvoicesPage },
{ path: '/audit', Component: AuditPage },
],
}
// Own router: pass the extension to both the routes and the shell.
{ element: <AppShell extension={extension} />, children: gatewayPageRoutes(extension) }
gatewayRoutes({ extension }) fa entrambe le cose per te. Una voce di navigazione il cui percorso non ha una route mostra il segnaposto "coming soon". Imposta end: true su una voce il cui percorso è un prefisso dei percorsi di altre voci, così è attiva solo sul proprio percorso.
Il browser deve raggiungere l'API del gateway sul percorso impostato come apiBase. Quando l'app host serve la console, aggiungi una regola di reverse-proxy che inoltri /api/v1/* (o il tuo percorso apiBase, riscritto di nuovo in /api/v1) al gateway sulla porta 8081. Mantieni invariati il percorso, tutti gli header di richiesta e risposta (Authorization, X-CSRF-Token, X-Gateway-Acting-Tenant) e i cookie, altrimenti l'accesso e i controlli CSRF falliranno.
Compila il pacchetto con npm run build:lib, che scrive dist-lib/ (index.js, types/, style.css, fonts.css). npm pack produce quindi il tarball; il workflow di release lo allega alla release di GitHub a ogni tag v*.
npm run lint # eslint
npm run typecheck # tsc --noEmit (project references)
npm run test # vitest
npm run format:check # prettier --check
npx shadcn@latest add <component>
Il components.json di questo progetto punta al template Vite, alla base radix, al colore di base neutral e alle variabili CSS per il theming, con l'alias di importazione @/* che risolve in src/*. I nuovi componenti vengono scritti in src/components/ui/.
tokens.json (radice del repository) è l'unica fonte di verità per il design system — colori, spaziatura, raggi, ombre, font. Esegui npm run gen:tokens dopo averlo modificato per rigenerare:
src/styles/tokens.css — i token grezzi come proprietà personalizzate CSS (:root per i valori chiari, .dark per le sovrascritture scure), mantenendo i nomi dei token originali del designer (--indigo-9, --sev-high, --r-4, --shadow-1, ...).src/styles/tokens.ts — le stesse scale di colori categoriche (colors.indigo, colors.slate, colors.sev, colors.status, colors.brand) più fonts, radii, shadows, per i consumatori non-CSS (ad es. i colori delle serie di recharts).src/index.css mappa le variabili semantiche di shadcn (--background, --primary, --sidebar, ...) su questi token e registra le voci @theme di Tailwind v4 in modo che utility come bg-indigo-9, text-text-muted, border-border-strong, shadow-1, rounded-r-4 e font-mono siano disponibili ovunque nell'app. Non modificare manualmente src/styles/tokens.css / src/styles/tokens.ts — vengono sovrascritti dal generatore. src/test/tokens.test.ts verifica che ogni voce di tokens.ts abbia una dichiarazione corrispondente in tokens.css.