@systemdox/mcp-server 0.1.28 → 0.1.30

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
@@ -130,7 +130,7 @@ require an API key with `editor`+ role.
130
130
  The aggregator. It ranks checks, specs and docs against the task, then
131
131
  spends the token budget **fetching the bodies** of the highest-ranked specs and
132
132
  docs (`/v1/specs/{id}`, `/v1/docs/{id}/content`) — concurrently, clipped to a
133
- fair share of what's left. Every item carries the `spec_id` / `doc_id` needed to
133
+ fair share of what's left. Every item carries the `draft_id` / `doc_id` needed to
134
134
  fetch it in full, so nothing is a dead end: items whose body did not fit, or
135
135
  whose fetch failed, still appear as a title + ID. Tech stack and project rules
136
136
  are always included; the budget is spent on bodies, never on truncating the
package/dist/cli.js CHANGED
@@ -394,15 +394,15 @@ function registerGetSpecs(server2, apiClient2) {
394
394
  title: "Get Specs",
395
395
  description: "Retrieve SystemDox specifications (proposal, requirements with RFC 2119 keywords, Given/When/Then scenarios). Get a specific spec by ID, filter by status, or search by keyword.",
396
396
  inputSchema: {
397
- spec_id: z2.string().optional().describe("Specific spec ID to retrieve with full content"),
397
+ draft_id: z2.string().optional().describe("Specific spec ID to retrieve with full content"),
398
398
  status: z2.enum(["draft", "ready", "archived"]).optional().describe("Filter by status"),
399
399
  search: z2.string().optional().describe("Keyword search across spec names")
400
400
  }
401
401
  },
402
- async ({ spec_id, status, search }) => {
403
- if (spec_id) {
402
+ async ({ draft_id, status, search }) => {
403
+ if (draft_id) {
404
404
  const spec = await apiClient2.get(
405
- `/v1/specs/${spec_id}`
405
+ `/v1/specs/${draft_id}`
406
406
  );
407
407
  const sections = [`# ${spec.name}
408
408
 
@@ -451,7 +451,7 @@ ${spec.taskContent}`);
451
451
  };
452
452
  }
453
453
  const text = filtered.map(
454
- (s) => `- **${s.name}** (${s.specId}) \u2014 ${s.status}, ${s.requirementCount} requirements` + (s.repoFullName ? `, repo: ${s.repoFullName}` : "")
454
+ (s) => `- **${s.name}** (${s.draftId}) \u2014 ${s.status}, ${s.requirementCount} requirements` + (s.repoFullName ? `, repo: ${s.repoFullName}` : "")
455
455
  ).join("\n");
456
456
  return {
457
457
  content: [
@@ -1117,7 +1117,7 @@ ${g.fix}
1117
1117
  }
1118
1118
  function formatSpecHeadline(s) {
1119
1119
  return `### ${s.name}
1120
- \`spec_id: ${s.specId}\` \xB7 ${s.status} \xB7 ${s.requirementCount} requirements`;
1120
+ \`draft_id: ${s.draftId}\` \xB7 ${s.status} \xB7 ${s.requirementCount} requirements`;
1121
1121
  }
1122
1122
  function formatDocHeadline(d) {
1123
1123
  return `### ${d.title}
@@ -1149,9 +1149,9 @@ function formatRules(rules) {
1149
1149
 
1150
1150
  ${text.trim()}`;
1151
1151
  }
1152
- async function fetchSpecBody(api, specId) {
1152
+ async function fetchSpecBody(api, draftId) {
1153
1153
  const spec = await api.get(
1154
- `/v1/specs/${encodeURIComponent(specId)}`
1154
+ `/v1/specs/${encodeURIComponent(draftId)}`
1155
1155
  );
1156
1156
  const parts = [];
1157
1157
  if (spec.proposalContent) {
@@ -1245,16 +1245,16 @@ async function buildContext(api, { taskDescription, filePaths = [], maxTokens })
1245
1245
  updatedAt: g.updatedAt
1246
1246
  })),
1247
1247
  ...specs.filter((s) => s.status !== "archived").map((s) => {
1248
- refs.set(key("spec", s.specId), {
1248
+ refs.set(key("spec", s.draftId), {
1249
1249
  type: "spec",
1250
- id: s.specId,
1250
+ id: s.draftId,
1251
1251
  title: s.name,
1252
- listLine: `- **${s.name}** \u2014 \`spec_id: ${s.specId}\` (${s.status}, ${s.requirementCount} requirements)`,
1253
- fetchHint: `get_specs(spec_id="${s.specId}")`
1252
+ listLine: `- **${s.name}** \u2014 \`draft_id: ${s.draftId}\` (${s.status}, ${s.requirementCount} requirements)`,
1253
+ fetchHint: `get_specs(draft_id="${s.draftId}")`
1254
1254
  });
1255
1255
  return {
1256
1256
  type: "spec",
1257
- id: s.specId,
1257
+ id: s.draftId,
1258
1258
  title: s.name,
1259
1259
  content: formatSpecHeadline(s),
1260
1260
  updatedAt: s.updatedAt
@@ -1620,7 +1620,7 @@ function registerUpdateSpec(server2, apiClient2) {
1620
1620
  title: "Update Spec",
1621
1621
  description: "Update an existing SystemDox spec's proposal, tasks, or requirements. Only draft specs can be modified \u2014 published specs must be versioned first.",
1622
1622
  inputSchema: {
1623
- spec_id: z8.string().describe("ID of the spec to update"),
1623
+ draft_id: z8.string().describe("ID of the spec to update"),
1624
1624
  section: z8.enum(["proposal", "tasks", "requirements"]).describe("Which section to update"),
1625
1625
  content: z8.string().describe(
1626
1626
  "New markdown content for the section. For requirements, provide the full requirement content."
@@ -1633,8 +1633,8 @@ function registerUpdateSpec(server2, apiClient2) {
1633
1633
  readOnlyHint: false
1634
1634
  }
1635
1635
  },
1636
- async ({ spec_id, section, content, requirement_name }) => {
1637
- const spec = await apiClient2.get(`/v1/specs/${spec_id}`);
1636
+ async ({ draft_id, section, content, requirement_name }) => {
1637
+ const spec = await apiClient2.get(`/v1/specs/${draft_id}`);
1638
1638
  if (spec.status !== "draft") {
1639
1639
  return {
1640
1640
  content: [
@@ -1659,8 +1659,8 @@ function registerUpdateSpec(server2, apiClient2) {
1659
1659
  };
1660
1660
  body.requirements = [...existing, newReq];
1661
1661
  }
1662
- await apiClient2.put(`/v1/specs/${spec_id}`, body);
1663
- apiClient2.invalidateCache(`/v1/specs/${spec_id}`);
1662
+ await apiClient2.put(`/v1/specs/${draft_id}`, body);
1663
+ apiClient2.invalidateCache(`/v1/specs/${draft_id}`);
1664
1664
  apiClient2.invalidateCache("/v1/specs");
1665
1665
  return {
1666
1666
  content: [
@@ -1724,7 +1724,7 @@ ${decision}
1724
1724
  ## Consequences
1725
1725
 
1726
1726
  ${consequences}` + relatedSection;
1727
- await apiClient2.put(`/v1/specs/${created.specId}`, {
1727
+ await apiClient2.put(`/v1/specs/${created.draftId}`, {
1728
1728
  proposalContent: adrContent
1729
1729
  });
1730
1730
  apiClient2.invalidateCache("/v1/specs");
@@ -1732,7 +1732,7 @@ ${consequences}` + relatedSection;
1732
1732
  content: [
1733
1733
  {
1734
1734
  type: "text",
1735
- text: `Architecture decision recorded: **${adrTitle}** (spec id: ${created.specId})
1735
+ text: `Architecture decision recorded: **${adrTitle}** (spec id: ${created.draftId})
1736
1736
 
1737
1737
  Status: draft \u2014 review in SystemDox before publishing.`
1738
1738
  }
@@ -2000,7 +2000,7 @@ var init_server = __esm({
2000
2000
  init_create_project_rule();
2001
2001
  init_get_prompt_templates();
2002
2002
  init_create_prompt_template();
2003
- SERVER_VERSION = true ? "0.1.28" : "0.0.0-dev";
2003
+ SERVER_VERSION = true ? "0.1.30" : "0.0.0-dev";
2004
2004
  }
2005
2005
  });
2006
2006
 
package/dist/http.js CHANGED
@@ -117,6 +117,25 @@ var SystemDoxApiClient = class {
117
117
  }
118
118
  };
119
119
 
120
+ // src/lib/config.ts
121
+ var API_URL_DEFAULT = "https://api.puglieseweb.com/systemdox";
122
+ function requireHttpsApiUrl(apiUrl) {
123
+ let parsed;
124
+ try {
125
+ parsed = new URL(apiUrl);
126
+ } catch {
127
+ throw new Error(
128
+ `SYSTEMDOX_API_URL is not a valid URL: ${apiUrl}`
129
+ );
130
+ }
131
+ if (parsed.protocol !== "https:") {
132
+ throw new Error(
133
+ `SYSTEMDOX_API_URL must use https:// \u2014 refusing to send the API key over ${parsed.protocol}// in cleartext. Got: ${apiUrl}`
134
+ );
135
+ }
136
+ return apiUrl;
137
+ }
138
+
120
139
  // src/lib/metrics.ts
121
140
  var NAMESPACE = "SystemDox/Mcp";
122
141
  var METRIC_NAME = "McpToolCall";
@@ -347,15 +366,15 @@ function registerGetSpecs(server, apiClient) {
347
366
  title: "Get Specs",
348
367
  description: "Retrieve SystemDox specifications (proposal, requirements with RFC 2119 keywords, Given/When/Then scenarios). Get a specific spec by ID, filter by status, or search by keyword.",
349
368
  inputSchema: {
350
- spec_id: z2.string().optional().describe("Specific spec ID to retrieve with full content"),
369
+ draft_id: z2.string().optional().describe("Specific spec ID to retrieve with full content"),
351
370
  status: z2.enum(["draft", "ready", "archived"]).optional().describe("Filter by status"),
352
371
  search: z2.string().optional().describe("Keyword search across spec names")
353
372
  }
354
373
  },
355
- async ({ spec_id, status, search }) => {
356
- if (spec_id) {
374
+ async ({ draft_id, status, search }) => {
375
+ if (draft_id) {
357
376
  const spec = await apiClient.get(
358
- `/v1/specs/${spec_id}`
377
+ `/v1/specs/${draft_id}`
359
378
  );
360
379
  const sections = [`# ${spec.name}
361
380
 
@@ -404,7 +423,7 @@ ${spec.taskContent}`);
404
423
  };
405
424
  }
406
425
  const text = filtered.map(
407
- (s) => `- **${s.name}** (${s.specId}) \u2014 ${s.status}, ${s.requirementCount} requirements` + (s.repoFullName ? `, repo: ${s.repoFullName}` : "")
426
+ (s) => `- **${s.name}** (${s.draftId}) \u2014 ${s.status}, ${s.requirementCount} requirements` + (s.repoFullName ? `, repo: ${s.repoFullName}` : "")
408
427
  ).join("\n");
409
428
  return {
410
429
  content: [
@@ -1045,7 +1064,7 @@ ${g.fix}
1045
1064
  }
1046
1065
  function formatSpecHeadline(s) {
1047
1066
  return `### ${s.name}
1048
- \`spec_id: ${s.specId}\` \xB7 ${s.status} \xB7 ${s.requirementCount} requirements`;
1067
+ \`draft_id: ${s.draftId}\` \xB7 ${s.status} \xB7 ${s.requirementCount} requirements`;
1049
1068
  }
1050
1069
  function formatDocHeadline(d) {
1051
1070
  return `### ${d.title}
@@ -1077,9 +1096,9 @@ function formatRules(rules) {
1077
1096
 
1078
1097
  ${text.trim()}`;
1079
1098
  }
1080
- async function fetchSpecBody(api, specId) {
1099
+ async function fetchSpecBody(api, draftId) {
1081
1100
  const spec = await api.get(
1082
- `/v1/specs/${encodeURIComponent(specId)}`
1101
+ `/v1/specs/${encodeURIComponent(draftId)}`
1083
1102
  );
1084
1103
  const parts = [];
1085
1104
  if (spec.proposalContent) {
@@ -1195,16 +1214,16 @@ async function buildContext(api, { taskDescription, filePaths = [], maxTokens })
1195
1214
  updatedAt: g.updatedAt
1196
1215
  })),
1197
1216
  ...specs.filter((s) => s.status !== "archived").map((s) => {
1198
- refs.set(key("spec", s.specId), {
1217
+ refs.set(key("spec", s.draftId), {
1199
1218
  type: "spec",
1200
- id: s.specId,
1219
+ id: s.draftId,
1201
1220
  title: s.name,
1202
- listLine: `- **${s.name}** \u2014 \`spec_id: ${s.specId}\` (${s.status}, ${s.requirementCount} requirements)`,
1203
- fetchHint: `get_specs(spec_id="${s.specId}")`
1221
+ listLine: `- **${s.name}** \u2014 \`draft_id: ${s.draftId}\` (${s.status}, ${s.requirementCount} requirements)`,
1222
+ fetchHint: `get_specs(draft_id="${s.draftId}")`
1204
1223
  });
1205
1224
  return {
1206
1225
  type: "spec",
1207
- id: s.specId,
1226
+ id: s.draftId,
1208
1227
  title: s.name,
1209
1228
  content: formatSpecHeadline(s),
1210
1229
  updatedAt: s.updatedAt
@@ -1518,7 +1537,7 @@ function registerUpdateSpec(server, apiClient) {
1518
1537
  title: "Update Spec",
1519
1538
  description: "Update an existing SystemDox spec's proposal, tasks, or requirements. Only draft specs can be modified \u2014 published specs must be versioned first.",
1520
1539
  inputSchema: {
1521
- spec_id: z8.string().describe("ID of the spec to update"),
1540
+ draft_id: z8.string().describe("ID of the spec to update"),
1522
1541
  section: z8.enum(["proposal", "tasks", "requirements"]).describe("Which section to update"),
1523
1542
  content: z8.string().describe(
1524
1543
  "New markdown content for the section. For requirements, provide the full requirement content."
@@ -1531,8 +1550,8 @@ function registerUpdateSpec(server, apiClient) {
1531
1550
  readOnlyHint: false
1532
1551
  }
1533
1552
  },
1534
- async ({ spec_id, section, content, requirement_name }) => {
1535
- const spec = await apiClient.get(`/v1/specs/${spec_id}`);
1553
+ async ({ draft_id, section, content, requirement_name }) => {
1554
+ const spec = await apiClient.get(`/v1/specs/${draft_id}`);
1536
1555
  if (spec.status !== "draft") {
1537
1556
  return {
1538
1557
  content: [
@@ -1557,8 +1576,8 @@ function registerUpdateSpec(server, apiClient) {
1557
1576
  };
1558
1577
  body.requirements = [...existing, newReq];
1559
1578
  }
1560
- await apiClient.put(`/v1/specs/${spec_id}`, body);
1561
- apiClient.invalidateCache(`/v1/specs/${spec_id}`);
1579
+ await apiClient.put(`/v1/specs/${draft_id}`, body);
1580
+ apiClient.invalidateCache(`/v1/specs/${draft_id}`);
1562
1581
  apiClient.invalidateCache("/v1/specs");
1563
1582
  return {
1564
1583
  content: [
@@ -1617,7 +1636,7 @@ ${decision}
1617
1636
  ## Consequences
1618
1637
 
1619
1638
  ${consequences}` + relatedSection;
1620
- await apiClient.put(`/v1/specs/${created.specId}`, {
1639
+ await apiClient.put(`/v1/specs/${created.draftId}`, {
1621
1640
  proposalContent: adrContent
1622
1641
  });
1623
1642
  apiClient.invalidateCache("/v1/specs");
@@ -1625,7 +1644,7 @@ ${consequences}` + relatedSection;
1625
1644
  content: [
1626
1645
  {
1627
1646
  type: "text",
1628
- text: `Architecture decision recorded: **${adrTitle}** (spec id: ${created.specId})
1647
+ text: `Architecture decision recorded: **${adrTitle}** (spec id: ${created.draftId})
1629
1648
 
1630
1649
  Status: draft \u2014 review in SystemDox before publishing.`
1631
1650
  }
@@ -1825,7 +1844,7 @@ function registerCreatePromptTemplate(server, apiClient) {
1825
1844
  }
1826
1845
 
1827
1846
  // src/server.ts
1828
- var SERVER_VERSION = true ? "0.1.28" : "0.0.0-dev";
1847
+ var SERVER_VERSION = true ? "0.1.30" : "0.0.0-dev";
1829
1848
  function createServer(apiClient) {
1830
1849
  const server = new McpServer({
1831
1850
  name: "systemdox-mcp-server",
@@ -1896,9 +1915,16 @@ async function handler(event) {
1896
1915
  }
1897
1916
  const rawBody = event.isBase64Encoded ? Buffer.from(event.body ?? "", "base64").toString("utf8") : event.body ?? "";
1898
1917
  emitMcpToolCalls(keyTenant, rawBody);
1918
+ let apiUrl;
1919
+ try {
1920
+ apiUrl = requireHttpsApiUrl(process.env.SYSTEMDOX_API_URL ?? API_URL_DEFAULT);
1921
+ } catch (err) {
1922
+ console.error("Refusing to proxy MCP tool calls:", err);
1923
+ return jsonError(500, "Server misconfigured: API URL must use https://");
1924
+ }
1899
1925
  const apiClient = new SystemDoxApiClient({
1900
1926
  apiKey,
1901
- apiUrl: process.env.SYSTEMDOX_API_URL ?? "https://api.puglieseweb.com/systemdox",
1927
+ apiUrl,
1902
1928
  cacheTtlMs: 0,
1903
1929
  // per-request client; never cache across invocations
1904
1930
  defaultOrg: void 0
package/dist/index.js CHANGED
@@ -348,15 +348,15 @@ function registerGetSpecs(server2, apiClient2) {
348
348
  title: "Get Specs",
349
349
  description: "Retrieve SystemDox specifications (proposal, requirements with RFC 2119 keywords, Given/When/Then scenarios). Get a specific spec by ID, filter by status, or search by keyword.",
350
350
  inputSchema: {
351
- spec_id: z2.string().optional().describe("Specific spec ID to retrieve with full content"),
351
+ draft_id: z2.string().optional().describe("Specific spec ID to retrieve with full content"),
352
352
  status: z2.enum(["draft", "ready", "archived"]).optional().describe("Filter by status"),
353
353
  search: z2.string().optional().describe("Keyword search across spec names")
354
354
  }
355
355
  },
356
- async ({ spec_id, status, search }) => {
357
- if (spec_id) {
356
+ async ({ draft_id, status, search }) => {
357
+ if (draft_id) {
358
358
  const spec = await apiClient2.get(
359
- `/v1/specs/${spec_id}`
359
+ `/v1/specs/${draft_id}`
360
360
  );
361
361
  const sections = [`# ${spec.name}
362
362
 
@@ -405,7 +405,7 @@ ${spec.taskContent}`);
405
405
  };
406
406
  }
407
407
  const text = filtered.map(
408
- (s) => `- **${s.name}** (${s.specId}) \u2014 ${s.status}, ${s.requirementCount} requirements` + (s.repoFullName ? `, repo: ${s.repoFullName}` : "")
408
+ (s) => `- **${s.name}** (${s.draftId}) \u2014 ${s.status}, ${s.requirementCount} requirements` + (s.repoFullName ? `, repo: ${s.repoFullName}` : "")
409
409
  ).join("\n");
410
410
  return {
411
411
  content: [
@@ -1046,7 +1046,7 @@ ${g.fix}
1046
1046
  }
1047
1047
  function formatSpecHeadline(s) {
1048
1048
  return `### ${s.name}
1049
- \`spec_id: ${s.specId}\` \xB7 ${s.status} \xB7 ${s.requirementCount} requirements`;
1049
+ \`draft_id: ${s.draftId}\` \xB7 ${s.status} \xB7 ${s.requirementCount} requirements`;
1050
1050
  }
1051
1051
  function formatDocHeadline(d) {
1052
1052
  return `### ${d.title}
@@ -1078,9 +1078,9 @@ function formatRules(rules) {
1078
1078
 
1079
1079
  ${text.trim()}`;
1080
1080
  }
1081
- async function fetchSpecBody(api, specId) {
1081
+ async function fetchSpecBody(api, draftId) {
1082
1082
  const spec = await api.get(
1083
- `/v1/specs/${encodeURIComponent(specId)}`
1083
+ `/v1/specs/${encodeURIComponent(draftId)}`
1084
1084
  );
1085
1085
  const parts = [];
1086
1086
  if (spec.proposalContent) {
@@ -1196,16 +1196,16 @@ async function buildContext(api, { taskDescription, filePaths = [], maxTokens })
1196
1196
  updatedAt: g.updatedAt
1197
1197
  })),
1198
1198
  ...specs.filter((s) => s.status !== "archived").map((s) => {
1199
- refs.set(key("spec", s.specId), {
1199
+ refs.set(key("spec", s.draftId), {
1200
1200
  type: "spec",
1201
- id: s.specId,
1201
+ id: s.draftId,
1202
1202
  title: s.name,
1203
- listLine: `- **${s.name}** \u2014 \`spec_id: ${s.specId}\` (${s.status}, ${s.requirementCount} requirements)`,
1204
- fetchHint: `get_specs(spec_id="${s.specId}")`
1203
+ listLine: `- **${s.name}** \u2014 \`draft_id: ${s.draftId}\` (${s.status}, ${s.requirementCount} requirements)`,
1204
+ fetchHint: `get_specs(draft_id="${s.draftId}")`
1205
1205
  });
1206
1206
  return {
1207
1207
  type: "spec",
1208
- id: s.specId,
1208
+ id: s.draftId,
1209
1209
  title: s.name,
1210
1210
  content: formatSpecHeadline(s),
1211
1211
  updatedAt: s.updatedAt
@@ -1519,7 +1519,7 @@ function registerUpdateSpec(server2, apiClient2) {
1519
1519
  title: "Update Spec",
1520
1520
  description: "Update an existing SystemDox spec's proposal, tasks, or requirements. Only draft specs can be modified \u2014 published specs must be versioned first.",
1521
1521
  inputSchema: {
1522
- spec_id: z8.string().describe("ID of the spec to update"),
1522
+ draft_id: z8.string().describe("ID of the spec to update"),
1523
1523
  section: z8.enum(["proposal", "tasks", "requirements"]).describe("Which section to update"),
1524
1524
  content: z8.string().describe(
1525
1525
  "New markdown content for the section. For requirements, provide the full requirement content."
@@ -1532,8 +1532,8 @@ function registerUpdateSpec(server2, apiClient2) {
1532
1532
  readOnlyHint: false
1533
1533
  }
1534
1534
  },
1535
- async ({ spec_id, section, content, requirement_name }) => {
1536
- const spec = await apiClient2.get(`/v1/specs/${spec_id}`);
1535
+ async ({ draft_id, section, content, requirement_name }) => {
1536
+ const spec = await apiClient2.get(`/v1/specs/${draft_id}`);
1537
1537
  if (spec.status !== "draft") {
1538
1538
  return {
1539
1539
  content: [
@@ -1558,8 +1558,8 @@ function registerUpdateSpec(server2, apiClient2) {
1558
1558
  };
1559
1559
  body.requirements = [...existing, newReq];
1560
1560
  }
1561
- await apiClient2.put(`/v1/specs/${spec_id}`, body);
1562
- apiClient2.invalidateCache(`/v1/specs/${spec_id}`);
1561
+ await apiClient2.put(`/v1/specs/${draft_id}`, body);
1562
+ apiClient2.invalidateCache(`/v1/specs/${draft_id}`);
1563
1563
  apiClient2.invalidateCache("/v1/specs");
1564
1564
  return {
1565
1565
  content: [
@@ -1618,7 +1618,7 @@ ${decision}
1618
1618
  ## Consequences
1619
1619
 
1620
1620
  ${consequences}` + relatedSection;
1621
- await apiClient2.put(`/v1/specs/${created.specId}`, {
1621
+ await apiClient2.put(`/v1/specs/${created.draftId}`, {
1622
1622
  proposalContent: adrContent
1623
1623
  });
1624
1624
  apiClient2.invalidateCache("/v1/specs");
@@ -1626,7 +1626,7 @@ ${consequences}` + relatedSection;
1626
1626
  content: [
1627
1627
  {
1628
1628
  type: "text",
1629
- text: `Architecture decision recorded: **${adrTitle}** (spec id: ${created.specId})
1629
+ text: `Architecture decision recorded: **${adrTitle}** (spec id: ${created.draftId})
1630
1630
 
1631
1631
  Status: draft \u2014 review in SystemDox before publishing.`
1632
1632
  }
@@ -1826,7 +1826,7 @@ function registerCreatePromptTemplate(server2, apiClient2) {
1826
1826
  }
1827
1827
 
1828
1828
  // src/server.ts
1829
- var SERVER_VERSION = true ? "0.1.28" : "0.0.0-dev";
1829
+ var SERVER_VERSION = true ? "0.1.30" : "0.0.0-dev";
1830
1830
  function createServer(apiClient2) {
1831
1831
  const server2 = new McpServer({
1832
1832
  name: "systemdox-mcp-server",
@@ -17,7 +17,7 @@ export interface Guardrail {
17
17
  updatedAt: string;
18
18
  }
19
19
  export interface SpecSummary {
20
- specId: string;
20
+ draftId: string;
21
21
  name: string;
22
22
  status: string;
23
23
  requirementCount: number;
@@ -279,7 +279,7 @@ ${g.fix}
279
279
  }
280
280
  function formatSpecHeadline(s) {
281
281
  return `### ${s.name}
282
- \`spec_id: ${s.specId}\` \xB7 ${s.status} \xB7 ${s.requirementCount} requirements`;
282
+ \`draft_id: ${s.draftId}\` \xB7 ${s.status} \xB7 ${s.requirementCount} requirements`;
283
283
  }
284
284
  function formatDocHeadline(d) {
285
285
  return `### ${d.title}
@@ -311,9 +311,9 @@ function formatRules(rules) {
311
311
 
312
312
  ${text.trim()}`;
313
313
  }
314
- async function fetchSpecBody(api, specId) {
314
+ async function fetchSpecBody(api, draftId) {
315
315
  const spec = await api.get(
316
- `/v1/specs/${encodeURIComponent(specId)}`
316
+ `/v1/specs/${encodeURIComponent(draftId)}`
317
317
  );
318
318
  const parts = [];
319
319
  if (spec.proposalContent) {
@@ -429,16 +429,16 @@ async function buildContext(api, { taskDescription, filePaths = [], maxTokens })
429
429
  updatedAt: g.updatedAt
430
430
  })),
431
431
  ...specs.filter((s) => s.status !== "archived").map((s) => {
432
- refs.set(key("spec", s.specId), {
432
+ refs.set(key("spec", s.draftId), {
433
433
  type: "spec",
434
- id: s.specId,
434
+ id: s.draftId,
435
435
  title: s.name,
436
- listLine: `- **${s.name}** \u2014 \`spec_id: ${s.specId}\` (${s.status}, ${s.requirementCount} requirements)`,
437
- fetchHint: `get_specs(spec_id="${s.specId}")`
436
+ listLine: `- **${s.name}** \u2014 \`draft_id: ${s.draftId}\` (${s.status}, ${s.requirementCount} requirements)`,
437
+ fetchHint: `get_specs(draft_id="${s.draftId}")`
438
438
  });
439
439
  return {
440
440
  type: "spec",
441
- id: s.specId,
441
+ id: s.draftId,
442
442
  title: s.name,
443
443
  content: formatSpecHeadline(s),
444
444
  updatedAt: s.updatedAt
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@systemdox/mcp-server",
3
- "version": "0.1.28",
3
+ "version": "0.1.30",
4
4
  "mcpName": "io.github.puglieseweb/systemdox",
5
5
  "type": "module",
6
6
  "description": "Give AI coding agents your architecture context over MCP — checks, specs, ADRs, project rules, and docs from SystemDox, delivered at write time",