@algosuite/vo-mcp 0.2.0-beta.17 → 0.2.0-beta.18

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/cli.js CHANGED
@@ -1625,7 +1625,7 @@ var init_sync_config = __esm({
1625
1625
  // src/cli.ts
1626
1626
  import { homedir as homedir6, hostname } from "node:os";
1627
1627
  import { randomUUID as randomUUID5 } from "node:crypto";
1628
- import { join as join8 } from "node:path";
1628
+ import { join as join9 } from "node:path";
1629
1629
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
1630
1630
 
1631
1631
  // src/server.ts
@@ -2481,7 +2481,11 @@ async function handleConsensusJudgment(deps, rawInput, signal) {
2481
2481
  ...engineResult.low_confidence_sources !== void 0 ? { low_confidence_sources: engineResult.low_confidence_sources } : {},
2482
2482
  // Escalation (from citation grade or human-tiebreak synthesizer).
2483
2483
  ...engineResult.escalation_required !== void 0 ? { escalation_required: engineResult.escalation_required } : {},
2484
- ...engineResult.escalation_reason !== void 0 ? { escalation_reason: engineResult.escalation_reason } : {}
2484
+ ...engineResult.escalation_reason !== void 0 ? { escalation_reason: engineResult.escalation_reason } : {},
2485
+ // Critique-uptake (2026-07-20 red-team fix) — the engine computes this
2486
+ // on every call; this spread closes the gap where the visibility report
2487
+ // was itself silently dropped at the payload boundary.
2488
+ ...engineResult.critique_uptake !== void 0 ? { critique_uptake: engineResult.critique_uptake } : {}
2485
2489
  };
2486
2490
  const envelope = {
2487
2491
  tool: TOOL_NAME4,
@@ -5741,6 +5745,121 @@ async function handleHqWhiteboardRead(_deps, rawInput, signal) {
5741
5745
  return jsonContent(await callWhiteboard("GET", input, signal));
5742
5746
  }
5743
5747
 
5748
+ // src/tools/skills/skill-corpus.ts
5749
+ init_common();
5750
+ import { existsSync as existsSync6, statSync as statSync4 } from "node:fs";
5751
+ import { dirname as dirname5, isAbsolute, join as join8, resolve as resolve2 } from "node:path";
5752
+ import {
5753
+ loadSkillsFromDir
5754
+ } from "@algosuite/skill-registry";
5755
+ var LIST_TOOL_NAME = "vo_skill_list";
5756
+ var GET_TOOL_NAME = "vo_skill_get";
5757
+ var listDescription = "List the Algosuite skill corpus (name + trigger description for every skill). Call once near session start to learn which skills exist; then fetch the full instructions for a relevant skill with vo_skill_get. This is the same corpus Claude Code loads natively from .claude/skills \u2014 served over MCP so every vendor works from identical playbooks. Pass refresh:true to re-scan from disk.";
5758
+ var getDescription = "Fetch the full markdown instructions of one Algosuite skill by name. Follow the returned instructions for the current task the same way a native skill invocation would. Use vo_skill_list to discover skill names.";
5759
+ var listInputSchema = {
5760
+ type: "object",
5761
+ properties: {
5762
+ refresh: {
5763
+ type: "boolean",
5764
+ description: "Re-scan the skills directory instead of using the cached corpus."
5765
+ }
5766
+ },
5767
+ required: []
5768
+ };
5769
+ var getInputSchema = {
5770
+ type: "object",
5771
+ properties: {
5772
+ name: {
5773
+ type: "string",
5774
+ description: "Skill name exactly as returned by vo_skill_list."
5775
+ }
5776
+ },
5777
+ required: ["name"]
5778
+ };
5779
+ var MAX_WALK_UP_LEVELS = 8;
5780
+ var cachedCorpus = null;
5781
+ function resolveSkillsDir(env = process.env, startDir = process.cwd()) {
5782
+ const override = env.VO_SKILLS_DIR;
5783
+ if (typeof override === "string" && override.length > 0) {
5784
+ const abs = isAbsolute(override) ? override : resolve2(startDir, override);
5785
+ return existsSync6(abs) && statSync4(abs).isDirectory() ? abs : null;
5786
+ }
5787
+ let dir = resolve2(startDir);
5788
+ for (let i = 0; i < MAX_WALK_UP_LEVELS; i += 1) {
5789
+ const candidate = join8(dir, ".claude", "skills");
5790
+ if (existsSync6(candidate) && statSync4(candidate).isDirectory()) return candidate;
5791
+ const parent = dirname5(dir);
5792
+ if (parent === dir) break;
5793
+ dir = parent;
5794
+ }
5795
+ return null;
5796
+ }
5797
+ function loadCorpus() {
5798
+ const skillsDir = resolveSkillsDir();
5799
+ if (skillsDir === null) {
5800
+ return {
5801
+ skills: [],
5802
+ skillsDir: null,
5803
+ unavailableReason: "No skills directory found. Set VO_SKILLS_DIR or run inside a repo with .claude/skills."
5804
+ };
5805
+ }
5806
+ try {
5807
+ return { skills: loadSkillsFromDir(skillsDir), skillsDir, unavailableReason: null };
5808
+ } catch (err) {
5809
+ const message = err instanceof Error ? `${err.name}: ${err.message}` : String(err);
5810
+ return { skills: [], skillsDir, unavailableReason: message };
5811
+ }
5812
+ }
5813
+ function getCorpus(refresh) {
5814
+ if (refresh || cachedCorpus === null) {
5815
+ cachedCorpus = loadCorpus();
5816
+ }
5817
+ return cachedCorpus;
5818
+ }
5819
+ async function handleSkillList(_deps, rawInput) {
5820
+ const input = rawInput ?? {};
5821
+ const refresh = input.refresh === true;
5822
+ const corpus = getCorpus(refresh);
5823
+ return jsonContent({
5824
+ corpus_available: corpus.unavailableReason === null,
5825
+ skills_dir: corpus.skillsDir,
5826
+ unavailable_reason: corpus.unavailableReason,
5827
+ skill_count: corpus.skills.length,
5828
+ skills: corpus.skills.map((s) => ({ name: s.name, description: s.description }))
5829
+ });
5830
+ }
5831
+ async function handleSkillGet(_deps, rawInput) {
5832
+ const input = rawInput ?? {};
5833
+ if (typeof input.name !== "string" || input.name.trim().length === 0) {
5834
+ throw invalidParams(GET_TOOL_NAME, 'input field "name" (non-empty string) is required');
5835
+ }
5836
+ const requested = input.name.trim();
5837
+ const corpus = getCorpus(false);
5838
+ if (corpus.unavailableReason !== null) {
5839
+ return jsonContent({
5840
+ corpus_available: false,
5841
+ unavailable_reason: corpus.unavailableReason,
5842
+ skill: null
5843
+ });
5844
+ }
5845
+ const skill = corpus.skills.find((s) => s.name === requested);
5846
+ if (skill === void 0) {
5847
+ throw invalidParams(
5848
+ GET_TOOL_NAME,
5849
+ `unknown skill "${requested}". Known skills: ${corpus.skills.map((s) => s.name).join(", ")}`
5850
+ );
5851
+ }
5852
+ return jsonContent({
5853
+ corpus_available: true,
5854
+ skill: {
5855
+ name: skill.name,
5856
+ description: skill.description,
5857
+ instructions: skill.body,
5858
+ source_path: skill.sourcePath
5859
+ }
5860
+ });
5861
+ }
5862
+
5744
5863
  // src/server.ts
5745
5864
  function buildToolRegistry() {
5746
5865
  return {
@@ -5951,6 +6070,22 @@ function buildToolRegistry() {
5951
6070
  inputSchema: readInputSchema
5952
6071
  },
5953
6072
  handler: handleHqWhiteboardRead
6073
+ },
6074
+ [LIST_TOOL_NAME]: {
6075
+ definition: {
6076
+ name: LIST_TOOL_NAME,
6077
+ description: listDescription,
6078
+ inputSchema: listInputSchema
6079
+ },
6080
+ handler: handleSkillList
6081
+ },
6082
+ [GET_TOOL_NAME]: {
6083
+ definition: {
6084
+ name: GET_TOOL_NAME,
6085
+ description: getDescription,
6086
+ inputSchema: getInputSchema
6087
+ },
6088
+ handler: handleSkillGet
5954
6089
  }
5955
6090
  };
5956
6091
  }
@@ -6006,7 +6141,7 @@ function createServer(options) {
6006
6141
  // src/cache/sqlite-cache.ts
6007
6142
  import { createHash as createHash3 } from "node:crypto";
6008
6143
  import { chmodSync as chmodSync3, mkdirSync as mkdirSync5 } from "node:fs";
6009
- import { dirname as dirname5 } from "node:path";
6144
+ import { dirname as dirname6 } from "node:path";
6010
6145
  import { DatabaseSync } from "node:sqlite";
6011
6146
 
6012
6147
  // src/cache/canonicalize.ts
@@ -6051,7 +6186,7 @@ function normalizeString(s) {
6051
6186
  function createSqliteCache(options) {
6052
6187
  const fileBacked = options.dbPath !== ":memory:";
6053
6188
  if (fileBacked) {
6054
- mkdirSync5(dirname5(options.dbPath), { recursive: true, mode: 448 });
6189
+ mkdirSync5(dirname6(options.dbPath), { recursive: true, mode: 448 });
6055
6190
  }
6056
6191
  const versionNamespace = options.cacheVersionNamespace ?? "";
6057
6192
  const db = new DatabaseSync(options.dbPath);
@@ -6524,6 +6659,10 @@ function createEngineConsensusClient(options) {
6524
6659
  ...mapFanOutDiagnostics(response.fan_out_diagnostics) !== void 0 ? { fan_out_diagnostics: mapFanOutDiagnostics(response.fan_out_diagnostics) } : {},
6525
6660
  // Stage A7-shadow — adaptive-vs-incumbent comparison (PII-free; present iff shadow on).
6526
6661
  ...mapShadowSynthesis(response.shadow_synthesis) !== void 0 ? { shadow_synthesis: mapShadowSynthesis(response.shadow_synthesis) } : {},
6662
+ // Critique-uptake (2026-07-20 red-team fix) — verifier-critique
6663
+ // visibility report; previously computed by the engine on every
6664
+ // call but dropped at this boundary.
6665
+ ...response.critique_uptake !== void 0 ? { critique_uptake: response.critique_uptake } : {},
6527
6666
  // Source-grounded additive outputs (Tier-4 features).
6528
6667
  ...useSourceGrounded ? { source_grounded: true } : {},
6529
6668
  ...sourceExtras?.citation_grade !== void 0 ? { citation_grade: sourceExtras.citation_grade } : {},
@@ -6904,7 +7043,7 @@ async function runLogin(opts = {}) {
6904
7043
  const nowIso = opts.nowIso ?? (() => (/* @__PURE__ */ new Date()).toISOString());
6905
7044
  const openBrowser = opts.openBrowser ?? defaultOpenBrowser;
6906
7045
  const state = randomBytes(32).toString("base64url");
6907
- return new Promise((resolve2, reject) => {
7046
+ return new Promise((resolve3, reject) => {
6908
7047
  let settled = false;
6909
7048
  const finish = (err, result) => {
6910
7049
  if (settled) return;
@@ -6912,7 +7051,7 @@ async function runLogin(opts = {}) {
6912
7051
  clearTimeout(timer);
6913
7052
  server.close();
6914
7053
  if (err) reject(err);
6915
- else resolve2(result);
7054
+ else resolve3(result);
6916
7055
  };
6917
7056
  const server = createServer2((req, res) => {
6918
7057
  const url = new URL(req.url ?? "/", "http://127.0.0.1");
@@ -7027,7 +7166,7 @@ init_common();
7027
7166
  function defaultCacheDbPath() {
7028
7167
  const env = process.env["VO_MCP_DB_PATH"];
7029
7168
  if (env && env.length > 0) return env;
7030
- return join8(homedir6(), ".claude", "vo-mcp-cache.db");
7169
+ return join9(homedir6(), ".claude", "vo-mcp-cache.db");
7031
7170
  }
7032
7171
  async function probeEngineVersion() {
7033
7172
  try {