Skip to main content
Glama
RFingAdam

EMC Regulations MCP Server

by RFingAdam

fcc_part15_limit

Get FCC Part 15 emission limits for unintentional or intentional radiators at a specified frequency. Choose section and device class to retrieve radiated or conducted limits.

Instructions

Get FCC Part 15 emission limits for a frequency. Returns Class A and/or Class B limits for unintentional radiators (15.109), intentional radiators (15.209), or conducted emissions (15.207).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
frequency_mhzYesFrequency in MHz
sectionNoSection to query
device_classNoDevice class

Implementation Reference

  • The handler function `_part15_limit` that executes the fcc_part15_limit tool logic. Looks up FCC Part 15 limits (radiated emissions 15.109, conducted 15.207, intentional radiators 15.209) for a given frequency, device class, and section.
    @staticmethod
    def _part15_limit(arguments: dict[str, Any]) -> list[TextContent]:
        freq_mhz = arguments["frequency_mhz"]
        section = arguments.get("section", "all")
        device_class = arguments.get("device_class", "both")
    
        results = [f"FCC Part 15 Limits at {freq_mhz} MHz\n{'=' * 40}"]
    
        if section in ["15.109", "all"]:
            sec_data = PART15_LIMITS.get("section_15_109", {})
            results.append(f"\n## Section 15.109 - {sec_data.get('title', 'Radiated Emission Limits')}")
    
            if device_class in ["A", "both"]:
                class_a = sec_data.get("class_a", {})
                limit = find_limit_for_frequency(class_a.get("limits", []), freq_mhz)
                if limit:
                    results.append(f"\nClass A ({class_a.get('description', 'Commercial')}):")
                    results.append(format_limit_result(limit))
    
            if device_class in ["B", "both"]:
                class_b = sec_data.get("class_b", {})
                limit = find_limit_for_frequency(class_b.get("limits", []), freq_mhz)
                if limit:
                    results.append(f"\nClass B ({class_b.get('description', 'Residential')}):")
                    results.append(format_limit_result(limit))
    
        if section in ["15.207", "all"] and freq_mhz <= 30:
            sec_data = PART15_LIMITS.get("section_15_207", {})
            results.append(f"\n## Section 15.207 - {sec_data.get('title', 'Conducted Limits')}")
    
            if device_class in ["A", "both"]:
                limit = find_limit_for_frequency(sec_data.get("class_a", {}).get("limits", []), freq_mhz)
                if limit:
                    results.append("\nClass A:")
                    results.append(format_limit_result(limit))
    
            if device_class in ["B", "both"]:
                limit = find_limit_for_frequency(sec_data.get("class_b", {}).get("limits", []), freq_mhz)
                if limit:
                    results.append("\nClass B:")
                    results.append(format_limit_result(limit))
    
        if section in ["15.209", "all"]:
            sec_data = PART15_LIMITS.get("section_15_209", {})
            results.append(f"\n## Section 15.209 - {sec_data.get('title', 'Intentional Radiators')}")
            limit = find_limit_for_frequency(sec_data.get("limits", []), freq_mhz)
            if limit:
                results.append(format_limit_result(limit))
    
        restricted = check_restricted_band(freq_mhz)
        if restricted:
            results.append(f"\n\u26a0\ufe0f  WARNING: {freq_mhz} MHz is in a RESTRICTED BAND (15.205)")
            results.append(f"   {restricted['freq_min_mhz']} - {restricted['freq_max_mhz']} MHz: {restricted['service']}")
    
        return [TextContent(type="text", text="\n".join(results))]
  • Tool registration with input schema for fcc_part15_limit: accepts frequency_mhz (required), section (15.109/15.207/15.209/all), and device_class (A/B/both).
    Tool(
        name="fcc_part15_limit",
        description="Get FCC Part 15 emission limits for a frequency. Returns Class A and/or Class B limits for unintentional radiators (15.109), intentional radiators (15.209), or conducted emissions (15.207).",
        inputSchema={
            "type": "object",
            "properties": {
                "frequency_mhz": {"type": "number", "description": "Frequency in MHz"},
                "section": {"type": "string", "enum": ["15.109", "15.207", "15.209", "all"], "description": "Section to query"},
                "device_class": {"type": "string", "enum": ["A", "B", "both"], "description": "Device class"},
            },
            "required": ["frequency_mhz"],
        },
    ),
  • Routing entry in FCCTools.call_tool that dispatches 'fcc_part15_limit' to _part15_limit handler.
    async def call_tool(self, name: str, arguments: dict[str, Any]) -> list[TextContent]:
        if name == "fcc_part15_limit":
            return self._part15_limit(arguments)
  • FCCTools class (ToolModule subclass) with list_tools that registers fcc_part15_limit. Discovered automatically by ToolRegistry.
    class FCCTools(ToolModule):
        def list_tools(self) -> list[Tool]:
            return [
                Tool(
                    name="fcc_part15_limit",
                    description="Get FCC Part 15 emission limits for a frequency. Returns Class A and/or Class B limits for unintentional radiators (15.109), intentional radiators (15.209), or conducted emissions (15.207).",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "frequency_mhz": {"type": "number", "description": "Frequency in MHz"},
                            "section": {"type": "string", "enum": ["15.109", "15.207", "15.209", "all"], "description": "Section to query"},
                            "device_class": {"type": "string", "enum": ["A", "B", "both"], "description": "Device class"},
                        },
                        "required": ["frequency_mhz"],
                    },
                ),
Behavior4/5

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

No annotations exist, so the description carries full burden. It accurately states it returns limits and specifies which sections and device classes apply. It does not disclose any potential constraints (e.g., frequency range limitations) but for a read-only lookup, the transparency is sufficient.

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

Conciseness5/5

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

The description is a single, well-structured sentence that immediately states the tool's purpose. It is concise at 25 words with no superfluous content.

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

Completeness3/5

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

The tool lacks an output schema, and the description does not explain the return format (e.g., units, structure). While the purpose is clear, the absence of output details leaves some ambiguity for an agent expecting structured data.

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

Parameters3/5

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

Schema coverage is 100% with each parameter described. The description adds overarching context linking sections to emission types (unintentional radiators, intentional radiators, conducted emissions) but does not provide additional detail beyond the schema's enum descriptions. Baseline 3 is appropriate.

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 specifies the tool retrieves FCC Part 15 emission limits for a given frequency. It names the exact regulation sections (15.109, 15.207, 15.209) and device classes (Class A/B), making its purpose distinct from sibling tools like cispr12_limit or fcc_part18_limit.

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 implies usage for FCC Part 15 limit queries by naming sections and classes. While it does not explicitly list when not to use it or mention alternatives, the context is clear enough for an AI agent to discern if FCC Part 15 limits are needed.

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/RFingAdam/mcp-emc-regulations'

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