Skip to content

9.5 The MCP Protocol: A Bridge Between AI and IoT

9.5.1 Background and Core Design of the MCP Protocol

The communication models of MQTT, CoAP, LwM2M, and OPC UA are essentially static: the platform defines the rules, data flows along topics or resource paths, and state changes are triggered by the device or the platform side. When AI applications operate these devices, the problem they face is no longer unreachable data, but three deeper gaps.

The semantic gap. MQTT publishes to a topic such as topic/dev/001/temp with a payload of 26.8. The AI can receive this value, but it cannot tell whether it is Celsius or Fahrenheit, an instantaneous value or a five-minute average, a normal range or an anomaly alarm. CoAP's path structure is somewhat more standardized, but the meaning of the fields still depends on the thing-model mapping on the platform side. What an AI system needs is not only a data stream but also a meta-description of device capabilities: which parameters are readable, which are writable, what constraints a write operation carries, and how return values should be interpreted.

Missing security boundaries and context. An AI application that subscribes to device topics directly through an MQTT client either gains too many privileges (it can read other tenants' devices) or lacks the context for control operations (it does not know whether the target device is in an operable state). An MQTT broker does not maintain session state, authorization context, or a call chain for an AI conversation. Processing one question usually requires multi-step reasoning that touches multiple devices or data sources, and every call must carry the security context already established.

Asymmetric state management. Device communication protocols are mostly event-driven or polling models: the device reports, and the platform consumes. An AI Agent's task, however, usually spans multiple steps: it first understands the current state, then decides the next action, and finally confirms the result. MQTT's publish–subscribe model is not well suited to query–response patterns; CoAP's request–response model is closer, but it has no unified mechanism for tool discovery and parameter description. AI needs an interaction protocol with discoverable capability boundaries. Task state, conversational memory, and approval progress must be maintained by the Host, Agent Runtime, or business system, rather than assuming that the base protocol stores this state for the application.

MCP (Model Context Protocol) emerged against exactly this background. It is not a device protocol; it is a context-exchange protocol for interactions between AI applications and external tools, resources, and knowledge bases.

Before going further, it helps to separate two kinds of statements. Facts about the IoT DC3 implementation are tied to source snapshot 987c96d50 dated August 29, 2026. The application and value boundaries of this class of protocols in IoT are the author's engineering judgment, not a final definition of the formal standard, and some details are illustrative. After a version upgrade, the endpoint, protocol revision, declared capabilities, and authorization path must be checked again.

MCP's context model and communication model

MCP abstracts interaction between AI and external systems as discoverable capabilities and structured requests. The specification defines three core capability categories — resources, tools, and prompts — but a particular server may implement only a subset:

  • Resources: readable context exposed by the server for a Host or Client to include in model context as needed. Resources are identified by URI and may carry a MIME type; the specification also provides resource templates, list pagination, and optional subscriptions. That is not the same as HTTP content negotiation or arbitrary byte-range reads.
  • Tools: executable actions that can be triggered by a model request. Each tool declares an input schema describing parameter names, types, constraints, and whether they are required. The AI model proposes a call, while the MCP Server still has to enforce authorization, parameter validation, risk controls, and auditing. In this IoT DC3 source snapshot, the server declares only the Tools capability. It combines the platform catalog in dc3_api and dc3_resource with versioned static openapi-*.json snapshots, then trims the resulting tool definitions by OAuth scope, tenant, permission, and risk policy. This is not unbounded runtime crawling of every center's OpenAPI, nor does it imply that Resources or Prompts are implemented.
  • Prompts: reusable, parameterized prompt templates that let the server guide the model on "how to understand this domain's resources."

IoT DC3's MCP endpoint exchanges messages over JSON-RPC 2.0. This source snapshot implements the 2025-06-18 initialization handshake and handles initialize, notifications/initialized, ping, tools/list, and tools/call. The Gateway exposes POST /mcp and introspects the Bearer Token on every request. The current code does not declare Resources, Prompts, or Tasks. A JSON-RPC request ID only correlates a request with its response, and initialization state does not mean that the server stores a conversational session. Cross-call task state, timeout compensation, and approval records must still reside in the Agent Runtime or business storage. Authentication also depends on the transport and deployment model. OAuth 2.1 is the authorization foundation here and, as of August 2026, remains an IETF draft rather than a published RFC.

Figure 9-9 shows a typical MCP interaction sequence in an IoT scenario, covering initialization, Tool-catalog discovery, Tool invocation, and state feedback.

Figure 9-9 MCP Interaction SequenceThe AI Agent discovers and calls IoT platform capabilities scoped by identity, tenant, and risk policy through the MCP Server; the platform then reaches devices over the existing protocol path and returns results.Figure 9-9 MCP Interaction SequenceMCP is the interop layer between AI and the IoT platform: it bypasses neither platform governance nor the MQTT / CoAP device protocolsIdentity + tenant scopingAuth · whitelist · parameter checksRisk tiers · human approval when neededinitialize · capability negotiationinitialize response · version & capabilitiestools/listTool list · JSON Schematools/call · tool + parametersPlatform service call (REST)Deliver via existing path · MQTT / CoAPAction commandResponse / telemetryResult callbackStatus + data + audit trailtools/call responseInitialization & discoveryGoverned tool callDevice response & audit returnAI application domainIoT platform security domainDevice communication domainAI AgentClaude Desktop etc.MCP ServerProtocol · policy · tool routingIoT platform backendDevice / data servicesProtocol adaptation layerMQTT / CoAP gatewayPhysical deviceSensors / actuatorsSolid: governed calls & responsesGreen: device response returnOrange box: security decision pointDashed domain boundary: neither AI nor devices bypass the platform security domainFigure 9-9 MCP interaction sequence: the AI Agent discovers and invokes policy-scoped platform Tools through the MCP Server, while the IoT platform retains control of the device path.
Figure 9-9 MCP Interaction Sequence

This design differs from MQTT's Topic-based publish/subscribe model. In the 2025-06-18 lifecycle implemented by IoT DC3, MCP completes initialization and capability negotiation, then discovers and invokes capabilities through structured requests. The server trims the Tool catalog using identity, tenant, and policy context revalidated on each request. Such protocol-handshake state is not business conversation or task state; cross-call state still belongs to the Host, Agent Runtime, or business storage. The July 28, 2026 release candidate proposes a stateless lifecycle without initialize, carrying protocol metadata in requests; that proposal must not be projected backward onto this source snapshot.

The division of labor between MCP and the IoT platform

In IoT DC3, the MCP entry point sits in the Gateway, the Tool catalog and policy are managed through Auth Center capabilities, and execution is routed to the selected platform-center API. It is a platform adaptation entry point, not a replacement for device-side protocols. In this source snapshot, the call chain is:

  • An AI Agent, such as Claude Desktop or a custom Agent, completes initialization and obtains through tools/list the Tool catalog visible to the current Bearer Token, tenant, and permission context.
  • The MCP Gateway derives candidate tools from the API/resource catalog and versioned OpenAPI snapshots, then applies scope, tenant, permission, and risk filtering before returning them. On tools/call, it revalidates visibility and authorization instead of trusting the previously returned catalog alone.
  • When the Agent invokes a "read device point" tool, the Gateway reads data or triggers the existing command path through a controlled platform-center API. It neither sends CoAP directly to the device nor publishes directly to a device Topic.

This design ensures that MCP does not bypass the existing IoT security governance. The device-side protocols remain MQTT, CoAP, OPC UA, or Modbus. What MCP adds is an interoperability layer between AI and the platform, not a reinvention of device communication protocols.

Pitfalls to avoid in engineering practice

In practice, teams are tempted to treat MCP as a shortcut for "letting AI connect directly to devices." The most typical design mistake is an MCP Server that maintains its own MQTT connection pool and publishes directly to device topics whenever the agent invokes a tool. Such an architecture bypasses the platform layer's policy engine, service degradation, tenant isolation, and interlocking logic, and hands the duties of two-factor confirmation, write-rate limiting, and operation audit over to the AI prompt. An AI model is not a deterministic real-time control system; any call chain that bypasses platform governance should be treated as a security violation.

The sounder judgment is this: the correct place for MCP in IoT is the interoperability layer between AI applications and the IoT platform. It answers "how does AI discover and invoke platform capabilities through a unified protocol," not "how does AI replace MQTT/CoAP and take over device communication." The platform still receives telemetry over MQTT, manages devices over CoAP, and carries industrial semantics over OPC UA; MCP only adds an AI-facing tool abstraction that lets the model operate policy-trimmed platform capabilities inside a security context. These two stacks should never be short-circuited directly, unless the architect is willing to accept open-loop control risk.

Further reading: Chapter 7, Section 7.3, covers the Tool catalog, platform conversation state, and security policy in the IoT DC3 Agentic Center. MCP protocol-handshake state is not platform conversation state, nor does it preserve business tasks for the application. Chapter 8, Section 8.5.4, discusses the security boundaries and auditing scheme for AI Agents operating devices.

9.5.2 MCP Message Format and Capability Description

MCP uses JSON-RPC 2.0 as its message carrier. The choice does not minimize payload size; it lowers the entry barrier for AI applications because languages with JSON serialization can process the messages directly. The published 2025-11-25 specification defines stdio and Streamable HTTP, with Streamable HTTP replacing the earlier HTTP+SSE transport. The IoT DC3 source snapshot contains one POST /mcp endpoint that handles JSON-RPC. What can be confirmed is therefore an HTTP POST MCP endpoint; its path alone does not prove implementation of every Streamable HTTP GET, SSE, and session semantic. Experimental Tasks appeared in the 2025-11-25 specification, but this snapshot does not implement them. The 2026-07-28 document is a release candidate proposing changes such as a stateless lifecycle, not a stable implementation baseline. Chapter 7, Section 7.1.5 discusses these mechanisms from the standpoint of IoT DC3's implementation boundary; this section focuses on protocol layers and version boundaries. MCP does not define device-side envelopes, frame headers, or payload formats. It addresses how an AI application discovers and invokes external capabilities and how those capabilities describe themselves.

Standard Message Model and Capability Negotiation

This section first describes the 2025-06-18 lifecycle implemented by IoT DC3; the published 2025-11-25 specification also retains this handshake. The Client first sends initialize with its protocol revision and capabilities. The Server returns the selected revision, capabilities, and implementation information, after which the Client sends notifications/initialized. Subsequent operations must conform to the negotiated result. Initialization state constrains protocol interaction; it does not mean that the Server stores business conversations, approvals, or long-running task state. A client targeting the July 28, 2026 release candidate must instead follow its stateless lifecycle rather than mixing the two flows.

An initialize request looks like this:

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-06-18",
    "capabilities": {},
    "clientInfo": {
      "name": "iot-supervisor-agent",
      "version": "1.0.0"
    }
  }
}

This example uses 2025-06-18, the revision declared by the IoT DC3 source snapshot. A Client should send a revision it supports and handle the version selected by the Server, rather than using an ambiguous value such as v1. Capability negotiation is not an authorization credential. Authentication, authorization, and capabilities should be revalidated for a new connection or interaction context. The Server may have changed its Tools or resource paths, and a Client should not reuse a stale catalog indefinitely across contexts.

The specification allows a Server to declare the capabilities it actually supports. Common categories include:

  • tools: actions the model may invoke; each must declare a name, a description, and JSON Schema input parameters.
  • resources: context resources read by the client (device descriptions, historical summaries, documentation), supporting URI pattern matching.
  • prompts: discoverable, parameterizable prompt templates used to steer model behavior.

A server need not support all three categories. This IoT DC3 snapshot declares only tools, so a client cannot infer from the general specification that resources/list or prompts/list is available.

JSON Schema is explicitly used for Tool input parameters. Resources are described through fields such as URIs, content, and templates, while Prompts have their own parameter and message structures; the three capability categories therefore must not be described as sharing one JSON Schema format. MCP does not define device-domain semantics for the platform. A Tool description for reading a device point looks like this:

json
{
  "name": "iot_read_point",
  "description": "Read the device points the current user has permission to access",
  "inputSchema": {
    "type": "object",
    "properties": {
      "deviceId": {"type": "string", "description": "Device identifier"},
      "pointId":  {"type": "string", "description": "Point identifier"}
    },
    "required": ["deviceId", "pointId"]
  }
}

The inputSchema here defines the invocation parameters of an MCP tool — not a device register mapping or a unified CoAP resource format. How the MCP server internally routes these parameters to the IoT platform's actual protocol driver is completely transparent to the AI application. The caller cares only about the name and the arguments, not whether the target device is reached over MQTT or Modbus.

The AI agent sends the actual operation request through the tools/call method:

json
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "iot_read_point",
    "arguments": {
      "deviceId": "pump-001",
      "pointId": "motor_temp"
    }
  }
}

The server returns the result:

json
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [{"type": "text", "text": "motor_temp = 68.5°C"}],
    "isError": false
  }
}

Along the entire call chain, the server is responsible for verifying user permissions, tenant boundaries, and data masking; the model never touches raw point values. MCP's "capability description" is in essence the interface contract of a security proxy, not the device's own feature list. This point matters especially to architects: if you want the model to manipulate device registers directly, that is a dangerous design that bypasses platform governance, and it should not be implemented through MCP.

The Responsibility Boundary of Capability Description: Differences from WoT TD

Device attributes, events, commands, data types, units, and protocol bindings should remain the responsibility of the thing model, LwM2M objects, the OPC UA information model, or the W3C Web of Things Thing Description. An MCP server can adapt these models to generate tools or resources, but that adaptation is not part of the MCP standard — MCP specifies only the description format of tools; it does not specify the measurement unit, enumeration range, or lifecycle of a "temperature attribute."

Take WoT TD as an example: the TD of a lighting device describes the brightness property, the setBrightness action, and its parameter constraints. An MCP server can generate a set_brightness tool from that TD, but it must additionally supply three things:

  1. User permissions — whether the current principal is authorized to invoke the action.
  2. Action risk level — whether the parameter-write operation requires a second confirmation.
  3. Idempotency policy — whether repeated invocation is safe.

The adaptation chain is as follows:

Device model / WoT TD / OPC UA information model
        ↓ adaptation and permission trimming
MCP tools / resources

AI applications discover, interpret, and invoke

The JSON fields of a WoT TD cannot be used directly as MCP "capability description" fields. MCP cares only about the semantics of the calling interface; it does not define the units, enumerations, or lifecycle of device attributes. This is consistent with the layered semantic model discussed in Section 9.6.2 of this chapter: the bottom layer is the device standard model, the middle layer is the platform's internal adaptation, and the top layer is the interface discovered on the AI side.

The Complementary Relationship Between A2A and MCP

MCP solves the connection between AI applications and tools/resources. A2A solves discovery, task delegation, and result exchange between agents. The division of labor is clear: an orchestrating agent can delegate a "diagnose pump anomaly" task to a diagnostic agent through A2A, and the latter then queries device status and history through MCP.

Identity authentication, authorization, and user consent must not be bypassed by MCP or A2A. Every tool call must still verify the principal, the tenant, the action, and the parameters. Tool descriptions themselves are untrusted input — clients should restrict server sources and review changes to tool names and schemas, to keep malicious descriptions from inducing the model to leak context or invoke unauthorized capabilities. This aligns with the security checklist in Section 9.7.2 of this chapter: the protocol itself is not responsible for trust; trust is enforced by the platform layer's authorization and governance.

Boundary Judgments in Protocol Design

If a project needs a protocol for device registration, capability-catalog synchronization, or action execution, it can be designed as a platform-internal "device semantic adaptation protocol," defined independently of MCP. Such a protocol can run over MQTT, CoAP, or a message queue, but the following points must be made explicit:

  • Message fields, registration flows, and error codes are custom content.
  • Its relationship to MCP is adaptation or bridging, not part of the MCP specification.
  • All hypothetical fields and example parameters should be labeled as such, so that readers do not mistake them for standardized definitions.

Real-time telemetry, device shadow synchronization, and safety control should prefer the IoT platform's existing data plane and control plane. MCP serves only as the capability-discovery and invocation entry point on the AI application side; it does not replace the device-side protocol stack. This boundary judgment is the engineering baseline an IoT architect must hold when introducing an AI interaction layer.

Figure 9-10 MCP Message Model and Capability BoundaryMCP rides on JSON-RPC 2.0; after initialize negotiation it exposes tools/resources/prompts — capability descriptions are the interface contract for secure proxying.Figure 9-10 MCP Message Model and Capability BoundaryMCP solves one problem: how AI apps discover and invoke external capabilitiesMCP Client(AI Agent)Sends protocol version and capabilitiesNo stale lists reused across sessionsMCP ServerReturns version + capabilities + extensionsRe-validated at every new sessioninitialize request (JSON-RPC 2.0)Response: protocolVersion + capabilitiesThree core capabilities declared by the servertoolsActions the model can callDeclares name, description, JSON Schema inputse.g. iot_read_point(deviceId, pointId)resourcesContext resources read by the clientDevice docs, history summaries, documentsSupports URI pattern matchingpromptsDiscoverable, parameterizable prompt templatesUsed to steer model behaviorCapability descriptions follow JSON SchemaResponsibility boundary: MCP and WoT TD each cover their partWoT TD / OPC UA / LwM2M objects own properties, events, commands, data types, units, protocol bindingsThe MCP server derives tools/resources from those models but must add three things:① user permission (is the principal authorized) ② action risk level (does a write need confirmation) ③ idempotency policy (is a repeat call safe)Tool descriptions are untrusted input: restrict server sources, review tool names and schema changes to prevent leaks or privilege escalationMCP only defines the tools description format — not the unit, enum range, or lifecycle of "temperature"Figure 9-10 MCP rides on JSON-RPC 2.0 and, after initialize negotiation, exposes three capability types — tools/resources/prompts; a capability description is essentially the interface contract for secure proxying, with permissions, risk levels, and idempotency policy supplied by the platform layer.
Figure 9-10 MCP Message Model and Capability Boundary

9.5.3 An MCP Engineering Prototype: AI-Controlled Lighting

Sections 9.5.1 and 9.5.2 covered MCP's design motivation and message format; this section strings them together through one complete scenario, showing how MCP (Model Context Protocol) links AI applications to the control chain of IoT devices.

Scenario: the user says to an AI voice assistant, "Set the bedroom light to warm yellow, brightness sixty percent." After natural-language parsing, tool discovery, parameter mapping, remote invocation, and state synchronization, the AI agent takes control of the smart light. Throughout the interaction, the AI agent never communicates with the device or the MQTT broker directly — it interacts only with the MCP Server; the MCP Server translates the tool call into the IoT platform's REST interface, and the platform issues the command over MQTT.

Device Registration and Capability Exposure

In this teaching prototype, the smart light declares set_light (set brightness and color) and get_status (query current state) when it registers with the IoT platform, and the adaptation layer maps controlled platform APIs into MCP Tools. This illustrates the layering relationship rather than reproducing IoT DC3's current Tool aggregator line for line. After initialize and notifications/initialized complete, the Client sends a separate tools/list request and the Server returns the visible Tools. The following is a simplified response fragment:

json
{
  "tools": [
    {
      "name": "iot_get_device_status",
      "description": "Query the device's current state, including brightness and color",
      "inputSchema": {
        "type": "object",
        "properties": {
          "deviceId": {"type": "string", "description": "Device ID"}
        },
        "required": ["deviceId"]
      }
    },
    {
      "name": "iot_set_light",
      "description": "Set lamp brightness (0-100) and color (supports 'cool white', 'natural white', 'warm yellow', 'warm white')",
      "inputSchema": {
        "type": "object",
        "properties": {
          "deviceId": {"type": "string"},
          "brightness": {"type": "integer", "minimum": 0, "maximum": 100},
          "color": {"type": "string", "enum": ["cool white", "natural white", "warm yellow", "warm white"]}
        },
        "required": ["deviceId", "brightness"]
      }
    }
  ]
}

AI Parsing and Tool Invocation

The AI agent parses the user's speech into a tool-call intent. This process usually involves named-entity recognition ("bedroom light" → device ID light-bedroom-01), parameter extraction ("sixty" → 60, "warm yellow" → the corresponding color enum value), and tool matching (selecting iot_set_light). The agent then constructs a tools/call request:

json
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "iot_set_light",
    "arguments": {
      "deviceId": "light-bedroom-01",
      "brightness": 60,
      "color": "warm yellow"
    }
  }
}

When the MCP Server receives the request, it calls the IoT platform API through internal handlers, and the platform performs the real operation through its existing command path. The Python code below simulates the message flow from Agent to Server to platform and device. It omits the HTTP transport wrapper, MCP initialization handshake, request authentication, and external task state, focusing only on core message handling and state changes. The request_context in the code is illustrative business authorization context, not a conversational session stored by the MCP Server:

python
import json
import time
from dataclasses import dataclass, field

# ---------- Device abstraction in the simulated IoT platform ----------
@dataclass
class LightDevice:
    device_id: str
    brightness: int = 0
    color: str = "cool white"
    online: bool = True

    def set_light(self, brightness: int, color: str) -> bool:
        if not self.online:
            raise RuntimeError("device offline")
        if not (0 <= brightness <= 100):
            raise ValueError("brightness out of range")
        if color not in ["cool white", "natural white", "warm yellow", "warm white"]:
            raise ValueError("unsupported color")
        self.brightness = brightness
        self.color = color
        return True

# ---------- Simulated MCP Server ----------
class MCPToolServer:
    def __init__(self, platform):
        self.platform = platform
        self.tools = {
            "iot_get_device_status": {"handler": self.handle_get_status},
            "iot_set_light": {"handler": self.handle_set_light}
        }

    def handle_get_status(self, request_context, args):
        device = self.platform.get_device(args["deviceId"])
        if device is None:
            return {"error": "device not found"}
        return {
            "brightness": device.brightness,
            "color": device.color,
            "online": device.online
        }

    def handle_set_light(self, request_context, args):
        device = self.platform.get_device(args["deviceId"])
        if device is None:
            return {"error": "device not found"}
        try:
            device.set_light(args.get("brightness"), args.get("color", "cool white"))
            # The platform issues the real command over MQTT
            mqtt_publish(device.device_id, device.brightness, device.color)
            return {
                "success": True,
                "state": {
                    "brightness": device.brightness,
                    "color": device.color
                }
            }
        except (ValueError, RuntimeError) as e:
            return {"error": str(e)}

# ---------- Simulated MQTT publish ----------
def mqtt_publish(device_id, brightness, color):
    print(f"[MQTT] Command issued: {device_id} brightness={brightness} color={color}")

# ---------- Simulated IoT platform ----------
class IoTPlatform:
    def __init__(self):
        self.devices = {}
    def register_device(self, device: LightDevice):
        self.devices[device.device_id] = device
    def get_device(self, device_id):
        return self.devices.get(device_id)

# ---------- Simulated AI Agent (MCP Client) ----------
class AIAgent:
    def __init__(self, mcp_server: MCPToolServer):
        self.server = mcp_server
        self.request_context = {"user": "admin"}

    def parse_intent(self, text: str):
        """Simplified intent parsing, for demonstration only"""
        if "bedroom light" in text and "brightness" in text:
            brightness = 60 if ("sixty" in text or "60" in text) else 50
            color = "warm yellow" if "warm yellow" in text else "cool white"
            return "iot_set_light", {
                "deviceId": "light-bedroom-01",
                "brightness": brightness,
                "color": color
            }
        return None, None

    def execute_intent(self, tool_name, args):
        if tool_name not in self.server.tools:
            print("Tool not found")
            return
        result = self.server.tools[tool_name]["handler"](self.request_context, args)
        print(f"[AI Agent] Execution result: {result}")
        return result

# ---------- Main flow ----------
def main():
    platform = IoTPlatform()
    device = LightDevice(
        device_id="light-bedroom-01",
        brightness=50,
        color="cool white",
        online=True
    )
    platform.register_device(device)

    mcp_server = MCPToolServer(platform)
    agent = AIAgent(mcp_server)

    user_voice = "Turn the bedroom light to warm yellow, brightness sixty percent"
    tool_name, args = agent.parse_intent(user_voice)
    if not tool_name:
        print("Unable to parse intent")
        return

    print(f"[Parse result] Tool: {tool_name}, Args: {args}")
    result = agent.execute_intent(tool_name, args)
    time.sleep(0.1)
    print(f"[Final state] brightness={device.brightness}, color={device.color}")

if __name__ == "__main__":
    main()

Program output

[Parse result] Tool: iot_set_light, Args: {'deviceId': 'light-bedroom-01', 'brightness': 60, 'color': 'warm yellow'}
[MQTT] Command issued: light-bedroom-01 brightness=60 color=warm yellow
[AI Agent] Execution result: {'success': True, 'state': {'brightness': 60, 'color': 'warm yellow'}}
[Final state] brightness=60, color=warm yellow

Exception Handling and Engineering Boundaries

In real deployments, the MCP Server must handle the following exception scenarios, returning structured error messages instead of crashing outright:

  • Device offline: the platform detects that the device is unreachable and returns {"error": "device offline"}.
  • Parameter out of range: the server validates and returns {"error": "brightness out of range"}.
  • Insufficient permissions: the user in the current request context has no right to control the device; the Server should refuse the call and write an audit log.
  • Timeout and retry: if no device acknowledgment arrives after the platform issues a command, decide whether to query state, compensate, or retry a limited number of times according to the action's semantics. A business wrapper may add idempotencyKey, but it is not a standard field in the core MCP tools/call; both parties must define it explicitly in the Tool's input contract.

The core layering logic of this engineering pattern is that the AI agent never touches the device chain. Device registration, capability description, command execution, and state synchronization are still performed by the IoT platform and its existing protocols (such as MQTT); the MCP Server only performs translation and control duties between AI and the platform. This layering provides well-defined enforcement points for security audit, permission control, and tool version management, and it greatly reduces the awareness cost of device-side protocols when AI applications are integrated.

Figure 9-11 MCP Prototype: Governed AI Light ControlThe AI Agent never talks to the device directly; after the MCP Server validates permissions and parameters, the IoT platform sends the MQTT command to the smart light.Figure 9-11 MCP Prototype: Governed AI Light ControlNo direct device access · permissions, validation, and auditing land in the server and platform layersAI Agent(MCP Client)Parse speech: "bedroom light → warm yellow → 60%"Named entity recognition + parameter extractionTool match: iot_set_lightTalks only to the MCP ServerMCP Servertools/call parsing & dispatchPermission check (is the session user authorized)Parameter bounds check (0~100, color enum)Log an audit record on rejectionIoT platform (REST → MQTT)REST endpoint receives the tool callPlatform-side device state managementReal command delivered over MQTTRegistration, capabilities, and state stay with the platformSmart light (light-bedroom-01)Receives the MQTT command, updates brightness and colorReports: brightness=60, color=warm yellowCapabilities: set_light / get_statusThe device side stays MQTT — no MCP involvedExceptions and engineering edges the server must handleDevice offline / parameter out of rangeReturn a structured error: device offlinebrightness out of rangeInsufficient permissionThe session user may not control this deviceReject the call and log an audit recordTimeout and retryOn MQTT timeout, retry or roll back statetools/call supports idempotency keys to prevent double executionCore layeringDevice registration, capability description, command execution, and state sync stay on the IoT platform and MQTT; the MCP Server only converts and governs between AI and platformThis gives audit, access control, and tool versioning a clear enforcement point, lowering the protocol burden of AI integrationFigure 9-11 The AI Agent does not touch devices directly: tool discovery, permission checks, and parameter validation happen in the MCP Server, and the IoT platform delivers the actual command to the smart light over MQTT; failure paths return structured errors and keep an audit trail.
Figure 9-11 MCP Prototype: Governed AI Light Control

From Industrial Software to AI Agents · Building a multi-protocol, cloud-native, open-source industrial IoT platform ready to evolve toward AI agents