Endara Desktop

A tray app that bundles Endara Relay, manages its lifecycle, and gives you a UI for adding endpoints, running OAuth flows, and watching tool calls live — no terminal required.

Overview

Endara Desktop is a Tauri 2 tray application that wraps the relay. It bundles the endara-relaybinary as a sidecar, spawns it on launch, monitors its health, restarts it if it crashes, and kills it cleanly on quit. Everything you can do from the relay's management API — adding endpoints, completing OAuth flows, browsing tools, streaming logs — is available from the UI, which reaches the management API through a local socket rather than HTTP.

If the relay sidecar exits unexpectedly (an external kill, OS-initiated termination, or a crash), Endara Desktop restarts it automatically with bounded exponential backoff (1s, 2s, 4s, 8s, 16s, capped at 30s). The header status dot turns amber and pulses with a Relay restarting… label during the gap, then flips back to green when the new relay is healthy. After 5 consecutive failed restarts in a short window the supervisor backs off and shows Relay crashed repeatedly; auto-restart suspended. Click Restart to retry. The attempt counter resets after 60 seconds of healthy uptime, so a stable relay that crashes once an hour never hits the cap. Intentional shutdowns (Quit, manual Restart, port conflict) never trigger auto-restart.

In the standard install, the desktop owns the relay. There is no separate background service: the relay's lifetime is bounded by the desktop's lifetime. The relay's MCP endpoint binds to 127.0.0.1:9400 in production (and 127.0.0.1:9500 in dev), so any MCP client on the same machine can reach it over loopback. The management API used by Endara Desktop is exposed on a separate local Unix-domain socket / Windows Named Pipe — see Management API.

Under the hood the UI is a SvelteKit frontend (Svelte 5 + Tailwind CSS 4). It talks to the bundled relay's management API through a Tauri command (relay_api_request) that proxies HTTP semantics over a local Unix-domain socket (macOS / Linux) or Windows Named Pipe — never over a TCP port. This means a malicious page in your browser can't reach /api/* even if it guesses the right URL. Both the GUI and the bundled relay are open source — see endara-ai/endara-desktop.

Install

macOS — Homebrew (recommended)

brew install --cask endara-ai/tap/endara

Installs the latest signed and notarized DMG from the endara-ai/homebrew-tap tap and registers the app for brew upgrade. The built-in Tauri updater also continues to work, so new versions arrive whichever way you prefer.

Direct downloads

Grab an installer for your platform from github.com/endara-ai/endara-desktop/releases:

PlatformFormatFile
macOSDMG installerEndara_x.x.x_aarch64.dmg
WindowsNSIS setupEndara_x.x.x_x64-setup.exe
WindowsMSI installerEndara_x.x.x_x64_en-US.msi
LinuxDebian packageendara_x.x.x_amd64.deb
LinuxAppImageEndara_x.x.x_amd64.AppImage
NoteDon't mix the bundled relay with a separately-installed CLI relay. See Troubleshooting → Port 9400 in use.

First run

Launch the app. The Endara icon appears in your menu bar (macOS) or system tray (Windows / Linux), and the bundled relay starts automatically on 127.0.0.1:9400. Click the tray icon and choose Open Endara to bring up the main window.

From the dashboard you'll see an empty endpoint list (left sidebar) and a detail panel on the right. Add your first MCP server from + Add server, then point any MCP client at http://localhost:9400/mcp. For Claude Desktop, drop this into claude_desktop_config.json:

{
  "mcpServers": {
    "endara": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "http://localhost:9400/mcp"]
    }
  }
}

Claude Desktop's config file does not accept HTTP URLs directly — entries with a top-level url field are silently stripped on startup. The snippet above uses mcp-remote as a stdio shim that proxies to the relay over loopback. It requires npx on your PATH (ships with Node.js).

For Cursor, paste http://localhost:9400/mcp under Settings → MCP → Add new MCP server → HTTP. Restart the client and your endpoint's tools show up in its tool list, prefixed by the endpoint name.

Start on Login

Open Settings (⌘, on macOS) and toggle Start on Login. On macOS this registers a LaunchAgent at ~/Library/LaunchAgents/Endara Desktop.plist that re-launches the desktopat login — the desktop then spawns the relay as its child. The LaunchAgent does not run the relay directly. On Linux and Windows, autostart uses the platform's native mechanism (XDG autostart and the Windows registry, respectively).

Keyboard shortcuts

ShortcutAction
⌘KOpen global tool search
⌘,Open settings
EscGo back / close panel

Managing endpoints

An endpoint is one MCP server the relay talks to. The sidebar lists every endpoint with a transport badge (STDIO / SSE / HTTP / OAuth) and a health dot — 🟢 healthy, 🟡 degraded, 🔴 failed. Endpoints that are still spinning up display an Initializing…label in place of the usual tool count; the relay's parallel async startup means slow remote/OAuth servers no longer hold up the rest of the UI. Selecting one opens a detail panel with tabs for tools, logs, config, and (for OAuth endpoints) auth.

Add a server

Click + Add server and choose a transport:

Saving the form writes the new [[endpoints]] entry into ~/.endara/config.toml. The relay's file watcher picks the change up and reloads adapters without a restart — see hot reloadin the relay docs. Once the adapter is healthy, the modal's Advanced section surfaces the upstream-reported serverInfo.name alongside the prefixed-tool preview, so you can see exactly what the relay learned from the server.

The Add Server modal also exposes a Server type override field under Advanced. Use it when an upstream MCP server reports a placeholder or unhelpful serverInfo.name(e.g. Google's hosted MCP servers all self-identify as statelessserver). The override replaces the label the relay advertises to connected clients in Connected server types: — tool-name routing (the tool_prefix) is unaffected. See tool prefixing for the full story.

If you start typing in the configure step and then dismiss the modal (Escape, backdrop click, or Cancel), Endara asks Discard changes?before closing. The catalog browse step (before you've picked a server) still closes instantly. The per-endpoint Config tab applies the same guard to any navigation away from unsaved edits — clicking a different server in the sidebar, switching to another inner tab, jumping to a top-level tab, pressing Cmd+,, or using the Unified Catalog's jump-to-endpoint icon all prompt before discarding. Saving clears the dirty state.

Edit, disable, or remove

Right-click an endpoint (or use the menu) to edit its configuration, temporarily disable it, restart its adapter, or remove it altogether. Disabling keeps the entry in config.toml but unloads the adapter; removing deletes the entry. STDIO adapters that crash are restarted automatically with exponential backoff — their logs stream to the Logs tab, which renders each line as a structured row — timestamp, color-coded level pill (ERROR, WARN, INFO, DEBUG, TRACE), endpoint chip, and message — with a filter bar above for free-text search, per-level toggles, and an endpoint multiselect; tool-call events are highlighted inline. The per-endpoint Logs tab live-streams new lines scoped to that endpoint only. The per-endpoint Config tab also exposes server_type_override inline so you can change the advertised label without leaving the detail panel.

Browse tools

The Tools tab lists every tool the endpoint exposes, with the prefixed name the relay advertises (<name>__<tool>), the input schema, and the description. The global ⌘K palette searches across every connected endpoint at once.

Containerized stdio servers

Local (STDIO) servers run inside their own per-endpoint container by default, for stronger isolation and clearer observability. Endara auto-detects a container runtime — docker or podman — and runs each server in a small mcp-runner image that ships with uvx and npx on the path, so the usual launch commands work without installing anything on the host. If no runtime is detected, Endara falls back to spawning the server directly, exactly as before.

The endpoint detail panel shows a status badge — CONTAINERIZED (docker) or DIRECT — alongside live CPU, memory, and network stats for the container. The Config tab adds an isolation toggle and a volume-mount editor that takes Docker-style host:container pairs, so servers that need host paths (key files, Unix sockets) can be wired up from the UI. The Logstab surfaces each container's stderr line by line, tagged [stderr], so a failure shows the server's own error message instead of a cryptic exit code.

Endpoint profiles

Profiles let you serve a named subset of your endpoints under their own MCP URL — for example, a work profile reachable at http://localhost:9400/mcp/work that only exposes the servers you added to it. See Endpoint profiles in the relay docs for the URL shape and protocol details; this section covers the Desktop UI.

Create and delete profiles

Open the Profiles tab in the main window. Click + New profile, give it a short name (used in the URL), and submit — the profile shows up immediately with an empty allow-list. Right-click a profile (or use its menu) to rename or delete it. Deleting a profile removes its entry from config.toml and tears down its URL; the underlying endpoints are untouched.

Add servers to a profile

From the profile detail page, click + Add serverand pick from a list of registered endpoints. Or open any server's detail panel and use its Profiles sub-tab to toggle membership in each profile. Both flows write straight to config.toml and the relay picks up the change without a restart.

Per-profile TOON + JS Execution toggles

Each profile carries its own JS Execution and TOON Output toggles on the profile detail page, independent of the global toggles on the Settings page. Flip JS Execution on for an agent that benefits from the meta-tool surface while keeping it off for another agent on the same machine, or run one profile in raw-JSON mode for a tool that needs JSON while keeping TOON on everywhere else.

Copy a claude_desktop_config.json snippet

The profile detail page includes a copy button that yields an mcp-remote-based snippet ready to paste into claude_desktop_config.json, pointed at the profile's URL. The same pattern works for any stdio-only client that can't speak streamable HTTP directly.

OAuth setup

Some MCP servers require an OAuth flow before they expose any tools. Endara Desktop runs the entire flow inside the app: you fill in the + Add serverdialog, complete the provider's consent screen in your default browser, and the relay receives the authorization code on a loopback redirect URI at http://127.0.0.1:9400/oauth/callback.

Add an OAuth endpoint

From + Add server, choose OAuth and fill in:

If the authorization server supports Dynamic Client Registration (RFC 7591), the relay registers a client automatically and you don't have to provide a client_id. If not, follow Manual client setup below.

Manual client setup (Google, GitHub, etc.)

For providers without DCR, register an OAuth app yourself before adding the endpoint. Use these values when registering the app:

Back in the + Add server dialog, expand the Advanced section and paste the client_id (and client_secretif the provider is a confidential client) before submitting. If the relay still attempts DCR and the authorization server rejects it, the dialog falls back to a manual credentials prompt — paste the same values there. Credentials are persisted via the relay's management API into ~/.endara/tokens/ with mode 0600; they are not written into config.toml. See OAuth credential storage in the relay docs for details.

Run the flow

Submitting the + Add serverdialog kicks off the OAuth flow automatically: your default browser opens the provider's consent screen, and after you approve, the provider redirects to 127.0.0.1:9400/oauth/callback. The relay exchanges the code for a token, stores it, and the new endpoint appears in the sidebar with its Auth tab badge set to Authenticated. Tools become available immediately.

Token lifecycle

Just-in-time sign-in

Endara also handles servers that require sign-in without you having to pick the OAuth transport up front. When you add an http/sse server that advertises OAuth, Endara detects it at add-time and offers to walk you through the OAuth setup wizard right away; declining still saves a plain HTTP endpoint. At runtime, if a tool call hits a server that needs sign-in (an HTTP 401 with a WWW-Authenticate challenge), the relay starts the OAuth flow and hands your client a sign-in URL instead of a raw error — after you sign in, retrying the call just works, and your AI client never sees the upstream 401 or any upstream credentials.

When an OAuth-protected server lands in a connection_failed state, the Auth tab surfaces recovery actions inline: Refresh Now attempts a silent token refresh when a refresh token is on hand, and Re-authenticatereopens the browser sign-in. The two share a busy state so they can't run at the same time.

Organizations (EMA)

PreviewEnterprise-Managed Authorization is a previewcapability. The relay's full sign-in → token-exchange → call chain is implemented and mock-validated, but a live run needs an identity provider and a resource authorization server that both support cross-app access / ID-JAG. No production catalog provider (GitHub, Linear, Slack, Atlassian, …) redeems ID-JAGs today, so you cannot EMA-connect them in production yet. See the relay EMA reference for the full background and the per-provider setup matrix.

An organization is one identity-provider sign-in shared across every MCP server that org governs. Connect it once and Endara detects the servers your organization grants — no per-server URLs or OAuth flows to run by hand.

Connect an organization

From + Add server, choose Connect an organization. The flow walks through:

  1. Pick a provider — Okta, Microsoft Entra ID, Google, PingOne, or Custom.
  2. Name the organization (e.g. Acme Corp) and supply its slug (Okta subdomain, Entra tenant, Ping environment id) or, for Custom, paste the full issuer URL. Endara previews the resolved issuer inline.
  3. Client ID (optional) — paste a pre-registered IdP client id. This is required for Okta and Entra, which do not support automatic client registration. The form reminds you that the IdP app must whitelist http://127.0.0.1:9400/oauth/callback(or your relay's dev port, 9500) — byte-exact, with 127.0.0.1 rather than localhost.
  4. Sign in — clicking Connect opens the IdP consent screen in your browser. Endara polls until the sign-in lands.
  5. Detecting— Endara probes which MCP servers the org's credentials can reach.
  6. Review & select — pick the detected servers you want. Confirming creates an auth.type = "ema" endpoint per server, all sharing the org's pooled ID token.

See the per-provider matrix for the exact app type, issuer, grants (Authorization Code + Refresh Token), and scopes (openid offline_access) to register at each IdP.

Bind a custom server to an organization

You can also route a server you add manually through an existing organization. In + Add server, for a URL-based (HTTP/SSE) server, use the Organization selector. The default, None — use this server's own authentication, keeps the server's per-endpoint OAuth. Choosing an organization instead creates an EMA endpoint bound to that org (the server URL becomes the EMA resource), and the per-server OAuth fields are hidden. The selector is disabled with a Connect an organization hint when none exist yet, and never appears for stdio servers.

Manage organizations (Settings)

Settings → Organizations lists every connected org with a status pill (Connected vs Sign-in required). Each row offers:

JS execution mode

Endara Desktop exposes a toggle for the relay's JS execution engine. When enabled, the relay stops advertising every tool from every endpoint to the model. Instead it advertises three meta-tools — list_tools, search_tools, and execute_tools — and lets the model run a sandboxed JavaScript program that calls the underlying tools in a single round-trip.

Toggle it from Settings → JS Execution Mode. The relay reloads in place; any open MCP clients pick up the new tool list on their next refresh. The sandbox is in-process boa_engine with no network or filesystem access — see sandbox limits and the meta-tool reference for the full surface area.

WhyAdvertising hundreds of tool definitions on every model turn burns context tokens. JS execution mode trades that for a one-time teach-the-model-to-search step and lets the model fan out across many tools in a single program. See Why this exists in the relay docs.

TOON output format

Endara Relay re-encodes JSON-shaped tool-call responses to TOON (Token-Oriented Object Notation) before forwarding them to MCP clients, which typically cuts tool-response token usage by 40-60% on the structured shapes most MCP tools return. The encoding is lossless and applies to both the native tools/call path and the relay's meta-tool responses.

Toggle it from Settings → TOON Output Format, directly below the JS Execution Modetoggle. The toggle defaults to on (matching the relay's default) and persists to config.toml as [relay] toon_output. Changes take effect immediately — the running relay sidecar reloads in place, so you do not have to restart the app or the relay process. Flip it off to forward JSON responses unchanged.

Tool-call overlay window

Endara Desktop ships an always-on-top, click-through overlay window that surfaces every MCP tool call routed through the relay as a live card. Cards flash in-flight (blue), turn green on success, or red on failure, then dismiss after a short countdown so the overlay stays out of your way when nothing is happening.

Each card shows the calling client, the upstream server, the tool name, and the call status (for example Claude Desktop → Linear). Repeat calls to the same tool stack into a single card with rising counts and a rolling-average duration, so a burst of activity appears as one entry instead of a wall of toasts. Clicking a card jumps straight to that request in the desktop Logs view.

Settings

The overlay is enabled by default. Toggle it on or off from the tray menu (Show overlay) or from the new Overlay section of Settings, which also lets you pick the screen corner (any of the four), the maximum number of visible cards, and whether the overlay is suspended while the main Endara window is focused. Every option persists across launches.

How it works

The overlay consumes the relay's tool-call event bus — GET /api/events/tool-calls(server-sent events) on the management API — bridged through the desktop's relay sidecar rather than spoken over loopback HTTP. If the relay sidecar restarts (manual restart, auto-restart after a crash), the overlay re-subscribes automatically once it's healthy again.

Because the overlay is click-through, it never steals focus from windows beneath it — clicks fall through to whatever is under the cursor. The only interactive surface is the optional click target on each card that jumps to the corresponding Logs entry.

Observability

The Observability tab records every proxied tools/call routed through the relay, so you can see exactly what flows through it — the server and tool involved, which client made the request, how long it took, whether it succeeded or failed, and the request and response sizes. Search across calls and filter by server, tool, status, and time window, with latency sparklines to spot slow tools at a glance.

Drill into any call for a detail view that shows the captured request and response payloads in a collapsible JSON viewer, complete with copy and a full-screen pop-out. A confirm-guarded Purge all data action clears the history when you need a clean slate.

Capture, retention, and payload storage are configurable under Settings → Observability: toggle capture on or off, set the retention window, cap the database size, and bound the payload budget.

Tray health indicator

The Endara tray icon displays a small colored dot reflecting overall relay health at a glance — green when everything is healthy, yellow when one or more endpoints need attention (most commonly an OAuth sign-in), and red when the relay itself is failed, stopped, or unreachable. You can see whether anything wants you without opening the app.

Status line in the menu

The first item in the tray menu (and the tooltip on hover) spells out a specific reason instead of a generic label. The exact strings:

The tray menu also contains the existing Open Endara, Show overlay, Restart relay, and Quitentries. If the icon doesn't appear at all on your system, see Tray icon doesn't appear in Troubleshooting.

Troubleshooting

Relay not starting / port 9400 in use

If the desktop reports the relay failed to start with EADDRINUSE, another process is already bound to 127.0.0.1:9400. The most common cause is having both the bundled relay (inside Endara Desktop) and a separately-installed CLI relay (brew install endara-ai/tap/endara-relay) running. Pick one. Dev builds listen on 127.0.0.1:9500instead — substitute that port below if you're running a dev build.

Find the process holding the port:

# macOS / Linux
lsof -nP -iTCP:9400 -sTCP:LISTEN   # use 9500 for dev builds

# Windows (PowerShell)
Get-NetTCPConnection -LocalPort 9400 -State Listen

Stop whichever instance you don't want. The desktop's relay watchdog restarts the bundled relay automatically on the next health check; if it stays in a failed state, open Settings and use the relay-restart action shown when the relay is down. See also Relay troubleshooting.

NoteThe relay's management API (/api/*) does not bind a TCP port — it lives on a Unix-domain socket / Windows Named Pipe (see Management API). Don't look for an api.sock conflict in the diagnostic above; a separate failure mode is covered in the next subsection.

Management socket conflict (UDS / Named Pipe)

The management API binds to a per-user local endpoint. If the bundled relay reports it can't bind the socket or pipe, a previous process likely left a stale entry behind after a hard kill. The relay attempts to clean these up automatically on the next start, but you can verify and remove the stale entry by hand if needed.

Socket and pipe names include a stable hash of the relay's data-dir (<suffix> below), so the dev build (~/.endara-dev) and the installed production build (~/.endara) get distinct endpoints and can run side-by-side. Locations:

Check whether a stale socket is present:

# Linux — replace <suffix> with the value from the relay's startup logs
ls -l "$XDG_RUNTIME_DIR"/endara-relay-*/api.sock

# macOS
ls -l "$TMPDIR"/endara-relay-$(id -u)-*/api.sock

# If you confirm the relay isn't running, a stale file is safe to remove:
rm -f "$XDG_RUNTIME_DIR"/endara-relay-*/api.sock   # or the macOS path above

Named Pipes on Windows do not leave a file on disk — the OS releases the pipe when the owning process exits, so the same hard-kill scenario isn't a concern. If a pipe-binding failure persists, another endara-relay instance is still running under the same user account.

Tray icon doesn't appear

If the Endara tray icon is missing from the menu bar — or the Open Endaraentry isn't showing in the tray menu — first quit and relaunch the app. On macOS, check System Settings → Control Center → Menu Bar Only for hidden items, and make sure Endara Desktop is allowed in System Settings → General → Login Items & Extensions if you expect it to launch at login. On Windows and Linux, confirm the system tray / notification area is enabled and not collapsed behind an overflow chevron.

OAuth redirect failed

If the browser approves the consent screen but the Auth tab stays on Needs Login:

Endpoint stuck in failed or degraded state

Open the Logstab for that endpoint to stream the adapter's stderr live. STDIO adapters auto-restart with exponential backoff, so a transient crash will recover on its own; persistent failures are usually a missing command, an unset env var, or an OAuth flow that hasn't completed. The relay's own log at ~/.endara/logs/relay.log.<YYYY-MM-DD> has the full picture.

Auto-update isn't finding new versions

The Tauri updater checks GitHub Releases. Make sure the app can reach github.com. On macOS you can also force an upgrade through Homebrew:

brew upgrade --cask endara-ai/tap/endara

On Windows and Linux, re-run the installer from the latest release.

Reset configuration

Quit Endara Desktop, then edit or delete ~/.endara/config.toml. The relay recreates a default config on next start if the file is missing. To force every endpoint back through OAuth, also remove ~/.endara/tokens/.

File locations (macOS)

On Linux and Windows the same parent/child model applies; only the paths differ — the desktop uses Tauri's standard log/config directories for the ai.endara.desktopidentifier, and autostart uses the platform's native mechanism (XDG autostart on Linux, the Run registry key on Windows) instead of a LaunchAgent.