@nonbot/mcp 0.3.2 → 0.3.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.
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface EdgeLibrary {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
path: 'curve' | 'circuit';
|
|
5
|
+
hierarchyWidth: number;
|
|
6
|
+
dependencyWidth: number;
|
|
7
|
+
ink: 'gradient' | 'solid';
|
|
8
|
+
color?: string;
|
|
9
|
+
pads: boolean;
|
|
10
|
+
corner: number;
|
|
11
|
+
}
|
|
12
|
+
export declare const NONBOT_DEFAULT: EdgeLibrary;
|
|
13
|
+
export declare const NONBOT_CIRCUIT_BOARD: EdgeLibrary;
|
|
14
|
+
export declare const BUILT_IN_EDGE_LIBRARIES: Record<string, EdgeLibrary>;
|
|
15
|
+
export declare function safeEdgeLibrary(x: unknown): EdgeLibrary | null;
|
|
16
|
+
export declare function resolveEdgeLibraryArg(arg: unknown): {
|
|
17
|
+
library: EdgeLibrary | null;
|
|
18
|
+
} | {
|
|
19
|
+
error: string;
|
|
20
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export const NONBOT_DEFAULT = {
|
|
2
|
+
id: 'nonbot-default', name: 'non.bot default', path: 'curve', hierarchyWidth: 3, dependencyWidth: 2, ink: 'gradient', pads: false, corner: 0,
|
|
3
|
+
};
|
|
4
|
+
export const NONBOT_CIRCUIT_BOARD = {
|
|
5
|
+
id: 'nonbot-circuit-board', name: 'NON.BOT Circuit Board', path: 'circuit', hierarchyWidth: 2, dependencyWidth: 1.5, ink: 'solid', color: '#C8894A', pads: true, corner: 14,
|
|
6
|
+
};
|
|
7
|
+
export const BUILT_IN_EDGE_LIBRARIES = {
|
|
8
|
+
[NONBOT_DEFAULT.id]: NONBOT_DEFAULT,
|
|
9
|
+
[NONBOT_CIRCUIT_BOARD.id]: NONBOT_CIRCUIT_BOARD,
|
|
10
|
+
};
|
|
11
|
+
const ID_RE = /^[a-z0-9][a-z0-9:_-]{0,63}$/;
|
|
12
|
+
const HEX_RE = /^#[0-9a-fA-F]{6}$/;
|
|
13
|
+
const clamp = (v, min, max) => typeof v === 'number' && Number.isFinite(v) ? Math.round(Math.min(max, Math.max(min, v)) * 2) / 2 : null;
|
|
14
|
+
export function safeEdgeLibrary(x) {
|
|
15
|
+
if (!x || typeof x !== 'object')
|
|
16
|
+
return null;
|
|
17
|
+
const o = x;
|
|
18
|
+
if (typeof o.id !== 'string' || !ID_RE.test(o.id) || typeof o.name !== 'string' || !o.name.trim())
|
|
19
|
+
return null;
|
|
20
|
+
if (o.path !== 'curve' && o.path !== 'circuit')
|
|
21
|
+
return null;
|
|
22
|
+
if (o.ink !== 'gradient' && o.ink !== 'solid')
|
|
23
|
+
return null;
|
|
24
|
+
const hierarchyWidth = clamp(o.hierarchyWidth, 1, 8);
|
|
25
|
+
const dependencyWidth = clamp(o.dependencyWidth, 1, 6);
|
|
26
|
+
if (hierarchyWidth === null || dependencyWidth === null)
|
|
27
|
+
return null;
|
|
28
|
+
const color = typeof o.color === 'string' && HEX_RE.test(o.color) ? o.color.toUpperCase() : undefined;
|
|
29
|
+
if (o.ink === 'solid' && !color)
|
|
30
|
+
return null;
|
|
31
|
+
return {
|
|
32
|
+
id: o.id, name: o.name.trim().slice(0, 48), path: o.path, hierarchyWidth, dependencyWidth, ink: o.ink,
|
|
33
|
+
...(color ? { color } : {}), pads: o.pads === true, corner: Math.round(clamp(o.corner ?? 0, 0, 40) ?? 0),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function resolveEdgeLibraryArg(arg) {
|
|
37
|
+
const lib = typeof arg === 'string' ? BUILT_IN_EDGE_LIBRARIES[arg] ?? null : safeEdgeLibrary(arg);
|
|
38
|
+
if (!lib) {
|
|
39
|
+
return { error: typeof arg === 'string'
|
|
40
|
+
? `Unknown edge library "${arg}". Built in: ${Object.keys(BUILT_IN_EDGE_LIBRARIES).join(', ')} — or pass a whole library object (a WhyStore item's \`library\`).`
|
|
41
|
+
: 'edge_library is not a whole library: needs id, name, path (curve|circuit), hierarchyWidth 1–8, dependencyWidth 1–6, ink (gradient|solid; solid needs color #RRGGBB), pads, corner 0–40.' };
|
|
42
|
+
}
|
|
43
|
+
return { library: lib.id === NONBOT_DEFAULT.id ? null : lib };
|
|
44
|
+
}
|
package/dist/core/server.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import type { ApiContext } from './config.js';
|
|
3
3
|
export declare const SERVER_NAME = "nonbot-mcp";
|
|
4
|
-
export declare const SERVER_VERSION = "0.3.
|
|
4
|
+
export declare const SERVER_VERSION = "0.3.3";
|
|
5
5
|
export declare const INSTRUCTIONS: string;
|
|
6
6
|
export declare function registerAll(server: McpServer, ctx: ApiContext): void;
|
|
7
7
|
export declare function createNonbotMcpServer(ctx: ApiContext): McpServer;
|
package/dist/core/server.js
CHANGED
|
@@ -10,7 +10,7 @@ import { registerRadbugsTools } from './toolsets/radbugs.js';
|
|
|
10
10
|
import { registerResources } from './resources.js';
|
|
11
11
|
import { registerPrompts } from './prompts.js';
|
|
12
12
|
export const SERVER_NAME = 'nonbot-mcp';
|
|
13
|
-
export const SERVER_VERSION = '0.3.
|
|
13
|
+
export const SERVER_VERSION = '0.3.3';
|
|
14
14
|
export const INSTRUCTIONS = [
|
|
15
15
|
'non.bot MCP — work against the caller’s real product-management data, not a copy.',
|
|
16
16
|
'Two domains: PORTFOLIOS (the SAFe portfolio canvas — epics → features → stories) and',
|
|
@@ -7,6 +7,7 @@ import { layoutReleaseLane } from '../releases.js';
|
|
|
7
7
|
import { emptyIp, IP_KINDS, IP_NODE_SIZE } from '../ipShape.js';
|
|
8
8
|
import { withMapHeaders } from '../mapHeaders.js';
|
|
9
9
|
import { renderPreviewSvg } from '../preview.js';
|
|
10
|
+
import { resolveEdgeLibraryArg } from '../edgeLibraries.js';
|
|
10
11
|
import { applyStyleRules, CARD_STYLES, TITLE_SIZES, ACCENTS, SHOW_KEYS, STATES as STYLE_STATES } from '../style.js';
|
|
11
12
|
const STATES = ['funnel', 'reviewing', 'analyzing', 'ready', 'implementing', 'done'];
|
|
12
13
|
const OKR_STATUSES = ['on-track', 'at-risk', 'behind'];
|
|
@@ -424,17 +425,21 @@ export function registerBuildTools(server, ctx) {
|
|
|
424
425
|
});
|
|
425
426
|
server.registerTool('portfolio_set_meta', {
|
|
426
427
|
title: 'Set portfolio settings',
|
|
427
|
-
description: 'Graph-level settings that travel with the portfolio (the `__graph_meta__` record): `context_text` (the portfolio\'s context notes — what a newcomer reads first), `palette` ({ id, name, swatches: [{hex, label?}] ≤ 10, roles?: {epic, feature, story, …: hex | "p:N"} }), `canvas_style`, `sprint_settings
|
|
428
|
+
description: 'Graph-level settings that travel with the portfolio (the `__graph_meta__` record): `context_text` (the portfolio\'s context notes — what a newcomer reads first), `palette` ({ id, name, swatches: [{hex, label?}] ≤ 10, roles?: {epic, feature, story, …: hex | "p:N"} }), `canvas_style`, `sprint_settings`, `edge_library` (how the wires are drawn: "nonbot-default" — the canvas as it always was — or "nonbot-circuit-board" — NON.BOT Circuit Board, copper traces with 45° corners, pads and vias — or a whole library object from the WhyStore Edges catalog). Only the keys you pass change; everything else in the record is kept.',
|
|
428
429
|
inputSchema: {
|
|
429
430
|
portfolio_id: z.string(),
|
|
430
431
|
context_text: z.string().max(20000).optional(),
|
|
431
432
|
palette: z.object({ id: z.string().min(1).max(64), name: z.string().min(1).max(64), swatches: z.array(z.object({ hex: z.string().regex(/^#[0-9a-fA-F]{6}$/), label: z.string().max(32).optional() })).max(10), roles: z.record(z.string(), z.string()).optional() }).optional(),
|
|
432
433
|
canvas_style: z.record(z.string(), z.unknown()).optional(),
|
|
433
434
|
sprint_settings: z.record(z.string(), z.unknown()).optional(),
|
|
435
|
+
edge_library: z.union([z.string().max(64), z.record(z.string(), z.unknown())]).optional(),
|
|
434
436
|
expected_version: z.number().int().optional(),
|
|
435
437
|
},
|
|
436
438
|
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
|
|
437
439
|
}, async (a) => {
|
|
440
|
+
const edge = a.edge_library === undefined ? undefined : resolveEdgeLibraryArg(a.edge_library);
|
|
441
|
+
if (edge && 'error' in edge)
|
|
442
|
+
return fail(edge.error);
|
|
438
443
|
const g = await loadGraph(ctx, a.portfolio_id);
|
|
439
444
|
const cur = g.nodes.find(n => n.id === '__graph_meta__' || n.type === 'graph-meta');
|
|
440
445
|
const data = { ...(cur?.data ?? {}) };
|
|
@@ -444,6 +449,14 @@ export function registerBuildTools(server, ctx) {
|
|
|
444
449
|
data.palette = { ...a.palette, swatches: a.palette.swatches.map(s => ({ ...s, hex: s.hex.toUpperCase() })), roles: a.palette.roles ?? {} };
|
|
445
450
|
if (a.canvas_style)
|
|
446
451
|
data.canvasStyle = { ...(data.canvasStyle ?? {}), ...a.canvas_style };
|
|
452
|
+
if (edge) {
|
|
453
|
+
const cs = { ...(data.canvasStyle ?? {}) };
|
|
454
|
+
if (edge.library)
|
|
455
|
+
cs.edgeLibrary = edge.library;
|
|
456
|
+
else
|
|
457
|
+
delete cs.edgeLibrary;
|
|
458
|
+
data.canvasStyle = cs;
|
|
459
|
+
}
|
|
447
460
|
if (a.sprint_settings)
|
|
448
461
|
data.sprintSettings = { ...(data.sprintSettings ?? {}), ...a.sprint_settings };
|
|
449
462
|
const meta = { id: '__graph_meta__', type: 'graph-meta', position: { x: 0, y: 0 }, data };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nonbot/mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The non.bot MCP server — one server for your portfolios, decision graph, and Runs. Runs over stdio (Claude Code, Cursor, VS Code) with a pat_ token. Built on MCP protocol 2025-11-25.",
|
|
6
6
|
"keywords": [
|