@@ -310,31 +310,40 @@ async def test_write_note_accepts_directory_aliases(mcp_server, app, test_projec
310310
311311
312312@pytest .mark .asyncio
313- async def test_write_note_accepts_overwrite_aliases (mcp_server , app , test_project ):
314- """`force`/`replace` should map to `overwrite` ."""
313+ async def test_write_note_overwrite_canonical_via_mcp (mcp_server , app , test_project ):
314+ """Canonical overwrite=True must reach the handler (#818 regression) ."""
315315 async with Client (mcp_server ) as client :
316- # First create
317316 await client .call_tool (
318317 "write_note" ,
319318 {
320319 "project" : test_project .name ,
321- "title" : "Overwrite Alias Note" ,
320+ "title" : "Overwrite Canonical Note" ,
322321 "directory" : "overwrite-test" ,
323322 "content" : "v1" ,
324323 },
325324 )
326- # Overwrite using `force` alias
325+ blocked = await client .call_tool (
326+ "write_note" ,
327+ {
328+ "project" : test_project .name ,
329+ "title" : "Overwrite Canonical Note" ,
330+ "directory" : "overwrite-test" ,
331+ "content" : "v2" ,
332+ },
333+ )
334+ assert "# Error: Note already exists" in blocked .content [0 ].text
335+
327336 result = await client .call_tool (
328337 "write_note" ,
329338 {
330339 "project" : test_project .name ,
331- "title" : "Overwrite Alias Note" ,
340+ "title" : "Overwrite Canonical Note" ,
332341 "directory" : "overwrite-test" ,
333342 "content" : "v2" ,
334- "force " : True , # alias for overwrite
343+ "overwrite " : True ,
335344 },
336345 )
337- assert "Updated note" in result . content [ 0 ]. text or "Created note" in result .content [0 ].text
346+ assert "# Updated note" in result .content [0 ].text
338347
339348
340349# --- move_note aliases ---
@@ -538,3 +547,19 @@ async def test_aliases_not_advertised_in_schema(mcp_server, app):
538547 assert canonical in props , f"{ tool_name } : canonical '{ canonical } ' missing"
539548 for alias in must_not_have :
540549 assert alias not in props , f"{ tool_name } : alias '{ alias } ' leaked into schema"
550+
551+ # #818: AliasChoices on optional bool broke external-client JSON schema (null-only).
552+ overwrite_schema = tools ["write_note" ].inputSchema ["properties" ]["overwrite" ]
553+ schema_types : set [str ] = set ()
554+ if "type" in overwrite_schema :
555+ raw = overwrite_schema ["type" ]
556+ if isinstance (raw , str ):
557+ schema_types .add (raw )
558+ else :
559+ schema_types .update (raw )
560+ for option in overwrite_schema .get ("anyOf" , ()):
561+ if "type" in option :
562+ schema_types .add (option ["type" ])
563+ assert "boolean" in schema_types , (
564+ f"write_note overwrite must expose boolean in schema, got { overwrite_schema } "
565+ )
0 commit comments