Note
This is a lightweight version of ToolHive Cloud for viewing your MCP servers. Interested in enterprise capabilities? Reach out to us.
A Next.js application for visualizing MCP (Model Context Protocol) servers running in user infrastructure with easy URL copying for integration with AI agents.
Frontend: toolhive-cloud-ui (this repository)
Backend API: toolhive-registry-server - implements the official MCP Registry API
Quickstart
Prerequisites
- Node.js 20+ and pnpm 10+
- For Kubernetes deployment: Docker, Kind, Helm, kubectl
Developer guide
Local development
This section covers all available commands and development workflows.
# Install dependencies pnpm install # Copy environment variables template (optional for development) cp .env.example .env.local
# Start full dev environment (Next.js + OIDC mock + MSW mock server) pnpm dev # Application will be available at http://localhost:3000
Authentication: the dev stack also starts a local OIDC provider (on :4000) and MSW mock API (on :9090). The /signin page initiates the OIDC flow and redirects back to /catalog on success.
Available commands
Development commands (pnpm)
# Full development environment (recommended) pnpm dev # Starts Next.js + OIDC mock + MSW mock server # - Next.js: http://localhost:3000 # - OIDC Mock: http://localhost:3001 # - MSW Mock API: http://localhost:9090 # Individual services pnpm dev:next # Start only Next.js dev server pnpm dev:mock-server # Start Next.js + MSW mock (requires real OIDC provider configured) pnpm dev:mock-oidc # Start Next.js + OIDC mock (requires real backend API configured) pnpm oidc # Start only OIDC mock provider pnpm mock:server # Start only MSW standalone mock server # Production build pnpm build # Build optimized production bundle pnpm start # Start production server (after build) # Code quality pnpm lint # Run Biome linter pnpm format # Auto-format code with Biome pnpm test # Run Vitest tests pnpm type-check # TypeScript compilation check # API client generation pnpm generate-client # Fetch swagger.json and regenerate client pnpm generate-client:nofetch # Regenerate client without fetching
Make commands
For convenience, common pnpm commands are also available as Make targets:
# Development make install # Install dependencies make dev # Run dev server (pnpm dev) make dev-next # Run only Next.js (pnpm dev:next) make dev-mock-server # Run with MSW only (pnpm dev:mock-server) make lint # Run linter make format # Format code make test # Run tests make type-check # Type checking make generate-client # Generate API client # Docker (see Docker section below) make build # Build Docker image make start # Start container # ... (see Docker section) # Kubernetes (see Kubernetes section below) make kind-setup # Setup Kind cluster make kind-deploy # Deploy to Kind # ... (see Kubernetes section)
Development workflow
1. Initial setup
# Clone repository git clone https://github.com/stacklok/toolhive-cloud-ui.git cd toolhive-cloud-ui # Install dependencies pnpm install # Copy environment variables (optional for dev) cp .env.example .env.local
2. Start development server
# Full environment (recommended)
pnpm devThis starts:
- Next.js on
http://localhost:3000- Main application - OIDC Mock on
http://localhost:3001- Mock authentication provider - MSW Mock Server on
http://localhost:9090- Mock backend API
Note: For other development modes (different combinations of mock/real services), see the Development Modes section below.
3. Code quality checks
Before committing:
# Run all checks pnpm lint # Check code style pnpm format # Auto-fix formatting pnpm type-check # Verify TypeScript pnpm test # Run test suite
Git hooks (via Husky) automatically run linting on staged files.
4. API client updates
When the backend API changes:
# Fetch latest swagger.json and regenerate client pnpm generate-client # Files updated: # - swagger.json # - src/generated/**
Note: Never edit files in src/generated/ manually - they are auto-generated.
Development modes
Choose the mode that best fits your development needs:
Mode 1: Full stack development (default - recommended)
What runs:
- ✅ Mock OIDC authentication (
localhost:3001) - ✅ Mock backend API via MSW (
localhost:9090) - ✅ Next.js dev server (
localhost:3000)
Best for: Frontend development without external dependencies
Mode 2: Mock OIDC + real backend API
What runs:
- ✅ Mock OIDC authentication (
localhost:3001) - ❌ No API mock - requires real backend API configured
- ✅ Next.js dev server (
localhost:3000)
Best for: Backend integration testing with mock authentication
Required configuration in .env.local:
API_BASE_URL=https://your-backend-api.com # Real backend API URLMode 3: Mock backend API + real OIDC
What runs:
- ❌ No OIDC mock - requires real OIDC provider configured
- ✅ Mock backend API via MSW (
localhost:9090) - ✅ Next.js dev server (
localhost:3000)
Best for: Authentication integration testing with mock backend
Required configuration in .env.local:
OIDC_ISSUER_URL=https://your-oidc-provider.com
OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret
OIDC_PROVIDER_ID=okta # or your provider
BETTER_AUTH_SECRET=your-secret
BETTER_AUTH_URL=http://localhost:3000Mode 4: Real services only
What runs:
- ❌ No OIDC mock
- ❌ No API mock
- ✅ Next.js dev server only (
localhost:3000)
Best for: Full production-like testing with real services
Required configuration in .env.local:
# Real OIDC provider OIDC_ISSUER_URL=https://your-oidc-provider.com OIDC_CLIENT_ID=your-client-id OIDC_CLIENT_SECRET=your-client-secret OIDC_PROVIDER_ID=okta # Real backend API API_BASE_URL=https://your-backend-api.com # Auth configuration BETTER_AUTH_SECRET=your-secret BETTER_AUTH_URL=http://localhost:3000
Testing
Unit/component tests
pnpm test # Run all tests pnpm test --watch # Watch mode pnpm test --coverage # With coverage
Uses Vitest + Testing Library + MSW.
E2E tests (Playwright)
pnpm exec playwright install # One-time browser install pnpm test:e2e # Run tests (auto-starts dev server if needed) pnpm test:e2e:ui # Playwright UI mode pnpm test:e2e:debug # With Playwright Inspector
Tests automatically start the dev stack if it's not already running. If you prefer to start it manually first, run pnpm dev before the tests.
Mock server
The project includes a standalone MSW mock server for development:
# Start standalone mock server pnpm mock:server # Available at http://localhost:9090
Features:
- Auto-generates mocks from OpenAPI schema
- Customizable fixtures in
src/mocks/fixtures/ - Custom handlers in
src/mocks/customHandlers/
See docs/mocks.md for details.
Environment variables
Required for production
| Variable | Description | Example |
|---|---|---|
OIDC_ISSUER_URL |
OIDC provider's issuer URL | https://auth.example.com |
OIDC_CLIENT_ID |
OAuth2 client ID | your-client-id |
OIDC_CLIENT_SECRET |
OAuth2 client secret | your-client-secret |
OIDC_PROVIDER_ID |
Provider identifier | okta, auth0, oidc |
BETTER_AUTH_SECRET |
Secret for token encryption | Generate with openssl rand -base64 32 |
BETTER_AUTH_URL |
Application base URL | https://your-app.example.com |
API_BASE_URL |
Backend API URL | https://api.example.com |
Optional
| Variable | Description | Default |
|---|---|---|
DATABASE_URL |
PostgreSQL connection for session storage | None (uses encrypted cookies instead) |
TRUSTED_ORIGINS |
Comma-separated list of trusted origins | BASE_URL,http://localhost:3002,http://localhost:3003 |
OPENROUTER_API_KEY |
OpenRouter API key for AI Assistant | None (assistant disabled without it) |
Note: The AI Assistant feature requires an OpenRouter API key. See the Assistant documentation for setup instructions.
Development (auto-configured)
When running pnpm dev, these are automatically configured:
NODE_ENV=development OIDC_ISSUER_URL=http://localhost:3001 OIDC_CLIENT_ID=web-client OIDC_CLIENT_SECRET=web-secret OIDC_PROVIDER_ID=oidc BETTER_AUTH_URL=http://localhost:3000 API_BASE_URL=http://localhost:9090
Configuration file
Copy .env.example to .env.local and fill in your values:
cp .env.example .env.local
Note: .env.local is git-ignored and should never be committed.
Docker
This project includes Docker support for containerized deployments.
Using Makefile (recommended)
# Show all available commands make help # Build Docker image make build # Start container make start # View logs make logs # Stop container make stop # Clean up (remove container and image) make clean # Rebuild from scratch make rebuild
The application will be available at http://localhost:3000.
Docker Compose (full stack)
Run the complete stack (UI + Registry Server + PostgreSQL) with Docker Compose.
Prerequisites
Clone the registry-server repo in the same parent directory:
git clone https://github.com/stacklok/toolhive-registry-server.git ../toolhive-registry-server
Services
| Service | Container | Port | Description |
|---|---|---|---|
| cloud-ui | toolhive-cloud-ui |
3000 |
Next.js frontend |
| auth-db | toolhive-auth-db |
5433 |
PostgreSQL for session storage |
| registry-api | toolhive-registry-api |
8080 |
Backend API (from registry-server) |
| registry-postgres | toolhive-registry-postgres |
5432 |
PostgreSQL for registry |
| oidc-mock | toolhive-oidc-mock |
4000 |
Mock OIDC (only with --profile mock) |
Note: The
auth-dbPostgreSQL schema is automatically initialized on first startup viadb/init.sql.
With real OIDC provider (Okta, Azure AD, Auth0, etc.)
-
Create a
.envfile with your OIDC credentials:OIDC_ISSUER_URL=https://your-org.okta.com OIDC_CLIENT_ID=your-client-id OIDC_CLIENT_SECRET=your-client-secret OIDC_PROVIDER_ID=okta # or: azure-ad, auth0, oidc -
Start the stack:
With mock OIDC (development)
No .env file needed:
With external API
To use an external backend API instead of the local registry-server, add API_BASE_URL to your .env:
# .env OIDC_ISSUER_URL=https://your-org.okta.com OIDC_CLIENT_ID=your-client-id OIDC_CLIENT_SECRET=your-client-secret OIDC_PROVIDER_ID=okta # Override local registry-server with external API API_BASE_URL=https://api.toolhive.example.com
Note: The local
registry-apicontainer will still start but won't be used.
Access
- UI:
http://localhost:3000 - API:
http://localhost:8080(or yourAPI_BASE_URL) - Auth DB:
localhost:5433(PostgreSQL) - OIDC Mock (if using
--profile mock):http://localhost:4000
Commands
make compose-up # Start with real OIDC (requires .env) + rebuild make compose-up-dev # Start without rebuild (uses existing images) make compose-up-mock # Start with mock OIDC + rebuild make compose-down # Stop all services make compose-logs # View logs make compose-build # Rebuild images
Configuration combinations
| Command | OIDC | Backend API | Rebuild |
|---|---|---|---|
make compose-up |
Real (from .env) |
Local registry-server | Yes |
make compose-up-dev |
Real (from .env) |
Local registry-server | No |
make compose-up + API_BASE_URL |
Real (from .env) |
External API | Yes |
make compose-up-mock |
Mock (:4000) |
Local registry-server | Yes |
Kubernetes / Kind deployment
This project includes a complete Helm chart for deploying to Kubernetes (optimized for Kind).
Quick start with kind
# Create cluster and deploy (first time) make kind-setup # Or step by step: # 1. Create Kind cluster make kind-create # 2. Deploy application make kind-deploy # 3. Access the application make kind-port-forward # Then open: http://localhost:8080 # View logs make kind-logs # Uninstall make kind-uninstall # Delete cluster make kind-delete
Helm chart
The Helm chart is located in the helm/ directory and includes:
- Deployment with configurable replicas
- Service (ClusterIP/NodePort/LoadBalancer)
- Horizontal Pod Autoscaler (optional)
- Configurable resource limits
- Health checks (startup, liveness and readiness probes)
- Security contexts following Pod Security Standards
CI/CD
The chart is automatically tested on every push using GitHub Actions with Kind:
- Helm Lint: Validates chart syntax and best practices
- Integration Test: Deploys to Kind cluster and verifies the app responds
Project documentation
For detailed information about the project:
- AGENTS.md - Project overview, architecture, and key patterns
- CLAUDE.md - Detailed development guidelines
- docs/mocks.md - MSW mock server documentation
- AI Assistant - AI Assistant feature documentation (requires OpenRouter API key)
- CONTRIBUTING.md - How to contribute
Technology stack
- Framework: Next.js 16 (App Router)
- Language: TypeScript (strict mode)
- UI: React 19 + shadcn/ui + Tailwind CSS 4
- Auth: Better Auth (OIDC)
- API client: hey-api
- Testing: Vitest + Testing Library
- Linting: Biome
Related projects
- toolhive-registry-server - Backend API implementing the official MCP Registry API
- ToolHive Desktop UI - Desktop application for running and managing MCP servers locally
External resources
- Next.js Documentation
- Better Auth Documentation
- hey-api Documentation
- shadcn/ui Components
- MCP Registry Official
Deploy on Vercel
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.
Contributing
We welcome contributions! Please see our Contributing Guide for details on how to get started.
License
This project is licensed under the Apache License 2.0. See the LICENSE file for details.