@de-otio/epimethian-mcp 5.1.0 → 5.1.1

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
@@ -134,10 +134,26 @@ Confluence pages are verbose — storage format HTML with macro markup can easil
134
134
  | `set_page_status` | Set the content status badge on a page |
135
135
  | `remove_page_status` | Remove the content status badge from a page |
136
136
  | `get_page_versions` | List version history for a page |
137
- | `get_page_version` | Get page content at a specific historical version |
137
+ | `get_page_version` | Get page content at a specific historical version (read-only markdown) |
138
138
  | `diff_page_versions` | Compare two versions of a page |
139
+ | `prepend_to_page` | Insert content at the beginning of a page (additive, safe) |
140
+ | `append_to_page` | Insert content at the end of a page (additive, safe) |
141
+ | `revert_page` | Revert a page to a previous version (lossless) |
142
+ | `lookup_user` | Search for Atlassian users by name or email |
143
+ | `resolve_page_link` | Resolve a page title + space key to a stable page ID and URL |
139
144
  | `get_version` | Return the server version |
140
145
 
146
+ ## Content Safety
147
+
148
+ Write operations are protected by layered safety guards to prevent accidental content loss:
149
+
150
+ - **Shrinkage guard** — `update_page` rejects writes that reduce the body by more than 50%. Pass `confirm_shrinkage: true` to override.
151
+ - **Structural integrity** — rejects writes that drop more than 50% of headings. Pass `confirm_structure_loss: true` to override.
152
+ - **Empty-body rejection** — hard guard, no opt-out. Rejects writes that produce near-empty pages.
153
+ - **Additive tools** — `prepend_to_page` and `append_to_page` avoid full-body replacement entirely.
154
+ - **Lossless revert** — `revert_page` uses raw storage format, avoiding lossy markdown conversion.
155
+ - **Mutation log** — opt-in via `EPIMETHIAN_MUTATION_LOG=true`. Writes JSONL records to `~/.epimethian/logs/` for every write operation.
156
+
141
157
  ## Credential Security
142
158
 
143
159
  - Credentials are stored per-profile in the OS keychain (macOS Keychain / Linux libsecret)
package/dist/cli/index.js CHANGED
@@ -49274,7 +49274,7 @@ async function createPage(spaceId, title, body, parentId) {
49274
49274
  representation: "storage",
49275
49275
  value: pageBody
49276
49276
  },
49277
- version: { message: `Created by Epimethian v${"5.1.0"}` }
49277
+ version: { message: `Created by Epimethian v${"5.1.1"}` }
49278
49278
  };
49279
49279
  if (parentId) payload.parentId = parentId;
49280
49280
  const raw = await v2Post("/pages", payload);
@@ -49289,7 +49289,7 @@ async function createPage(spaceId, title, body, parentId) {
49289
49289
  async function updatePage(pageId, opts) {
49290
49290
  const cfg = await getConfig();
49291
49291
  const newVersion = opts.version + 1;
49292
- const versionMessage = opts.versionMessage ? `${opts.versionMessage} (via Epimethian v${"5.1.0"})` : `Updated by Epimethian v${"5.1.0"}`;
49292
+ const versionMessage = opts.versionMessage ? `${opts.versionMessage} (via Epimethian v${"5.1.1"})` : `Updated by Epimethian v${"5.1.1"}`;
49293
49293
  const payload = {
49294
49294
  id: pageId,
49295
49295
  status: "current",
@@ -49500,7 +49500,7 @@ var ATTRIBUTION_LABEL = "epimethian-managed";
49500
49500
  var ATTRIBUTION_START = "<!-- epimethian-attribution-start -->";
49501
49501
  var ATTRIBUTION_END = "<!-- epimethian-attribution-end -->";
49502
49502
  function buildAttributionFooter(action) {
49503
- return ATTRIBUTION_START + `<p style="font-size:9px;color:#999;margin-top:2em;"><em>This page was ${action} with <a href="${GITHUB_URL}">Epimethian</a> v${"5.1.0"}.</em></p>` + ATTRIBUTION_END;
49503
+ return ATTRIBUTION_START + `<p style="font-size:9px;color:#999;margin-top:2em;"><em>This page was ${action} with <a href="${GITHUB_URL}">Epimethian</a> v${"5.1.1"}.</em></p>` + ATTRIBUTION_END;
49504
49504
  }
49505
49505
  function stripAttributionFooter(body) {
49506
49506
  return body.replace(
@@ -49510,7 +49510,7 @@ function stripAttributionFooter(body) {
49510
49510
  // Also strip bare (unmarked) attribution paragraphs — these appear
49511
49511
  // when an agent copies page content from get_page and passes it
49512
49512
  // back to update_page without removing the footer.
49513
- /<p[^>]*>[\s\S]*?<a\s[^>]*href="https:\/\/github\.com\/de-otio\/epimethian-mcp"[^>]*>Epimethian<\/a>[\s\S]*?<\/p>/gi,
49513
+ /<p[^>]*>[\s\S]*?<a\s[^>]*href="https:\/\/github\.com\/de-otio\/epimethian-mcp"[^>]*>(?:<em>)?Epimethian(?:<\/em>)?<\/a>[\s\S]*?<\/p>/gi,
49514
49514
  ""
49515
49515
  ).trimEnd();
49516
49516
  }
@@ -58323,7 +58323,7 @@ ${lines.join("\n")}${echo2}`
58323
58323
  description: "Return the epimethian-mcp server version.",
58324
58324
  inputSchema: {}
58325
58325
  },
58326
- async () => toolResult(`epimethian-mcp v${"5.1.0"}`)
58326
+ async () => toolResult(`epimethian-mcp v${"5.1.1"}`)
58327
58327
  );
58328
58328
  }
58329
58329
  async function main() {
@@ -58336,7 +58336,7 @@ async function main() {
58336
58336
  const serverName = config3.profile ? `confluence-${config3.profile}` : "confluence";
58337
58337
  const server = new McpServer({
58338
58338
  name: serverName,
58339
- version: "5.1.0"
58339
+ version: "5.1.1"
58340
58340
  });
58341
58341
  registerTools(server, config3);
58342
58342
  const transport = new StdioServerTransport();