AIR MCP Server
Connects AI assistants (Cursor, Claude Code/Desktop, VS Code, Windsurf, any MCP client) to AIR for governed AI risk assessments — discover projects, upload evidence, run assessments, and read structured EU AI Act reports, over stdio or hosted HTTP with OAuth.
Discovery — list/get domains and projects, create projects, full-text search across orgs, domains, and projects.
Documents & uploads — list document sources and artifacts, get download URLs, read extracted artifact text, upload via presigned PUT (
init→ PUT →complete) or one-shotair_upload_documentfor text.Assessments — create drafts, start/retry runs (consumes credits), poll status, inspect stage logs and input artifacts, and wait with exponential backoff.
Reports — fetch full reports or slice by section with offset/limit paging for large lists; get a slim summary (tier, section counts, saved choices, changes since previous scan).
EU AI Act screening — ask open/screening questions via dialogs, submit fact answers with justification, save pre-scan answers, and re-check the tier under current rules without a new scan or credit.
Governance — record and list project decisions (
not_applicable/accept_gap), check/postpone AIR rules-change notices.Portfolio — domain-level portfolio dashboard (fullPipeline scope).
Composites — run whole pipelines (local file → upload → assess) as MCP Tasks; stdio can read local files.
Account & credentials — create an account in-chat (with or without existing credentials, via MCP Apps form or elicitation), stored key at
~/.air/credentials.json(0600), sign out locally; no credential needed to boot (setup mode).Support — send feedback, request credits, check credit balance.
Resources & prompts — report JSON, stage logs, and project-assessment resources; guided workflows for running/reviewing assessments and exploring portfolios.
Click 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., "@AIR MCP ServerStart a risk assessment for project 'Photon' using the latest uploaded evidence."
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.
AIR MCP Server
Connect AI assistants to AIR (AI Responsibly) for governed risk assessments: discover projects, upload evidence, run assessments, and retrieve structured reports — from Cursor, Claude Code, Claude Desktop, VS Code, Windsurf, or any Model Context Protocol client.
This package ships two transports:
Transport | Who uses it | How |
stdio (default) | Local IDE agents (Cursor, Claude Code, VS Code, …) |
|
Streamable HTTP | Claude Directory / remote MCP clients | Hosted at |
Local assessment workloads still execute on Thalus cloud via the AIR Integrator API. For stdio you provide a domain-scoped API key, or let the server store one when you create an account in chat; remote Directory clients authorize through the AIR portal (OAuth). No local database, worker, or Docker stack is required for stdio.
No AIR account? Create one from inside the conversation on the local server or the hosted connector — see Starting without an account.
Overview
┌──────────────────────┐ stdio MCP ┌──────────────────┐ HTTPS ┌─────────────────┐
│ Your IDE / agent │ ◄────────────► │ @thalus-ai/ │ ────────► │ AIR Integrator │
│ (Cursor, Claude, │ │ mcp-air (local) │ │ API (cloud) │
│ VS Code, …) │ └──────────────────┘ └─────────────────┘
└──────────────────────┘Component | Role |
This server | Exposes MCP tools, resources, and prompts; translates agent requests to Integrator API calls |
AIR cloud | Document extraction, risk pipeline, billing, and report generation |
Your API key | Domain-scoped bearer token created in the AIR portal |
Related MCP server: Phantom MCP
Prerequisites
Node.js 20+
An AIR organization with active billing (assessments consume credits) — or create one from the conversation, see Starting without an account
A credential, from any of three sources — see Credentials. None is needed to start: with no credential the server boots in setup mode so you can create an account.
Quick start
1. Create an API key
In the AIR portal: open your domain → API Keys → create a key with the assessmentRunner or fullPipeline preset (see below).
2. Configure your MCP client
Add the server to whichever client you use. All clients run the same npx command; only the config file and JSON root key differ.
Most clients (Cursor, Claude Code, Claude Desktop, Windsurf) — mcpServers:
{
"mcpServers": {
"air": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@thalus-ai/mcp-air@1.5.0"],
"env": {
"AIR_API_KEY": "${env:AIR_API_KEY}"
}
}
}
}VS Code — servers in .vscode/mcp.json (docs):
{
"servers": {
"air": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@thalus-ai/mcp-air@1.5.0"],
"env": {
"AIR_API_KEY": "${env:AIR_API_KEY}"
}
}
}
}Set AIR_API_KEY in your shell, or use envFile where supported. See Client setup for file paths per IDE.
3. Verify
Ask your agent to run air_list_domains and air_list_projects. You should see successful tool calls in the MCP log.
MCP Inspector (optional):
AIR_API_KEY=your-key npx @modelcontextprotocol/inspector npx -y @thalus-ai/mcp-air@1.5.0Remote HTTP (operators)
Hosted endpoint: https://mcp.air.thalus.ai/mcp.
# After build
AIR_API_URL=https://api.air.thalus.ai \
MCP_OAUTH_RESOURCE=https://mcp.air.thalus.ai/mcp \
REDIS_URL=redis://127.0.0.1:6379 \
OAUTH_INTROSPECT_CLIENT_ID=your-resource-server-client-id \
OAUTH_INTROSPECT_CLIENT_SECRET=your-resource-server-client-secret \
MCP_HTTP_PORT=4104 \
node dist/build/http.mjsTwo variables carry this deployment's identity, and both default to production:
Variable | What it sets |
| The upstream API and the protected-resource metadata origin advertised in the |
| This server's own public URL, which access tokens must name as their audience |
Set both when running anywhere other than production. Left at their defaults, a staging or dev server sends clients to production for OAuth discovery and then rejects the tokens they come back with, because the audience never matches.
Deploy notes, Angie, and systemd units live in infra/.
Remote clients authorize with OAuth 2.0 against https://api.air.thalus.ai (authorization code + PKCE S256, dynamic client registration). Discovery starts from the 401 on /mcp, whose WWW-Authenticate header points at https://api.air.thalus.ai/.well-known/oauth-protected-resource. Access tokens must carry https://mcp.air.thalus.ai/mcp as their audience.
End-user setup: Remote MCP server (OAuth).
Starting without an account
Both transports support this. On stdio the server boots in setup mode with no credential; on the remote transport the connector can be added without a token. These tools need no credential:
Tool | What it does |
| Collects name, email, organization, code and terms — in a form or a dialog |
| Sends feedback to Thalus — you are asked for a reply address when you have no account |
| The form's own callbacks; hidden from the model |
| stdio only; clears the stored credential |
On the remote transport, everything else is protected. The first time the assistant calls a protected tool without a token, the server answers HTTP 401 with a WWW-Authenticate challenge, and the client shows its inline Connect card. You authorize in a popup, the client retries the same call automatically, and the conversation carries on — nothing is lost. This is lazy authentication; the alternative, refusing every request until you sign in first, is what made an agent-first signup impossible.
Creating an account in chat:
Ask the assistant to create an AIR account. It calls
air_create_account.Type your name, work email and organization. You type them — the model supplies nothing, and what you type does not enter its context.
Enter the code emailed to you, tick the terms box, and submit. The terms tick is read from the checkbox only; the model cannot set it, and the API refuses without it.
On the remote transport, press the sign-in button: it gives your browser a session, so the OAuth consent screen appears directly next time. On stdio there is nothing more to do — the key is already stored and the full tool set is available.
Your organization starts on the Free plan with one assessment credit per 30 days. Use air_get_credit_balance to see where you stand and air_request_credits to ask for more.
Neither feedback nor a credit request asks the assistant for an email address. Thalus replies to the organization owner, or to an address you type yourself in the confirmation dialog. Only the unauthenticated case needs one from you, because there is no account to reply to.
What your client supports
air_create_account uses the richest input your client offers:
Client capability | What happens |
MCP Apps (Claude Code, Claude, VS Code) | A form renders in the conversation. Fields never reach the model at all. |
Elicitation only | Two dialogs: details, then the code and the terms checkbox. |
Neither | The portal signup link, and it stops. It will not ask the model for your details. |
Credentials
The stdio server resolves a credential in this order, and starts either way:
Order | Source | Notes |
1 |
| Set in your MCP client config. Wins over anything on disk. |
2 |
| Written by |
3 | none → setup mode | Only the tools that work without an account are offered. |
The stored file holds a bearer key, so it is written with mode 0600 (owner read/write only) in a directory created 0700. The key is written straight to that file and never returned in a tool result, so it does not end up in your conversation transcript or your client's logs. Alongside it the file records the API URL, org slug, domain pid, domain slug and creation time, so the server can answer "which account is this?" without a network call.
A damaged or unreadable credential file is reported on stderr and treated as no credential, so the server still starts in setup mode; air_sign_out removes the file.
Setup mode
With no credential, the server offers five tools — air_create_account, air_submit_feedback, air_sign_out, and the signup form's two callbacks. Everything else is registered but disabled, so it is not offered and cannot be called.
The moment an account is created, the key is stored and the full surface is enabled, and the server emits tools/list_changed. No restart is needed — the client sees the tool list grow in place.
Signing out
air_sign_out deletes ~/.air/credentials.json and returns to setup mode. The account itself is untouched; you can sign back in with the same key or create another account.
Signing out forgets the key on this machine — it does not revoke it. The key keeps working anywhere else it is held. If the machine was lost, shared, or is no longer yours, revoke the key itself in the AIR portal: open your domain → API Keys, find the key for the MCP service account, and revoke it there.
If your key came from AIR_API_KEY, there is no file to delete and the tool says so rather than reporting a success: remove the variable from your client configuration and restart. If a stored file also exists, the result tells you that too, since that file would take over once the variable is gone.
Configuration
For stdio you can set AIR_API_KEY, or create an account in the conversation and let the server store one. The server connects to production AIR automatically.
API key scopes
Choose a portal preset when creating your key:
Preset | Use when | Scopes (summary) |
| List domains/projects, start assessments, read reports on existing artifacts |
|
| Upload documents, search, domain portfolio, create projects | Above plus |
Capability | Minimum preset |
|
|
|
|
|
|
|
|
Org-wide portfolio dashboards require a browser session in the portal and are not available via MCP.
Full scope reference: Authentication guide.
Client setup
Client | Config file | Notes |
Cursor |
| Restart after changes |
Claude Code |
| Or: |
Claude Desktop | See platform paths below | Quit and reopen the app |
VS Code |
| Use Copilot Agent mode; root key is |
Windsurf |
| Same |
Other | Your client's MCP docs | Same |
Claude Desktop paths
Platform | Path |
macOS |
|
Windows |
|
Logs (macOS): ~/Library/Logs/Claude/mcp*.log
Full walkthrough: air.thalus.ai/docs/mcp-air-setup
Capabilities
Tools (45 stdio / 42 remote)
Category | Tools |
Discovery |
|
Documents |
|
Assessments |
|
Scan prep |
|
Decisions |
|
Portfolio |
|
Composites |
|
Account |
|
Support |
|
air_ask_open_facts — Ask the open EU AI Act questions as a short form: a checklist of what the system does, then details for what was ticked. Saves each page and re-checks the tier.
air_ask_screening_questions — Ask the same checklist before a scan; hold the answers and save them with air_save_prepared_answers once the scan starts.
air_recheck_tier — Re-check a scan's tier under the current AIR rules, with no new scan and no credit.
air_upload_document — Upload a text document, such as the scan summary, to a project in one call: start the upload, send the content, finish it, and wait until AIR has read it.
† stdio only ‡ needs no credential § form-only, hidden from the model ¶ stdio only — it exists where a credential file can
The stdio count is one higher than the remote count because air_sign_out manages the local credential file, and the hosted transport has none: there, OAuth is the credential.
air_wait_for_* block with exponential backoff until the resource is ready or timeoutMs elapses, then return ready: false with the last observed status — call again with the same pid to keep waiting. Pipeline tools (air_run_assessment_from_file, air_run_full_assessment_pipeline) use the MCP Tasks extension and return a task handle immediately, so they require a Tasks-capable client.
Surface differences: stdio vs remote
Local capability | Remote equivalent |
Read a local file ( |
|
MCP Tasks ( |
|
Uploads work the same on both surfaces, through the presigned pair. The client must be able to reach the storage host to perform the PUT.
Remote waits are capped at 240s per call (hosted clients abort a tool call at 300s); stdio keeps the longer 10 / 30 minute ceilings.
Uploading to the presigned URL
The presigned URL signs content-type and host only. Send the file bytes with the same contentType you passed to air_upload_document_init and nothing else:
curl -X PUT --upload-file ./model-card.pdf \
-H 'Content-Type: application/pdf' \
"$UPLOAD_URL"Do not add x-amz-* headers. AWS SDKs and aws s3 cp attach x-amz-checksum-crc32 and x-amz-sdk-checksum-algorithm by default; those are not part of the signature and the PUT fails with SignatureDoesNotMatch. With boto3, set AWS_REQUEST_CHECKSUM_CALCULATION=when_required, or use a plain HTTP client.
Reading a large report
A full report can run past what a single tool result can carry, so air_get_assessment_report degrades in steps rather than getting truncated:
Call | You get |
| Overview, quality, EU AI Act tier, per-section counts, saved choices, and what changed since the previous scan |
| The whole report, or a section index if it doesn't fit |
| That one slice |
| A page of a list section, with |
| The raw full report, unsliced |
The section index lists every section with its serialized size and item count, so a caller that overflows can pick deliberately instead of guessing. List sections page automatically: ask for riskRegister and you get as many entries as fit plus a nextOffset to resume from.
Resources (3 templates)
URI pattern | Description |
| Completed assessment report JSON |
| Stage execution log |
| Assessments for a project |
App resource (1)
URI | Description |
| The in-chat signup form, served as |
Prompts (3)
Name | Purpose |
| End-to-end assessment workflow guidance |
| Structured report review |
| Domain portfolio exploration |
Typical workflow
No account yet?
air_create_account(remote transport) — see Starting without an accountair_list_domains→ obtaindomainPidair_list_projects→ obtainprojectPid(orair_create_projectwith fullPipeline)Upload evidence:
air_run_assessment_from_file(stdio), orair_upload_document_init→ PUT →air_upload_document_complete→air_wait_for_document_extractionair_start_assessmentwithartifactPidsfromair_list_artifactsair_wait_for_assessmentair_get_assessment_reportor read theair://assessments/{id}/reportresource
See the Integration flow guide for the underlying HTTP API sequence.
Development
Contributors: see AGENTS.md for build, test, publish, and optional AIR_API_URL override.
git clone https://github.com/VericyIO/mcp-air.git
cd mcp-air && pnpm install && pnpm build
pnpm testDocumentation
Resource | URL |
MCP setup guide | |
Integrator API guides | |
API reference | |
Agent skills (optional) |
Security
The MCP process runs with your OS user privileges. Tools such as
air_run_assessment_from_filecan read any local path your user can access.Pin the package version in production (
@thalus-ai/mcp-air@1.5.0) rather than floating@latest.Use least-privilege API key scopes. Write tools (
air_start_assessment, uploads) consume organization credits.Never commit API keys. Use
envorenvFilein MCP client configuration.
Privacy
The AIR cloud (Thalus) processes the documents, project data, and account information you submit through this server in order to run assessments and generate reports. See the Privacy Policy for details on data collection, usage and storage, third-party sharing, and retention. Contact privacy@thalus.ai with privacy questions.
License
MIT — see LICENSE.
Related repositories
VericyIO/mcp-air — this server (source)
VericyIO/thalus-air-skills — optional agent skills for MCP workflows
Maintainer notes (build, publish, constants sync): see AGENTS.md.
Available Tools
45 toolsair_ask_open_factsAsk open EU AI Act questionsADestructive
Ask the person the open EU AI Act questions one at a time. Each dialog shows the full question, then Yes, No and Not sure, or the labelled options. Saves each answer and re-checks the tier, until no question is open or every open one is "Not sure". proposedAnswers may only cover facts marked suggestFromCode, which the code can show; never suggest what the system is used for or whom it affects. Pass back notSureFactPaths from the last call as skipFactPaths. Answers are kept on the project for later scans. Requires assessments:write.
Inputs: assessmentPid (required), skipFactPaths, proposedAnswers.
air_ask_screening_questionsAsk the EU AI Act checklist before a scanARead-only
Before a scan, ask the person each EU AI Act screening question in its own dialog, with the full question and Yes, No and Not sure, or the labelled options. Facts the project already holds an answer for are left out. Returns the answers to hold: after air_start_assessment, send them with air_save_prepared_answers. It saves nothing itself. Requires projects:read.
Inputs: projectPid (required).
air_create_accountCreate an AIR accountADestructive
Open a form in this conversation to create an AIR account. The person types their own details and accepts the terms; the model supplies nothing. Needs no existing account.
Inputs: no named parameters.
air_create_assessment_draftCreate assessment draftADestructive
Create an assessment draft without starting the pipeline. Requires assessments:write.
Inputs: name (required), projectPid (required), artifactPids (required).
air_create_projectCreate projectADestructive
Create a project in a domain. Requires domains:write (fullPipeline preset). Returns project pid and slug.
Inputs: name (required), slug (required), domainPid (required), description.
air_get_artifact_textGet artifact textBRead-only
Get extracted plain text for an artifact. Requires projects:read.
Inputs: projectPid (required), artifactPid (required).
air_get_assessmentGet assessmentBRead-only
Get assessment detail including status and workflowRunId. Requires assessments:read.
Inputs: assessmentPid (required).
air_get_assessment_input_artifactsGet assessment input artifactsBRead-only
List artifacts used as inputs when the assessment report was generated. Requires assessments:read.
Inputs: assessmentPid (required).
air_get_assessment_reportGet assessment reportARead-only
Fetch the structured risk assessment report for a completed run. Omit section to get the whole report; if it is too large for one response you get a section index instead — each section with its size and item count — so you can pull the parts you need. Pass section for one slice, and offset/limit to page through a list section such as riskRegister or evidenceAppendix. Requires assessments:read.
Inputs: assessmentPid (required), limit, offset, section.
air_get_assessment_stagesGet assessment stagesARead-only
List per-stage checkpoint logs for an assessment run. Requires assessments:read.
Inputs: assessmentPid (required).
air_get_assessment_summaryGet assessment summaryARead-only
Fetch a slim assessment report summary without the full risk/evidence payload: overview, quality, the EU AI Act tier (value, name, description, and final: true when no open question can change it) with the names of the matched criteria, section counts, the saved project choices (projectDecisions, each with posture and, when it came back, cameBackBecause), and changesSincePrevious — each checklist item that closed, is still open, is new, was newly judged, came back, or could not be judged since the previous completed scan, plus inputs: the documents added, removed, or changed in content (a re-upload of the same text is unchanged). Read those labels as given; do not work out the match yourself. Prefer this over air_get_assessment_report for triage. topRisks lists the first few risk-register items in short form; fetch the riskRegister section of air_get_assessment_report for the full list. Requires assessments:read.
Inputs: assessmentPid (required).
air_get_credit_balanceGet credit balanceARead-only
Assessment credits available to this organization, with the plan and the cost per assessment. Call it before a batch of assessments so the limit is predicted instead of hit.
Inputs: no named parameters.
air_get_document_download_urlGet document download URLARead-only
Get a presigned download URL for an uploaded document source. Requires projects:read.
Inputs: sourcePid (required), projectPid (required).
air_get_domainGet domainARead-only
Resolve a domain by pid from air_list_domains results, or by orgSlug + domainSlug via slug lookup.
Inputs: orgSlug, domainPid, domainSlug.
air_get_domain_portfolioGet domain portfolioBRead-only
Domain-level portfolio dashboard. Requires portfolio:read (fullPipeline preset). Domain-scoped API keys only work for their bound domain.
Inputs: orgSlug (required), domainSlug (required).
air_get_projectGet projectARead-only
Resolve a project by pid from air_list_projects, or by orgSlug + domainSlug + projectSlug.
Inputs: orgSlug, domainSlug, projectPid, projectSlug.
air_get_rules_noticeCheck if the AIR rules have moved onCRead-only
due is true when the latest completed scan used older AIR EU AI Act rules and nobody has said later to the current ones. lastCompleted.tier is the stored tier and lastCompleted.tierUnderCurrentRules is what the same facts give now. postponed says when someone said later to the current rules. Do not decide the version yourself. Requires projects:read.
Inputs: projectPid (required).
air_list_artifactsList artifactsBRead-only
List document-derived artifacts for a project. Use artifact pids in air_start_assessment. Requires projects:read.
Inputs: projectPid (required), includeArchived.
air_list_assessmentsList assessmentsBRead-only
List assessment summaries for a project. Requires assessments:read.
Inputs: projectPid (required).
air_list_documentsList documentsARead-only
List document sources for a project. Poll until status is connected before starting an assessment. Requires projects:read.
Inputs: projectPid (required), includeArchived.
air_list_domainsList domainsARead-only
List domains visible to the API key. For domain-scoped service account keys, returns the single bound domain. Requires domains:read scope.
Inputs: no named parameters.
air_list_open_factsList open EU AI Act factsARead-only
List the open EU AI Act questions for an assessment: only facts whose answer can still change the tier and that are worth asking now, checklist facts first. screeningGroups are the checklist lines that still hold an open fact. Each item has question (ask it as written), help (one line on why it matters) and, for list facts, options (show the labels, send the values). Boolean facts take true, false, or null for "Not sure"; list facts take option values, or [] for none. answerConflicts are earlier answers that this scan read differently, with the scan's excerpts. Never show factPath, description or a raw null to the person. Prefer air_ask_open_facts when the client can show forms. Requires assessments:read.
Inputs: assessmentPid (required).
air_list_project_decisionsList saved project choicesARead-only
List saved choices for a project, each judged against assessmentPid. posture: stands (quiet; the topic is raised on the same documents and seriousness the person decided on), conflicts (show the saved sentence and ask again; cameBackBecause says why: new_evidence = the scan cites text that was not in the documents they decided on, more_serious = the topic moved up, for example from the watchlist to a risk, review_due = six months have passed), settled (the accepted gap is no longer open). Requires projects:read.
Inputs: projectPid (required), assessmentPid (required).
air_list_project_fact_answersList saved project fact answersCRead-only
Active answers already saved on the project. factPath is for the tool call. Do not show factPath to the person. Requires projects:read.
Inputs: projectPid (required).
air_list_projectsList projectsARead-only
List projects in a domain (paginated). Requires domains:read and projects:read. Use domainPid from air_list_domains.
Inputs: domainPid (required), page, search, pageSize.
air_postpone_rules_noticeKeep the result on older AIR rules for nowCDestructive
The person said later to the current AIR rules. Records who and when. The notice returns when the rules move past this version. Refused when nothing is due. Requires projects:write.
Inputs: projectPid (required).
air_recheck_tierRe-check the tier under the current AIR rulesADestructive
Re-check a scan's EU AI Act tier under the current AIR rules from the facts it already holds. Reads no documents and spends no credit. Returns previousTier, the new tier, and the questions that can still change it. Requires assessments:write.
Inputs: assessmentPid (required).
air_record_project_decisionSave a project choiceADestructive
Save a developer choice on the project, in the person's own words. Ask them first. Use not_applicable when the whole topic (themeId) does not apply to this system: later scans keep that topic and its gaps quiet while it is raised on the same documents and seriousness, and bring it back when the scan cites new text, the topic grows more serious, or six months have passed. Use accept_gap when the topic applies but the person accepts one missing control (controlId required): the gap stays listed with the saved sentence beside it. Pass the assessmentPid the person decided on; the choice remembers that scan's documents. The scan the choice is recorded on does not judge it; later scans do. A later choice for the same theme or control replaces the earlier one. Requires projects:write.
Inputs: choice (required), reason (required), themeId (required), projectPid (required), +2 more.
air_request_creditsRequest more creditsADestructive
Ask Thalus for more assessment credits. The person reviews the amount and the reason before the request is sent, and Thalus replies by email to the organization owner. To buy credits immediately instead, call air_get_credit_balance for the purchase link.
Inputs: reason (required), credits (required).
air_retry_assessmentRetry assessmentADestructive
Retry a failed assessment from the last completed stage. Requires assessments:write and consumes credits.
Inputs: assessmentPid (required).
air_run_assessment_from_fileRun assessment from local fileADestructive
Upload a local file, wait for extraction, start assessment on the new artifact. Consumes credits. Requires projects:write and assessments:write. Returns an MCP Task handle immediately. Reads filePath with your OS user permissions.
Inputs: filePath (required), projectPid (required), name, contentType.
air_run_full_assessment_pipelineRun full assessment pipelineBDestructive
Start assessment on existing artifacts, wait for completion, return report summary. Consumes credits. Returns an MCP Task handle immediately; poll tasks/get until completed.
Inputs: name (required), projectPid (required), artifactPids (required), waitTimeoutMs.
air_save_prepared_answersSave answers before the scan has factsADestructive
Save the checklist answers right after air_start_assessment. They are kept on the project and applied when the scan reads its facts; a scan that reads a different value from the documents raises it as a conflict. Refused once the scan has read its facts. It does not recompute the tier. Requires assessments:write.
Inputs: answers (required), assessmentPid (required).
air_searchSearchARead-only
Full-text search across orgs, domains, and projects. Requires search:read scope (fullPipeline preset; not included in assessmentRunner).
Inputs: q (required), kind, limit.
air_sign_outSign out of AIR on this machineADestructive
Remove the AIR credentials stored on this machine and return to setup mode. The account itself is untouched. A key supplied through AIR_API_KEY cannot be removed here — the result says where to remove it instead.
Inputs: no named parameters.
air_signup_send_codeSignup: send verification codeADestructive
Signup form step one: send the verification code. Submitted by the form itself, not by the assistant.
Inputs: name (required), email (required), orgName (required).
air_signup_verify_codeSignup: verify codeADestructive
Signup form step two: verify the code and create the account. Submitted by the form itself, not by the assistant.
Inputs: otp (required), acceptTerms (required), termsVersion (required), continuationToken (required).
air_start_assessmentStart assessmentADestructive
Start a risk assessment on a project. Consumes org credits and dispatches the risk pipeline. Requires assessments:write. Returns assessmentPid and reportUrl. Give the person the reportUrl link when the scan starts.
Inputs: name (required), projectPid (required), artifactPids (required).
air_submit_fact_answersSubmit EU AI Act fact answersADestructive
Submit answers for open EU AI Act facts and re-derive the tier on this assessment, with no new scan. Pass factPath + value + a short justification in the person's words. An array fact accepts only its allowedValues; any other word is refused with 422 naming the allowed values. Answers are kept on the project, so later scans start from them; null ("I don't know") clears a kept answer. Answering a conflicted fact replaces the kept answer. Requires assessments:write.
Inputs: answers (required), assessmentPid (required).
air_submit_feedbackSend feedback to ThalusBDestructive
Send product feedback to Thalus. The person reviews the text before it is sent. A reply goes to the organization owner, or to an address the person gives. Works without an AIR account, where the person is asked for one.
Inputs: message (required), category (required).
air_upload_documentUpload a text documentADestructive
Upload a text document, such as the scan summary, to a project in one call: start the upload, send the content, finish it, and wait until AIR has read it. Returns the source and its status. For binary files, use air_upload_document_init and the related tools. Requires projects:write.
Inputs: content (required), fileName (required), projectPid (required), contentType.
air_upload_document_completeComplete document uploadADestructive
Finalize a presigned upload after the PUT to uploadUrl succeeded. Dispatches the document extraction workflow. Requires projects:write.
Inputs: s3Key (required), filename (required), projectPid (required), contentType (required).
air_upload_document_initInitialize document uploadADestructive
Start a presigned upload: returns uploadUrl and s3Key. PUT the raw file bytes to uploadUrl with the same contentType you passed here and no other headers — the URL signs content-type and host only, so any x-amz-* header (notably the checksum headers AWS SDKs add by default) invalidates the signature. Then call air_upload_document_complete with the returned s3Key. Requires projects:write.
Inputs: filename (required), projectPid (required), contentType (required).
air_wait_for_assessmentWait for assessmentARead-only
Wait until an assessment is completed, failed, or reportAvailable, or until its step differs from lastStageLabel, up to timeoutMs. Uses exponential backoff. A new step returns ready:false with stageLabel ("Step 4 of 12: Checking each risk theme"), the line to show the person, and reportUrl. Call again with lastStageLabel set to the line you showed. Returns ready:false with the last observed status if the wait budget runs out — call again to keep waiting. Requires assessments:read.
Inputs: assessmentPid (required), timeoutMs, lastStageLabel.
air_wait_for_document_extractionWait for document extractionARead-only
Wait until sourcePid reaches connected or error, up to timeoutMs. Uses exponential backoff. Returns ready:false with the last observed status if the wait budget runs out — call again with the same sourcePid to keep waiting. Requires projects:read.
Inputs: sourcePid (required), projectPid (required), timeoutMs.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
TDQS
Scored across 45 tools
Several tools overlap significantly, especially around starting assessments (air_start_assessment, air_run_full_assessment_pipeline, air_run_assessment_from_file) and answering facts (air_ask_open_facts, air_submit_fact_answers, air_save_prepared_answers). Descriptions are detailed and provide some differentiation, but an agent could easily misselect among these similarly purposed tools.
All tool names follow a consistent air_verb_noun or air_verb pattern in snake_case. There is no mixing of camelCase or inconsistent verb styles; the prefix and structure are predictable throughout.
45 tools is excessive for the apparent scope, with multiple redundant entry points for the same core workflows (assessment initiation, fact answering, uploads). The server would benefit from consolidation to reduce cognitive load and misselection risk.
Core lifecycle for risk assessment is well covered: project creation, document upload and extraction, assessment start and reporting, fact answering, decisions, credits, and account flows. Minor gaps exist such as no project update/delete or document deletion, but agents can work around them.
Maintenance
Related MCP Connectors
Governance maturity assessment, compliance gap analysis, and evidence-linked briefs for AI agents.
AI-native GRC: compliance scores, security findings, tickets and agent trust tiers.
Run AI evaluations, record agent traces and gate releases on evidence, with scoped org access.
Connect your AI assistant to governed tender and RFP dossiers: sources, versions, decisions.
Related MCP Servers
AlicenseAqualityBmaintenanceEnables AI agents to assess AWS environments against the AWS Security Reference Architecture (SRA) by providing tools to discover, describe, and run security checks across AWS services and accounts.53Apache 2.0- FlicenseNot gradedqualityDmaintenanceEnables authorized compliance verification and security auditing through natural language, bridging AI assistants with industry-standard security tools for enterprise audits.24-
- AlicenseBqualityBmaintenanceEnables AI agents to interact with the SCF Controls Platform for security compliance, including browsing controls, tracking implementation, managing evidence, assessing risks, and monitoring vendors via natural language.26790 npm3MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI impact assessments according to ISO/IEC 42005:2025, with built-in EU AI Act compliance and support for phases, categories, and assessment operations.30 PyPIMIT