@shiftleftpt/sbd-toe-mcp 0.6.1 → 0.6.3
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 +2 -2
- package/dist/index.js +76 -121
- package/dist/index.js.map +1 -1
- package/dist/resources/sbd-toe-resources.d.ts +1 -7
- package/dist/resources/sbd-toe-resources.js +45 -105
- package/dist/resources/sbd-toe-resources.js.map +1 -1
- package/dist/tools/generate-sbd-toe-skill.d.ts +12 -0
- package/dist/tools/generate-sbd-toe-skill.js +26 -0
- package/dist/tools/generate-sbd-toe-skill.js.map +1 -0
- package/dist/tools/plan-repo-governance.d.ts +25 -38
- package/dist/tools/plan-repo-governance.js +71 -498
- package/dist/tools/plan-repo-governance.js.map +1 -1
- package/package.json +2 -2
- package/dist/tools/generate-document.d.ts +0 -22
- package/dist/tools/generate-document.js +0 -392
- package/dist/tools/generate-document.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @shiftleftpt/sbd-toe-mcp
|
|
2
2
|
|
|
3
|
-
MCP server for the SbD-ToE security manual — structured tools for Claude, GitHub Copilot, Cursor, Windsurf, Zed and any MCP-compatible client.
|
|
3
|
+
MCP server for the **SbD-ToE** (**Security by Design — Theory of Everything**) security manual — structured tools for Claude, GitHub Copilot, Cursor, Windsurf, Zed and any MCP-compatible client.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@shiftleftpt/sbd-toe-mcp)
|
|
6
6
|
[](LICENSE)
|
|
@@ -49,7 +49,7 @@ For full installation instructions for all clients see [`docs/installation.md`](
|
|
|
49
49
|
|
|
50
50
|
## What it does
|
|
51
51
|
|
|
52
|
-
This MCP server gives any AI client structured access to the [SbD-ToE security manual](https://www.securitybydesign.dev/sbd-toe/sbd-manual/) — a
|
|
52
|
+
This MCP server gives any AI client structured access to the [SbD-ToE security manual](https://www.securitybydesign.dev/sbd-toe/sbd-manual/) — a 15-chapter (00–14) framework for Security by Design — Theory of Everything.
|
|
53
53
|
|
|
54
54
|
All data is bundled locally. No Algolia, no internet connection required at runtime, no API keys.
|
|
55
55
|
|
package/dist/index.js
CHANGED
|
@@ -7,10 +7,10 @@ import { formatSampledAnswerResult, inspectManualRetrieval, prepareManualAnsweri
|
|
|
7
7
|
import { loadSystemPromptTemplate } from "./prompt/system-prompt.js";
|
|
8
8
|
import { getSnapshotCache, retrievePublishedContext } from "./backend/semantic-index-gateway.js";
|
|
9
9
|
import { handleGetSbdToeChapterBrief, handleListSbdToeChapters, handleMapSbdToeApplicability, handleQuerySbdToeEntities } from "./tools/structured-tools.js";
|
|
10
|
-
import {
|
|
10
|
+
import { handleGenerateSbdToeSkill } from "./tools/generate-sbd-toe-skill.js";
|
|
11
11
|
import { handleMapSbdToeReviewScope } from "./tools/map-review-scope.js";
|
|
12
12
|
import { handlePlanRepoGovernance } from "./tools/plan-repo-governance.js";
|
|
13
|
-
import { buildChapterApplicabilityJson, buildSetupAgentPrompt
|
|
13
|
+
import { buildChapterApplicabilityJson, buildSetupAgentPrompt } from "./resources/sbd-toe-resources.js";
|
|
14
14
|
const PROTOCOL_VERSION = "2025-03-26";
|
|
15
15
|
const LOG_LEVELS = [
|
|
16
16
|
"debug",
|
|
@@ -255,7 +255,9 @@ class McpRuntime {
|
|
|
255
255
|
"BEFORE answering any SbD-ToE question, read resource sbd://toe/agent-guide — it contains\n" +
|
|
256
256
|
"operating modes, routing by phase/domain, tool selection, epistemic standards, and chapter map.\n" +
|
|
257
257
|
"\n" +
|
|
258
|
-
"Then run setup_sbd_toe_agent(riskLevel, projectRole) for risk-level specific active chapters
|
|
258
|
+
"Then run setup_sbd_toe_agent(riskLevel, projectRole) for risk-level specific active chapters.\n" +
|
|
259
|
+
"\n" +
|
|
260
|
+
"To create a skill or instructions file for an AI client, use generate_sbd_toe_skill(clientType)."
|
|
259
261
|
});
|
|
260
262
|
}
|
|
261
263
|
handleSetLogLevel(request) {
|
|
@@ -293,23 +295,23 @@ class McpRuntime {
|
|
|
293
295
|
{
|
|
294
296
|
name: "search_sbd_toe_manual",
|
|
295
297
|
title: "Search SbD-ToE Manual",
|
|
296
|
-
description: "
|
|
298
|
+
description: "Retrieves grounded context from the SbD-ToE manual using the embedded local semantic snapshot.",
|
|
297
299
|
inputSchema: {
|
|
298
300
|
type: "object",
|
|
299
301
|
properties: {
|
|
300
302
|
question: {
|
|
301
303
|
type: "string",
|
|
302
|
-
description: "
|
|
304
|
+
description: "Natural-language question about the manual."
|
|
303
305
|
},
|
|
304
306
|
debug: {
|
|
305
307
|
type: "boolean",
|
|
306
|
-
description: "
|
|
308
|
+
description: "When true, appends full retrieval debug information."
|
|
307
309
|
},
|
|
308
310
|
topK: {
|
|
309
311
|
type: "integer",
|
|
310
312
|
minimum: 1,
|
|
311
313
|
maximum: 15,
|
|
312
|
-
description: "
|
|
314
|
+
description: "Maximum number of records used as context."
|
|
313
315
|
}
|
|
314
316
|
},
|
|
315
317
|
required: ["question"],
|
|
@@ -322,23 +324,23 @@ class McpRuntime {
|
|
|
322
324
|
{
|
|
323
325
|
name: "answer_sbd_toe_manual",
|
|
324
326
|
title: "Answer SbD-ToE Manual",
|
|
325
|
-
description: "
|
|
327
|
+
description: "Retrieves SbD-ToE manual context and requests the final answer from the client's model via MCP sampling.",
|
|
326
328
|
inputSchema: {
|
|
327
329
|
type: "object",
|
|
328
330
|
properties: {
|
|
329
331
|
question: {
|
|
330
332
|
type: "string",
|
|
331
|
-
description: "
|
|
333
|
+
description: "Natural-language question about the manual."
|
|
332
334
|
},
|
|
333
335
|
debug: {
|
|
334
336
|
type: "boolean",
|
|
335
|
-
description: "
|
|
337
|
+
description: "When true, appends full debug information."
|
|
336
338
|
},
|
|
337
339
|
topK: {
|
|
338
340
|
type: "integer",
|
|
339
341
|
minimum: 1,
|
|
340
342
|
maximum: 15,
|
|
341
|
-
description: "
|
|
343
|
+
description: "Maximum number of records used as context."
|
|
342
344
|
}
|
|
343
345
|
},
|
|
344
346
|
required: ["question"],
|
|
@@ -351,19 +353,19 @@ class McpRuntime {
|
|
|
351
353
|
{
|
|
352
354
|
name: "inspect_sbd_toe_retrieval",
|
|
353
355
|
title: "Inspect SbD-ToE Retrieval",
|
|
354
|
-
description: "
|
|
356
|
+
description: "Inspects retrieval, context selection and final prompt without requesting an answer from the client model.",
|
|
355
357
|
inputSchema: {
|
|
356
358
|
type: "object",
|
|
357
359
|
properties: {
|
|
358
360
|
question: {
|
|
359
361
|
type: "string",
|
|
360
|
-
description: "
|
|
362
|
+
description: "Question to use for the retrieval inspection."
|
|
361
363
|
},
|
|
362
364
|
topK: {
|
|
363
365
|
type: "integer",
|
|
364
366
|
minimum: 1,
|
|
365
367
|
maximum: 15,
|
|
366
|
-
description: "
|
|
368
|
+
description: "Maximum number of records selected for the prompt."
|
|
367
369
|
}
|
|
368
370
|
},
|
|
369
371
|
required: ["question"],
|
|
@@ -376,14 +378,14 @@ class McpRuntime {
|
|
|
376
378
|
{
|
|
377
379
|
name: "list_sbd_toe_chapters",
|
|
378
380
|
title: "List SbD-ToE Chapters",
|
|
379
|
-
description: "
|
|
381
|
+
description: "Lists SbD-ToE manual chapters with id, title and applicability.",
|
|
380
382
|
inputSchema: {
|
|
381
383
|
type: "object",
|
|
382
384
|
properties: {
|
|
383
385
|
riskLevel: {
|
|
384
386
|
type: "string",
|
|
385
387
|
enum: ["L1", "L2", "L3"],
|
|
386
|
-
description: "
|
|
388
|
+
description: "Filter by risk level."
|
|
387
389
|
}
|
|
388
390
|
},
|
|
389
391
|
additionalProperties: false
|
|
@@ -393,7 +395,7 @@ class McpRuntime {
|
|
|
393
395
|
{
|
|
394
396
|
name: "query_sbd_toe_entities",
|
|
395
397
|
title: "Query SbD-ToE Entities",
|
|
396
|
-
description: "
|
|
398
|
+
description: "Queries manual entities by text, entity type, chapter or risk level.",
|
|
397
399
|
inputSchema: {
|
|
398
400
|
type: "object",
|
|
399
401
|
properties: {
|
|
@@ -411,7 +413,7 @@ class McpRuntime {
|
|
|
411
413
|
{
|
|
412
414
|
name: "get_sbd_toe_chapter_brief",
|
|
413
415
|
title: "Get SbD-ToE Chapter Brief",
|
|
414
|
-
description: "
|
|
416
|
+
description: "Returns an operational summary of a chapter: role, phases, artefacts, intent_topics.",
|
|
415
417
|
inputSchema: {
|
|
416
418
|
type: "object",
|
|
417
419
|
properties: {
|
|
@@ -424,66 +426,39 @@ class McpRuntime {
|
|
|
424
426
|
},
|
|
425
427
|
{
|
|
426
428
|
name: "plan_sbd_toe_repo_governance",
|
|
427
|
-
title: "
|
|
428
|
-
description: "
|
|
429
|
+
title: "List SbD-ToE Manual Artefacts",
|
|
430
|
+
description: "Returns the list of artefacts/documents identified in the SbD-ToE manual, " +
|
|
431
|
+
"grouped by chapter, with risk level applicability. " +
|
|
432
|
+
"Optionally filter by riskLevel (L1/L2/L3). " +
|
|
433
|
+
"All data comes from the manual indices — nothing is invented. " +
|
|
434
|
+
"The manual does not provide templates; ask the LLM to generate one if needed.",
|
|
429
435
|
inputSchema: {
|
|
430
436
|
type: "object",
|
|
431
437
|
properties: {
|
|
432
|
-
repoType: {
|
|
433
|
-
type: "string",
|
|
434
|
-
enum: ["library", "service", "webapp", "infrastructure", "pipeline", "monorepo"],
|
|
435
|
-
description: "Tipo de repositório."
|
|
436
|
-
},
|
|
437
|
-
platform: {
|
|
438
|
-
type: "string",
|
|
439
|
-
enum: ["github", "gitlab"],
|
|
440
|
-
description: "Plataforma de hosting do repositório."
|
|
441
|
-
},
|
|
442
438
|
riskLevel: {
|
|
443
439
|
type: "string",
|
|
444
440
|
enum: ["L1", "L2", "L3"],
|
|
445
|
-
description: "
|
|
446
|
-
},
|
|
447
|
-
organizationContext: {
|
|
448
|
-
type: "object",
|
|
449
|
-
description: "Contexto organizacional opcional.",
|
|
450
|
-
properties: {
|
|
451
|
-
scale: { type: "string", enum: ["startup", "mid-size", "enterprise"] },
|
|
452
|
-
teamSize: { type: "integer", minimum: 1 },
|
|
453
|
-
enforcementLevel: { type: "string", enum: ["advisory", "enforced", "strict"] }
|
|
454
|
-
},
|
|
455
|
-
additionalProperties: false
|
|
441
|
+
description: "Optional. If provided, only artefacts applicable at this risk level are returned."
|
|
456
442
|
}
|
|
457
443
|
},
|
|
458
|
-
required: [
|
|
444
|
+
required: [],
|
|
459
445
|
additionalProperties: false
|
|
460
446
|
},
|
|
461
447
|
annotations: { readOnlyHint: true }
|
|
462
448
|
},
|
|
463
449
|
{
|
|
464
|
-
name: "
|
|
465
|
-
title: "Generate SbD-ToE
|
|
466
|
-
description: "
|
|
450
|
+
name: "generate_sbd_toe_skill",
|
|
451
|
+
title: "Generate SbD-ToE Skill Content",
|
|
452
|
+
description: "Use this tool when asked to 'create a skill for SbD-ToE', 'set up instructions', " +
|
|
453
|
+
"'configure this client to use SbD-ToE', or 'integrate SbD-ToE'. " +
|
|
454
|
+
"Returns the canonical skill content from sbd://toe/agent-guide. " +
|
|
455
|
+
"Save the returned content to the appropriate skill/instructions file for your client " +
|
|
456
|
+
"(e.g. .claude/skills/sbd-toe.md, .github/copilot-instructions.md, .cursorrules). " +
|
|
457
|
+
"No parameters required.",
|
|
467
458
|
inputSchema: {
|
|
468
459
|
type: "object",
|
|
469
|
-
properties: {
|
|
470
|
-
|
|
471
|
-
type: "string",
|
|
472
|
-
enum: ["classification-template", "threat-model-template", "checklist", "training-plan", "secure-config"],
|
|
473
|
-
description: "Tipo de documento a gerar."
|
|
474
|
-
},
|
|
475
|
-
riskLevel: {
|
|
476
|
-
type: "string",
|
|
477
|
-
enum: ["L1", "L2", "L3"],
|
|
478
|
-
description: "Nível de risco do projecto."
|
|
479
|
-
},
|
|
480
|
-
context: {
|
|
481
|
-
type: "object",
|
|
482
|
-
description: "Contexto adicional do projecto (reservado, não usado na estrutura).",
|
|
483
|
-
additionalProperties: true
|
|
484
|
-
}
|
|
485
|
-
},
|
|
486
|
-
required: ["type", "riskLevel"],
|
|
460
|
+
properties: {},
|
|
461
|
+
required: [],
|
|
487
462
|
additionalProperties: false
|
|
488
463
|
},
|
|
489
464
|
annotations: { readOnlyHint: true }
|
|
@@ -491,7 +466,7 @@ class McpRuntime {
|
|
|
491
466
|
{
|
|
492
467
|
name: "map_sbd_toe_review_scope",
|
|
493
468
|
title: "Map SbD-ToE Review Scope",
|
|
494
|
-
description: "
|
|
469
|
+
description: "Given a set of changed files, maps which SbD-ToE knowledge bundles should be reviewed, with explicit reasoning per path.",
|
|
495
470
|
inputSchema: {
|
|
496
471
|
type: "object",
|
|
497
472
|
properties: {
|
|
@@ -499,16 +474,16 @@ class McpRuntime {
|
|
|
499
474
|
type: "array",
|
|
500
475
|
items: { type: "string" },
|
|
501
476
|
minItems: 1,
|
|
502
|
-
description: "
|
|
477
|
+
description: "List of paths relative to the repository root."
|
|
503
478
|
},
|
|
504
479
|
riskLevel: {
|
|
505
480
|
type: "string",
|
|
506
481
|
enum: ["L1", "L2", "L3"],
|
|
507
|
-
description: "
|
|
482
|
+
description: "Project risk level."
|
|
508
483
|
},
|
|
509
484
|
projectContext: {
|
|
510
485
|
type: "object",
|
|
511
|
-
description: "
|
|
486
|
+
description: "Additional project context (optional).",
|
|
512
487
|
properties: {
|
|
513
488
|
repoRole: { type: "string" },
|
|
514
489
|
runtimeModel: { type: "string" },
|
|
@@ -519,7 +494,7 @@ class McpRuntime {
|
|
|
519
494
|
},
|
|
520
495
|
diffSummary: {
|
|
521
496
|
type: "string",
|
|
522
|
-
description: "
|
|
497
|
+
description: "Diff summary (truncated to 500 chars)."
|
|
523
498
|
}
|
|
524
499
|
},
|
|
525
500
|
required: ["changedFiles", "riskLevel"],
|
|
@@ -530,7 +505,7 @@ class McpRuntime {
|
|
|
530
505
|
{
|
|
531
506
|
name: "map_sbd_toe_applicability",
|
|
532
507
|
title: "Map SbD-ToE Applicability",
|
|
533
|
-
description: "
|
|
508
|
+
description: "Maps active, conditional and excluded chapters/controls for a given risk level L1/L2/L3. Supports project context to activate relevant bundles.",
|
|
534
509
|
inputSchema: {
|
|
535
510
|
type: "object",
|
|
536
511
|
properties: {
|
|
@@ -546,20 +521,20 @@ class McpRuntime {
|
|
|
546
521
|
"network-segmentation", "cryptography"
|
|
547
522
|
]
|
|
548
523
|
},
|
|
549
|
-
description: "
|
|
524
|
+
description: "Technologies used in the project."
|
|
550
525
|
},
|
|
551
526
|
hasPersonalData: {
|
|
552
527
|
type: "boolean",
|
|
553
|
-
description: "
|
|
528
|
+
description: "Does the project process personal data?"
|
|
554
529
|
},
|
|
555
530
|
isPublicFacing: {
|
|
556
531
|
type: "boolean",
|
|
557
|
-
description: "
|
|
532
|
+
description: "Does the project have public-facing exposure?"
|
|
558
533
|
},
|
|
559
534
|
projectRole: {
|
|
560
535
|
type: "string",
|
|
561
536
|
enum: ["developer", "architect", "security", "devops", "manager"],
|
|
562
|
-
description: "
|
|
537
|
+
description: "User role in the project."
|
|
563
538
|
}
|
|
564
539
|
},
|
|
565
540
|
required: ["riskLevel"],
|
|
@@ -574,11 +549,11 @@ class McpRuntime {
|
|
|
574
549
|
return {
|
|
575
550
|
name: "ask_sbd_toe_manual",
|
|
576
551
|
title: "Ask SbD-ToE Manual",
|
|
577
|
-
description: "
|
|
552
|
+
description: "MCP prompt to guide the AI chat to answer questions about the SbD-ToE manual with grounding.",
|
|
578
553
|
arguments: [
|
|
579
554
|
{
|
|
580
555
|
name: "question",
|
|
581
|
-
description: "
|
|
556
|
+
description: "Question about the SbD-ToE manual.",
|
|
582
557
|
required: true
|
|
583
558
|
}
|
|
584
559
|
]
|
|
@@ -591,16 +566,16 @@ class McpRuntime {
|
|
|
591
566
|
{
|
|
592
567
|
name: "setup_sbd_toe_agent",
|
|
593
568
|
title: "Setup SbD-ToE Agent",
|
|
594
|
-
description: "
|
|
569
|
+
description: "MCP prompt to configure an agent with SbD-ToE manual context and rules for a given risk level.",
|
|
595
570
|
arguments: [
|
|
596
571
|
{
|
|
597
572
|
name: "riskLevel",
|
|
598
|
-
description: "
|
|
573
|
+
description: "Project risk level: L1, L2 or L3.",
|
|
599
574
|
required: true
|
|
600
575
|
},
|
|
601
576
|
{
|
|
602
577
|
name: "projectRole",
|
|
603
|
-
description: "
|
|
578
|
+
description: "Project role or description (optional).",
|
|
604
579
|
required: false
|
|
605
580
|
}
|
|
606
581
|
]
|
|
@@ -616,10 +591,10 @@ class McpRuntime {
|
|
|
616
591
|
if (name === "ask_sbd_toe_manual") {
|
|
617
592
|
const question = typeof args.question === "string" ? args.question : "";
|
|
618
593
|
const promptText = `${loadSystemPromptTemplate()}\n\n` +
|
|
619
|
-
"Use
|
|
594
|
+
"Use the `search_sbd_toe_manual` tool before answering.\n" +
|
|
620
595
|
`Question: ${question}`;
|
|
621
596
|
this.sendResponse(request.id, {
|
|
622
|
-
description: "
|
|
597
|
+
description: "Grounded prompt for questions about the SbD-ToE manual.",
|
|
623
598
|
messages: [
|
|
624
599
|
{
|
|
625
600
|
role: "user",
|
|
@@ -635,13 +610,13 @@ class McpRuntime {
|
|
|
635
610
|
if (name === "setup_sbd_toe_agent") {
|
|
636
611
|
const riskLevel = args["riskLevel"];
|
|
637
612
|
if (typeof riskLevel !== "string" || !["L1", "L2", "L3"].includes(riskLevel)) {
|
|
638
|
-
this.sendError(request.id, -32602, '
|
|
613
|
+
this.sendError(request.id, -32602, 'The "riskLevel" argument is required and must be L1, L2 or L3.');
|
|
639
614
|
return;
|
|
640
615
|
}
|
|
641
616
|
const projectRole = typeof args["projectRole"] === "string" ? args["projectRole"] : undefined;
|
|
642
617
|
const promptText = buildSetupAgentPrompt(riskLevel, projectRole);
|
|
643
618
|
this.sendResponse(request.id, {
|
|
644
|
-
description: "Prompt
|
|
619
|
+
description: "Prompt to configure an agent with SbD-ToE context.",
|
|
645
620
|
messages: [
|
|
646
621
|
{
|
|
647
622
|
role: "user",
|
|
@@ -654,34 +629,28 @@ class McpRuntime {
|
|
|
654
629
|
});
|
|
655
630
|
return;
|
|
656
631
|
}
|
|
657
|
-
this.sendError(request.id, -32602, `
|
|
632
|
+
this.sendError(request.id, -32602, `Unknown prompt: ${name}`);
|
|
658
633
|
}
|
|
659
634
|
handleResourcesList(request) {
|
|
660
635
|
this.sendResponse(request.id, {
|
|
661
636
|
resources: [
|
|
662
637
|
{
|
|
663
|
-
uri: "sbd://toe/
|
|
664
|
-
name: "SbD-ToE
|
|
665
|
-
description: "
|
|
638
|
+
uri: "sbd://toe/agent-guide",
|
|
639
|
+
name: "SbD-ToE Agent Guide",
|
|
640
|
+
description: "READ THIS FIRST. Operational guide for AI agents: SbD-ToE identity (Security by Design — Theory of Everything), CONSULT/GUIDE modes, routing by SDLC phase and domain, tool selection, epistemic standards, chapter map, risk levels, identifier conventions.",
|
|
666
641
|
mimeType: "text/markdown"
|
|
667
642
|
},
|
|
668
643
|
{
|
|
669
644
|
uri: "sbd://toe/chapter-applicability/{riskLevel}",
|
|
670
645
|
name: "SbD-ToE Chapter Applicability",
|
|
671
|
-
description: "
|
|
646
|
+
description: "Active, conditional and excluded chapters for a given risk level (L1/L2/L3).",
|
|
672
647
|
mimeType: "application/json"
|
|
673
648
|
},
|
|
674
649
|
{
|
|
675
650
|
uri: "sbd://toe/index-compact",
|
|
676
651
|
name: "SbD-ToE Index Compact",
|
|
677
|
-
description: "
|
|
652
|
+
description: "Compact JSON index of the full SbD-ToE manual. Injectable into system prompt to eliminate exploratory discovery.",
|
|
678
653
|
mimeType: "application/json"
|
|
679
|
-
},
|
|
680
|
-
{
|
|
681
|
-
uri: "sbd://toe/agent-guide",
|
|
682
|
-
name: "SbD-ToE Agent Guide",
|
|
683
|
-
description: "Full operational guide for agents: CONSULT/GUIDE modes, routing by phase and domain, tool selection, epistemic standards, chapter map, risk levels.",
|
|
684
|
-
mimeType: "text/markdown"
|
|
685
654
|
}
|
|
686
655
|
]
|
|
687
656
|
});
|
|
@@ -692,7 +661,7 @@ class McpRuntime {
|
|
|
692
661
|
if (applicabilityMatch !== null) {
|
|
693
662
|
const riskLevel = applicabilityMatch[1] ?? "";
|
|
694
663
|
if (!["L1", "L2", "L3"].includes(riskLevel)) {
|
|
695
|
-
this.sendError(request.id, -32602, `riskLevel
|
|
664
|
+
this.sendError(request.id, -32602, `Invalid riskLevel: "${riskLevel}". Allowed values: L1, L2, L3.`);
|
|
696
665
|
return;
|
|
697
666
|
}
|
|
698
667
|
const data = buildChapterApplicabilityJson(riskLevel);
|
|
@@ -701,20 +670,6 @@ class McpRuntime {
|
|
|
701
670
|
});
|
|
702
671
|
return;
|
|
703
672
|
}
|
|
704
|
-
const skillTemplateMatch = /^\/\/toe\/skill-template\/([^/]+)\/([^/]+)$/.exec(uri.startsWith("sbd:") ? uri.slice(4) : "");
|
|
705
|
-
if (skillTemplateMatch !== null) {
|
|
706
|
-
const riskLevel = skillTemplateMatch[1] ?? "";
|
|
707
|
-
const projectRole = skillTemplateMatch[2] ?? "";
|
|
708
|
-
if (!["L1", "L2", "L3"].includes(riskLevel)) {
|
|
709
|
-
this.sendError(request.id, -32602, `riskLevel inválido: "${riskLevel}". Valores permitidos: L1, L2, L3.`);
|
|
710
|
-
return;
|
|
711
|
-
}
|
|
712
|
-
const text = buildSkillTemplateMarkdown(riskLevel, projectRole);
|
|
713
|
-
this.sendResponse(request.id, {
|
|
714
|
-
contents: [{ uri, mimeType: "text/markdown", text }]
|
|
715
|
-
});
|
|
716
|
-
return;
|
|
717
|
-
}
|
|
718
673
|
if (uri === "sbd://toe/index-compact") {
|
|
719
674
|
const indexPath = resolveAppPath("data/publish/sbd-toe-index-compact.json");
|
|
720
675
|
let indexText;
|
|
@@ -722,7 +677,7 @@ class McpRuntime {
|
|
|
722
677
|
indexText = readFileSync(indexPath, "utf-8");
|
|
723
678
|
}
|
|
724
679
|
catch {
|
|
725
|
-
this.sendError(request.id, -32603, "
|
|
680
|
+
this.sendError(request.id, -32603, "Could not read the SbD-ToE compact index.");
|
|
726
681
|
return;
|
|
727
682
|
}
|
|
728
683
|
this.sendResponse(request.id, {
|
|
@@ -745,12 +700,12 @@ class McpRuntime {
|
|
|
745
700
|
});
|
|
746
701
|
return;
|
|
747
702
|
}
|
|
748
|
-
this.sendError(request.id, -32602, `
|
|
703
|
+
this.sendError(request.id, -32602, `Unknown resource URI: ${uri}`);
|
|
749
704
|
}
|
|
750
705
|
getStringArg(args, key) {
|
|
751
706
|
const value = args[key];
|
|
752
707
|
if (typeof value !== "string" || value.trim().length === 0) {
|
|
753
|
-
throw new Error(`
|
|
708
|
+
throw new Error(`The "${key}" argument is required.`);
|
|
754
709
|
}
|
|
755
710
|
return value;
|
|
756
711
|
}
|
|
@@ -768,7 +723,7 @@ class McpRuntime {
|
|
|
768
723
|
}
|
|
769
724
|
async requestSampling(systemPrompt, userPrompt) {
|
|
770
725
|
if (!this.supportsSampling()) {
|
|
771
|
-
throw new Error("
|
|
726
|
+
throw new Error("The current MCP client has not declared sampling support.");
|
|
772
727
|
}
|
|
773
728
|
const startedAt = Date.now();
|
|
774
729
|
await this.log("debug", {
|
|
@@ -903,11 +858,11 @@ class McpRuntime {
|
|
|
903
858
|
const debug = this.getOptionalBooleanArg(args, "debug");
|
|
904
859
|
const topK = this.getOptionalIntegerArg(args, "topK");
|
|
905
860
|
if (!this.supportsSampling()) {
|
|
906
|
-
//
|
|
861
|
+
// Graceful fallback: return top-3 documents without sampling
|
|
907
862
|
const bundle = await retrievePublishedContext(question, 3);
|
|
908
863
|
const fallbackResult = {
|
|
909
864
|
sampling_unavailable: true,
|
|
910
|
-
note: "Sampling
|
|
865
|
+
note: "Sampling is not available in this client. Returning the 3 most relevant documents as context.",
|
|
911
866
|
results: bundle.retrieved
|
|
912
867
|
};
|
|
913
868
|
this.sendResponse(request.id, {
|
|
@@ -983,7 +938,7 @@ class McpRuntime {
|
|
|
983
938
|
return;
|
|
984
939
|
}
|
|
985
940
|
case "plan_sbd_toe_repo_governance": {
|
|
986
|
-
const result = handlePlanRepoGovernance(args);
|
|
941
|
+
const result = handlePlanRepoGovernance(args, getSnapshotCache());
|
|
987
942
|
this.sendResponse(request.id, {
|
|
988
943
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
989
944
|
});
|
|
@@ -996,8 +951,8 @@ class McpRuntime {
|
|
|
996
951
|
});
|
|
997
952
|
return;
|
|
998
953
|
}
|
|
999
|
-
case "
|
|
1000
|
-
const result =
|
|
954
|
+
case "generate_sbd_toe_skill": {
|
|
955
|
+
const result = handleGenerateSbdToeSkill();
|
|
1001
956
|
this.sendResponse(request.id, {
|
|
1002
957
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
|
|
1003
958
|
});
|
|
@@ -1048,11 +1003,11 @@ class McpRuntime {
|
|
|
1048
1003
|
error_code: -32602,
|
|
1049
1004
|
message: "Unknown tool requested"
|
|
1050
1005
|
});
|
|
1051
|
-
this.sendError(request.id, -32602, `
|
|
1006
|
+
this.sendError(request.id, -32602, `Unknown tool: ${name}`);
|
|
1052
1007
|
}
|
|
1053
1008
|
}
|
|
1054
1009
|
catch (error) {
|
|
1055
|
-
//
|
|
1010
|
+
// Errors with rpcError emit JSON-RPC error (e.g. -32602 for invalid input)
|
|
1056
1011
|
if (error instanceof Error &&
|
|
1057
1012
|
"rpcError" in error &&
|
|
1058
1013
|
error.rpcError !== null &&
|
|
@@ -1069,7 +1024,7 @@ class McpRuntime {
|
|
|
1069
1024
|
this.sendError(request.id, rpcError.code, rpcError.message, rpcError.data);
|
|
1070
1025
|
return;
|
|
1071
1026
|
}
|
|
1072
|
-
const message = error instanceof Error ? error.message : "
|
|
1027
|
+
const message = error instanceof Error ? error.message : "Unexpected error.";
|
|
1073
1028
|
await this.log("error", {
|
|
1074
1029
|
event_type: "tool.call",
|
|
1075
1030
|
outcome: "failed",
|