@evref-bl/pharo-mcp 0.0.0-stage → 1.4.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 +79 -2
- package/bin/pharo-mcp.js +22 -0
- package/node/index.js +1 -0
- package/node/installer.js +151 -0
- package/package.json +33 -4
- package/templates/.claude/mcp.json +8 -0
- package/templates/.codex/config.toml +4 -0
- package/templates/.opencode/opencode.json +10 -0
- package/templates/pharo-references/debugger-driven-development.md +101 -0
- package/templates/pharo-references/debugging.md +147 -0
- package/templates/pharo-references/getting-started.md +143 -0
- package/templates/pharo-references/pharo-coding-rules.md +147 -0
- package/templates/pharo-references/pharo-coding-style.md +139 -0
- package/templates/pharo-references/safety-and-ecosystem.md +256 -0
- package/templates/pharo-references/source-vs-live-image.md +75 -0
- package/templates/pharo-references/tool-reference.md +273 -0
- package/templates/pharo-references/troubleshooting.md +137 -0
- package/templates/pharo-references/using-pharo-mcp.md +156 -0
- package/templates/pharo-skills/pharo-ci-repro/SKILL.md +46 -0
- package/templates/pharo-skills/pharo-ci-repro/agents/openai.yaml +4 -0
- package/templates/pharo-skills/pharo-ci-repro/references/pharo-smalltalkci.md +102 -0
- package/templates/pharo-skills/pharo-ci-repro/scripts/run-smalltalkci-docker.sh +172 -0
- package/templates/pharo-skills/pharo-image-git-handoff/SKILL.md +37 -0
- package/templates/pharo-skills/pharo-image-git-handoff/agents/openai.yaml +4 -0
- package/templates/pharo-skills/pharo-mcp-recovery/SKILL.md +34 -0
- package/templates/pharo-skills/pharo-mcp-recovery/agents/openai.yaml +4 -0
- package/templates/pharo-skills/pharo-project-load/SKILL.md +47 -0
- package/templates/pharo-skills/pharo-project-load/agents/openai.yaml +4 -0
- package/templates/pharo-skills/pharo-version-compat/SKILL.md +57 -0
- package/templates/pharo-skills/pharo-version-compat/agents/openai.yaml +4 -0
- package/templates/pharo.AGENTS.md +42 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Getting Started
|
|
2
|
+
|
|
3
|
+
This is the canonical guide for loading MCP, starting its HTTP endpoint, and
|
|
4
|
+
connecting a client.
|
|
5
|
+
|
|
6
|
+
## Requirements
|
|
7
|
+
|
|
8
|
+
- Pharo 12, 13, or 14
|
|
9
|
+
- An MCP client that supports Streamable HTTP directly or through a local bridge
|
|
10
|
+
- Network access from the client to the image host
|
|
11
|
+
|
|
12
|
+
For local use, keep the image and client on the same machine and use
|
|
13
|
+
`127.0.0.1`.
|
|
14
|
+
|
|
15
|
+
## Load MCP
|
|
16
|
+
|
|
17
|
+
Evaluate in a supported image:
|
|
18
|
+
|
|
19
|
+
```smalltalk
|
|
20
|
+
Metacello new
|
|
21
|
+
baseline: 'MCP';
|
|
22
|
+
repository: 'github://Evref-BL/MCP:main/src';
|
|
23
|
+
load.
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
As a project dependency:
|
|
27
|
+
|
|
28
|
+
```smalltalk
|
|
29
|
+
spec
|
|
30
|
+
baseline: 'MCP'
|
|
31
|
+
with: [ spec repository: 'github://Evref-BL/MCP:main/src' ].
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Load Groups
|
|
35
|
+
|
|
36
|
+
The default load includes the server, optional UI, and their tests.
|
|
37
|
+
|
|
38
|
+
| Group | Contents |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| `default` | `Core`, `UI`, `Tests`, and `UI Tests` |
|
|
41
|
+
| `Core` | The `MCP` server package |
|
|
42
|
+
| `UI` | `MCP-UI` and its required core package |
|
|
43
|
+
| `Tests` | Core server tests and test resources |
|
|
44
|
+
| `UI Tests` | UI tests and their required test dependencies |
|
|
45
|
+
| `OpenTelemetry` | Optional OpenTelemetry backend |
|
|
46
|
+
| `all` | Every package, including the optional OpenTelemetry backend |
|
|
47
|
+
|
|
48
|
+
For a headless image, load only the core server:
|
|
49
|
+
|
|
50
|
+
```smalltalk
|
|
51
|
+
Metacello new
|
|
52
|
+
baseline: 'MCP';
|
|
53
|
+
repository: 'github://Evref-BL/MCP:main/src';
|
|
54
|
+
load: 'Core'.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Dependencies can select the same group with `loads: #( 'Core' )`.
|
|
58
|
+
|
|
59
|
+
## Start And Stop
|
|
60
|
+
|
|
61
|
+
```smalltalk
|
|
62
|
+
mcp := MCP new.
|
|
63
|
+
mcp port: 4000.
|
|
64
|
+
mcp start.
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Tool calls return canonical LLM-facing `content` by default. If a client or
|
|
68
|
+
integration needs programmatic payloads, configure the response fields before
|
|
69
|
+
starting:
|
|
70
|
+
|
|
71
|
+
```smalltalk
|
|
72
|
+
mcp useStructuredContentOnlyToolResponses.
|
|
73
|
+
mcp useContentAndStructuredContentToolResponses.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Inspect or control the server with:
|
|
77
|
+
|
|
78
|
+
```smalltalk
|
|
79
|
+
mcp localUrlString.
|
|
80
|
+
mcp isRunning.
|
|
81
|
+
mcp isListening.
|
|
82
|
+
mcp restart.
|
|
83
|
+
mcp stop.
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The server lives in the image and stops when the image exits.
|
|
87
|
+
|
|
88
|
+
## Connect A Client
|
|
89
|
+
|
|
90
|
+
The endpoint above is:
|
|
91
|
+
|
|
92
|
+
```text
|
|
93
|
+
http://127.0.0.1:4000
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Client configuration formats differ. Configure a Streamable HTTP MCP server
|
|
97
|
+
using the client documentation rather than copying another client's JSON.
|
|
98
|
+
Loopback addresses work only when the client connects from the local machine;
|
|
99
|
+
cloud-brokered connectors cannot reach `127.0.0.1`.
|
|
100
|
+
|
|
101
|
+
Install the supplied guide, local references, workflow skills, and direct MCP
|
|
102
|
+
configuration into the current agent project:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
npx @evref-bl/pharo-mcp install --host codex
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Use `--host claude` or `--host opencode` for those hosts. The direct MCP
|
|
109
|
+
configuration expects port `4000`; update it when the image uses another port.
|
|
110
|
+
|
|
111
|
+
## First Calls
|
|
112
|
+
|
|
113
|
+
Start with catalog discovery:
|
|
114
|
+
|
|
115
|
+
```text
|
|
116
|
+
tools/list
|
|
117
|
+
tool_search
|
|
118
|
+
tool_get
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Then inspect the image with focused read-only tools such as:
|
|
122
|
+
|
|
123
|
+
```text
|
|
124
|
+
package_search
|
|
125
|
+
class_search
|
|
126
|
+
class_get
|
|
127
|
+
method_metadata_search
|
|
128
|
+
method_source_search
|
|
129
|
+
method_implementor_search
|
|
130
|
+
method_sender_search
|
|
131
|
+
method_get
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Before mutation, inspect the target and use a copied or disposable image.
|
|
135
|
+
Prefer dedicated tools such as `class_create`, `method_compile`, refactoring
|
|
136
|
+
tools, and `test_run` over `image_evaluate`.
|
|
137
|
+
|
|
138
|
+
Continue with:
|
|
139
|
+
|
|
140
|
+
- [Using MCP from an agent](using-pharo-mcp.md)
|
|
141
|
+
- [Tool reference](tool-reference.md)
|
|
142
|
+
- [Safety and ecosystem integration](safety-and-ecosystem.md)
|
|
143
|
+
- [Troubleshooting](troubleshooting.md)
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Pharo Coding Rules For MCP Users
|
|
2
|
+
|
|
3
|
+
Applies when using MCP to inspect, write, review, or refactor Pharo source in
|
|
4
|
+
any project.
|
|
5
|
+
|
|
6
|
+
This file covers object-design and correctness-oriented rules. For
|
|
7
|
+
expression-level readability heuristics, also read
|
|
8
|
+
[Pharo coding style](pharo-coding-style.md).
|
|
9
|
+
|
|
10
|
+
## First Principle
|
|
11
|
+
|
|
12
|
+
Pharo code should communicate through messages and protocols. Prefer normal
|
|
13
|
+
dispatch over representation checks, class checks, reflective lookup, or
|
|
14
|
+
dynamic selector tricks.
|
|
15
|
+
|
|
16
|
+
## Dispatch Over Inspection
|
|
17
|
+
|
|
18
|
+
Do:
|
|
19
|
+
|
|
20
|
+
- send a domain message to the receiver;
|
|
21
|
+
- add or refine a protocol on the object that owns the behavior;
|
|
22
|
+
- use polymorphic collaborators, strategy objects, double dispatch, or visitors
|
|
23
|
+
when behavior varies by object role.
|
|
24
|
+
|
|
25
|
+
Avoid in application behavior:
|
|
26
|
+
|
|
27
|
+
- `class = ...`;
|
|
28
|
+
- `isKindOf:` and `isMemberOf:`;
|
|
29
|
+
- `respondsTo:` as control flow;
|
|
30
|
+
- `perform:` as a disguised switch;
|
|
31
|
+
- method dictionary or instance-variable reflection.
|
|
32
|
+
|
|
33
|
+
Reflection is acceptable for tools, proxies, compatibility shims, and explicit
|
|
34
|
+
framework boundaries. Keep reflective behavior isolated and named as tooling
|
|
35
|
+
or boundary behavior; do not spread it through ordinary domain logic.
|
|
36
|
+
|
|
37
|
+
## Tell, Do Not Ask
|
|
38
|
+
|
|
39
|
+
Do not pull state out of an object, compute externally, then push state back
|
|
40
|
+
when the object can own the behavior.
|
|
41
|
+
|
|
42
|
+
Prefer:
|
|
43
|
+
|
|
44
|
+
- `aCommand executeOn: aModel`;
|
|
45
|
+
- `aDocument writeOn: aStream`;
|
|
46
|
+
- `aPolicy accepts: anObject`.
|
|
47
|
+
|
|
48
|
+
over clients branching on concrete classes or internal fields.
|
|
49
|
+
|
|
50
|
+
## Object APIs, Not Data Bags
|
|
51
|
+
|
|
52
|
+
- Keep domain objects behavior-rich instead of using them only as data bags.
|
|
53
|
+
- Avoid dictionaries or arrays as internal domain models unless the data is
|
|
54
|
+
genuinely unstructured external input.
|
|
55
|
+
- If several clients repeat the same extraction and calculation, move the
|
|
56
|
+
behavior to the object with the knowledge.
|
|
57
|
+
- Avoid long message chains through internals; add a meaningful domain method.
|
|
58
|
+
|
|
59
|
+
## Small Methods And Hooks
|
|
60
|
+
|
|
61
|
+
- Extract meaningful steps into small named methods.
|
|
62
|
+
- Use self-send hooks when subclass or compatibility variation is plausible.
|
|
63
|
+
- Keep block bodies short; move domain logic from blocks into methods.
|
|
64
|
+
- Do not add wrappers that only rename obvious library calls unless the wrapper
|
|
65
|
+
captures a domain concept or extension hook.
|
|
66
|
+
- Trust collaborators first. Prefer direct sends to the documented protocol of
|
|
67
|
+
the object you were given; add adapters or project-specific extensions only
|
|
68
|
+
when the code truly accepts multiple concrete framework shapes or compatibility
|
|
69
|
+
differences.
|
|
70
|
+
- Be especially conservative with extensions on broad system classes such as
|
|
71
|
+
`Object`, `Behavior`, `String`, or `Exception`. They should model a real
|
|
72
|
+
boundary protocol, not hypothetical defense against wrong callers.
|
|
73
|
+
|
|
74
|
+
## Nil And Error Handling
|
|
75
|
+
|
|
76
|
+
- Return empty collections for "no elements".
|
|
77
|
+
- Use a null object when "do nothing" is valid behavior.
|
|
78
|
+
- Signal or return structured domain errors for exceptional cases.
|
|
79
|
+
- Do not use `nil` as a normal status code.
|
|
80
|
+
- Do not swallow broad `Error` silently.
|
|
81
|
+
- Catch the most specific exception class that matches the recovery policy.
|
|
82
|
+
- Use `ensure:` for cleanup.
|
|
83
|
+
|
|
84
|
+
## Initialization
|
|
85
|
+
|
|
86
|
+
- Instance-side `initialize` starts with `super initialize`.
|
|
87
|
+
- Initialize sensible defaults.
|
|
88
|
+
- Methods without an explicit return answer `self`. Do not add a trailing
|
|
89
|
+
`^ self` to initializers or mutators only to return the receiver; keep
|
|
90
|
+
explicit returns for early exits or non-self results.
|
|
91
|
+
- Do not redefine class-side `new` just to call `initialize`.
|
|
92
|
+
- Use class-side creation messages such as `on:`, `with:`, or domain-specific
|
|
93
|
+
constructors when required data exists.
|
|
94
|
+
- Use `basicNew` only when deliberately bypassing initialization.
|
|
95
|
+
|
|
96
|
+
## Names And Selectors
|
|
97
|
+
|
|
98
|
+
- Use domain vocabulary.
|
|
99
|
+
- Getter selector is the variable name; setter selector is `name:`.
|
|
100
|
+
- Do not use `getName` or `setName:`.
|
|
101
|
+
- Predicates should read as predicates: `isReady`, `hasErrors`,
|
|
102
|
+
`canHandle:`.
|
|
103
|
+
- Action selectors should use verbs: `parseRequest:`, `registerTool:`,
|
|
104
|
+
`writeResponseOn:`.
|
|
105
|
+
- Conversion selectors should start with `as`.
|
|
106
|
+
|
|
107
|
+
## Collections And Streams
|
|
108
|
+
|
|
109
|
+
- Prefer collection protocol such as `collect:`, `select:`, `reject:`,
|
|
110
|
+
`detect:ifNone:`, `inject:into:`, `anySatisfy:`, and `allSatisfy:`.
|
|
111
|
+
- Do not mutate a collection while iterating it unless iterating a copy is
|
|
112
|
+
intentional.
|
|
113
|
+
- Do not rely on `add:` answering the collection; use a variable or cascade
|
|
114
|
+
with `yourself`.
|
|
115
|
+
- Override `hash` when overriding `=`.
|
|
116
|
+
- Use `String streamContents:` or writer streams for string construction.
|
|
117
|
+
- Do not concatenate strings with `,` in loops or recursive code.
|
|
118
|
+
|
|
119
|
+
## Tests
|
|
120
|
+
|
|
121
|
+
- Add or update SUnit tests for behavior changes.
|
|
122
|
+
- Use `assert:equals:` for comparisons when possible.
|
|
123
|
+
- Use `deny:` for negative assertions.
|
|
124
|
+
- Use `should:raise:` and `shouldnt:raise:` with blocks for exception
|
|
125
|
+
behavior.
|
|
126
|
+
- Prefer focused tests around the public protocol.
|
|
127
|
+
- Use memory filesystems, fakes, or injected collaborators for unit tests when
|
|
128
|
+
possible.
|
|
129
|
+
- Keep live-image and external-state tests separate from source-only checks.
|
|
130
|
+
|
|
131
|
+
## Review Checklist
|
|
132
|
+
|
|
133
|
+
Before finishing a Pharo source change, scan for:
|
|
134
|
+
|
|
135
|
+
- class checks or reflection used as ordinary dispatch;
|
|
136
|
+
- `perform:` selector registries;
|
|
137
|
+
- normal control flow through `nil`;
|
|
138
|
+
- repeated client-side extraction from an object;
|
|
139
|
+
- long methods or blocks hiding named domain steps;
|
|
140
|
+
- project-specific extensions on broad system classes that only defend
|
|
141
|
+
hypothetical collaborators;
|
|
142
|
+
- missing `super initialize`;
|
|
143
|
+
- stream/file cleanup without `ensure:`;
|
|
144
|
+
- string concatenation in loops;
|
|
145
|
+
- overridden `=` without `hash`;
|
|
146
|
+
- broad exception handlers that hide failures;
|
|
147
|
+
- missing tests for changed public behavior.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Pharo Coding Style
|
|
2
|
+
|
|
3
|
+
Applies when writing or reviewing the shape of Pharo source code after loading
|
|
4
|
+
[Pharo coding rules](pharo-coding-rules.md).
|
|
5
|
+
|
|
6
|
+
## Goal
|
|
7
|
+
|
|
8
|
+
Keep Pharo code readable, scannable, and idiomatic. These are readability
|
|
9
|
+
heuristics, not mechanical laws. Prefer the shape that makes dependencies,
|
|
10
|
+
main operations, and exceptional paths easiest to understand.
|
|
11
|
+
|
|
12
|
+
## Main Send
|
|
13
|
+
|
|
14
|
+
- Make the main send easy to see. When both branches of a conditional perform
|
|
15
|
+
the same operation, lift the branch-invariant send out of the branches and
|
|
16
|
+
use the conditional only for the receiver or argument that varies.
|
|
17
|
+
- This applies to return expressions, assigned values, message arguments, and
|
|
18
|
+
nested expressions.
|
|
19
|
+
- Do not over-compress multi-step domain logic into one expression.
|
|
20
|
+
|
|
21
|
+
Prefer:
|
|
22
|
+
|
|
23
|
+
```smalltalk
|
|
24
|
+
result := self transform: (condition ifTrue: [ selectedValue ])
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
over duplicating the same `transform:` send inside both conditional branches.
|
|
28
|
+
|
|
29
|
+
## Guards
|
|
30
|
+
|
|
31
|
+
- Guard before dependent work. If `nil`, invalid bounds, failed lookup, or
|
|
32
|
+
missing capability exits early or returns a fallback, check it before sends,
|
|
33
|
+
computations, or mutations that assume the value is present.
|
|
34
|
+
- Keep the normal path visible. Use early returns for local exceptional or
|
|
35
|
+
fallback cases when they keep the main path low-indentation.
|
|
36
|
+
- Do not mechanically move every condition to the top. Choose the order that
|
|
37
|
+
makes dependencies and intent clearest.
|
|
38
|
+
- Prefer "win fast" when the successful case is tiny, obvious, and safe to
|
|
39
|
+
attempt before fallback work.
|
|
40
|
+
|
|
41
|
+
## Temporaries
|
|
42
|
+
|
|
43
|
+
- Prefer short supporting expressions for simple receiver or argument
|
|
44
|
+
computation.
|
|
45
|
+
- Use a temporary when the value has domain meaning, is reused, names an
|
|
46
|
+
important step, or helps debugging and review.
|
|
47
|
+
- Keep temporaries near their use.
|
|
48
|
+
|
|
49
|
+
## Collections
|
|
50
|
+
|
|
51
|
+
Common collection families, as a protocol reminder rather than a reason to
|
|
52
|
+
branch on concrete collection classes:
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
Collection
|
|
56
|
+
HashedCollection
|
|
57
|
+
Dictionary
|
|
58
|
+
Set
|
|
59
|
+
OrderedDictionary
|
|
60
|
+
SequenceableCollection
|
|
61
|
+
OrderedCollection
|
|
62
|
+
SortedCollection
|
|
63
|
+
ArrayedCollection
|
|
64
|
+
Array
|
|
65
|
+
String
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- Build the collection you mean to return. When the result type matters, use
|
|
69
|
+
messages such as `collect:as:`, `select:as:`, or `flatCollect:as:` instead
|
|
70
|
+
of collecting into one species and immediately converting to another.
|
|
71
|
+
- Avoid intermediate collections. Prefer fused messages such as
|
|
72
|
+
`select:thenCollect:` and `reject:thenCollect:` when filtering and
|
|
73
|
+
transforming. When a filtered or transformed collection exists only to feed
|
|
74
|
+
iteration, use `select:thenDo:`, `reject:thenDo:`, or `collect:thenDo:`.
|
|
75
|
+
Use `groupedBy:` for simple grouping.
|
|
76
|
+
- Prefer direct queries over filtered collections. Use `detect:ifNone:` for a
|
|
77
|
+
first match with fallback, and `anySatisfy:`, `allSatisfy:`, or
|
|
78
|
+
`noneSatisfy:` when asking a boolean question.
|
|
79
|
+
- Use streaming constructors such as `Array streamContents:` and
|
|
80
|
+
`String streamContents:` when code conditionally appends values or would
|
|
81
|
+
otherwise need a temporary `OrderedCollection`.
|
|
82
|
+
- Avoid conversion chains that exist only to sort or change species, such as
|
|
83
|
+
`asSortedCollection asArray`. Sort a `SequenceableCollection` in-place with
|
|
84
|
+
`sort`/`sort:`, or make a copy with `sorted`/`sorted:`.
|
|
85
|
+
|
|
86
|
+
## Conditions
|
|
87
|
+
|
|
88
|
+
- Avoid assignment inside boolean conditions. Conditions should decide control
|
|
89
|
+
flow, not also mutate state.
|
|
90
|
+
- Keep questions pure: predicates should answer questions, not mutate state.
|
|
91
|
+
- When the fallback value is `nil`, prefer a one-arm conditional. In Pharo,
|
|
92
|
+
`ifTrue:` answers `nil` when the condition is false, and `ifFalse:` answers
|
|
93
|
+
`nil` when the condition is true.
|
|
94
|
+
- Use `ifNotNil:` for local nil traversal when a boundary API can genuinely
|
|
95
|
+
return `nil` and the next step is asking the non-nil object for a value.
|
|
96
|
+
- Prefer presence-aware lookup messages over lookup-to-nil followed by a nil
|
|
97
|
+
check. Use `ifPresent:` or `ifPresent:ifAbsent:` variants when they keep the
|
|
98
|
+
present case local; add `ifAbsent: [ ]` when absence should be an explicit
|
|
99
|
+
no-op.
|
|
100
|
+
- Keep simple boolean predicates simple. Expressions such as
|
|
101
|
+
`value notNil and: [ value isReady ]` are idiomatic when the result is a
|
|
102
|
+
boolean. Do not rewrite them into `ifNil:/ifNotNil:` only to return a
|
|
103
|
+
boolean literal from one branch.
|
|
104
|
+
- Remove nil-only branches from nil traversal. Both `receiver ifNil: [ nil ]
|
|
105
|
+
ifNotNil: [ ... ]` and `receiver ifNotNil: [ ... ] ifNil: [ nil ]` should
|
|
106
|
+
normally become `receiver ifNotNil: [ ... ]`.
|
|
107
|
+
- Avoid defensive type or protocol checks in private helpers unless the helper
|
|
108
|
+
is an explicit boundary. Let incorrect callers fail or validate at the
|
|
109
|
+
boundary with a named policy.
|
|
110
|
+
- Prefer a direct send to a known collaborator over a defensive wrapper. Add a
|
|
111
|
+
wrapper or extension after concrete variation appears, not before.
|
|
112
|
+
|
|
113
|
+
## Review Smells
|
|
114
|
+
|
|
115
|
+
Scan for:
|
|
116
|
+
|
|
117
|
+
- duplicated sends in both conditional branches when only one receiver or
|
|
118
|
+
argument changes;
|
|
119
|
+
- dependent work performed before a guard proves the value is present or valid;
|
|
120
|
+
- assignment embedded inside boolean conditions;
|
|
121
|
+
- repeated `isNotNil` checks where `ifNotNil:` would express local nil
|
|
122
|
+
traversal;
|
|
123
|
+
- lookup with `ifAbsent: [ nil ]` followed by a nil check where an
|
|
124
|
+
`ifPresent:` variant can express the positive path directly;
|
|
125
|
+
- `ifNil:/ifNotNil:` expressions that return only `true` or `false` from one
|
|
126
|
+
branch and would read more directly as a boolean condition;
|
|
127
|
+
- `ifNil: [ nil ] ifNotNil: [...]` or `ifNotNil: [...] ifNil: [ nil ]`
|
|
128
|
+
branches where plain `ifNotNil:` communicates the same behavior;
|
|
129
|
+
- collection pipelines that allocate intermediate collections only to
|
|
130
|
+
immediately convert, sort, query emptiness, take a first match, or group
|
|
131
|
+
values manually;
|
|
132
|
+
- `select:`, `reject:`, or `collect:` immediately followed by `do:` when a
|
|
133
|
+
`thenDo:` variant would avoid the intermediate collection;
|
|
134
|
+
- sorting through conversion chains instead of sorting a result array directly;
|
|
135
|
+
- defensive type checks in private helpers that hide caller bugs;
|
|
136
|
+
- wrapper methods or extensions that exist only because a collaborator might be
|
|
137
|
+
wrong someday;
|
|
138
|
+
- dense nested expressions that would be clearer with a temporary or extracted
|
|
139
|
+
method.
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# Safety And Ecosystem Integration
|
|
2
|
+
|
|
3
|
+
MCP is safest when callers use the dedicated tools before falling back to raw
|
|
4
|
+
evaluation. The tools are built around Pharo's normal development systems, so an
|
|
5
|
+
agent works through image-aware operations instead of editing exported source
|
|
6
|
+
text blindly.
|
|
7
|
+
|
|
8
|
+
## Tool Boundary
|
|
9
|
+
|
|
10
|
+
Each tool owns its MCP metadata:
|
|
11
|
+
|
|
12
|
+
- name and title
|
|
13
|
+
- description
|
|
14
|
+
- icon
|
|
15
|
+
- input JSON schema
|
|
16
|
+
- output JSON schema
|
|
17
|
+
|
|
18
|
+
The execution path is:
|
|
19
|
+
|
|
20
|
+
1. The HTTP endpoint receives a JSON-RPC `tools/call`.
|
|
21
|
+
2. `MCPToolRequest` validates raw arguments against the tool input schema.
|
|
22
|
+
3. The concrete tool parses the request into a typed request or spec object.
|
|
23
|
+
4. The tool dispatches a command or query object.
|
|
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.
|
|
29
|
+
|
|
30
|
+
```mermaid
|
|
31
|
+
sequenceDiagram
|
|
32
|
+
participant Client
|
|
33
|
+
participant HTTP as HTTP Endpoint
|
|
34
|
+
participant Req as MCPToolRequest
|
|
35
|
+
participant Tool as Concrete Tool
|
|
36
|
+
participant Cmd as Command/Query
|
|
37
|
+
participant Pharo as Pharo Image
|
|
38
|
+
|
|
39
|
+
Client->>HTTP: JSON-RPC tools/call
|
|
40
|
+
HTTP->>Req: validate raw arguments
|
|
41
|
+
Req->>Req: check against tool input schema
|
|
42
|
+
alt invalid arguments
|
|
43
|
+
Req-->>HTTP: validation error
|
|
44
|
+
HTTP-->>Client: error response
|
|
45
|
+
else valid arguments
|
|
46
|
+
Req->>Tool: validated arguments
|
|
47
|
+
Tool->>Tool: parse into typed request/spec
|
|
48
|
+
Tool->>Cmd: dispatch command or query
|
|
49
|
+
Cmd->>Pharo: query or mutate image via Pharo APIs
|
|
50
|
+
Pharo-->>Cmd: result / side effect
|
|
51
|
+
Cmd-->>Tool: outcome
|
|
52
|
+
Tool-->>HTTP: structured content (status, summary, warnings, data/error)
|
|
53
|
+
HTTP-->>Client: JSON-RPC response
|
|
54
|
+
end
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
This keeps transport parsing, schema validation, image operations, and result
|
|
58
|
+
formatting in separate places.
|
|
59
|
+
|
|
60
|
+
## Refactorings
|
|
61
|
+
|
|
62
|
+
Class and method edits use Refactoring Browser and Refactoring Engine operations
|
|
63
|
+
where Pharo owns the behavior.
|
|
64
|
+
|
|
65
|
+
Examples include:
|
|
66
|
+
|
|
67
|
+
- class rename with `ReRenameClassRefactoring`
|
|
68
|
+
- class removal with `ReRemoveClassRefactoring`
|
|
69
|
+
- method rename with `ReRenameMethodRefactoring`
|
|
70
|
+
- argument add/remove with `RBAddParameterRefactoring` and
|
|
71
|
+
`RBRemoveParameterRefactoring`
|
|
72
|
+
- slot add, remove, rename, pull-up, and push-down with the corresponding
|
|
73
|
+
instance-variable refactorings
|
|
74
|
+
- method batch removal with `ReRemoveMethodsRefactoring`
|
|
75
|
+
|
|
76
|
+
When a refactoring raises `RBRefactoringWarning`, the default behavior is to
|
|
77
|
+
stop. The tool result includes:
|
|
78
|
+
|
|
79
|
+
```text
|
|
80
|
+
impactMessages
|
|
81
|
+
howToProceed
|
|
82
|
+
forceSupported: true
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Review the impact and rerun the same request with `force=true` only when the
|
|
86
|
+
warning is acceptable. When forced, the warning messages are returned in the
|
|
87
|
+
normal `warnings` array.
|
|
88
|
+
|
|
89
|
+
## Critiques
|
|
90
|
+
|
|
91
|
+
`method_compile` compiles method source in the image and returns selected Renraku
|
|
92
|
+
critiques in the structured result. It includes error-severity critiques and a
|
|
93
|
+
small set of non-error rules that are useful after automated edits, such as
|
|
94
|
+
excessive arguments, missing super sends, return in ensure, temporary variable
|
|
95
|
+
overrides, and unary accessing methods without returns.
|
|
96
|
+
|
|
97
|
+
Critiques include:
|
|
98
|
+
|
|
99
|
+
- Renraku rule class
|
|
100
|
+
- title
|
|
101
|
+
- description
|
|
102
|
+
- source interval when available
|
|
103
|
+
|
|
104
|
+
The method may compile successfully and still return critiques. Treat critiques
|
|
105
|
+
as follow-up review evidence, not as transport failures.
|
|
106
|
+
|
|
107
|
+
## Rewrite Preview And Confirmation
|
|
108
|
+
|
|
109
|
+
`method_rewrite` uses Smalltalk AST rewrite rules. Patterns use RB AST pattern
|
|
110
|
+
syntax, not regex.
|
|
111
|
+
|
|
112
|
+
The default mode is preview:
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"rules": [
|
|
117
|
+
{
|
|
118
|
+
"lhs": "`@receiver ifTrue: [ `@body ]",
|
|
119
|
+
"rhs": "`@receiver ifTrue: [ `@body ]"
|
|
120
|
+
}
|
|
121
|
+
],
|
|
122
|
+
"apply": false
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Preview mode returns calculated changes and a `changeSetHash`. Applying requires
|
|
127
|
+
the hash from a preview of the same request:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"rules": [
|
|
132
|
+
{
|
|
133
|
+
"lhs": "`@old",
|
|
134
|
+
"rhs": "`@new"
|
|
135
|
+
}
|
|
136
|
+
],
|
|
137
|
+
"packageNames": ["MyPackage"],
|
|
138
|
+
"apply": true,
|
|
139
|
+
"expectedChangeSetHash": 123456
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Applying to the whole image also requires `force=true`. Prefer an explicit
|
|
144
|
+
package, class, hierarchy, or method scope.
|
|
145
|
+
|
|
146
|
+
## Tests And Coverage
|
|
147
|
+
|
|
148
|
+
`test_run` runs SUnit classes or individual methods and returns structured test
|
|
149
|
+
results. Use `test_coverage_run` when the same test run should collect
|
|
150
|
+
CoverageCollector method and node coverage for an explicit method scope.
|
|
151
|
+
`test_run` deduplicates concrete test cases across a batch. Use
|
|
152
|
+
`selectedTestCount` for selected unique tests, `runCount` for non-skipped
|
|
153
|
+
executed tests, and `skippedCount` for skipped tests.
|
|
154
|
+
|
|
155
|
+
Coverage output includes method counts, node counts, uncovered methods,
|
|
156
|
+
partially covered methods, and optional covered method details. Use it after
|
|
157
|
+
edits to ask whether the relevant methods were exercised.
|
|
158
|
+
|
|
159
|
+
## Repository Work
|
|
160
|
+
|
|
161
|
+
MCP uses Iceberg for repository state. The repository tools can:
|
|
162
|
+
|
|
163
|
+
- list registered repositories and their branch, head, package, modified, and
|
|
164
|
+
remote metadata
|
|
165
|
+
- load Metacello baselines
|
|
166
|
+
- create image-side repository registrations or update their metadata,
|
|
167
|
+
including registrations for linked Git worktree checkouts
|
|
168
|
+
- inspect `workingCopyDiff`
|
|
169
|
+
- verify expected repository identity before edits or exports
|
|
170
|
+
- export image changes to Tonel files
|
|
171
|
+
- commit, fetch, pull, push, create branches, and switch branches
|
|
172
|
+
|
|
173
|
+
Use `repository_identity_verify` before edits or exports, and
|
|
174
|
+
`repository_change_list` before exporting or committing. Use
|
|
175
|
+
`repository_create`, `repository_attach`, and `repository_update` for repository
|
|
176
|
+
registration workflows. Export writes image changes to disk and updates the
|
|
177
|
+
Iceberg index; it does not stage or commit Git changes.
|
|
178
|
+
|
|
179
|
+
## Change History
|
|
180
|
+
|
|
181
|
+
MCP uses Epicea change history. `history_file_list` lists `.ombu`
|
|
182
|
+
files, and `history_entry_list` lists entries from the current history
|
|
183
|
+
or a selected file. `history_entry_apply` and `history_entry_revert` preview
|
|
184
|
+
selected entries, and perform the selected apply or revert only when
|
|
185
|
+
`confirm=true`.
|
|
186
|
+
|
|
187
|
+
Use this when recovering image-side changes or preparing a clean handoff from a
|
|
188
|
+
live image back to Tonel/Git.
|
|
189
|
+
|
|
190
|
+
## Debugging
|
|
191
|
+
|
|
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.
|
|
200
|
+
|
|
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.
|
|
204
|
+
|
|
205
|
+
## Evaluation Escape Hatch
|
|
206
|
+
|
|
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
|
|
209
|
+
exists.
|
|
210
|
+
|
|
211
|
+
Prefer a dedicated tool when one exists, because the dedicated tools validate
|
|
212
|
+
input, return structured result data, and often use safer Pharo APIs.
|
|
213
|
+
|
|
214
|
+
## Observability And UI
|
|
215
|
+
|
|
216
|
+
The Spec dashboard is available from an inspected `MCP` object. It shows:
|
|
217
|
+
|
|
218
|
+
- server status and port
|
|
219
|
+
- debug mode
|
|
220
|
+
- registered tools and descriptions
|
|
221
|
+
- observability status
|
|
222
|
+
- per-tool timing metrics
|
|
223
|
+
- traces for errors, outliers, and output overruns
|
|
224
|
+
- recent logs
|
|
225
|
+
|
|
226
|
+
MCP starts with the built-in JSON observability backend enabled. Disable it for
|
|
227
|
+
a specific server when its local metrics, traces, and logs are not wanted:
|
|
228
|
+
|
|
229
|
+
```smalltalk
|
|
230
|
+
mcp observabilityEnabled: false
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
By default, JSON observability exports under the image-local
|
|
234
|
+
`pharo-local/mcp/observability` directory. Configure
|
|
235
|
+
`mcp observabilityExportDirectory: aDirectory` to override that export root for
|
|
236
|
+
instance metadata, `logs.jsonl`, `metrics.json`, and `traces.jsonl`.
|
|
237
|
+
|
|
238
|
+
OpenTelemetry support is optional. Load the `OpenTelemetry` group, then enable
|
|
239
|
+
the OpenTelemetry backend for an MCP instance:
|
|
240
|
+
|
|
241
|
+
```smalltalk
|
|
242
|
+
Metacello new
|
|
243
|
+
baseline: 'MCP';
|
|
244
|
+
repository: 'github://Evref-BL/MCP:main/src';
|
|
245
|
+
load: 'OpenTelemetry'.
|
|
246
|
+
|
|
247
|
+
mcp useOpenTelemetryObservability
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Version Compatibility
|
|
251
|
+
|
|
252
|
+
The core baseline loads PharoCompatibility, JRPC, and PCRE2.
|
|
253
|
+
OpenTelemetry is loaded only by the optional `OpenTelemetry` group. CI covers
|
|
254
|
+
Pharo 12, 13, and 14. Code that depends on version-sensitive Pharo APIs should
|
|
255
|
+
go through PharoCompatibility rather than assuming the Pharo 13 API is present
|
|
256
|
+
everywhere.
|