signed_fria_attestation
Produce an HMAC-signed FRIA attestation by submitting deployer name, AI system name, annex III category, and completed sections, receiving a signed document with verification URL.
Instructions
Produce an HMAC-signed FRIA attestation via the public meok-attestation-api.
Args: deployer_name: Legal name of the deployer. ai_system_name: Name of the AI system. annex_iii_category: Annex III category. completed_sections: List of FRIA section IDs that have been completed (e.g., ["a_deployer_processes", "b_period_frequency_use"]). sign_off_role: Role of the signer.
Returns: Signed attestation with verification URL.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| deployer_name | Yes | ||
| ai_system_name | Yes | ||
| annex_iii_category | Yes | ||
| completed_sections | Yes | ||
| sign_off_role | No | compliance-lead |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- meok_fria_generator/server.py:283-340 (handler)The `signed_fria_attestation` MCP tool handler function. It builds a FRIA attestation payload, sends it to the meok-attestation-api for HMAC signing, and returns the signed attestation with verification URL. Decorated with @mcp.tool() at line 283, making it a registered MCP tool.
@mcp.tool() def signed_fria_attestation( deployer_name: str, ai_system_name: str, annex_iii_category: str, completed_sections: list[str], sign_off_role: str = "compliance-lead", ) -> dict[str, Any]: """Produce an HMAC-signed FRIA attestation via the public meok-attestation-api. Args: deployer_name: Legal name of the deployer. ai_system_name: Name of the AI system. annex_iii_category: Annex III category. completed_sections: List of FRIA section IDs that have been completed (e.g., ["a_deployer_processes", "b_period_frequency_use"]). sign_off_role: Role of the signer. Returns: Signed attestation with verification URL. """ payload = { "kind": "fria-attestation", "deployer": deployer_name, "ai_system": ai_system_name, "annex_iii_category": annex_iii_category, "completed_sections": completed_sections, "missing_sections": [ sid for sid in ARTICLE_27_FIELDS.keys() if sid not in completed_sections ], "sign_off_role": sign_off_role, "signed_at": datetime.now(timezone.utc).isoformat(), "regulatory_basis": "EU AI Act Reg (EU) 2024/1689 Article 27", "tool": "meok-fria-generator-mcp", "tool_version": "1.0.0", } try: req = urllib.request.Request( f"{ATTESTATION_API}/sign", data=json.dumps({"payload": payload, "type": "fria"}).encode("utf-8"), headers={"Content-Type": "application/json"}, ) with urllib.request.urlopen(req, timeout=10) as resp: result = json.loads(resp.read().decode("utf-8")) return { "ok": True, "payload": payload, "signature": result.get("signature"), "verify_url": result.get("verify_url"), "attestation_id": result.get("attestation_id"), } except urllib.error.URLError as e: return { "ok": False, "error": f"attestation API unreachable: {e}", "payload": payload, "fallback": "Use payload above as self-attestation; sign locally with your own HMAC key.", } - meok_fria_generator/server.py:283-284 (registration)The tool is registered via the @mcp.tool() decorator on the `signed_fria_attestation` function. The FastMCP instance `mcp` (line 25) manages all tool registrations.
@mcp.tool() def signed_fria_attestation( - meok_fria_generator/server.py:29-68 (helper)The ARTICLE_27_FIELDS constant is used by the handler to determine which sections are missing from the completed_sections list (line 309-311). It defines the 7 mandatory FRIA fields under Article 27(1)(a)-(g).
# EU AI Act Article 27 — FRIA mandatory fields (per Article 27(1)(a)-(g)) ARTICLE_27_FIELDS = { "a_deployer_processes": { "label": "Deployer's processes in which the system will be used", "guidance": "Describe each business process where the high-risk AI system will be deployed. " "Include process owner, throughput volume, decision-making authority of the AI vs human.", }, "b_period_frequency_use": { "label": "Period and frequency of intended use", "guidance": "Time horizon (pilot 6mo / production 3yr / etc.) and frequency " "(real-time per request / batch nightly / etc.). Note any seasonality.", }, "c_categories_persons_affected": { "label": "Categories of natural persons and groups likely affected", "guidance": "Affected populations (employees, customers, candidates, claimants, citizens, etc.). " "Include vulnerable groups protected under EU Charter (children, disabled, refugees, minorities).", }, "d_specific_risks_harm": { "label": "Specific risks of harm likely to impact the categories of persons", "guidance": "Risks across: discrimination, dignity, privacy, freedom of expression, " "access to services, due process, mental health, economic outcomes. " "Use EU Charter of Fundamental Rights as the reference framework.", }, "e_human_oversight_measures": { "label": "Measures of human oversight per Art. 14", "guidance": "How the natural persons assigned human oversight are enabled to: (a) understand " "system capacity, (b) interpret outputs, (c) decide not to use the output, (d) intervene/halt, " "(e) reverse outcomes. Specific roles, training, escalation paths.", }, "f_internal_governance_complaint_mechanisms": { "label": "Internal governance + complaint mechanisms", "guidance": "Internal governance structure (AI ethics board, escalation paths). " "Complaint mechanisms for affected persons, including timelines and accessibility.", }, "g_review_modify_obligations": { "label": "Periodic review of FRIA + obligations to update", "guidance": "Frequency of FRIA review (annual / per-deployment / per-significant-change). " "Triggers for re-review (regulatory change, incident, complaint volume).", }, } - meok_fria_generator/server.py:27-27 (helper)The ATTESTATION_API endpoint URL (loaded from environment variable MEOK_ATTESTATION_API, defaulting to https://meok-attestation-api.vercel.app) is used by the handler to POST the attestation payload for signing.
ATTESTATION_API = os.environ.get("MEOK_ATTESTATION_API", "https://meok-attestation-api.vercel.app")