Repository navigation
fix(mcp): fix small note-tool defects from the v0.24.0 live run - #1705
Merged
Merged
Conversation
Fixes four defects reported in #1634. 1. A line read that starts past the end of the document now fails with "start_line N is past the end of the document (M lines)" instead of rendering an inverted "Lines 500-17" range. The slicer returns the error (the API answers 404 with that detail, like other slice failures), and cat's client-side range path raises the same message. 2. A path link that climbs past the project root is no longer stored as a permanently unresolved relation. Relation rows are built at write, move, and index time against the note's own path, and a path target that resolve_project_path cannot place in the project is dropped there. Relations are derived state; canonical Markdown is unchanged. 3. A write_note conflict names the note that owns the path. The API's already_exists outcome gains optional external_id and permalink fields (additive; older payloads still validate). The tool reports that stored permalink, external_id, and file_path instead of the permalink computed from the request, which after a move named the moved note. 4. recent_activity: the tool and prompt text no longer promise all projects when a bare call uses the default project; an empty list result now carries a "[]" text block plus a sentence, so text-only clients see an answer while structured content stays {"result": []}; the server instructions say find needs a project or a project-qualified path. Item 5 (local authorship keys) was already resolved by 91d79bd. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01APFUk2bjEwMptMQqpRhjea Signed-off-by: phernandez <paul@basicmachines.co>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
A second prose block broke clients that join text blocks and parse the result as JSON. "[]" alone is explicit for text-only clients and keeps the joined text valid JSON. Refs #1634 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01APFUk2bjEwMptMQqpRhjea Signed-off-by: phernandez <paul@basicmachines.co>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f65fceaf33
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
A bare prompt call can resolve to the default project or, with no default, to every project. The header claimed "the default project" in both cases. It now names a project only when the caller passed one; the tool's own summary states which scope applied. Refs #1634 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01APFUk2bjEwMptMQqpRhjea Signed-off-by: phernandez <paul@basicmachines.co>
phernandez
added a commit
that referenced
this pull request
Oct 9, 2026
Entries for #1697, #1698, #1699, #1700, #1701, #1702, #1704 and #1705, which landed without changelog edits so the parallel PRs would not conflict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01APFUk2bjEwMptMQqpRhjea Signed-off-by: phernandez <paul@basicmachines.co>
phernandez
added a commit
that referenced
this pull request
Oct 9, 2026
Entries for #1697, #1698, #1699, #1700, #1701, #1702, #1704 and #1705, which landed without changelog edits so the parallel PRs would not conflict. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01APFUk2bjEwMptMQqpRhjea Signed-off-by: phernandez <paul@basicmachines.co>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1634.
Summary
1. Out-of-range line read
slice_note_content(markdown/sections.py) returns aNoteSliceErrorwhen a line range starts after the last line. The message isstart_line 500 is past the end of the document (17 lines). Before this change it clamped only the end, which produced the inverted range "Lines 500-17".read_note(text and JSON),catwithmax_tokens, and the CLI all report the message as an error.catslices plain line ranges on the client side, so that path raises the same message.2. Markdown links that climb out of the project
climbs_out_of_project(target, source_path)inmarkdown/path_links.py. It is true for a path target whereresolve_project_pathreturns None.EntityServicegraph publish. All four now drop these targets instead of storing an unresolvedlinks_torow that can never resolve.[[../../x.md]]. feat(core): index Markdown links to project files #1514 already resolves those with the same rule.3.
write_noteconflict names the wrong note after a moveAlreadyExistsnow carries theNoteLocationof the note found at the path. On a lost create race (a 409 from create), it looks up the note that won the path.NoteAlreadyExistsinschemas/v2/note_write.pygainsexternal_id: str | None = Noneandpermalink: str | None = None. The change is additive: no field is renamed or removed, and a payload with onlyfile_pathstill validates.external_idand setsfile_path.edit_note/read_noteidentifier falls back to the file path, not the permalink computed from the request.4.
recent_activityEmptyListResultMiddleware(mcp/empty_results.py) adds a single[]text block in that case: the same JSON shape a non-empty list renders as, so clients that parse the text (joined or not) still get valid JSON. Structured content stays{"result": []}. The middleware applies to every tool, sotailgets the same fix.findneedsprojectwhen no project-qualified path is given, alongsidegrepandtail.5. Local authorship keys
Already resolved on main by 91d79bd. This PR does not touch it.
Behavior changes worth noting
read_note(start_line=1000)used to return empty content. It now raises the past-end error.file_path: None. It now holds the existing note's path.already_existsHTTP payload now includesexternal_idandpermalink. The cloud consumes this schema, and the addition is backward compatible.Verification
just fast-check: lint, format, and typecheck all clean.BASIC_MEMORY_TESTMON_SELECT_FLAGS="--import-mode=importlib" just fast-test <touched test paths>: passed.just test-sqlite:just man-regen: all pages already match their source.🤖 Generated with Claude Code
https://claude.ai/code/session_01APFUk2bjEwMptMQqpRhjea