QDG Knowledge Base Read-only viewer QWebHub
workflow

Production handover

Version 3 · Publish the reviewed production handover and verify the versioned update path.

QDG Knowledge Base MCP production handover

Date: 4 September 2026

Outcome

The QDG Knowledge Base MCP is a central team service on Odin. Codex and Claude clients connect to https://qdb.qdatasite.com/mcp/qdg-kb with an individual bearer token. QWebHub terminates public HTTPS and proxies only that exact path to the service on 127.0.0.1:8972. Only the service has the MySQL writer password.

“QDG Knowledge Base” is the canonical product/data name. “KB Wiki” and “QDG Wiki” are legacy or informal names; the backing MySQL schema remains qdgwiki.

Fixes and safeguards applied

  • Confirmed the real Odin/IIS/MySQL topology with read-only inventory instead of assuming that the repository matched production.
  • Corrected the unrelated \QWebHub\Restart scheduled task so it restarts the QWebHub application pool rather than AdminManagement; all reviewed websites returned HTTP 200 after the change.
  • Created the loopback-only qdgkb_writer@localhost account with table-specific read/write permissions and no administrative/database-wide privileges.
  • Stored the database password and token hashes under protected ProgramData ACLs; raw bearer tokens remain only in the private inventory.
  • Installed a dedicated, pinned Python 3.13.15 runtime and isolated application venv instead of trusting the shared, user-writable Python tree.
  • Installed the service as the virtual account NT SERVICE\QDG-KB-MCP; code/runtime are read/execute, database/token config is read-only, and only its own log/runtime folders are writable.
  • Corrected 187 Python cache ACLs that inherited rather than explicitly protected the intended Administrator/SYSTEM-only rules.
  • Verified the writer password, exact MySQL grants, allowed table reads and denial of migration/system-table reads.
  • Imported the existing 30-token inventory without changing token values; Odin stores hashes only.
  • Verified local startup, authentication, MCP tool discovery and database access.
  • Added the exact route to the overarching QWebHub site after confirming that the internal qdb-backend site was not the public entry point.
  • Enabled Automatic (Delayed Start), restarted the service and repeated both the QWebHub and independent public HTTPS tests successfully.
  • Corrected MySQL 8.4 locking permissions: kb_projects now includes UPDATE for its locking read, while application hotfix b974c4e restricts the page-update lock to mutable kb_pages and preserves immutable version-history permissions.
  • Completed the public write canary: created this operations project/page, published immutable version 2 as Robert, and confirmed a stale update is rejected.

Decisions not to repeat

  • Do not deploy an ignored working copy for the long term. Build releases from a reviewed commit with pinned artifacts and a recorded version.
  • Do not assume a working website proves the MCP route works; test missing-token, invalid-token and valid-token requests through the public hostname.
  • Do not place a public route on a plausible backend site before proving the actual ingress chain. QWebHub is the public route owner in this deployment.
  • Do not give the MCP shared web_admin, root, DDL, DELETE or GRANT OPTION access.
  • Do not grant UPDATE on kb_page_versions; joined locking reads must explicitly lock only the mutable kb_pages row.
  • Do not put raw tokens, MySQL passwords or protected Odin inventories in source, command lines, screenshots, chat or shared documents.
  • Do not use a single generic team token when per-person history and independent revocation matter. Generic enabled slots must be relabelled before issue.
  • Do not make ad-hoc edits without a byte-for-byte backup, exact target checks and post-change verification. The successful scripts deliberately failed closed and restored state when their assumptions were wrong.
  • Do not combine unrelated QWebHub application changes with an MCP release. The MCP route is a narrow infrastructure rule; QWebHub source remains a separate concern.

Client setup

Codex:

[mcp_servers.qdg_kb]
url = "https://qdb.qdatasite.com/mcp/qdg-kb"
bearer_token_env_var = "QDG_KB_TOKEN"
default_tools_approval_mode = "writes"

Claude project .mcp.json:

{
  "mcpServers": {
    "qdg_kb": {
      "type": "http",
      "url": "https://qdb.qdatasite.com/mcp/qdg-kb",
      "headers": {
        "Authorization": "Bearer ${QDG_KB_TOKEN}"
      }
    }
  }
}

Each teammate sets their own token locally as QDG_KB_TOKEN, restarts the client, and runs qdg_kb_status. A successful connection makes the shared documentation available; project rules/workflows must still tell assistants when to publish or update documentation during commits and handovers.

Operations

  • Service: Get-Service QDG-KB-MCP
  • Private config: C:\ProgramData\QDG\Config\QDG-KB-MCP
  • Logs: C:\ProgramData\QDG\Logs\QDG-KB-MCP
  • Audit evidence: C:\ProgramData\QDG\DeploymentAudit\QDG-KB-MCP
  • Public check: deployment\Test-PublicMcp.ps1 -InventoryPath <private inventory>
  • Token procedure: FIRST_TOKEN.md
  • Current evidence and known cleanup: ROLLOUT_STATUS.md

The installed package reports version 0.1.0 plus the guarded b974c4e locking hotfix. Its byte-for-byte backup and receipt are under the audit-evidence directory. The next normal release must package that source correction under a new version.

The next release should use a versioned updater that stages a new venv, stops the service, swaps application versions, preserves ProgramData secrets, starts and runs health/auth/database checks, then automatically rolls back on failure.

Updated by Robert on Sept. 4, 2026, 9 a.m. · Task: production-deployment-2026-09-04 · Commit: 3b0045b