@productbrain/mcp 0.0.1-beta.41 → 0.0.1-beta.42

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.
@@ -4,7 +4,7 @@ import {
4
4
  trackCaptureClassifierFallback,
5
5
  trackQualityVerdict,
6
6
  trackToolCall
7
- } from "./chunk-P7ABQEFK.js";
7
+ } from "./chunk-6R67YS23.js";
8
8
 
9
9
  // src/tools/smart-capture.ts
10
10
  import { z } from "zod";
@@ -2321,4 +2321,4 @@ export {
2321
2321
  formatRubricCoaching,
2322
2322
  formatRubricVerdictSection
2323
2323
  };
2324
- //# sourceMappingURL=chunk-M264FY2V.js.map
2324
+ //# sourceMappingURL=chunk-4YKORBQX.js.map
@@ -9,8 +9,15 @@ function log(msg) {
9
9
  process.stderr.write(msg);
10
10
  }
11
11
  }
12
+ function getBuildTimeKey() {
13
+ try {
14
+ return "";
15
+ } catch {
16
+ return "";
17
+ }
18
+ }
12
19
  function initAnalytics() {
13
- const apiKey = process.env.POSTHOG_MCP_KEY || "";
20
+ const apiKey = process.env.POSTHOG_MCP_KEY || getBuildTimeKey();
14
21
  if (!apiKey) {
15
22
  log("[MCP-ANALYTICS] No PostHog key \u2014 tracking disabled (set SYNERGYOS_POSTHOG_KEY at build time for publish)\n");
16
23
  return;
@@ -158,4 +165,4 @@ export {
158
165
  getPostHogClient,
159
166
  shutdownAnalytics
160
167
  };
161
- //# sourceMappingURL=chunk-P7ABQEFK.js.map
168
+ //# sourceMappingURL=chunk-6R67YS23.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/analytics.ts"],"sourcesContent":["/**\n * PostHog analytics for SynergyOS maintainers — tracks MCP usage (sessions, tool calls).\n * Not user-facing. Key is injected at build time via SYNERGYOS_POSTHOG_KEY.\n * Override with POSTHOG_MCP_KEY for self-hosted deployments.\n */\n\nimport { userInfo } from \"node:os\";\nimport { PostHog } from \"posthog-node\";\n\nlet client: PostHog | null = null;\nlet distinctId = \"anonymous\";\n\nconst POSTHOG_HOST = \"https://eu.i.posthog.com\";\n\n/** Injected at build time: SYNERGYOS_POSTHOG_KEY env when running `npm run build`/publish. */\ndeclare const __SYNERGYOS_POSTHOG_KEY__: string;\n\n/** Only write to stderr when MCP_DEBUG=1 for quieter default DX. */\nfunction log(msg: string): void {\n if (process.env.MCP_DEBUG === \"1\") {\n process.stderr.write(msg);\n }\n}\n\nfunction getBuildTimeKey(): string {\n try {\n return __SYNERGYOS_POSTHOG_KEY__;\n } catch {\n // Not replaced by bundler (e.g. running via tsx in tests) — treat as absent.\n return \"\";\n }\n}\n\nexport function initAnalytics(): void {\n const apiKey = process.env.POSTHOG_MCP_KEY || getBuildTimeKey();\n if (!apiKey) {\n log(\"[MCP-ANALYTICS] No PostHog key — tracking disabled (set SYNERGYOS_POSTHOG_KEY at build time for publish)\\n\");\n return;\n }\n\n client = new PostHog(apiKey, {\n host: POSTHOG_HOST,\n flushAt: 1,\n flushInterval: 5000,\n featureFlagsPollingInterval: 30_000,\n });\n distinctId = process.env.MCP_USER_ID || fallbackDistinctId();\n\n log(`[MCP-ANALYTICS] Initialized — host=${POSTHOG_HOST} distinctId=${distinctId}\\n`);\n}\n\nfunction fallbackDistinctId(): string {\n try {\n return userInfo().username;\n } catch {\n return `os-${process.pid}`;\n }\n}\n\nexport function trackSessionStarted(\n workspaceId: string,\n serverVersion: string,\n): void {\n if (!client) return;\n client.capture({\n distinctId,\n event: \"mcp_session_started\",\n properties: {\n workspace_id: workspaceId,\n server_version: serverVersion,\n source: \"mcp-server\",\n $groups: { workspace: workspaceId },\n },\n });\n}\n\nexport function trackToolCall(\n fn: string,\n status: \"ok\" | \"error\",\n durationMs: number,\n workspaceId: string,\n errorMsg?: string,\n): void {\n const properties: Record<string, unknown> = {\n tool: fn,\n status,\n duration_ms: durationMs,\n workspace_id: workspaceId,\n source: \"mcp-server\",\n $groups: { workspace: workspaceId },\n };\n if (errorMsg) properties.error = errorMsg;\n\n if (!client) return;\n client.capture({\n distinctId,\n event: \"mcp_tool_called\",\n properties,\n });\n}\n\nexport function trackSetupStarted(): void {\n if (!client) return;\n client.capture({\n distinctId,\n event: \"mcp_setup_started\",\n properties: {\n source: \"mcp-server\",\n platform: process.platform,\n },\n });\n}\n\nexport function trackSetupCompleted(\n chosenClient: string,\n outcome: \"config_written\" | \"config_existed\" | \"snippet_shown\" | \"write_error\",\n): void {\n if (!client) return;\n client.capture({\n distinctId,\n event: \"mcp_setup_completed\",\n properties: {\n client: chosenClient,\n outcome,\n source: \"mcp-server\",\n platform: process.platform,\n },\n });\n}\n\nexport function trackQualityVerdict(\n workspaceId: string,\n props: {\n entry_id: string;\n entry_type: string;\n tier: string;\n context: string;\n passed: boolean;\n source: string;\n criteria_total: number;\n criteria_failed: number;\n llm_scheduled: boolean;\n },\n): void {\n if (!client) return;\n client.capture({\n distinctId,\n event: \"quality_verdict_generated\",\n properties: {\n ...props,\n workspace_id: workspaceId,\n source_system: \"mcp-server\",\n $groups: { workspace: workspaceId },\n },\n });\n}\n\nexport function trackQualityCheck(\n workspaceId: string,\n props: {\n entry_id: string;\n entry_type: string;\n tier: string;\n passed: boolean;\n source: string;\n llm_status?: string;\n llm_duration_ms?: number;\n llm_error?: string;\n has_roger_martin: boolean;\n },\n): void {\n if (!client) return;\n client.capture({\n distinctId,\n event: \"quality_verdict_checked\",\n properties: {\n ...props,\n workspace_id: workspaceId,\n source_system: \"mcp-server\",\n $groups: { workspace: workspaceId },\n },\n });\n}\n\nexport type ClassifierReasonCategory =\n | \"auto-routed\"\n | \"low-confidence\"\n | \"ambiguous\"\n | \"non-provisioned\";\n\ntype CaptureClassifierTelemetryProps = {\n predicted_collection: string;\n confidence: number;\n auto_routed: boolean;\n reason_category: ClassifierReasonCategory;\n explicit_collection_provided: boolean;\n};\n\nfunction trackCaptureClassifierEvent(\n event: \"mcp_capture_classifier_evaluated\" | \"mcp_capture_classifier_auto_routed\" | \"mcp_capture_classifier_fallback\",\n workspaceId: string,\n props: CaptureClassifierTelemetryProps,\n): void {\n if (!client) return;\n try {\n client.capture({\n distinctId,\n event,\n properties: {\n ...props,\n workspace_id: workspaceId,\n source_system: \"mcp-server\",\n $groups: { workspace: workspaceId },\n },\n });\n } catch {\n // Analytics are advisory and must never break capture flow.\n }\n}\n\nexport function trackCaptureClassifierEvaluated(\n workspaceId: string,\n props: CaptureClassifierTelemetryProps,\n): void {\n trackCaptureClassifierEvent(\"mcp_capture_classifier_evaluated\", workspaceId, props);\n}\n\nexport function trackCaptureClassifierAutoRouted(\n workspaceId: string,\n props: CaptureClassifierTelemetryProps,\n): void {\n trackCaptureClassifierEvent(\"mcp_capture_classifier_auto_routed\", workspaceId, props);\n}\n\nexport function trackCaptureClassifierFallback(\n workspaceId: string,\n props: CaptureClassifierTelemetryProps,\n): void {\n trackCaptureClassifierEvent(\"mcp_capture_classifier_fallback\", workspaceId, props);\n}\n\nexport function getPostHogClient(): PostHog | null {\n return client;\n}\n\nexport async function shutdownAnalytics(): Promise<void> {\n await client?.shutdown();\n}\n"],"mappings":"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","names":[]}
@@ -25,11 +25,11 @@ import {
25
25
  startAgentSession,
26
26
  trackWriteTool,
27
27
  translateStaleToolNames
28
- } from "./chunk-M264FY2V.js";
28
+ } from "./chunk-4YKORBQX.js";
29
29
  import {
30
30
  trackQualityCheck,
31
31
  trackQualityVerdict
32
- } from "./chunk-P7ABQEFK.js";
32
+ } from "./chunk-6R67YS23.js";
33
33
 
34
34
  // src/server.ts
35
35
  import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -61,7 +61,7 @@ var updateEntrySchema = z.object({
61
61
  z.enum(["draft", "active", "deprecated", "archived"]),
62
62
  z.enum(["open", "pending", "decided", "proposed", "accepted", "needs-amendment", "withdrawn", "review", "in-progress", "conflict", "processing", "closed", "shaped", "bet", "building", "shipped"])
63
63
  ]).optional().describe("Lifecycle status: draft | active | deprecated | archived. **Workflow values (open, pending, decided\u2026) are deprecated here \u2014 use `workflowStatus` instead. Passing a workflow value as `status` will be auto-routed with a warning until 2026-09-03, then hard-errored.**"),
64
- workflowStatus: z.enum(["open", "pending", "proposed", "accepted", "needs-amendment", "withdrawn", "review", "in-progress", "decided", "conflict", "processing", "closed"]).optional().describe("Collection workflow state (e.g. 'open', 'pending', 'decided', 'conflict'). Validated against collection's allowed values."),
64
+ workflowStatus: z.enum(["open", "pending", "proposed", "accepted", "needs-amendment", "withdrawn", "review", "in-progress", "decided", "conflict", "processing", "closed", "shaped", "bet", "building", "shipped"]).optional().describe("Collection workflow state (e.g. 'open', 'pending', 'decided', 'conflict', 'building', 'shipped'). Validated against collection's allowed values."),
65
65
  data: z.record(z.unknown()).optional().describe("Fields to update (merged with existing data)"),
66
66
  order: z.number().optional().describe("New sort order"),
67
67
  canonicalKey: z.string().optional().describe("Semantic type (e.g. 'decision', 'tension'). Only changeable on draft/uncommitted entries."),
@@ -195,7 +195,7 @@ ${formatted}` }]
195
195
  },
196
196
  async ({ entryId }) => {
197
197
  requireWriteAccess();
198
- const { runContradictionCheck } = await import("./smart-capture-GH4CXVVX.js");
198
+ const { runContradictionCheck } = await import("./smart-capture-TD5M4WFE.js");
199
199
  const entry = await mcpQuery("chain.getEntry", { entryId });
200
200
  if (!entry) {
201
201
  return {
@@ -4121,6 +4121,7 @@ async function handleStart2(args) {
4121
4121
  const sc = orient?.strategicContext;
4122
4122
  const parts = [];
4123
4123
  if (sc?.vision) parts.push(`Vision: ${sc.vision}`);
4124
+ if (sc?.purpose) parts.push(`Purpose: ${sc.purpose}`);
4124
4125
  if (sc?.activeBetCount) parts.push(`${sc.activeBetCount} active bet(s)`);
4125
4126
  if (sc?.activeTensionCount) parts.push(`${sc.activeTensionCount} open tension(s)`);
4126
4127
  if (orient?.activeBets?.length) {
@@ -4800,7 +4801,7 @@ async function handleCommitConstellation(args) {
4800
4801
  }
4801
4802
  let contradictionWarnings = [];
4802
4803
  try {
4803
- const { runContradictionCheck } = await import("./smart-capture-GH4CXVVX.js");
4804
+ const { runContradictionCheck } = await import("./smart-capture-TD5M4WFE.js");
4804
4805
  const descField = betData.problem ?? betData.description ?? "";
4805
4806
  contradictionWarnings = await runContradictionCheck(
4806
4807
  betEntry.name ?? betId,
@@ -4839,6 +4840,7 @@ No constellation entries were committed.`
4839
4840
  await recordSessionActivity({ entryModified: entryId });
4840
4841
  }
4841
4842
  const lines = [];
4843
+ const hasIssues = result.failedIds.length > 0 || result.conflictIds.length > 0;
4842
4844
  if (result.proposalCreated) {
4843
4845
  const linkedCount = result.committedIds.filter((id) => id !== betId).length;
4844
4846
  lines.push(
@@ -4849,10 +4851,10 @@ No constellation entries were committed.`
4849
4851
  );
4850
4852
  } else {
4851
4853
  lines.push(
4852
- `# Published`,
4854
+ hasIssues ? `# Published with issues` : `# Published`,
4853
4855
  "",
4854
4856
  `**${result.committedIds.length} entries** committed to the Chain, **${result.totalRelations} connections** preserved.`,
4855
- `\`${betId}\` and its full constellation are now source of truth.`
4857
+ hasIssues ? `\`${betId}\` was partially committed. Review conflicts/failed entries below before considering the constellation complete.` : `\`${betId}\` and its full constellation are now source of truth.`
4856
4858
  );
4857
4859
  }
4858
4860
  if (contradictionWarnings.length > 0) {
@@ -8077,6 +8079,7 @@ function registerHealthTools(server) {
8077
8079
  if (orientEntries?.strategicContext) {
8078
8080
  const sc = orientEntries.strategicContext;
8079
8081
  if (sc.vision) lines.push(`Vision: ${sc.vision}`);
8082
+ if (sc.purpose) lines.push(`Purpose: ${sc.purpose}`);
8080
8083
  if (sc.productAreaCount != null && sc.productAreaCount > 0) {
8081
8084
  lines.push(`Product areas (${sc.productAreaCount}): ${(sc.productAreas ?? []).join(", ")}`);
8082
8085
  }
@@ -8172,6 +8175,7 @@ function registerHealthTools(server) {
8172
8175
  const sc = orientEntries.strategicContext;
8173
8176
  lines.push("## Strategic Context");
8174
8177
  if (sc.vision) lines.push(`**Vision:** ${sc.vision}`);
8178
+ if (sc.purpose) lines.push(`**Purpose:** ${sc.purpose}`);
8175
8179
  if (sc.productAreaCount != null && sc.productAreaCount > 0) {
8176
8180
  lines.push(`**Product areas (${sc.productAreaCount}):** ${(sc.productAreas ?? []).join(", ")}`);
8177
8181
  }
@@ -9122,6 +9126,8 @@ Description field: ${wf.kbOutputTemplate.descriptionField}
9122
9126
  const orient = await mcpQuery("chain.getOrientEntries", {});
9123
9127
  const sc = orient?.strategicContext;
9124
9128
  if (sc?.vision) strategicContext += `**Vision:** ${sc.vision}
9129
+ `;
9130
+ if (sc?.purpose) strategicContext += `**Purpose:** ${sc.purpose}
9125
9131
  `;
9126
9132
  if (sc?.currentBet) strategicContext += `**Current bet:** ${sc.currentBet}
9127
9133
  `;
@@ -9687,4 +9693,4 @@ export {
9687
9693
  SERVER_VERSION,
9688
9694
  createProductBrainServer
9689
9695
  };
9690
- //# sourceMappingURL=chunk-5IH3KEAZ.js.map
9696
+ //# sourceMappingURL=chunk-X7DON33G.js.map