@savvy-web/mcp 1.6.0 → 1.6.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@savvy-web/mcp",
3
- "version": "1.6.0",
3
+ "version": "1.6.2",
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,9 +36,9 @@
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": "2.0.0",
39
+ "@savvy-web/silk-effects": "2.0.2",
40
40
  "effect": "^3.21.4",
41
- "workspaces-effect": "^2.0.0",
41
+ "workspaces-effect": "^2.0.1",
42
42
  "zod": "^4.4.3"
43
43
  }
44
44
  }
@@ -17,7 +17,8 @@ import { z } from "zod";
17
17
  * them.
18
18
  */
19
19
  const effectToZodSchema = (schema) => {
20
- const inlined = inlineAllRefs(JSONSchema.make(schema));
20
+ const jsonSchema = JSONSchema.make(schema);
21
+ const inlined = inlineAllRefs(jsonSchema);
21
22
  const zodSchema = z.fromJSONSchema(inlined);
22
23
  if (isObjectLike(zodSchema)) return zodSchema;
23
24
  return z.object({}).catchall(z.unknown());
@@ -35,7 +36,8 @@ const inlineAllRefs = (root) => {
35
36
  if (value === null || typeof value !== "object") return value;
36
37
  const obj = value;
37
38
  if (typeof obj.$ref === "string" && obj.$ref.startsWith(REF_PREFIX)) {
38
- const target = defs[obj.$ref.slice(8)];
39
+ const defName = obj.$ref.slice(8);
40
+ const target = defs[defName];
39
41
  if (target !== void 0) return visit(target);
40
42
  }
41
43
  const out = {};
package/server.js CHANGED
@@ -41,7 +41,8 @@ function buildServer(ctx) {
41
41
  }, async (args) => {
42
42
  const root = args.cwd ?? ctx.cwd;
43
43
  const data = await ctx.runtime.runPromise(workspaceInfo(root));
44
- return structuredResult(Schema.decodeSync(WorkspaceInfoAsMarkdown)(data), data);
44
+ const text = Schema.decodeSync(WorkspaceInfoAsMarkdown)(data);
45
+ return structuredResult(text, data);
45
46
  });
46
47
  server.registerTool("turbo_inspect", {
47
48
  description: "Read-only Turborepo inspection. mode=cache diagnoses why a task's cache is hitting/missing (per-package status plus the exact hash contributors: input files, env vars, external-dep hashes, global hash). mode=graph returns the task graph and critical path. mode=affected lists changed packages and their dependents. Never executes tasks (uses --dry).",
@@ -59,7 +60,8 @@ function buildServer(ctx) {
59
60
  annotations: { readOnlyHint: true }
60
61
  }, async (args) => {
61
62
  const data = await ctx.runtime.runPromise(turboInspect(args, ctx.cwd));
62
- return structuredResult(Schema.decodeSync(TurboInspectAsMarkdown)(data), data);
63
+ const text = Schema.decodeSync(TurboInspectAsMarkdown)(data);
64
+ return structuredResult(text, data);
63
65
  });
64
66
  server.registerTool("changeset_inspect", {
65
67
  description: "Read-only changeset analysis for the changeset-manager workflow. mode=branch diffs the current branch against its base and classifies every changed file by owning package (with packagesAffected and the unmapped paths to ask the user about). mode=config surfaces the resolved .changeset/config.json (release surfaces, versionFiles, ignore list). mode=classify maps arbitrary repo-relative paths to their owning package. Prefer this over shelling out to the savvy CLI.",
@@ -77,7 +79,8 @@ function buildServer(ctx) {
77
79
  annotations: { readOnlyHint: true }
78
80
  }, async (args) => {
79
81
  const data = await ctx.runtime.runPromise(changesetInspect(args, ctx.cwd));
80
- return structuredResult(Schema.decodeSync(ChangesetInspectAsMarkdown)(data), data);
82
+ const text = Schema.decodeSync(ChangesetInspectAsMarkdown)(data);
83
+ return structuredResult(text, data);
81
84
  });
82
85
  server.registerTool("changeset_validate", {
83
86
  description: "Read-only validation of changeset files against the section-aware rules. Pass dir (default .changeset). Returns typed diagnostics (file, rule, line, column, message) plus ok/errorCount in structuredContent. Prefer this over shelling out to savvy changeset lint.",
@@ -89,7 +92,8 @@ function buildServer(ctx) {
89
92
  annotations: { readOnlyHint: true }
90
93
  }, async (args) => {
91
94
  const data = await ctx.runtime.runPromise(changesetValidate(args, ctx.cwd));
92
- return structuredResult(Schema.decodeSync(ChangesetValidateAsMarkdown)(data), data);
95
+ const text = Schema.decodeSync(ChangesetValidateAsMarkdown)(data);
96
+ return structuredResult(text, data);
93
97
  });
94
98
  server.registerTool("changeset_deps_detect", {
95
99
  description: "Read-only preview of the cumulative dependency diff (merge-base -> working tree) per workspace package. Returns each affected package's resolved dependency-table rows (catalog:/workspace: specifiers resolved to concrete versions; devDependencies retained) as the exact rows a pure-dependency changeset would carry. Does NOT write or delete any file. Prefer this over shelling out to savvy changeset deps detect.",
@@ -102,7 +106,8 @@ function buildServer(ctx) {
102
106
  annotations: { readOnlyHint: true }
103
107
  }, async (args) => {
104
108
  const data = await ctx.runtime.runPromise(changesetDepsDetect(args, ctx.cwd));
105
- return structuredResult(Schema.decodeSync(ChangesetDepsDetectAsMarkdown)(data), data);
109
+ const text = Schema.decodeSync(ChangesetDepsDetectAsMarkdown)(data);
110
+ return structuredResult(text, data);
106
111
  });
107
112
  server.registerTool("changeset_preview", {
108
113
  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.",
@@ -111,7 +116,8 @@ function buildServer(ctx) {
111
116
  annotations: { readOnlyHint: true }
112
117
  }, async (args) => {
113
118
  const data = await ctx.runtime.runPromise(changesetPreview(args, ctx.cwd));
114
- return structuredResult(Schema.decodeSync(ChangesetPreviewAsMarkdown)(data), data);
119
+ const text = Schema.decodeSync(ChangesetPreviewAsMarkdown)(data);
120
+ return structuredResult(text, data);
115
121
  });
116
122
  server.registerTool("changeset_deps_regen", {
117
123
  description: "Regenerate pure-dependency changesets: delete stale single-package Dependencies-only changesets and write fresh single-package, patch-bump changesets from the cumulative dependency diff (catalog:/workspace: resolved; devDependencies dropped). Mixed changesets (Dependencies plus other content) are left untouched. Set dryRun=true to preview the plan without touching the filesystem. NOTE: without dryRun this tool MUTATES .changeset/*.md (git-reversible). Prefer this over shelling out to savvy changeset deps regen.",
@@ -128,7 +134,8 @@ function buildServer(ctx) {
128
134
  }
129
135
  }, async (args) => {
130
136
  const data = await ctx.runtime.runPromise(changesetDepsRegen(args, ctx.cwd));
131
- return structuredResult(Schema.decodeSync(ChangesetDepsRegenAsMarkdown)(data), data);
137
+ const text = Schema.decodeSync(ChangesetDepsRegenAsMarkdown)(data);
138
+ return structuredResult(text, data);
132
139
  });
133
140
  server.registerTool("biome_check", {
134
141
  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).",
@@ -142,7 +149,8 @@ function buildServer(ctx) {
142
149
  outputSchema: effectToZodSchema(BiomeCheckResult)
143
150
  }, async (args) => {
144
151
  const data = await runBiomeCheck(args, ctx.cwd);
145
- return structuredResult(Schema.decodeSync(BiomeCheckAsMarkdown)(data), data);
152
+ const text = Schema.decodeSync(BiomeCheckAsMarkdown)(data);
153
+ return structuredResult(text, data);
146
154
  });
147
155
  return server;
148
156
  }
@@ -85,7 +85,8 @@ const WorkspaceInfoAsMarkdown = Schema.transformOrFail(WorkspaceInfoResult, Sche
85
85
  */
86
86
  const workspaceInfo = (base) => Effect.gen(function* () {
87
87
  const root = yield* (yield* WorkspaceRoot).find(base);
88
- return toWorkspaceInfoResult(yield* (yield* SilkWorkspaceAnalyzer).analyze(root));
88
+ const analysis = yield* (yield* SilkWorkspaceAnalyzer).analyze(root);
89
+ return toWorkspaceInfoResult(analysis);
89
90
  });
90
91
 
91
92
  //#endregion