@savvy-web/mcp 1.1.2 → 1.2.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 +4 -1
- package/index.d.ts +6 -5
- package/package.json +2 -2
- package/runtime.js +5 -4
- package/server.js +10 -0
- package/tools/changeset-preview.js +52 -0
package/README.md
CHANGED
|
@@ -44,7 +44,10 @@ npx @modelcontextprotocol/inspector savvy-mcp .
|
|
|
44
44
|
- `workspace_info` — returns a flat, structured projection of the workspace analysis: linked and fixed package groups as name arrays plus resolved registry targets. Backed by the same `silk-effects` analyzer the `savvy` CLI uses.
|
|
45
45
|
- `silk_docs_search` — ranks documents in the corpus against a plain keyword or phrase query and returns hits with a normalized confidence score plus a high/medium/low label. It never returns empty: when nothing matches, it falls back to the priority-ordered top results.
|
|
46
46
|
- `turbo_inspect` — read-only Turborepo inspection over `turbo --dry`: diagnose a task's per-package cache hits, derive the task graph or list the packages affected by recent changes. It never runs a task. Backed by the same `silk-effects` `Turbo` inspector an agent would otherwise drive by hand.
|
|
47
|
-
- `changeset_inspect` — read-only changeset analysis for release work: `mode=branch` diffs the current branch against its base and attributes every changed file to its owning package, `mode=config` surfaces the resolved `.changeset/config.json` with its release surfaces, version files and ignore list. It never writes a changeset. Backed by the same `silk-effects` changeset services the `savvy` CLI uses.
|
|
47
|
+
- `changeset_inspect` — read-only changeset analysis for release work: `mode=branch` diffs the current branch against its base and attributes every changed file to its owning package, `mode=config` surfaces the resolved `.changeset/config.json` with its release surfaces, version files and ignore list, and `mode=classify` reports how the branch's pending changesets classify each package's bump. It never writes a changeset. Backed by the same `silk-effects` changeset services the `savvy` CLI uses.
|
|
48
|
+
- `changeset_validate` — read-only validation of the files in a changeset directory against the section-aware rules, returning typed diagnostics (file, rule, line, column, message) plus an ok flag and error count. Use it instead of shelling out to `savvy changeset lint`.
|
|
49
|
+
- `changeset_preview` — read-only preview of the next release: it runs the genuine changesets engine over the pending changesets and returns each package's version bump (old to new) plus the rendered CHANGELOG block, exactly as it would ship. It never mutates the repo. Backed by the same `silk-effects` release planner the `savvy changeset version` command applies.
|
|
50
|
+
- `biome_check` — run Biome over a path and get structured diagnostics back: `mode=check` (lint, format and organize-imports) or `mode=lint`. Unlike the other tools it can mutate — pass `write` for safe fixes or `unsafe` for unsafe ones (both git-reversible) — so it returns the same diagnostics the Biome LSP surfaces for files you have edited.
|
|
48
51
|
|
|
49
52
|
## Resources
|
|
50
53
|
|
package/index.d.ts
CHANGED
|
@@ -84,7 +84,7 @@ declare class DocIndex {
|
|
|
84
84
|
//#region src/context.d.ts
|
|
85
85
|
/** The long-lived runtime, the project working directory, and the resource layer. */
|
|
86
86
|
interface McpContext {
|
|
87
|
-
readonly runtime: ManagedRuntime.ManagedRuntime<SilkWorkspaceAnalyzer | WorkspaceRoot | Turbo.TurboInspector | Changesets.BranchAnalyzer | Changesets.ConfigInspector, WorkspaceDiscoveryError>;
|
|
87
|
+
readonly runtime: ManagedRuntime.ManagedRuntime<SilkWorkspaceAnalyzer | WorkspaceRoot | Turbo.TurboInspector | Changesets.BranchAnalyzer | Changesets.ConfigInspector | Changesets.ReleasePlanner, WorkspaceDiscoveryError>;
|
|
88
88
|
readonly cwd: string;
|
|
89
89
|
readonly docIndex: DocIndex;
|
|
90
90
|
readonly manifest: Manifest;
|
|
@@ -94,16 +94,17 @@ interface McpContext {
|
|
|
94
94
|
//#region src/runtime.d.ts
|
|
95
95
|
/**
|
|
96
96
|
* The MCP runtime layer. Provides `SilkWorkspaceAnalyzer`, `WorkspaceRoot`,
|
|
97
|
-
* `Turbo.TurboInspector`, `Changesets.BranchAnalyzer`,
|
|
98
|
-
* `Changesets.ConfigInspector
|
|
99
|
-
* `Path` from the host's platform layer
|
|
97
|
+
* `Turbo.TurboInspector`, `Changesets.BranchAnalyzer`,
|
|
98
|
+
* `Changesets.ConfigInspector`, and `Changesets.ReleasePlanner`; requires
|
|
99
|
+
* `CommandExecutor` + `FileSystem` + `Path` from the host's platform layer
|
|
100
|
+
* (`NodeContext.layer` in bin.ts).
|
|
100
101
|
*
|
|
101
102
|
* `TurboInspectorLive` is fed its own `ToolDiscoveryLive`, whose
|
|
102
103
|
* `PackageManagerDetector` + `WorkspaceRoot` requirements are satisfied by
|
|
103
104
|
* {@link DepsLive}; the leftover `CommandExecutor` + `FileSystem` flow up to the
|
|
104
105
|
* host platform layer.
|
|
105
106
|
*/
|
|
106
|
-
declare const SilkRuntimeLive: Layer.Layer<import("@savvy-web/silk-effects").SilkWorkspaceAnalyzer | import("workspaces-effect").WorkspaceRoot | Turbo.TurboInspector | Changesets.BranchAnalyzer | Changesets.ConfigInspector, import("workspaces-effect").WorkspaceDiscoveryError, import("@effect/platform/FileSystem").FileSystem | import("@effect/platform/Path").Path | import("@effect/platform/CommandExecutor").CommandExecutor>;
|
|
107
|
+
declare const SilkRuntimeLive: Layer.Layer<import("@savvy-web/silk-effects").SilkWorkspaceAnalyzer | import("workspaces-effect").WorkspaceRoot | Turbo.TurboInspector | Changesets.BranchAnalyzer | Changesets.ConfigInspector | Changesets.ReleasePlanner, import("workspaces-effect").WorkspaceDiscoveryError, import("@effect/platform/FileSystem").FileSystem | import("@effect/platform/Path").Path | import("@effect/platform/CommandExecutor").CommandExecutor>;
|
|
107
108
|
//#endregion
|
|
108
109
|
//#region src/server.d.ts
|
|
109
110
|
/** Build the server and connect it over stdio. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@savvy-web/mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The savvy MCP server — Silk Suite tooling and library knowledge for coding agents",
|
|
6
6
|
"homepage": "https://github.com/savvy-web/systems/tree/main/packages/mcp",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"@effect/rpc": "^0.75.1",
|
|
37
37
|
"@effect/sql": "^0.51.1",
|
|
38
38
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
39
|
-
"@savvy-web/silk-effects": "1.
|
|
39
|
+
"@savvy-web/silk-effects": "1.4.0",
|
|
40
40
|
"effect": "^3.21.3",
|
|
41
41
|
"fuse.js": "^7.4.0",
|
|
42
42
|
"workspaces-effect": "^1.2.0",
|
package/runtime.js
CHANGED
|
@@ -22,12 +22,13 @@ import { WorkspaceRootLive, WorkspacesLive } from "workspaces-effect";
|
|
|
22
22
|
* cross-feed sibling layers.
|
|
23
23
|
*/
|
|
24
24
|
const DepsLive = Layer.mergeAll(WorkspacesLive, ChangesetConfigReaderLive, TagStrategyLive, VersioningStrategyLive.pipe(Layer.provide(ChangesetConfigReaderLive)));
|
|
25
|
-
const InspectorAndAnalyzerLive = Changesets.BranchAnalyzerLive.pipe(Layer.provideMerge(Changesets.ConfigInspectorLive));
|
|
25
|
+
const InspectorAndAnalyzerLive = Changesets.BranchAnalyzerLive.pipe(Layer.provideMerge(Changesets.ReleasePlannerLive), Layer.provideMerge(Changesets.ConfigInspectorLive));
|
|
26
26
|
/**
|
|
27
27
|
* The MCP runtime layer. Provides `SilkWorkspaceAnalyzer`, `WorkspaceRoot`,
|
|
28
|
-
* `Turbo.TurboInspector`, `Changesets.BranchAnalyzer`,
|
|
29
|
-
* `Changesets.ConfigInspector
|
|
30
|
-
* `Path` from the host's platform layer
|
|
28
|
+
* `Turbo.TurboInspector`, `Changesets.BranchAnalyzer`,
|
|
29
|
+
* `Changesets.ConfigInspector`, and `Changesets.ReleasePlanner`; requires
|
|
30
|
+
* `CommandExecutor` + `FileSystem` + `Path` from the host's platform layer
|
|
31
|
+
* (`NodeContext.layer` in bin.ts).
|
|
31
32
|
*
|
|
32
33
|
* `TurboInspectorLive` is fed its own `ToolDiscoveryLive`, whose
|
|
33
34
|
* `PackageManagerDetector` + `WorkspaceRoot` requirements are satisfied by
|
package/server.js
CHANGED
|
@@ -3,6 +3,7 @@ import { stderrQueryLogger } from "./resources/query-log.js";
|
|
|
3
3
|
import { effectToZodSchema } from "./schema/effect-to-zod.js";
|
|
4
4
|
import { BiomeCheckAsMarkdown, BiomeCheckResult, runBiomeCheck } from "./tools/biome-check.js";
|
|
5
5
|
import { ChangesetInspectAsMarkdown, ChangesetInspectResult, changesetInspect } from "./tools/changeset-inspect.js";
|
|
6
|
+
import { ChangesetPreviewAsMarkdown, ChangesetPreviewResult, changesetPreview } from "./tools/changeset-preview.js";
|
|
6
7
|
import { ChangesetValidateAsMarkdown, ChangesetValidateResult, changesetValidate } from "./tools/changeset-validate.js";
|
|
7
8
|
import { DocsSearchResult, DocsSearchResultAsMarkdown, runDocsSearch } from "./tools/docs-search.js";
|
|
8
9
|
import { TurboInspectAsMarkdown, TurboInspectResult, turboInspect } from "./tools/turbo-inspect.js";
|
|
@@ -111,6 +112,15 @@ function buildServer(ctx) {
|
|
|
111
112
|
const data = await ctx.runtime.runPromise(changesetValidate(args, ctx.cwd));
|
|
112
113
|
return structuredResult(Schema.decodeSync(ChangesetValidateAsMarkdown)(data), data);
|
|
113
114
|
});
|
|
115
|
+
server.registerTool("changeset_preview", {
|
|
116
|
+
description: "Read-only preview of the next release. Runs the genuine changesets engine over the pending changesets and returns each package's version bump (old -> new) plus the rendered CHANGELOG block (dependency tables included), exactly as it would ship. Does not modify the repo. Prefer this over hand-merging changeset files.",
|
|
117
|
+
inputSchema: { cwd: z.optional(z.string()).describe("Directory to resolve the workspace root from.") },
|
|
118
|
+
outputSchema: effectToZodSchema(ChangesetPreviewResult),
|
|
119
|
+
annotations: { readOnlyHint: true }
|
|
120
|
+
}, async (args) => {
|
|
121
|
+
const data = await ctx.runtime.runPromise(changesetPreview(args, ctx.cwd));
|
|
122
|
+
return structuredResult(Schema.decodeSync(ChangesetPreviewAsMarkdown)(data), data);
|
|
123
|
+
});
|
|
114
124
|
server.registerTool("biome_check", {
|
|
115
125
|
description: "Run Biome over a path and get structured diagnostics back. mode=check (default; lint + format + organize-imports) or mode=lint. Set write=true to apply safe fixes (--write), unsafe=true for unsafe fixes (--write --unsafe). Prefer this over shelling out to biome; the LSP already covers files you've edited. Returns markdown in content[] and a typed object in structuredContent. NOTE: with write/unsafe this tool MUTATES files (git-reversible).",
|
|
116
126
|
inputSchema: {
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Changesets } from "@savvy-web/silk-effects";
|
|
2
|
+
import { Effect, ParseResult, Schema } from "effect";
|
|
3
|
+
import { WorkspaceRoot } from "workspaces-effect";
|
|
4
|
+
|
|
5
|
+
//#region src/tools/changeset-preview.ts
|
|
6
|
+
/**
|
|
7
|
+
* The `changeset_preview` MCP tool: a read-only preview of the next release's
|
|
8
|
+
* CHANGELOG, produced by the genuine changesets engine via silk-effects'
|
|
9
|
+
* ReleasePlanner. Structured result + one-way markdown transform. Read-only.
|
|
10
|
+
*
|
|
11
|
+
* @packageDocumentation
|
|
12
|
+
*/
|
|
13
|
+
/** The `changeset_preview` result — the silk-effects preview shape. */
|
|
14
|
+
const ChangesetPreviewResult = Changesets.ChangesetPreviewSchema.annotations({
|
|
15
|
+
identifier: "ChangesetPreviewResult",
|
|
16
|
+
title: "changeset_preview result",
|
|
17
|
+
description: "Read-only preview of the next release: version bumps + rendered CHANGELOG blocks."
|
|
18
|
+
});
|
|
19
|
+
/** Render a value as an inert markdown code span (escapes backticks/backslashes). */
|
|
20
|
+
const mdInline = (value) => `\`${value.replace(/[`\\]/g, "\\$&")}\``;
|
|
21
|
+
/** Render the structured preview as a markdown transcript. */
|
|
22
|
+
const renderMarkdown = (data) => {
|
|
23
|
+
if (data.releases.length === 0) return "# changeset preview\n\nNo pending changesets.";
|
|
24
|
+
const lines = [
|
|
25
|
+
`# changeset preview${data.preMode ? ` (pre: ${data.preMode})` : ""}`,
|
|
26
|
+
``,
|
|
27
|
+
`## Version bumps`,
|
|
28
|
+
``
|
|
29
|
+
];
|
|
30
|
+
lines.push(`| Package | Old | New | Bump |`, `| --- | --- | --- | --- |`);
|
|
31
|
+
for (const r of data.releases) lines.push(`| ${mdInline(r.name)} | ${r.oldVersion} | ${r.newVersion} | ${r.type} |`);
|
|
32
|
+
lines.push(``, `## Release notes`, ``);
|
|
33
|
+
for (const r of data.releases) lines.push(`### ${mdInline(r.name)}`, ``, r.changelogEntry, ``);
|
|
34
|
+
return lines.join("\n").trimEnd();
|
|
35
|
+
};
|
|
36
|
+
/** One-way transform: result to markdown. Encoding back is forbidden. */
|
|
37
|
+
const ChangesetPreviewAsMarkdown = Schema.transformOrFail(ChangesetPreviewResult, Schema.String, {
|
|
38
|
+
strict: true,
|
|
39
|
+
decode: (data) => ParseResult.succeed(renderMarkdown(data)),
|
|
40
|
+
encode: (text, _options, ast) => ParseResult.fail(new ParseResult.Forbidden(ast, text, "ChangesetPreviewAsMarkdown is one-way: markdown cannot be parsed back."))
|
|
41
|
+
});
|
|
42
|
+
/**
|
|
43
|
+
* Effect handler: resolve the workspace root, then render the preview via
|
|
44
|
+
* ReleasePlanner. Mirrors `changesetInspect`.
|
|
45
|
+
*/
|
|
46
|
+
const changesetPreview = (args, fallbackCwd) => Effect.gen(function* () {
|
|
47
|
+
const root = yield* (yield* WorkspaceRoot).find(args.cwd ?? fallbackCwd);
|
|
48
|
+
return yield* (yield* Changesets.ReleasePlanner).preview(root);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
//#endregion
|
|
52
|
+
export { ChangesetPreviewAsMarkdown, ChangesetPreviewResult, changesetPreview };
|