@loomweaver/mcp 0.7.2 → 0.7.3
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 +0 -4
- package/dist/main.mjs +161 -67
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,10 +14,6 @@ is not inside this repo (a chat assistant, a remote client) can scaffold and val
|
|
|
14
14
|
|
|
15
15
|
## Consume from npm (product repos)
|
|
16
16
|
|
|
17
|
-
> **Availability:** the `@loomweaver/*` packages are not on the public npm registry yet — the first
|
|
18
|
-
> public release publishes them. Until then they come from LoomWeaver's own package feed, and
|
|
19
|
-
> `npx` needs that registry configured for the `@loomweaver` scope.
|
|
20
|
-
|
|
21
17
|
`@loomweaver/mcp` ships as a self-contained bundle (devkit + the MCP SDK are inlined — no transitive
|
|
22
18
|
install). A product repo that already consumes `@loomweaver/shell` / `@loomweaver/plugin-sdk` just adds the
|
|
23
19
|
server to its `.mcp.json`; `npx` fetches the bundle and starts the stdio server:
|
package/dist/main.mjs
CHANGED
|
@@ -31012,6 +31012,36 @@ function generate(recipe, input) {
|
|
|
31012
31012
|
}
|
|
31013
31013
|
return files;
|
|
31014
31014
|
}
|
|
31015
|
+
function amendments(recipe, input) {
|
|
31016
|
+
return recipe.amend?.(input) ?? [];
|
|
31017
|
+
}
|
|
31018
|
+
|
|
31019
|
+
// ../devkit/src/lib/amend/describe.ts
|
|
31020
|
+
function describeAmendment(amendment) {
|
|
31021
|
+
if (amendment.kind === "postcss") {
|
|
31022
|
+
return `Write ${amendment.file} beside your package.json, naming ${amendment.plugin}. Without it the stylesheet is read as plain CSS: no utility class is emitted, the workbench renders unstyled, and the build still reports success.`;
|
|
31023
|
+
}
|
|
31024
|
+
if (amendment.kind === "stylesheet-source") {
|
|
31025
|
+
return `Add an @source entry for '${amendment.sourceRoot}' to the application's entry stylesheet, resolved from that stylesheet. Without it none of that code's utilities are emitted.`;
|
|
31026
|
+
}
|
|
31027
|
+
if (amendment.kind === "compose-plugin") {
|
|
31028
|
+
return `Register ${amendment.id} in the composition root: import { ${amendment.symbol} }, provideTranslationNamespaces('${amendment.id}'), provideCapabilityGrants({ ${amendment.id}: [${amendment.capabilities.map((capability) => `'${capability}'`).join(
|
|
31029
|
+
", "
|
|
31030
|
+
)}] }) and ...providePlugins(${amendment.symbol}). Without it none of its contributions appear.`;
|
|
31031
|
+
}
|
|
31032
|
+
return [
|
|
31033
|
+
...amendment.styles.length > 0 ? [`name ${amendment.styles.join(", ")} in styles`] : [],
|
|
31034
|
+
...amendment.assets.length > 0 ? [
|
|
31035
|
+
`add assets for ${amendment.assets.map((asset) => asset.input).join(", ")} (the shell fetches its own strings at runtime, so without that glob every label in the chrome renders as its raw translation key)`
|
|
31036
|
+
] : [],
|
|
31037
|
+
...amendment.serviceWorker ? [
|
|
31038
|
+
`set serviceWorker to ${amendment.serviceWorker} in the production configuration (provideShell registers a worker that 404s otherwise)`
|
|
31039
|
+
] : [],
|
|
31040
|
+
...amendment.inlineCritical === void 0 ? [] : [
|
|
31041
|
+
`set optimization.styles.inlineCritical to ${amendment.inlineCritical} in the production configuration (the generated content-security policy blocks the inline handler Angular's critical-CSS pass attaches, so a release build renders unstyled)`
|
|
31042
|
+
]
|
|
31043
|
+
].map((step, index) => `${index + 1}. ${step}`).join(" ");
|
|
31044
|
+
}
|
|
31015
31045
|
|
|
31016
31046
|
// ../devkit/src/lib/generate/casing.ts
|
|
31017
31047
|
function isKebabId(value) {
|
|
@@ -31834,6 +31864,40 @@ var framePlugin = {
|
|
|
31834
31864
|
}
|
|
31835
31865
|
};
|
|
31836
31866
|
|
|
31867
|
+
// ../devkit/src/recipes/angular-distribution/amendments.ts
|
|
31868
|
+
function distributionAmendments(d) {
|
|
31869
|
+
return [
|
|
31870
|
+
...d.styles === "tailwind" ? [
|
|
31871
|
+
{
|
|
31872
|
+
kind: "postcss",
|
|
31873
|
+
file: ".postcssrc.json",
|
|
31874
|
+
plugin: "@tailwindcss/postcss"
|
|
31875
|
+
}
|
|
31876
|
+
] : [],
|
|
31877
|
+
{
|
|
31878
|
+
kind: "build-target",
|
|
31879
|
+
styles: ["src/styles.css"],
|
|
31880
|
+
assets: [
|
|
31881
|
+
{ glob: "**/*", input: "public", from: "project" },
|
|
31882
|
+
{
|
|
31883
|
+
glob: "**/*",
|
|
31884
|
+
input: "node_modules/@loomweaver/shell/i18n",
|
|
31885
|
+
from: "workspace",
|
|
31886
|
+
output: "i18n"
|
|
31887
|
+
},
|
|
31888
|
+
{
|
|
31889
|
+
glob: "**/*",
|
|
31890
|
+
input: "node_modules/@loomweaver/frame-kit/dist",
|
|
31891
|
+
from: "workspace",
|
|
31892
|
+
output: "frame-kit"
|
|
31893
|
+
}
|
|
31894
|
+
],
|
|
31895
|
+
serviceWorker: "ngsw-config.json",
|
|
31896
|
+
inlineCritical: false
|
|
31897
|
+
}
|
|
31898
|
+
];
|
|
31899
|
+
}
|
|
31900
|
+
|
|
31837
31901
|
// ../devkit/src/recipes/shell-regions.ts
|
|
31838
31902
|
var SHELL_REGIONS = [
|
|
31839
31903
|
"{ id: 'top-bar', type: 'bar', dock: 'top' }",
|
|
@@ -32086,20 +32150,15 @@ function stylesNotes(d) {
|
|
|
32086
32150
|
}
|
|
32087
32151
|
return [
|
|
32088
32152
|
"`src/styles.css` compiles the shell's source theme with Tailwind 4, which is also what lets you",
|
|
32089
|
-
"write Tailwind utilities in your own templates.
|
|
32090
|
-
"you
|
|
32153
|
+
"write Tailwind utilities in your own templates. The scaffold wrote `.postcssrc.json` beside your",
|
|
32154
|
+
"`package.json` for you, because without it the stylesheet is read as plain CSS: no utility class",
|
|
32155
|
+
"is emitted, the workbench renders unstyled, and the build still reports success. The packages are",
|
|
32156
|
+
"the one thing left, because a scaffold does not install:",
|
|
32091
32157
|
"",
|
|
32092
32158
|
"```sh",
|
|
32093
32159
|
"npm install -D tailwindcss @tailwindcss/postcss @tailwindcss/typography",
|
|
32094
32160
|
"```",
|
|
32095
32161
|
"",
|
|
32096
|
-
"and the PostCSS plugin, in a file next to your `package.json`:",
|
|
32097
|
-
"",
|
|
32098
|
-
"```jsonc",
|
|
32099
|
-
"// .postcssrc.json",
|
|
32100
|
-
'{ "plugins": { "@tailwindcss/postcss": {} } }',
|
|
32101
|
-
"```",
|
|
32102
|
-
"",
|
|
32103
32162
|
"Use **semantic tokens only** in your own templates (`bg-surface`, `text-content`, `text-brand`,",
|
|
32104
32163
|
"`border-border`), never raw palette colours.",
|
|
32105
32164
|
"",
|
|
@@ -32185,39 +32244,25 @@ function readme2(d) {
|
|
|
32185
32244
|
"",
|
|
32186
32245
|
"## Build wiring",
|
|
32187
32246
|
"",
|
|
32188
|
-
"The
|
|
32189
|
-
"
|
|
32190
|
-
"
|
|
32191
|
-
"resolved from the workspace root, so they read the same either way:",
|
|
32192
|
-
"",
|
|
32193
|
-
"```jsonc",
|
|
32194
|
-
'"styles": ["src/styles.css"],',
|
|
32195
|
-
'"assets": [',
|
|
32196
|
-
' { "glob": "**/*", "input": "public" },',
|
|
32197
|
-
' { "glob": "**/*", "input": "node_modules/@loomweaver/shell/i18n", "output": "i18n" },',
|
|
32198
|
-
' { "glob": "**/*", "input": "node_modules/@loomweaver/frame-kit/dist", "output": "frame-kit" }',
|
|
32199
|
-
"],",
|
|
32200
|
-
'"serviceWorker": "ngsw-config.json"',
|
|
32201
|
-
"```",
|
|
32202
|
-
"",
|
|
32203
|
-
"And in the **production** configuration of that same target:",
|
|
32247
|
+
"The scaffold did this. Your build target now names the stylesheet, three asset globs, the",
|
|
32248
|
+
"service worker and one production setting, and the run that wrote these files listed each one it",
|
|
32249
|
+
"added. Anything you had already set was left exactly as you set it.",
|
|
32204
32250
|
"",
|
|
32205
|
-
"
|
|
32206
|
-
|
|
32207
|
-
"
|
|
32251
|
+
"What each is for, so that nobody removes one as clutter. The **`@loomweaver/shell/i18n` glob**",
|
|
32252
|
+
"serves the strings the shell fetches at runtime; without it every label in the chrome renders as",
|
|
32253
|
+
"its raw translation key and nothing errors. The **frame-kit** glob only matters if you host",
|
|
32254
|
+
"sandboxed (iframe) plugins \u2014 until you install that package the glob simply matches nothing.",
|
|
32255
|
+
"**`serviceWorker`** emits the worker that `provideShell()` already registers for you (inert in",
|
|
32256
|
+
"dev) \u2014 never add `provideServiceWorker` yourself, and if you would rather ship no worker at all,",
|
|
32257
|
+
"drop `ngsw-config.json` and pass `provideShell({ serviceWorker: false })`, because otherwise the",
|
|
32258
|
+
"registration 404s in production. **`optimization.styles.inlineCritical: false`** is not optional:",
|
|
32259
|
+
"the `index.html` above ships a strict `script-src 'self'`, and Angular's critical-CSS pass loads",
|
|
32260
|
+
"the stylesheet with an **inline** `onload` handler that the policy blocks \u2014 the app then renders",
|
|
32261
|
+
"completely unstyled, and only in production builds.",
|
|
32208
32262
|
"",
|
|
32209
|
-
"
|
|
32210
|
-
"
|
|
32211
|
-
"chrome
|
|
32212
|
-
"matters if you host sandboxed (iframe) plugins \u2014 install that package then; until you do, the",
|
|
32213
|
-
"glob simply matches nothing. **`serviceWorker`** emits the worker that `provideShell()` already",
|
|
32214
|
-
"registers for you (inert in dev) \u2014 never add `provideServiceWorker` yourself, and if you would",
|
|
32215
|
-
"rather ship no worker at all, drop `ngsw-config.json` and pass",
|
|
32216
|
-
"`provideShell({ serviceWorker: false })`, because otherwise the registration 404s in production.",
|
|
32217
|
-
"**`inlineCritical: false`** is not optional here: the `index.html` above ships a strict",
|
|
32218
|
-
"`script-src 'self'`, and Angular's critical-CSS pass loads the stylesheet with an **inline**",
|
|
32219
|
-
"`onload` handler that the policy blocks \u2014 the app then renders completely unstyled, and only in",
|
|
32220
|
-
"production builds.",
|
|
32263
|
+
"One thing is still yours, because the scaffold cannot know your budget: a production build warns",
|
|
32264
|
+
"that the initial bundle exceeds Angular's 500 kB default. The shell is a whole application",
|
|
32265
|
+
"chrome, so raise the budgets in your build target.",
|
|
32221
32266
|
"",
|
|
32222
32267
|
"## Ship less than the whole workbench",
|
|
32223
32268
|
"",
|
|
@@ -32256,6 +32301,9 @@ function readme2(d) {
|
|
|
32256
32301
|
}
|
|
32257
32302
|
var angularDistribution = {
|
|
32258
32303
|
id: "angular-distribution",
|
|
32304
|
+
amend(input) {
|
|
32305
|
+
return distributionAmendments(resolveDistributionInput(input));
|
|
32306
|
+
},
|
|
32259
32307
|
build(input) {
|
|
32260
32308
|
const d = resolveDistributionInput(input);
|
|
32261
32309
|
return {
|
|
@@ -32546,6 +32594,67 @@ var layout = {
|
|
|
32546
32594
|
}
|
|
32547
32595
|
};
|
|
32548
32596
|
|
|
32597
|
+
// ../devkit/src/recipes/angular-weaver/amendments.ts
|
|
32598
|
+
function weaverAmendments(input, where) {
|
|
32599
|
+
const w = resolveWeaverInput(input);
|
|
32600
|
+
const directory = (where ?? "").replace(/^\.?\/*/, "").replace(/\/+$/, "");
|
|
32601
|
+
if (!directory) {
|
|
32602
|
+
return [];
|
|
32603
|
+
}
|
|
32604
|
+
return [
|
|
32605
|
+
{
|
|
32606
|
+
kind: "build-target",
|
|
32607
|
+
styles: [],
|
|
32608
|
+
assets: [
|
|
32609
|
+
{
|
|
32610
|
+
glob: "**/*.json",
|
|
32611
|
+
input: `${directory}/src/lib/i18n`,
|
|
32612
|
+
from: "workspace",
|
|
32613
|
+
output: `i18n/${w.id}`
|
|
32614
|
+
}
|
|
32615
|
+
]
|
|
32616
|
+
},
|
|
32617
|
+
{ kind: "stylesheet-source", sourceRoot: `${directory}/src` },
|
|
32618
|
+
{
|
|
32619
|
+
kind: "compose-plugin",
|
|
32620
|
+
id: w.id,
|
|
32621
|
+
symbol: `${w.propertyName}Plugin`,
|
|
32622
|
+
capabilities: w.capabilities,
|
|
32623
|
+
sourceRoot: `${directory}/src`
|
|
32624
|
+
}
|
|
32625
|
+
];
|
|
32626
|
+
}
|
|
32627
|
+
|
|
32628
|
+
// ../devkit/src/lib/scaffolds/inputs.ts
|
|
32629
|
+
function weaverInput(values) {
|
|
32630
|
+
return {
|
|
32631
|
+
id: str(values, "id") ?? "",
|
|
32632
|
+
name: str(values, "name"),
|
|
32633
|
+
prefix: str(values, "prefix"),
|
|
32634
|
+
importPath: str(values, "importPath"),
|
|
32635
|
+
features: {
|
|
32636
|
+
command: bool(values, "command"),
|
|
32637
|
+
shortcut: str(values, "shortcut"),
|
|
32638
|
+
menu: str(values, "menu"),
|
|
32639
|
+
barItem: bool(values, "barItem"),
|
|
32640
|
+
settings: bool(values, "settings"),
|
|
32641
|
+
about: bool(values, "about"),
|
|
32642
|
+
instanceable: bool(values, "instanceable"),
|
|
32643
|
+
container: bool(values, "container"),
|
|
32644
|
+
access: str(values, "access"),
|
|
32645
|
+
spec: bool(values, "spec")
|
|
32646
|
+
}
|
|
32647
|
+
};
|
|
32648
|
+
}
|
|
32649
|
+
function distributionInput(values) {
|
|
32650
|
+
return {
|
|
32651
|
+
name: str(values, "name") ?? "",
|
|
32652
|
+
title: str(values, "title"),
|
|
32653
|
+
directory: str(values, "directory"),
|
|
32654
|
+
styles: str(values, "styles") ?? "tailwind"
|
|
32655
|
+
};
|
|
32656
|
+
}
|
|
32657
|
+
|
|
32549
32658
|
// ../devkit/src/lib/scaffolds/scaffolds.ts
|
|
32550
32659
|
function str(values, name) {
|
|
32551
32660
|
const value = values[name];
|
|
@@ -32681,24 +32790,8 @@ var SCAFFOLDS = [
|
|
|
32681
32790
|
APP_OPTION,
|
|
32682
32791
|
...PLACEMENT_OPTIONS
|
|
32683
32792
|
],
|
|
32684
|
-
build: (values) => generate(angularWeaver,
|
|
32685
|
-
|
|
32686
|
-
name: str(values, "name"),
|
|
32687
|
-
prefix: str(values, "prefix"),
|
|
32688
|
-
importPath: str(values, "importPath"),
|
|
32689
|
-
features: {
|
|
32690
|
-
command: bool(values, "command"),
|
|
32691
|
-
shortcut: str(values, "shortcut"),
|
|
32692
|
-
menu: str(values, "menu"),
|
|
32693
|
-
barItem: bool(values, "barItem"),
|
|
32694
|
-
settings: bool(values, "settings"),
|
|
32695
|
-
about: bool(values, "about"),
|
|
32696
|
-
instanceable: bool(values, "instanceable"),
|
|
32697
|
-
container: bool(values, "container"),
|
|
32698
|
-
access: str(values, "access"),
|
|
32699
|
-
spec: bool(values, "spec")
|
|
32700
|
-
}
|
|
32701
|
-
})
|
|
32793
|
+
build: (values) => generate(angularWeaver, weaverInput(values)),
|
|
32794
|
+
amend: (values) => weaverAmendments(weaverInput(values), str(values, "directory"))
|
|
32702
32795
|
},
|
|
32703
32796
|
{
|
|
32704
32797
|
name: "frame-plugin",
|
|
@@ -32754,12 +32847,8 @@ var SCAFFOLDS = [
|
|
|
32754
32847
|
},
|
|
32755
32848
|
...PLACEMENT_OPTIONS
|
|
32756
32849
|
],
|
|
32757
|
-
build: (values) => generate(angularDistribution,
|
|
32758
|
-
|
|
32759
|
-
title: str(values, "title"),
|
|
32760
|
-
directory: str(values, "directory"),
|
|
32761
|
-
styles: str(values, "styles") ?? "tailwind"
|
|
32762
|
-
})
|
|
32850
|
+
build: (values) => generate(angularDistribution, distributionInput(values)),
|
|
32851
|
+
amend: (values) => amendments(angularDistribution, distributionInput(values))
|
|
32763
32852
|
},
|
|
32764
32853
|
{
|
|
32765
32854
|
name: "auth-source",
|
|
@@ -33130,7 +33219,12 @@ function valuesFor(scaffold2, args) {
|
|
|
33130
33219
|
return values;
|
|
33131
33220
|
}
|
|
33132
33221
|
function scaffold(scaffold2, args) {
|
|
33133
|
-
|
|
33222
|
+
const values = valuesFor(scaffold2, args);
|
|
33223
|
+
const remaining = (scaffold2.amend?.(values) ?? []).map(describeAmendment);
|
|
33224
|
+
return ok({
|
|
33225
|
+
files: scaffold2.build(values),
|
|
33226
|
+
...remaining.length > 0 ? { remaining } : {}
|
|
33227
|
+
});
|
|
33134
33228
|
}
|
|
33135
33229
|
function validateManifestTool(a) {
|
|
33136
33230
|
return ok({
|
|
@@ -33150,7 +33244,7 @@ function validateI18nTool(a) {
|
|
|
33150
33244
|
}
|
|
33151
33245
|
|
|
33152
33246
|
// src/lib/server.ts
|
|
33153
|
-
var FILE_MAP_NOTE =
|
|
33247
|
+
var FILE_MAP_NOTE = 'Returns a file map (relative path -> content); write the files into your project. May also return "remaining": steps the workspace needs that this route cannot perform, each saying what it costs to skip. Carry them out, or the generated output builds and does not work.';
|
|
33154
33248
|
function inputSchema(descriptor) {
|
|
33155
33249
|
const shape = {};
|
|
33156
33250
|
for (const option of portableOptions(descriptor)) {
|
|
@@ -33163,7 +33257,7 @@ function inputSchema(descriptor) {
|
|
|
33163
33257
|
function createMcpServer() {
|
|
33164
33258
|
const server = new McpServer({
|
|
33165
33259
|
name: "loomweaver-devkit",
|
|
33166
|
-
version: "0.7.
|
|
33260
|
+
version: "0.7.3"
|
|
33167
33261
|
});
|
|
33168
33262
|
server.registerTool(
|
|
33169
33263
|
"list_generators",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loomweaver/mcp",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"description": "LoomWeaver MCP server: exposes LoomWeaver's scaffolding and validation as MCP tools, so an AI assistant in any product repo can scaffold and validate weavers, distributions and integrations without a LoomWeaver checkout.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"loomweaver",
|