@stackwright-pro/mcp 0.2.0-alpha.16 → 0.2.0-alpha.17
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/dist/integrity.js +9 -9
- package/dist/integrity.js.map +1 -1
- package/dist/integrity.mjs +9 -9
- package/dist/integrity.mjs.map +1 -1
- package/dist/server.js +128 -27
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +128 -27
- package/dist/server.mjs.map +1 -1
- package/package.json +1 -1
package/dist/server.mjs
CHANGED
|
@@ -1383,12 +1383,12 @@ function registerQuestionTools(server2) {
|
|
|
1383
1383
|
content: [
|
|
1384
1384
|
{
|
|
1385
1385
|
type: "text",
|
|
1386
|
-
text:
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1386
|
+
text: `Phase "${phase}" has no questions to present. Do NOT call ask_user_question. Call stackwright_pro_save_phase_answers({ phase: "${phase}", rawAnswers: [] }) directly, then proceed to the execution step for this phase.`
|
|
1387
|
+
},
|
|
1388
|
+
{
|
|
1389
|
+
type: "text",
|
|
1390
|
+
// Empty array — second block always present so the foreman's two-block contract holds
|
|
1391
|
+
text: JSON.stringify([])
|
|
1392
1392
|
}
|
|
1393
1393
|
],
|
|
1394
1394
|
isError: false
|
|
@@ -1580,7 +1580,57 @@ function handleGetOtterName(input) {
|
|
|
1580
1580
|
isError: false
|
|
1581
1581
|
};
|
|
1582
1582
|
}
|
|
1583
|
+
function handleSaveBuildContext(input) {
|
|
1584
|
+
const cwd = input._cwd ?? process.cwd();
|
|
1585
|
+
const dir = join2(cwd, ".stackwright");
|
|
1586
|
+
const filePath = join2(dir, "build-context.json");
|
|
1587
|
+
try {
|
|
1588
|
+
mkdirSync(dir, { recursive: true });
|
|
1589
|
+
if (existsSync2(filePath)) {
|
|
1590
|
+
const stat = lstatSync2(filePath);
|
|
1591
|
+
if (stat.isSymbolicLink()) {
|
|
1592
|
+
return {
|
|
1593
|
+
text: JSON.stringify({
|
|
1594
|
+
success: false,
|
|
1595
|
+
error: `Refusing to write to symlink: ${filePath}`
|
|
1596
|
+
}),
|
|
1597
|
+
isError: true
|
|
1598
|
+
};
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
const payload = {
|
|
1602
|
+
version: "1.0",
|
|
1603
|
+
savedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1604
|
+
buildContext: input.buildContext
|
|
1605
|
+
};
|
|
1606
|
+
writeFileSync2(filePath, JSON.stringify(payload, null, 2) + "\n");
|
|
1607
|
+
return {
|
|
1608
|
+
text: JSON.stringify({ success: true, path: filePath }),
|
|
1609
|
+
isError: false
|
|
1610
|
+
};
|
|
1611
|
+
} catch (err) {
|
|
1612
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1613
|
+
return {
|
|
1614
|
+
text: JSON.stringify({ success: false, error: message }),
|
|
1615
|
+
isError: true
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
}
|
|
1583
1619
|
function registerOrchestrationTools(server2) {
|
|
1620
|
+
server2.tool(
|
|
1621
|
+
"stackwright_pro_save_build_context",
|
|
1622
|
+
`Save the user's initial build description to .stackwright/build-context.json. Call this once at startup after the user answers the opening "what are you building" question. The saved context is automatically prepended to specialist prompts by stackwright_pro_build_specialist_prompt.`,
|
|
1623
|
+
{
|
|
1624
|
+
buildContext: z9.string().describe("Free-text description of what the user wants to build")
|
|
1625
|
+
},
|
|
1626
|
+
async ({ buildContext }) => {
|
|
1627
|
+
const { text, isError } = handleSaveBuildContext({ buildContext });
|
|
1628
|
+
return {
|
|
1629
|
+
content: [{ type: "text", text }],
|
|
1630
|
+
isError
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
);
|
|
1584
1634
|
server2.tool(
|
|
1585
1635
|
"stackwright_pro_parse_otter_response",
|
|
1586
1636
|
"Parse and validate a specialist otter's QUESTION_COLLECTION_MODE JSON response. Handles JSON extraction from LLM responses (strips markdown, fixes single quotes, trailing commas). Detects the phase from the otter name. Use this immediately after invoke_agent() to get a validated manifest phase object.",
|
|
@@ -1859,28 +1909,62 @@ function handleSetPipelineState(input) {
|
|
|
1859
1909
|
return { text: JSON.stringify({ error: true, message: String(err) }), isError: true };
|
|
1860
1910
|
}
|
|
1861
1911
|
}
|
|
1862
|
-
function handleCheckExecutionReady(_cwd) {
|
|
1912
|
+
function handleCheckExecutionReady(_cwd, phase) {
|
|
1863
1913
|
const cwd = _cwd ?? process.cwd();
|
|
1914
|
+
if (phase) {
|
|
1915
|
+
if (!isValidPhase(phase)) {
|
|
1916
|
+
return {
|
|
1917
|
+
text: JSON.stringify({
|
|
1918
|
+
error: true,
|
|
1919
|
+
message: `Invalid phase: ${phase}. Valid phases are: ${PHASE_ORDER.join(", ")}`
|
|
1920
|
+
}),
|
|
1921
|
+
isError: true
|
|
1922
|
+
};
|
|
1923
|
+
}
|
|
1924
|
+
const answerFile = join3(cwd, ".stackwright", "answers", `${phase}.json`);
|
|
1925
|
+
if (!existsSync3(answerFile)) {
|
|
1926
|
+
return {
|
|
1927
|
+
text: JSON.stringify({ ready: false, phase, reason: "Answer file not found" }),
|
|
1928
|
+
isError: false
|
|
1929
|
+
};
|
|
1930
|
+
}
|
|
1931
|
+
try {
|
|
1932
|
+
const raw = safeReadSync(answerFile);
|
|
1933
|
+
const parsed = JSON.parse(raw);
|
|
1934
|
+
if (typeof parsed["version"] !== "string" || typeof parsed["phase"] !== "string" || typeof parsed["answers"] !== "object" || parsed["answers"] === null) {
|
|
1935
|
+
return {
|
|
1936
|
+
text: JSON.stringify({ ready: false, phase, reason: "Answer file is malformed" }),
|
|
1937
|
+
isError: false
|
|
1938
|
+
};
|
|
1939
|
+
}
|
|
1940
|
+
return { text: JSON.stringify({ ready: true, phase }), isError: false };
|
|
1941
|
+
} catch {
|
|
1942
|
+
return {
|
|
1943
|
+
text: JSON.stringify({ ready: false, phase, reason: "Answer file could not be parsed" }),
|
|
1944
|
+
isError: false
|
|
1945
|
+
};
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1864
1948
|
try {
|
|
1865
1949
|
const answersDir = join3(cwd, ".stackwright", "answers");
|
|
1866
1950
|
const answeredPhases = [];
|
|
1867
1951
|
const missingPhases = [];
|
|
1868
|
-
for (const
|
|
1869
|
-
const answerFile = join3(answersDir, `${
|
|
1952
|
+
for (const phase2 of PHASE_ORDER) {
|
|
1953
|
+
const answerFile = join3(answersDir, `${phase2}.json`);
|
|
1870
1954
|
if (existsSync3(answerFile)) {
|
|
1871
1955
|
try {
|
|
1872
1956
|
const raw = safeReadSync(answerFile);
|
|
1873
1957
|
const parsed = JSON.parse(raw);
|
|
1874
1958
|
if (typeof parsed["version"] !== "string" || typeof parsed["phase"] !== "string" || typeof parsed["answers"] !== "object" || parsed["answers"] === null) {
|
|
1875
|
-
missingPhases.push(
|
|
1959
|
+
missingPhases.push(phase2);
|
|
1876
1960
|
continue;
|
|
1877
1961
|
}
|
|
1878
|
-
answeredPhases.push(
|
|
1962
|
+
answeredPhases.push(phase2);
|
|
1879
1963
|
} catch {
|
|
1880
|
-
missingPhases.push(
|
|
1964
|
+
missingPhases.push(phase2);
|
|
1881
1965
|
}
|
|
1882
1966
|
} else {
|
|
1883
|
-
missingPhases.push(
|
|
1967
|
+
missingPhases.push(phase2);
|
|
1884
1968
|
}
|
|
1885
1969
|
}
|
|
1886
1970
|
return {
|
|
@@ -1990,6 +2074,17 @@ function handleBuildSpecialistPrompt(input) {
|
|
|
1990
2074
|
if (existsSync3(answersPath)) {
|
|
1991
2075
|
answers = JSON.parse(safeReadSync(answersPath));
|
|
1992
2076
|
}
|
|
2077
|
+
let buildContextText = "";
|
|
2078
|
+
const buildContextPath = join3(cwd, ".stackwright", "build-context.json");
|
|
2079
|
+
if (existsSync3(buildContextPath)) {
|
|
2080
|
+
try {
|
|
2081
|
+
const bcRaw = JSON.parse(safeReadSync(buildContextPath));
|
|
2082
|
+
if (typeof bcRaw.buildContext === "string" && bcRaw.buildContext.trim().length > 0) {
|
|
2083
|
+
buildContextText = bcRaw.buildContext.trim();
|
|
2084
|
+
}
|
|
2085
|
+
} catch {
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
1993
2088
|
const deps = PHASE_DEPENDENCIES[phase];
|
|
1994
2089
|
const artifactSections = [];
|
|
1995
2090
|
const missingDependencies = [];
|
|
@@ -2022,7 +2117,11 @@ ${JSON.stringify(content, null, 2)}`);
|
|
|
2022
2117
|
(not yet available)`);
|
|
2023
2118
|
}
|
|
2024
2119
|
}
|
|
2025
|
-
const parts = [
|
|
2120
|
+
const parts = [];
|
|
2121
|
+
if (buildContextText) {
|
|
2122
|
+
parts.push("BUILD_CONTEXT:", buildContextText, "");
|
|
2123
|
+
}
|
|
2124
|
+
parts.push("ANSWERS:", JSON.stringify(answers, null, 2));
|
|
2026
2125
|
if (artifactSections.length > 0) {
|
|
2027
2126
|
parts.push("", "UPSTREAM ARTIFACTS:", "", ...artifactSections);
|
|
2028
2127
|
}
|
|
@@ -2181,9 +2280,11 @@ function registerPipelineTools(server2) {
|
|
|
2181
2280
|
);
|
|
2182
2281
|
server2.tool(
|
|
2183
2282
|
"stackwright_pro_check_execution_ready",
|
|
2184
|
-
`Check all phases have answer files in .stackwright/answers/. ${DESC}`,
|
|
2185
|
-
{
|
|
2186
|
-
|
|
2283
|
+
`Check all phases have answer files in .stackwright/answers/. If phase is provided, check only that phase. ${DESC}`,
|
|
2284
|
+
{
|
|
2285
|
+
phase: z10.string().optional().describe("If provided, check only this phase's readiness. Omit to check all phases.")
|
|
2286
|
+
},
|
|
2287
|
+
async ({ phase }) => res(handleCheckExecutionReady(void 0, phase))
|
|
2187
2288
|
);
|
|
2188
2289
|
server2.tool(
|
|
2189
2290
|
"stackwright_pro_list_artifacts",
|
|
@@ -2867,39 +2968,39 @@ import { join as join6, basename } from "path";
|
|
|
2867
2968
|
var _checksums = /* @__PURE__ */ new Map([
|
|
2868
2969
|
[
|
|
2869
2970
|
"stackwright-pro-api-otter.json",
|
|
2870
|
-
"
|
|
2971
|
+
"d72f365d7eb16f6195148d09f8d42249cc1b01fab21e769d991533a31b0b588a"
|
|
2871
2972
|
],
|
|
2872
2973
|
[
|
|
2873
2974
|
"stackwright-pro-auth-otter.json",
|
|
2874
|
-
"
|
|
2975
|
+
"6610a5a4e1f981a00771494832a5dbf2e7897f993ed2cfad388528578d15955c"
|
|
2875
2976
|
],
|
|
2876
2977
|
[
|
|
2877
2978
|
"stackwright-pro-dashboard-otter.json",
|
|
2878
|
-
"
|
|
2979
|
+
"f0316349b38e0923c2fa5385e24c4393511c61cea410a2b080a5ece14ace4801"
|
|
2879
2980
|
],
|
|
2880
2981
|
[
|
|
2881
2982
|
"stackwright-pro-data-otter.json",
|
|
2882
|
-
"
|
|
2983
|
+
"bd85c01c352630088c3f27110bcd23b6f8f7d2eb72d62a324214ac405a4c1c65"
|
|
2883
2984
|
],
|
|
2884
2985
|
[
|
|
2885
2986
|
"stackwright-pro-designer-otter.json",
|
|
2886
|
-
"
|
|
2987
|
+
"aadac659f170c24a3921fe0940464b5dd22db290fb2d7340647c3c4795cfe246"
|
|
2887
2988
|
],
|
|
2888
2989
|
[
|
|
2889
2990
|
"stackwright-pro-foreman-otter.json",
|
|
2890
|
-
"
|
|
2991
|
+
"5bb8eca6d24efa970acc24974d3789a1ce48ead42624236bb7211c1c881b2584"
|
|
2891
2992
|
],
|
|
2892
2993
|
[
|
|
2893
2994
|
"stackwright-pro-page-otter.json",
|
|
2894
|
-
"
|
|
2995
|
+
"c5ad7b312e1c4f83183c489291233adfb5466050d6db44b8816817ac601faca8"
|
|
2895
2996
|
],
|
|
2896
2997
|
[
|
|
2897
2998
|
"stackwright-pro-theme-otter.json",
|
|
2898
|
-
"
|
|
2999
|
+
"a303ec6c045420f2c916583e3f6efcda469e9610fedfc84a508ed8a8a75866bc"
|
|
2899
3000
|
],
|
|
2900
3001
|
[
|
|
2901
3002
|
"stackwright-pro-workflow-otter.json",
|
|
2902
|
-
"
|
|
3003
|
+
"2b2d132c536148bcd1fa5598d575f2a40b572c050e1cfe17a387d306b62fd855"
|
|
2903
3004
|
]
|
|
2904
3005
|
]);
|
|
2905
3006
|
Object.freeze(_checksums);
|
|
@@ -3505,7 +3606,7 @@ var package_default = {
|
|
|
3505
3606
|
"test:coverage": "vitest run --coverage"
|
|
3506
3607
|
},
|
|
3507
3608
|
name: "@stackwright-pro/mcp",
|
|
3508
|
-
version: "0.2.0-alpha.
|
|
3609
|
+
version: "0.2.0-alpha.17",
|
|
3509
3610
|
description: "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
|
|
3510
3611
|
license: "PROPRIETARY",
|
|
3511
3612
|
main: "./dist/server.js",
|