@bicon/mcp-composer 0.3.1 → 0.3.2

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 CHANGED
@@ -58,6 +58,10 @@ naming the fix, never a wrong answer. Effects:
58
58
  spelling; new ones are created in the app's Settings); `dependsOn`,
59
59
  `requiredSkills[].skillId` and an update `id` must be ids that exist (any
60
60
  id format; Retired initiatives count, archived ones do not);
61
+ - ratings must be on the organisation's **slider step** (Settings › Slider
62
+ granularity: 5, 10, 20 or 25) — the plan states it, a value off the grid is
63
+ rejected with the step in the message (files exported before 2026-08-21
64
+ carry no step and are not checked);
61
65
  - every EU-AI-Act field the app strips is warned about while the
62
66
  organisation's AI-Act module is off; the export file defaults to the
63
67
  context's mode and language; a file newer than the Composer knows is flagged.
package/dist/index.mjs CHANGED
@@ -12,7 +12,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
12
12
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
13
13
 
14
14
  // src/version.ts
15
- var COMPOSER_VERSION = true ? "0.3.1" : readPackageVersion();
15
+ var COMPOSER_VERSION = true ? "0.3.2" : readPackageVersion();
16
16
 
17
17
  // ../../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
18
18
  var external_exports = {};
@@ -8721,7 +8721,7 @@ function buildSchemaDescriptor(sectionShapes) {
8721
8721
  ...AI_ACT_VOCABULARIES,
8722
8722
  note: "prohibitedPractices/art50Flags: arrays of these ids. artifacts/obligations: maps keyed by these ids. annexIIICategory: one of these, or omit when no Annex III area applies (record the reasoning in classificationRationale; annexExceptionRationale is only for an Art. 6(3) exception claim). Empty is honest; invented values are rejected."
8723
8723
  },
8724
- portfolioContext: "Ask the user for the organisation's portfolio-context file first (in the app: Import/Export \u2192 'Download portfolio context'). Call read_portfolio_context on it: it returns the interview plan in the organisation's own wording, the sub-dimensions that are switched off, and the organisation's business units, categories, tags, skills and initiatives \u2014 with the file, business unit and category MUST be from those lists (no inventing) and skill / dependency ids are validated. Pass the same context to assemble_initiative and export_initiative_file. Without the file, interview with the wording below and treat business unit / category as free text.",
8724
+ portfolioContext: "Ask the user for the organisation's portfolio-context file first (in the app: Import/Export \u2192 'Download portfolio context'). Call read_portfolio_context on it: it returns the interview plan in the organisation's own wording, the sub-dimensions that are switched off, the slider step the ratings must follow, and the organisation's business units, categories, tags, skills and initiatives \u2014 with the file, business unit and category MUST be from those lists (no inventing) and skill / dependency ids are validated. Pass the same context to assemble_initiative and export_initiative_file. Without the file, interview with the wording below and treat business unit / category as free text.",
8725
8725
  handoff: "Call assemble_initiative with the compact spec (+ context), review derivedScores (and any warnings) with the user, then call export_initiative_file with the SAME spec (+ context) \u2192 save the JSON \u2192 in the app: Import/Export \u2192 Single initiative \u2192 drop the file \u2192 'Add as new' \u2192 Confirm. If the initiative carries EU-AI-Act data, the organisation's EU-AI-Act module must be switched on (Settings \u203A AI Act) when importing."
8726
8726
  };
8727
8727
  }
@@ -8938,6 +8938,8 @@ var portfolioContextSchema = external_exports.object({
8938
8938
  currency: external_exports.string(),
8939
8939
  aiActEnabled: external_exports.boolean(),
8940
8940
  discountRatePct: external_exports.number(),
8941
+ /** Slider step (5/10/20/25). Files from before 2026-08-21 lack it → no grid check. */
8942
+ sliderGranularity: external_exports.number().int().positive().max(100).optional(),
8941
8943
  businessUnits: external_exports.array(external_exports.string()),
8942
8944
  categories: external_exports.array(external_exports.string()),
8943
8945
  suggestedTags: external_exports.array(external_exports.string()),
@@ -9053,6 +9055,10 @@ function resolveSub(base, ctxSlider, mode, lang) {
9053
9055
  if (note) out.note = note;
9054
9056
  return out;
9055
9057
  }
9058
+ function gridExample(step) {
9059
+ const pts = [0, step, 2 * step].filter((v) => v < 100);
9060
+ return `${pts.join(", ")} \u2026 100`;
9061
+ }
9056
9062
  function buildInterviewPlan(ctx, contextId) {
9057
9063
  const mode = ctx.portfolioMode;
9058
9064
  const lang = ctx.language;
@@ -9074,6 +9080,7 @@ function buildInterviewPlan(ctx, contextId) {
9074
9080
  ctx.businessUnits.length && ctx.categories.length ? "businessUnit MUST be one of lists.businessUnits and aiCategory one of lists.categories (matched case-insensitively, normalised to the organisation's spelling) \u2014 the Composer rejects anything else; new ones are created in the app's Settings, not in the interview." : "This organisation has no business units and/or categories configured yet \u2014 they must be added in the app's Settings and the context downloaded again before an initiative can be assembled.",
9075
9081
  "dependsOn entries must be ids from lists.initiatives; requiredSkills[].skillId must be ids from lists.skills. Never invent an id; leave the list empty when unsure.",
9076
9082
  "To UPDATE an existing initiative instead of creating a new one, pass its id (from lists.initiatives) as `id` in the spec \u2014 the exported file then updates it in the app (Import/Export \u2192 Single initiative \u2192 'Update'). Omit id for a new initiative.",
9083
+ ...ctx.sliderGranularity ? [`Ratings are in steps of ${ctx.sliderGranularity} (the organisation's slider step \u2014 Settings \u203A Slider granularity): ask for and send only multiples of ${ctx.sliderGranularity} between 0 and 100 (${gridExample(ctx.sliderGranularity)}); any other value is rejected.`] : [],
9077
9084
  "Dates: talk to the user in dd/mm/yyyy; you may send dates as dd/mm/yyyy, dd.mm.yyyy or yyyy-mm-dd \u2014 the Composer stores yyyy-mm-dd.",
9078
9085
  ctx.aiActEnabled ? "The organisation's EU-AI-Act module is ON: collect the AI-Act block and governance flags." : "The organisation's EU-AI-Act module is OFF: skip the AI-Act block and governance flags (the app would remove them on import).",
9079
9086
  `Pass \`context: "${contextId}"\` (this contextId \u2014 or the whole file again) to assemble_initiative and export_initiative_file so scores are derived over the enabled sub-dimensions and ids are validated. Amounts are in ${ctx.currency}; the default discount rate is ${ctx.discountRatePct}%.`,
@@ -9088,6 +9095,7 @@ function buildInterviewPlan(ctx, contextId) {
9088
9095
  currency: ctx.currency,
9089
9096
  aiActEnabled: ctx.aiActEnabled,
9090
9097
  discountRatePct: ctx.discountRatePct,
9098
+ ...ctx.sliderGranularity ? { sliderGranularity: ctx.sliderGranularity } : {},
9091
9099
  contextExportedAt: ctx.exportedAt
9092
9100
  },
9093
9101
  lists: {
@@ -9110,7 +9118,7 @@ function buildInterviewPlan(ctx, contextId) {
9110
9118
  // src/assembler.ts
9111
9119
  var uuidSchema = external_exports.string().uuid();
9112
9120
  var isUuid = (v) => typeof v === "string" && uuidSchema.safeParse(v).success;
9113
- function checkSubs(dim, subs, errors, disabled) {
9121
+ function checkSubs(dim, subs, errors, disabled, step) {
9114
9122
  const expected = DIMENSION_SUBS[dim];
9115
9123
  const enabled = expected.filter((k) => !disabled.has(k));
9116
9124
  if (!subs || typeof subs !== "object") {
@@ -9122,6 +9130,7 @@ function checkSubs(dim, subs, errors, disabled) {
9122
9130
  if (v === void 0) errors.push(`evaluation.${dim}.subs.${key} is missing`);
9123
9131
  else if (typeof v !== "number" || !Number.isFinite(v)) errors.push(`evaluation.${dim}.subs.${key} must be a number`);
9124
9132
  else if (v < 0 || v > 100) errors.push(`evaluation.${dim}.subs.${key} must be within 0\u2013100 (got ${v})`);
9133
+ else if (step && v % step !== 0) errors.push(`evaluation.${dim}.subs.${key} must be a multiple of ${step} \u2014 the organisation's slider step (got ${v})`);
9125
9134
  }
9126
9135
  for (const key of Object.keys(subs)) {
9127
9136
  if (!expected.includes(key)) errors.push(`evaluation.${dim}.subs.${key} is not a known sub-dimension (expected: ${enabled.join(", ")})`);
@@ -9183,7 +9192,7 @@ function assembleInitiative(input, now = /* @__PURE__ */ new Date()) {
9183
9192
  errors.push(`evaluation.${dim} is missing`);
9184
9193
  continue;
9185
9194
  }
9186
- checkSubs(dim, d.subs, errors, disabled);
9195
+ checkSubs(dim, d.subs, errors, disabled, context?.sliderGranularity);
9187
9196
  if (!d.confidence) errors.push(`evaluation.${dim}.confidence is missing (Low | Medium | High)`);
9188
9197
  for (const key of Object.keys(d.subs ?? {})) {
9189
9198
  if (disabled.has(key)) warnings.push(`evaluation.${dim}.subs.${key}: this sub-dimension is switched off in the organisation \u2014 value ignored (stored as 0, not scored).`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bicon/mcp-composer",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "MCP server that helps an AI client compose a valid BICon portfolio initiative and hand it back as an import file (draft-first, no auth, no API calls).",
5
5
  "license": "UNLICENSED",
6
6
  "author": "BICon Establishment",