From ef80f9eab08a07a80e8f72033ca86aad07aa281e Mon Sep 17 00:00:00 2001 From: Ryan Malloy Date: Fri, 30 Jan 2026 12:01:17 -0700 Subject: [PATCH] Fix lock_device: refuse when elicitation unavailable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lock_device shared the confirm_write() fallback which returns True when the client doesn't support elicitation. This meant lock could proceed silently without user consent — confirmed by accidentally locking a real device. Now lock_device has its own strict path that returns an error when elicitation fails, rather than falling through. --- src/cp210x_mcp/server.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/cp210x_mcp/server.py b/src/cp210x_mcp/server.py index fde8c47..56ea56b 100644 --- a/src/cp210x_mcp/server.py +++ b/src/cp210x_mcp/server.py @@ -325,15 +325,24 @@ async def lock_device(device_index: int = 0, ctx: Context = None) -> dict: f"will be frozen forever." ) - if ctx: - confirmed = await confirm_write(ctx, info) - else: - # No context = no way to confirm, refuse + if not ctx: return { "error": "Lock requires interactive confirmation", "message": "This operation is too dangerous without user confirmation.", } + # Strict confirmation — do NOT fall back to True on failure. + # Unlike regular writes, an irreversible lock must get explicit consent. + try: + result = await ctx.elicit(info, ["Confirm", "Cancel"]) + confirmed = isinstance(result, AcceptedElicitation) and result.data == "Confirm" + except Exception: + return { + "error": "Lock requires elicitation support", + "message": "Your MCP client does not support elicitation. " + "Lock is too dangerous to proceed without explicit confirmation.", + } + if not confirmed: return {"cancelled": True, "message": "Lock cancelled by user"}