@aquex/tracelab-mcp
v2.2.0
Published
MCP server for TraceLab — gives AI agents research-to-output loops against a TraceLab knowledge base. Nine action-clustered tools (search, project, collection, report, document, mission, mission-execution, evidence, home) and an RFC 8628 device-code login
Maintainers
Readme
@aquex/tracelab-mcp
MCP server for TraceLab. Lets AI agents run complete research-to-output loops — semantic search, project and collection management, mission authoring, DeepSearch execution, and report generation, plus cross-session evidence capture — against a TraceLab knowledge base.
- 9 action-clustered tools / 50 actions in source (one tool per noun, dispatched by
action) - RFC 8628 device-code login — install, run, click a link, you're in
- Works out of the box with Claude Desktop, Claude Code, and any Model Context Protocol client over stdio
Requirements: Node ≥ 18, a reachable TraceLab API endpoint, and an invited TraceLab account with access to that deployment.
Install
Configure your stdio MCP client to launch the current published adapter with
npx — no global install needed:
npx -y @aquex/tracelab-mcp@latestTo install the current release globally:
npm install -g @aquex/tracelab-mcp@latest
tracelab-mcpFrom source (development):
git clone https://github.com/kneelinghorse/TraceLab.git
cd TraceLab/packages/tracelab-mcp
npm install
npm run build
node dist/index.jsThese commands launch a long-running stdio server for your MCP client. They are not shell commands for individual tool calls.
First run: from sign-in to a cited answer
Obtain an invitation and sign in to the TraceLab browser app. Configure your MCP client with the API origin
https://api.tracelab.aquex.ai, then let the client launch the adapter.Open the device-approval URL shown in the client's server logs and approve that launch in your signed-in browser. See First-time login below. Allow enough startup time for the device flow to finish; if your client stops the process first, increase its startup timeout and relaunch to get a fresh code.
Ask the MCP client to call
tracelab_projectwithaction="list":{ "name": "tracelab_project", "arguments": { "action": "list" } }Select a returned project's
idforproject_id. Signup creates a personal Space, not a project or bundled corpus; shared access may make existing projects visible. If the list is empty, create a project in the browser app (or withtracelab_project,action="create", andname). Upload and process documents in that project before asking about them. Do the same if a visible project has no indexed documents yet. The adapter also exposestracelab_documentactionsuploadandprocessfor this ingestion path.Call
tracelab_searchwithaction="ask", the selectedproject_id, and yourquestion. Replace this example UUID with the ID returned above:{ "name": "tracelab_search", "arguments": { "action": "ask", "project_id": "fbd3bd03-5ddc-49ee-8013-529163a99290", "question": "What do these documents say about onboarding?" } }Open a returned
citations[].urlto view its supporting chunk in the document.no_evidence: trueis expected when the accessible indexed documents do not support an answer. This action answers only from that project's corpus; general Librarian chat/planning is a separate interaction. Asking does not submit a DeepSearch mission. Any paid model call is recorded as your usage.
The JSON above describes MCP tool calls made by your client, not terminal input.
Authoring an output descriptor
For tracelab_mission create/update, expected_output_schema is one output
descriptor object. Set nonempty kind, title and format; this is not a raw
JSON Schema with type and properties. For example:
{
"kind": "report",
"title": "Research summary",
"format": "markdown",
"required_sections": ["Executive summary", "Evidence", "Limitations"]
}TraceLab's MCP, REST and UI accept an object, not an array of descriptors, even
though the underlying compiler also supports sequences internally. Omit this
optional field to use inferred deliverables. Drafts preserve the object as
authored; contract preview validates it. After creating a draft, call
tracelab_mission_execution with action="preview" and its returned UUID.
Preview is structural and does not dispatch research or execute a provider.
Submitting research is a separate action.
First-time login
When neither an environment credential nor a stored credential matching the
API origin is available, tracelab-mcp runs an RFC 8628 device-authorization
flow. You'll see this on stderr:
────────────────────────────────────────────────────────────
[tracelab-mcp] Login required
────────────────────────────────────────────────────────────
Open: https://tracelab.aquex.ai/device?code=WDJB-MJHT
Code: WDJB-MJHT
(Code expires in 600s; this client will poll every 5s.)
────────────────────────────────────────────────────────────- Open the URL in any browser where you're logged in to TraceLab.
- Confirm the User-Agent shown matches the install you started, then click Approve.
- The MCP client picks up the freshly minted API key within ~5 seconds and continues startup.
The minted key is stored at ~/.config/tracelab-mcp/credentials.json
(chmod 600). Subsequent launches against the same API origin reuse it. A
revoked credential must be removed and replaced through a fresh login.
To revoke a key, delete the credential file and delete the key from your
TraceLab account at /profile → API Keys. To force a re-login, delete the
credential file and relaunch.
Configure your MCP client
TRACELAB_API_URL is the FastAPI origin, without an /api/v1 suffix. The
client appends /api/v1 to each request itself. For production, use
https://api.tracelab.aquex.ai; https://tracelab.aquex.ai is the browser UI.
Generated browser navigation uses canonical /projects/:id, /documents/:id,
/collections/:id, /reports/:id, /missions/:id and /evidence/:id routes.
Entity projections carry url; related resources use named document_url,
collection_url, report_url or project_url fields. Optional missing IDs do
not produce links. Existing evidence source_url, authored references/context,
full contract previews and Markdown exports retain their original values.
The public API above uses https://tracelab.aquex.ai for browser links. Loopback
API hosts use http://localhost:3000. For another deployment or local frontend
port, set TRACELAB_FRONTEND_URL in the MCP process environment to the browser
origin, for example https://research.example.com. It must be an HTTP(S) origin
without credentials, a path, query or fragment. Configuration is checked before
login and tool execution; custom API hosts require this explicit setting.
Codex (desktop, CLI, and IDE)
Add the stdio server to ~/.codex/config.toml:
[mcp_servers.tracelab]
command = "npx"
args = ["-y", "@aquex/tracelab-mcp@latest"]
startup_timeout_sec = 600
[mcp_servers.tracelab.env]
TRACELAB_API_URL = "https://api.tracelab.aquex.ai"The startup timeout
allows time to approve the device code before the adapter registers its tools.
Restart Codex after saving the configuration. TraceLab does not expose a
remote SSE MCP endpoint; a connector configured with url =
"https://aquex.ai/mcp" is not the TraceLab MCP server.
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"tracelab": {
"command": "npx",
"args": ["-y", "@aquex/tracelab-mcp@latest"],
"env": {
"TRACELAB_API_URL": "https://api.tracelab.aquex.ai"
}
}
}
}Restart Claude Desktop. The first invocation triggers the device-code flow on stderr (visible in Claude Desktop's MCP server logs).
Claude Code
claude mcp add --transport stdio tracelab \
--env TRACELAB_API_URL=https://api.tracelab.aquex.ai \
-- npx -y @aquex/tracelab-mcp@latestOther MCP clients
The server speaks stdio. Any MCP-compatible client that can launch a
subprocess will work — point it at tracelab-mcp (or
npx -y @aquex/tracelab-mcp@latest) and pass TRACELAB_API_URL in the environment.
Configuration
| Variable | Default | Purpose |
| --- | --- | --- |
| TRACELAB_API_URL | http://localhost:8000 | TraceLab API base URL (the FastAPI service, not the frontend). |
| TRACELAB_TOKEN | (unset) | Optional JWT bearer. Wins over device-code credential when set. Useful for short-lived CI runs. |
| TRACELAB_API_KEY | (unset) | Optional tl_* API key. Wins over device-code credential when set. Useful when you've already minted a key via the web UI and want to skip the flow. |
Auth resolution order at startup:
TRACELAB_TOKENenv var (JWT).TRACELAB_API_KEYenv var (tl_*key).- Stored credential at
~/.config/tracelab-mcp/credentials.json, only if itsapiBaseUrlmatchesTRACELAB_API_URL. - Interactive device-code flow (mints a fresh key, persists it).
Step 3's URL match means switching TRACELAB_API_URL between (e.g.) prod
and a local dev server forces a fresh login per environment — credentials
never leak across deployments.
Tools
Nine action-clustered tools / 50 actions in source. Each cluster exposes multiple actions
selected via the action parameter.
| Cluster | Actions | Purpose |
| --- | --- | --- |
| tracelab_search | knowledge, navigate, pedr, ask | Semantic search across the knowledge base, and cited answers to a question about one project's documents. |
| tracelab_project | list, get, create, update, stats, neighborhood | Project CRUD, aggregate stats and the scoped relationship neighborhood. |
| tracelab_collection | list, get, export, create, add, synthesize, documents, mission_seed, update, add_document | Curate chunks and documents into collections, edit their instructions, then synthesize. |
| tracelab_report | create, list, get, export, update | Persistent named research reports, including title/status updates. |
| tracelab_document | upload, get_content, list, process | Document ingestion, explicit processing and full-text fetch. |
| tracelab_mission | create, list, get, update | Mission CRUD against the DeepSearch authoring contract; list sorts by created/updated time. |
| tracelab_mission_execution | submit, status, preview, logs, events, cancel, promote_report | DeepSearch lifecycle: queue, poll status, preview the compiled contract, cancel, promote a finished report to a document. |
| tracelab_evidence | capture, note, list, search, promote, get | Capture sourced findings and working notes, reuse them across sessions, and promote a session to a report or document. |
| tracelab_home | snapshot, favorites, activity, activity_summary | Caller-scoped home and recent-activity reads (human credential required). |
The Sprint 52 additions below first shipped in 1.2.0. These sections record release history; subsequent changes are called out below and in the changelog. For current installation guidance, use Install; the current surface is the nine-tool, fifty-action table above.
Sprint 52 read parameters (1.2.0)
Every action calls the authenticated REST API afresh. Server totals and authored
fields are preserved. Entity responses add absolute browser links; existing
href fields and authored/source URLs are retained.
| Action | Required and optional parameters |
| --- | --- |
| tracelab_home.snapshot | No additional parameters. Returns the caller-scoped home sections, including server missions.total. |
| tracelab_home.favorites | Optional project_id, page (default 1), page_size (default 6, max 100). |
| tracelab_search.navigate | Required q (1–200 characters). Optional entity_type: project/document/mission/report/collection/evidence; page (1), page_size (5, max 50). |
| tracelab_search.pedr | Required query (1–2000 characters). Optional top_k (10, max 100), project_id, source_type, date_from, date_to (YYYY-MM-DD), enable_graph (true, matching the UI). Returns full results and layer/graph diagnostics. |
| tracelab_evidence.get | Required entry_id UUID. Returns the full entry and relationships; no separate project parameter is needed. |
| tracelab_document.list | Optional project_id, processed (true or false), search, page (1), page_size (20, max 100). total comes from server pagination. |
| tracelab_project.get | Required project_id UUID. |
| tracelab_collection.documents | Required collection_id UUID. Optional page (1), page_size (20, max 100). |
| tracelab_collection.mission_seed | Required collection_id UUID. Returns drafting instructions, background and source references. |
| tracelab_mission_execution.logs | Required mission_id UUID. Optional limit (100, max 500). |
| tracelab_mission_execution.events | Optional mission_id UUID, limit (50, max 200). |
PEDR remains an explicit choice for multi-layer search and graph diagnostics;
knowledge continues to use plain /retrieval/search. These are alternative
retrieval paths, with no claim that PEDR ranks better. Logs/events are bounded
snapshots of recorded activity. An empty list includes an explicit empty flag
and message; it does not establish that streaming is active.
Existing actions also gain UI parameters:
tracelab_search.knowledge: optionalsource_type,date_from,date_to(YYYY-MM-DD), alongside the existingquery,limit,project_idandtags.tracelab_mission.list: optionalsort=created_desc(default),created_asc,updated_descorupdated_asc. Withoutsortthe request URL is unchanged. (The 1.2.0viewandreasonparameters were removed with the attention surface; see the 2.0.0 notes below.)tracelab_collection.list: optionalproject_id,page,page_size(max 100).getreturnsinstructions;createaccepts optionalinstructions(max 20,000 characters).tracelab_evidence.listand.search: optionaltag,created_from,created_until(YYYY-MM-DD),source_id(UUID),report_id,document_id, in addition to existing project/session/mission/disposition/pagination filters. Use at most one ofreport_idordocument_id; it must belong toproject_id. The start date must not follow the end date, and9999-12-31is not a valid end date. Tags are nonblank and at most 64 characters.tracelab_report.export: optionalformat=md,jsonortxtcalls the REST export route and returns its exact text. Omitformatto retain the legacy response of exactreport.contentbytes.
Sprint 52 actions and reads (MCP-2, 1.2.0)
Six non-destructive actions on research objects and caller-scoped reads mirror the exact REST routes the web UI calls. Per-user acknowledgements (favorites, saved searches and the activity viewed watermark) and every DELETE route stay in the web UI by decision #426; the MCP never performs them on the user's behalf.
| Action | Route and parameters |
| --- | --- |
| tracelab_mission_execution.cancel | PATCH /missions/{id} with {status: "cancelled"}. Required mission_id; status is optional and only ever cancelled. |
| tracelab_mission_execution.promote_report | POST /missions/{id}/promote-report. Required mission_id (completed mission with a report or markdown). Returns the new document with document_url. |
| tracelab_document.process | POST /documents/{id}/process. Required document_id. Runs parse, PII redaction, chunking and embedding. |
| tracelab_collection.update | PUT /collections/{id}. Required collection_id plus at least one of name, description, instructions (max 20,000 characters). |
| tracelab_collection.add_document | POST /collections/{id}/documents with {document_id}. Required collection_id, document_id. |
| tracelab_report.update | PUT /reports/{id}. Required report_id plus title and/or status (draft or final). |
| tracelab_project.neighborhood | GET /graph/neighborhood. Required root_type (project/document/mission/report/collection/evidence) and root_id. Optional depth (1, max 2), per_relation_limit (12, max 50), max_nodes (60, max 150). Nodes carry canonical links; groups carry server totals. |
Report origins (2.2.0)
tracelab_report.list accepts an optional origin array with mission, written,
librarian and agent_brief. Omit it to keep all artifacts, or use
["written", "librarian"] for the Reports UI's default. List/get return origin,
origin_label, origin_href and a readable project_name. Get preserves source
name and href; an inaccessible or deleted source has no source identity or
link and displays “Source unavailable”. Mission copies remain stored; Home's
recent reports and report activity omit them because the mission already appears.
Recent activity (ACT-1, 2.0.0)
Decision #459 replaced the inbox, "needs attention", mission reviews and saved
mission views with one recency-ordered activity stream. The 1.2.0 actions
tracelab_home.attention, tracelab_home.inbox_summary,
tracelab_home.inbox_list and tracelab_mission.views are gone, as are the
view/reason parameters of tracelab_mission.list and the attention
section of tracelab_home.snapshot (which now carries activity).
| Action | Route and parameters |
| --- | --- |
| tracelab_home.activity | GET /activity. Optional page (1), page_size (20, max 100). Missions, reports and evidence in one recency order; each item has type, id, title, subtitle, status, occurred_at, href, url and caller-relative viewed and new flags. new means unviewed and occurred within the last three days; older unseen items remain viewed: false, new: false. Server total and new_total are preserved. |
| tracelab_home.activity_summary | GET /activity/summary. No parameters. new_total and by_type count unviewed items within three days. completed_missions_new counts only unviewed completed missions whose completed_at is within three days; it drives the Missions sidebar dot. |
Marking activity as viewed (PUT /activity/viewed) stays in the web UI.
Home, activity and evidence routes reject service principals: use the device-code login or a user API key.
Creating in a Space (PERSONAL-2, 2.0.0)
tracelab_project.create takes an optional workspace_id (UUID), the Space to
create the project in. Omit it and the project lands in your personal Space. You
must be a member of the named Space (403 otherwise); owners and admins may name
any existing Space (404 if it does not exist). The web UI's Space picker sends
the same field to the same route. tracelab_project.list and the create result
now carry each project's workspace_id; get always did.
Asking a project a question (MCP-6, 2.1.0)
tracelab_search.ask gives agents the Librarian's "Ask the documents": the same
Q&A service, the same citation rule and the same access check.
| Action | Route and parameters |
| --- | --- |
| tracelab_search.ask | POST /search/ask. Required project_id and question (1–20,000 characters). Optional max_tokens (64–4000; omitted uses the server default; the Librarian uses 600 for a short answer and 2000 for a full synthesis). Returns answer, passages (each paragraph with the chunk ids it cites), citations (chunk_id, document_id, document_name, chunk_index, snippet, href, and a url that opens the chunk in its document), project_url and no_evidence. |
Every citation is a chunk the answer was written from, in a document that still
exists. When nothing in the project answers the question, no_evidence is true
and the answer says so instead of guessing. You can ask only a project you can
read (403 otherwise; 404 when it does not exist), with a human credential. Each
paid model call is recorded as your usage.
Example calls
Semantic search:
{
"name": "tracelab_search",
"arguments": {
"action": "knowledge",
"query": "user onboarding best practices",
"limit": 10
}
}Ask a project a question:
{
"name": "tracelab_search",
"arguments": {
"action": "ask",
"project_id": "fbd3bd03-5ddc-49ee-8013-529163a99290",
"question": "What does self-hosting Qdrant cost?",
"max_tokens": 600
}
}Create a mission and submit it to DeepSearch:
{
"name": "tracelab_mission",
"arguments": {
"action": "create",
"mission_id": "RESEARCH-001",
"title": "Hosted code-execution platforms",
"objective": "Compare serverless container platforms for evaluation",
"success_criteria": ["≥5 platforms covered", "Latency benchmarks cited"],
"project_id": "fbd3bd03-5ddc-49ee-8013-529163a99290",
"required_entities": ["AWS Lambda", "Google Cloud Run", "Vercel", "Fly.io"],
"deliverable_format": "comparison table"
}
}{
"name": "tracelab_mission_execution",
"arguments": {
"action": "submit",
"mission_id": "RESEARCH-001"
}
}Synthesize a collection into a report:
{
"name": "tracelab_collection",
"arguments": {
"action": "synthesize",
"collection_id": "11111111-1111-1111-1111-111111111111",
"prompt": "Compare the platforms on cold-start latency and cost."
}
}Capture sourced findings for reuse in later sessions:
{
"name": "tracelab_evidence",
"arguments": {
"action": "capture",
"project_id": "fbd3bd03-5ddc-49ee-8013-529163a99290",
"session_key": "competitive-scan-2026-08-20",
"entries": [
{
"claim": "The vendor publishes a documented data-retention limit.",
"source_url": "https://example.com/security/retention",
"snippet": "Customer content is retained for no more than 30 days.",
"query": "vendor data retention policy",
"disposition": "supporting",
"tags": ["security", "retention"]
}
]
}
}Search the project ledger before repeating research:
{
"name": "tracelab_evidence",
"arguments": {
"action": "search",
"project_id": "fbd3bd03-5ddc-49ee-8013-529163a99290",
"q": "data retention"
}
}Search before research
Use the two search surfaces in this order:
- Call
tracelab_evidence(action="search")with the project ID to reuse raw findings from earlier sessions. These results retain the source URL, disposition, canonicalsource_id, andsource_sighting_count. - Call
tracelab_search(action="knowledge")when you need semantic matches from the ingested document corpus. - Capture material new findings with
tracelab_evidence(action="capture"), including contradictory and rejected evidence rather than silently dropping it.
Raw ledger entries do not automatically appear in tracelab_search. When a
reviewed session should join the document corpus, promote it explicitly:
{
"name": "tracelab_evidence",
"arguments": {
"action": "promote",
"project_id": "fbd3bd03-5ddc-49ee-8013-529163a99290",
"session_key": "competitive-scan-2026-08-20",
"target": "document"
}
}Document promotion is the bridge into TraceLab's normal ingestion, chunking, embedding, Qdrant, and PEDR/preflight paths. Report-only promotion preserves a durable report but does not add its content to document search.
Evidence required text and tags are trimmed and must remain nonblank. Working
note keys may contain ordinary encoded path characters (including /), but
the dot-only keys . and .. are reserved because URL parsers treat them as
navigation segments.
Migration from earlier names
If you previously used the un-published @tracelab/mcp-server name from
this repo, the only change is the package name on install. Tool names,
schemas, and behavior are unchanged. The flat ~24 tool surface from
sprint-40 was collapsed into 7 clusters in sprint-41 (T41.7), then extended
to 8 by the additive Evidence Ledger cluster in LEDGER-1, and to 9 with
tracelab_home in 1.2.0. The 2.0.0 activity changes and 2.1.0 corpus Q&A addition
bring the current surface to 9 tools / 50 actions. As before,
calls to the legacy names return a friendly migration error pointing at
the cluster equivalent.
Troubleshooting
Login times out / expired_token — the device code is valid for 10
minutes. Approve faster, or relaunch to mint a new code.
access_denied immediately — someone clicked Deny on the web
/device page (possibly you, possibly not). Relaunch and re-approve.
slow_down errors in logs — harmless. The server enforces a polling
interval; the client bumps its sleep by 5 seconds and continues.
MCP tools not showing up in Claude Desktop — check the MCP server logs (Settings → Developer → MCP Server Logs in Claude Desktop). The first launch must complete the device-code flow before tools register.
Stale credential after server URL change — if you switched
TRACELAB_API_URL between deployments, the client logs "Stored credential
targets X, but TRACELAB_API_URL is Y. Re-running device login." and
prompts again. Expected behavior.
Stored credential leak / suspected compromise — delete
~/.config/tracelab-mcp/credentials.json and revoke the key in TraceLab
at /profile → API Keys. Then relaunch to mint a fresh one.
Want to skip the device flow on CI — set TRACELAB_API_KEY (or
TRACELAB_TOKEN) in the environment. Both win over the stored credential
and skip the interactive flow.
Development
Build:
cd packages/tracelab-mcp
npm install
npm run buildWatch mode:
npm run devTests:
npm test # watch mode
npm run test:run # one-shotLint:
npm run lintpackages/*/dist/ is .gitignored at the repo root; a pre-commit hook
(scripts/check_no_mcp_dist.sh) blocks accidentally-staged build output.
prepublishOnly rebuilds from src/ before every npm publish, so the
published tarball never contains stale builds.
License
The @aquex/tracelab-mcp adapter is MIT licensed. See its
LICENSE.
This license applies to the adapter package; it does not grant a license to the
entire TraceLab service.
Links
- TraceLab — https://github.com/kneelinghorse/TraceLab
- Issue tracker — https://github.com/kneelinghorse/TraceLab/issues
- Changelog — CHANGELOG.md
- Model Context Protocol spec — https://modelcontextprotocol.io
Authored scope preview (2.1.2)
Mission create/update preserves context.authored_scope and structured reference
seeds (exact url, optional title). Scope uses restriction, allowed_urls,
allowed_domains, min_words, max_words, and max_sources. Ordinary references
do not restrict sources. Preview returns authored_scope, canonical contract ID
and SHA-256, semantic compiler revision and pinned source revision in both summary
and full output. It is a structural plan; worker deployment is a separate gate.
See the repository's cmos/contracts/mission-authoring-contract.md for the complete
field map. Explicit save, preview and submit remain separate actions.
