drafted 1.7.21 → 1.7.22

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.
Files changed (2) hide show
  1. package/mcp/server.mjs +66 -1
  2. package/package.json +1 -1
package/mcp/server.mjs CHANGED
@@ -1528,6 +1528,68 @@ async function getGoogleDriveAvailability() {
1528
1528
  }
1529
1529
  }
1530
1530
 
1531
+ function normalizeMcpUpdatePolicy(policy) {
1532
+ const severity = policy?.policy?.severity || 'unknown';
1533
+ const updateAvailable = !!policy?.policy?.updateAvailable;
1534
+ const required = !!policy?.policy?.required;
1535
+ return {
1536
+ status: required ? 'required' : updateAvailable ? 'stale' : severity === 'unknown' ? 'unknown' : 'current',
1537
+ currentVersion: policy?.versions?.client || PACKAGE_VERSION,
1538
+ latestVersion: policy?.versions?.latest || null,
1539
+ recommendedVersion: policy?.versions?.recommended || null,
1540
+ minimumRequiredVersion: policy?.versions?.minimumRequired || null,
1541
+ severity,
1542
+ updateAvailable,
1543
+ stale: updateAvailable,
1544
+ required,
1545
+ reason: policy?.policy?.reason || null,
1546
+ enabled: policy?.policy?.enabled !== false,
1547
+ mode: policy?.package?.mcpMode || mcpMode(),
1548
+ distribution: policy?.package?.distribution || (mcpMode() === 'stdio' ? 'npm-stdio' : 'hosted-http'),
1549
+ update: {
1550
+ command: policy?.update?.command || null,
1551
+ helper: policy?.update?.helper || null,
1552
+ packageManager: policy?.update?.packageManager || 'npm',
1553
+ },
1554
+ restart: {
1555
+ required: !!policy?.restart?.required,
1556
+ guidance: policy?.restart?.guidance || null,
1557
+ },
1558
+ checkedAt: policy?.serverTimestamp || null,
1559
+ };
1560
+ }
1561
+
1562
+ async function getMcpUpdateMetadata() {
1563
+ const mode = mcpMode();
1564
+ try {
1565
+ const query = new URLSearchParams({
1566
+ cliVersion: PACKAGE_VERSION,
1567
+ mcpMode: mode,
1568
+ });
1569
+ const policy = await api('GET', `/api/installations/latest?${query.toString()}`);
1570
+ return normalizeMcpUpdatePolicy(policy);
1571
+ } catch (error) {
1572
+ return {
1573
+ status: 'unknown',
1574
+ currentVersion: PACKAGE_VERSION,
1575
+ latestVersion: null,
1576
+ recommendedVersion: null,
1577
+ minimumRequiredVersion: null,
1578
+ severity: 'unknown',
1579
+ updateAvailable: false,
1580
+ stale: false,
1581
+ required: false,
1582
+ reason: 'latest_check_failed',
1583
+ enabled: false,
1584
+ mode,
1585
+ distribution: mode === 'stdio' ? 'npm-stdio' : 'hosted-http',
1586
+ update: { command: null, helper: null, packageManager: 'npm' },
1587
+ restart: { required: false, guidance: 'Drafted MCP update status is unavailable; get_org still succeeded.' },
1588
+ checkedAt: null,
1589
+ };
1590
+ }
1591
+ }
1592
+
1531
1593
 
1532
1594
  tool('get_org', {
1533
1595
  action: z.enum(['get', 'switch']).optional().describe('Default: "get" returns active org and member info. Use "switch" with orgId to change the active org without opening a project.'),
@@ -1550,7 +1612,8 @@ tool('get_org', {
1550
1612
  const orgs = (await api('GET', '/api/orgs')).orgs || [];
1551
1613
  const activeOrg = (orgs || []).map(o => ({ id: o.orgId || o.id, name: o.orgName || o.name })).find(o => o.id === me?.orgId) || null;
1552
1614
  const googleDrive = await getGoogleDriveAvailability();
1553
- return ok({ switched: true, activeOrg, googleDrive, note: 'Active org switched. Wiki and skill calls now target this org. Active project cleared — open a project (or stay org-scoped for wiki/skill). If googleDrive.connected is true, prefer Google Workspace frames for docs, sheets, and slides.' });
1615
+ const mcpUpdate = await getMcpUpdateMetadata();
1616
+ return ok({ switched: true, activeOrg, googleDrive, mcpVersion: PACKAGE_VERSION, mcpUpdate, note: 'Active org switched. Wiki and skill calls now target this org. Active project cleared — open a project (or stay org-scoped for wiki/skill). If googleDrive.connected is true, prefer Google Workspace frames for docs, sheets, and slides.' });
1554
1617
  }
1555
1618
 
1556
1619
  // Source of truth = THIS MCP session's bound org (what mutations will actually
@@ -1564,6 +1627,7 @@ tool('get_org', {
1564
1627
  const activeOrg = sessionOrgId ? (orgs.find(o => o.id === sessionOrgId) || null) : null;
1565
1628
 
1566
1629
  const googleDrive = await getGoogleDriveAvailability();
1630
+ const mcpUpdate = await getMcpUpdateMetadata();
1567
1631
 
1568
1632
  let members = [];
1569
1633
  if (sessionOrgId) {
@@ -1578,6 +1642,7 @@ tool('get_org', {
1578
1642
  members: members.map(m => ({ id: m.userId, name: m.username, email: m.email, role: m.role })),
1579
1643
  googleDrive,
1580
1644
  mcpVersion: PACKAGE_VERSION,
1645
+ mcpUpdate,
1581
1646
  note: "activeOrg is the org bound to THIS MCP session — what mutations will actually target. To switch orgs without creating a project, call get_org(action=\"switch\", orgId=\"...\"). Browser tabs and other MCP sessions for the same user can be on different orgs. If googleDrive.connected is true, strongly prefer Google Workspace frames for docs, sheets, and slides.",
1582
1647
  });
1583
1648
  } catch (error) { return err(error); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drafted",
3
- "version": "1.7.21",
3
+ "version": "1.7.22",
4
4
  "description": "Drafted — visual thinking surface for humans and AI agents. Renders HTML, markdown, images, and code as frames on a zoomable canvas, with MCP tools for AI agents and real-time sync for humans.",
5
5
  "type": "module",
6
6
  "files": [