drafted 1.7.0 → 1.7.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.
Files changed (2) hide show
  1. package/mcp/server.mjs +25 -3
  2. package/package.json +2 -2
package/mcp/server.mjs CHANGED
@@ -22,6 +22,15 @@ import { LAYERS } from '../src/shared/constants.mjs';
22
22
 
23
23
  const __dirname = dirname(fileURLToPath(import.meta.url));
24
24
 
25
+ // Read the npm package version once so the MCP server, get_org, and the
26
+ // `drafted://info` resource all report the same number — and it stays in
27
+ // sync with package.json automatically (no hardcoded duplicate).
28
+ const PACKAGE_VERSION = (() => {
29
+ try {
30
+ return JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8')).version || 'unknown';
31
+ } catch { return 'unknown'; }
32
+ })();
33
+
25
34
  // ── Per-instance session ──────────────────────────────────────────
26
35
  // State is per-request via AsyncLocalStorage. Standalone modes (stdio, --http)
27
36
  // share a process-wide default frame so the existing single-tenant behaviour
@@ -92,7 +101,7 @@ export function runWithRequestState(initial, fn) {
92
101
  export function createMcpServer() {
93
102
  const server = new McpServer({
94
103
  name: 'drafted',
95
- version: '2.4.0',
104
+ version: PACKAGE_VERSION,
96
105
  description: `Multi-tenant design workspace. Structure: Organization → Projects → Layers → Lanes → Frames.
97
106
 
98
107
  An org contains projects. Each project has a zoomable canvas with frames (HTML files) organized as /{layer}/{lane}/{filename}. Layers are predefined categories (wireframes, designs, brand-assets, etc.), lanes are groups within a layer, and frames are the individual design files.
@@ -1201,6 +1210,7 @@ tool('get_org', {
1201
1210
  activeOrg,
1202
1211
  orgs,
1203
1212
  members: members.map(m => ({ id: m.userId, name: m.username, email: m.email, role: m.role })),
1213
+ mcpVersion: PACKAGE_VERSION,
1204
1214
  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.",
1205
1215
  });
1206
1216
  } catch (error) { return err(error); }
@@ -1756,6 +1766,7 @@ tool('skill', 'Manage the Drafted skill library. Skills are reusable prompts/gui
1756
1766
  limit: z.number().optional().describe('[search] max results (default 25, max 100)'),
1757
1767
  skill: z.string().optional().describe('[load] skill ID (UUID) or slug'),
1758
1768
  skillId: z.string().optional().describe('[update|remove|attach|detach|favorite|unfavorite|read_file|update_file] skill ID'),
1769
+ projectId: z.string().optional().describe('[list] project to list skills for (defaults to active project; falls back to org-attached skills if no project)'),
1759
1770
  name: z.string().optional().describe('[add|update] skill name'),
1760
1771
  description: z.string().optional().describe('[add|update] one-line description'),
1761
1772
  content: z.string().optional().describe('[add|update] root SKILL.md content; [update_file] file content'),
@@ -1792,8 +1803,18 @@ tool('skill', 'Manage the Drafted skill library. Skills are reusable prompts/gui
1792
1803
  return ok(result);
1793
1804
  }
1794
1805
  case 'list': {
1795
- if (!getState().projectId) throw new Error('No active project. Call project(action="open") first.');
1796
- return ok(await api('GET', `/api/projects/${getState().projectId}/skills`));
1806
+ // Prefer the explicit projectId param; otherwise the active project;
1807
+ // otherwise fall back to org-attached skills so list works in
1808
+ // empty-org / wiki-only sessions where there's no project to bind to.
1809
+ const explicit = args.projectId;
1810
+ const active = getState().projectId;
1811
+ if (explicit || active) {
1812
+ const pid = explicit || active;
1813
+ return ok(await api('GET', `/api/projects/${pid}/skills`));
1814
+ }
1815
+ const orgId = await getCurrentOrgId();
1816
+ if (!orgId) throw new Error('No active org. Call get_org first or pass projectId.');
1817
+ return ok(await api('GET', `/api/orgs/${orgId}/skills`));
1797
1818
  }
1798
1819
  case 'add': {
1799
1820
  const { name, description, content, tags, triggerPatterns } = args;
@@ -2253,6 +2274,7 @@ server.resource('info', 'drafted://info', {
2253
2274
  uri: uri.href,
2254
2275
  mimeType: 'application/json',
2255
2276
  text: JSON.stringify({
2277
+ version: PACKAGE_VERSION,
2256
2278
  layers: LAYERS,
2257
2279
  pathFormat: '/{layer}/{lane}/{filename}',
2258
2280
  tools: ['write', 'read', 'edit', 'ls', 'rm', 'mv'],
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "drafted",
3
- "version": "1.7.0",
4
- "description": "Drafted CLI - Design preview server for Claude agents",
3
+ "version": "1.7.2",
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": [
7
7
  "cli/",