comfyui-mcp 0.48.28 → 0.48.29
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/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/orchestrator/panel-tools.js +144 -10
- package/dist/orchestrator/panel-tools.js.map +1 -1
- package/dist/services/graph-query.js +172 -13
- package/dist/services/graph-query.js.map +1 -1
- package/dist/services/panel-settings.js +11 -2
- package/dist/services/panel-settings.js.map +1 -1
- package/dist/services/ui-bridge.js +78 -7
- package/dist/services/ui-bridge.js.map +1 -1
- package/dist/tools/compact.js +30 -4
- package/dist/tools/compact.js.map +1 -1
- package/dist/tools/index.js +59 -0
- package/dist/tools/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { randomBytes } from "node:crypto";
|
|
|
3
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
5
|
import { ListPromptsRequestSchema, ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
-
import {
|
|
6
|
+
import { collectToolCatalog, registerFullTools } from "./tools/index.js";
|
|
7
7
|
import { registerCompactTools } from "./tools/compact.js";
|
|
8
8
|
import { logger } from "./utils/logger.js";
|
|
9
9
|
import { JobWatcher } from "./services/job-watcher.js";
|
|
@@ -102,7 +102,11 @@ async function createConfiguredServer(toolMode = "full") {
|
|
|
102
102
|
logger.info(`Compact tool mode: ${catalog.tools.size} tools available via list_tools/describe_tool/call_tool`);
|
|
103
103
|
}
|
|
104
104
|
else {
|
|
105
|
-
|
|
105
|
+
// Full direct surface PLUS the compact facade (list_tools/describe_tool/
|
|
106
|
+
// call_tool) as a stable reconnect escape hatch — see registerFullTools and
|
|
107
|
+
// issue #616. One atomic registration pass, completed before the transport
|
|
108
|
+
// connects below. Opt out of the facade with COMFYUI_MCP_NO_FACADE=1.
|
|
109
|
+
await registerFullTools(server);
|
|
106
110
|
}
|
|
107
111
|
server.server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
|
108
112
|
resources: [],
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,kCAAkC,GACnC,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,7 +30,7 @@ import { fileURLToPath } from "node:url";
|
|
|
30
30
|
import { comfyuiFetch } from "../comfyui/fetch.js";
|
|
31
31
|
import { createSdkMcpServer, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
32
32
|
import { parse as parseYaml } from "yaml";
|
|
33
|
-
import { dispatchOutcomeOf, isPanelCmdUnsupportedError } from "../services/ui-bridge.js";
|
|
33
|
+
import { dispatchOutcomeOf, isPanelCmdUnsupportedError, isReplyTimeoutTagged, } from "../services/ui-bridge.js";
|
|
34
34
|
import { withWorkflowTarget, } from "../services/workflow-target-store.js";
|
|
35
35
|
import { addUserMcpServer, readUserMcpServers, removeUserMcpServer, setUserMcpServerSecret, } from "../services/user-mcp-config.js";
|
|
36
36
|
import { setComfyuiSecret, setAgentSecret, isAllowedAgentSecretKey } from "../services/panel-secrets.js";
|
|
@@ -43,12 +43,65 @@ import { restartComfyUI } from "../services/process-control.js";
|
|
|
43
43
|
import { isRemoteMode, isCloudMode, getBootLocalComfyUIBaseUrl, getComfyUIBaseUrl, } from "../config.js";
|
|
44
44
|
import { sliceWorkflow } from "../services/workflow-slicer.js";
|
|
45
45
|
import { validateA2UISpecServer } from "../services/a2ui-spec.js";
|
|
46
|
-
/** Treat these as an affirmative answer to
|
|
46
|
+
/** Treat these as an affirmative answer to a yes/no confirm card (destructive-op
|
|
47
|
+
* gate). Deliberately BROAD/lenient — a false "no" only SKIPS a destructive op, so
|
|
48
|
+
* erring toward "not yes" is safe. NEVER use this for the adult-consent gate: a
|
|
49
|
+
* false positive there would enable adult content without genuine consent. Use
|
|
50
|
+
* classifyConsentReply() for that. */
|
|
47
51
|
function isAffirmative(reply) {
|
|
48
52
|
if (typeof reply !== "string")
|
|
49
53
|
return false;
|
|
50
54
|
return /^(yes|allow|allowed|true|on|ok(ay)?|sure|agree|confirm|enable|i'?m? ?18|18\+?|adult)/i.test(reply.trim());
|
|
51
55
|
}
|
|
56
|
+
// The exact option labels the adult-consent card presents. Single source of truth
|
|
57
|
+
// shared by the card and its STRICT reply classifier so the gate matches on option
|
|
58
|
+
// IDENTITY, never on a loose heuristic.
|
|
59
|
+
const CONSENT_YES_LABEL = "Yes — I'm 18+ and it's legal in my region";
|
|
60
|
+
const CONSENT_NO_LABEL = "No — keep it SFW";
|
|
61
|
+
// STRICT, whole-string affirmatives/declines accepted from the card's free-text
|
|
62
|
+
// ("Other") box in addition to the exact option labels. Anchored ^…$ so ONLY an
|
|
63
|
+
// unambiguous token counts — unlike the broad isAffirmative() PREFIX match, a
|
|
64
|
+
// free-text reply like "adult content is illegal here", "On second thought, no",
|
|
65
|
+
// or "18 is the age but I decline" can NEVER be read as consent. Consent semantics
|
|
66
|
+
// (18+ AND legal) really live in the affirmative BUTTON; these bare tokens are the
|
|
67
|
+
// pragmatic fallback for a user who types instead of clicking.
|
|
68
|
+
const CONSENT_STRICT_YES_RE = /^(yes|y|yep|yeah|i agree|i consent|agreed?|confirm(ed)?|enable)$/i;
|
|
69
|
+
const CONSENT_STRICT_NO_RE = /^(no|n|nope|decline|declined|cancel|keep (it )?sfw|sfw)$/i;
|
|
70
|
+
/**
|
|
71
|
+
* STRICT classification of an adult-consent card reply — the ONLY gate that may
|
|
72
|
+
* turn adult mode ON. Returns:
|
|
73
|
+
* "grant" → the EXACT affirmative option, or a strict whole-string yes token
|
|
74
|
+
* → turn consent ON.
|
|
75
|
+
* "decline" → the EXACT decline option, or a strict whole-string no token
|
|
76
|
+
* → turn consent OFF.
|
|
77
|
+
* "unclear" → anything else (free text, ambiguous, non-string) → change NOTHING
|
|
78
|
+
* (never grants; never revokes a prior genuine grant).
|
|
79
|
+
* Never routes through isAffirmative() — a loose prefix match must not gate adult
|
|
80
|
+
* content.
|
|
81
|
+
*/
|
|
82
|
+
function classifyConsentReply(reply) {
|
|
83
|
+
if (typeof reply !== "string")
|
|
84
|
+
return "unclear";
|
|
85
|
+
// Exact OPTION IDENTITY: a button click echoes the card's label verbatim, so match
|
|
86
|
+
// it BYTE-FOR-BYTE — no .trim(). Trimming here would strip zero-width/BOM/line-
|
|
87
|
+
// separator characters (U+2028/U+2029/U+FEFF, \n) and let a near-label like
|
|
88
|
+
// " Yes — I'm 18+…" pass as the exact affirmative, defeating the exact-identity
|
|
89
|
+
// invariant this classifier exists to hold.
|
|
90
|
+
if (reply === CONSENT_YES_LABEL)
|
|
91
|
+
return "grant";
|
|
92
|
+
if (reply === CONSENT_NO_LABEL)
|
|
93
|
+
return "decline";
|
|
94
|
+
// Free-text ("Other" box) fallback: a small set of unambiguous whole-string tokens.
|
|
95
|
+
// This path is DELIBERATELY loose — a user who types " yes " is consenting — so a
|
|
96
|
+
// minimal .trim() of surrounding whitespace is applied ONLY here, never to the
|
|
97
|
+
// exact-label comparison above.
|
|
98
|
+
const t = reply.trim();
|
|
99
|
+
if (CONSENT_STRICT_YES_RE.test(t))
|
|
100
|
+
return "grant";
|
|
101
|
+
if (CONSENT_STRICT_NO_RE.test(t))
|
|
102
|
+
return "decline";
|
|
103
|
+
return "unclear";
|
|
104
|
+
}
|
|
52
105
|
function ok(value) {
|
|
53
106
|
return {
|
|
54
107
|
content: [
|
|
@@ -199,6 +252,10 @@ export const __panelToolsTestHooks = {
|
|
|
199
252
|
},
|
|
200
253
|
isRetrySafeCmd,
|
|
201
254
|
isTransientReconnectError,
|
|
255
|
+
// Adult-consent classifier + its exact card labels (#390 gate tests).
|
|
256
|
+
classifyConsentReply,
|
|
257
|
+
CONSENT_YES_LABEL,
|
|
258
|
+
CONSENT_NO_LABEL,
|
|
202
259
|
// #384 live-canvas capture fallback (defined later in the module).
|
|
203
260
|
reconstructUiFromState: (reply) => reconstructUiFromState(reply),
|
|
204
261
|
resolveWorkflowInput: (args, ctx, allowStateFallback = true) => resolveWorkflowInput(args, ctx, allowStateFallback),
|
|
@@ -2006,10 +2063,37 @@ function getAskTiming() {
|
|
|
2006
2063
|
}
|
|
2007
2064
|
/** True when an error is the bridge's reply-TIMEOUT for a card (the tab never
|
|
2008
2065
|
* replied within the window), NOT a genuine transport/command error. Only a
|
|
2009
|
-
* timeout warrants polling the late-reply buffer for a slow-but-valid answer.
|
|
2066
|
+
* timeout warrants polling the late-reply buffer for a slow-but-valid answer.
|
|
2067
|
+
*
|
|
2068
|
+
* Anchored (`^…$`) on the bridge's CANONICAL no-reply message — the WHOLE message
|
|
2069
|
+
* ui-bridge `dispatch()` emits: `Panel tab <id> did not reply to "<cmd>" within <N>
|
|
2070
|
+
* ms — the ComfyUI tab may be backgrounded or frozen`. Whole-message anchoring is
|
|
2071
|
+
* deliberate: a genuine transport error that merely WRAPS or embeds the phrase —
|
|
2072
|
+
* e.g. `relay failed: Panel tab abcd did not reply to "ask_user" within 500 ms;
|
|
2073
|
+
* reconnecting`, or `upstream service did not reply to us within 500 ms` — must NOT
|
|
2074
|
+
* be mis-handled as a recoverable card-reply timeout. It mirrors the same canonical
|
|
2075
|
+
* distinction the panel_open_workflow ack-timeout path draws. Crucial for the
|
|
2076
|
+
* consent gate: a real transport failure must reach fail(), never be quietly
|
|
2077
|
+
* reported as an unchanged-state success. */
|
|
2010
2078
|
function isReplyTimeoutError(err) {
|
|
2079
|
+
// AUTHORITATIVE: the bridge tags every reply-timeout with a typed marker
|
|
2080
|
+
// (markReplyTimeout). Keying on it makes the recoverable-timeout decision robust to
|
|
2081
|
+
// ANY tab_id — including one containing spaces, which the text form below can't
|
|
2082
|
+
// segment (ui-bridge accepts an arbitrary-string tab_id).
|
|
2083
|
+
if (isReplyTimeoutTagged(err))
|
|
2084
|
+
return true;
|
|
2085
|
+
// FALLBACK (test-injected plain errors / any untagged error): an EXACT whole-message
|
|
2086
|
+
// match of the bridge's canonical no-reply. Literal single space before "ms" (the
|
|
2087
|
+
// bridge always emits "within <N> ms"), no `.trim()`, `^` at true start (no /m flag)
|
|
2088
|
+
// and a HARD end-of-input `(?![\s\S])` — NOT `$`, which in JS also matches just
|
|
2089
|
+
// before a final "\n" and would let `canonical + "\n"` slip through. The tab-id
|
|
2090
|
+
// segment is `.+?` (lazy, bounded by the fixed ` did not reply to "` that follows —
|
|
2091
|
+
// an ≤8-char id slice can't contain that 19-char delimiter) so a spaced tab_id still
|
|
2092
|
+
// matches here too. So a prefixed/suffixed wrapper, whitespace/newline-wrapped text,
|
|
2093
|
+
// or noncanonical spacing ("within 500ms") does NOT match and is surfaced as a real
|
|
2094
|
+
// error. Case-sensitive: the message is a fixed literal template.
|
|
2011
2095
|
const msg = err instanceof Error ? err.message : String(err ?? "");
|
|
2012
|
-
return
|
|
2096
|
+
return /^Panel tab .+? did not reply to "[^"]*" within \d+ ms — the ComfyUI tab may be backgrounded or frozen(?![\s\S])/.test(msg);
|
|
2013
2097
|
}
|
|
2014
2098
|
/**
|
|
2015
2099
|
* Actionable error string when THIS session has no interactive surface able to
|
|
@@ -2802,16 +2886,64 @@ export function buildPanelToolDefs() {
|
|
|
2802
2886
|
// that lost its live binding (reconnect/reload/workflow-switch) throws a
|
|
2803
2887
|
// false `no connected tab` here even though graph tools just worked.
|
|
2804
2888
|
ctx.ensureReachable?.();
|
|
2805
|
-
|
|
2889
|
+
// #390: the enclosing MCP `tools/call` is killed at ~300s. A hardcoded 300s
|
|
2890
|
+
// card wait raced that budget with ZERO margin, so an idle user who never
|
|
2891
|
+
// clicked blew the whole tool call as a transport timeout ("timed out
|
|
2892
|
+
// awaiting tools/call after 300s") instead of resolving cleanly. CLAMP the
|
|
2893
|
+
// card deadline under the budget (the same getAskTiming() ceiling panel_ask
|
|
2894
|
+
// and confirm use) with a stable ask_id, and on a reply-timeout poll the
|
|
2895
|
+
// bridge's late-reply buffer for a bounded grace so a slow-but-VALID pick is
|
|
2896
|
+
// still honored. If the user is simply away, resolve cleanly with
|
|
2897
|
+
// { nsfw_allowed:false, timed_out:true } WITHOUT touching consent — a timeout
|
|
2898
|
+
// NEVER grants the gate; the persistent decision is unchanged and can be read
|
|
2899
|
+
// back with panel_get_content_mode, or the user re-asked, on the next turn.
|
|
2900
|
+
const timing = getAskTiming();
|
|
2901
|
+
const askId = randomUUID();
|
|
2902
|
+
const askCard = {
|
|
2806
2903
|
cmd: "ask_user",
|
|
2904
|
+
ask_id: askId,
|
|
2807
2905
|
question,
|
|
2808
2906
|
header: "18+ consent",
|
|
2809
2907
|
options: [
|
|
2810
|
-
{ label:
|
|
2811
|
-
{ label:
|
|
2908
|
+
{ label: CONSENT_YES_LABEL, description: "Enable adult content for this session" },
|
|
2909
|
+
{ label: CONSENT_NO_LABEL, description: "Stay in safe-for-work mode" },
|
|
2812
2910
|
],
|
|
2813
|
-
}
|
|
2814
|
-
|
|
2911
|
+
};
|
|
2912
|
+
let reply;
|
|
2913
|
+
let timedOut = false;
|
|
2914
|
+
try {
|
|
2915
|
+
reply = await ctx.bridge.send(askCard, { tabId: ctx.tabId, timeoutMs: timing.deadlineMs });
|
|
2916
|
+
}
|
|
2917
|
+
catch (err) {
|
|
2918
|
+
// Only a card-reply TIMEOUT is recoverable here: poll the late buffer for a
|
|
2919
|
+
// slow-but-valid answer. Any other error (no panel, transport failure)
|
|
2920
|
+
// propagates to the outer catch → fail(), exactly as before.
|
|
2921
|
+
if (!isReplyTimeoutError(err))
|
|
2922
|
+
throw err;
|
|
2923
|
+
timedOut = true;
|
|
2924
|
+
reply = await pollLateAskReply(ctx.bridge, askId, timing);
|
|
2925
|
+
}
|
|
2926
|
+
// STRICT gate: adult mode turns ON only on the EXACT affirmative option (or a
|
|
2927
|
+
// strict whole-string yes token) — never via the loose isAffirmative() prefix
|
|
2928
|
+
// match, so a free-text late reply like "adult content is illegal here" or "On
|
|
2929
|
+
// second thought, no" can't grant. An UNCLEAR reply (incl. a no-answer timeout,
|
|
2930
|
+
// where reply is undefined) changes NOTHING: it neither grants nor revokes a
|
|
2931
|
+
// prior genuine grant. Only an EXACT decline explicitly reverts to SFW.
|
|
2932
|
+
const decision = classifyConsentReply(reply);
|
|
2933
|
+
if (decision === "unclear") {
|
|
2934
|
+
const current = getNsfwConsent();
|
|
2935
|
+
return ok({
|
|
2936
|
+
nsfw_allowed: current.allowed,
|
|
2937
|
+
decided_at: current.decidedAt ?? null,
|
|
2938
|
+
...(timedOut ? { timed_out: true } : {}),
|
|
2939
|
+
note: timedOut
|
|
2940
|
+
? "The 18+ consent card wasn't answered in time, so nothing changed — adult content stays gated by the existing state. " +
|
|
2941
|
+
"Ask again when the user is back, or read the current state with panel_get_content_mode."
|
|
2942
|
+
: "The 18+ consent card wasn't answered with a clear yes/no, so nothing changed — the existing content-mode state is unchanged. " +
|
|
2943
|
+
"Ask again with a clear choice, or read the current state with panel_get_content_mode.",
|
|
2944
|
+
});
|
|
2945
|
+
}
|
|
2946
|
+
const allowed = decision === "grant";
|
|
2815
2947
|
const state = setNsfwConsent(allowed);
|
|
2816
2948
|
return ok({
|
|
2817
2949
|
nsfw_allowed: state.allowed,
|
|
@@ -3133,7 +3265,9 @@ export function buildPanelToolDefs() {
|
|
|
3133
3265
|
deferredBind = true;
|
|
3134
3266
|
rebindNote =
|
|
3135
3267
|
" No panel tab is connected yet — cleared the stale binding; this session will " +
|
|
3136
|
-
"follow (bind onto) the tab as soon as one reconnects. Retry your graph tool in a
|
|
3268
|
+
"follow (bind onto) the tab as soon as one reconnects. Retry your graph tool in a " +
|
|
3269
|
+
"moment; if nothing reconnects shortly, ask the user to refresh (reload) the ComfyUI " +
|
|
3270
|
+
"browser tab, which reconnects the Agent panel after a restart (not an install issue).";
|
|
3137
3271
|
}
|
|
3138
3272
|
// Detect the rebind regardless of whether awaitReachable or rebindToActiveTab
|
|
3139
3273
|
// performed it (either mutates ctx.tabId), so the note is never swallowed.
|