bla-agents 1.1.0 → 1.6.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/.agents/skills/blind-llm-agents/SKILL.md +20 -14
- package/DISCLAIMER.md +15 -7
- package/README.md +153 -198
- package/dist/bundler/index.d.ts +19 -2
- package/dist/bundler/index.d.ts.map +1 -1
- package/dist/bundler/index.js +47 -4
- package/dist/bundler/index.js.map +1 -1
- package/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +123 -18
- package/dist/cli.js.map +1 -1
- package/dist/core/config.d.ts +54 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +160 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/coverage-contract.d.ts +97 -0
- package/dist/core/coverage-contract.d.ts.map +1 -0
- package/dist/core/coverage-contract.js +164 -0
- package/dist/core/coverage-contract.js.map +1 -0
- package/dist/core/debug-posture.d.ts +40 -0
- package/dist/core/debug-posture.d.ts.map +1 -0
- package/dist/core/debug-posture.js +197 -0
- package/dist/core/debug-posture.js.map +1 -0
- package/dist/core/detector.d.ts.map +1 -1
- package/dist/core/detector.js +58 -6
- package/dist/core/detector.js.map +1 -1
- package/dist/core/identifiers.d.ts +32 -0
- package/dist/core/identifiers.d.ts.map +1 -0
- package/dist/core/identifiers.js +263 -0
- package/dist/core/identifiers.js.map +1 -0
- package/dist/core/llm-directives.d.ts +12 -0
- package/dist/core/llm-directives.d.ts.map +1 -0
- package/dist/core/llm-directives.js +23 -0
- package/dist/core/llm-directives.js.map +1 -0
- package/dist/core/prng.d.ts +10 -1
- package/dist/core/prng.d.ts.map +1 -1
- package/dist/core/prng.js +27 -2
- package/dist/core/prng.js.map +1 -1
- package/dist/core/release-exposure.d.ts.map +1 -1
- package/dist/core/release-exposure.js +13 -2
- package/dist/core/release-exposure.js.map +1 -1
- package/dist/core/release-plan.d.ts +68 -0
- package/dist/core/release-plan.d.ts.map +1 -0
- package/dist/core/release-plan.js +244 -0
- package/dist/core/release-plan.js.map +1 -0
- package/dist/core/sarif.d.ts +53 -0
- package/dist/core/sarif.d.ts.map +1 -0
- package/dist/core/sarif.js +95 -0
- package/dist/core/sarif.js.map +1 -0
- package/dist/core/sqlite-runtime.d.ts +13 -0
- package/dist/core/sqlite-runtime.d.ts.map +1 -1
- package/dist/core/sqlite-runtime.js +38 -8
- package/dist/core/sqlite-runtime.js.map +1 -1
- package/dist/core/types.d.ts +7 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/engine/auditor.d.ts.map +1 -1
- package/dist/engine/auditor.js +380 -19
- package/dist/engine/auditor.js.map +1 -1
- package/dist/engine/benchmark.d.ts +1 -1
- package/dist/engine/benchmark.d.ts.map +1 -1
- package/dist/engine/benchmark.js +121 -41
- package/dist/engine/benchmark.js.map +1 -1
- package/dist/engine/defender.d.ts +1 -0
- package/dist/engine/defender.d.ts.map +1 -1
- package/dist/engine/defender.js +7 -1
- package/dist/engine/defender.js.map +1 -1
- package/dist/engine/harden.d.ts +61 -0
- package/dist/engine/harden.d.ts.map +1 -0
- package/dist/engine/harden.js +294 -0
- package/dist/engine/harden.js.map +1 -0
- package/dist/engine/protector.d.ts.map +1 -1
- package/dist/engine/protector.js +242 -26
- package/dist/engine/protector.js.map +1 -1
- package/dist/identity.d.ts +112 -2
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +112 -2
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +26 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +26 -9
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts +59 -152
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +466 -50
- package/dist/mcp/server.js.map +1 -1
- package/dist/setup/clients.d.ts +49 -1
- package/dist/setup/clients.d.ts.map +1 -1
- package/dist/setup/clients.js +1193 -20
- package/dist/setup/clients.js.map +1 -1
- package/dist/setup/doctor.d.ts +58 -14
- package/dist/setup/doctor.d.ts.map +1 -1
- package/dist/setup/doctor.js +316 -22
- package/dist/setup/doctor.js.map +1 -1
- package/dist/setup/setup.d.ts +77 -7
- package/dist/setup/setup.d.ts.map +1 -1
- package/dist/setup/setup.js +591 -62
- package/dist/setup/setup.js.map +1 -1
- package/dist/shields/chaff/chaff-generator.d.ts.map +1 -1
- package/dist/shields/chaff/chaff-generator.js +12 -3
- package/dist/shields/chaff/chaff-generator.js.map +1 -1
- package/dist/shields/deception/architecture-mirage.js +1 -1
- package/dist/shields/deception/architecture-mirage.js.map +1 -1
- package/dist/shields/deception/canary-honeypot.d.ts +33 -0
- package/dist/shields/deception/canary-honeypot.d.ts.map +1 -0
- package/dist/shields/deception/canary-honeypot.js +95 -0
- package/dist/shields/deception/canary-honeypot.js.map +1 -0
- package/dist/shields/deception/cognitive-armor-trigger.d.ts +43 -0
- package/dist/shields/deception/cognitive-armor-trigger.d.ts.map +1 -0
- package/dist/shields/deception/cognitive-armor-trigger.js +204 -0
- package/dist/shields/deception/cognitive-armor-trigger.js.map +1 -0
- package/dist/shields/deception/crash-trace-decoy.js +1 -1
- package/dist/shields/deception/crash-trace-decoy.js.map +1 -1
- package/dist/shields/deception/decompiler-illusion.js +1 -1
- package/dist/shields/deception/decompiler-illusion.js.map +1 -1
- package/dist/shields/deception/diff-noise-injector.js +1 -1
- package/dist/shields/deception/diff-noise-injector.js.map +1 -1
- package/dist/shields/deception/evidence-contract-poison.js +5 -5
- package/dist/shields/deception/evidence-contract-poison.js.map +1 -1
- package/dist/shields/deception/format-payloads.d.ts +21 -0
- package/dist/shields/deception/format-payloads.d.ts.map +1 -0
- package/dist/shields/deception/format-payloads.js +24 -0
- package/dist/shields/deception/format-payloads.js.map +1 -0
- package/dist/shields/deception/index.d.ts +10 -2
- package/dist/shields/deception/index.d.ts.map +1 -1
- package/dist/shields/deception/index.js +20 -3
- package/dist/shields/deception/index.js.map +1 -1
- package/dist/shields/deception/prompt-completion-poison.d.ts +3 -2
- package/dist/shields/deception/prompt-completion-poison.d.ts.map +1 -1
- package/dist/shields/deception/prompt-completion-poison.js +6 -3
- package/dist/shields/deception/prompt-completion-poison.js.map +1 -1
- package/dist/shields/deception/shadow-business-logic.js +4 -4
- package/dist/shields/deception/shadow-business-logic.js.map +1 -1
- package/dist/shields/deception/system-diagnostic-decoy.d.ts +36 -0
- package/dist/shields/deception/system-diagnostic-decoy.d.ts.map +1 -0
- package/dist/shields/deception/system-diagnostic-decoy.js +101 -0
- package/dist/shields/deception/system-diagnostic-decoy.js.map +1 -0
- package/dist/shields/exhaustion/asar-header-amplifier.d.ts +12 -3
- package/dist/shields/exhaustion/asar-header-amplifier.d.ts.map +1 -1
- package/dist/shields/exhaustion/asar-header-amplifier.js +30 -8
- package/dist/shields/exhaustion/asar-header-amplifier.js.map +1 -1
- package/dist/shields/exhaustion/bpe-token-amplifier.js +2 -2
- package/dist/shields/exhaustion/bpe-token-amplifier.js.map +1 -1
- package/dist/shields/exhaustion/callgraph-labyrinth.js +2 -2
- package/dist/shields/exhaustion/callgraph-labyrinth.js.map +1 -1
- package/dist/shields/exhaustion/cdp-shape-budget-breaker.js +1 -1
- package/dist/shields/exhaustion/cdp-shape-budget-breaker.js.map +1 -1
- package/dist/shields/exhaustion/frida-capture-saturation.d.ts +10 -5
- package/dist/shields/exhaustion/frida-capture-saturation.d.ts.map +1 -1
- package/dist/shields/exhaustion/frida-capture-saturation.js +21 -8
- package/dist/shields/exhaustion/frida-capture-saturation.js.map +1 -1
- package/dist/shields/exhaustion/index.d.ts +2 -2
- package/dist/shields/exhaustion/index.d.ts.map +1 -1
- package/dist/shields/exhaustion/index.js +2 -2
- package/dist/shields/exhaustion/index.js.map +1 -1
- package/dist/shields/exhaustion/obligation-flooder.d.ts +23 -6
- package/dist/shields/exhaustion/obligation-flooder.d.ts.map +1 -1
- package/dist/shields/exhaustion/obligation-flooder.js +29 -12
- package/dist/shields/exhaustion/obligation-flooder.js.map +1 -1
- package/dist/shields/exhaustion/rea-budget-matrix.d.ts +8 -2
- package/dist/shields/exhaustion/rea-budget-matrix.d.ts.map +1 -1
- package/dist/shields/exhaustion/rea-budget-matrix.js +139 -16
- package/dist/shields/exhaustion/rea-budget-matrix.js.map +1 -1
- package/dist/shields/exhaustion/regex-worker-tarpit.d.ts.map +1 -1
- package/dist/shields/exhaustion/regex-worker-tarpit.js +2 -1
- package/dist/shields/exhaustion/regex-worker-tarpit.js.map +1 -1
- package/dist/shields/exhaustion/wasm-interface-exhaustion.d.ts +7 -4
- package/dist/shields/exhaustion/wasm-interface-exhaustion.d.ts.map +1 -1
- package/dist/shields/exhaustion/wasm-interface-exhaustion.js +16 -7
- package/dist/shields/exhaustion/wasm-interface-exhaustion.js.map +1 -1
- package/dist/shields/formats/android-dex-xref.d.ts +19 -0
- package/dist/shields/formats/android-dex-xref.d.ts.map +1 -0
- package/dist/shields/formats/android-dex-xref.js +427 -0
- package/dist/shields/formats/android-dex-xref.js.map +1 -0
- package/dist/shields/formats/android-manifest.d.ts +44 -0
- package/dist/shields/formats/android-manifest.d.ts.map +1 -0
- package/dist/shields/formats/android-manifest.js +240 -0
- package/dist/shields/formats/android-manifest.js.map +1 -0
- package/dist/shields/formats/android-r8.d.ts +44 -0
- package/dist/shields/formats/android-r8.d.ts.map +1 -0
- package/dist/shields/formats/android-r8.js +246 -0
- package/dist/shields/formats/android-r8.js.map +1 -0
- package/dist/shields/formats/apple-plist.d.ts +15 -0
- package/dist/shields/formats/apple-plist.d.ts.map +1 -1
- package/dist/shields/formats/apple-plist.js +59 -1
- package/dist/shields/formats/apple-plist.js.map +1 -1
- package/dist/shields/formats/archive.d.ts +27 -6
- package/dist/shields/formats/archive.d.ts.map +1 -1
- package/dist/shields/formats/archive.js +247 -45
- package/dist/shields/formats/archive.js.map +1 -1
- package/dist/shields/formats/asar.d.ts +50 -10
- package/dist/shields/formats/asar.d.ts.map +1 -1
- package/dist/shields/formats/asar.js +265 -39
- package/dist/shields/formats/asar.js.map +1 -1
- package/dist/shields/formats/bun-standalone.d.ts +78 -0
- package/dist/shields/formats/bun-standalone.d.ts.map +1 -0
- package/dist/shields/formats/bun-standalone.js +272 -0
- package/dist/shields/formats/bun-standalone.js.map +1 -0
- package/dist/shields/formats/dotnet-managed.d.ts +9 -0
- package/dist/shields/formats/dotnet-managed.d.ts.map +1 -1
- package/dist/shields/formats/dotnet-managed.js +26 -1
- package/dist/shields/formats/dotnet-managed.js.map +1 -1
- package/dist/shields/formats/electron-fuses.d.ts +63 -8
- package/dist/shields/formats/electron-fuses.d.ts.map +1 -1
- package/dist/shields/formats/electron-fuses.js +297 -65
- package/dist/shields/formats/electron-fuses.js.map +1 -1
- package/dist/shields/formats/erlang-beam.d.ts +34 -0
- package/dist/shields/formats/erlang-beam.d.ts.map +1 -0
- package/dist/shields/formats/erlang-beam.js +319 -0
- package/dist/shields/formats/erlang-beam.js.map +1 -0
- package/dist/shields/formats/evm-bytecode.d.ts +28 -0
- package/dist/shields/formats/evm-bytecode.d.ts.map +1 -0
- package/dist/shields/formats/evm-bytecode.js +124 -0
- package/dist/shields/formats/evm-bytecode.js.map +1 -0
- package/dist/shields/formats/go-flutter-exhaustion.d.ts +55 -0
- package/dist/shields/formats/go-flutter-exhaustion.d.ts.map +1 -0
- package/dist/shields/formats/go-flutter-exhaustion.js +346 -0
- package/dist/shields/formats/go-flutter-exhaustion.js.map +1 -0
- package/dist/shields/formats/gpu-ptx.d.ts +40 -0
- package/dist/shields/formats/gpu-ptx.d.ts.map +1 -0
- package/dist/shields/formats/gpu-ptx.js +62 -0
- package/dist/shields/formats/gpu-ptx.js.map +1 -0
- package/dist/shields/formats/headers.d.ts.map +1 -1
- package/dist/shields/formats/headers.js +54 -14
- package/dist/shields/formats/headers.js.map +1 -1
- package/dist/shields/formats/jvm-bytecode.d.ts +20 -0
- package/dist/shields/formats/jvm-bytecode.d.ts.map +1 -0
- package/dist/shields/formats/jvm-bytecode.js +134 -0
- package/dist/shields/formats/jvm-bytecode.js.map +1 -0
- package/dist/shields/formats/mobile-game.d.ts +4 -0
- package/dist/shields/formats/mobile-game.d.ts.map +1 -1
- package/dist/shields/formats/mobile-game.js +16 -0
- package/dist/shields/formats/mobile-game.js.map +1 -1
- package/dist/shields/formats/model.d.ts +22 -8
- package/dist/shields/formats/model.d.ts.map +1 -1
- package/dist/shields/formats/model.js +231 -59
- package/dist/shields/formats/model.js.map +1 -1
- package/dist/shields/formats/native.d.ts +74 -11
- package/dist/shields/formats/native.d.ts.map +1 -1
- package/dist/shields/formats/native.js +557 -109
- package/dist/shields/formats/native.js.map +1 -1
- package/dist/shields/formats/pcap-capture.d.ts +27 -0
- package/dist/shields/formats/pcap-capture.d.ts.map +1 -0
- package/dist/shields/formats/pcap-capture.js +201 -0
- package/dist/shields/formats/pcap-capture.js.map +1 -0
- package/dist/shields/formats/python.d.ts +22 -1
- package/dist/shields/formats/python.d.ts.map +1 -1
- package/dist/shields/formats/python.js +568 -27
- package/dist/shields/formats/python.js.map +1 -1
- package/dist/shields/formats/sourcemap.d.ts.map +1 -1
- package/dist/shields/formats/sourcemap.js +2 -0
- package/dist/shields/formats/sourcemap.js.map +1 -1
- package/dist/shields/formats/sqlite.d.ts +87 -15
- package/dist/shields/formats/sqlite.d.ts.map +1 -1
- package/dist/shields/formats/sqlite.js +377 -42
- package/dist/shields/formats/sqlite.js.map +1 -1
- package/dist/shields/formats/wasm.d.ts +6 -0
- package/dist/shields/formats/wasm.d.ts.map +1 -1
- package/dist/shields/formats/wasm.js +118 -3
- package/dist/shields/formats/wasm.js.map +1 -1
- package/dist/shields/javascript/ast-shield.d.ts +26 -5
- package/dist/shields/javascript/ast-shield.d.ts.map +1 -1
- package/dist/shields/javascript/ast-shield.js +748 -104
- package/dist/shields/javascript/ast-shield.js.map +1 -1
- package/dist/shields/runtime/memory-diff-shield.d.ts +56 -0
- package/dist/shields/runtime/memory-diff-shield.d.ts.map +1 -0
- package/dist/shields/runtime/memory-diff-shield.js +170 -0
- package/dist/shields/runtime/memory-diff-shield.js.map +1 -0
- package/dist/shields/runtime/runtime-shield.d.ts +12 -16
- package/dist/shields/runtime/runtime-shield.d.ts.map +1 -1
- package/dist/shields/runtime/runtime-shield.js +30 -24
- package/dist/shields/runtime/runtime-shield.js.map +1 -1
- package/dist/shields/tarpit/opaque-predicates.d.ts.map +1 -1
- package/dist/shields/tarpit/opaque-predicates.js +3 -3
- package/dist/shields/tarpit/opaque-predicates.js.map +1 -1
- package/dist/shields/tarpit/tarpit-generator.d.ts +9 -4
- package/dist/shields/tarpit/tarpit-generator.d.ts.map +1 -1
- package/dist/shields/tarpit/tarpit-generator.js +30 -23
- package/dist/shields/tarpit/tarpit-generator.js.map +1 -1
- package/package.json +13 -6
package/dist/mcp/server.js
CHANGED
|
@@ -1,12 +1,62 @@
|
|
|
1
1
|
import { BLA_IDENTITY } from "../identity.js";
|
|
2
|
+
import { initBlaConfig } from "../core/config.js";
|
|
3
|
+
import { inspectReleaseExposure } from "../core/release-exposure.js";
|
|
2
4
|
import { auditTarget } from "../engine/auditor.js";
|
|
3
5
|
import { protectTarget } from "../engine/protector.js";
|
|
4
6
|
import { verifyTarget } from "../engine/verifier.js";
|
|
5
7
|
import { defendTarget } from "../engine/defender.js";
|
|
8
|
+
import { hardenProject } from "../engine/harden.js";
|
|
6
9
|
import { runShowcaseBenchmark } from "../engine/benchmark.js";
|
|
7
10
|
import { emitCompileTimeNativeHeader, } from "../shields/formats/headers.js";
|
|
8
11
|
import { runDoctor } from "../setup/doctor.js";
|
|
12
|
+
const DEFAULT_ENGINE_HANDLERS = Object.freeze({
|
|
13
|
+
hardenProject,
|
|
14
|
+
defendTarget,
|
|
15
|
+
auditTarget,
|
|
16
|
+
protectTarget,
|
|
17
|
+
verifyTarget,
|
|
18
|
+
runShowcaseBenchmark,
|
|
19
|
+
emitCompileTimeNativeHeader,
|
|
20
|
+
runDoctor,
|
|
21
|
+
inspectReleaseExposure,
|
|
22
|
+
initBlaConfig,
|
|
23
|
+
});
|
|
24
|
+
export const SUPPORTED_MCP_PROTOCOL_VERSIONS = Object.freeze([
|
|
25
|
+
"2024-11-05",
|
|
26
|
+
"2025-03-26",
|
|
27
|
+
]);
|
|
9
28
|
export const BLA_MCP_TOOLS = Object.freeze([
|
|
29
|
+
{
|
|
30
|
+
name: "bla_harden",
|
|
31
|
+
description: "DEFAULT one-sentence Counter-REA hardening. Auto-discovers build outputs (dist/, build/, out/, release/, .asar, native binaries, .wasm, .py/.pyc, .sqlite, .safetensors/.gguf, .dex, .class, etc.), detects each artifact's format, and runs the full audit→defend→verify pipeline with the bankrupt profile. Pass just a project or build directory (default: cwd). Prefer this over bla_defend when the user says 'harden my software' without naming a specific file.",
|
|
32
|
+
inputSchema: {
|
|
33
|
+
type: "object",
|
|
34
|
+
properties: {
|
|
35
|
+
directory: {
|
|
36
|
+
type: "string",
|
|
37
|
+
description: "Project or build directory to harden (default: current working directory)",
|
|
38
|
+
},
|
|
39
|
+
intensity: {
|
|
40
|
+
type: "string",
|
|
41
|
+
enum: ["stealth", "balanced", "maximum", "bankrupt"],
|
|
42
|
+
description: "Protection intensity preset (default: bankrupt)",
|
|
43
|
+
},
|
|
44
|
+
emit_manifest: {
|
|
45
|
+
type: "boolean",
|
|
46
|
+
description: "Opt-in: emit an unsigned .bla-manifest.json attestation (not ed25519-signed) per artifact. Default false.",
|
|
47
|
+
},
|
|
48
|
+
llm_directives: {
|
|
49
|
+
type: "boolean",
|
|
50
|
+
description: "Opt-in risky LLM directive layers (fake COPPA/medical notices, dual-use imitation, AI chat markers). Default false.",
|
|
51
|
+
},
|
|
52
|
+
seed: {
|
|
53
|
+
type: "string",
|
|
54
|
+
description: "Optional deterministic seed; when omitted, BLA uses/persists a per-project random seed in .blarc",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
additionalProperties: false,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
10
60
|
{
|
|
11
61
|
name: "bla_defend",
|
|
12
62
|
description: "One-click Counter-REA full defense hardening pipeline. Runs release source-map exposure inspection, 16-vector REA vulnerability audit, Resource-Exhaustion + Model-Misjudgment shield injection (default: bankrupt preset), and mathematical invariant verification in a single call.",
|
|
@@ -28,10 +78,19 @@ export const BLA_MCP_TOOLS = Object.freeze([
|
|
|
28
78
|
},
|
|
29
79
|
emit_manifest: {
|
|
30
80
|
type: "boolean",
|
|
31
|
-
description: "
|
|
81
|
+
description: "Opt-in: emit an unsigned .bla-manifest.json attestation (not ed25519-signed) next to the hardened artifact. Default false.",
|
|
82
|
+
},
|
|
83
|
+
llm_directives: {
|
|
84
|
+
type: "boolean",
|
|
85
|
+
description: "Opt-in risky LLM directive layers (fake COPPA/medical notices, dual-use imitation, AI chat markers). Default false.",
|
|
86
|
+
},
|
|
87
|
+
seed: {
|
|
88
|
+
type: "string",
|
|
89
|
+
description: "Optional deterministic seed; when omitted, BLA uses/persists a per-project random seed in .blarc",
|
|
32
90
|
},
|
|
33
91
|
},
|
|
34
92
|
required: ["input_path"],
|
|
93
|
+
additionalProperties: false,
|
|
35
94
|
},
|
|
36
95
|
},
|
|
37
96
|
{
|
|
@@ -46,6 +105,7 @@ export const BLA_MCP_TOOLS = Object.freeze([
|
|
|
46
105
|
},
|
|
47
106
|
},
|
|
48
107
|
required: ["path"],
|
|
108
|
+
additionalProperties: false,
|
|
49
109
|
},
|
|
50
110
|
},
|
|
51
111
|
{
|
|
@@ -69,10 +129,15 @@ export const BLA_MCP_TOOLS = Object.freeze([
|
|
|
69
129
|
},
|
|
70
130
|
seed: {
|
|
71
131
|
type: "string",
|
|
72
|
-
description: "Optional deterministic seed
|
|
132
|
+
description: "Optional deterministic seed; when omitted, BLA mints an ephemeral random seed (prefer project .blarc via CLI)",
|
|
133
|
+
},
|
|
134
|
+
llm_directives: {
|
|
135
|
+
type: "boolean",
|
|
136
|
+
description: "Opt-in risky LLM directive layers. Default false.",
|
|
73
137
|
},
|
|
74
138
|
},
|
|
75
139
|
required: ["input_path"],
|
|
140
|
+
additionalProperties: false,
|
|
76
141
|
},
|
|
77
142
|
},
|
|
78
143
|
{
|
|
@@ -91,14 +156,16 @@ export const BLA_MCP_TOOLS = Object.freeze([
|
|
|
91
156
|
},
|
|
92
157
|
},
|
|
93
158
|
required: ["target_path"],
|
|
159
|
+
additionalProperties: false,
|
|
94
160
|
},
|
|
95
161
|
},
|
|
96
162
|
{
|
|
97
163
|
name: "bla_benchmark",
|
|
98
|
-
description: "Runs the
|
|
164
|
+
description: "Runs the Counter-REA Showcase Benchmark suite and returns Before vs. After metrics.",
|
|
99
165
|
inputSchema: {
|
|
100
166
|
type: "object",
|
|
101
167
|
properties: {},
|
|
168
|
+
additionalProperties: false,
|
|
102
169
|
},
|
|
103
170
|
},
|
|
104
171
|
{
|
|
@@ -118,6 +185,7 @@ export const BLA_MCP_TOOLS = Object.freeze([
|
|
|
118
185
|
},
|
|
119
186
|
},
|
|
120
187
|
required: ["language"],
|
|
188
|
+
additionalProperties: false,
|
|
121
189
|
},
|
|
122
190
|
},
|
|
123
191
|
{
|
|
@@ -125,23 +193,269 @@ export const BLA_MCP_TOOLS = Object.freeze([
|
|
|
125
193
|
description: "Checks readiness of all BLA protection engines and agent MCP registrations.",
|
|
126
194
|
inputSchema: {
|
|
127
195
|
type: "object",
|
|
128
|
-
properties: {
|
|
196
|
+
properties: {
|
|
197
|
+
home_dir: {
|
|
198
|
+
type: "string",
|
|
199
|
+
description: "Optional home directory path to inspect",
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
additionalProperties: false,
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
name: "bla_inspect_release",
|
|
207
|
+
description: "Read-only local source-map and symbol exposure scan for build directories and release artifacts.",
|
|
208
|
+
inputSchema: {
|
|
209
|
+
type: "object",
|
|
210
|
+
properties: {
|
|
211
|
+
path: {
|
|
212
|
+
type: "string",
|
|
213
|
+
description: "Path to the build directory or artifact to inspect",
|
|
214
|
+
},
|
|
215
|
+
max_files: {
|
|
216
|
+
type: "number",
|
|
217
|
+
description: "Optional maximum number of files to scan",
|
|
218
|
+
},
|
|
219
|
+
max_total_bytes: {
|
|
220
|
+
type: "number",
|
|
221
|
+
description: "Optional maximum total bytes to scan",
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
required: ["path"],
|
|
225
|
+
additionalProperties: false,
|
|
129
226
|
},
|
|
130
227
|
},
|
|
228
|
+
{
|
|
229
|
+
name: "bla_init",
|
|
230
|
+
description: "Creates a starter bla.config.json in a project directory for zero-argument `bla defend` workflows.",
|
|
231
|
+
inputSchema: {
|
|
232
|
+
type: "object",
|
|
233
|
+
properties: {
|
|
234
|
+
directory: {
|
|
235
|
+
type: "string",
|
|
236
|
+
description: "Target project directory (pass '.' explicitly for current directory)",
|
|
237
|
+
},
|
|
238
|
+
overwrite: {
|
|
239
|
+
type: "boolean",
|
|
240
|
+
description: "Overwrite an existing bla.config.json if present",
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
required: ["directory"],
|
|
244
|
+
additionalProperties: false,
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
]);
|
|
248
|
+
export const BLA_MCP_PROMPTS = Object.freeze([
|
|
249
|
+
{
|
|
250
|
+
name: "bla-harden-project",
|
|
251
|
+
description: "One-sentence Counter-REA hardening: discover every protectable build artifact under a project directory and run bla_harden (audit→defend→verify, bankrupt profile).",
|
|
252
|
+
arguments: [
|
|
253
|
+
{
|
|
254
|
+
name: "directory",
|
|
255
|
+
description: "Project or build directory (default: .)",
|
|
256
|
+
required: false,
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
name: "shield-against-rea",
|
|
262
|
+
description: "Audit a build artifact for REA exposure, apply BLA's adversarial shield, and verify the token bankruptcy factor.",
|
|
263
|
+
arguments: [
|
|
264
|
+
{
|
|
265
|
+
name: "target_path",
|
|
266
|
+
description: "Path to the build artifact or directory",
|
|
267
|
+
required: true,
|
|
268
|
+
},
|
|
269
|
+
],
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
name: "bla-hardening-workflow",
|
|
273
|
+
description: "Step-by-step release hardening checklist using bla_inspect_release, bla_audit, bla_protect, and bla_verify.",
|
|
274
|
+
arguments: [
|
|
275
|
+
{
|
|
276
|
+
name: "target_path",
|
|
277
|
+
description: "Path to the build artifact or directory",
|
|
278
|
+
required: true,
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
name: "bla-counter-rea",
|
|
284
|
+
description: "Evaluate REA reverse-engineering exposure and plan defensive hardening for a software artifact.",
|
|
285
|
+
arguments: [
|
|
286
|
+
{
|
|
287
|
+
name: "target_path",
|
|
288
|
+
description: "Path to the build artifact or directory",
|
|
289
|
+
required: true,
|
|
290
|
+
},
|
|
291
|
+
],
|
|
292
|
+
},
|
|
131
293
|
]);
|
|
132
|
-
|
|
294
|
+
function isPlainObject(value) {
|
|
295
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
296
|
+
}
|
|
297
|
+
export function validateMcpToolCall(params) {
|
|
298
|
+
if (!isPlainObject(params)) {
|
|
299
|
+
return {
|
|
300
|
+
ok: false,
|
|
301
|
+
code: -32602,
|
|
302
|
+
message: "Invalid params: tool call params must be a JSON object",
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
if (typeof params.name !== "string" || params.name.trim().length === 0) {
|
|
306
|
+
return {
|
|
307
|
+
ok: false,
|
|
308
|
+
code: -32602,
|
|
309
|
+
message: "Invalid params: tool 'name' must be a non-empty string",
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
const tool = BLA_MCP_TOOLS.find((t) => t.name === params.name);
|
|
313
|
+
if (!tool) {
|
|
314
|
+
return {
|
|
315
|
+
ok: false,
|
|
316
|
+
code: -32602,
|
|
317
|
+
message: `Invalid params: unknown BLA MCP tool '${params.name}'`,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
const rawArgs = params.arguments;
|
|
321
|
+
const requiredFields = tool.inputSchema.required ?? [];
|
|
322
|
+
if (rawArgs === undefined) {
|
|
323
|
+
if (requiredFields.length > 0) {
|
|
324
|
+
return {
|
|
325
|
+
ok: false,
|
|
326
|
+
code: -32602,
|
|
327
|
+
message: `Invalid params for '${tool.name}': missing required arguments (${requiredFields.join(", ")})`,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
return { ok: true, tool, args: {} };
|
|
331
|
+
}
|
|
332
|
+
if (!isPlainObject(rawArgs)) {
|
|
333
|
+
return {
|
|
334
|
+
ok: false,
|
|
335
|
+
code: -32602,
|
|
336
|
+
message: `Invalid params for '${tool.name}': 'arguments' must be a JSON object`,
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
// Reject unexpected properties when additionalProperties is false
|
|
340
|
+
const allowedProps = tool.inputSchema.properties;
|
|
341
|
+
for (const key of Object.keys(rawArgs)) {
|
|
342
|
+
if (!(key in allowedProps)) {
|
|
343
|
+
return {
|
|
344
|
+
ok: false,
|
|
345
|
+
code: -32602,
|
|
346
|
+
message: `Invalid params for '${tool.name}': unknown argument '${key}'`,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// Validate required properties
|
|
351
|
+
for (const reqKey of requiredFields) {
|
|
352
|
+
if (!(reqKey in rawArgs) || rawArgs[reqKey] === undefined || rawArgs[reqKey] === null) {
|
|
353
|
+
return {
|
|
354
|
+
ok: false,
|
|
355
|
+
code: -32602,
|
|
356
|
+
message: `Invalid params for '${tool.name}': missing required argument '${reqKey}'`,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
// Validate types, non-empty strings, numbers, booleans, and enums
|
|
361
|
+
for (const [key, val] of Object.entries(rawArgs)) {
|
|
362
|
+
if (val === undefined)
|
|
363
|
+
continue;
|
|
364
|
+
const propSchema = allowedProps[key];
|
|
365
|
+
if (!propSchema)
|
|
366
|
+
continue;
|
|
367
|
+
if (propSchema.type === "string") {
|
|
368
|
+
if (typeof val !== "string") {
|
|
369
|
+
return {
|
|
370
|
+
ok: false,
|
|
371
|
+
code: -32602,
|
|
372
|
+
message: `Invalid params for '${tool.name}': argument '${key}' must be a string, received ${val === null ? "null" : typeof val}`,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
if (val.trim().length === 0) {
|
|
376
|
+
return {
|
|
377
|
+
ok: false,
|
|
378
|
+
code: -32602,
|
|
379
|
+
message: `Invalid params for '${tool.name}': argument '${key}' must be a non-empty string`,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
if (propSchema.enum && !propSchema.enum.includes(val)) {
|
|
383
|
+
return {
|
|
384
|
+
ok: false,
|
|
385
|
+
code: -32602,
|
|
386
|
+
message: `Invalid params for '${tool.name}': argument '${key}' must be one of [${propSchema.enum.join(", ")}], received '${val}'`,
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
else if (propSchema.type === "boolean") {
|
|
391
|
+
if (typeof val !== "boolean") {
|
|
392
|
+
return {
|
|
393
|
+
ok: false,
|
|
394
|
+
code: -32602,
|
|
395
|
+
message: `Invalid params for '${tool.name}': argument '${key}' must be a boolean`,
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
else if (propSchema.type === "number") {
|
|
400
|
+
if (typeof val !== "number" || !Number.isFinite(val) || val <= 0) {
|
|
401
|
+
return {
|
|
402
|
+
ok: false,
|
|
403
|
+
code: -32602,
|
|
404
|
+
message: `Invalid params for '${tool.name}': argument '${key}' must be a positive finite number`,
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return { ok: true, tool, args: rawArgs };
|
|
410
|
+
}
|
|
411
|
+
export async function handleMcpRequest(req, handlers = DEFAULT_ENGINE_HANDLERS) {
|
|
412
|
+
if (!isPlainObject(req) || req.jsonrpc !== "2.0" || typeof req.method !== "string") {
|
|
413
|
+
return {
|
|
414
|
+
jsonrpc: "2.0",
|
|
415
|
+
id: isPlainObject(req) && (typeof req.id === "string" || typeof req.id === "number") ? req.id : null,
|
|
416
|
+
error: {
|
|
417
|
+
code: -32600,
|
|
418
|
+
message: "Invalid Request: expected JSON-RPC 2.0 request object",
|
|
419
|
+
},
|
|
420
|
+
};
|
|
421
|
+
}
|
|
133
422
|
// Notifications without an `id` do not produce a response
|
|
134
423
|
if (req.id === undefined) {
|
|
135
424
|
return null;
|
|
136
425
|
}
|
|
137
426
|
try {
|
|
138
427
|
switch (req.method) {
|
|
139
|
-
case "initialize":
|
|
428
|
+
case "initialize": {
|
|
429
|
+
if (req.params !== undefined && !isPlainObject(req.params)) {
|
|
430
|
+
return {
|
|
431
|
+
jsonrpc: "2.0",
|
|
432
|
+
id: req.id,
|
|
433
|
+
error: {
|
|
434
|
+
code: -32602,
|
|
435
|
+
message: "Invalid params: initialize params must be an object",
|
|
436
|
+
},
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
const requestedVersion = req.params?.protocolVersion;
|
|
440
|
+
if (requestedVersion !== undefined && typeof requestedVersion !== "string") {
|
|
441
|
+
return {
|
|
442
|
+
jsonrpc: "2.0",
|
|
443
|
+
id: req.id,
|
|
444
|
+
error: {
|
|
445
|
+
code: -32602,
|
|
446
|
+
message: "Invalid params: protocolVersion must be a string",
|
|
447
|
+
},
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
const negotiatedVersion = typeof requestedVersion === "string" &&
|
|
451
|
+
SUPPORTED_MCP_PROTOCOL_VERSIONS.includes(requestedVersion)
|
|
452
|
+
? requestedVersion
|
|
453
|
+
: "2024-11-05";
|
|
140
454
|
return {
|
|
141
455
|
jsonrpc: "2.0",
|
|
142
456
|
id: req.id,
|
|
143
457
|
result: {
|
|
144
|
-
protocolVersion:
|
|
458
|
+
protocolVersion: negotiatedVersion,
|
|
145
459
|
capabilities: {
|
|
146
460
|
tools: {},
|
|
147
461
|
prompts: {},
|
|
@@ -152,6 +466,7 @@ export async function handleMcpRequest(req) {
|
|
|
152
466
|
},
|
|
153
467
|
},
|
|
154
468
|
};
|
|
469
|
+
}
|
|
155
470
|
case "ping":
|
|
156
471
|
return {
|
|
157
472
|
jsonrpc: "2.0",
|
|
@@ -171,29 +486,120 @@ export async function handleMcpRequest(req) {
|
|
|
171
486
|
jsonrpc: "2.0",
|
|
172
487
|
id: req.id,
|
|
173
488
|
result: {
|
|
174
|
-
prompts:
|
|
489
|
+
prompts: BLA_MCP_PROMPTS,
|
|
490
|
+
},
|
|
491
|
+
};
|
|
492
|
+
case "prompts/get": {
|
|
493
|
+
if (!isPlainObject(req.params) || typeof req.params.name !== "string") {
|
|
494
|
+
return {
|
|
495
|
+
jsonrpc: "2.0",
|
|
496
|
+
id: req.id,
|
|
497
|
+
error: {
|
|
498
|
+
code: -32602,
|
|
499
|
+
message: "Invalid params: prompts/get requires a string 'name'",
|
|
500
|
+
},
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
const promptDef = BLA_MCP_PROMPTS.find((p) => p.name === req.params.name);
|
|
504
|
+
if (!promptDef) {
|
|
505
|
+
return {
|
|
506
|
+
jsonrpc: "2.0",
|
|
507
|
+
id: req.id,
|
|
508
|
+
error: {
|
|
509
|
+
code: -32602,
|
|
510
|
+
message: `Invalid params: unknown prompt '${req.params.name}'`,
|
|
511
|
+
},
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
const promptArgs = req.params.arguments;
|
|
515
|
+
if (!isPlainObject(promptArgs)) {
|
|
516
|
+
return {
|
|
517
|
+
jsonrpc: "2.0",
|
|
518
|
+
id: req.id,
|
|
519
|
+
error: {
|
|
520
|
+
code: -32602,
|
|
521
|
+
message: `Invalid params: prompt '${promptDef.name}' requires an 'arguments' object`,
|
|
522
|
+
},
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
for (const argSpec of promptDef.arguments) {
|
|
526
|
+
if (argSpec.required) {
|
|
527
|
+
const val = promptArgs[argSpec.name];
|
|
528
|
+
if (typeof val !== "string" || val.trim().length === 0) {
|
|
529
|
+
return {
|
|
530
|
+
jsonrpc: "2.0",
|
|
531
|
+
id: req.id,
|
|
532
|
+
error: {
|
|
533
|
+
code: -32602,
|
|
534
|
+
message: `Invalid params: prompt '${promptDef.name}' requires non-empty string argument '${argSpec.name}'`,
|
|
535
|
+
},
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
let promptText;
|
|
541
|
+
if (promptDef.name === "bla-harden-project") {
|
|
542
|
+
const directory = typeof promptArgs.directory === "string" && promptArgs.directory.trim().length > 0
|
|
543
|
+
? String(promptArgs.directory)
|
|
544
|
+
: ".";
|
|
545
|
+
promptText =
|
|
546
|
+
`Harden my software against REA in one step: call bla_harden with { "directory": "${directory}" }. ` +
|
|
547
|
+
`It auto-discovers build outputs, runs audit→defend→verify with the bankrupt profile on every artifact, and returns a per-artifact summary. ` +
|
|
548
|
+
`Do not ask which files to protect — discover them.`;
|
|
549
|
+
}
|
|
550
|
+
else {
|
|
551
|
+
const targetPath = String(promptArgs.target_path ?? ".");
|
|
552
|
+
promptText =
|
|
553
|
+
`Inspect and audit '${targetPath}' using bla_inspect_release and bla_audit, then review findings before applying bla_protect or bla_defend and verifying with bla_verify.`;
|
|
554
|
+
}
|
|
555
|
+
return {
|
|
556
|
+
jsonrpc: "2.0",
|
|
557
|
+
id: req.id,
|
|
558
|
+
result: {
|
|
559
|
+
description: promptDef.description,
|
|
560
|
+
messages: [
|
|
175
561
|
{
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
description: "Path to the build artifact or directory",
|
|
182
|
-
required: true,
|
|
183
|
-
},
|
|
184
|
-
],
|
|
562
|
+
role: "user",
|
|
563
|
+
content: {
|
|
564
|
+
type: "text",
|
|
565
|
+
text: promptText,
|
|
566
|
+
},
|
|
185
567
|
},
|
|
186
568
|
],
|
|
187
569
|
},
|
|
188
570
|
};
|
|
571
|
+
}
|
|
189
572
|
case "tools/call": {
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
573
|
+
const validated = validateMcpToolCall(req.params);
|
|
574
|
+
if (!validated.ok) {
|
|
575
|
+
return {
|
|
576
|
+
jsonrpc: "2.0",
|
|
577
|
+
id: req.id,
|
|
578
|
+
error: {
|
|
579
|
+
code: validated.code,
|
|
580
|
+
message: validated.message,
|
|
581
|
+
},
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
const { tool, args } = validated;
|
|
585
|
+
const name = tool.name;
|
|
193
586
|
let payload;
|
|
194
|
-
if (name === "
|
|
195
|
-
payload =
|
|
196
|
-
|
|
587
|
+
if (name === "bla_harden") {
|
|
588
|
+
payload = handlers.hardenProject({
|
|
589
|
+
directory: typeof args.directory === "string" && args.directory.trim().length > 0
|
|
590
|
+
? args.directory
|
|
591
|
+
: process.cwd(),
|
|
592
|
+
intensity: typeof args.intensity === "string"
|
|
593
|
+
? args.intensity
|
|
594
|
+
: "bankrupt",
|
|
595
|
+
emitManifest: Boolean(args.emit_manifest),
|
|
596
|
+
llmDirectives: Boolean(args.llm_directives),
|
|
597
|
+
...(typeof args.seed === "string" ? { seed: args.seed } : {}),
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
else if (name === "bla_defend") {
|
|
601
|
+
payload = handlers.defendTarget({
|
|
602
|
+
inputPath: args.input_path,
|
|
197
603
|
...(typeof args.output_path === "string"
|
|
198
604
|
? { outputPath: args.output_path }
|
|
199
605
|
: {}),
|
|
@@ -201,46 +607,45 @@ export async function handleMcpRequest(req) {
|
|
|
201
607
|
? args.intensity
|
|
202
608
|
: "bankrupt",
|
|
203
609
|
emitManifest: Boolean(args.emit_manifest),
|
|
610
|
+
llmDirectives: Boolean(args.llm_directives),
|
|
611
|
+
...(typeof args.seed === "string" ? { seed: args.seed } : {}),
|
|
204
612
|
});
|
|
205
613
|
}
|
|
206
614
|
else if (name === "bla_audit") {
|
|
207
|
-
payload = auditTarget(
|
|
615
|
+
payload = handlers.auditTarget(args.path);
|
|
208
616
|
}
|
|
209
617
|
else if (name === "bla_protect") {
|
|
210
|
-
payload = protectTarget({
|
|
211
|
-
inputPath:
|
|
618
|
+
payload = handlers.protectTarget({
|
|
619
|
+
inputPath: args.input_path,
|
|
212
620
|
...(typeof args.output_path === "string" ? { outputPath: args.output_path } : {}),
|
|
213
621
|
...(typeof args.intensity === "string"
|
|
214
622
|
? { intensity: args.intensity }
|
|
215
623
|
: {}),
|
|
216
624
|
...(typeof args.seed === "string" ? { seed: args.seed } : {}),
|
|
625
|
+
llmDirectives: Boolean(args.llm_directives),
|
|
217
626
|
});
|
|
218
627
|
}
|
|
219
628
|
else if (name === "bla_verify") {
|
|
220
|
-
payload = verifyTarget(
|
|
629
|
+
payload = handlers.verifyTarget(args.target_path, typeof args.original_path === "string" ? args.original_path : undefined);
|
|
221
630
|
}
|
|
222
631
|
else if (name === "bla_benchmark") {
|
|
223
|
-
payload = await runShowcaseBenchmark();
|
|
632
|
+
payload = await handlers.runShowcaseBenchmark();
|
|
224
633
|
}
|
|
225
634
|
else if (name === "bla_emit_headers") {
|
|
226
|
-
payload = emitCompileTimeNativeHeader(args.language
|
|
635
|
+
payload = handlers.emitCompileTimeNativeHeader(args.language, {
|
|
227
636
|
...(typeof args.intensity === "string"
|
|
228
637
|
? { intensity: args.intensity }
|
|
229
638
|
: {}),
|
|
230
639
|
});
|
|
231
640
|
}
|
|
232
641
|
else if (name === "bla_doctor") {
|
|
233
|
-
payload = runDoctor();
|
|
642
|
+
payload = handlers.runDoctor(typeof args.home_dir === "string" ? args.home_dir : undefined);
|
|
234
643
|
}
|
|
235
|
-
else {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
code: -32601,
|
|
241
|
-
message: `Unknown BLA MCP tool: ${name}`,
|
|
242
|
-
},
|
|
243
|
-
};
|
|
644
|
+
else if (name === "bla_inspect_release") {
|
|
645
|
+
payload = handlers.inspectReleaseExposure(args.path);
|
|
646
|
+
}
|
|
647
|
+
else if (name === "bla_init") {
|
|
648
|
+
payload = handlers.initBlaConfig(args.directory, Boolean(args.overwrite));
|
|
244
649
|
}
|
|
245
650
|
return {
|
|
246
651
|
jsonrpc: "2.0",
|
|
@@ -285,12 +690,13 @@ export async function handleMcpRequest(req) {
|
|
|
285
690
|
}
|
|
286
691
|
}
|
|
287
692
|
/**
|
|
288
|
-
* Starts the BLA MCP server over stdio (supporting newline-delimited JSON-RPC).
|
|
693
|
+
* Starts the BLA MCP server over stdio (supporting newline-delimited JSON-RPC 2.0).
|
|
289
694
|
*/
|
|
290
695
|
export function startMcpStdioServer() {
|
|
291
696
|
let buffer = "";
|
|
697
|
+
let processingQueue = Promise.resolve();
|
|
292
698
|
process.stdin.setEncoding("utf8");
|
|
293
|
-
process.stdin.on("data",
|
|
699
|
+
process.stdin.on("data", (chunk) => {
|
|
294
700
|
buffer += chunk;
|
|
295
701
|
let newlineIdx;
|
|
296
702
|
while ((newlineIdx = buffer.indexOf("\n")) >= 0) {
|
|
@@ -298,16 +704,26 @@ export function startMcpStdioServer() {
|
|
|
298
704
|
buffer = buffer.slice(newlineIdx + 1);
|
|
299
705
|
if (!line || line.startsWith("Content-Length:"))
|
|
300
706
|
continue;
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
707
|
+
processingQueue = processingQueue.then(async () => {
|
|
708
|
+
try {
|
|
709
|
+
const req = JSON.parse(line);
|
|
710
|
+
const res = await handleMcpRequest(req);
|
|
711
|
+
if (res !== null) {
|
|
712
|
+
process.stdout.write(JSON.stringify(res) + "\n");
|
|
713
|
+
}
|
|
306
714
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
715
|
+
catch {
|
|
716
|
+
const parseErr = {
|
|
717
|
+
jsonrpc: "2.0",
|
|
718
|
+
id: null,
|
|
719
|
+
error: {
|
|
720
|
+
code: -32700,
|
|
721
|
+
message: "Parse error",
|
|
722
|
+
},
|
|
723
|
+
};
|
|
724
|
+
process.stdout.write(JSON.stringify(parseErr) + "\n");
|
|
725
|
+
}
|
|
726
|
+
});
|
|
311
727
|
}
|
|
312
728
|
});
|
|
313
729
|
}
|