nextQ MCP server
OfficialClick on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@nextQ MCP serverWhat are the top opportunities for Acme Corp?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
nextQ MCP server
Read-only, multi-tenant MCP server that lets Claude answer seller questions from the research the nextQ pipeline already saved. It is built on FastMCP 4 and asyncpg, deployed on FastMCP Cloud, and authenticated with WorkOS AuthKit.
It reads only the aiml schema (the aimla_* views) of each tenant database. It never
writes, and it never touches dwh.
Tool | What it returns |
| account_id for a company name / ticker |
| company facts, strongest opportunities, top surging topics, named executives |
| initiatives of the latest research run, in rank order |
| description, score breakdown, alignment strategy, case study, intent, hiring, roles |
| Bombora intent topics, highest score first |
| initiatives scored 0-100 as sales opportunities, each signal with points and reason |
| target roles ranked with reasons, plus named executives |
| an initiative's intent topics with surge scores, hiring and roles |
| RAG retrieval: the most relevant cited passages for any question |
| datasets open to free-form questions, their columns and common values |
| one guarded, read-only SELECT over those datasets |
The server's MCP instructions tell Claude which tool fits which question and how to answer,
including the exact reply "table doesn't have this info". This works in any MCP client, so no
skills are required. The skills in nextq-plugin/ are optional output templates.
How a request flows
MCP client ──HTTPS──▶ FastMCP Cloud ──▶ FastMCP server (stateless HTTP)
│ 1. WorkOS JWT verified (signature, expiry, audience)
│ 2. middleware: audit log, per-user rate limit, response cap
│ 3. tenant resolved from the token (tenants.py), never from arguments
│ 4. tenant's asyncpg pool (created lazily, shared by all its users)
▼
tenant Postgres: aiml.aimla_* views, as nextq_readerConcurrency.
Every tool is
async. Each tenant has its own asyncpg pool (NEXTQ_DB_POOL_MAX_SIZEconnections), and a connection is held only for the length of one query.Independent queries run concurrently with
asyncio.gather. One account loads with three parallel queries, and the search corpus with five.When many users ask for the same account at once, a single load runs and every caller shares it (single-flight TTL cache).
Each tenant has its own search index, built in the background at startup. It is refreshed stale-while-revalidate, so a rebuild never blocks a request. The CPU-heavy part runs in a worker thread, keeping the event loop free.
HTTP is stateless, so any instance can serve any request.
Security: read-only is enforced in three independent layers.
sql_guard.pyparses model-written SQL with sqlglot. It allows only one SELECT over the catalog datasets, with no schema prefixes, writes, system functions or recursive CTEs, and it enforces a LIMIT.Every session has
default_transaction_read_only=onand astatement_timeout. Ad-hoc SQL also runs in an explicitREAD ONLYtransaction that is always rolled back.The
nextq_readerrole (migrations/003_nextq_reader_role.sql) can only SELECT the aiml views.
Further protections:
Tenant isolation: the tenant comes only from the verified token. Pools, caches and search indexes are all keyed by tenant. A user who matches no access rule gets no data.
Errors: unexpected errors are masked (
mask_error_details). Expected failures return a safe, actionable message.Logs: audit lines record the user, tool, outcome and latency. Tool arguments and results are never logged.
Fail closed: the default environment is
production, which refuses to start without WorkOS auth configured.
Related MCP server: MCPipe Toolchain
Layout
server.py FastMCP Cloud entrypoint (server.py:mcp)
nextq_mcp/
app.py server factory: instructions, lifespan, middleware, /health
config.py NEXTQ_* settings (pydantic-settings), fail-closed validation
auth.py WorkOS AuthKit / dev auth, caller identity
tenants.py tenant registry + user -> tenant resolution
db.py per-tenant asyncpg pools, read-only execution
queries.py the server's own SQL over the aiml views
runtime.py app state (lifespan) + per-request TenantRuntime, error mapping
cache.py async single-flight TTL cache
scoring.py opportunity / role scoring (pure)
search.py BM25 knowledge search + per-tenant index manager
catalog.py, sql_guard.py ask-data catalog and SQL guard
tools/ the 12 tools (accounts, intel, ask_data, knowledge)
data/ catalog.yaml, scoring.yaml
nextq-plugin/ Claude Code plugin: remote server + optional skills
migrations/ nextq_reader role
evals/ answerable / unanswerable / refuse question set
tests/ 113 tests: guard, scoring, search, tenants, cache, tools, HTTP authTenant registry (NEXTQ_TENANTS)
A single JSON secret holds every tenant's database and the rules that map users to tenants.
tenants.example.json is a dummy example.
{
"tenants": {
"c112": {
"name": "NextQ demo",
"database": {"host": "...", "port": 5432, "name": "qpilot_v1_c112",
"user": "nextq_reader", "password": "...", "sslmode": "require"},
"aiml_schema": "aiml",
"views": {}
}
},
"access": {
"user_ids": {"user_01H...": "c112"},
"emails": {"seller@customer.com": "c112"},
"org_ids": {"org_01H...": "c112"},
"email_domains": {"customer.com": "c112"}
}
}Rules are checked most specific first: WorkOS user id (sub), then email, then WorkOS
organization (org_id), then email domain.
viewsoptionally overrides the view names per tenant (keys as intenants.DEFAULT_VIEWS).Schema and view names must be plain lowercase identifiers.
WorkOS access tokens carry
subandorg_idby default. Theemailsandemail_domainsrules only work if you add anemailclaim with a WorkOS JWT template. Preferorg_ids: one WorkOS organization per customer.
Adding a tenant means updating the secret and redeploying.
Local development
Requires uv.
uv sync
cp .env.example .env # dev settings: no auth, one tenant
# create tenants.local.json (gitignored) shaped like tenants.example.json
uv run pytest # 113 tests, no database needed
uv run ruff check . && uv run ruff format --check .
uv run python -m nextq_mcp # stdio
uv run python -m nextq_mcp --http # http://127.0.0.1:8000/mcp
uv run fastmcp run server.py:mcp --transport http --port 8000 # exactly as FastMCP Cloud runs itTo use the local server from Claude Code over stdio:
claude mcp add nextq-local -- uv run --directory /path/to/nextq-mcp python -m nextq_mcp
To test tenant routing over HTTP locally, set NEXTQ_AUTH_MODE=static with NEXTQ_DEV_TOKENS
(see .env.example) and connect with Authorization: Bearer <token>. Settings refuse
static and none when NEXTQ_ENVIRONMENT=production.
Deploy to FastMCP Cloud
1. WorkOS (one-time)
In the WorkOS dashboard:
Applications → Configuration: enable Dynamic Client Registration, so MCP clients (Claude, Cursor...) register themselves.
Resource Indicators: add
https://<server-name>.fastmcp.app/mcp. FastMCP validates the token'saudagainst this exact URL.Create an organization per customer and invite its users. Put each
org_...id inaccess.org_ids.Note your AuthKit domain, e.g.
https://your-app.authkit.app.
See WorkOS' guide: https://workos.com/docs/authkit/mcp/integrating/token-verification
2. Database (per tenant, one-time)
Run migrations/003_nextq_reader_role.sql as an admin,
and use nextq_reader in the registry. The database must accept TLS connections from
FastMCP Cloud. FastMCP Cloud does not document fixed egress IPs, so an IP allowlist may not work.
3. FastMCP Cloud
Create a server from this GitHub repo:
Entrypoint:
server.py:mcpAuthentication: OFF. The server runs WorkOS auth itself. FastMCP Cloud's built-in auth would consume the
Authorizationheader, and the server could not see who the user is.
Set the environment variables (store the secrets as secrets):
Variable
Value
NEXTQ_PUBLIC_BASE_URLhttps://<server-name>.fastmcp.appNEXTQ_WORKOS_AUTHKIT_DOMAINhttps://your-app.authkit.appNEXTQ_TENANTSthe registry JSON (secret)
NEXTQ_ENVIRONMENT=productionandNEXTQ_AUTH_MODE=workosare the defaults.Deploy, then check
https://<server-name>.fastmcp.app/health.
Dependencies come from pyproject.toml / uv.lock, and .python-version pins Python 3.12.
FastMCP Cloud redeploys on every push to main. Protect main and require the CI workflow
(.github/workflows/ci.yml) to pass before merging.
4. Connect
Claude Code:
claude --plugin-dir ./nextq-plugin(setNEXTQ_MCP_URLif the server name is notnextq), orclaude mcp add --transport http nextq https://<server-name>.fastmcp.app/mcp.claude.ai / Claude Desktop: add a custom connector with the same URL.
On first use, the client opens the WorkOS login.
Configuration reference
Variable | Default | |
|
|
|
|
|
|
| — | registry JSON / path to it |
|
| per tenant, per instance |
|
| set |
|
| statement timeout |
|
| per-account cache |
|
| search index refresh |
|
| build every tenant's index at startup (2 at a time) |
|
| per user, counts every MCP request |
|
| tool responses are truncated above this |
|
| alternative catalog / scoring |
|
|
Operations notes
Connection budget:
NEXTQ_DB_POOL_MAX_SIZE× number of instances must stay under the role'sCONNECTION LIMIT(20).Memory: each tenant's search index lives in memory. The c112 index (~37k passages) builds in about 15 s. For very large tenants, move
search.pyto Postgres full-text search or pgvector behind the same tool.Per-instance state: caches, indexes and rate limits are per instance. The rate limit is a per-instance guard, not a global quota.
Scores: opportunity and role scores rank signal strength. They are not win probabilities. Tune them in
data/scoring.yaml.More data: to expose more datasets, add them to
data/catalog.yamlwith descriptions and add a matching GRANT to the migration.
Related MCP Connectors
Query your org's data in natural language — read-only MCP access to SQL, NoSQL, files & warehouses.
Discover Frontier inference capabilities and read sanitized usage through read-only tools.
Query 40 databases from Claude, ChatGPT, or Cursor — on any device. Read-only, encrypted, audited.
Salesforce-grounded retrieval, diagnoses, and a vetted-Force marketplace for MCP clients.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables sales, marketing, and C-suite teams to search, view, and update Salesforce records through Claude, with tools for record management, activity tracking, and global search.16MIT
- FlicenseNot gradedqualityCmaintenanceProvides read-only access to Confluence, GitHub, Jira, Figma, Outlook, Teams, and browser automation for AI clients, enabling safe discovery, retrieval, and summarization of company knowledge without modifying source systems.-
- FlicenseNot gradedqualityBmaintenanceEnables AI assistants to query internal business data for insights into customers, revenue, subscriptions, sales, and churn through controlled, read-only MCP tools.-
- AlicenseNot gradedqualityCmaintenanceEnables a language model to safely query internal services through a closed set of read-only, schema-validated tools, with full auditing and refusal logging.MIT