Skip to main content
Glama
CSOAI-ORG

EU AI Act Compliance MCP

check_compliance

Assess AI system compliance with EU AI Act Articles 9–15. Input system details and current posture to receive a pass/fail checklist for core obligations.

Instructions

Run an EU AI Act compliance check against Articles 9-15 requirements.

Takes system details and current compliance posture, returns a detailed checklist with pass/fail/unknown for each requirement under Articles 9-15 (the core obligations for high-risk AI systems).

Args: system_name: Name of the AI system being assessed. purpose: Description of the system's intended purpose and use context. data_types: Types of data processed (e.g., "personal data, biometric data, health records"). decision_scope: What decisions the system makes or assists with (e.g., "loan approvals, hiring recommendations"). has_risk_management: Whether a documented risk management system exists (Article 9). has_data_governance: Whether data governance practices are in place (Article 10). has_technical_docs: Whether Annex IV technical documentation exists (Article 11). has_logging: Whether automatic event logging is implemented (Article 12). has_transparency_info: Whether transparency/instructions for use exist (Article 13). has_human_oversight: Whether human oversight measures are built in (Article 14). has_accuracy_testing: Whether accuracy, robustness, and cybersecurity are tested (Article 15). caller: Identifier for rate limiting. tier: "free" (10 calls/day) or "pro" (unlimited, $29/mo).

Behavior: This tool is read-only and stateless — it produces analysis output without modifying any external systems, databases, or files. Safe to call repeatedly with identical inputs (idempotent). Free tier: 10/day rate limit. Pro tier: unlimited. No authentication required for basic usage.

When to use: Use this tool when you need to assess, audit, or verify compliance requirements. Ideal for gap analysis, readiness checks, and generating compliance documentation.

When NOT to use: Do not use as a substitute for qualified legal counsel. This tool provides technical compliance guidance, not legal advice.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
system_nameYes
purposeYes
data_typesYes
decision_scopeYes
has_risk_managementNo
has_data_governanceNo
has_technical_docsNo
has_loggingNo
has_transparency_infoNo
has_human_oversightNo
has_accuracy_testingNo
callerNoanonymous
api_keyNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • Main execution function for the 'check_compliance' tool. It takes system details and compliance posture booleans, classifies risk, runs a 42-point checklist against Articles 9-15, computes a compliance score, checks GDPR relevance, and optionally trains the neural net.
    @mcp.tool()
    def check_compliance(
        system_name: str,
        purpose: str,
        data_types: str,
        decision_scope: str,
        has_risk_management: bool = False,
        has_data_governance: bool = False,
        has_technical_docs: bool = False,
        has_logging: bool = False,
        has_transparency_info: bool = False,
        has_human_oversight: bool = False,
        has_accuracy_testing: bool = False,
        caller: str = "anonymous",
        api_key: str = "") -> str:
        """Run an EU AI Act compliance check against Articles 9-15 requirements.
    
        Takes system details and current compliance posture, returns a detailed
        checklist with pass/fail/unknown for each requirement under Articles 9-15
        (the core obligations for high-risk AI systems).
    
        Args:
            system_name: Name of the AI system being assessed.
            purpose: Description of the system's intended purpose and use context.
            data_types: Types of data processed (e.g., "personal data, biometric data, health records").
            decision_scope: What decisions the system makes or assists with (e.g., "loan approvals, hiring recommendations").
            has_risk_management: Whether a documented risk management system exists (Article 9).
            has_data_governance: Whether data governance practices are in place (Article 10).
            has_technical_docs: Whether Annex IV technical documentation exists (Article 11).
            has_logging: Whether automatic event logging is implemented (Article 12).
            has_transparency_info: Whether transparency/instructions for use exist (Article 13).
            has_human_oversight: Whether human oversight measures are built in (Article 14).
            has_accuracy_testing: Whether accuracy, robustness, and cybersecurity are tested (Article 15).
            caller: Identifier for rate limiting.
            tier: "free" (10 calls/day) or "pro" (unlimited, $29/mo).
    
        Behavior:
            This tool is read-only and stateless — it produces analysis output
            without modifying any external systems, databases, or files.
            Safe to call repeatedly with identical inputs (idempotent).
            Free tier: 10/day rate limit. Pro tier: unlimited.
            No authentication required for basic usage.
    
        When to use:
            Use this tool when you need to assess, audit, or verify compliance
            requirements. Ideal for gap analysis, readiness checks, and generating
            compliance documentation.
    
        When NOT to use:
            Do not use as a substitute for qualified legal counsel. This tool
            provides technical compliance guidance, not legal advice.
        """
        allowed, msg, tier = check_access(api_key)
        if not allowed:
            return {"error": msg, "upgrade_url": "https://meok.ai/pricing"}
        limit_err = _check_rate_limit(caller, tier)
        if limit_err:
            return {"error": "rate_limited", "message": limit_err}
    
        # First classify to determine if high-risk
        classification_context = f"{purpose} {data_types} {decision_scope}"
        is_high_risk = False
        matched_areas = []
        for area in ANNEX_III_HIGH_RISK:
            if _match_keywords(classification_context, area["keywords"]):
                is_high_risk = True
                matched_areas.append(f"Area {area['area']}: {area['title']}")
    
        is_prohibited = False
        for practice in PROHIBITED_PRACTICES:
            if _match_keywords(classification_context, practice["keywords"]):
                is_prohibited = True
    
        # Map booleans to articles
        compliance_inputs = {
            "ART9": has_risk_management,
            "ART10": has_data_governance,
            "ART11": has_technical_docs,
            "ART12": has_logging,
            "ART13": has_transparency_info,
            "ART14": has_human_oversight,
            "ART15": has_accuracy_testing,
        }
    
        # Build checklist
        checklist = []
        total_checks = 0
        passed = 0
        failed = 0
        unknown = 0
    
        for req in COMPLIANCE_REQUIREMENTS:
            art_id = req["id"]
            has_it = compliance_inputs.get(art_id, False)
    
            checks_results = []
            for check_desc in req["checks"]:
                total_checks += 1
                if has_it:
                    status = "PASS"
                    passed += 1
                else:
                    status = "FAIL"
                    failed += 1
                checks_results.append({"check": check_desc, "status": status})
    
            checklist.append({
                "article": req["article"],
                "title": req["title"],
                "description": req["description"],
                "overall_status": "PASS" if has_it else "FAIL",
                "checks": checks_results,
            })
    
        # GDPR check based on data types
        gdpr_relevant = any(kw in data_types.lower() for kw in [
            "personal", "biometric", "health", "genetic", "ethnic", "racial",
            "political", "religious", "trade union", "sex life", "sexual orientation",
        ])
    
        # Special data categories (GDPR Article 9)
        special_categories = any(kw in data_types.lower() for kw in [
            "biometric", "health", "genetic", "ethnic", "racial", "political",
            "religious", "trade union", "sex life", "sexual orientation",
        ])
    
        score = (passed / total_checks * 100) if total_checks > 0 else 0
    
        result = {
            "system_name": system_name,
            "assessment_date": datetime.now().isoformat(),
            "risk_classification": "prohibited" if is_prohibited else ("high-risk" if is_high_risk else "potentially-high-risk"),
            "matched_annex_iii_areas": matched_areas,
            "compliance_score": f"{score:.1f}%",
            "summary": {
                "total_checks": total_checks,
                "passed": passed,
                "failed": failed,
                "unknown": unknown,
            },
            "gdpr_relevant": gdpr_relevant,
            "special_category_data": special_categories,
            "gdpr_note": (
                "WARNING: System processes special category data under GDPR Article 9. "
                "Explicit consent or other lawful basis required. Data Protection Impact Assessment (DPIA) "
                "likely mandatory under GDPR Article 35."
            ) if special_categories else (
                "System processes personal data — ensure GDPR compliance (Article 10(5) of the AI Act)."
            ) if gdpr_relevant else "No personal data identified in declared data types.",
            "checklist": checklist,
            "recommendation": (
                "CRITICAL: System may involve prohibited practices. Cease development/deployment immediately "
                "and seek legal review."
            ) if is_prohibited else (
                f"System scores {score:.1f}% compliance. "
                + (f"URGENT: {failed} requirement areas need attention before the system can be placed on the market. "
                   if failed > 0 else "All declared requirements are met. Proceed to conformity assessment. ")
                + "Full enforcement deadline: 2 August 2026."
            ),
            "regulation": "Regulation (EU) 2024/1689",
            "meok_labs": "https://meok.ai",
        }
    
        # Neural learning: train from this compliance check (if neural engine available)
        if _neural_net is not None:
            try:
                features = _neural_net.extract_features_from_system(
                    system_name=system_name,
                    uses_biometric="biometric" in data_types.lower(),
                    uses_health_data="health" in data_types.lower(),
                    uses_financial_data="financial" in data_types.lower() or "credit" in data_types.lower(),
                    has_human_oversight=has_human_oversight,
                    has_documentation=has_technical_docs,
                    deployed_cross_border=False,
                    model_explainable=True,
                )
                outcome = {
                    "overall_risk_score": 1.0 if is_prohibited else (0.8 if is_high_risk else 0.4),
                    "violation_probability": failed / max(1, total_checks),
                    "remediation_urgency": 1.0 if is_prohibited else (failed / max(1, total_checks)),
                    "audit_priority": 0.9 if is_prohibited else (0.7 if is_high_risk else 0.3),
                }
                learn_result = _neural_net.learn_from_check(features, outcome)
                result["neural_learning"] = {
                    "trained": True,
                    "loss": learn_result["loss"],
                    "checks_learned_from": learn_result["check_number"],
                }
            except Exception:
                result["neural_learning"] = {"trained": False, "reason": "learning error"}
        else:
            result["neural_learning"] = {"trained": False, "reason": "neural engine not available"}
    
        return result
  • server.py:806-807 (registration)
    The tool is registered via the @mcp.tool() decorator on the check_compliance function. mcp is a FastMCP instance.
    @mcp.tool()
    def check_compliance(
  • Input schema defined by function parameters: system_name, purpose, data_types, decision_scope (required strings), 7 boolean compliance booleans, and optional caller/api_key. Return type is str (actually dict).
    def check_compliance(
        system_name: str,
        purpose: str,
        data_types: str,
        decision_scope: str,
        has_risk_management: bool = False,
        has_data_governance: bool = False,
        has_technical_docs: bool = False,
        has_logging: bool = False,
        has_transparency_info: bool = False,
        has_human_oversight: bool = False,
        has_accuracy_testing: bool = False,
        caller: str = "anonymous",
        api_key: str = "") -> str:
  • Helper function _match_keywords used by check_compliance to match keywords case-insensitively.
    def _match_keywords(text: str, keywords: list[str]) -> list[str]:
        """Return matched keywords found in text (case-insensitive)."""
        text_lower = text.lower()
        return [kw for kw in keywords if kw.lower() in text_lower]
  • Helper function check_access unified access check (used by check_compliance for auth/rate limiting).
    def check_access(api_key: str = ""):
        """Unified access check — works with or without shared auth engine."""
        return _shared_check_access(api_key)
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description declares read-only, stateless, idempotent behavior with rate limits. However, it mentions a 'tier' parameter ('free' vs 'pro') that does not exist in the input schema, which is a factual error and could mislead an agent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a clear action verb, followed by args list, behavior, and usage guidance. It is front-loaded and efficient, though slightly lengthy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers purpose, parameters, behavior, and usage guidelines. Despite having an output schema, it only vaguely describes the return value. Overall, it is comprehensive for the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description provides detailed explanations for all 13 parameters, mapping boolean flags to specific articles. The inclusion of a nonexistent 'tier' parameter reduces clarity slightly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool runs an EU AI Act compliance check against Articles 9-15, specifying it returns a checklist with pass/fail/unknown. This distinguishes it from siblings like audit_report or classify_ai_risk.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description includes explicit 'When to use' and 'When NOT to use' sections, covering gap analysis, readiness checks, and legal disclaimer. It does not compare against siblings but provides sufficient context for invocation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/CSOAI-ORG/eu-ai-act-compliance-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server