Skip to content

Make tool results harder to misread: pending threads, lineage scope, flags, addresses, redaction - #14

Merged
markmnl merged 1 commit into
mainfrom
connector-round3
Oct 9, 2026
Merged

markmnl merged 1 commit into
mainfrom
connector-round3

Conversation

@markmnl

@markmnl markmnl commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

Third round of fixes from a live chat-host tester. Text content and structuredContent both carry each fix. Output schemas stay open: every new field is optional and nothing is removed or renamed.

A. wait_for_message stepped past unread messages in other threads. While a batch settles, messages from other threads are still not returned and after_id still moves past them. Holding the cursor back would replay the batch that was already returned. What changes: next, and the text, now name each skipped message before the "keep waiting" step. For example: "Also new and not included here: message 40 in another thread (root 40). after_id has moved past it … read it with get_thread (or get_message) "40" and reply if appropriate before waiting again. Then call wait_for_message with after_id …". Results add pending_ids, oldest first. The tool description and the chat prompt describe this behaviour.

B. get_thread returns only the lineage. The Web API's thread routes return only the lineage and give no count of children or other replies, so other replies can't be listed. What changes:

  • Results add scope: "lineage".
  • The description and next say that other replies (siblings and other branches) are not included, and that list_messages shows newer messages.
  • complete is now described as "the lineage is complete".

C. Escaped underscores in addresses. Addresses in text results are now code spans (`@bob_mcp@example.com`), so they are no longer escaped as \_. A value that a code span can't hold safely still falls back to escaped text. Address validation now follows the fmsg specification's user-part rule: letters and digits, with a single ., _ or - between them. Validation also rejects backslashes, spaces and control characters. The error for a backslash hints that the address may still carry Markdown escaping.

D. Thread messages lacked flags. Thread messages add no_reply, terminal, important, added and compressed, and results add the target's no_reply. next no longer suggests replying to:

  • a terminal message: no replies are possible.
  • a no-reply message: the sender asked for no replies, and reply refuses unless allow_no_reply is set.

The pid-walk fallback carries the same fields.

E. size was unlabelled. size is now described as "body size in bytes on the wire; the compressed length when compressed is true". Message items add compressed, and the text still says "N bytes compressed".

F. Redaction missed cloud access key ids. New patterns cover:

  • AKIA… and ASIA… key ids, including the published documentation example.
  • 40-character secret access keys next to their usual labels.
  • glpat- tokens.
  • Chat tokens (xox…, xapp-…).
  • AIza… API keys.
  • sk_live_, rk_live_, sk_test_ and whsec_ keys.
  • PGP private key blocks.

The existing GitHub token pattern already covered gho_, ghs_ and ghu_. Tests check that ordinary text is not redacted. The tests build token-shaped values at run time because GitHub push protection rejected the literals.

G. Smaller fixes

  1. download_attachment adds type, and save_attachment does too for consistency. content_type is kept.
  2. Every tool, including send results, lists attachments by filename. The API reports position only on thread entries, and messages sent through it share position 0, so filename order is the order the host uses.
  3. A wrong filename on a readable message now says the message has no attachment by that name and lists the names it does have. An unreadable message keeps the visibility hint.
  4. The delivery_status description now covers received messages and explains via.
  5. get_message adds thread_topic, with one thread lookup made only for replies. send_message and reply add it when it is known without another request; a reply below the root's direct children gets null.
  6. via: "add_to" is unchanged.

Tests: new test/result-clarity.test.ts covers A–E and G, and new redaction tests are in test/safety.test.ts. The suite has 215 tests; typecheck passes and test/output-schemas.test.ts still passes. The README tool table, README security notes, SECURITY.md and CHANGELOG (Unreleased) are updated.

Follow-up outside this repo: GET /fmsg/:id and the list routes in fmsg-webapi return attachments without ORDER BY or position. Exposing position there would let clients use wire order.

🤖 Generated with Claude Code

…flags, addresses, redaction

- wait_for_message: next (and the text) names messages from other threads that after_id moved
  past, with get_thread/get_message steps, before the next wait; results add pending_ids.
- get_thread: scope "lineage", description/next say other replies are not included; complete
  describes the lineage. Thread messages add no_reply, terminal, important, added, compressed;
  next never suggests replying to terminal or no-reply messages.
- Addresses render as code spans in text; address validation follows the spec's user-part rule
  and rejects backslashes, whitespace and control characters.
- size is described as the wire size; message items add compressed.
- Redact cloud access key ids and labelled secret access keys, more source-hosting, chat,
  payment and API key formats, and PGP private key blocks.
- download/save_attachment add type; a missing filename lists the message's attachments.
- One attachment order (filename) in every tool; delivery_status describes received messages
  and via; get_message, send_message and reply add thread_topic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@markmnl
markmnl merged commit 4cb7526 into main Oct 9, 2026
4 checks passed
@markmnl
markmnl deleted the connector-round3 branch October 9, 2026 13:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant