Skip to main content
Glama

Zava Relocation MCP UI Demo

Watch the demo: 2-minute narrated walkthrough

Zava Relocation Inc. helps employees move for a new job. This project is a reference demo for building an interactive MCP App with MCP-UI, a local Qwen2.5 7B model, and a synchronized conversational intake form.

The user can chat with Ava, upload an offer letter, or edit the profile directly. Extracted information is applied to the form immediately and highlighted so the user can review what changed.

For a customer-facing teaching walkthrough, see the dedicated MCP UI + LLM form-fill guide.

What the demo demonstrates

  • Chat-driven form completion with live field updates

  • Optional browser voice mode: speak to Ava and hear Qwen responses aloud

  • PDF and DOCX offer-letter extraction in the browser

  • Local interpretation with Qwen2.5 7B through Foundry Local

  • Five profile sections: contact, employment, move, moving logistics, and preferences

  • Grounded moving-option and reimbursement guidance from the fictional Contoso policy PDF

  • Progress tracking, highlighted AI updates, reset, and completion state

  • Responsive desktop and mobile layouts

  • MCP Apps resource/tool linkage through @mcp-ui/server and @modelcontextprotocol/ext-apps

  • A production build that inlines the UI into one HTML resource

Demo boundary: This is a local prototype. It does not persist relocation cases, authenticate users, or submit data to a production HR system. The sample PDFs in sample-documents/ contain fictional data.

Related MCP server: Docalyze

Architecture

MCP Apps host
      |
      | Streamable HTTP: POST /mcp
      v
Node + Express MCP server
      |-- start_relocation_intake tool
      |-- ui://zava-relocation/intake resource
      |-- POST /api/chat
      v
Foundry Local (same machine)
      |
      v
Qwen2.5 7B

Browser UI
  |-- PDF.js / Mammoth extract document text locally
  |-- regex extractor gives immediate form updates
  |-- /api/chat sends text and current form to local Qwen

There are two ways to use the UI:

  1. Standalone mode: Vite serves the React application at http://localhost:5173.

  2. MCP App mode: An MCP Apps-compatible host connects to http://localhost:3001/mcp, discovers start_relocation_intake, and renders the linked ui://zava-relocation/intake resource.

How MCP-UI is leveraged

This project uses the MCP Apps pattern recommended by MCP-UI:

  1. server/index.ts creates an McpServer and a StreamableHTTPServerTransport.

  2. The production dist/index.html is loaded into a UI resource using createUIResource.

  3. registerAppResource publishes that resource at ui://zava-relocation/intake.

  4. registerAppTool exposes start_relocation_intake and links it to the UI with:

    _meta: {
      ui: { resourceUri: relocationUI.resource.uri },
    }
  5. The embedded UI signals readiness with ui-lifecycle-iframe-ready and can send host messages with window.parent.postMessage.

The important distinction is that the MCP server does not render the form itself. It registers the tool and UI resource; the MCP Apps host decides where and how to display that resource.

Foundry Local and Qwen2.5 7B

The assistant uses Qwen2.5 7B through Foundry Local. Foundry Local runs on the same machine as this Node server and exposes an OpenAI-compatible local chat-completions endpoint. No cloud model fallback is configured.

Prerequisites

Foundry Local support depends on the host machine. On Windows, Microsoft documents Windows 11 24H2 or later, .NET 9 or later, and a DirectX 12-capable GPU for the Windows ML runtime.

Install the Foundry Local CLI:

winget install Microsoft.FoundryLocal

Close and reopen PowerShell, then verify the CLI:

foundry --version

List the model aliases available in the local catalog:

foundry model list

Start or download the Qwen model using the alias shown by the catalog. The expected demo alias is:

foundry model run qwen2.5-7b

Keep Foundry Local running while using the demo. The current Foundry Local service endpoint for this project is:

http://127.0.0.1:61563/v1/chat/completions

If the installed catalog uses a different alias or port, configure the Node server before starting it:

$env:FOUNDRY_LOCAL_ENDPOINT = "http://127.0.0.1:<actual-port>/v1/chat/completions"
$env:FOUNDRY_LOCAL_MODEL = "qwen2.5-7b-instruct-cuda-gpu"

Foundry Local assigns the service port dynamically. Use foundry service status or foundry service list to inspect the active service, and use GET http://127.0.0.1:<port>/openai/models to list available model IDs. The exact model ID can vary by hardware; on this machine the available Qwen GPU model is qwen2.5-7b-instruct-cuda-gpu.

What the model receives

server/foundryLocal.ts sends Qwen:

  • The latest user message or a document-review instruction

  • The current form state

  • Up to 8,000 characters of extracted document text

The system prompt asks Qwen to return JSON in this shape:

{
  "reply": "I found your new employer and start date.",
  "fields": {
    "employer": "Northstar Analytics",
    "role": "Senior Product Manager",
    "startDate": "2026-10-07"
  }
}

Only allowlisted form keys are accepted by the server. The model cannot add arbitrary fields to the client state.

Voice mode

Qwen2.5 7B remains a text-only model. Voice mode uses browser capabilities around the existing text pipeline:

microphone
  -> browser SpeechRecognition
  -> transcript
  -> POST /api/chat
  -> Foundry Local + Qwen
  -> text reply and form fields
  -> browser SpeechSynthesis
  -> spoken Ava response

Click the microphone button in the composer to speak. When recognition ends, the transcript is submitted through the same chat flow used by typed messages. The Ava voice on/off control enables or disables spoken replies, Voice lets you choose an installed browser voice, and Stop Ava interrupts the current response. The app prefers Microsoft/Edge natural English voices when available, such as Ava, Jenny, Aria, or Sonia. Chrome and Edge provide the best support; microphone permission is required and voice input needs localhost or HTTPS. Voice quality depends on the voices installed and exposed by the browser.

Voice input uses a guided one-field-at-a-time flow. The app identifies the next incomplete required field, asks Qwen to focus on that field, advances the active form section after the answer, and speaks one short next question. This keeps each voice turn easy to remember. Typed chat remains free-form.

Document parsing flow

The browser handles the original file; the file itself is not uploaded to a cloud service:

  1. src/App.tsx validates the extension and 10 MB limit.

  2. src/documentParser.ts uses PDF.js for PDFs and Mammoth for DOCX files.

  3. The extracted text is sent to local Qwen through POST /api/chat for document interpretation.

  4. Qwen returns structured fields. The UI uses a consistent document-review message telling the user to review the form and manually complete any missing information; it does not enumerate missing fields.

  5. The model fields are applied and highlighted in the form.

Grounded logistics walkthrough

Upload contoso-moving-offers-and-reimbursement-guide.pdf, then ask Ava questions such as “Which option is best for a 250-mile move?” or “Can I use a rented truck for 150 miles?” The browser keeps the extracted policy text as grounding for later chat turns, and the model is instructed to answer policy questions only from that text. The Moving logistics section captures the selected method, approximate distance, reimbursement path, and notes.

The browser-side PDF.js and Mammoth libraries are text extraction utilities only; they do not decide which values belong in the relocation form. Foundry Local/Qwen is the source of truth for PDF/DOCX field extraction. If the model is unavailable, the UI reports the error instead of silently filling document fields with a non-LLM parser.

Code breadcrumbs

Area

File

Purpose

Main UI

src/App.tsx

Chat, form sections, uploads, reset, progress, MCP host messages

Styling

src/styles.css

Zava layout, responsive behavior, light/dark theme variables

Form types

src/types.ts

IntakeForm, FormField, Message, and blank initial state

PDF/DOCX parsing

src/documentParser.ts

Browser-side PDF.js and Mammoth extraction

Immediate extraction

src/extraction.ts

Labeled values, dates, phone, email, and relocation phrase matching

Local LLM client

server/foundryLocal.ts

OpenAI-compatible request, JSON validation, field allowlist

MCP server

server/index.ts

Express routes, MCP transport, tool/resource registration

Dev proxy

vite.config.ts

Proxies browser /api calls to port 3001

Sample files

sample-documents/

Fictional offer letters for upload testing

Single-file build

vite.config.ts

vite-plugin-singlefile inlines JavaScript and CSS

Install and run

Install Node dependencies:

npm install

Standalone development mode

Start Vite and the MCP server together:

npm run dev

Open:

http://localhost:5173

The Vite /api proxy forwards local model requests to port 3001.

MCP Apps mode

Build the UI first. The MCP server embeds the resulting dist/index.html:

npm run build
npm start

Configure the MCP Apps-compatible host with:

http://localhost:3001/mcp

Then call:

start_relocation_intake

The server also exposes a basic health check:

http://localhost:3001/health

Demo workflow

  1. Start Foundry Local and make the Qwen model available.

  2. Run npm run dev.

  3. Click a quick prompt or type a relocation message.

  4. Watch the matching fields populate and highlight.

  5. Upload one of the PDFs in sample-documents/.

  6. Review the extracted and model-enriched fields.

  7. Use Reset demo to return to a blank state.

Useful chat prompts:

  • I'm moving from Seattle to Austin for a role at Contoso.

  • My family has 3 people.

  • Employer: Fabrikam

  • Position: Senior Product Manager

  • I need temporary housing.

Troubleshooting

Could not connect to Foundry Local

Check that Foundry Local is running, that the model has been downloaded/loaded, and that the endpoint matches FOUNDRY_LOCAL_ENDPOINT.

Model not found

Run foundry model list and set FOUNDRY_LOCAL_MODEL to an alias in the installed catalog.

The MCP server says Missing dist/index.html

Run:

npm run build

before npm start.

The form does not find fields in a document

The PDF must contain selectable text. Scanned/image-only PDFs need OCR before PDF.js can extract useful text. Labeled values such as Employee name:, Email address:, New employer:, Job title:, Start date:, Moving from:, and Moving to: are easiest for the deterministic extractor to recognize.

Scripts

Command

Purpose

npm run dev

Start Vite and the MCP server in watch mode

npm run dev:ui

Start only Vite

npm run dev:mcp

Start only the MCP server in watch mode

npm run build

Type-check and create the single-file production UI

npm start

Start the MCP server against dist/index.html

npm run preview

Preview the Vite production build

To regenerate the fictional Contoso policy PDF, install the script dependency and run the generator:

python -m pip install -r scripts/requirements.txt
python scripts/generate_contoso_policy_pdf.py
F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server that enables AI assistants to perform semantic searches over local document collections using multi-context organization and automatic OCR. It supports various file formats including PDF, DOCX, and images, ensuring all data processing remains local and private.
    6
    MIT
  • A
    license
    B
    quality
    D
    maintenance
    An MCP server that lets AI assistants read and visually analyze local documents — PDFs, Excel spreadsheets, CSV files, Word documents, PowerPoint presentations, and images.
    4
    56
    MIT

View all related MCP servers

Related MCP Connectors

  • Self-hosted MCP gateway: turn any API, database or MCP server into AI connectors — no code.

  • Hosted MCP server exposing US hospital procedure cost data to AI assistants

  • MCP server giving Claude AI access to 22+ NYC public-record databases for real estate due diligence

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/stvflowers/zava-mcp-ui'

If you have feedback or need assistance with the MCP directory API, please join our Discord server