Fix create_block and update_block content parameter type mismatch #26
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/pal-e-mcp#26
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Lineage
todo-mcp-block-content-type— discovered during Epilogue item 9 workRepo
forgejo_admin/pal-e-docs-mcpUser Story
As an agent using block tools
I want
create_blockandupdate_blockto accept structured contentSo that I can create and edit blocks without falling back to curl
Context
The
contentparameter oncreate_blockandupdate_blockMCP tools is typed asstrin the Pydantic schema. The pal-e-docs REST API expectscontentas a JSON dict:{"level": 4, "text": "..."}{"html": "..."}{"ordered": false, "items": [...]}{"headers": [...], "rows": [...]}This creates a catch-22 — dict input is rejected by the tool ("Input should be a valid string"), string input is rejected by the API ("Input should be a valid dictionary"). Agents must use curl as a workaround.
File Targets
Files the agent should modify:
create_blockandupdate_block— changecontentparam type fromstrtodictFiles the agent should NOT touch:
Acceptance Criteria
create_blockaccepts a dict forcontentand forwards it correctly to the APIupdate_blockaccepts a dict forcontentand forwards it correctly to the API{"level": 4, "text": "Test"}works via MCP{"html": "test"}works via MCPTest Expectations
create_blockvia MCP with dict content, verify block createdupdate_blockvia MCP with dict content, verify block updatedpytest tests/ -v(if tests exist)Constraints
Checklist
Related
todo-mcp-block-content-type— tracking TODOPR #27 Review
BLOCKERS
None.
NITS
pytestimported inside test methods --TestParseContent.test_invalid_json_raises_value_error,test_json_array_raises_value_error, andtest_json_scalar_raises_value_erroreach doimport pytestinside the method body. The module already hasfrom __future__ import annotationsat the top; addingimport pytestalongside the other top-level imports would be cleaner and consistent with the rest of the test file (which usesmock_sdkfixture without local imports). Non-blocking since it works fine either way.Truncated branch name -- Branch is
26-fix-create-block-and-update-block-conten(missing trailing 't'). Likely auto-generated by Forgejo from the issue title. No action needed, just noting it.SOP COMPLIANCE
26-...)todo-mcp-block-content-type) and issue #26CODE REVIEW
_parse_contenthelper -- Correct implementation. Handles all three input types cleanly:Noneanddictpass through immediately (line 39)json.loadswith proper error handling for bothJSONDecodeError/TypeError(invalid JSON) and non-dict parsed results (arrays, scalars)ValueErrormessages with the specific type or parse errorIntegration into
create_blockandupdate_block-- Both tools call_parse_content(content)inside theirtryblock, before the SDK call. TheValueErrorraised by_parse_contentis caught by the broadexcept Exceptionhandler and formatted via_error_response, which correctly produces{"error": true, "detail": "..."}for non-PalEDocsErrorexceptions. This means invalid content returns a user-friendly error without crashing._CONTENT_DESCfield description -- Documents all 5 content shapes (heading, paragraph, list, table, code) with example JSON structures. Uses JSON-stylefalsein the description, which is correct since the description shows JSON object shapes to LLM consumers.conftest.pychange -- Correctly patchesget_sdkin the blocks module namespace, matching the existing pattern for notes, sprints, and links modules.Test coverage -- Thorough:
_parse_content(None, dict identity, valid JSON string, invalid JSON, JSON array, JSON scalar)create_blockandupdate_block(dict forwarded, JSON string parsed, None forwarded, invalid JSON returns error)ValueErrorraise (unit) and the_error_responseformatting (integration)Type annotation -- The
# type: ignore[return-value]on line 40 is justified; it suppresses a mypy narrowing limitation whereisinstance(content, dict)narrows todictbut notdict[str, Any].No security concerns. No scope creep. Clean fix.
VERDICT: APPROVED