@de-otio/epimethian-mcp 6.6.0 → 6.6.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/dist/cli/index.js +78 -18
- package/dist/cli/index.js.map +3 -3
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -35481,7 +35481,7 @@ async function getPage(pageId, includeBody) {
|
|
|
35481
35481
|
async function _rawCreatePage(spaceId, title, body, parentId, clientLabel) {
|
|
35482
35482
|
const cfg = await getConfig();
|
|
35483
35483
|
const pageBody = normalizeBodyForSubmit(body);
|
|
35484
|
-
const epimethianTag = `Epimethian v${"6.6.
|
|
35484
|
+
const epimethianTag = `Epimethian v${"6.6.1"}`;
|
|
35485
35485
|
const versionMsg = cfg.attribution && clientLabel ? `Created by ${clientLabel} (via ${epimethianTag})` : `Created by ${epimethianTag}`;
|
|
35486
35486
|
const payload = {
|
|
35487
35487
|
title,
|
|
@@ -35502,7 +35502,7 @@ async function _rawCreatePage(spaceId, title, body, parentId, clientLabel) {
|
|
|
35502
35502
|
async function _rawUpdatePage(pageId, opts) {
|
|
35503
35503
|
const cfg = await getConfig();
|
|
35504
35504
|
const newVersion = opts.version + 1;
|
|
35505
|
-
const epimethianTag = `Epimethian v${"6.6.
|
|
35505
|
+
const epimethianTag = `Epimethian v${"6.6.1"}`;
|
|
35506
35506
|
const effectiveClient = cfg.attribution ? opts.clientLabel : void 0;
|
|
35507
35507
|
let versionMessage;
|
|
35508
35508
|
if (opts.versionMessage && effectiveClient)
|
|
@@ -49937,7 +49937,7 @@ __export(upgrade_exports, {
|
|
|
49937
49937
|
runUpgrade: () => runUpgrade
|
|
49938
49938
|
});
|
|
49939
49939
|
async function runUpgrade() {
|
|
49940
|
-
const currentVersion = "6.6.
|
|
49940
|
+
const currentVersion = "6.6.1";
|
|
49941
49941
|
console.log(`epimethian-mcp upgrade: current version v${currentVersion}`);
|
|
49942
49942
|
let pending = await getPendingUpdate();
|
|
49943
49943
|
if (!pending) {
|
|
@@ -60928,8 +60928,37 @@ function renderDeletionSummary(s) {
|
|
|
60928
60928
|
return `This update will remove ${list2}.`;
|
|
60929
60929
|
}
|
|
60930
60930
|
var bypassMisconfigWarningFired = false;
|
|
60931
|
-
|
|
60932
|
-
|
|
60931
|
+
var FAST_DECLINE_THRESHOLD_MS = 50;
|
|
60932
|
+
var FAST_DECLINE_THRESHOLD_OVERRIDE_ENV = "EPIMETHIAN_FAST_DECLINE_THRESHOLD_MS";
|
|
60933
|
+
var DISABLE_FAST_DECLINE_DETECTION_ENV = "EPIMETHIAN_DISABLE_FAST_DECLINE_DETECTION";
|
|
60934
|
+
var TREAT_ELICITATION_AS_UNSUPPORTED_ENV = "EPIMETHIAN_TREAT_ELICITATION_AS_UNSUPPORTED";
|
|
60935
|
+
var fakingElicitationFlags = /* @__PURE__ */ new WeakMap();
|
|
60936
|
+
function isClientFakingElicitation(server) {
|
|
60937
|
+
return fakingElicitationFlags.get(server) === true;
|
|
60938
|
+
}
|
|
60939
|
+
function _markClientAsFakingElicitation(server) {
|
|
60940
|
+
fakingElicitationFlags.set(server, true);
|
|
60941
|
+
}
|
|
60942
|
+
function readFastDeclineThresholdMs() {
|
|
60943
|
+
const raw = process.env[FAST_DECLINE_THRESHOLD_OVERRIDE_ENV];
|
|
60944
|
+
if (raw === void 0 || raw === "") return FAST_DECLINE_THRESHOLD_MS;
|
|
60945
|
+
const parsed = Number.parseInt(raw, 10);
|
|
60946
|
+
if (!Number.isFinite(parsed)) return FAST_DECLINE_THRESHOLD_MS;
|
|
60947
|
+
if (parsed < 10) return 10;
|
|
60948
|
+
if (parsed > 5e3) return 5e3;
|
|
60949
|
+
return parsed;
|
|
60950
|
+
}
|
|
60951
|
+
function effectiveSupportsElicitation(server) {
|
|
60952
|
+
if (process.env[TREAT_ELICITATION_AS_UNSUPPORTED_ENV] === "true") {
|
|
60953
|
+
return false;
|
|
60954
|
+
}
|
|
60955
|
+
if (isClientFakingElicitation(server)) {
|
|
60956
|
+
return false;
|
|
60957
|
+
}
|
|
60958
|
+
return clientSupportsElicitation(server);
|
|
60959
|
+
}
|
|
60960
|
+
async function evaluateUnsupportedBranch(server, context) {
|
|
60961
|
+
const supported = effectiveSupportsElicitation(server);
|
|
60933
60962
|
if (process.env.EPIMETHIAN_BYPASS_ELICITATION === "true") {
|
|
60934
60963
|
if (!supported && !bypassMisconfigWarningFired) {
|
|
60935
60964
|
bypassMisconfigWarningFired = true;
|
|
@@ -60940,13 +60969,13 @@ async function gateOperation(server, context) {
|
|
|
60940
60969
|
console.error(
|
|
60941
60970
|
`epimethian-mcp: [UNGATED] tool=${context.tool} \u2014 bypassing elicitation gate; proceeding because EPIMETHIAN_BYPASS_ELICITATION=true.`
|
|
60942
60971
|
);
|
|
60943
|
-
return;
|
|
60972
|
+
return "handled";
|
|
60944
60973
|
}
|
|
60945
60974
|
if (!supported && process.env.EPIMETHIAN_ALLOW_UNGATED_WRITES === "true") {
|
|
60946
60975
|
console.error(
|
|
60947
60976
|
`epimethian-mcp: [UNGATED] tool=${context.tool} \u2014 client does not support elicitation; proceeding because EPIMETHIAN_ALLOW_UNGATED_WRITES=true.`
|
|
60948
60977
|
);
|
|
60949
|
-
return;
|
|
60978
|
+
return "handled";
|
|
60950
60979
|
}
|
|
60951
60980
|
if (!supported && process.env.EPIMETHIAN_DISABLE_SOFT_CONFIRM === "true") {
|
|
60952
60981
|
throw new GatedOperationError(
|
|
@@ -60989,6 +61018,11 @@ async function gateOperation(server, context) {
|
|
|
60989
61018
|
`This tool requires interactive confirmation but your MCP client does not expose elicitation. Use \`update_page_section\` instead, or switch to a client that supports MCP elicitation (Claude Code \u2265 2.x, Claude Desktop \u2265 0.10).`
|
|
60990
61019
|
);
|
|
60991
61020
|
}
|
|
61021
|
+
return "fall_through";
|
|
61022
|
+
}
|
|
61023
|
+
async function gateOperation(server, context) {
|
|
61024
|
+
const initial = await evaluateUnsupportedBranch(server, context);
|
|
61025
|
+
if (initial === "handled") return;
|
|
60992
61026
|
const lines = [context.summary];
|
|
60993
61027
|
if (context.details) {
|
|
60994
61028
|
for (const [k, v] of Object.entries(context.details)) {
|
|
@@ -61007,6 +61041,7 @@ async function gateOperation(server, context) {
|
|
|
61007
61041
|
}
|
|
61008
61042
|
const message = lines.join("\n");
|
|
61009
61043
|
let result;
|
|
61044
|
+
const startedAt = performance.now();
|
|
61010
61045
|
try {
|
|
61011
61046
|
result = await server.server.elicitInput({
|
|
61012
61047
|
message,
|
|
@@ -61028,6 +61063,19 @@ async function gateOperation(server, context) {
|
|
|
61028
61063
|
`Elicitation for ${context.tool} failed (${err instanceof Error ? err.message : String(err)}) \u2014 refusing the operation.`
|
|
61029
61064
|
);
|
|
61030
61065
|
}
|
|
61066
|
+
const elapsedMs = performance.now() - startedAt;
|
|
61067
|
+
const fastDeclineDisabled = process.env[DISABLE_FAST_DECLINE_DETECTION_ENV] === "true";
|
|
61068
|
+
if (!fastDeclineDisabled && result.action === "decline" && elapsedMs < readFastDeclineThresholdMs()) {
|
|
61069
|
+
_markClientAsFakingElicitation(server);
|
|
61070
|
+
const retry = await evaluateUnsupportedBranch(server, context);
|
|
61071
|
+
if (retry === "fall_through") {
|
|
61072
|
+
throw new GatedOperationError(
|
|
61073
|
+
NO_USER_RESPONSE,
|
|
61074
|
+
`${context.tool} could not be confirmed: fast-decline retry unexpectedly fell through to row 6.`
|
|
61075
|
+
);
|
|
61076
|
+
}
|
|
61077
|
+
return;
|
|
61078
|
+
}
|
|
61031
61079
|
if (result.action === "accept" && result.content?.confirm === true) {
|
|
61032
61080
|
return;
|
|
61033
61081
|
}
|
|
@@ -61051,6 +61099,18 @@ async function gateOperation(server, context) {
|
|
|
61051
61099
|
|
|
61052
61100
|
// src/server/index.ts
|
|
61053
61101
|
init_confirmation_tokens();
|
|
61102
|
+
|
|
61103
|
+
// src/server/version-schema.ts
|
|
61104
|
+
init_zod();
|
|
61105
|
+
var versionField = external_exports.union([
|
|
61106
|
+
external_exports.preprocess(
|
|
61107
|
+
(v) => typeof v === "string" && /^\d+$/.test(v) ? Number(v) : v,
|
|
61108
|
+
external_exports.number().int().positive()
|
|
61109
|
+
),
|
|
61110
|
+
external_exports.literal("current")
|
|
61111
|
+
]);
|
|
61112
|
+
|
|
61113
|
+
// src/server/index.ts
|
|
61054
61114
|
init_update_orchestrator();
|
|
61055
61115
|
init_tokeniser();
|
|
61056
61116
|
|
|
@@ -61798,7 +61858,7 @@ ${truncated}${truncationNote(origLen)}`
|
|
|
61798
61858
|
inputSchema: {
|
|
61799
61859
|
page_id: external_exports.string().describe("The Confluence page ID"),
|
|
61800
61860
|
title: external_exports.string().describe("Page title (use the title from get_page if unchanged)"),
|
|
61801
|
-
version:
|
|
61861
|
+
version: versionField.describe(
|
|
61802
61862
|
`The page version number from your most recent get_page call. Pass the literal string "current" to skip the read and apply this update on top of whatever the latest version is right now. WARNING: "current" deliberately bypasses optimistic concurrency \u2014 it is NOT a conflict-resolution strategy. If a coworker (or another agent) writes between our read and submit, the API will still 409 and we propagate the conflict. Use a numeric version when you want the "don't overwrite my coworker's changes" guard. Use "current" only as a shortcut to skip the get_page round-trip when concurrent writes are not a concern (e.g. immediately after create_page).`
|
|
61803
61863
|
),
|
|
61804
61864
|
body: external_exports.string().optional().describe("New body content \u2014 GFM markdown or Confluence storage format (XHTML). Markdown is auto-detected and converted via the token-aware write path. Do not mix the two: inlining <ac:.../> macros inside a markdown body is rejected. For a TOC use YAML frontmatter (toc: { maxLevel, minLevel }); for other macros use directive syntax (:info[...], :mention[...]{...})."),
|
|
@@ -62047,7 +62107,7 @@ ${truncated}${truncationNote(origLen)}`
|
|
|
62047
62107
|
).min(1).optional().describe(
|
|
62048
62108
|
"Alternative to `body`: apply literal string substitutions inside the section's storage XML instead of replacing the whole section. Each entry's `find` is searched for and replaced with `replace`. Pairs are applied in input order; each subsequent `find` searches the partially-substituted body, so chained substitutions work as expected. If a `find` string is not found, the call fails with FIND_REPLACE_MATCH_FAILED \u2014 no silent no-op. Substitutions are ONLY applied to text outside macro boundaries (attribute values and CDATA bodies are protected). Exactly one of `body` or `find_replace` must be provided."
|
|
62049
62109
|
),
|
|
62050
|
-
version:
|
|
62110
|
+
version: versionField.describe(
|
|
62051
62111
|
`The page version number from your most recent get_page call. Pass the literal string "current" to skip the read and apply this update on top of whatever the latest version is right now. WARNING: "current" deliberately bypasses optimistic concurrency \u2014 it is NOT a conflict-resolution strategy. If a coworker (or another agent) writes between our read and submit, the API will still 409. Use a numeric version when you want the "don't overwrite my coworker's changes" guard.`
|
|
62052
62112
|
),
|
|
62053
62113
|
version_message: external_exports.string().optional().describe("Optional version comment"),
|
|
@@ -62223,7 +62283,7 @@ ${truncated}${truncationNote(origLen)}`
|
|
|
62223
62283
|
),
|
|
62224
62284
|
inputSchema: {
|
|
62225
62285
|
page_id: external_exports.string().describe("The Confluence page ID"),
|
|
62226
|
-
version:
|
|
62286
|
+
version: versionField.describe(
|
|
62227
62287
|
'The page version number from your most recent get_page call. Pass the literal string "current" to skip the read and apply this update on top of whatever the latest version is right now. WARNING: "current" deliberately bypasses optimistic concurrency.'
|
|
62228
62288
|
),
|
|
62229
62289
|
version_message: external_exports.string().optional().describe("Optional version comment for the single resulting revision"),
|
|
@@ -62381,7 +62441,7 @@ ${truncated}${truncationNote(origLen)}`
|
|
|
62381
62441
|
),
|
|
62382
62442
|
inputSchema: {
|
|
62383
62443
|
page_id: external_exports.string().describe("The Confluence page ID"),
|
|
62384
|
-
version:
|
|
62444
|
+
version: versionField.describe(
|
|
62385
62445
|
'Page version from your most recent get_page call. Pass the literal string "current" to skip the read and apply on top of whatever the latest version is right now. WARNING: "current" bypasses optimistic concurrency \u2014 it does not protect against concurrent writes; the API can still 409 between our read and submit.'
|
|
62386
62446
|
),
|
|
62387
62447
|
content: external_exports.string().describe("Content to insert before the existing body. GFM markdown or storage format (auto-detected)."),
|
|
@@ -62431,7 +62491,7 @@ ${truncated}${truncationNote(origLen)}`
|
|
|
62431
62491
|
),
|
|
62432
62492
|
inputSchema: {
|
|
62433
62493
|
page_id: external_exports.string().describe("The Confluence page ID"),
|
|
62434
|
-
version:
|
|
62494
|
+
version: versionField.describe(
|
|
62435
62495
|
'Page version from your most recent get_page call. Pass the literal string "current" to skip the read and apply on top of whatever the latest version is right now. WARNING: "current" bypasses optimistic concurrency \u2014 it does not protect against concurrent writes; the API can still 409 between our read and submit.'
|
|
62436
62496
|
),
|
|
62437
62497
|
content: external_exports.string().describe("Content to insert after the existing body. GFM markdown or storage format (auto-detected)."),
|
|
@@ -63620,7 +63680,7 @@ ${titleFenced}${echo2}`
|
|
|
63620
63680
|
inputSchema: {}
|
|
63621
63681
|
},
|
|
63622
63682
|
async () => {
|
|
63623
|
-
let text2 = `epimethian-mcp v${"6.6.
|
|
63683
|
+
let text2 = `epimethian-mcp v${"6.6.1"}`;
|
|
63624
63684
|
try {
|
|
63625
63685
|
const pending = await getPendingUpdate();
|
|
63626
63686
|
if (pending) {
|
|
@@ -63651,7 +63711,7 @@ ${label} update available: v${pending.current} \u2192 v${pending.latest}. Run \`
|
|
|
63651
63711
|
const pending = await getPendingUpdate();
|
|
63652
63712
|
if (!pending) {
|
|
63653
63713
|
return toolResult(
|
|
63654
|
-
`epimethian-mcp v${"6.6.
|
|
63714
|
+
`epimethian-mcp v${"6.6.1"} is already up to date.`
|
|
63655
63715
|
);
|
|
63656
63716
|
}
|
|
63657
63717
|
const output = await performUpgrade(pending.latest);
|
|
@@ -63673,7 +63733,7 @@ async function startRecoveryServer(profile) {
|
|
|
63673
63733
|
const server = new McpServer(
|
|
63674
63734
|
{
|
|
63675
63735
|
name: `confluence-${profile}-setup-needed`,
|
|
63676
|
-
version: "6.6.
|
|
63736
|
+
version: "6.6.1"
|
|
63677
63737
|
},
|
|
63678
63738
|
{
|
|
63679
63739
|
instructions: `The Confluence profile "${profile}" referenced by CONFLUENCE_PROFILE has no keychain entry, so no Confluence tools are available. Call the setup_profile tool for instructions to create it.`
|
|
@@ -63724,21 +63784,21 @@ async function main() {
|
|
|
63724
63784
|
const serverName = config3.profile ? `confluence-${config3.profile}` : "confluence";
|
|
63725
63785
|
const server = new McpServer({
|
|
63726
63786
|
name: serverName,
|
|
63727
|
-
version: "6.6.
|
|
63787
|
+
version: "6.6.1"
|
|
63728
63788
|
});
|
|
63729
63789
|
await registerTools(server, config3);
|
|
63730
63790
|
const transport = new StdioServerTransport();
|
|
63731
63791
|
await server.connect(transport);
|
|
63732
63792
|
try {
|
|
63733
63793
|
const pending = await getPendingUpdate();
|
|
63734
|
-
if (pending && pending.current === "6.6.
|
|
63794
|
+
if (pending && pending.current === "6.6.1") {
|
|
63735
63795
|
console.error(
|
|
63736
63796
|
`epimethian-mcp: update available: v${pending.current} \u2192 v${pending.latest} (${pending.type}). Run \`epimethian-mcp upgrade\` to install.`
|
|
63737
63797
|
);
|
|
63738
63798
|
}
|
|
63739
63799
|
} catch {
|
|
63740
63800
|
}
|
|
63741
|
-
checkForUpdates("6.6.
|
|
63801
|
+
checkForUpdates("6.6.1").catch(() => {
|
|
63742
63802
|
});
|
|
63743
63803
|
}
|
|
63744
63804
|
|