I built a local AI chat client that never loses a response — even if you refresh mid-generation

11.07.2026 - 09:15

Read on dev.to

Your local LLM deserves a better front end

LM Studio, Ollama, llama.cpp, vLLM — local inference has never been easier to run. But the chat UIs around them? Mostly bare-bones. So I built Liquid Local AI Client : an Angular + NestJS + MongoDB chat app that talks to any OpenAI-compatible inference server, with a pile of features you don't usually get for free.

It's fully open source. Here's what makes it worth a look.


🔌 MCP tools, without depending on your inference server for it

Most local setups that support MCP (Model Context Protocol) rely on the inference server itself to orchestrate tool calls. LM Studio recently disabled that for localhost servers, which broke a lot of setups overnight.

This client sidesteps the whole problem: the NestJS backend runs its own MCP client, lists tools, converts them to plain OpenAI function-tool definitions, and executes tool_calls itself in a loop. Works with any backend that supports standard function calling — not just LM Studio.

MCP tool integration

On top of the built-in tools (file generation, ZIP bundling, image generation…), users can now register their own custom MCP servers right from the UI — auto-discovers the server's name and tools, lets you toggle individual tools on/off account-wide, and even opt a specific chat out of a server without touching the global config.

Chat MCP Management overview


🎙️ Talk to your model — literally

llama.cpp added audio input support, so I added a mic button. Record a voice message, it's hand-encoded as WAV client-side (not the lossy webm your browser wants to give you), sent as an input_audio content part, and played back in the chat as a custom-styled audio bubble — no ugly native <audio> controls.

Chat voice overview


🧟 Refresh the page mid-response? The AI keeps talking.

This is the one I'm proudest of. Every other local chat UI I've tried loses your in-progress response if you refresh, switch tabs, or your laptop sleeps. Not here.

Generation is fully decoupled from the HTTP connection that started it:

  • The chat gets its ID and is saved to the database before the model even starts responding — refresh at any point and you're back in the same chat, not a duplicate.
  • The backend keeps generating even if your browser disconnects — writes to a dead socket just get silently absorbed instead of aborting the whole thing.
  • Every chunk is buffered per-chat server-side. Reconnect (via a dedicated resume SSE endpoint) and you replay everything you missed, then keep streaming live — tool calls, reasoning, all of it, in the right order.
  • The sidebar even shows you which chats are actively generating with a subtle animated wave + pulsing dot, so you never lose track of an in-flight response while browsing other chats.

No polling-and-praying. No "please wait, reloading…". It just picks up where it left off.


🎨 AI image generation, baked in

The model can call generate-image-tool mid-conversation — it submits a job to a local InvokeAI instance, downloads the result, and drops it straight into the chat.

Image generator overview


🔐 End-to-end message encryption

Opt-in per chat: messages are AES-encrypted in the browser before they ever touch your inference server's own logs/message store. The model decrypts via an MCP tool call at inference time — from the user's side, completely invisible.


🛠️ Plus the usual (but done well)

  • Real-time SSE streaming, including reasoning/"thinking" deltas
  • Image upload with vision support
  • JWT auth, role-based access, subscription-aware token rate limiting
  • A genuinely nice Admin CMS for managing users and token-limit tiers

Admin CMS


Try it

git clone https://github.com/xsip/liquid-local-ai-client
npm install
npm start
Enter fullscreen mode Exit fullscreen mode

Point it at any OpenAI-compatible server, register, and go. Full setup docs, architecture breakdown, and API reference in the README.

If you're running local models and tired of chat UIs that fall apart the moment you refresh the page — give it a spin. ⭐ the repo if it's useful, issues and PRs welcome.