@evref-bl/pharo-mcp 1.5.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,9 +1,9 @@
1
- [![Pharo version](https://img.shields.io/badge/Pharo-12%20%7C%2013%20%7C%2014-%23aac9ff.svg)](https://github.com/pharo-project/Pharo)
1
+ # MCP for Pharo
2
+
3
+ [![Pharo version](https://img.shields.io/badge/Pharo-12%20%7C%2013%20%7C%2014%20%7C%2015-%23aac9ff.svg)](https://github.com/pharo-project/Pharo)
2
4
  [![CI](https://github.com/Evref-BL/MCP/actions/workflows/ci.yml/badge.svg?branch=main&event=push)](https://github.com/Evref-BL/MCP/actions/workflows/ci.yml?query=branch%3Amain+event%3Apush)
3
5
  [![Coverage Status](https://coveralls.io/repos/github/Evref-BL/MCP/badge.svg?branch=main)](https://coveralls.io/github/Evref-BL/MCP?branch=main)
4
6
 
5
- # MCP for Pharo
6
-
7
7
  MCP is an in-image [Model Context Protocol](https://modelcontextprotocol.io/)
8
8
  server for Pharo. It lets MCP clients inspect and change the running image
9
9
  through Pharo-aware tools for packages, classes, methods, tests, repositories,
@@ -15,8 +15,10 @@ files as plain text.
15
15
 
16
16
  ## Supported Versions
17
17
 
18
- Pharo 12, 13, and 14 are supported. Development targets Pharo 14 while CI
19
- checks the full matrix.
18
+ Pharo 12, 13, 14, and 15 are supported.
19
+
20
+ Protocol revisions `2025-03-26`, `2025-06-18`, `2025-11-25` and `2026-07-28`
21
+ are supported, each answered in its own shape.
20
22
 
21
23
  ## Install And Start
22
24
 
@@ -26,17 +28,20 @@ Load MCP in a supported image:
26
28
  Metacello new
27
29
  baseline: 'MCP';
28
30
  repository: 'github://Evref-BL/MCP:main/src';
31
+ onConflictUseIncoming;
29
32
  load.
30
33
  ```
31
34
 
32
35
  Start the Streamable HTTP server:
33
36
 
34
37
  ```smalltalk
35
- mcp := MCP new.
36
- mcp port: 4000.
37
- mcp start.
38
+ MCP startOnPort: 4000.
38
39
  ```
39
40
 
41
+ That answers the server already on 4000 when the image has one, so running it
42
+ again after a restart is safe. `MCP allServers` lists what the image holds, and
43
+ `Library → MCP Servers` in the world menu shows the same list.
44
+
40
45
  Connect a local MCP client to `http://127.0.0.1:4000`. Client configuration
41
46
  formats differ; see [Getting started](templates/pharo-references/getting-started.md) for setup
42
47
  and first calls.
@@ -57,10 +62,10 @@ Install the guide, local references, workflow skills, and direct MCP
57
62
  configuration for an agent host into the current project:
58
63
 
59
64
  ```sh
60
- npx @evref-bl/pharo-mcp install --host codex
65
+ npx @evref-bl/pharo-mcp install --host claude
61
66
  ```
62
67
 
63
- Use `--host claude` or `--host opencode` for those hosts. The direct MCP
68
+ Use `--host codex` or `--host opencode` for those hosts. The direct MCP
64
69
  configuration expects port `4000`; update it when the image uses another port.
65
70
 
66
71
  Node integrations that provide their own MCP transport can install only the
@@ -74,7 +79,7 @@ installGuidance({ host: "codex", cwd: process.cwd() });
74
79
 
75
80
  ## Contributing
76
81
 
77
- Use Pharo 14 for normal development and preserve Pharo 12/13 compatibility.
78
- Live behavior must be verified in an image; source inspection alone is not
79
- enough. Start with [AGENTS.md](AGENTS.md) and
82
+ Use Pharo 14 for normal development and preserve Pharo 12, 13 and 15
83
+ compatibility. Live behavior must be verified in an image; source inspection
84
+ alone is not enough. Start with [AGENTS.md](AGENTS.md) and
80
85
  [MCP verification](docs/mcp-verification.md).
package/node/installer.js CHANGED
@@ -44,9 +44,11 @@ function filesIn(directory) {
44
44
  });
45
45
  }
46
46
 
47
- function directoryPlan(sourceRelativePath, targetRelativePath) {
47
+ function directoryPlan(sourceRelativePath, targetRelativePath, host) {
48
48
  const sourceDirectory = path.join(templateDirectory(), sourceRelativePath);
49
- return filesIn(sourceDirectory).map((source) => ({
49
+ return filesIn(sourceDirectory).filter((source) =>
50
+ host === "codex" || !source.endsWith(`${path.sep}agents${path.sep}openai.yaml`)
51
+ ).map((source) => ({
50
52
  source,
51
53
  target: path.join(targetRelativePath, path.relative(sourceDirectory, source)),
52
54
  }));
@@ -59,17 +61,17 @@ function filePlan(sourceRelativePath, targetRelativePath) {
59
61
  }];
60
62
  }
61
63
 
62
- function guidancePlan(configuration) {
64
+ function guidancePlan(configuration, host) {
63
65
  return [
64
66
  ...filePlan("pharo.AGENTS.md", path.join(configuration.directory, "pharo.AGENTS.md")),
65
- ...directoryPlan("pharo-skills", path.join(configuration.directory, "skills")),
67
+ ...directoryPlan("pharo-skills", path.join(configuration.directory, "skills"), host),
66
68
  ...directoryPlan("pharo-references", path.join(configuration.directory, "pharo-references")),
67
69
  ];
68
70
  }
69
71
 
70
- function fullPlan(configuration) {
72
+ function fullPlan(configuration, host) {
71
73
  const [source, target] = configuration.configuration;
72
- return [...guidancePlan(configuration), ...filePlan(source, target)];
74
+ return [...guidancePlan(configuration, host), ...filePlan(source, target)];
73
75
  }
74
76
 
75
77
  function absolutePlan(cwd, plan) {
@@ -129,7 +131,7 @@ function writeGuide({ target, content }) {
129
131
  function prepare(options, direct) {
130
132
  const cwd = path.resolve(options.cwd ?? process.cwd());
131
133
  const configuration = hostConfiguration(options.host);
132
- const plan = absolutePlan(cwd, direct ? fullPlan(configuration) : guidancePlan(configuration));
134
+ const plan = absolutePlan(cwd, direct ? fullPlan(configuration, options.host) : guidancePlan(configuration, options.host));
133
135
  const guide = guidePlan(cwd, configuration);
134
136
  assertCompatible(plan);
135
137
  return { configuration, cwd, guide, plan };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evref-bl/pharo-mcp",
3
- "version": "1.5.1",
3
+ "version": "2.1.0",
4
4
  "description": "Pharo MCP agent-host templates",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,147 +1,70 @@
1
1
  # Debugging Tools
2
2
 
3
- Applies when using MCP-Pharo to capture exceptions, inspect debug sessions,
4
- control paused execution, manage breakpoints, or repair code from a debugger
5
- state.
3
+ Applies when using MCP-Pharo to watch values while code runs, or to see what
4
+ debuggers a person has open.
6
5
 
7
6
  ## Goal
8
7
 
9
- Use debugger tools without guessing from source, driving Morphic debugger UI by
10
- hand, or issuing stale frame and variable references.
8
+ See what running code is doing without guessing from source and without driving
9
+ the Morphic debugger by hand.
11
10
 
12
11
  Debugger tools are discoverable, not part of the default static surface.
13
12
 
14
13
  ## Discovery Flow
15
14
 
16
- 1. Use `tool_search` with `group=debugging` to find available debugger
17
- tools.
15
+ 1. Use `tool_search` with a query such as `watch` or `debugger`.
18
16
  2. Use `tool_get` for the exact schema of the tool you plan to call.
19
17
  3. If the current client exposes a catalog bridge, use `tool_call` to invoke
20
- the selected debugger tool by name. Otherwise use the callable form exposed
21
- by the current client.
18
+ the selected tool by name. Otherwise use the callable form exposed by the
19
+ current client.
22
20
 
23
- ## Must Do
21
+ ## Tool Map
24
22
 
25
- - Treat `stateId`, `frameRef`, and `variableRef` values as opaque and
26
- state-scoped.
27
- - Use the newest returned state after every control or edit action.
28
- - Keep stack and variable limits small first, then expand only what is needed.
29
- - Clear temporary breakpoints and forget agent-owned sessions when the task is
30
- done.
31
- - Report the exact debugger tool names used and the final session state.
23
+ | Tool | Use |
24
+ | --- | --- |
25
+ | `debug_watch` | Record what variables hold while an expression runs, without stopping it. |
26
+ | `debug_search` | Answer the debuggers open in the image, read-only. |
32
27
 
33
- ## Do Not
28
+ Neither tool keeps anything. No session is started, attached or registered, so
29
+ there is no reference to carry between calls and nothing to clean up.
34
30
 
35
- - Do not drive debugger windows or mutate contexts through general `image_evaluate`
36
- code.
37
- - Do not reuse frame or variable references after stepping, restarting,
38
- resuming, terminating, or editing.
39
- - Do not leave breakpoints or captured sessions behind without reporting them.
40
- - Do not use debugger editing as a substitute for normal source tools when
41
- there is no paused debugger state.
31
+ ## Watching Values
42
32
 
43
- ## Tool Map
33
+ `debug_watch` is print debugging without editing the method. Name the methods to
34
+ probe, the variables to record, and the expression to run. Every assignment to a
35
+ named variable is recorded as it happens, the expression runs to completion, and
36
+ the probes are removed before the call answers.
44
37
 
45
- | Tool | Use |
46
- | --- | --- |
47
- | `debug_capture` | Evaluate a Smalltalk expression in a bounded worker process and capture runtime exceptions as tracked debug sessions. |
48
- | `debug_test_run` | Run one SUnit test method in a bounded worker process and capture failures or errors as tracked debug sessions. |
49
- | `debug_session_list` | List tracked debug sessions. |
50
- | `debug_session_get` | Inspect one tracked debug session summary. |
51
- | `debug_session_remove` | Remove a tracked debug session from the registry. |
52
- | `debug_candidate_search` | Search unattached open debugger candidates. |
53
- | `debug_candidate_attach` | Attach an open debugger candidate and return its debug state. |
54
- | `debug_state_get` | Return the current session snapshot: stack, selected frame, source, scopes, repair actions, and state-scoped refs. |
55
- | `debug_variable_get` | Expand scope and variable refs returned by `debug_state_get`. |
56
- | `debug_expression_evaluate` | Evaluate a Smalltalk expression in a selected debug frame. |
57
- | `debug_session_step_into` | Step into the selected frame of a tracked session. |
58
- | `debug_session_step_over` | Step over the selected frame of a tracked session. |
59
- | `debug_session_step_through` | Step through the selected frame of a tracked session. |
60
- | `debug_session_restart` | Restart the selected frame of a tracked session. |
61
- | `debug_session_resume` | Resume a tracked session. |
62
- | `debug_session_terminate` | Terminate a tracked session. |
63
- | `debug_breakpoint_list` | List tracked transient DebugPoint breakpoints. |
64
- | `debug_breakpoint_set` | Install a transient method-entry or source-interval DebugPoint breakpoint. |
65
- | `debug_breakpoint_remove` | Remove one tracked transient DebugPoint breakpoint. |
66
- | `debug_breakpoint_enable` | Enable one tracked transient DebugPoint breakpoint. |
67
- | `debug_breakpoint_disable` | Disable one tracked transient DebugPoint breakpoint. |
68
- | `debug_breakpoint_clear` | Remove all tracked transient DebugPoint breakpoints. |
69
- | `debug_method_update` | Update the method associated with a paused debug state, then proceed when possible. |
70
-
71
- ## Session Workflow
72
-
73
- Use `debug_capture` when the agent should run code and capture its own
74
- failure. If execution completes normally, there is no debugger session. If a
75
- runtime exception is captured, use the returned `sessionId` and `state`.
76
-
77
- Use `debug_test_run` when the failure is already expressed as one SUnit test method.
78
- If the test passes, there is no debugger session. If it fails or errors, use the
79
- returned `sessionId` and `state`.
80
-
81
- Use `debug_candidate_search` when a human already opened a debugger. It returns
82
- unattached candidates with identifying details. Attach by passing the
83
- candidate's `candidateRef` to `debug_candidate_attach`.
84
-
85
- Use `debug_session_remove` when you are done. Removing an agent-owned captured
86
- session can terminate its worker process. Removing an attached human debugger
87
- only removes it from the MCP registry.
88
-
89
- ## State And References
90
-
91
- Treat `stateId`, `frameRef`, and `variableRef` values as state-scoped opaque
92
- references. After a debug-session control tool or `debug_method_update`, old
93
- frame and variable refs can be stale. Use the new returned state before
94
- evaluating, expanding variables, or controlling execution again.
95
-
96
- Use `debug_state_get` as the main context-loading tool. Keep stack and variable
97
- limits small first, then expand details with `debug_variable_get` only when needed.
98
-
99
- Use `debug_expression_evaluate` only for expressions that need the selected frame's
100
- receiver or temporaries. Prefer normal code tools for project edits.
101
-
102
- ## Control
103
-
104
- Use `debug_session_step_into`, `debug_session_step_over`,
105
- `debug_session_step_through`, `debug_session_restart`,
106
- `debug_session_resume`, and `debug_session_terminate` for control actions.
107
- Control tools can return a `debug_state_get` snapshot when execution pauses.
108
- Set `returnState=true` when the next step needs that snapshot inline;
109
- otherwise call `debug_state_get` after the control action.
110
- When the user asks for a bounded action, such as "step into twice", perform
111
- those control calls and stop.
112
-
113
- For externally attached debuggers, control should operate through the attached
114
- debugger controller so the visible debugger remains the owner of its UI. Do not
115
- manipulate debugger windows or contexts with general `image_evaluate` code.
116
-
117
- ## Breakpoints
118
-
119
- Use the `debug_breakpoint_*` tools for temporary method-entry or
120
- source-interval DebugPoint breakpoints. Clear breakpoints when the debugging
121
- task ends.
122
-
123
- File/line breakpoints are intentionally not emulated. Resolve source intervals
124
- from the relevant method when source-interval precision is needed.
125
-
126
- ## Debugger-Driven Development
127
-
128
- When a debug state offers repair actions, prefer `debug_method_update` over separate
129
- manual edits. It can create missing methods or recompile stub/selected methods,
130
- formats the compiled method, reports critiques, and proceeds when the edit is
131
- accepted.
132
-
133
- Read [Debugger-Driven Development](debugger-driven-development.md) before using
134
- `debug_method_update` for missing methods, `subclassResponsibility`,
135
- `shouldBeImplemented`, `notYetImplemented`, or iterative repair workflows.
136
-
137
- ## Reporting
138
-
139
- When finishing debugger work, report:
140
-
141
- - how the session was obtained: capture, test, discovered debugger, or attached
142
- debugger;
143
- - debugger tools called;
144
- - final session outcome: completed, paused, running, terminated, forgotten, or
145
- still open;
146
- - breakpoints created, cleared, or left in place;
147
- - cleanup performed or still needed.
38
+ Name no variable and each method's arguments are recorded as it is entered.
39
+ Both `method` and `variable` take one value or a list, and a probe goes on every
40
+ pair that exists, so a variable a method never assigns simply has no series there.
41
+
42
+ Reach for it whenever the question is what a value became, rather than where to
43
+ intervene.
44
+
45
+ ## Seeing A Person's Debuggers
46
+
47
+ `debug_search` answers the debuggers open in the image: each one's name, the
48
+ exception it stopped on, and the frames nearest the stop with what those frames
49
+ hold. Pass a `query` to keep only the debuggers whose name or exception matches.
50
+
51
+ It is a query and nothing else. It attaches to nothing, changes nothing, and
52
+ remembers nothing, so the picture it gives is whatever is open at that moment.
53
+ Ask again for a fresh one.
54
+
55
+ Act on what it shows with the ordinary tools: read the method with `method_get`,
56
+ change it with `method_compile`, run something with `image_evaluate`. Stepping,
57
+ resuming and repairing from inside a frame belong to the person at the debugger,
58
+ not to the agent.
59
+
60
+ ## To Debug Your Own Code
61
+
62
+ Do not open a debugger for it. Call the tool that runs the code and read the
63
+ failure it reports: it names the frames nearest the error and the values they
64
+ held. When that is not enough, `debug_watch` shows how a value got there.
65
+
66
+ ## Do Not
67
+
68
+ - Do not drive debugger windows or mutate contexts through general
69
+ `image_evaluate` code.
70
+ - Do not resume, step or terminate a person's debugger. It is theirs.
@@ -5,7 +5,7 @@ connecting a client.
5
5
 
6
6
  ## Requirements
7
7
 
8
- - Pharo 12, 13, or 14
8
+ - Pharo 12, 13, 14, or 15
9
9
  - An MCP client that supports Streamable HTTP directly or through a local bridge
10
10
  - Network access from the client to the image host
11
11
 
@@ -58,6 +58,14 @@ Dependencies can select the same group with `loads: #( 'Core' )`.
58
58
 
59
59
  ## Start And Stop
60
60
 
61
+ ```smalltalk
62
+ mcp := MCP startOnPort: 4000.
63
+ ```
64
+
65
+ That answers the server already on 4000 when the image has one, rather than
66
+ failing on the port it holds. Build one by hand when it needs configuring
67
+ before it starts:
68
+
61
69
  ```smalltalk
62
70
  mcp := MCP new.
63
71
  mcp port: 4000.
@@ -121,16 +129,16 @@ tool_get
121
129
  Then inspect the image with focused read-only tools such as:
122
130
 
123
131
  ```text
124
- package_search
125
132
  class_search
126
133
  class_get
127
- method_metadata_search
134
+ method_search
128
135
  method_source_search
129
- method_implementor_search
130
- method_sender_search
136
+ method_reference_search
131
137
  method_get
132
138
  ```
133
139
 
140
+ `package_search` and the specialized tools are found with `tool_search`.
141
+
134
142
  Before mutation, inspect the target and use a copied or disposable image.
135
143
  Prefer dedicated tools such as `class_create`, `method_compile`, refactoring
136
144
  tools, and `test_run` over `image_evaluate`.
@@ -100,7 +100,7 @@ over clients branching on concrete classes or internal fields.
100
100
  - Do not use `getName` or `setName:`.
101
101
  - Predicates should read as predicates: `isReady`, `hasErrors`,
102
102
  `canHandle:`.
103
- - Action selectors should use verbs: `parseRequest:`, `registerTool:`,
103
+ - Action selectors should use verbs: `parseRequest:`, `addTool:`,
104
104
  `writeResponseOn:`.
105
105
  - Conversion selectors should start with `as`.
106
106
 
@@ -133,6 +133,8 @@ Scan for:
133
133
  `thenDo:` variant would avoid the intermediate collection;
134
134
  - sorting through conversion chains instead of sorting a result array directly;
135
135
  - defensive type checks in private helpers that hide caller bugs;
136
+ - cascaded stream writes, where `stream << a; << b` says what `stream << a << b`
137
+ says with more punctuation, since `<<` answers the stream;
136
138
  - wrapper methods or extensions that exist only because a collaborator might be
137
139
  wrong someday;
138
140
  - dense nested expressions that would be clearer with a temporary or extracted
@@ -22,10 +22,22 @@ The execution path is:
22
22
  3. The concrete tool parses the request into a typed request or spec object.
23
23
  4. The tool dispatches a command or query object.
24
24
  5. The command uses Pharo APIs to query or mutate the image.
25
- 6. The tool returns a payload with `status`, `summary`, `warnings`, and either
26
- `data` or `error`. By default this payload is serialized into the MCP
27
- `content` field; the server can also emit `structuredContent` for clients
28
- that need programmatic results.
25
+ 6. The tool returns a payload with `summary`, `warnings`, and either `data` or
26
+ `error`, with a failure flagged by the protocol's own `isError`. By default
27
+ this payload reaches the MCP `content` field; the server can also emit
28
+ `structuredContent` for clients that need programmatic results.
29
+
30
+ ### Notifications
31
+
32
+ A notification is not a failed call. Pharo signals them for remarks rather than
33
+ faults, and every `Warning` is one. The tool boundary resumes them with the
34
+ value the image itself would have produced and the call proceeds, so a
35
+ deprecated send, or an undeclared variable during a package load, does not fail
36
+ it. A deprecated method called from a test does not abort the suite.
37
+
38
+ Refactoring warnings are the exception. `RBRefactoringWarning` reports a change
39
+ that breaks something, so it reaches the boundary unresumed and stops the call,
40
+ aborting a removal or a rename that `force=true` did not authorize.
29
41
 
30
42
  ```mermaid
31
43
  sequenceDiagram
@@ -104,44 +116,66 @@ Critiques include:
104
116
  The method may compile successfully and still return critiques. Treat critiques
105
117
  as follow-up review evidence, not as transport failures.
106
118
 
107
- ## Rewrite Preview And Confirmation
119
+ ## Rewriting Methods
120
+
121
+ `method_rewrite` uses Smalltalk AST rewrite patterns, not regex. A rule has a
122
+ `match` and a `replacement`, and a scope is required, so rewriting everything is
123
+ something a caller asks for by naming the packages rather than by leaving an
124
+ argument out.
108
125
 
109
- `method_rewrite` uses Smalltalk AST rewrite rules. Patterns use RB AST pattern
110
- syntax, not regex.
126
+ A metavariable starts with a backquote and stands for whatever is in its place.
127
+ `` `@receiver `` matches one expression, however big: the same rule rewrites
128
+ `anObject notNil` and `(anObject foo) notNil`. **The names must be the same on
129
+ both sides** — a name that appears only in `replacement` is bound to nothing.
111
130
 
112
- The default mode is preview:
131
+ The default mode is preview, which carries the old and new source of every
132
+ change:
113
133
 
114
134
  ```json
115
135
  {
116
136
  "rules": [
117
137
  {
118
- "lhs": "`@receiver ifTrue: [ `@body ]",
119
- "rhs": "`@receiver ifTrue: [ `@body ]"
138
+ "match": "`@receiver notNil",
139
+ "replacement": "`@receiver isNotNil"
120
140
  }
121
141
  ],
122
- "apply": false
142
+ "scope": { "packages": ["MyPackage"] }
123
143
  }
124
144
  ```
125
145
 
126
- Preview mode returns calculated changes and a `changeSetHash`. Applying requires
127
- the hash from a preview of the same request:
146
+ A metavariable stands for a block just as readily, which is how a rule drops
147
+ one branch of a conditional:
128
148
 
129
149
  ```json
130
150
  {
131
151
  "rules": [
132
152
  {
133
- "lhs": "`@old",
134
- "rhs": "`@new"
153
+ "match": "`@receiver ifTrue: [ `@body ] ifFalse: [ nil ]",
154
+ "replacement": "`@receiver ifTrue: [ `@body ]"
135
155
  }
136
156
  ],
137
- "packageNames": ["MyPackage"],
138
- "apply": true,
139
- "expectedChangeSetHash": 123456
157
+ "scope": { "packages": ["MyPackage"] }
140
158
  }
141
159
  ```
142
160
 
143
- Applying to the whole image also requires `force=true`. Prefer an explicit
144
- package, class, hierarchy, or method scope.
161
+ Add `apply` to make the changes. One call is enough; preview first only when
162
+ you want to read them before they land. `history_entry_revert` undoes a rewrite
163
+ that turned out wrong.
164
+
165
+ Any rewrite rule stands for its own patterns, so its name can be given instead
166
+ of writing them out. That includes Pharo's own, not only MCP's:
167
+
168
+ ```json
169
+ {
170
+ "ruleClasses": ["MCPCollectionThenDoRule"],
171
+ "scope": { "packages": ["MyPackage"] },
172
+ "apply": true
173
+ }
174
+ ```
175
+
176
+ Rules that report a critique are not applied by the tools that compile. A
177
+ compile reports what it would change; changing it is this tool's job, and the
178
+ caller asks.
145
179
 
146
180
  ## Tests And Coverage
147
181
 
@@ -189,39 +223,72 @@ live image back to Tonel/Git.
189
223
 
190
224
  ## Debugging
191
225
 
192
- Debugger tools are discoverable through the `debugging` group. They work with
193
- tracked Pharo `DebugSession` records, captured worker-process exceptions,
194
- SUnit test failures, transient DebugPoint breakpoints, and attached human-opened
195
- debuggers.
196
-
197
- Treat debugger state references as opaque and state-scoped. After stepping,
198
- resuming, restarting, terminating, or editing from a debug state, use the newly
199
- returned state before expanding variables or evaluating in a frame again.
226
+ Debugger tools are discoverable through the `debugging` group. They keep no
227
+ state: `debug_watch` installs non-halting probes and removes them before it
228
+ answers, and `debug_search` only reads the debuggers a person has open.
200
229
 
201
- Use `debug_method_update` only from a paused debug state and only after reading the
202
- offered repair actions. It uses the same critique gate as method editing before
203
- proceeding a repaired computation.
230
+ A debugger somebody opened belongs to them. Read it, then act with the ordinary
231
+ class and method tools; do not step, resume or terminate it.
204
232
 
205
233
  ## Evaluation Escape Hatch
206
234
 
207
- `image_evaluate` runs arbitrary Smalltalk and saves the image after a successful
208
- call. It is useful for short inspection or glue code when no dedicated tool
235
+ `image_evaluate` runs arbitrary Smalltalk in the running image without saving
236
+ it. It is useful for short inspection or glue code when no dedicated tool
209
237
  exists.
210
238
 
211
239
  Prefer a dedicated tool when one exists, because the dedicated tools validate
212
240
  input, return structured result data, and often use safer Pharo APIs.
213
241
 
242
+ Compiling source is one of those cases. Method source in the image separates
243
+ lines with CR, and `method_compile` normalizes what it is given; a bare
244
+ `compile:` from `image_evaluate` stores whatever it receives, so source written
245
+ with LF compares unequal to every other method in the image. Use
246
+ `method_compile` for a method, and `withInternalLineEndings` if you must compile
247
+ source by hand.
248
+
214
249
  ## Observability And UI
215
250
 
216
- The Spec dashboard is available from an inspected `MCP` object. It shows:
251
+ The servers an image holds are listed under `Library → MCP Servers` in the
252
+ world menu, and on the `Servers` tab of an inspected `MCP` class. From there a
253
+ server can be started, stopped, or opened in its dashboard, and a new one
254
+ created on a port, where 0 asks for a free one. The tool catalog sits beside it
255
+ under `Library → MCP Tool Catalog`, since it describes the image rather than
256
+ any one server. The same list in a script:
217
257
 
218
- - server status and port
258
+ ```smalltalk
259
+ MCP allServers
260
+ ```
261
+
262
+ It is taken from the heap rather than from a registry, so a server is never
263
+ kept alive for being listable, and one that is still holding a port after its
264
+ owner forgot it is shown rather than hidden.
265
+
266
+ To reach the server on a port, whether or not this script is the one that
267
+ started it, ask for the port rather than for a new server:
268
+
269
+ ```smalltalk
270
+ MCP startOnPort: 4000
271
+ ```
272
+
273
+ That answers the server already on 4000, starting it if it was stopped, and
274
+ makes one only when the image has none there. Starting a second server on a
275
+ taken port fails after a couple of seconds, and the error now says when the
276
+ port is held by another MCP in the same image.
277
+
278
+ An inspected `MCP` object has two Spec tabs. The dashboard runs the server:
279
+
280
+ - server status, endpoint and port
219
281
  - debug mode
220
- - registered tools and descriptions
221
- - observability status
282
+ - every tool the server could run, with `Enabled` for whether it has the tool
283
+ at all and `Listed` for whether `tools/list` shows it; an unlisted tool is
284
+ still found by `tool_search` and still runs
285
+
286
+ The observability tab shows what the server recorded about itself:
287
+
222
288
  - per-tool timing metrics
223
289
  - traces for errors, outliers, and output overruns
224
290
  - recent logs
291
+ - auto-refresh while the tab is displayed
225
292
 
226
293
  MCP starts with the built-in JSON observability backend enabled. Disable it for
227
294
  a specific server when its local metrics, traces, and logs are not wanted:
@@ -251,5 +318,5 @@ mcp useOpenTelemetryObservability
251
318
 
252
319
  The core baseline loads PharoBackwardCompatibility, JRPC, and PCRE2.
253
320
  OpenTelemetry is loaded only by the optional `Telemetry` group. CI covers
254
- Pharo 12, 13, and 14. Code should target the Pharo 14 API; PharoBackwardCompatibility
255
- backports supported APIs to older images.
321
+ Pharo 12, 13, 14, and 15. Code should target the Pharo 14 API;
322
+ PharoBackwardCompatibility backports supported APIs to older images.