Skip to content

Repository files navigation

QueryMesh

A standalone MCP server that gives AI agents read-only, scope-controlled, fully audited access to production data across many products, services, and databases.

Why this exists

One uniform tool (query) over MySQL + MongoDB sources. Agents hold a scoped API key, receive a pre-filtered registry (they can't even enumerate what they can't reach), and every call is validated against scope and written to an audit store. Read-only is enforced twice: at the query guard and by the DB credential itself.

Service database

QueryMesh has its own MySQL database that acts as both the config service and the audit store — three tables (src/store/schema.sql):

  • registry_nodes — the Project → Service → Database registry (adding a source is an INSERT, not a deploy)
  • api_keys — key id → label + scopes + HMAC hash (never the raw key)
  • audit_log — every tool call, 180-day retention

This DB is separate from any data source it fronts. Source credentials come from the env secret backend (QM_SECRET_*), never from the config service.

Quick start

npm install
cp .env.example .env        # set QM_DB_*, QM_KEY_PEPPER, QM_SECRET_*

# One-time: create the service database + least-privilege user (run as a MySQL
# admin, NOT as the querymesh user). Edit the password in the file to match .env.
mysql -u root -p < src/store/bootstrap.sql

npm run migrate             # create the three tables (assumes the DB + user exist)
npm run seed                # optional: example registry nodes for local dev
npm run issue-key -- --label "daily-summary-agent" --scopes edumix.api,edumix.eduvid.videocdn
npm run dev

Access denied for user 'querymesh'@'localhost'? The DB/user weren't created, or the password doesn't match QM_DB_PASSWORD. Run bootstrap.sql as root (above), or ALTER USER 'querymesh'@'localhost' IDENTIFIED BY '<your password>';. .env is loaded automatically; real shell env vars, if set, take precedence over it.

Point an MCP client at POST http://localhost:8080/mcp with Authorization: Bearer <key> (the raw key printed by issue-key).

Connecting from the Claude UI (OAuth)

QueryMesh is its own OAuth 2.1 Authorization + Resource Server, so it can be added as a custom connector in claude.ai / Claude Desktop (Settings → Connectors → Add custom connector). Two requirements:

  1. Public HTTPS URL. The connector UI can't reach localhost — expose the server via a tunnel (cloudflared tunnel --url http://localhost:8080 or ngrok http 8080) and set QM_PUBLIC_URL to that https://… origin (it's the OAuth issuer). Register https://…/mcp as the connector URL.
  2. Authorize with an API key. During the OAuth flow QueryMesh shows a login page; paste a key issued by issue-key. The access token is bound to that key's scopes.

Raw Authorization: Bearer <key> still works for the CLI (claude mcp add --transport http … --header) and curl — both auth paths share one verifier.

npm test          # guard + scope adversarial tests
npm run typecheck

Project layout

src/
  index.ts              entry: migrate, load config service, start Express edge, retention purge
  http/edge.ts          Express: OAuth router + bearer auth -> per-principal MCP server (Streamable HTTP)
  server.ts             MCP server: injects scoped registry, registers the query tool
  store/
    schema.sql          service DB schema (registry_nodes, api_keys, audit_log, oauth_*)
    db.ts               service MySQL pool + migration runner
    config-store.ts     loads + hot-reloads registry/keys from the service DB
  config/               Zod schemas + SecretResolver (env backend)
  registry/             Project->Service->Database model, scope filtering, safe injection view
  auth/                 HMAC key hashing, key resolution, boundary-aware scope matching
    oauth/              OAuth 2.1 provider (DB-backed) + interactive login page
  connectors/           Connector interface, pool mgmt, MySQL/Mongo impls + read-only guards
    guards/             mysql-guard (single SELECT), mongo-guard (block $out/$merge/JS + allowlist)
  tools/                query tool + shared context
  audit/                buffered logger + MySQL sink (with retention purge)
  cli/                  migrate, seed, issue-key, add-node (interactive)
test/                   guard + scope adversarial tests

Adding a data source

Run the interactive CLI — it prompts for each field, validates against the same Zod schema the server uses, previews the node, upserts it, and prints the QM_SECRET_* env var to set:

npm run add-node

(Or INSERT directly into registry_nodes.) Then add the matching QM_SECRET_* to the env backend and grant an API-key scope. The config service hot-reloads within CONFIG_REFRESH_MS. No code touched, no deploy.

Status

Skeleton / scaffolding — typechecks and unit tests pass. Before production (see SPEC §11): per-key rate limiting, audit-failure metric, /readyz pool health, and an integration suite proving writes are refused at both the guard and credential layers.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages