QCDatabase.AI

ai.qcdatabasePublished by qcdatabase.aiOfficial publisherv0.1.0Updated Oct 26, 2026

Connects AI assistants to QCDatabase.AI for everyday construction quality-control work.

Overview

AI-generated overview

Connects an AI assistant to QCDatabase.AI so it can manage construction QC projects, upload records, and close out turnover items.

What you can do
  • Sign in, check session status and pick the active project or company workspace
  • Browse projects, jobs, packages, line specs, lists, folders, schemas and project members
  • Upload, version, download, delete and restore documents, drawings and photos
  • Create and update map items on drawings, including bulk placement and zipmap uploads
  • Fill and submit PDF forms, add notes, and record repairs
  • Create ITP line items, mark work complete or accepted, and place or clear quality-hold locks
When to use it
Useful for construction quality-control teams already working in QCDatabase.AI who want an assistant to file documents and drawings, look up what is still missing for turnover, search project data, or draft and close out inspection items without leaving the chat.
Requirements
A QCDatabase.AI account with membership in the relevant company workspace and project. The hosted endpoint uses OAuth sign-in; the local Python package (3.10 or newer) signs in through a browser callback on port 8765, configurable with QCDB_CALLBACK_PORT, and stores the login in a per-user config folder.
Before you install
Sign-offs and acceptances are recorded under your name, and the server states you are responsible for those actions. Hold-point locks are quality gates, not security controls, and should only be placed or cleared at the owner's or an authorized inspector's request. Many tools write, delete (soft), or restore records. The login token is stored locally in store.json; run logout to forget it.

Installation

In SourceWeft

  1. Open QCDatabase.AI in the dashboard and add it to a workspace.
  2. Connect the required credentials. They are stored privately and never shown on public pages.
  3. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/ai.qcdatabase%2Fmcp/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config. The client completes OAuth sign-in on first connect.

{
  "mcpServers": {
    "qcdatabase-ai": {
      "type": "http",
      "url": "https://mcp.qcdatabase.ai/mcp"
    }
  }
}

README

QC Database MCP Server

A small program that lets an AI assistant (like Claude) do your everyday QC Database work for you — set the project you're working on, upload records, read what the AI pulled off a document, and find and close out the items still needed for a complete, traceable turnover package.

It runs on your own computer. Your AI assistant talks to it; it talks to QCDatabase.AI on your behalf, using your own login.

Built on the official Model Context Protocol Python library and the QC Database MCP specification — published at qcdatabase.ai/mcp_server_spec.md and kept in this repo as mcp_server_spec.md.


What you can ask your assistant to do

Once it's connected, you can talk to it in plain language. For example:

  • "Connect to QC Database." → signs you in (opens your browser once).
  • "Work on the Riverside Unit 2 project." → pins that project for the session.
  • "Upload this MTR to the Mill Test Reports folder."
  • "What's still missing for turnover on this project?"
  • "Show me the open reference requests assigned to me."
  • "Find welds that failed X-ray near line 12." → meaning-based (semantic) search across your project data, ranked by relevance.
  • "How do I create a test package in QC Database?" → answers from the built-in QC Database user manual, so you can learn the app without leaving your assistant.
  • "Attach this photo to that weld."
  • "Mark this inspection complete." (it will remind you that the sign-off is recorded under your name — that's your call, not the AI's).

Before you start

You need Python 3.10 or newer on your computer.

  • Windows: install from the Microsoft Store (search "Python") or from python.org/downloads. During the python.org install, tick "Add Python to PATH."
  • Mac: brew install python or get it from python.org/downloads.

To check it's installed, open a terminal (PowerShell on Windows, Terminal on Mac) and run:

python --version

You should see Python 3.10 or higher. (On some Macs the command is python3.)


Install

From a terminal, in this folder:

pip install ".[runtime]"

That's it. This installs the server and a command called qcdatabase-mcp.

If pip isn't found, try python -m pip install ".[runtime]" (or python3 -m pip install ".[runtime]").


Install in Claude Desktop

Claude Desktop launches this server for you and shows its tools in your chats. Set it up once:

1. Install the Claude Desktop app

If you don't have it, download it from claude.ai/download and sign in.

2. Open the config file

In Claude Desktop:

  1. Open Settings (Windows: menu ☰ → File → Settings; Mac: Claude → Settings).
  2. Go to the Developer tab.
  3. Click Edit Config.

This opens (and, if needed, creates) a file named claude_desktop_config.json. You can also open it directly:

  • Windows: %APPDATA%\Claude\claude_desktop_config.json
  • Mac: ~/Library/Application Support/Claude/claude_desktop_config.json

3. Add the QC Database server

Put this in the file. If the file already has other servers, just add the "qcdatabase" block inside the existing "mcpServers" section.

Windows:

json
{  "mcpServers": {    "qcdatabase": {      "command": "python",      "args": ["-m", "qcdatabase_mcp"]    }  }}

Mac (Python is usually python3 there):

json
{  "mcpServers": {    "qcdatabase": {      "command": "python3",      "args": ["-m", "qcdatabase_mcp"]    }  }}

Save the file.

If Claude can't start it (you see "python not found" or the server fails), use the full path to Python instead of just "python". Find it by running where python (Windows) or which python3 (Mac) in a terminal, then paste that path as the "command". For example on Windows:

json
{  "mcpServers": {    "qcdatabase": {      "command": "C:\\Users\\you\\AppData\\Local\\Programs\\Python\\Python312\\python.exe",      "args": ["-m", "qcdatabase_mcp"]    }  }}

(Use double backslashes \\ in Windows paths inside JSON.)

4. Restart Claude Desktop

Fully quit and reopen the app (on Windows, also close it from the system tray; on Mac, Quit with Cmd-Q — closing the window isn't enough). The new server only loads on a fresh start.

5. Confirm it loaded

Start a new chat and look for the tools/connector indicator (a slider or tool icon near the message box). Click it and you should see qcdatabase with its tools listed. If you don't, see Troubleshooting.

Then ask Claude to "connect to QC Database" to sign in — see below.


First time you use it

  1. Sign in. Ask the assistant to connect to QC Database (the login tool). Your web browser opens; log in and pick which company workspace you want to connect. That choice locks the connection to that one organization. You only do this once — it's remembered.

  2. Pick your project. Ask it to work on a project by name, or list your projects first. Almost every action happens "inside" a project, so the server asks you to choose one before it will do project work. You can switch projects any time.

  3. Get to work. Upload documents and drawings, check what's missing for turnover, create and close reference requests, add notes and photos, and so on.


What it can do (tool groups)

  • Session: login, logout, auth_status, whoami
  • Find your way around: list_tenants, list_projects, set_project, get_active_project, list_project_members, list_lists, list_list_items, list_map_item_schemas, get_map_item_schema, list_document_folders, list_form_schemas
  • Controlled-vocabulary lists: create_list_item, update_list_item, delete_list_item (a soft delete — the entry stops appearing in list reads but stays on record)
  • Projects, jobs & packages: update_project, list_jobs, create_job, update_job, list_packages, create_package, update_package, list_line_specs, create_line_spec, update_line_spec (updates change only the fields you pass; name a field in clear to empty it), attach_line_spec_documents, detach_line_spec_documents, generate_line_spec_requirements (an AI draft; save it with update_line_spec)
  • Upload records: upload_document, upload_document_version, download_document, upload_drawing, upload_large_format_drawing, upload_drawing_to_package, upload_drawing_version, upload_large_format_drawing_version, attach_photo
  • Drawings: list_drawings (filter by type, status, job, package, or updated_since to see only drawings changed since a date-time), get_drawing (incl. pixel width/height — the HTML5-canvas coordinate space for map items), export_drawing, export_large_format_drawing, update_drawing (identifying metadata), move_drawing_to_package (existing drawing and destination in the active project; only changes package assignment, without uploading or duplicating)
  • Fillable PDF forms: list_fillable_templates, get_fillable_template, download_fillable_template, submit_fillable_template
  • Documents: list_documents (filter by folder, status, job, package, tags and metadata values), get_document_history, delete_document, bulk_delete_documents, list_deleted_documents, restore_document, bulk_restore_documents (deletes are soft: the document is archived and can be restored). download_document is the document export
  • Structured data: get_document, set_document_extracted_data, list_map_items, get_map_item, create_map_item (place welds/flanges by pixel coordinates), update_map_item (rename, move, notes, assignee, working status), bulk_create_map_items, bulk_update_map_items (batch up to 500 items on one drawing/schema). Always call list_map_item_schemas first — see the CAD/PCF/.weldb note below
  • Zipmaps (a whole mapped drawing in one upload): inspect_zipmap, upload_zipmap — see Zipmaps
  • Repairs: list_repair_codes, add_map_item_repair
  • Inspection forms & notes: list_form_submissions, create_form_submission, get_form_submission, update_form_submission, complete_form_submission, create_note, list_notes, resolve_note
  • Photos: list_photos, attach_photo
  • ITP & sign-offs (your call): list_itp_line_items, get_itp_line_item, create_itp_line_item, update_itp_line_item, mark_map_item_complete, mark_map_item_accepted, mark_itp_complete, mark_itp_accepted
  • Quality-hold locks (witness/hold points — the user's call): list_lock_types (read only), list_locks, get_lock, add_lock (place a hold point — fit-up, tack-up, weld-cleanliness, FME, final-closure, boiler-tube FME sponge-in/sponge-out, etc. — on a map item or ITP line item so it can't be turned in until inspected), unlock_lock, assign_lock, delete_lock (withdraws a hold placed in error — a soft delete: kept in the audit trail, no longer holding the item; use unlock_lock for a hold that was actually satisfied). A lock is a construction quality gate, not a security control; place or clear one only at the explicit request of its owner/author or an authorized inspector. Creating or editing lock types (the named hold definitions, and who may place/clear each) is intentionally not exposed here — that permission-sensitive setup is done in the web app's Project Admin, and the assistant will point you there
  • Turnover (the important part): list_reference_requests, create_reference_request, list_references, create_reference, turnover_report
  • Shippers: list_shippers, get_shipper, list_shipper_line_items, list_shipper_types, list_shipper_locations, create_shipper, update_shipper, set_shipper_status, add_shipper_line_items, update_shipper_line_item, remove_shipper_line_item (a soft delete), reorder_shipper_line_items, delete_shipper (project admins only; a soft delete), unlock_shipper; checklists: confirm_shipper_checklist_item, unconfirm_shipper_checklist_item; receiving: receive_shipper_line_item, unreceive_shipper_line_item, add_shipper_line_item_note, remove_shipper_line_item_note, list_shipper_note_categories; audit_shipper, export_shipper_pdf; building a shipment: find_drawings_to_ship, get_drawing_bom_for_shipping, list_drawing_map_items_for_shipping, list_non_drawing_item_suggestions; settings (project admins): create_shipper_type, update_shipper_type, delete_shipper_type, create_shipper_location, update_shipper_location, delete_shipper_location. Any status other than draft locks a shipper until it is unlocked; checklists, receiving and notes work on locked shippers, with the web app's rules. Needs the shippers:write scope: connections approved before it was added must reconnect (stdio: run login again) to get it
  • Semantic search (meaning-based, ranked): semantic_search — natural-language search across the project's documents, drawings, large-format drawings, jobs, packages, list items, map items, form submissions, notes, and shippers
  • How QC Database works: search_user_manual (ask "how do I…?" questions and read the product help articles), list_user_manual (browse the help contents)
  • Trainings (playable trainings on redline.school): create_training, list_trainings, get_training, list_training_ideas, get_training_idea, get_training_policy (admins), upload_training_policy, get_training_authoring_guide, get_training_template, validate_training_bundle (free), upload_training_version (free; stores a private version only you can play), submit_training_review ($25 security review, needs confirm_charge), get_training_review and download_training_version (reviewed versions only, for co-developers). The local server zips a bundle folder itself and sends it straight to redline.school; on the hosted server, send a zip with begin_upload first. File contents never pass through the AI. These tools take an explicit scope rather than the active project. Connections approved before Trainings existed must re-approve to get trainings:read/trainings:write. Publishing, delisting and reassigning owners stay in the QC Database web app.
  • Training compliance: assign_training and invite_users (admins; both preview until confirm=True, at most 200 people), list_assignments (the Training Matrix: completed / due / overdue / expired, and blocked / grace for required trainings), list_permission_requirements (which permissions need a current training; set only in the web app) and get_my_trainings (any member, one call: required and completed trainings, results, links, and gated permissions). Gated actions (accepting map items or ITP rows, lock actions, gated forms) can fail with training_required; the error names the training, its expiry and the link to take it.
  • Training competition: get_training_leaderboard (any member who can play the game: ranked best scores by person, user type, project role or project, with your own rank) and get_engagement_report (admins: replays, voluntary plays, time trained, multiplayer, score improvement and trainings nobody replays, for the workspace, a project or one training).
  • Crew sessions (live multiplayer): start_crew_session (a published multiplayer training; returns the join code, join link and QR link the crew scans to play together, optionally with an in-app invite to a project), list_crew_sessions, get_crew_session (who joined, teams, results as games finish), end_crew_session and invite_project_to_crew_session. Starting, ending and inviting preview first and need confirm=True.
  • Build service: list_build_requests, get_build_request and, for PQS staff, quote_build_request (price, $0 allowed, and description; previews first; emails both sides). A PQS Training Builder sees the builds assigned to them and builds each with the usual training tools (reviews included, no charge); a customer's admins see their requests and quotes. Requesting a quote, accepting the bid, accepting the training and change orders happen on the training page.
  • Crews: list_crews (admins); assign a training to a crew with assign_training and {type: 'crew', crew_id}. Crews are edited in the web app.
  • Community forum (shared by all QC Database users): list_forum_boards, list_forum_posts (filter by board, search, questions), get_forum_post, list_forum_replies, create_forum_post and reply_to_forum_post (optional image; on the hosted server, send it with begin_upload first). Posts are public to every company and are badged "via MCP" by QC Database, so the assistant shows you the text before posting. Connections approved before the Forum API existed must re-approve to get forum:read/forum:write. Moderation stays in the web app.
  • Utilities: generate_qr_code

A companion to CAD, PCF, and .weldb systems

Map-item type definitions are read-only in MCP: discovery is available, but no create/edit/promote operation is exposed. Record edits and imports bind to existing schema IDs; archive schemas are not installed as new types.

List and document type creation/editing are permitted, but blocked by missing API write contracts. Document folder moves and package tags placed on LFDs are also API-blocked; moving a drawing to a package is not an LFD package tag. See the API handoff for the exact gaps. Hosted production needs a republish and refreshed client tool discovery before new tools appear; development verification alone does not update production.

This server is a natural partner to the systems that already describe your geometry — CAD/CAE exports, PCF piping files, and .weldb boilermaker replacement-panel files. Those sources carry most of what a good map item needs, so the assistant can turn them into accurate weld maps — if it follows two habits:

  1. Fetch the schema first. Always call list_map_item_schemas before create_map_item / bulk_create_map_items. That picks the right schema and reveals its exact fields, so source values land where they belong instead of being guessed or free-texted:
    • PCF (piping) files carry most of what a pipe weld needs — joint type, material, weight/sch.
    • .weldb files carry material, tube wall thickness, and the weld's rectangular position on the drawing — enough to build a weld map automatically.
  2. Match the source's geometry — point vs. rectangular welds. This is the big data-quality lever. A PCF pipe weld is a single point weld (one x/y). A .weldb weld has a rectangular position — give the second point (x_position_2/y_position_2) as the opposite corner so the extent is preserved. Collapsing a rectangular weld to a bare point (or spreading a point weld into a box) silently corrupts the map. Fetching the schema up front is what makes this distinction obvious before any items are placed.

Zipmaps: a whole mapped drawing in one upload

A zipmap is a plain zip that packages one drawing (a PNG, optionally the source single-page PDF) together with every map item already placed on it and the JSON Schemas that describe those item types. It is the "bring your own AI" hand-off: your model, CAD export, or takeoff tool produces the map; QC Database ingests it.

upload_zipmap replaces the old three-step dance (upload the drawing → wait → bulk-create items against it) with one transactional request. The drawing, all of its map items across every schema, and its extracted data are created together — or nothing is. No server-side AI runs on it; the map is yours.

Ask for it in plain language: "upload this zipmap into the Unit 2 hydro package." Behind that, the assistant does three things first:

  1. inspect_zipmap — looks inside without uploading: the drawing size, how many items of each type, the data fields those items use, and which types are not yet bound to a QC Database map item schema.
  2. list_map_item_schemas / get_map_item_schema — a zipmap names its types locally (weld, heat); QC Database identifies schemas by id. Any unbound type must be paired with the schema it belongs on (schema_ids={"weld": "<id>"}), and comparing the type's fields against the schema's fields is how that match is confirmed. Producers can skip this by writing the id into the archive's schemata/<type>.schema.json up front.
  3. list_packages — the new drawing has to be filed somewhere, and the API requires a package id. Pick (or create_package) the scope package first.

Coordinates travel as pixels of the zipmap's PNG (top-left origin, y down) — exactly the space QC Database maps in — so nothing is rescaled or flipped. If the project uses per-schema auto-numbering, its labels win over the zipmap's item ids and the result reports each new item against the id it came from.

Re-sending a corrected map? mode="replace" first soft-deletes any live drawing in that package with the same drawing number (retained in the audit trail, gone from drawing lists, and its map items go with it) instead of leaving a duplicate. The default, mode="append", always creates a new drawing.

Everything that can be checked locally is checked before the upload — a missing PNG, a type with no schema id, a coordinate outside the drawing, PDF-space coordinates that would misplace every item — so a bad map fails in a second with a list of what to fix, not after a multi-megabyte round trip.

Zipmaps are read from your own computer, so this works with the local (stdio) server. A hosted server never touches your disk (see Filesystem safety).


A note on sign-offs

Marking work complete or accepted is a buy-off — the system records it under your name and the current time. The assistant can do these for you, but every one of those tools tells you plainly that you are responsible for the action. The server never signs anything off silently. Treat those as your decisions, made with your go-ahead.


Privacy & safety

  • The server runs locally and only talks to https://qcdatabase.ai.
  • Your login is pinned to one organization (chosen at sign-in) and your session is pinned to one project — so the assistant can't reach into a different workspace or project by accident.
  • The server only requests the permissions an everyday user needs; admin actions are out of scope by design.
  • You can disconnect any connected app at any time from your QC Database account.

Your login is stored on your own computer in a per-user folder:

  • Windows: %LOCALAPPDATA%\qcdatabase-mcp\store.json
  • Mac: ~/Library/Application Support/qcdatabase-mcp/store.json
  • Linux: ~/.config/qcdatabase-mcp/store.json

Run the logout tool (or delete that file) to forget the login.

Filesystem safety (design invariant)

This is a hard rule the server must always uphold — for its own safety and for anyone contributing to this open-source repo:

  • The server never modifies its own files. No tool can read from or write to the server's whole installation — its own source, its dependencies (site-packages), the virtualenv, or (from a checkout) the repo root — whatever path it is given, so the assistant can never edit the server's or a dependency's code (no self-modification). Downloads also refuse to overwrite an existing file; choose a new path.
  • The server never touches its credential store beyond the token flow. No tool can read or write the per-user config directory, so a token can never be exfiltrated or overwritten through a tool, and it can never be committed to the repo (it lives outside any checkout; store.json is also .gitignored).
  • The only local files a tool ever touches are the user's own documents, and only in stdio mode — the upload tools read a file you point them at, and the download/export tools write to a path you choose. In hosted mode the server refuses all local filesystem access, because the disk is the server's, not yours (uploads/downloads there would need a client-side file channel instead).

These rules are enforced in code by _guard_local_path in server.py.


Troubleshooting

  • "qcdatabase" doesn't show up in Claude Desktop after restarting.
    1. Make sure you fully quit the app (system tray on Windows, Cmd-Q on Mac) and reopened it.
    2. Check the config file is valid JSON — a missing comma or brace stops every server from loading. Paste it into a JSON checker if unsure.
    3. If it still doesn't load, set "command" to the full path to Python (see the install note above).
    4. Look at the Claude Desktop logs for an error: Windows %APPDATA%\Claude\logs\, Mac ~/Library/Logs/Claude/.
  • "Not logged in." Ask the assistant to connect to QC Database and finish the sign-in in your browser.
  • "No project is set." Ask it to work on a project, or to list projects.
  • "Access denied (403): missing OAuth scope …" (e.g. shippers:write or qr:write). Your sign-in was approved before that permission existed. Reconnect the connector (hosted) and approve the named scope; for stdio, delete your store.json (see Privacy & safety for its location) and sign in again — that re-registers the app with the current permissions. A 403 that does not name a scope is a project membership/role problem: a project admin has to grant access, and reconnecting won't help.
  • The browser didn't open during login. The assistant will show you a link — open it manually to finish, then sign in again.
  • The sign-in page can't connect / port already in use. The login uses a local web address on port 8765. If another program is using it, set a different free port before launching the app by adding an environment variable QCDB_CALLBACK_PORT (for example 8766), then sign in again.
  • It can't find python. Reinstall Python with "Add to PATH" ticked (Windows), or use python3 in the config.

For developers

pip install -e '.[runtime]' # editable installpython -m qcdatabase_mcp    # run the stdio server directly
pip install -e '.[dev]'     # editable install + test depspytest                      # run the test suite

Layout:

src/qcdatabase_mcp/  __main__.py   # entry point + CLI (chooses stdio vs. hosted HTTP)  server.py     # FastMCP server + all tools + local filesystem guard  hosted.py     # multi-user hosting: OAuth resource server, token verify, sessions  client.py     # HTTP client: bearer auth, auto-refresh, errors, pagination, path safety  auth.py       # OAuth2 (PKCE + dynamic client registration) login & refresh (stdio)  config.py     # local token / project storage (stdio)tests/  test_security.py  # guard, token verifier, path safety, pagination, refresh, ...mcp_server_spec.md  # the API + behaviour spec this server implementsCLAUDE.md           # contributor invariants (filesystem safety, credential handling)

Environment variables (stdio mode):

  • QCDB_CALLBACK_PORT — local OAuth callback port (default 8765).
  • QCDB_CONFIG_DIR — override where tokens/settings are stored.

Hosting it for many users (mcp.qcdatabase.ai)

By default the server speaks MCP over stdio — one local user, sign-in via the login tool. Pass --http to run the multi-user hosted server instead, which serves the Streamable HTTP transport at /mcp, plus a public home page at / (connection instructions for humans) and a health check at /health (for load balancers and uptime monitors).

Try it on your own machine (creates a .venv, installs, runs on http://127.0.0.1:8000):

./scripts/run-local.sh        # Mac/Linux.\scripts\run-local.ps1       # Windows (PowerShell)scripts\run-local.bat         # Windows (double-clickable / cmd)

Then open http://127.0.0.1:8000/ in a browser.

Deploy it on a server so that git pull + restart is a complete deploy — the full walkthrough (systemd unit, nginx/Caddy configs, verification checklist, troubleshooting) is in deploy/README.md:

cp deploy/example.env .env    # set QCDB_MCP_RESOURCE_URL=https://mcp.example.com./scripts/run-server.sh       # binds 127.0.0.1:8000; put a TLS proxy in front

Behind nginx you MUST forward the original Host header (proxy_set_header Host $host;) — the provided deploy/nginx.conf does. Without it, the DNS-rebinding protection rejects every authenticated request with 421, which looks like "OAuth works but no tool call ever does". Caddy (deploy/Caddyfile) does the right thing by default.

In hosted mode the server is an OAuth 2.0 resource server (per the MCP authorization spec) — there are no shared secrets and nothing is stored on disk:

  • Each MCP client signs its own user in against QCDatabase.AI (discovered from the /.well-known/oauth-protected-resource document this server publishes) and sends that user's access token as Authorization: Bearer … on every request.
  • The server verifies the token against /api/whoami/, identifies the user, and acts as them. Unauthenticated requests get 401 with a WWW-Authenticate header pointing clients at the authorization server, so sign-in is automatic.
  • Per-user session state (the active project) is kept in memory keyed by a globally-unique identity (tenant + user id, never the raw token), so many people share one deployment without ever seeing each other's work. Verification fails closed — a token that doesn't resolve to a user is rejected. (State resets on restart — users just re-run set_project.)
  • DNS-rebinding protection validates the Host/Origin of every request (forged Host → 421, forged Origin → 403).

The login / logout tools become no-ops in hosted mode (sign-in is the client's job); everything else works identically to stdio.

Hosted-mode configuration (flags override env):

  • QCDB_MCP_HTTP=1 — same as --http.
  • --host / QCDB_MCP_HOST, --port / QCDB_MCP_PORT — bind (default 127.0.0.1:8000).
  • --resource-url / QCDB_MCP_RESOURCE_URL — this server's public URL and OAuth resource id; required when binding a non-loopback host.
  • --issuer-url / QCDB_MCP_ISSUER_URL — the OAuth authorization server (default https://qcdatabase.ai).
  • QCDB_MCP_ALLOWED_HOSTS / QCDB_MCP_ALLOWED_ORIGINS — extra allow-list entries (comma-separated), e.g. when fronted by additional hostnames. The allowed origins are also the only origins that get CORS headers on /mcp, so add a browser-based client's origin here to let it connect.
  • QCDB_MCP_SCOPES — scopes advertised as scopes_supported in the protected-resource document and as scope="..." in the 401 challenge (space- or comma-separated). Defaults to the same everyday read + write set the stdio login uses. MCP clients such as Claude only request advertised scopes, so leaving this empty would give them read-only access. Advertised, not required: a token approved with fewer scopes still connects. Every value must be a scope QCDatabase.AI grants.
  • QCDB_MCP_TOKEN_CACHE_TTL — seconds a verified token is trusted before re-checking /api/whoami/ (default 60). This is also the window in which a token revoked upstream keeps working here; lower it to shrink that window.
  • QCDB_MCP_TOKEN_NEG_CACHE_TTL — seconds a failed verification is remembered (default 5), which blunts garbage-token amplification against the API.
  • QCDB_MCP_STATELESS — serve each request without a server-held MCP session (default 1). Leave on: stateful sessions break on restarts, redeploys, and multi-replica setups ("session not found"). Set 0 only if you need server-initiated messages within a session.
  • QCDB_MCP_JSON_RESPONSE — answer POSTs with plain JSON instead of an SSE stream (default 1). Leave on: buffering proxies (nginx's default) stall SSE and the client times out; none of this server's tools stream partial results.

TLS. Terminate TLS at a reverse proxy in front of the server (never expose plain HTTP publicly) and forward the real Host header.

Resource indicator (kept open). This server accepts any valid QCDatabase- issued token and takes its resource id from QCDB_MCP_RESOURCE_URL, so anyone can fork it and host on their own domain without special AS configuration. For strict RFC 8707 audience binding, an operator may configure their authorization server to issue tokens bound to their MCP URL — but it is not required.

Scaling across replicas. The only shared state is each user's pinned project — small, non-secret, and disposable (lost pins just mean re-running set_project). Pick whichever fits your deployment:

  • Single instance (default). In-memory store, nothing to run. Best for most self-hosters.
  • Sticky sessions. Several replicas behind a load balancer that routes each user to the same replica; still in-memory, but a replica restart drops its users' pins.
  • Shared store (Redis). Set QCDB_MCP_REDIS_URL and install the extra (pip install 'qcdatabase-mcp[redis]'). All replicas share state and it survives restarts. Pins expire after QCDB_MCP_SESSION_TTL seconds idle (default 8h). To plug in a different backend, implement the two-method store in hosted.py (get_active_project / set_active_project) and return it from build_session_store.

(The token-verification cache is intentionally per-replica — each rebuilds it from /api/whoami/, so it needs no sharing.)

Licensed under the MIT License (see LICENSE).

Source: README.md at commit 29ef872

Tools

0
This server asks you to sign in, so SourceWeft could not read its tools without an account and has not indexed them. What a connected account sees can depend on that account and its permissions.

Version history

1
  1. v0.1.0LatestSep 16, 2026

Score

85% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts