cispr_limit
Retrieve CISPR emission limits for radiated or conducted emissions by specifying frequency, standard, device class, and emission type.
Instructions
Get CISPR emission limits (CISPR 11, 22, 32, 14-1). Returns radiated or conducted limits for Class A or B.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| frequency_mhz | Yes | Frequency in MHz | |
| standard | Yes | CISPR standard | |
| device_class | No | Device class | |
| emission_type | No | Emission type |
Implementation Reference
- Tool handler dispatcher - routes 'cispr_limit' calls to get_cispr_limit()
async def call_tool(self, name: str, arguments: dict[str, Any]) -> list[TextContent]: if name == "cispr_limit": freq_mhz = arguments["frequency_mhz"] standard = arguments["standard"] device_class = arguments.get("device_class", "B") emission_type = arguments.get("emission_type", "radiated") result = get_cispr_limit(standard, device_class, freq_mhz, emission_type) return [TextContent(type="text", text=result)] - Core handler function - looks up CISPR limits from JSON data and returns formatted result
def get_cispr_limit(standard: str, device_class: str, freq_mhz: float, emission_type: str = "radiated") -> str: """Get CISPR emission limit as a formatted string.""" standard = standard.lower() device_class = device_class.lower() if "32" in standard or "22" in standard: data = CISPR_LIMITS.get("cispr_32", {}) elif "11" in standard: data = CISPR_LIMITS.get("cispr_11", {}) elif "14" in standard: data = CISPR_LIMITS.get("cispr_14_1", {}) else: return f"Unknown CISPR standard: {standard}" class_key = f"class_{device_class}" if device_class in ["a", "b"] else "class_b" class_data = data.get(class_key, data.get("group_1", {}).get(class_key, {})) if not class_data: return f"No data for {standard} Class {device_class.upper()}" result = f"CISPR {standard.upper()} Class {device_class.upper()} at {freq_mhz} MHz\n{'=' * 50}\n\n" if emission_type == "radiated": rad_data = class_data.get("radiated_emissions", {}) limits = rad_data.get("limits", []) limit = find_limit_for_frequency(limits, freq_mhz) if limit: result += f"Radiated Emissions (@ {rad_data.get('measurement_distance_m', '?')}m):\n" result += format_limit_result(limit) else: above_1g = rad_data.get("above_1ghz", {}) if above_1g and freq_mhz >= 1000: limits = above_1g.get("limits", []) limit = find_limit_for_frequency(limits, freq_mhz) if limit: result += f"Radiated Emissions >1GHz (@ {above_1g.get('measurement_distance_m', '?')}m):\n" result += format_limit_result(limit) if not limit: result += "No radiated limit found for this frequency" else: cond_data = class_data.get("conducted_emissions", {}) limits = cond_data.get("limits", []) limit = find_limit_for_frequency(limits, freq_mhz) if limit: result += f"Conducted Emissions ({cond_data.get('port', 'AC mains')}):\n" result += format_limit_result(limit) else: result += "No conducted limit found for this frequency" return result - Tool schema/registration - defines name, description, and input schema for the cispr_limit tool
Tool( name="cispr_limit", description="Get CISPR emission limits (CISPR 11, 22, 32, 14-1). Returns radiated or conducted limits for Class A or B.", inputSchema={ "type": "object", "properties": { "frequency_mhz": {"type": "number", "description": "Frequency in MHz"}, "standard": {"type": "string", "enum": ["CISPR 11", "CISPR 22", "CISPR 32", "CISPR 14-1"], "description": "CISPR standard"}, "device_class": {"type": "string", "enum": ["A", "B"], "description": "Device class"}, "emission_type": {"type": "string", "enum": ["radiated", "conducted"], "description": "Emission type"}, }, "required": ["frequency_mhz", "standard"], }, ), - src/mcp_emc_regulations/registry.py:14-52 (registration)Auto-discovery registers all ToolModule subclasses; CISPRTools is discovered via pkgutil and registered automatically
class ToolRegistry: """Discovers all :class:`ToolModule` subclasses in the ``tools`` package.""" def __init__(self) -> None: self._modules: list[ToolModule] = [] self._discover() # ------------------------------------------------------------------ # Public API used by server.py # ------------------------------------------------------------------ def list_tools(self) -> list[Tool]: result: list[Tool] = [] for mod in self._modules: result.extend(mod.list_tools()) return result async def call_tool(self, name: str, arguments: dict[str, Any]) -> list[TextContent]: for mod in self._modules: if mod.handles(name): return await mod.call_tool(name, arguments) return [TextContent(type="text", text=f"Unknown tool: {name}")] # ------------------------------------------------------------------ # Auto-discovery # ------------------------------------------------------------------ def _discover(self) -> None: """Import every module in the ``tools`` package and instantiate ToolModules.""" for info in pkgutil.iter_modules(_tools_pkg.__path__, _tools_pkg.__name__ + "."): module = importlib.import_module(info.name) for attr_name in dir(module): attr = getattr(module, attr_name) if ( isinstance(attr, type) and issubclass(attr, ToolModule) and attr is not ToolModule ): self._modules.append(attr()) - Helper used by get_cispr_limit to format limit entries for display
def format_limit_result(limit: dict, section: str = "") -> str: """Format a single limit entry for human-readable display.""" freq_range = f"{limit.get('freq_min_mhz', '?')} - {limit.get('freq_max_mhz', '?')} MHz" if "limit_dbuv_m" in limit: value = f"{limit['limit_dbuv_m']} dBuV/m" elif "limit_uv_m" in limit: value = f"{limit['limit_uv_m']} uV/m ({limit.get('limit_dbuv_m', '?')} dBuV/m)" elif "limit_dbuv" in limit: value = f"{limit['limit_dbuv']} dBuV" elif "limit_dbuv_qp" in limit: value = f"QP: {limit['limit_dbuv_qp']} dBuV/m, Avg: {limit.get('limit_dbuv_avg', '?')} dBuV/m" else: value = "See notes" distance = f"@ {limit['distance_m']}m" if "distance_m" in limit else "" detector = f"({limit['detector']})" if "detector" in limit else "" notes = f" - {limit['notes']}" if "notes" in limit else "" return f" {freq_range}: {value} {distance} {detector}{notes}"