@@ -46,3 +46,57 @@ async def test_read_note_after_write(mcp_server, app, test_project):
4646 assert "# Test Note" in result_text
4747 assert "This is test content." in result_text
4848 assert "test/test-note" in result_text # permalink
49+
50+
51+ @pytest .mark .asyncio
52+ async def test_read_note_underscored_folder_by_permalink (mcp_server , app , test_project ):
53+ """Test read_note with permalink from underscored folder.
54+
55+ Reproduces bug #416: read_note fails to find notes when given permalinks
56+ from underscored folder names (e.g., _archive/, _drafts/), even though
57+ the permalink is copied directly from the note's YAML frontmatter.
58+ """
59+
60+ async with Client (mcp_server ) as client :
61+ # Create a note in an underscored folder
62+ write_result = await client .call_tool (
63+ "write_note" ,
64+ {
65+ "project" : test_project .name ,
66+ "title" : "Example Note" ,
67+ "folder" : "_archive/articles" ,
68+ "content" : "# Example Note\n \n This is a test note in an underscored folder." ,
69+ "tags" : "test,archive" ,
70+ },
71+ )
72+
73+ assert len (write_result .content ) == 1
74+ assert write_result .content [0 ].type == "text"
75+ write_text = write_result .content [0 ].text
76+
77+ # Verify the file path includes the underscore
78+ assert "_archive/articles/Example Note.md" in write_text
79+
80+ # Verify the permalink has underscores stripped (this is the expected behavior)
81+ assert "archive/articles/example-note" in write_text
82+
83+ # Now try to read the note using the permalink (without underscores)
84+ # This is the exact scenario from the bug report - using the permalink
85+ # that was generated in the YAML frontmatter
86+ read_result = await client .call_tool (
87+ "read_note" ,
88+ {
89+ "project" : test_project .name ,
90+ "identifier" : "archive/articles/example-note" , # permalink without underscores
91+ },
92+ )
93+
94+ # This should succeed - the note should be found by its permalink
95+ assert len (read_result .content ) == 1
96+ assert read_result .content [0 ].type == "text"
97+ result_text = read_result .content [0 ].text
98+
99+ # Should contain the note content
100+ assert "# Example Note" in result_text
101+ assert "This is a test note in an underscored folder." in result_text
102+ assert "archive/articles/example-note" in result_text # permalink
0 commit comments