Documentation Index
Fetch the complete documentation index at: https://docs.mcpjungle.com/llms.txt
Use this file to discover all available pages before exploring further.
MCPJungle dashboard frontend development
1. What the dashboard is
The Dashboard UI is served by the MCPJungle Go server at/ in development mode.
2. Frontend architecture
Frontend source
- Frontend app root: web/dashboard
- Main React entry: web/dashboard/src/main.tsx
- Main app component: web/dashboard/src/App.tsx
- Shared components: web/dashboard/src/components
- API helpers: web/dashboard/src/lib/api.ts
- Frontend types: web/dashboard/src/lib/types.ts
- Global styles: web/dashboard/src/styles.css
Stack
- Framework: React 18 + TypeScript
- Build tool: Vite
- React plugin:
@vitejs/plugin-react
Built assets
- Vite build output:
web/dashboard/dist - Go-served dashboard asset directory:
internal/dashboardui/dist - Embed wiring: internal/dashboardui/embed.go
internal/dashboardui/embed.go embeds dist at Go compile time:
internal/dashboardui/dist and then embedded into the Go binary.
How the Go server serves the frontend
Dashboard route registration is in internal/api/server.go. WhenDashboardService is available, the server registers:
GET /GET /index.htmlGET /assets/*filepath
dashboardui.FileServer() from internal/dashboardui/embed.go.
Are assets embedded or served from disk?
For the real MCPJungle server, assets are embedded into the Go binary. The Go server does not readweb/dashboard/src directly at runtime.
During frontend-only development, you can also run the Vite dev server at http://localhost:5173/.
Backend dashboard handlers
Dashboard API handlers live in:- internal/api/dashboard.go
- internal/api/dashboard_mutations.go
- internal/api/dashboard_oauth.go
- internal/api/dashboard_tool_groups.go
- internal/service/dashboard/service.go
fetch("/api/dashboard/...") through the helpers in web/dashboard/src/lib/api.ts.
Routing model in the frontend
The dashboard is a single React app with section-state navigation. It does not use React Router today.- Sidebar items are defined in web/dashboard/src/components/NavSidebar.tsx
- Active page state is controlled in web/dashboard/src/App.tsx
/.
3. Local development workflow
Recommended workflow while changing frontend code:Install frontend dependencies
web/dashboard/package-lock.json exists, so npm is the expected package manager here.
Run the Go backend
From the repo root:http://localhost:8080.
If you are using the installed CLI instead of go run, the equivalent command is:
Run the frontend dev server
In another terminal:http://localhost:5173.
Which URL to open during active frontend development
Open:- Vite hot reload works there
- CSS/React changes update immediately
/api/*requests are proxied to the Go backend onhttp://localhost:8080
Do API calls go through CORS?
No special CORS setup is needed for normal frontend development because Vite proxies/api requests to the Go backend.
When to open http://localhost:8080/
Open http://localhost:8080/ when you want to verify the real Go-served embedded dashboard, not just the Vite dev server.
4. Build workflow
This is the most important workflow.After I change frontend code, what do I run so it shows up at http://localhost:8080/?
From the repo root:
- Run the shared dashboard build script.
- Rebuild or rerun the Go server so it embeds the updated files.
- Refresh
http://localhost:8080/.
What the build script does
scripts/build-dashboard.sh is the canonical dashboard bundle refresh step for both local development and releases.
It does:
cd web/dashboardnpm ciifnode_modules/is missingnpm run buildrm -rf internal/dashboardui/distcp -R web/dashboard/dist internal/dashboardui/dist
Why is the restart required?
Because dashboard assets are embedded into the Go binary at build/run time. Updatingweb/dashboard/dist or internal/dashboardui/dist alone does not update an already-running server process.
Do generated assets need to be committed?
No.dist/ is ignored in .gitignore, and internal/dashboardui/dist is also treated as a generated artifact.
What is the final served UI source?
The UI served fromhttp://localhost:8080/ comes from:
- Vite build output in
web/dashboard/dist - copied into
internal/dashboardui/dist - embedded by internal/dashboardui/embed.go
- served by internal/api/server.go
What happens if the frontend build is stale?
Common symptom:http://localhost:5173/shows your new UIhttp://localhost:8080/still shows the old UI
- you did not run
bash ./scripts/build-dashboard.sh - the Go server is still running an old embedded build
5. Go server integration
Where the dashboard routes are registered
Go route registration is in internal/api/server.go. Dashboard UI routes:GET /GET /index.htmlGET /assets/*filepath
/api/dashboard/...
How / serves the dashboard
The router uses dashboardui.FileServer() and wraps it with:
s.requireInitialized()requireDashboardMode
How local/dev mode is checked
Dashboard mode gating is in internal/api/middleware.go.requireDashboardMode() checks the current server mode from request context and only allows the dashboard when:
mode == model.ModeDev
404 Not Found
What happens in enterprise mode
If MCPJungle is started with:SERVER_MODE=enterprise, dashboard UI routes and dashboard API routes return 404.
How static assets are wired
- Embedded source: internal/dashboardui/embed.go
- File server registration: internal/api/server.go
Frontend fallback routing
There is no multi-route SPA fallback setup today because the dashboard currently uses a single entrypoint and in-app section switching instead of browser URL routing.6. Dashboard backend APIs
Where routes are defined
Dashboard routes are registered in internal/api/server.go. Handlers live in:- internal/api/dashboard.go
- internal/api/dashboard_mutations.go
- internal/api/dashboard_oauth.go
- internal/api/dashboard_tool_groups.go
Current route groups
Read endpoints
GET /api/dashboard/overviewGET /api/dashboard/serversGET /api/dashboard/toolsGET /api/dashboard/tool-groupsGET /api/dashboard/tool-groups/:nameGET /api/dashboard/promptsGET /api/dashboard/resourcesGET /api/dashboard/diagnostics
Mutation endpoints
POST /api/dashboard/serversDELETE /api/dashboard/servers/:namePATCH /api/dashboard/servers/:name/enabledPATCH /api/dashboard/tools/:name/enabledPATCH /api/dashboard/prompts/:name/enabledPOST /api/dashboard/tool-groupsDELETE /api/dashboard/tool-groups/:name
OAuth flow endpoints
GET /api/dashboard/oauth/callbackGET /api/dashboard/oauth/session/:id
Common patterns
- Read handlers usually delegate to
dashboard.Service - Mutation handlers usually reuse
mcp.MCPServiceortoolgroup.ToolGroupService - Frontend uses relative
fetch("/api/dashboard/...")
How to add a new dashboard API endpoint
Typical steps:- Add the route in internal/api/server.go.
- Add the handler in the appropriate dashboard API file under
internal/api/. - Reuse existing service logic where possible instead of reimplementing CLI behavior.
- Add/extend response types in pkg/types or local dashboard response structs if the API is dashboard-specific.
- Add frontend types in web/dashboard/src/lib/types.ts.
- Add a frontend helper in web/dashboard/src/lib/api.ts.
- Update the UI in web/dashboard/src/App.tsx.
- Add tests in
internal/apiorinternal/e2e.
Error handling
Handlers generally:- return
400for bad request / binding errors - call
handleServiceError(...)for service-layer errors
- internal/api/errors.go
Secret handling
Dashboard APIs must not expose:- tokens
- OAuth client secrets
- env var values
- authorization headers
- raw sensitive config
/api/v0/server_configs for the dashboard without sanitizing them first.
7. OAuth registration flow
Dashboard registration supports MCP servers that require upstream OAuth.Why dashboard OAuth differs from CLI OAuth
The CLI can create its own localhost callback server. See cmd/register.go. The browser frontend cannot do that, so the dashboard uses the MCPJungle Go server as the OAuth callback receiver.Current dashboard OAuth flow
- User submits
+ Add Serverin the dashboard. - Backend tries normal registration in internal/api/dashboard_mutations.go.
- If upstream OAuth is required, backend retries registration with:
- If the upstream server returns
AuthorizationRequired, the backend returns202 Acceptedwith:authorization_required.session_idauthorization_required.authorization_urlauthorization_required.expires_at
- Frontend opens the authorization URL in a new tab.
- Frontend polls:
- Upstream OAuth redirects back to:
- Backend completes the upstream OAuth session.
- Frontend sees completion via polling, closes the modal flow, and refreshes dashboard data.
Important implementation files
- CLI OAuth flow reference: cmd/register.go
- Dashboard registration entrypoint: internal/api/dashboard_mutations.go
- Dashboard callback + polling: internal/api/dashboard_oauth.go
- Upstream OAuth service logic: internal/service/mcp/upstream_oauth.go
- Frontend registration modal: web/dashboard/src/App.tsx
- Frontend API helpers: web/dashboard/src/lib/api.ts
Important constraints
- Do not expose OAuth codes, tokens, or secrets in the UI.
- The callback HTML page is intentionally simple.
- Pending dashboard OAuth completion state is tracked server-side and cleaned up after expiry/retention.
8. Common frontend tasks
Add a new sidebar page
- Add the section key/type in web/dashboard/src/lib/types.ts
- Add the sidebar item in web/dashboard/src/components/NavSidebar.tsx
- Add the section title/meta and render branch in web/dashboard/src/App.tsx
- If the page needs backend data, add an API helper in web/dashboard/src/lib/api.ts
Add a new dashboard API call
- Backend route: internal/api/server.go
- Backend handler:
internal/api/dashboard*.go - Frontend helper: web/dashboard/src/lib/api.ts
- Frontend response type: web/dashboard/src/lib/types.ts
Add a new table column
- UI rendering usually lives directly in web/dashboard/src/App.tsx
- Styling usually goes in web/dashboard/src/styles.css
- If the data is not already in the response, add it to the dashboard API response first
Add a new button or action
- UI button: web/dashboard/src/App.tsx
- API call: web/dashboard/src/lib/api.ts
- Backend mutation handler: internal/api/dashboard_mutations.go or internal/api/dashboard_tool_groups.go
Add a new expanded row/details panel
Patterns already exist on:- Tools
- Tool Groups
- Prompts
- Servers
Add a copy button
Reuse:- web/dashboard/src/components/CopyButton.tsx
aria-labeltitle
Add a filter/search field
Current filtering patterns live in web/dashboard/src/App.tsx using local React state plus derived filtered arrays.Add a new form/modal
Current examples:- server registration modal
- tool group creation modal
- add local form state
- add validation
- call dashboard API helper
- refresh dashboard data after success
- show inline mutation error/success feedback
9. Styling and design notes
Current v1 visual direction:- GitHub-like developer dashboard
- white / very light gray backgrounds
- subtle gray borders
- black / dark gray text
- green for primary actions and enabled/healthy states
- compact rows
- endpoints
- canonical names
- transports
- URIs
- command strings
- Avoid raw JSON as the default UI
- Prefer expandable rows for detail inspection
- Keep copy buttons close to the values they copy
- Keep detail panels compact and scan-friendly
- show human-readable schema/argument fields by default
- raw JSON, if present, should be fallback/debug-only
- raw JSON fallback should be collapsed by default
10. Testing and validation
Frontend checks
Fromweb/dashboard:
Backend/dashboard test commands
From the repo root:- internal/e2e/dashboard_test.go
- internal/e2e/tool_groups_test.go
Manual smoke-test checklist
- Start MCPJungle in dev mode and open
http://localhost:8080/. - Confirm the default page is
Servers. - Add a server.
- If possible, test an OAuth-required registration.
- Enable/disable a server.
- Delete a server.
- Enable/disable a tool.
- Enable/disable a prompt.
- Create and delete a tool group.
- Copy:
- endpoint
- canonical tool name
- canonical prompt name
- resource URI
- tool group endpoints
- Expand rows on:
- Tools
- Prompts
- Tool Groups
- Open
System Info. - Confirm the dashboard does not expose secrets.
11. Troubleshooting
Frontend changes do not show up at localhost:8080
Likely causes:
- you changed code while looking at the Vite dev server and forgot the Go-served UI uses embedded built assets
- you forgot
npm run build - you forgot to copy
web/dashboard/distintointernal/dashboardui/dist - the Go server is still running an older embedded build
- browser cache
- you are checking
http://localhost:8080/instead ofhttp://localhost:5173/during active frontend work
Frontend dev server works but Go-served UI does not
That usually means the Vite app is correct but the embedded Go-served bundle is stale. Remember:http://localhost:5173/uses live source + Vitehttp://localhost:8080/uses built/copied/embedded assets
Dashboard returns 404
Check:- MCPJungle is running in dev mode, not enterprise mode
- you started the real server
- the server is initialized
404 outside development mode. See internal/api/middleware.go.
API calls fail
Check:- the Go backend is running on
localhost:8080 - you are calling the right
/api/dashboard/...path - if using
npm run dev, the Vite proxy is active
5173 works but API calls fail, inspect:
- web/dashboard/vite.config.ts
OAuth registration gets stuck
Check:- the backend returned an authorization URL
- the auth tab actually opened
- the upstream provider redirected back to
/api/dashboard/oauth/callback - polling to
/api/dashboard/oauth/session/:idis succeeding - the session did not expire
- internal/api/dashboard_oauth.go
- internal/api/dashboard_mutations.go
- internal/service/mcp/upstream_oauth.go
Copy buttons do nothing
Copy buttons use the browser clipboard API. If copy fails:- check the browser console
- make sure the page is running in a normal browser context
- retry from the real UI page rather than an unusual embedded browser/webview
12. Release and build notes
Before cutting a release or shipping a frontend change, maintainers should:- Run frontend checks:
- Refresh the embedded dashboard bundle:
- Run backend/dashboard tests:
- Rebuild and run MCPJungle.
- Verify the dashboard from the Go server at
http://localhost:8080/, not only fromhttp://localhost:5173/.
bash ./scripts/build-dashboard.sh in its before.hooks, so release artifacts automatically include a fresh embedded dashboard bundle.
13. Keep this doc maintainable
When updating this document:- use real repo paths
- use real commands from this repo
- update page names if UI nav changes
- update API route lists if dashboard endpoints change
- update the build section whenever the embed/copy workflow changes
- prefer short, practical repo-specific guidance over frontend theory
