pi-show-me 0.1.0-alpha.1
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/CONTEXT.md +54 -0
- package/LICENSE +202 -0
- package/README.md +74 -0
- package/bin/mcp-server.mjs +189 -0
- package/bin/render-visual.mjs +14 -0
- package/docs/acceptance.md +64 -0
- package/docs/expression-elements.md +57 -0
- package/docs/extensibility.md +60 -0
- package/docs/module-design.md +196 -0
- package/docs/native-forms.md +79 -0
- package/docs/primitive-contract-v0.1.md +83 -0
- package/docs/project-spec.md +87 -0
- package/docs/prototype-status.md +132 -0
- package/docs/quality-slice.md +66 -0
- package/extensions/show-me.js +67 -0
- package/package.json +50 -0
- package/src/compile-template.mjs +62 -0
- package/src/composition.mjs +216 -0
- package/src/forms/mermaid.mjs +91 -0
- package/src/forms/schemas.mjs +48 -0
- package/src/forms/text.mjs +138 -0
- package/src/hosts/chromium.mjs +158 -0
- package/src/index.mjs +7 -0
- package/src/layout.mjs +54 -0
- package/src/libraries/core.mjs +16 -0
- package/src/mermaid.mjs +142 -0
- package/src/render.mjs +188 -0
- package/src/show-me.mjs +187 -0
- package/src/spec.mjs +118 -0
package/CONTEXT.md
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# show-me-mcp
|
|
2
|
+
|
|
3
|
+
Domain vocabulary for helping agents choose and organize explanations while ensuring the quality of display artifacts.
|
|
4
|
+
|
|
5
|
+
## Language
|
|
6
|
+
|
|
7
|
+
**Expression intent**: What the reader needs to understand, including the relationships, order, ownership, and emphasis that must be preserved.
|
|
8
|
+
|
|
9
|
+
**Display form**: The structure used to express intent: pseudocode, text trees, Mermaid, diff, or HTML.
|
|
10
|
+
_Avoid_: Image type, terminal mode
|
|
11
|
+
|
|
12
|
+
**Expression element**: A semantic building block that helps an agent organize content, such as an entity, step, group, relation, branch, note, comparison, or emphasis.
|
|
13
|
+
_Avoid_: Coordinates, drawing controls
|
|
14
|
+
|
|
15
|
+
**Expression recipe**: A reference example that combines expression elements for a particular explanation task without requiring a single display form.
|
|
16
|
+
|
|
17
|
+
**Expression library**: A collection of domain-specific expression elements, recipes, and their documentation, supplied by the project or a user.
|
|
18
|
+
|
|
19
|
+
**Component library**: A collection of visual components and style resources for a display form. It can represent expression elements but is distinct from their semantic definitions.
|
|
20
|
+
|
|
21
|
+
**Display adaptation**: Rules mapping expression elements to a display form and its components, including supported capabilities and limitations.
|
|
22
|
+
|
|
23
|
+
**Extension contract**: The shared rules expression and component libraries follow when participating in discovery, validation, display, and quality checks.
|
|
24
|
+
|
|
25
|
+
**Display artifact**: The text, diagram, or page actually presented to the reader. A single display form can be delivered in different file formats.
|
|
26
|
+
_Avoid_: Display form
|
|
27
|
+
|
|
28
|
+
**Display environment**: The client that presents an artifact, together with constraints such as dimensions, fonts, and rendering capabilities.
|
|
29
|
+
|
|
30
|
+
**Display defect**: A layout problem that impedes understanding, including occlusion, overlap, clipping, overflow, or ambiguous connector endpoints.
|
|
31
|
+
|
|
32
|
+
**Automatic repair**: Adjusting layout to eliminate display defects while preserving expression intent.
|
|
33
|
+
|
|
34
|
+
**Quality check**: Assessing the readability and semantic fidelity of an actual display artifact in a specified environment.
|
|
35
|
+
|
|
36
|
+
**Quality boundary**: The range of input sizes and display environments in which display quality can currently be verified and guaranteed.
|
|
37
|
+
|
|
38
|
+
**Template**: Reusable organization rules for a recurring explanation task; these may reference expression recipes and elements.
|
|
39
|
+
|
|
40
|
+
## Existing diagram primitives
|
|
41
|
+
|
|
42
|
+
**VisualSpec**: A versioned specification describing a structured diagram.
|
|
43
|
+
|
|
44
|
+
**Stack**: An arrangement expressing explicit horizontal or vertical reading order without implying relationships.
|
|
45
|
+
|
|
46
|
+
**Group**: A grouping that expresses ownership or containment.
|
|
47
|
+
|
|
48
|
+
**Card**: An addressable entity or step in a diagram.
|
|
49
|
+
|
|
50
|
+
**Note**: A non-addressable annotation expressing an explanation, risk, or constraint.
|
|
51
|
+
|
|
52
|
+
**Relation**: An explicitly declared relationship between entities.
|
|
53
|
+
|
|
54
|
+
**Legend**: An explanation of the symbols, states, or visual markings used in a diagram.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# pi-show-me
|
|
2
|
+
|
|
3
|
+
Source repository: [alchemistklk/show-me-mcp](https://github.com/alchemistklk/show-me-mcp).
|
|
4
|
+
|
|
5
|
+
Help agents explain complex ideas clearly and automatically fix layout problems in the resulting artifacts.
|
|
6
|
+
|
|
7
|
+
The agent chooses the display form and organizes the content. The MCP handles layout, detects and repairs occlusion, overlap, text overflow, and connector conflicts, and verifies the final artifact. The intended workflow does not require agents or users to repeatedly adjust diagrams by hand.
|
|
8
|
+
|
|
9
|
+
## Project documentation
|
|
10
|
+
|
|
11
|
+
- [Project specification](docs/project-spec.md): goals, responsibilities, five display forms, quality assurance, and delivery scope.
|
|
12
|
+
- [Expression elements](docs/expression-elements.md): element meanings, use cases, and composition examples.
|
|
13
|
+
- [Extensibility](docs/extensibility.md): separation between user expression libraries, component libraries, and the core engine.
|
|
14
|
+
- [Module design](docs/module-design.md): the adopted design, seams, and incremental validation strategy.
|
|
15
|
+
- [First quality slice](docs/quality-slice.md): implemented HTML layout repair, expression libraries, and MCP tools.
|
|
16
|
+
- [Four built-in forms](docs/native-forms.md): input, repair, and delivery contracts for Mermaid, pseudocode, text trees, and diff.
|
|
17
|
+
- [Acceptance criteria](docs/acceptance.md): quality checks, failure examples, existing evidence, and upcoming milestones.
|
|
18
|
+
- [Domain glossary](CONTEXT.md): shared project terminology.
|
|
19
|
+
- [Existing prototype](docs/prototype-status.md): operation and limitations.
|
|
20
|
+
- [Primitive contract v0.1](docs/primitive-contract-v0.1.md): compatibility reference for the existing interface.
|
|
21
|
+
|
|
22
|
+
## Goals and current status
|
|
23
|
+
|
|
24
|
+
| Goal | Current implementation |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| Five forms: pseudocode, text trees, Mermaid, diff, and HTML | All five are available through the new interface. HTML supports declarative libraries; the other four are built-in capabilities, each with a defined support scope. |
|
|
27
|
+
| Automatic layout repair inside the MCP | HTML label avoidance, Mermaid reflow and reinspection, text wrapping by display width, and diff display formatting are implemented. Arbitrarily complex diagrams are not guaranteed to be repairable. |
|
|
28
|
+
| Final display quality verification | HTML and Mermaid artifacts are verified in Chromium; text forms validate width and content preservation. Evidence records the verification scope and content hashes. |
|
|
29
|
+
| Public repository and Pi plugin distribution | The repository is public on GitHub. The native Pi extension is distributed as `pi-show-me` on npm. |
|
|
30
|
+
|
|
31
|
+
PNG is an optional artifact format, not a core display category. The existing `terminal | image | both` options and PNG fallback belong to the legacy prototype, not the target design.
|
|
32
|
+
|
|
33
|
+
## Install in Pi
|
|
34
|
+
|
|
35
|
+
The native Pi entry registers `describe_display` and `render_display` directly, without an MCP adapter. The alpha package is published on npm. Install it with `pi install npm:pi-show-me@alpha`. To try this checkout:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pi install /absolute/path/to/show-me-mcp
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Disable duplicate tools from an existing MCP adapter before enabling the native extension. Reload Pi after installation.
|
|
42
|
+
|
|
43
|
+
Artifacts are saved under `.pi/artifacts/show-me` in the current project. Override this with `SHOW_ME_ARTIFACT_DIR`. Text layout uses the current terminal width, or `SHOW_ME_TERMINAL_COLUMNS` when set; supported widths are 24–240 columns. Non-interactive sessions default to 120 columns. HTML and Mermaid return file paths; text forms also return a fenced preview. Diff keeps the applicable patch separate from its wrapped preview.
|
|
44
|
+
|
|
45
|
+
The npm package also exposes `show-me-mcp` as a stdio MCP command. Pi exposes only the two current tools; the MCP command retains legacy `render_visual` support.
|
|
46
|
+
|
|
47
|
+
## Run locally
|
|
48
|
+
|
|
49
|
+
Node.js and npm are required. Text trees, pseudocode, and diff do not need a browser. HTML, Mermaid, and the full test suite require a local Chrome or Chromium executable, which can be specified with `SHOW_ME_CHROMIUM_BIN`. The legacy image path also requires `rsvg-convert`. The project does not automatically download a browser or use your personal browser profile.
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
npm ci
|
|
53
|
+
npm test
|
|
54
|
+
npm run render:fixture
|
|
55
|
+
npm run render:composition
|
|
56
|
+
npm run render:quality-demo
|
|
57
|
+
npm run render:native-demo
|
|
58
|
+
node bin/mcp-server.mjs
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
If your machine uses the `with-env` environment wrapper, prefix the commands with it. Examples write their artifacts to `artifacts/`. Local Pi configuration, tool caches, dependencies, and generated artifacts are excluded from Git.
|
|
62
|
+
|
|
63
|
+
The MCP tools `describe_display` and `render_display` map to `describe` and `render`, supporting `html | mermaid | pseudocode | tree | diff`. Query a form's schema and examples before using an unfamiliar input format. Only HTML accepts expression-library references. The legacy `render_visual` tool remains available for compatibility; see the [prototype guide](docs/prototype-status.md) for its inputs.
|
|
64
|
+
|
|
65
|
+
Licensed under [Apache-2.0](LICENSE). The first npm release is `0.1.0-alpha.1` (tag: `alpha`).
|
|
66
|
+
|
|
67
|
+
## Migrating from show-me-mcp
|
|
68
|
+
|
|
69
|
+
The npm package has been renamed to `pi-show-me`. The repository and MCP command retain the name `show-me-mcp`. Replace the old Pi package and reload Pi:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pi remove npm:show-me-mcp
|
|
73
|
+
pi install npm:pi-show-me@alpha
|
|
74
|
+
```
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createInterface } from "node:readline";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { writeFile, mkdir } from "node:fs/promises";
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
7
|
+
import { compositionInputSchema, renderMermaid, renderToFiles, visualSpecInputSchema, createShowMe, displayRequestSchema, catalogQuerySchema } from "../src/index.mjs";
|
|
8
|
+
import { createChromiumHost } from "../src/hosts/chromium.mjs";
|
|
9
|
+
|
|
10
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
const defaultArtifacts = path.resolve(process.env.SHOW_ME_ARTIFACT_DIR ?? path.resolve(here, "../artifacts"));
|
|
12
|
+
const textOptions = { terminalColumns: Number(process.env.SHOW_ME_TERMINAL_COLUMNS ?? 120) };
|
|
13
|
+
const catalog = createShowMe(textOptions);
|
|
14
|
+
let displayHost;
|
|
15
|
+
let displayEngine;
|
|
16
|
+
|
|
17
|
+
async function closeDisplayHost() { await displayHost?.close(); }
|
|
18
|
+
process.once("SIGTERM", () => { closeDisplayHost().finally(() => process.exit(0)); });
|
|
19
|
+
process.once("SIGINT", () => { closeDisplayHost().finally(() => process.exit(0)); });
|
|
20
|
+
|
|
21
|
+
function send(message) {
|
|
22
|
+
process.stdout.write(`${JSON.stringify(message)}\n`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function result(id, value) {
|
|
26
|
+
send({ jsonrpc: "2.0", id, result: value });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function error(id, code, message) {
|
|
30
|
+
send({ jsonrpc: "2.0", id, error: { code, message } });
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function fencedText(text) {
|
|
34
|
+
const longest = Math.max(0, ...[...text.matchAll(/`+/g)].map(m => m[0].length));
|
|
35
|
+
const fence = "`".repeat(Math.max(3, longest + 1));
|
|
36
|
+
return `${fence}text\n${text}\n${fence}`;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function handle(request) {
|
|
40
|
+
const { id, method, params = {} } = request;
|
|
41
|
+
if (method === "initialize") {
|
|
42
|
+
result(id, {
|
|
43
|
+
protocolVersion: "2025-11-25",
|
|
44
|
+
capabilities: { tools: { listChanged: false } },
|
|
45
|
+
serverInfo: { name: "show-me-mcp", version: "0.0.0-prototype" },
|
|
46
|
+
});
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (method === "notifications/initialized") return;
|
|
50
|
+
if (method === "ping") {
|
|
51
|
+
result(id, {});
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (method === "tools/list") {
|
|
55
|
+
result(id, {
|
|
56
|
+
tools: [
|
|
57
|
+
{
|
|
58
|
+
name: "render_visual",
|
|
59
|
+
title: "Render structured visual",
|
|
60
|
+
description: "Legacy template/primitive renderer for terminal Mermaid and image artifacts. Prefer render_display for the verified five-form interface; this tool retains the original compatibility behavior.",
|
|
61
|
+
inputSchema: {
|
|
62
|
+
type: "object",
|
|
63
|
+
additionalProperties: false,
|
|
64
|
+
required: ["spec"],
|
|
65
|
+
properties: {
|
|
66
|
+
spec: { anyOf: [visualSpecInputSchema, compositionInputSchema] },
|
|
67
|
+
outputName: { type: "string", description: "Safe artifact basename without an extension." },
|
|
68
|
+
presentation: {
|
|
69
|
+
type: "string",
|
|
70
|
+
enum: ["terminal", "image", "both"],
|
|
71
|
+
default: "image",
|
|
72
|
+
description: "terminal returns fenced Mermaid; image returns PNG; both returns both presentations.",
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
{ name: "describe_display", description: "Discover native Mermaid flowcharts, pseudocode, text trees and diff schemas, plus extensible HTML elements. Only HTML uses expression libraries.", inputSchema: catalogQuerySchema },
|
|
78
|
+
{ name: "render_display", description: "Render and verify HTML, Mermaid flowcharts, pseudocode, text trees or diff. Automatically repair layout within declared limits; preserve semantics and selected form. Text forms need no browser; HTML and Mermaid require local Chromium. Diff delivers an applicable patch separately from its wrapped display. Only HTML accepts external elements.", inputSchema: displayRequestSchema },
|
|
79
|
+
],
|
|
80
|
+
});
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (method === "tools/call") {
|
|
84
|
+
if (["describe_display", "render_display"].includes(params.name)) {
|
|
85
|
+
try {
|
|
86
|
+
let value;
|
|
87
|
+
const content = [];
|
|
88
|
+
if (params.name === "describe_display") value = await catalog.describe(params.arguments ?? {});
|
|
89
|
+
else {
|
|
90
|
+
// Input/capability errors do not require launching a browser.
|
|
91
|
+
value = await catalog.render(params.arguments);
|
|
92
|
+
if (value.reason === "environment-unavailable") {
|
|
93
|
+
try {
|
|
94
|
+
if (!displayEngine) {
|
|
95
|
+
displayHost = await createChromiumHost();
|
|
96
|
+
displayEngine = createShowMe({ host: displayHost, ...textOptions });
|
|
97
|
+
}
|
|
98
|
+
value = await displayEngine.render(params.arguments);
|
|
99
|
+
} catch (caught) {
|
|
100
|
+
value = { ...value, details: caught instanceof Error ? caught.message : String(caught) };
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (value.status === "ready") {
|
|
104
|
+
const base = path.join(defaultArtifacts, `display-${randomUUID()}`);
|
|
105
|
+
const extension = { html: "html", mermaid: "svg", tree: "txt", pseudocode: "txt", diff: "diff" }[value.artifact.form];
|
|
106
|
+
const artifactPath = `${base}.${extension}`;
|
|
107
|
+
await mkdir(defaultArtifacts, { recursive: true });
|
|
108
|
+
await writeFile(artifactPath, value.artifact.content, "utf8");
|
|
109
|
+
const artifact = { form: value.artifact.form, mimeType: value.artifact.mimeType, path: artifactPath };
|
|
110
|
+
if (value.artifact.source) {
|
|
111
|
+
await writeFile(`${base}.mmd`, value.artifact.source.content, "utf8");
|
|
112
|
+
artifact.source = { mimeType: value.artifact.source.mimeType, path: `${base}.mmd` };
|
|
113
|
+
}
|
|
114
|
+
if (value.artifact.presentation) {
|
|
115
|
+
await writeFile(`${base}.display.txt`, value.artifact.presentation.content, "utf8");
|
|
116
|
+
artifact.presentation = { path: `${base}.display.txt`, notice: value.artifact.presentation.notice };
|
|
117
|
+
}
|
|
118
|
+
if (["tree", "pseudocode", "diff"].includes(artifact.form)) {
|
|
119
|
+
const text = value.artifact.presentation?.content ?? value.artifact.content;
|
|
120
|
+
if (text.length <= 24000) content.push({ type: "text", text: (value.artifact.presentation?.notice ? `${value.artifact.presentation.notice}\n\n` : "") + fencedText(text) });
|
|
121
|
+
}
|
|
122
|
+
value = { ...value, artifact };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
content.push({ type: "text", text: JSON.stringify(value) });
|
|
126
|
+
result(id, { content, structuredContent: value, isError: value.status === "not-ready" });
|
|
127
|
+
} catch (caught) {
|
|
128
|
+
result(id, { content: [{ type: "text", text: caught instanceof Error ? caught.message : String(caught) }], isError: true });
|
|
129
|
+
}
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (params.name !== "render_visual") {
|
|
133
|
+
error(id, -32602, `unknown tool: ${params.name}`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
try {
|
|
137
|
+
const args = params.arguments ?? {};
|
|
138
|
+
const outputName = String(args.outputName ?? `visual-${Date.now()}`)
|
|
139
|
+
.replace(/[^a-zA-Z0-9_-]+/g, "-")
|
|
140
|
+
.replace(/^-+|-+$/g, "") || "visual";
|
|
141
|
+
const requestedPresentation = args.presentation ?? "image";
|
|
142
|
+
if (!["terminal", "image", "both"].includes(requestedPresentation)) throw new TypeError("presentation must be terminal, image, or both");
|
|
143
|
+
const rendered = await renderToFiles(args.spec, path.join(defaultArtifacts, outputName));
|
|
144
|
+
const terminal = requestedPresentation === "terminal" || requestedPresentation === "both" ? renderMermaid(args.spec) : null;
|
|
145
|
+
const fallback = terminal?.diagnostics.terminal.fallbackRecommended ?? false;
|
|
146
|
+
const presentation = fallback ? "image" : requestedPresentation;
|
|
147
|
+
const structuredContent = {
|
|
148
|
+
presentation,
|
|
149
|
+
requestedPresentation,
|
|
150
|
+
pngPath: rendered.pngPath,
|
|
151
|
+
svgPath: rendered.svgPath,
|
|
152
|
+
...(terminal ? { mermaidDiagnostics: terminal.diagnostics } : {}),
|
|
153
|
+
...(terminal && !fallback ? { mermaid: terminal.mermaid } : {}),
|
|
154
|
+
diagnostics: rendered.diagnostics,
|
|
155
|
+
};
|
|
156
|
+
const content = [];
|
|
157
|
+
if (terminal && !fallback) content.push({ type: "text", text: `\`\`\`mermaid\n${terminal.mermaid}\n\`\`\`` });
|
|
158
|
+
if (presentation === "image" || presentation === "both") {
|
|
159
|
+
content.push({ type: "image", data: rendered.png.toString("base64"), mimeType: "image/png" });
|
|
160
|
+
}
|
|
161
|
+
content.push({ type: "text", text: JSON.stringify(structuredContent) });
|
|
162
|
+
result(id, {
|
|
163
|
+
content,
|
|
164
|
+
structuredContent,
|
|
165
|
+
isError: false,
|
|
166
|
+
});
|
|
167
|
+
} catch (caught) {
|
|
168
|
+
result(id, {
|
|
169
|
+
content: [{ type: "text", text: caught instanceof Error ? caught.message : String(caught) }],
|
|
170
|
+
isError: true,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (id !== undefined) error(id, -32601, `method not found: ${method}`);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const lines = createInterface({ input: process.stdin, crlfDelay: Infinity });
|
|
179
|
+
try {
|
|
180
|
+
for await (const line of lines) {
|
|
181
|
+
if (!line.trim()) continue;
|
|
182
|
+
try {
|
|
183
|
+
await handle(JSON.parse(line));
|
|
184
|
+
} catch (caught) {
|
|
185
|
+
console.error(caught);
|
|
186
|
+
error(null, -32700, "parse error");
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
} finally { await closeDisplayHost(); }
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { renderToFiles } from "../src/index.mjs";
|
|
5
|
+
|
|
6
|
+
const [inputPath, outputBase] = process.argv.slice(2);
|
|
7
|
+
if (!inputPath || !outputBase) {
|
|
8
|
+
console.error("usage: node bin/render-visual.mjs <visual-spec.json> <output-base>");
|
|
9
|
+
process.exit(2);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const spec = JSON.parse(await readFile(path.resolve(inputPath), "utf8"));
|
|
13
|
+
const result = await renderToFiles(spec, outputBase);
|
|
14
|
+
console.log(JSON.stringify({ svgPath: result.svgPath, pngPath: result.pngPath, diagnostics: result.diagnostics }, null, 2));
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Quality and acceptance criteria
|
|
2
|
+
|
|
3
|
+
Status: target acceptance specification, 2026-09-08. All five forms have limited-scope implementations and tests; this does not establish quality guarantees for arbitrary inputs or every client.
|
|
4
|
+
|
|
5
|
+
## Common gates
|
|
6
|
+
|
|
7
|
+
- Semantic fidelity: preserve identities, endpoints, relation types and directions, groups, and reading order; do not silently omit or truncate content.
|
|
8
|
+
- Complete text: no container clipping or unreadable overlap; measure long text and mixed English/Chinese content for the display environment.
|
|
9
|
+
- Clear graphics: labels must not obscure arrows, connectors must not cross unrelated nodes, and endpoints must be identifiable. Necessary crossings should be distinguishable; do not promise zero crossings for arbitrary graphs.
|
|
10
|
+
- Correct form: layout must not change tree hierarchy, pseudocode branch ownership, or diff addition/deletion semantics.
|
|
11
|
+
- Explicit environment: record the renderer, dimensions, fonts, and other conditions affecting the result.
|
|
12
|
+
- Terminating repair: the loop has a budget; distinguish passing, failing, and unsupported cases.
|
|
13
|
+
- Reproducibility: identical inputs and environments produce stable results; record initial defects, repairs, and final checks.
|
|
14
|
+
|
|
15
|
+
## Failure examples and existing evidence
|
|
16
|
+
|
|
17
|
+
| Example | Expected result | Current evidence / gap |
|
|
18
|
+
| --- | --- | --- |
|
|
19
|
+
| Card ID is `note-1` or `derived-legend` | Arrows point only to the Card | Endpoint-collision regression in `test/render.test.mjs` |
|
|
20
|
+
| Relation labels contain `&`, `"`, `|`, or Chinese text | No lost relations or invented nodes | Text-preservation checks for four relation kinds in `test/mermaid.test.mjs` |
|
|
21
|
+
| Card/Relation IDs contain surrounding whitespace | Endpoints remain consistent after normalization | Covered by Mermaid regressions |
|
|
22
|
+
| Horizontal flow between Cards of different heights | No meaningless short dogleg | `fixtures/horizontal-dogleg-regression.json` and horizontal-connector tests |
|
|
23
|
+
| A Stack directly contains another Stack | Reading direction and structure are preserved | The legacy path diagnoses and falls back to PNG; automatic Mermaid repair for this input remains incomplete |
|
|
24
|
+
| Complex diagrams reach 176/360 columns | Automatic repair and acceptance in the declared environment | Reproducible with the two complex fixtures; the legacy path only detects width and falls back |
|
|
25
|
+
| A label covers an arrow | Automatic avoidance makes both readable | HTML sequence tests in `test/show-me.test.mjs` verify single-call repair and final HTML reinspection; general routing remains incomplete |
|
|
26
|
+
| Connectors cross unrelated nodes / nodes overlap | Automatic avoidance, spacing adjustments, and reinspection | Native Mermaid has geometry checks and bounded reflow; path checks are sampled, not a guarantee for arbitrary graphs |
|
|
27
|
+
| Long labels, mixed-language widths, deep trees | Full text and hierarchy survive | Text-tree tests cover Unicode grapheme wrapping, hierarchy prefixes, reconstruction, and explicit limit failures |
|
|
28
|
+
| Pseudocode branches and long diff lines | No branch-ownership or addition/deletion changes | Pseudocode tests cover nested branches and loops; diff tests cover patch application and a separate wrapped view |
|
|
29
|
+
| Complex HTML in narrow and wide windows | No clipping or occlusion; relationships remain clear | Simple HTML sequences are verified; complex responsive layout is not implemented |
|
|
30
|
+
|
|
31
|
+
Run `npm test`. The current baseline has 31 local tests covering legacy MCP, HTML, the four built-in forms, and delivered files. The full suite requires local Chromium and runs test files serially to prevent browser/rasterizer contention from causing protocol timeouts. Test count is not a completion metric.
|
|
32
|
+
|
|
33
|
+
## Record for each acceptance run
|
|
34
|
+
|
|
35
|
+
1. Input fixture, selected form, and required semantic invariants.
|
|
36
|
+
2. Display environment and tool versions.
|
|
37
|
+
3. Initial defects and reproducible checks.
|
|
38
|
+
4. Repairs actually performed and budget consumed.
|
|
39
|
+
5. Final artifact, automated checks, and any necessary visual review.
|
|
40
|
+
6. Whether the agent had to intervene in layout, plus remaining limitations.
|
|
41
|
+
|
|
42
|
+
Mark unverified surfaces as UNKNOWN. A PNG file does not establish visual acceptance; a passing Pi parser does not establish an interactive Pi window check; local tests do not establish CI, release, or all-client acceptance.
|
|
43
|
+
|
|
44
|
+
## Extension acceptance
|
|
45
|
+
|
|
46
|
+
The following are extension goals. Current tests cover adding/removing the declarative example library, shared validation, discovery, duplicate identities, missing elements, and input schemas. Arbitrary UI components, resource changes, dynamic loading, and cross-client reproduction remain uncovered:
|
|
47
|
+
|
|
48
|
+
- Register, discover, use, and remove an example library outside the core source without modifying the engine.
|
|
49
|
+
- Default and example libraries use the same contract and quality workflow; one artifact can combine elements from both.
|
|
50
|
+
- Namespaces distinguish same-named elements. Missing libraries or incompatible versions produce explicit errors rather than substitution.
|
|
51
|
+
- Agents can discover custom element meanings, constraints, examples, and supported forms. Unsupported forms are not presented as supported.
|
|
52
|
+
- Long labels, font loading, or dimension changes in user components trigger measurement and avoidance again; third-party components cannot bypass final checks.
|
|
53
|
+
- Unmeasurable components, unsuccessful repairs, or unsupported environments cannot receive a quality pass.
|
|
54
|
+
- Record library, adaptation, and core versions; results must be reproducible for fixed inputs and environments.
|
|
55
|
+
|
|
56
|
+
## Implementation sequence
|
|
57
|
+
|
|
58
|
+
1. Complete the failure examples and define supported input sizes and environments. Turn pending examples into checks that can fail. Validate the extension seam with an independent library rather than hard-coding the default catalog.
|
|
59
|
+
2. Establish a complete detect → repair → recheck loop for the first selected defects, such as label occlusion, text overflow, or node overlap.
|
|
60
|
+
3. Extend each of the five forms with recipes, checks, repair strategies, and final display evidence.
|
|
61
|
+
4. Define verifiable Pi and desktop display paths and test client differences.
|
|
62
|
+
5. Complete remaining license, package-release, and Pi plugin distribution work. The repository is already public on GitHub.
|
|
63
|
+
|
|
64
|
+
This specification does not assume one layout engine for every form or PNG/Mermaid as the only artifact format.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Expression elements and recipes
|
|
2
|
+
|
|
3
|
+
Status: agreed first-batch expression references. These are semantic terms, not a newly implemented input schema, and need not map one-to-one to existing diagram primitives.
|
|
4
|
+
|
|
5
|
+
This catalog provides expression references and a starting point for the default HTML library. HTML users may supply their own elements, recipes, and component mappings under the [extension contract](extensibility.md). Mermaid, pseudocode, text trees, and diff use built-in native structures only, with no external expression libraries.
|
|
6
|
+
|
|
7
|
+
## Element catalog
|
|
8
|
+
|
|
9
|
+
| Element | Meaning and use cases | Composition example |
|
|
10
|
+
| --- | --- | --- |
|
|
11
|
+
| Entity / step | A system, role, operation, or capability | Client and server; send request and handle response |
|
|
12
|
+
| Group | Ownership, containment, stage, or responsibility | Group authentication and request handling under the server |
|
|
13
|
+
| Relation | A call, dependency, data flow, or feedback | Client calls server; failure feeds back to a retry step |
|
|
14
|
+
| Branch | An explicit condition and its outcome | Finish on success; retry on failure while below the limit |
|
|
15
|
+
| Note | An explanation, constraint, risk, or conclusion | At most 3 retries; the note is not a request recipient |
|
|
16
|
+
| Comparison / change | A before-and-after difference or alternative | The old flow fails immediately; the new flow adds bounded retries |
|
|
17
|
+
| Emphasis | A focus, critical path, or important object | Emphasize the retry limit without treating it as a new state |
|
|
18
|
+
|
|
19
|
+
Grouping creates no relationship; spatial order creates no causality; emphasis creates no business state. The agent must declare semantics explicitly.
|
|
20
|
+
|
|
21
|
+
## Recipe: explain failure and retry
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
Steps: send request → handle request
|
|
25
|
+
Branch: success / failure
|
|
26
|
+
Feedback: failure below the retry limit → send again
|
|
27
|
+
Note: at most 3 retries
|
|
28
|
+
Emphasis: retry limit
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Use pseudocode to explain logic, Mermaid to explain interactions, or diff to explain the change that introduced retries. One recipe does not mandate a single form. The tool must retain conditions and limits rather than omit them to simplify the diagram.
|
|
32
|
+
|
|
33
|
+
## Recipe: explain module responsibilities
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
Groups: client / server
|
|
37
|
+
Entities: page, request entry point, permission check
|
|
38
|
+
Relations: page calls entry point; entry point depends on permission check
|
|
39
|
+
Note: permission failure prevents further processing
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Use a text tree when explaining ownership alone and Mermaid when explaining calls. A text tree should not disguise a call relationship as directory containment.
|
|
43
|
+
|
|
44
|
+
## Recipe: explain a change
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
Comparison: before / after
|
|
48
|
+
Steps: save → return result
|
|
49
|
+
Change: check whether content has changed before saving
|
|
50
|
+
Emphasis: return the cache immediately when unchanged
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Use diff for small changes, retaining enough original steps to identify the context. Choose HTML when several interactive states are needed. Automatic wrapping must not change diff markers or the meaning of original lines.
|
|
54
|
+
|
|
55
|
+
## Relationship to the prototype
|
|
56
|
+
|
|
57
|
+
Existing Card, Group, Relation, and Note primitives can represent some of these elements; Stack specifies reading order and layout constraints. Cross-form interfaces for branches, comparison, and emphasis are not yet finalized. Do not mistake this catalog for the current MCP tool parameter schema.
|