Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
6d50dfa
fix(mcpl): tool hints follow the server's statements, and a change co…
Oct 26, 2026
df8f8ea
fix(mcpl): a toolHints connect registers its abort before adding the …
Oct 25, 2026
59e25fb
fix(mcpl): refuse a toolsets selector that is there but isn't a name
Oct 25, 2026
bd3eddf
fix(mcpl): an open or close whose outcome is unknown is reported as u…
Oct 25, 2026
75d5527
fix(mcpl): a result's tool change goes with it only where it reaches …
Oct 25, 2026
0904fbf
fix(mcpl): a hinted request is remembered without its arguments
Oct 25, 2026
da15ede
fix(mcpl): the capability mask leaves RFC-014's declarations alone
Oct 25, 2026
7917177
fix(mcpl): removing a server releases and forgets its toolset controller
Oct 25, 2026
609b8da
fix(mcpl): the toolset host logs a server's values redacted, as log f…
Oct 25, 2026
7b4c347
fix(mcpl): the meta-tools' refusals say what there is, and close says…
Oct 25, 2026
5c8017a
fix(mcpl): dynamic tools' names count for pattern checks, refused act…
Oct 25, 2026
b998505
test(mcpl): pin what act and the dispatch already do for dynamic tools
Oct 25, 2026
f86c128
test(mcpl): the off path against 0.26.2's literal advertisement, and …
Oct 25, 2026
b3092aa
test(mcpl): a manifest change that removes a toolset with instances, …
Oct 25, 2026
51218fe
fix(mcpl): until a move applies, a tool is called wherever the model …
Oct 26, 2026
3e93231
docs(changelog): the toolsets host's wiring changes and fixes since 0…
Oct 26, 2026
b5ceb97
fix(mcpl): a move waits for the next refresh, and one way each to tak…
Oct 26, 2026
b8614aa
fix(mcpl): ToolsetsModule takes its taker, and a server without toolH…
Oct 26, 2026
6b67651
test(mcpl): the wiring's tests assert facts, and start a rebuild with…
Oct 26, 2026
f9173ef
test(mcpl): the hint-state tests pin each requirement where the agent…
Oct 26, 2026
a9fbdf1
fix(mcpl): a structured-only result reads as JSON only where its tool…
Oct 26, 2026
ac19444
test(mcpl): a host-opened group the manifest declares is pinned where…
Oct 26, 2026
bccb27f
test(mcpl): the late-close test waits for the close to reach the server
Oct 26, 2026
bea7819
test(mcpl): the manifest test waits for each manifest change to be ap…
Oct 26, 2026
59ca752
fix(mcpl): rendering is total for literals and look's definition, a r…
Oct 26, 2026
8568492
docs(mcpl): a move's note is a notice, a list can undo a move a rebui…
Oct 26, 2026
4d2a3c5
fix(mcpl): look shows the definition act checks, a broken-off listing…
Oct 26, 2026
2d2fc8c
test(mcpl): act's results to a script are compared with a direct call's
Oct 26, 2026
f4923ac
docs(mcpl): the wiring's texts say what null selectors, structured-on…
Oct 26, 2026
af2db14
fix(mcpl): a restating look's taken change keeps its blocks for a not…
Oct 26, 2026
40e7e17
fix(mcpl): a listing that breaks off tells the moves of the tools it …
Oct 26, 2026
5e0cc94
docs(mcpl): the README and fragment say a moved tool is called by nam…
Oct 26, 2026
e988070
docs(mcpl): told's doc, typeSig's type comment, and the fixed fragmen…
Oct 26, 2026
4ad02a2
fix(mcpl): a move is told once the published list shows the tool wher…
Oct 26, 2026
10462ef
docs(mcpl): the either-place rule's docs name the server's latest too…
Oct 26, 2026
69873a1
docs(mcpl): look's one-tool answer named whole, the first-sentence ru…
Oct 26, 2026
a78a4ba
Merge main (e7e2391f) into the toolsets fixes
Oct 26, 2026
2432951
fix(mcpl): a recovery whose tools/list fails still reads toolsets/lis…
Oct 26, 2026
6a6549e
docs(mcpl): a model's call counts as reaching its agent once its resu…
Oct 26, 2026
59be5cb
test(mcpl): the unreadable-result test's runtime probe parses the nes…
Oct 26, 2026
30a86f1
docs(mcpl): recover() says what a failed tools/list leaves; its test …
Oct 26, 2026
6e7fe42
fix(mcpl): look's JSON says when it's too long to write, the README n…
Oct 26, 2026
03d1fe1
fix(mcpl): the puppet shows a structured-only error's content as its …
Oct 26, 2026
b06275a
docs(mcpl): the first-sentence exception names close, rendering is sa…
Oct 26, 2026
2b02200
fix(mcpl): a structured-only error the host can't write, or whose con…
Oct 26, 2026
3fdc42e
docs(mcpl): the error branch's comment no longer says the model's dis…
Oct 26, 2026
8f71c3b
docs(mcpl): limits no test pins are stated as read from the code
Oct 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 52 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -448,36 +448,75 @@ framework registers a `toolsets` module with four constant tools:
- `toolsets--act {server?, tool, instance?, args?}` calls a dynamic tool down
the same path as a direct call of it (the agent's `allowedTools`, the
server's tool policy, the state exchange, the reading of its result, RFC-007
observers, who see the server's tool), with only the instance added, in
observers and RFC-008 class rules, which see the server's tool and its class),
with only the instance added, in
`_meta["mcpl/instance"]`. It first checks `args` against the definition in
force for that instance; that check is bounded, and leaves `pattern` and
anything nested or branching too far to the server, which checks every
call itself;
- `toolsets--look {server?, toolset?, instance?, tool?}` restates what is open
and what can be opened, or one tool's whole definition;
and what can be opened, or one tool's signature, description, class and
input schema. It
re-reads each server that presents toolsets first, and says so when it
couldn't; what that changed
is in the answer when look restates everything, and otherwise told as a
notice;
- `toolsets--close {server?, toolset?, instance?}` closes it.

`server` can be left out when only one server has the name. Hint changes apply
`server` can be left out when only one server has the name. By our reading of
the code, a server with no toolsets stops presenting them once its latest `tools/list` has no dynamic
tool, so until the rebuild, act takes its last one only with `server` named.
Hint changes apply
as their message is read, in `rev` order, whatever becomes of the message (a
refused push, a result that came after its timeout). A skipped rev re-reads
`tools/list` and then `toolsets/list`, which the host also reads after every
(re)connect, adopting what the server kept open and never re-opening anything.
refused push, a result that came after its timeout). A move between static and
dynamic takes effect when the server's `tools/list` states it, and the tool
list follows at its next rebuild that lists the server, whichever refresh
brings it (a move is no reason to rebuild the tool list early). Until then the
tool is called at either place, where the tool list shows it or where the
server's latest list put it (RFC-014 §4.2 keeps it working where it is until
the move applies), and
once that rebuild has published the list, a notice says where it went. A list
read while a rebuild is under way can undo a move that rebuild then publishes;
neither is told, and the next rebuild puts the tool back.
A skipped rev re-reads `tools/list` and then `toolsets/list`, which the host
also reads after every (re)connect, adopting what the server kept open and
never re-opening anything.
What changed is told where it happened: after a call's own result, after the
push that explains it, or as a notice (`kind: 'mcpl-toolsets'`, which wakes
nothing) for a standalone `tools/hints`, a late result, an adoption, a
recovery, or a call whose result doesn't go to the agent (one the framework or
a module makes itself). Notices need the server's `pushEvents` grant, like any delivery. A
new tool's first sentence is told the first time its definition appears.
Suggestions are shown, never acted on. Each `ended` id is told once. When an
recovery, or a call whose result may not reach the agent (a script's, a
module's or a host's, or one the framework makes itself); an open, close or
look made that way also shows its caller the change, unless the change has
already gone as a notice (below). A dynamic tool's change also goes as a notice
when it wouldn't fit whole within its result's inline cap, or when its call
fails after the result was read. A call's change also goes as a notice, ahead of its
result, when a later change goes to the agent before the call's caller has
taken it, so changes are told in the order they were read (the agent's window
can still show a call's result, a push's event, or a change its taker couldn't
show after a change read later). The model's own call's change counts as told
once its result is handed back: if the turn is stopped while the call is out
(or, by our reading of the code, the agent is gone), the result is dropped and the change with it, and
`toolsets--look` shows the state it left. Notices and reminders
need the server's `pushEvents` grant, like any delivery; without it, a change
that would go as a notice is dropped, and `toolsets--look` shows the state. A new tool's first sentence is told with its
definition until text describing it has reached the model, except that, by our reading of the code, a puppet's
open, close or look whose result the store refuses has already counted it. Suggestions are shown, never acted on. Each
`ended` id is told once while the
host runs (told ids are kept in memory), short of rare interleavings, such as a
`toolsets--look` overlapping other reads of the same server, that can tell one
twice. When an
open toolset's announcements have left an agent's context (compressed or out
of the window), the module's `gatherContext` restates what is open, as a
stored `afterUser` injection (namespace `mcpl-toolsets`), at that agent's next
start.

A dynamic tool called by its prefixed name is refused, pointing at
`toolsets--act`. Calls to an undeclared toolset's tools are refused while the
host has that group closed (RFC-014 §5.4). Projection and surface mode are not
implemented: a `surface` server's static tools are listed like any server's.
`toolsets--act`, unless the tool list or the server's latest list shows it as
static (a move waiting for its rebuild). Calls to an undeclared toolset's
tools are refused while the host has that group closed (RFC-014 §5.4), except
by a tool's listed name until the rebuild that publishes its move into the
group. Projection and surface mode are not implemented: a `surface` server's
static tools are listed like any server's.

#### Per-channel conversation routing (deprecated)

Expand Down
1 change: 1 addition & 0 deletions changelog.d/mcpl-toolsets-hint-state.breaking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- **Hosts that set `toolHints: true` on an MCPL server without granting it `pushEvents`:** the reminder that restates a server's open toolsets at an agent's next start, once their announcement has left the context, now comes only for a server granted `pushEvents`, like every other notice of its changes. Grant `pushEvents` to that server to keep the reminders.
4 changes: 4 additions & 0 deletions changelog.d/mcpl-toolsets-hint-state.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
- MCPL RFC-014 tool presence (`toolHints: true`):
- A move between static and dynamic takes effect when the server's `tools/list` states it, not when a hint announces it, and once the next rebuild of the model's tool list that lists the server has published it, a notice says where the tool went, unless a list read during that rebuild undid the move. A move is no reason to rebuild the tool list early, whether a hint announced it or the host's own re-read found it.
- Each `ended` id is told once while the host runs: told ids are kept in memory, an id counts as told only once a notice or a result carrying it reached the agent, and it is forgotten once the server stops reporting it. Rare interleavings, such as a `toolsets--look` overlapping another read of the same server, can tell one twice.
- `toolsets--look` naming a tool shows its signature, description, class and input schema, as before; the README no longer calls that its whole definition. What look's own re-read of the server changed is in its answer when it restates everything, and otherwise told as a notice.
6 changes: 6 additions & 0 deletions changelog.d/mcpl-toolsets-hint-state.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- MCPL RFC-014 tool presence (`toolHints: true`), fixes to how hint changes are applied and told:
- A `tools/list` is applied whole as its last page is read, so a hint read just after it isn't undone, and a malformed or timed-out list changes nothing. A paged list whose pages straddle a change, or a hint or `toolsets/list` entry naming a tool `tools/list` hasn't listed, is recovered from.
- Changes are told in the order they were read, each once: a result's change nobody shows with it is told as a notice before any later change, and a new tool's first sentence counts as shown only once text describing it reached the model. A change a caller took and then couldn't show is told when the caller finds that out, after anything told meanwhile. By our reading of the code, a puppet's open, close or look whose result the store refuses has already counted the definitions it rendered.
- A change that would go as a notice to a server without the `pushEvents` grant is dropped, and `toolsets--look` shows the state.
- A tool the operator's tool policy refuses never starts a recovery, and a tool listed twice is known by its first listing.
- A malformed definition no longer makes rendering throw: a description that isn't a string is left out, and a schema or a toolset's `options` nested very deep is cut short, rather than failing a notice or `toolsets--look`.
1 change: 1 addition & 0 deletions changelog.d/mcpl-toolsets-wiring.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- MCPL RFC-014 tool presence (`toolHints: true`): until a move between static and dynamic reaches the model's tool list, the tool is called at either place: by its prefixed name where the tool list or the server's latest `tools/list` shows it static, and through `toolsets--act` where either shows it dynamic (RFC-014 §4.2). A dynamic tool called by its prefixed name is therefore no longer always refused. `toolsets--look` naming a tool shows the definition `toolsets--act` would check it against wherever `toolsets--act` would take it.
7 changes: 7 additions & 0 deletions changelog.d/mcpl-toolsets-wiring.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
- MCPL RFC-014 tool presence (`toolHints: true`), fixes to how the toolsets host is wired into the framework:
- A result's tool change goes with it only where the result reaches an agent: the model's own call, and the operator's puppet, whose call and result are stored in the agent's window. The model's own call counts as reaching it once its result is handed back. If the turn is stopped while the call is out (or, by our reading of the code, the agent is gone), the result is dropped, and the change with it, counted as told and not told again, as in 0.27.0; `toolsets--look` shows the state it left. A script's, a module's or a host's own call leaves it to a notice. A dynamic tool's change that wouldn't fit whole within its result's inline cap, or whose call fails after its result was read, goes as a notice too. A result that is structured content alone shows that content, as its JSON, before the change that goes with it.
- An open or close whose outcome is unknown is reported as unconfirmed rather than as not done, and names `toolsets--look`, which says when it couldn't ask the server. A selector that is present but isn't a name is refused (null reads as left out), and a refusal for a name the server doesn't have says what it has.
- Removing a server, or restarting it under another id or with `toolHints` off, leaves no toolset state behind. A stop or a disconnect while a `toolHints` server is still connecting ends the connect.
- The capability mask no longer reports `toolHints`, `toolsets` and `surface` as masked: `toolHints: false` turns hints off. Operator tool-name patterns naming a dynamic tool count as matched.
- Server-chosen values in the toolset host's log lines, and in the trace of a `toolsets--act` that can't be resolved, are redacted with the servers' configuration. A request kept for a late answer no longer holds a call's arguments.
- A programmatic `toolsets--act` that's refused is traced as `tool:failed`, as the model's own refused act already was. A tool change that can't be told for want of an agent is logged, as one without the `pushEvents` grant already was.
Loading
Loading