@systemdox/mcp-server 0.1.14 → 0.1.16
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 +3 -2
- package/dist/cli.js +270 -48
- package/dist/http.js +251 -47
- package/dist/index.js +251 -47
- package/dist/lib/config-links.d.ts +18 -0
- package/dist/lib/config-links.js +21 -0
- package/dist/tools/get-plan-board.d.ts +27 -0
- package/dist/tools/get-plan-board.js +208 -0
- package/package.json +1 -1
package/dist/http.js
CHANGED
|
@@ -200,6 +200,22 @@ function legacyToolDescription(canonical, description) {
|
|
|
200
200
|
return `DEPRECATED \u2014 use \`${canonical}\` instead. This name still works and will not be removed before ${LEGACY_TOOL_REMOVAL_EARLIEST}. ${description}`;
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
+
// src/lib/config-links.ts
|
|
204
|
+
async function workspaceBase(apiClient) {
|
|
205
|
+
try {
|
|
206
|
+
const access = await apiClient.get(
|
|
207
|
+
"/v1/docs/portal-access"
|
|
208
|
+
);
|
|
209
|
+
const slug = (access.host ?? "").split(".")[0];
|
|
210
|
+
return slug ? `https://${slug}.systemdox.com` : null;
|
|
211
|
+
} catch {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function configLink(path, base) {
|
|
216
|
+
return base ? `${base}${path}` : `${path} in your SystemDox workspace`;
|
|
217
|
+
}
|
|
218
|
+
|
|
203
219
|
// src/tools/get-guardrails.ts
|
|
204
220
|
var DESCRIPTION = "Retrieve SystemDox checks (banned patterns, required patterns, coding rules). Filter by language, category, or file path to get only relevant checks.";
|
|
205
221
|
var inputSchema = () => ({
|
|
@@ -233,13 +249,9 @@ function registerGetGuardrails(server, apiClient) {
|
|
|
233
249
|
);
|
|
234
250
|
}
|
|
235
251
|
if (filtered.length === 0) {
|
|
252
|
+
const text2 = guardrails.length === 0 ? `No checks found. Add checks at ${configLink("/docs/guardrails", await workspaceBase(apiClient))}` : `No checks found${lang ? ` for language "${lang}"` : ""}${category ? ` in category "${category}"` : ""}.`;
|
|
236
253
|
return {
|
|
237
|
-
content: [
|
|
238
|
-
{
|
|
239
|
-
type: "text",
|
|
240
|
-
text: `No checks found${lang ? ` for language "${lang}"` : ""}${category ? ` in category "${category}"` : ""}.`
|
|
241
|
-
}
|
|
242
|
-
]
|
|
254
|
+
content: [{ type: "text", text: text2 }]
|
|
243
255
|
};
|
|
244
256
|
}
|
|
245
257
|
const text = filtered.map(
|
|
@@ -494,7 +506,7 @@ function registerGetTechStack(server, apiClient) {
|
|
|
494
506
|
content: [
|
|
495
507
|
{
|
|
496
508
|
type: "text",
|
|
497
|
-
text:
|
|
509
|
+
text: `No tech stack entries configured. Add your stack at ${configLink("/docs/tech-stack", await workspaceBase(apiClient))}`
|
|
498
510
|
}
|
|
499
511
|
]
|
|
500
512
|
};
|
|
@@ -580,11 +592,21 @@ ${adrs}`);
|
|
|
580
592
|
|
|
581
593
|
${specs}`);
|
|
582
594
|
}
|
|
595
|
+
if (sections.length === 0) {
|
|
596
|
+
return {
|
|
597
|
+
content: [
|
|
598
|
+
{
|
|
599
|
+
type: "text",
|
|
600
|
+
text: `No planning context available. Connect repositories at ${configLink("/settings/github", await workspaceBase(apiClient))}`
|
|
601
|
+
}
|
|
602
|
+
]
|
|
603
|
+
};
|
|
604
|
+
}
|
|
583
605
|
return {
|
|
584
606
|
content: [
|
|
585
607
|
{
|
|
586
608
|
type: "text",
|
|
587
|
-
text: sections.join("\n\n")
|
|
609
|
+
text: sections.join("\n\n")
|
|
588
610
|
}
|
|
589
611
|
]
|
|
590
612
|
};
|
|
@@ -592,8 +614,193 @@ ${specs}`);
|
|
|
592
614
|
);
|
|
593
615
|
}
|
|
594
616
|
|
|
595
|
-
// src/tools/get-
|
|
617
|
+
// src/tools/get-plan-board.ts
|
|
596
618
|
import { z as z5 } from "zod";
|
|
619
|
+
var API_ITEM_PAGE = 100;
|
|
620
|
+
var DEFAULT_LIMIT = 50;
|
|
621
|
+
var BUCKET_LABELS = {
|
|
622
|
+
inProgress: "In Progress",
|
|
623
|
+
todo: "Todo",
|
|
624
|
+
done: "Done"
|
|
625
|
+
};
|
|
626
|
+
var BUCKET_ORDER = ["inProgress", "todo", "done"];
|
|
627
|
+
var STATUS_ARG_TO_BUCKET = {
|
|
628
|
+
todo: "todo",
|
|
629
|
+
in_progress: "inProgress",
|
|
630
|
+
done: "done"
|
|
631
|
+
};
|
|
632
|
+
function bucketOf(item) {
|
|
633
|
+
const status = (item.fields?.Status ?? "").trim().toLowerCase();
|
|
634
|
+
if (status) {
|
|
635
|
+
if (status.includes("done") || status.includes("ship") || status.includes("complete")) {
|
|
636
|
+
return "done";
|
|
637
|
+
}
|
|
638
|
+
if (status.includes("progress") || status.includes("doing") || status.includes("review")) {
|
|
639
|
+
return "inProgress";
|
|
640
|
+
}
|
|
641
|
+
return "todo";
|
|
642
|
+
}
|
|
643
|
+
return item.state === "CLOSED" ? "done" : "todo";
|
|
644
|
+
}
|
|
645
|
+
function formatBoards(boards) {
|
|
646
|
+
const lines = boards.map((b) => {
|
|
647
|
+
const c = b.statusCounts ?? { todo: 0, inProgress: 0, done: 0 };
|
|
648
|
+
return `- **${b.title}** \u2014 board #${b.number} \xB7 ${b.itemCount} item(s) (todo ${c.todo} \xB7 in progress ${c.inProgress} \xB7 done ${c.done})` + (b.description ? `
|
|
649
|
+
${b.description}` : "") + `
|
|
650
|
+
${b.url}`;
|
|
651
|
+
});
|
|
652
|
+
return lines.join("\n");
|
|
653
|
+
}
|
|
654
|
+
function formatItem(item) {
|
|
655
|
+
const meta = [];
|
|
656
|
+
if (item.labels.length > 0) meta.push(`labels: ${item.labels.join(", ")}`);
|
|
657
|
+
if (item.assignees.length > 0)
|
|
658
|
+
meta.push(`assignees: ${item.assignees.join(", ")}`);
|
|
659
|
+
const epic = item.fields?.Epic;
|
|
660
|
+
if (epic) meta.push(`epic: ${epic}`);
|
|
661
|
+
return `- #${item.number} ${item.title}${item.repo ? ` \u2014 ${item.repo}` : ""}` + (meta.length > 0 ? `
|
|
662
|
+
${meta.join(" \xB7 ")}` : "") + (item.url ? `
|
|
663
|
+
${item.url}` : "");
|
|
664
|
+
}
|
|
665
|
+
function registerGetPlanBoard(server, apiClient) {
|
|
666
|
+
server.registerTool(
|
|
667
|
+
"get_plan_board",
|
|
668
|
+
{
|
|
669
|
+
title: "Get Plan Board",
|
|
670
|
+
description: "Read the GitHub Projects boards connected to this workspace. With no arguments, lists the open boards with their item counts by status. With project_number, lists that board's issues grouped by status (In Progress / Todo / Done), each with issue number, title, repo, labels, assignees and URL \u2014 so you can see what is planned or in flight and pick up the right issue. Read-only: this tool cannot create, move, or close board items.",
|
|
671
|
+
inputSchema: {
|
|
672
|
+
project_number: z5.number().int().positive().optional().describe(
|
|
673
|
+
"Board number (the N in github.com/orgs/{org}/projects/N). Omit to list the open boards."
|
|
674
|
+
),
|
|
675
|
+
status: z5.enum(["todo", "in_progress", "done"]).optional().describe(
|
|
676
|
+
"With project_number, return only the items in this status group"
|
|
677
|
+
),
|
|
678
|
+
limit: z5.number().int().positive().max(200).optional().describe(
|
|
679
|
+
`Max items to list (default ${DEFAULT_LIMIT}). Group headings always show the true totals.`
|
|
680
|
+
)
|
|
681
|
+
}
|
|
682
|
+
},
|
|
683
|
+
async ({ project_number, status, limit }) => {
|
|
684
|
+
if (project_number === void 0) {
|
|
685
|
+
const boards = await apiClient.get(
|
|
686
|
+
"/v1/planning/projects"
|
|
687
|
+
);
|
|
688
|
+
if (boards.length === 0) {
|
|
689
|
+
return {
|
|
690
|
+
content: [
|
|
691
|
+
{
|
|
692
|
+
type: "text",
|
|
693
|
+
text: `No project boards found. Connect a GitHub organisation and create a board at ${configLink("/plan", await workspaceBase(apiClient))}`
|
|
694
|
+
}
|
|
695
|
+
]
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
const open = boards.filter((b) => !b.closed);
|
|
699
|
+
if (open.length === 0) {
|
|
700
|
+
return {
|
|
701
|
+
content: [
|
|
702
|
+
{
|
|
703
|
+
type: "text",
|
|
704
|
+
text: `No open project boards (${boards.length} closed). Reopen one, or create a board at ${configLink("/plan", await workspaceBase(apiClient))}`
|
|
705
|
+
}
|
|
706
|
+
]
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
const closedNote = boards.length > open.length ? `
|
|
710
|
+
|
|
711
|
+
_${boards.length - open.length} closed board(s) not listed._` : "";
|
|
712
|
+
return {
|
|
713
|
+
content: [
|
|
714
|
+
{
|
|
715
|
+
type: "text",
|
|
716
|
+
text: `${open.length} open project board(s):
|
|
717
|
+
|
|
718
|
+
${formatBoards(open)}` + closedNote + `
|
|
719
|
+
|
|
720
|
+
Call get_plan_board with project_number to list a board's issues.`
|
|
721
|
+
}
|
|
722
|
+
]
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
const response = await apiClient.get(
|
|
726
|
+
`/v1/planning/projects/${project_number}/items`
|
|
727
|
+
);
|
|
728
|
+
const allItems = response.items ?? [];
|
|
729
|
+
const boardName = response.projectTitle ? `**${response.projectTitle}** \u2014 board #${project_number}` : `Board #${project_number}`;
|
|
730
|
+
if (allItems.length === 0) {
|
|
731
|
+
return {
|
|
732
|
+
content: [
|
|
733
|
+
{
|
|
734
|
+
type: "text",
|
|
735
|
+
text: `${boardName} has no issues, or it is not visible to this workspace's GitHub connection. Check the board at ${configLink("/plan", await workspaceBase(apiClient))}`
|
|
736
|
+
}
|
|
737
|
+
]
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
const grouped = {
|
|
741
|
+
inProgress: [],
|
|
742
|
+
todo: [],
|
|
743
|
+
done: []
|
|
744
|
+
};
|
|
745
|
+
for (const item of allItems) grouped[bucketOf(item)].push(item);
|
|
746
|
+
const wanted = status ? [STATUS_ARG_TO_BUCKET[status]] : BUCKET_ORDER;
|
|
747
|
+
const shown = wanted.reduce((n, b) => n + grouped[b].length, 0);
|
|
748
|
+
if (shown === 0) {
|
|
749
|
+
return {
|
|
750
|
+
content: [
|
|
751
|
+
{
|
|
752
|
+
type: "text",
|
|
753
|
+
text: `${boardName}: no items with status "${status}" (of ${allItems.length} item(s) on the board).`
|
|
754
|
+
}
|
|
755
|
+
]
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
const cap = limit ?? DEFAULT_LIMIT;
|
|
759
|
+
let budget = cap;
|
|
760
|
+
const sections = [];
|
|
761
|
+
let rendered = 0;
|
|
762
|
+
for (const b of wanted) {
|
|
763
|
+
const items = grouped[b];
|
|
764
|
+
if (items.length === 0) continue;
|
|
765
|
+
const slice = items.slice(0, Math.max(budget, 0));
|
|
766
|
+
budget -= slice.length;
|
|
767
|
+
rendered += slice.length;
|
|
768
|
+
const omitted = items.length - slice.length;
|
|
769
|
+
sections.push(
|
|
770
|
+
`### ${BUCKET_LABELS[b]} (${items.length})
|
|
771
|
+
` + (slice.length > 0 ? slice.map(formatItem).join("\n") : "_(not listed \u2014 item limit reached)_") + (omitted > 0 && slice.length > 0 ? `
|
|
772
|
+
_\u2026${omitted} more not listed._` : "")
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
const notes = [];
|
|
776
|
+
if (rendered < shown) {
|
|
777
|
+
notes.push(
|
|
778
|
+
`_Listing ${rendered} of ${shown} matching item(s) \u2014 raise limit (max 200) or filter by status to see the rest._`
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
if (allItems.length >= API_ITEM_PAGE) {
|
|
782
|
+
notes.push(
|
|
783
|
+
`_The API reads the board's first ${API_ITEM_PAGE} items; a larger board may have more._`
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
return {
|
|
787
|
+
content: [
|
|
788
|
+
{
|
|
789
|
+
type: "text",
|
|
790
|
+
text: `${boardName} \u2014 ${allItems.length} item(s)
|
|
791
|
+
|
|
792
|
+
` + sections.join("\n\n") + (notes.length > 0 ? `
|
|
793
|
+
|
|
794
|
+
${notes.join("\n")}` : "")
|
|
795
|
+
}
|
|
796
|
+
]
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
);
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
// src/tools/get-context.ts
|
|
803
|
+
import { z as z6 } from "zod";
|
|
597
804
|
|
|
598
805
|
// src/lib/scoring.ts
|
|
599
806
|
var WEIGHT_PATH = 0.4;
|
|
@@ -1160,13 +1367,13 @@ function registerGetContext(server, apiClient) {
|
|
|
1160
1367
|
title: "Get Context",
|
|
1161
1368
|
description: "Intelligent context aggregator: fetches checks, specs, docs, and tech stack, ranks them by relevance to your current task, and returns the full text of the highest-ranked items within a token budget \u2014 each with the ID needed to fetch the rest. Use this instead of calling individual tools when you want curated, relevant context.",
|
|
1162
1369
|
inputSchema: {
|
|
1163
|
-
task_description:
|
|
1370
|
+
task_description: z6.string().describe(
|
|
1164
1371
|
"What you're working on (e.g., 'add a new REST endpoint for user preferences')"
|
|
1165
1372
|
),
|
|
1166
|
-
file_paths:
|
|
1373
|
+
file_paths: z6.array(z6.string()).optional().describe(
|
|
1167
1374
|
"File paths being edited \u2014 used for language/category detection"
|
|
1168
1375
|
),
|
|
1169
|
-
max_tokens:
|
|
1376
|
+
max_tokens: z6.number().optional().describe("Maximum token budget for the response (default: 4000)")
|
|
1170
1377
|
}
|
|
1171
1378
|
},
|
|
1172
1379
|
async ({ task_description, file_paths, max_tokens }) => {
|
|
@@ -1183,7 +1390,7 @@ function registerGetContext(server, apiClient) {
|
|
|
1183
1390
|
}
|
|
1184
1391
|
|
|
1185
1392
|
// src/tools/create-guardrail.ts
|
|
1186
|
-
import { z as
|
|
1393
|
+
import { z as z7 } from "zod";
|
|
1187
1394
|
var DESCRIPTION2 = "Create a new check in SystemDox. Use this when you discover a pattern that should be enforced (banned pattern, required pattern, coding rule).";
|
|
1188
1395
|
var CATEGORIES = [
|
|
1189
1396
|
"imports",
|
|
@@ -1196,13 +1403,13 @@ var CATEGORIES = [
|
|
|
1196
1403
|
"data-access"
|
|
1197
1404
|
];
|
|
1198
1405
|
var inputSchema2 = () => ({
|
|
1199
|
-
title:
|
|
1200
|
-
description:
|
|
1201
|
-
severity:
|
|
1202
|
-
category:
|
|
1203
|
-
pattern:
|
|
1204
|
-
fix:
|
|
1205
|
-
fitness_test:
|
|
1406
|
+
title: z7.string().describe("Short title for the check"),
|
|
1407
|
+
description: z7.string().describe("Detailed description of what the check enforces and why"),
|
|
1408
|
+
severity: z7.enum(["critical", "high", "medium", "low"]).describe("Severity level"),
|
|
1409
|
+
category: z7.enum(CATEGORIES).optional().describe("Category (defaults to conventions)"),
|
|
1410
|
+
pattern: z7.string().optional().describe("Bad code pattern that should be avoided"),
|
|
1411
|
+
fix: z7.string().optional().describe("Correct code pattern to use instead"),
|
|
1412
|
+
fitness_test: z7.string().optional().describe("Shell command to detect violations in CI")
|
|
1206
1413
|
});
|
|
1207
1414
|
function registerCreateGuardrail(server, apiClient) {
|
|
1208
1415
|
const handler2 = async ({
|
|
@@ -1268,7 +1475,7 @@ function registerCreateGuardrail(server, apiClient) {
|
|
|
1268
1475
|
}
|
|
1269
1476
|
|
|
1270
1477
|
// src/tools/update-spec.ts
|
|
1271
|
-
import { z as
|
|
1478
|
+
import { z as z8 } from "zod";
|
|
1272
1479
|
function registerUpdateSpec(server, apiClient) {
|
|
1273
1480
|
server.registerTool(
|
|
1274
1481
|
"update_spec",
|
|
@@ -1276,12 +1483,12 @@ function registerUpdateSpec(server, apiClient) {
|
|
|
1276
1483
|
title: "Update Spec",
|
|
1277
1484
|
description: "Update an existing SystemDox spec's proposal, tasks, or requirements. Only draft specs can be modified \u2014 published specs must be versioned first.",
|
|
1278
1485
|
inputSchema: {
|
|
1279
|
-
spec_id:
|
|
1280
|
-
section:
|
|
1281
|
-
content:
|
|
1486
|
+
spec_id: z8.string().describe("ID of the spec to update"),
|
|
1487
|
+
section: z8.enum(["proposal", "tasks", "requirements"]).describe("Which section to update"),
|
|
1488
|
+
content: z8.string().describe(
|
|
1282
1489
|
"New markdown content for the section. For requirements, provide the full requirement content."
|
|
1283
1490
|
),
|
|
1284
|
-
requirement_name:
|
|
1491
|
+
requirement_name: z8.string().optional().describe(
|
|
1285
1492
|
"Name of the requirement (required when section is 'requirements')"
|
|
1286
1493
|
)
|
|
1287
1494
|
},
|
|
@@ -1331,7 +1538,7 @@ function registerUpdateSpec(server, apiClient) {
|
|
|
1331
1538
|
}
|
|
1332
1539
|
|
|
1333
1540
|
// src/tools/report-decision.ts
|
|
1334
|
-
import { z as
|
|
1541
|
+
import { z as z9 } from "zod";
|
|
1335
1542
|
function registerReportDecision(server, apiClient) {
|
|
1336
1543
|
server.registerTool(
|
|
1337
1544
|
"report_decision",
|
|
@@ -1339,11 +1546,11 @@ function registerReportDecision(server, apiClient) {
|
|
|
1339
1546
|
title: "Report Decision",
|
|
1340
1547
|
description: "Record an architecture decision made during development. Creates a draft ADR in SystemDox for human review.",
|
|
1341
1548
|
inputSchema: {
|
|
1342
|
-
title:
|
|
1343
|
-
context:
|
|
1344
|
-
decision:
|
|
1345
|
-
consequences:
|
|
1346
|
-
related_files:
|
|
1549
|
+
title: z9.string().describe("Decision title (e.g., 'Use WebSocket for real-time updates')"),
|
|
1550
|
+
context: z9.string().describe("What prompted this decision \u2014 the problem or constraint"),
|
|
1551
|
+
decision: z9.string().describe("What was decided and why"),
|
|
1552
|
+
consequences: z9.string().describe("What this decision means going forward \u2014 trade-offs, follow-up work"),
|
|
1553
|
+
related_files: z9.array(z9.string()).optional().describe("File paths related to this decision")
|
|
1347
1554
|
},
|
|
1348
1555
|
annotations: {
|
|
1349
1556
|
readOnlyHint: false
|
|
@@ -1394,7 +1601,7 @@ Status: draft \u2014 review in SystemDox before publishing.`
|
|
|
1394
1601
|
}
|
|
1395
1602
|
|
|
1396
1603
|
// src/tools/get-project-rules.ts
|
|
1397
|
-
import { z as
|
|
1604
|
+
import { z as z10 } from "zod";
|
|
1398
1605
|
var CATEGORY_LABELS = {
|
|
1399
1606
|
deployment: "Deployment",
|
|
1400
1607
|
architecture: "Architecture",
|
|
@@ -1410,7 +1617,7 @@ function registerGetProjectRules(server, apiClient) {
|
|
|
1410
1617
|
title: "Get Project Rules",
|
|
1411
1618
|
description: "Retrieve project rules defined in SystemDox Standards. These are team-defined principles covering deployment, architecture, security, testing, and process. Filter by category to get only relevant rules.",
|
|
1412
1619
|
inputSchema: {
|
|
1413
|
-
category:
|
|
1620
|
+
category: z10.enum(["deployment", "architecture", "security", "testing", "process", "other"]).optional().describe("Filter by rule category")
|
|
1414
1621
|
}
|
|
1415
1622
|
},
|
|
1416
1623
|
async ({ category }) => {
|
|
@@ -1424,13 +1631,9 @@ function registerGetProjectRules(server, apiClient) {
|
|
|
1424
1631
|
);
|
|
1425
1632
|
}
|
|
1426
1633
|
if (filtered.length === 0) {
|
|
1634
|
+
const text2 = rules.length === 0 ? `No project rules found. Add rules at ${configLink("/docs/rules", await workspaceBase(apiClient))}` : `No project rules found${category ? ` in category "${category}"` : ""}.`;
|
|
1427
1635
|
return {
|
|
1428
|
-
content: [
|
|
1429
|
-
{
|
|
1430
|
-
type: "text",
|
|
1431
|
-
text: `No project rules found${category ? ` in category "${category}"` : ""}.`
|
|
1432
|
-
}
|
|
1433
|
-
]
|
|
1636
|
+
content: [{ type: "text", text: text2 }]
|
|
1434
1637
|
};
|
|
1435
1638
|
}
|
|
1436
1639
|
const grouped = /* @__PURE__ */ new Map();
|
|
@@ -1466,7 +1669,7 @@ function registerGetProjectRules(server, apiClient) {
|
|
|
1466
1669
|
}
|
|
1467
1670
|
|
|
1468
1671
|
// src/tools/create-project-rule.ts
|
|
1469
|
-
import { z as
|
|
1672
|
+
import { z as z11 } from "zod";
|
|
1470
1673
|
function registerCreateProjectRule(server, apiClient) {
|
|
1471
1674
|
server.registerTool(
|
|
1472
1675
|
"create_project_rule",
|
|
@@ -1474,10 +1677,10 @@ function registerCreateProjectRule(server, apiClient) {
|
|
|
1474
1677
|
title: "Create Project Rule",
|
|
1475
1678
|
description: "Create a new project rule in SystemDox Standards. Use this when you discover a team principle or convention that should be enforced across the project.",
|
|
1476
1679
|
inputSchema: {
|
|
1477
|
-
text:
|
|
1680
|
+
text: z11.string().describe(
|
|
1478
1681
|
"The rule statement \u2014 one enforceable principle per rule (e.g. 'All deployments MUST go through GitHub Actions workflows')"
|
|
1479
1682
|
),
|
|
1480
|
-
category:
|
|
1683
|
+
category: z11.enum(["deployment", "architecture", "security", "testing", "process", "other"]).describe("Rule category")
|
|
1481
1684
|
},
|
|
1482
1685
|
annotations: {
|
|
1483
1686
|
readOnlyHint: false
|
|
@@ -1519,7 +1722,7 @@ function registerGetPromptTemplates(server, apiClient) {
|
|
|
1519
1722
|
content: [
|
|
1520
1723
|
{
|
|
1521
1724
|
type: "text",
|
|
1522
|
-
text:
|
|
1725
|
+
text: `No prompt templates found. Add templates at ${configLink("/docs/prompts", await workspaceBase(apiClient))}`
|
|
1523
1726
|
}
|
|
1524
1727
|
]
|
|
1525
1728
|
};
|
|
@@ -1548,7 +1751,7 @@ ${text}`
|
|
|
1548
1751
|
}
|
|
1549
1752
|
|
|
1550
1753
|
// src/tools/create-prompt-template.ts
|
|
1551
|
-
import { z as
|
|
1754
|
+
import { z as z12 } from "zod";
|
|
1552
1755
|
function registerCreatePromptTemplate(server, apiClient) {
|
|
1553
1756
|
server.registerTool(
|
|
1554
1757
|
"create_prompt_template",
|
|
@@ -1556,9 +1759,9 @@ function registerCreatePromptTemplate(server, apiClient) {
|
|
|
1556
1759
|
title: "Create Prompt Template",
|
|
1557
1760
|
description: "Create a new reusable prompt template in SystemDox Standards. Use this to store preconfigured prompts for common AI tasks like code reviews, documentation generation, or analysis frameworks.",
|
|
1558
1761
|
inputSchema: {
|
|
1559
|
-
name:
|
|
1560
|
-
description:
|
|
1561
|
-
prompt:
|
|
1762
|
+
name: z12.string().describe("Short name for the template"),
|
|
1763
|
+
description: z12.string().optional().describe("Brief description of when to use this template"),
|
|
1764
|
+
prompt: z12.string().describe("The full prompt text that Gen AI will use when generating content")
|
|
1562
1765
|
},
|
|
1563
1766
|
annotations: {
|
|
1564
1767
|
readOnlyHint: false
|
|
@@ -1597,6 +1800,7 @@ function createServer(apiClient) {
|
|
|
1597
1800
|
registerGetDocs(server, apiClient);
|
|
1598
1801
|
registerGetTechStack(server, apiClient);
|
|
1599
1802
|
registerGetPlanningContext(server, apiClient);
|
|
1803
|
+
registerGetPlanBoard(server, apiClient);
|
|
1600
1804
|
registerGetContext(server, apiClient);
|
|
1601
1805
|
registerGetProjectRules(server, apiClient);
|
|
1602
1806
|
registerGetPromptTemplates(server, apiClient);
|