Skip to main content

MCP Server

CVD Portal exposes a Model Context Protocol (MCP) server so AI agents can act on the platform directly, the same way a script would use the REST API. An agent connected to it can submit a vulnerability report, read a company's CRA compliance status, and generate a CSAF advisory, without any custom integration code.

There are two servers, one for each side of a disclosure.

ServerEndpointWho it is forAuth
Manufacturer/api/mcpThe company operating a portal, acting inside its own workspaceOAuth 2.1 token or API key
Researcher/api/mcp/publicAnyone reporting a vulnerability to a manufacturerNone

The rest of this page covers the manufacturer server. The researcher server is documented under Public MCP server below.

The manufacturer server accepts companies on the Reporting plan or higher. Each tool also checks the plan.

  • Reporting. get_getting_started, get_next_deadline, get_next_task, the Article 14 tools record_article14_decision, prepare_article14_stage and open_incident, record_remediation_decision, and submit_job and get_job_status for drafting jobs.
  • Compliance. The CRA product tools, get_conformity_gaps, get_clause_mapping, record_assessment_result, and classification and conformity jobs.
  • Enterprise. All other tools, for example submission triage, advisories and get_compliance_status.

Below Enterprise, an API key can carry only the read scope, so it reaches only the read tools. The Article 14 and remediation tools need the article14:prepare, submissions:write or submissions:triage scope, so on Reporting and Compliance use browser sign-in (OAuth) for them. No MCP tool files a notification with ENISA. You file on the Single Reporting Platform yourself.

The server accepts either an OAuth 2.1 access token obtained via authorization code grant with PKCE, or a legacy Bearer API key. When accessed without credentials, it returns an HTTP 401 status with an RFC 9728 WWW-Authenticate header pointing to /.well-known/oauth-protected-resource so compatible agents can discover the authorization server and register automatically.

Endpoint​

https://cvdportal.com/api/mcp

The transport is streamable HTTP. There are two ways to authenticate.

MethodUse it forWhat happens
Browser sign-in (OAuth 2.1)Claude Code, the Claude apps, and other MCP clients that a person usesThe client opens your browser. You sign in to CVD Portal and approve the access. The client stores and renews the token.
API keyScripts, CI/CD pipelines, and servers with no browserYou send the key in the Authorization header on every request.

Use browser sign-in when a person runs the agent. The token is bound to you, so the audit log names you, and it is the only credential that can act for a client company (see Acting for a client company). An API key belongs to the company, not to a person.

Connecting with browser sign-in​

Claude Code

Add the server without a header:

claude mcp add --transport http cvd-portal https://cvdportal.com/api/mcp

Then, in an interactive claude session, run /mcp, select cvd-portal, and select Authenticate. Your browser opens.

Claude desktop app and claude.ai

Add a custom connector with the URL https://cvdportal.com/api/mcp and connect it. Your browser opens.

What you see in the browser

  1. The CVD Portal sign-in page, if you are not signed in already. Sign in with your password or with a sign-in provider such as Google, Microsoft or GitHub. If your account at that provider uses a passkey, you confirm with your fingerprint or face there.
  2. The consent screen. It names the client, your company, and the permissions (scopes) the client asks for. Select Authorize Access.
  3. The browser returns to the client, and the client is connected.

How it works

The client needs no configuration beyond the URL. A request without a token gets HTTP 401 with a WWW-Authenticate header that points to /.well-known/oauth-protected-resource. From there the client finds the authorization server, registers itself (RFC 7591), and starts the authorization code flow with PKCE. An access token lasts 1 hour. The client renews it with a refresh token, which lasts 30 days. After 30 days without use, you sign in again.

The token can only call tools whose scope you approved on the consent screen. A client that asks for no scopes gets a token that can call no tools. If every tool call fails with "OAuth token lacks the required scope", remove the connection, add it again, and check the permissions on the consent screen.

See Authentication for the endpoints and the standards they follow.

Connecting with an API key​

Create and scope keys under Settings → API Keys in the dashboard. On the Reporting or Compliance plan, you can create a key with only the read scope for the MCP server. Keys with other scopes need the Enterprise plan. A key with no scopes has full access. A scoped key can only call tools whose scope it carries.

Claude Code

claude mcp add --transport http cvd-portal https://cvdportal.com/api/mcp \
--header "Authorization: Bearer <your-api-key>"

Any MCP client

Point the client at https://cvdportal.com/api/mcp with the Authorization: Bearer <your-api-key> header. Clients that support the Model Context Protocol streamable HTTP transport discover the tools automatically.

Scopes​

Scoped API keys and OAuth tokens restrict which tools an agent can call.

ScopeDescription
readRead vulnerabilities, products, compliance and SBOM metadata
submissions:writeSubmit vulnerability reports
submissions:triageTriage and progress vulnerability reports
submissions:communicateDraft messages to reporters for approval
article14:preparePrepare CRA Article 14 notification dossiers
advisory:draftDraft CSAF and OpenVEX security advisories
products:writeRegister products, record classifications, and build the threat model
conformity:prepareRun conformity jobs, record assessments, and sign off Annex I requirements

Tools​

ToolScope requiredWhat it does
list_submissionsreadLists vulnerability reports with optional stage or status filtering.
get_submissionreadReturns decrypted case details excluding reporter contact information.
get_submission_journeyreadReturns the active journey stages, current status, and next step.
acknowledge_submissionsubmissions:triageAcknowledges a report and sends the standard template message.
triage_submissionsubmissions:triageSets severity, CVSS vector and score, and affected components.
link_submission_productsubmissions:triageLinks a vulnerability report to a workspace product.
record_article14_decisionarticle14:prepareRecords whether a vulnerability is actively exploited under CRA Article 14.
prepare_article14_stagearticle14:prepareSaves draft narrative fields and generates copy-ready SRP text.
assign_coordinatorsubmissions:triageAssigns a vulnerability coordinator from your team.
record_remediation_decisionsubmissions:triageRecords the remediation decision and target deadline.
record_fix_verificationsubmissions:triageConfirms that a deployed fix has been verified in production.
close_submissionsubmissions:triageCloses a vulnerability report as RESOLVED or DISMISSED with justification.
draft_reporter_messagesubmissions:communicateEnqueues a message to the vulnerability reporter for human approval.
request_advisory_publicationadvisory:draftEnqueues publication of an advisory draft for human approval.
open_incidentsubmissions:writeCreates a severe incident report and starts CRA Article 14 tracking. Severity is HIGH or CRITICAL, and HIGH when omitted.
submit_vulnerabilitysubmissions:writeFiles a disclosure report in your inbox, or in a client inbox with onBehalfOfCompanyId. Requires a description. The response names the company that received the report.
get_compliance_statusreadReturns your CRA compliance summary and recommendations.
generate_csaf_advisoryreadReturns the machine-readable advisory document for an existing advisory.
assess_responsereadEvaluates an incident or vulnerability response plan under CRA Article 14.
get_getting_startedreadReturns the ordered first steps for the company. Call it first.
get_next_deadlinereadReturns the soonest open Article 14 deadline.
get_next_taskreadReturns the next open CRA obligation.
submit_jobdepends on the job typeRuns a long job in the background. See Background jobs.
get_job_statusreadReturns the status, progress and result of a job. The plan check follows the job type, the same as submit_job.

CRA product tools​

These tools cover the product journey, from registration to the technical file. They need the Compliance plan features of the company they act for.

ToolScope requiredWhat it does
list_productsreadLists active products with their ids, the decided classification, the unconfirmed suggestion, and progress counts.
create_productproducts:writeRegisters a product. Records a class suggestion only. Refuses a duplicate name and returns the existing id.
set_product_classificationproducts:writeRecords the classification decision (Annex III or IV category, so the Article 32 route) and its legal basis. Needs an OAuth token.
generate_product_threatsproducts:writeGenerates STRIDE threat candidates. Does not save. Check source: catalogue means generic entries, not an analysis. Can take more than a minute.
propose_threat_treatmentproducts:writeProposes a mitigation and the residual risk for one threat. Does not save.
get_threat_modelreadReturns the saved assets, threats and risks, and every Annex I requirement with its key, evidence and sign-off.
save_threat_modelproducts:writeSaves assets, threats and risks row by row. null deletes a row. Sets risk treatment. Any validation failure refuses the whole save.
signoff_annex_i_requirementsconformity:prepare or products:writeSigns off or revokes Annex I requirements. See Annex I sign-off over MCP.
get_conformity_gapsreadLists open gaps across Annex I, technical documentation and evidence.
record_assessment_resultconformity:prepare or products:writeRecords a dated assessment of one CRA clause.
get_declaration_of_conformityreadBuilds the technical file with the Annex V Declaration of Conformity through the export gates. Returns the gaps when the file is not ready. Does not sign the declaration.

Background jobs​

submit_job takes a type and an input object.

TypeInputResult
CLASSIFY_PRODUCTtext, or productName and descriptionA class suggestion. It does not change the product. Use set_product_classification to record the decision.
IMPORT_PREFILLdocumentContent (text), productId, optional documentNameExtracts facts from the document and prefills the product assessment, each field with provenance. Send the text of a PDF, not the file.
AUTO_ENRICHproductIdFills the fixed risk methodology and the category standards.
ASSEMBLE_DOSSIERproductIdAssembles the technical dossier index and requests approval.
DRAFT_ARTIFACTartifactId, productId, inputsDrafts one CRA artifact.

A job for a product that is not in the job's company fails with "Product not found in this workspace". It does not report success.

Filing with the ENISA Single Reporting Platform stays with a person. Tools prepare draft text and calculate deadlines. Authorized personnel review the draft, file on the SRP, and record the reference in the portal.

Acting for a client company​

A consultancy can act for a client company where the consultancy user holds a seat (a partner membership). Pass the client's company id as onBehalfOfCompanyId on any tool that reads or changes company data.

  • Only a user-bound OAuth token can act for another company. A plain API key stays in its own company.
  • A read needs a membership in the client company. A write needs ADMIN there.
  • The membership is checked again on every call. When the client removes the seat, access stops at once.
  • The plan check uses the client's plan, not the consultancy's.
  • Background jobs run in the client company, so the job worker finds the client's products.

Without onBehalfOfCompanyId, every tool works in the company of the key or token. The company always comes from the verified credential and the membership check, never from a free tool argument.

Annex I sign-off over MCP​

signoff_annex_i_requirements records a legal attestation in the technical file.

  • The signatory is the person who owns the OAuth token. The platform takes the name and email from that user account, never from tool arguments.
  • A plain API key cannot sign.
  • The signatory must be ADMIN in the company the call acts for.
  • Each signed entry records that it came through MCP and through which OAuth client. The audit log records the same.

This differs from the dashboard. In the dashboard, a partner who drills into a client workspace cannot sign. Over MCP, a partner user who is ADMIN in the client company can sign for that client. Call the tool only when the signatory has reviewed the requirement and its evidence and has asked for the signature.

Public MCP server​

The researcher side needs no account and no API key. It exposes the same actions a researcher already performs in a browser, so an agent can find a vendor's portal, file a report, and follow it afterwards.

https://cvdportal.com/api/mcp/public

Claude Code

claude mcp add --transport http cvd-portal-public https://cvdportal.com/api/mcp/public
ToolWhat it does
find_vendor_portalLooks up a manufacturer's portal by slug or custom domain. Returns the portal URL, the security.txt URL, the policy URL, and the disclosure contact.
submit_vulnerability_to_vendorFiles a report to a manufacturer's portal. Takes a slug plus the report fields. Returns a reference number and a tracking token.
track_vulnerability_reportReads the current status of a filed report from its tracking token.
subscribe_to_reportSubscribes a public HTTPS callback URL to real-time status push notifications using the tracking token. Callbacks receive signed HTTP POST webhooks with status-only payloads.

Three things are worth knowing before an agent uses this.

Record the tracking token. It is the only route back to an anonymous report and it cannot be recovered.

Filing is limited to 5 reports per minute, per portal, per IP, the same ceiling as the web form. The limit is shared, so switching between the form and MCP does not raise it.

track_vulnerability_report returns status, vendor, product, and dates. It never returns the report body, the reproduction steps, the impact, or the contact details. A tracking token proves possession, not authorship.

A disclosure is a permanent record on the vendor's side and cannot be retracted through the API. Confirm the vendor and the finding with the person you are acting for before filing.

Privacy​

Tool-call analytics record which tool ran, its outcome, and timing. Argument and result content, which can include vulnerability details, is not recorded by default. This applies to both servers.

See also​