@savvy-web/mcp 0.3.0 → 0.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 +1 -0
- package/bin/savvy-mcp.js +40 -146
- package/package.json +42 -80
- package/{resources → public}/content/manifest.json +175 -250
- package/public/content/standards/turbo/best-practices.md +76 -0
- package/public/content/standards/turbo/boundaries.md +72 -0
- package/public/content/standards/turbo/ci.md +69 -0
- package/public/content/standards/turbo/environment.md +64 -0
- package/public/content/standards/turbo/filtering.md +72 -0
- package/public/content/standards/turbo/watch.md +64 -0
- package/{resources → public}/content/tags.json +3 -1
- package/547.js +0 -416
- package/index.d.ts +0 -126
- package/index.js +0 -3
- package/tsdoc-metadata.json +0 -11
- /package/{resources → public}/content/_templates/guides.md +0 -0
- /package/{resources → public}/content/_templates/packages.md +0 -0
- /package/{resources → public}/content/_templates/standards.md +0 -0
- /package/{resources → public}/content/guides/api-docs-from-api-extractor.md +0 -0
- /package/{resources → public}/content/guides/building-a-github-action.md +0 -0
- /package/{resources → public}/content/guides/choosing-a-builder.md +0 -0
- /package/{resources → public}/content/guides/llm-friendly-json-schemas.md +0 -0
- /package/{resources → public}/content/packages/cli/command-tree.md +0 -0
- /package/{resources → public}/content/packages/cli/init-and-check.md +0 -0
- /package/{resources → public}/content/packages/mcp/resource-taxonomy.md +0 -0
- /package/{resources → public}/content/packages/rslib-builder/overview.md +0 -0
- /package/{resources → public}/content/packages/silk/export-map.md +0 -0
- /package/{resources → public}/content/packages/silk/install-and-setup.md +0 -0
- /package/{resources → public}/content/packages/silk-effects/index.md +0 -0
- /package/{resources → public}/content/packages/silk-effects/managed-section.md +0 -0
- /package/{resources → public}/content/packages/silk-effects/platform-layers.md +0 -0
- /package/{resources → public}/content/standards/api-model-pipeline.md +0 -0
- /package/{resources → public}/content/standards/catalog-usage.md +0 -0
- /package/{resources → public}/content/standards/changeset-discipline.md +0 -0
- /package/{resources → public}/content/standards/changeset-format.md +0 -0
- /package/{resources → public}/content/standards/commit-contract.md +0 -0
- /package/{resources → public}/content/standards/dependency-conventions.md +0 -0
- /package/{resources → public}/content/standards/linting-conventions.md +0 -0
- /package/{resources → public}/content/standards/publishability.md +0 -0
- /package/{resources → public}/content/standards/semver.md +0 -0
- /package/{resources → public}/content/standards/test-classification.md +0 -0
package/README.md
CHANGED
|
@@ -43,6 +43,7 @@ npx @modelcontextprotocol/inspector savvy-mcp .
|
|
|
43
43
|
|
|
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
|
+
- `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.
|
|
46
47
|
|
|
47
48
|
## Resources
|
|
48
49
|
|
package/bin/savvy-mcp.js
CHANGED
|
@@ -1,153 +1,47 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { SilkRuntimeLive } from "../runtime.js";
|
|
3
|
+
import { loadManifest, readDocBody, resolveContentRoot } from "../resources/load.js";
|
|
4
|
+
import { startMcpServer } from "../server.js";
|
|
5
|
+
import { DocIndex } from "../resources/doc-index.js";
|
|
3
6
|
import { Layer, ManagedRuntime } from "effect";
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"for",
|
|
17
|
-
"is",
|
|
18
|
-
"what",
|
|
19
|
-
"when",
|
|
20
|
-
"use"
|
|
21
|
-
]);
|
|
22
|
-
const FUSE_THRESHOLD = 0.6;
|
|
23
|
-
const confidenceLabel = (confidence)=>confidence >= 0.6 ? "high" : confidence >= 0.4 ? "medium" : "low";
|
|
24
|
-
const toRanked = (item, score, matches)=>({
|
|
25
|
-
item,
|
|
26
|
-
confidence: 1 - (score ?? 1),
|
|
27
|
-
matchedOn: matches.map((m)=>m.key ?? "")
|
|
28
|
-
});
|
|
29
|
-
class DocIndex {
|
|
30
|
-
fuse;
|
|
31
|
-
entries;
|
|
32
|
-
byUri;
|
|
33
|
-
constructor(fuse, entries, byUri){
|
|
34
|
-
this.fuse = fuse;
|
|
35
|
-
this.entries = entries;
|
|
36
|
-
this.byUri = byUri;
|
|
37
|
-
}
|
|
38
|
-
static fromManifest(manifest, bodies) {
|
|
39
|
-
const entries = manifest.entries.filter((e)=>"deprecated" !== e.status).map((e)=>({
|
|
40
|
-
...e,
|
|
41
|
-
body: bodies[e.uri] ?? ""
|
|
42
|
-
}));
|
|
43
|
-
const fuse = new fuse_0(entries, {
|
|
44
|
-
useExtendedSearch: true,
|
|
45
|
-
ignoreLocation: true,
|
|
46
|
-
includeScore: true,
|
|
47
|
-
includeMatches: true,
|
|
48
|
-
minMatchCharLength: 2,
|
|
49
|
-
threshold: FUSE_THRESHOLD,
|
|
50
|
-
keys: [
|
|
51
|
-
{
|
|
52
|
-
name: "title",
|
|
53
|
-
weight: 0.55
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
name: "tags",
|
|
57
|
-
weight: 0.3
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
name: "summary",
|
|
61
|
-
weight: 0.12
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
name: "body",
|
|
65
|
-
weight: 0.03
|
|
66
|
-
}
|
|
67
|
-
]
|
|
68
|
-
});
|
|
69
|
-
const byUri = new Map(entries.map((e)=>[
|
|
70
|
-
e.uri,
|
|
71
|
-
e
|
|
72
|
-
]));
|
|
73
|
-
return new DocIndex(fuse, entries, byUri);
|
|
74
|
-
}
|
|
75
|
-
search(query, opts = {}) {
|
|
76
|
-
const limit = opts.limit ?? 10;
|
|
77
|
-
const tokens = query.toLowerCase().split(/\s+/).filter((t)=>t.length >= 2 && !STOP_WORDS.has(t));
|
|
78
|
-
const raw = tokens.length > 0 ? this.fuse.search(tokens.map((t)=>`'${t}`).join(" | ")) : [];
|
|
79
|
-
const filteredByTier = opts.tier ? raw.filter((r)=>r.item.tier === opts.tier) : raw;
|
|
80
|
-
const ranked = filteredByTier.length > 0 ? filteredByTier.map((r)=>toRanked(r.item, r.score, r.matches ?? [])) : this.fallback(opts.tier);
|
|
81
|
-
ranked.sort((a, b)=>b.confidence - a.confidence || (b.item.priority ?? 0.5) - (a.item.priority ?? 0.5));
|
|
82
|
-
const present = new Set(ranked.map((r)=>r.item.uri));
|
|
83
|
-
const seeAlso = [];
|
|
84
|
-
for (const r of ranked.slice(0, 3))for (const rel of r.item.related){
|
|
85
|
-
const uri = rel.startsWith("silk://") ? rel : `silk://${rel}`;
|
|
86
|
-
if (present.has(uri)) continue;
|
|
87
|
-
const neighbor = this.byUri.get(uri);
|
|
88
|
-
if (neighbor) {
|
|
89
|
-
present.add(uri);
|
|
90
|
-
seeAlso.push({
|
|
91
|
-
item: neighbor,
|
|
92
|
-
confidence: 0,
|
|
93
|
-
matchedOn: [
|
|
94
|
-
"related"
|
|
95
|
-
]
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return [
|
|
100
|
-
...ranked,
|
|
101
|
-
...seeAlso
|
|
102
|
-
].slice(0, limit).map(({ item, confidence, matchedOn })=>({
|
|
103
|
-
uri: item.uri,
|
|
104
|
-
title: item.title,
|
|
105
|
-
summary: item.summary,
|
|
106
|
-
tags: item.tags,
|
|
107
|
-
tier: item.tier,
|
|
108
|
-
confidence: Number(confidence.toFixed(3)),
|
|
109
|
-
confidenceLabel: confidenceLabel(confidence),
|
|
110
|
-
matchedOn: [
|
|
111
|
-
...new Set(matchedOn)
|
|
112
|
-
].filter(Boolean),
|
|
113
|
-
related: item.related
|
|
114
|
-
}));
|
|
115
|
-
}
|
|
116
|
-
fallback(tier) {
|
|
117
|
-
return this.entries.filter((e)=>tier ? e.tier === tier : true).slice().sort((a, b)=>(b.priority ?? 0.5) - (a.priority ?? 0.5)).slice(0, 5).map((item)=>({
|
|
118
|
-
item,
|
|
119
|
-
confidence: 0,
|
|
120
|
-
matchedOn: []
|
|
121
|
-
}));
|
|
122
|
-
}
|
|
123
|
-
}
|
|
7
|
+
import { NodeContext } from "@effect/platform-node";
|
|
8
|
+
|
|
9
|
+
//#region src/bin.ts
|
|
10
|
+
/**
|
|
11
|
+
* Binary entrypoint for the `savvy-mcp` server.
|
|
12
|
+
*
|
|
13
|
+
* Resolves the project working directory, builds the long-lived runtime, and
|
|
14
|
+
* starts the MCP server over stdio.
|
|
15
|
+
*
|
|
16
|
+
* @internal
|
|
17
|
+
*/
|
|
18
|
+
/* v8 ignore start -- process bootstrap; covered by server.smoke.test.ts */
|
|
124
19
|
function resolveProjectDir() {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return fromArgv ?? process.env.SAVVY_MCP_PROJECT_DIR ?? process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
20
|
+
const argv = process.argv[2];
|
|
21
|
+
return (argv !== void 0 && argv.trim().length > 0 && !(argv.startsWith("${") && argv.endsWith("}")) ? argv.trim() : void 0) ?? process.env.SAVVY_MCP_PROJECT_DIR ?? process.env.CLAUDE_PROJECT_DIR ?? process.cwd();
|
|
128
22
|
}
|
|
129
23
|
async function main() {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
contentRoot
|
|
146
|
-
};
|
|
147
|
-
process.stderr.write(`[savvy-mcp] starting in ${cwd}\n`);
|
|
148
|
-
await startMcpServer(ctx);
|
|
24
|
+
const cwd = resolveProjectDir();
|
|
25
|
+
const appLayer = SilkRuntimeLive.pipe(Layer.provide(NodeContext.layer));
|
|
26
|
+
const runtime = ManagedRuntime.make(appLayer);
|
|
27
|
+
const contentRoot = resolveContentRoot();
|
|
28
|
+
const manifest = loadManifest(contentRoot);
|
|
29
|
+
const bodies = Object.fromEntries(manifest.entries.map((e) => [e.uri, readDocBody(contentRoot, e.uri.replace(/^silk:\/\//, ""))]));
|
|
30
|
+
const ctx = {
|
|
31
|
+
runtime,
|
|
32
|
+
cwd,
|
|
33
|
+
docIndex: DocIndex.fromManifest(manifest, bodies),
|
|
34
|
+
manifest,
|
|
35
|
+
contentRoot
|
|
36
|
+
};
|
|
37
|
+
process.stderr.write(`[savvy-mcp] starting in ${cwd}\n`);
|
|
38
|
+
await startMcpServer(ctx);
|
|
149
39
|
}
|
|
150
|
-
main().catch((err)=>{
|
|
151
|
-
|
|
152
|
-
|
|
40
|
+
main().catch((err) => {
|
|
41
|
+
process.stderr.write(`savvy-mcp: ${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
|
|
42
|
+
process.exit(1);
|
|
153
43
|
});
|
|
44
|
+
/* v8 ignore stop */
|
|
45
|
+
|
|
46
|
+
//#endregion
|
|
47
|
+
export { };
|
package/package.json
CHANGED
|
@@ -1,82 +1,44 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"resources/content/_templates/standards.md",
|
|
45
|
-
"resources/content/guides/api-docs-from-api-extractor.md",
|
|
46
|
-
"resources/content/guides/building-a-github-action.md",
|
|
47
|
-
"resources/content/guides/choosing-a-builder.md",
|
|
48
|
-
"resources/content/guides/llm-friendly-json-schemas.md",
|
|
49
|
-
"resources/content/manifest.json",
|
|
50
|
-
"resources/content/packages/cli/command-tree.md",
|
|
51
|
-
"resources/content/packages/cli/init-and-check.md",
|
|
52
|
-
"resources/content/packages/mcp/resource-taxonomy.md",
|
|
53
|
-
"resources/content/packages/rslib-builder/overview.md",
|
|
54
|
-
"resources/content/packages/silk-effects/index.md",
|
|
55
|
-
"resources/content/packages/silk-effects/managed-section.md",
|
|
56
|
-
"resources/content/packages/silk-effects/platform-layers.md",
|
|
57
|
-
"resources/content/packages/silk/export-map.md",
|
|
58
|
-
"resources/content/packages/silk/install-and-setup.md",
|
|
59
|
-
"resources/content/standards/api-model-pipeline.md",
|
|
60
|
-
"resources/content/standards/catalog-usage.md",
|
|
61
|
-
"resources/content/standards/changeset-discipline.md",
|
|
62
|
-
"resources/content/standards/changeset-format.md",
|
|
63
|
-
"resources/content/standards/commit-contract.md",
|
|
64
|
-
"resources/content/standards/dependency-conventions.md",
|
|
65
|
-
"resources/content/standards/linting-conventions.md",
|
|
66
|
-
"resources/content/standards/publishability.md",
|
|
67
|
-
"resources/content/standards/semver.md",
|
|
68
|
-
"resources/content/standards/test-classification.md",
|
|
69
|
-
"resources/content/tags.json",
|
|
70
|
-
"tsdoc-metadata.json"
|
|
71
|
-
],
|
|
72
|
-
"dependencies": {
|
|
73
|
-
"@effect/platform": "^0.96.1",
|
|
74
|
-
"@effect/platform-node": "^0.106.0",
|
|
75
|
-
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
76
|
-
"@savvy-web/silk-effects": "0.6.0",
|
|
77
|
-
"effect": "^3.21.2",
|
|
78
|
-
"fuse.js": "^7.4.0",
|
|
79
|
-
"workspaces-effect": "^1.1.0",
|
|
80
|
-
"zod": "^4.4.3"
|
|
81
|
-
}
|
|
2
|
+
"name": "@savvy-web/mcp",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"private": false,
|
|
5
|
+
"description": "The savvy MCP server — Silk Suite tooling and library knowledge for coding agents",
|
|
6
|
+
"homepage": "https://github.com/savvy-web/systems/tree/main/packages/mcp",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/savvy-web/systems/issues"
|
|
9
|
+
},
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/savvy-web/systems.git",
|
|
13
|
+
"directory": "packages/mcp"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"author": {
|
|
17
|
+
"name": "C. Spencer Beggs",
|
|
18
|
+
"email": "spencer@savvyweb.systems",
|
|
19
|
+
"url": "https://savvyweb.systems"
|
|
20
|
+
},
|
|
21
|
+
"type": "module",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"types": "./index.d.ts",
|
|
25
|
+
"import": "./index.js"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"bin": {
|
|
29
|
+
"savvy-mcp": "bin/savvy-mcp.js"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"public"
|
|
33
|
+
],
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@effect/platform": "^0.96.1",
|
|
36
|
+
"@effect/platform-node": "^0.106.0",
|
|
37
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
38
|
+
"@savvy-web/silk-effects": "1.0.0",
|
|
39
|
+
"effect": "^3.21.2",
|
|
40
|
+
"fuse.js": "^7.4.0",
|
|
41
|
+
"workspaces-effect": "^1.1.0",
|
|
42
|
+
"zod": "^4.4.3"
|
|
43
|
+
}
|
|
82
44
|
}
|