AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP verified MIT Self-run

Okforge Webui

mcp-okforge-okforge-webui · by okforge

LAN web UI + job runner for okforge knowledge bases: scanned PDF -> VLM OCR -> translated, page-cited LLM wiki. Serial job queue, MCP server, Quartz publishing.

No reviews yet
0 installs
13 views
0.0% view→install

Install

$ agentstack add mcp-okforge-okforge-webui

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/mcp-okforge-okforge-webui)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
20d ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Okforge Webui? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

okforge-webui

A LAN web UI and job runner for okforge knowledge bases: drop a scanned book in an inbox and drive it through VLM OCR, optional translation, and ingestion into an LLM-synthesized wiki — then browse, query, and publish the result. Built for local-first setups where the LLM is your own llama.cpp/vLLM box, not a cloud API.

The pipeline is five screens: probe (inspect the PDF: text layer? language? page count) → pilot (OCR a page or three, check the transcription and image crops before committing) → project (pick or name the project that collects the output) → run (chunked OCR → translate → markdown with live progress) → verify & use (review the markdown, ingest it into the project's knowledge base, then query and publish). OCR and ingestion are always separate steps, so the same tool doubles as a pure PDF→markdown converter — skip the ingest and take the files from md-out/.

Inputs: PDFs, page-scan images (jpg/png/tif/bmp — wrapped into PDF on upload so the OCR pipeline handles them), and your own markdown/text documents (added straight to a project, no OCR). Selecting several PDFs/images at once combines them into one PDF in natural file-name order — the upload shows the exact order and combined name before anything is sent. Other formats (docx, pptx, html …) should be pre-converted to markdown first.

What's in the box

  • Serial job queue (sqlite + one worker, on purpose): one add or

OCR run at a time protects single-slot LLM hosts and the engine's per-KB ingest lock. Jobs survive backend restarts; every finished job keeps its log. One-click resume/retry, a stall watchdog (flags, never kills), per-chunk ETA from real history, and a git pre-ingest snapshot of the KB before every add.

  • Markdown first, ingest second: every run OCRs into the project's

md-out// folder (chunked .md + page maps + image crops); hand-made markdown/text files can be added to the same folder from the UI ("Add markdown…" — no OCR involved); ingesting that markdown into the knowledge base is a separate step — a one-click button in the verify stage (KB stats update chunk by chunk) or an auto-ingest toggle on the run. The KB is created on first ingest — or never, if all you wanted was the markdown.

  • Archive-first deletes: removing an uploaded PDF, a project's

markdown, a published site, or a whole project moves it to trash/ (KBs retire to kbs-retired/) — nothing in the UI is destructive, restore is a mv back.

  • OCR + image extraction via

okforge-vision-ocr (one VLM call per page: markdown transcription + photo bounding boxes together), with a table mode for pages the fast path mangles and a per-page re-OCR + re-ingest repair loop.

  • Translation workflow for non-English scans: faithful transcription

first, page-by-page translation second — both language versions share one image directory and page citations survive.

  • Wiki browser with lexical search (source hits carry real page

numbers), image lightbox, and markdown rendering.

  • MCP server at /mcp (streamable HTTP): list_projects,

project_status, ask, search, read_wiki_page. Connect any MCP client, e.g. claude mcp add --transport http okforge http:///mcp. Clients that don't surface MCP server instructions (Open-WebUI and other OpenAPI-bridged clients) should get the recommended system prompt from [docs/MCP_CLIENT_PROMPT.md](docs/MCPCLIENTPROMPT.md).

  • Static-site publishing per KB via Quartz

— full-text search, graph view, backlinks — one button, then a printed rsync command to go public.

Prerequisites

  • An OpenAI-compatible LLM endpoint — the whole pipeline's brain

(llama.cpp or vLLM on your own hardware, or a hosted service; see Configuration). For the OCR path the endpoint's model must be vision-capable (Qwen-VL family or similar) — it reads page images. Text-layer extraction, ingestion, and querying work with any capable chat model.

  • Python 3.10+
  • Git — for the clone; on Windows it also provides the grep

binary the engine's query agent uses.

  • Node.js 18+ — only for the optional static-site publishing

(Quartz); everything else runs without it. Quartz is a one-time, once-per-machine install into the shared quartz dir (/quartz, or OKFORGE_WEBUI_QUARTZ_DIR) — clone it, check out v5, npm ci, then npx quartz plugin install; the exact steps are in [OPERATIONS](docs/OPERATIONS.md#publishing-a-kb-as-a-website-quartz). Skipping the plugin install step is the usual first-publish failure: the build aborts with Could not resolve "../../.quartz/plugins", which is exactly the dir that step generates. On a LAN-only / offline box, also disable the default og-image emitter in quartz.config.ts (it fetches a font over the network at build time and otherwise fails); nothing else in Quartz needs outbound access.

Directory layout

/                 e.g. /opt/okforge/  or  C:\okforge\
    okforge-webui/      ← this repo; .venv/ inside it
    kbs//      ← one self-contained knowledge base per subject
    inbox/              ← PDF drop point for the web UI
    md-out//   ← OCR'd markdown per project (created on demand)
    kbs-retired/        ← retired KBs (archive-first "delete")
    trash/              ← web-UI deletes move things here, never erase
    quartz/             ← shared Quartz install (site publishing, optional)
    sites//    ← published static sites (optional)

The base directory can be anywhere — all defaults are relative to where this repo sits (each is individually overridable by env var, see Configuration). Every KB is self-contained (sources, wiki, engine state, .env, its own git history) — copy the directory and you've copied the KB. The UI discovers KBs by scanning the KB root; nothing is registered anywhere else.

Install

Linux/macOS:

cd /opt/okforge   # or any base dir
git clone https://github.com/okforge/okforge-webui
cd okforge-webui
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
mkdir -p ../kbs ../inbox

Windows (PowerShell):

cd C:\okforge     # or any base dir
git clone https://github.com/okforge/okforge-webui
cd okforge-webui
python -m venv .venv
.venv\Scripts\pip install -r requirements.txt
md ..\kbs, ..\inbox

(PowerShell gotcha: anything in the current directory needs a .\ prefix to run — .\script.ps1, not script.ps1. The .venv\Scripts\… forms above already qualify.)

requirements.txt pins the two okforge packages from PyPI — the okforge engine (ingestion, wiki compilation, query; see its GETTINGSTARTED) and okforge-vision-ocr (pre-conversion console scripts) — plus the FastAPI backend's own dependencies.

Run it

One process serves the frontend, the API, and the MCP server. Run it from this repo's directorypython -m webui resolves the webui package relative to the current dir, so from anywhere else Python exits with No module named webui:

cd /okforge-webui
.venv/bin/python -m webui          # Linux/macOS
.venv\Scripts\python -m webui      # Windows
# browse http://:8500/

OKFORGE_WEBUI_HOST / OKFORGE_WEBUI_PORT change the bind (default 0.0.0.0:8500 — LAN-visible; use 127.0.0.1 to keep it local). Same trust model in every mode: LAN-only, no auth — don't expose it beyond a network you trust.

First time? Follow the [small-test walkthrough](#first-run--start-with-a-small-test) below before pointing it at a whole book.

To run it as a service: on Linux, [webui/deploy/okforge-webui-standalone.service](webui/deploy/okforge-webui-standalone.service) is a ready-to-edit systemd unit; on Windows, use Task Scheduler ("At startup", run \.venv\Scripts\python.exe -m webui) or NSSM.

Optional: Apache in front (Linux)

For port 80, a LAN vhost name, and an easy basic-auth option, deploy.sh installs Apache (static docroot + /api/ reverse proxy) in front of the same backend under systemd:

SERVER_NAME=okforge.local OKFORGE_WEBUI_ENDPOINTS="gpu1=http://gpu1:8080/v1" \
    webui/deploy.sh

deploy.sh is idempotent — rerun it after changes (it restarts the backend, so never while a job is running). In this mode frontend files are served by Apache, so frontend-only changes are sudo rsync -a --delete webui/static/ /var/www/okforge-webui/ (standalone mode serves them straight from the repo — nothing to copy).

First run — start with a small test

Prove the whole loop — endpoint, OCR quality, ingest, query — on a handful of pages before committing to a book. Five pages take about ten minutes on a local GPU; a 300-page book is an overnight-plus run (see [ingest cost](docs/OPERATIONS.md#ingest-cost-at-collection-scale-measured)). Everything below happens in the browser at http://:8500/.

  1. Check the header. Pick your LLM server in the dropdown; the

status light beside it polls the server, so a steady light means you're actually talking to it. This choice gets baked into the knowledge base at first ingest (queries and MCP clients then use it too — [changeable later](#how-the-endpoint-choice-binds-to-a-kb)).

  1. Stage 1 — get a document in. Upload a short PDF — or a few

phone photos of pages, which combine into one PDF (the panel shows the page order before anything uploads; it comes from the file names). The probe runs automatically: scan means the OCR pipeline (the normal path), text means an embedded text layer you can optionally trust in stage 4.

  1. Stage 2 — pilot one page. Enter one page number with real

content on it (not the cover) and Run pilot. Read the transcription beside the rendered page; check the image crops. Bad OCR here means bad OCR everywhere, so fix it now — table mode for complex tables, --figures if line drawings were missed, or an OCR hint ("ignore marginalia"). Re-run until the page reads right.

  1. Stage 3 — create a project. Use a throwaway name like

MyBook-test — you'll delete it after the test (one click, and nothing is ever erased — it all moves to trash/).

  1. Stage 4 — run a small range. Set From page / to to a few

content pages, tick ingest into KB when OCR finishes, and Start run. The queue shows one plain-language row ("working — n/m chunks OCR'd"; ▸ expands the technical steps) and markdown appears in stage 5 as chunks finish.

  1. Stage 5 — verify and ask. Read the markdown. Watch the

knowledge-base stats tick up as chunks ingest; a one-line project description is written automatically at the end, and Publish unlocks when the last chunk is in. Then ask the knowledge base a question — answers cite source pages as (p. N).

  1. Happy? Delete the test and run for real. Delete project… in

stage 3, then repeat with the real project name and the full page range. (If you'd rather keep the test: make its range exactly the first chunk — e.g. pages 1–20 at the default 20 pages per chunk — and the full run will skip it instead of re-OCRing it.)

What a small test catches early: a wrong endpoint or non-vision model (pilot fails or returns junk), OCR quirks your document needs hints for, and a misconfigured model paying a hidden reasoning block on every call — a 20-page chunk should ingest in a couple of minutes on a local 27B model, not 27 (see the llm_extra_body note below).

Configuration

Everything is an environment variable (for the systemd deployments, set them in the unit — deploy.sh passes any that are exported when it runs). `` below means the directory this repo sits in.

> Note: these use the OKFORGE_WEBUI_* prefix. The pre-rebrand > OPENKB_WEBUI_* names (and OPENKB_DIR for the engine dir) still work > — the backend reads the new name first and falls back to the old one, > printing a one-time deprecation line on stderr naming what to rename.

| variable | default | meaning | |---|---|---| | OKFORGE_WEBUI_HOST | 0.0.0.0 | bind address (python -m webui) | | OKFORGE_WEBUI_PORT | 8500 | bind port (python -m webui) | | OKFORGE_WEBUI_ENDPOINTS | local=http://localhost:8080/v1 | LLM endpoints for the UI dropdown, comma-separated label=url[\|key[\|model]] — key and model only for hosted services (see below) | | OKFORGE_WEBUI_DEFAULT_ENDPOINT | first label | pre-selected endpoint | | OKFORGE_WEBUI_MODEL | openai/Qwen3.6-27B-MTP | model string new KBs are initialized with (per-endpoint model overrides it) | | OKFORGE_WEBUI_KB_ROOT | /kbs | where KBs live | | OKFORGE_WEBUI_INBOX | /inbox | PDF drop dir | | OKFORGE_WEBUI_MD_OUT | /md-out | per-project OCR'd markdown | | OKFORGE_WEBUI_RETIRED_DIR | /kbs-retired | where retired KBs move | | OKFORGE_WEBUI_TRASH | /trash | where web-UI deletes move things | | OKFORGE_WEBUI_QUARTZ_DIR | /quartz | shared Quartz install | | OKFORGE_WEBUI_SITES_DIR | /sites | published-site output | | OKFORGE_WEBUI_PUBLIC_SITE_HOST | localhost | public host for published sites' baseUrl | | OKFORGE_WEBUI_PUBLIC_SITE_DEST | user@host:/var/www/sites | rsync target shown by the go-public helper | | OKFORGE_WEBUI_NODE | node on PATH, else /usr/bin/node | node binary for Quartz builds | | OKFORGE_WEBUI_ENGINE_DIR | this repo | dir whose .venv holds the engine + okforge-vision-ocr console scripts — set this only if that .venv lives somewhere other than this repo (shared or parent-dir venv) |

The documented install puts .venv inside the repo, which is why OKFORGE_WEBUI_ENGINE_DIR needs no setting by default. If you instead share one .venv across checkouts or keep it in the base dir, point this var at the directory that contains it — otherwise the UI looks for openkb/okforge-vision-ocr under /.venv/bin and reports them missing.

Local llama.cpp/vLLM endpoints need only label=url. A hosted OpenAI-compatible service takes two more |-separated fields — its API key and the model in LiteLLM provider/model format:

OKFORGE_WEBUI_ENDPOINTS="gpu1=http://gpu1:8080/v1,openrouter=https://openrouter.ai/api/v1|sk-or-v1-...|openrouter/qwen/qwen3.6-27b"

KBs created on such an endpoint get the key in their .env, the model in their config.yaml, and a provider-appropriate thinking-off block (OpenRouter's reasoning.enabled=false instead of llama.cpp's chat_template_kwargs). OCR/translate jobs strip the LiteLLM provider prefix and pass the rest as the OpenAI-protocol model name. Note the key lives in plain text in the unit file/environment — acceptable on a single-operator LAN box; protect the systemd drop-in accordingly (chmod 640).

How the endpoint choice binds to a KB

The endpoint picked in the header is baked into each knowledge base at first ingest: that's when the KB's own .env (OPENAI_API_BASE, LLM_API_KEY) and config.yaml (model, thinking-off block) are written. From then on, everything that touches that KB — later ingests, the stage-5 Ask box, and the MCP server's ask tool — uses the KB's own endpoint, regardless of what the header currently shows. (The header selection still drives OCR/translate runs, which produce markdown before any KB exists.) So two KBs on one machine can happily run against two different LLM servers, and an MCP client querying a project lights up whichever server that project pins.

To repoint an existing KB (LLM moved to a new box, or a new model): edit those two files in the KB directory — .env for the URL and key, config.yaml for model: — and the next call uses them; no restart, nothing to re-register. Keep the llm_extra_body block a

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.