@forhuman/flowmcp 0.1.0
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/CONTRIBUTING.md +95 -0
- package/LICENSE +21 -0
- package/README.md +221 -0
- package/SKILL.md +214 -0
- package/bin/flowmcp +80 -0
- package/cases/flowmcp.md +79 -0
- package/commands/add.sh +46 -0
- package/commands/connect.sh +61 -0
- package/commands/debug.sh +122 -0
- package/commands/inspect.sh +58 -0
- package/commands/install.sh +67 -0
- package/commands/lang.sh +38 -0
- package/commands/list.sh +35 -0
- package/commands/remove.sh +82 -0
- package/commands/rename.sh +104 -0
- package/commands/rotate.sh +33 -0
- package/commands/run-mcp.sh +27 -0
- package/commands/schema.sh +131 -0
- package/commands/secret-set.sh +37 -0
- package/commands/test.sh +131 -0
- package/friction.md +67 -0
- package/lib/audit.sh +17 -0
- package/lib/bootstrap.sh +18 -0
- package/lib/clients.sh +107 -0
- package/lib/common.sh +66 -0
- package/lib/i18n.sh +248 -0
- package/lib/oauth.sh +22 -0
- package/lib/profiles.sh +58 -0
- package/lib/secrets.sh +89 -0
- package/lib/ui.sh +121 -0
- package/package.json +51 -0
package/lib/ui.sh
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Terminal output helpers: colors auto-disable when not a real TTY, when
|
|
3
|
+
# NO_COLOR is set, or when TERM=dumb — so agent tool-call output and piped
|
|
4
|
+
# logs stay plain text, never raw ANSI escapes.
|
|
5
|
+
|
|
6
|
+
if [[ -t 1 && -z "${NO_COLOR:-}" && "${TERM:-dumb}" != "dumb" ]]; then
|
|
7
|
+
WFW_C_RESET=$'\033[0m'
|
|
8
|
+
WFW_C_BOLD=$'\033[1m'
|
|
9
|
+
WFW_C_DIM=$'\033[2m'
|
|
10
|
+
WFW_C_GREEN=$'\033[32m'
|
|
11
|
+
WFW_C_RED=$'\033[31m'
|
|
12
|
+
WFW_C_GRAY=$'\033[90m'
|
|
13
|
+
# forhuman palette — used for all CLI chrome (banner accents, next/hint labels).
|
|
14
|
+
WFW_C_YELLOW=$'\033[38;2;255;190;0m' # forhuman yellow #FFBE00 — hint/warn
|
|
15
|
+
WFW_C_CYAN=$'\033[38;2;1;46;220m' # forhuman blue #012EDC — next / accents
|
|
16
|
+
# Webflow's own brand blue, used ONLY for the Webflow "W" logo glyph —
|
|
17
|
+
# deliberately kept true to Webflow's real color, not the forhuman palette.
|
|
18
|
+
WFW_C_BRAND=$'\033[38;2;45;113;236m' # Webflow blue #2D71EC
|
|
19
|
+
WFW_C_BRAND_DIM=$'\033[38;2;22;56;118m' # dimmed brand blue, for the "breathing" idle frame
|
|
20
|
+
else
|
|
21
|
+
WFW_C_RESET="" WFW_C_BOLD="" WFW_C_DIM="" WFW_C_GREEN="" WFW_C_RED="" WFW_C_YELLOW="" WFW_C_CYAN="" WFW_C_GRAY="" WFW_C_BRAND="" WFW_C_BRAND_DIM=""
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
# Webflow "W" mark, rasterized from the brand SVG into half-block glyphs
|
|
25
|
+
# (▀▄█) so it renders in any terminal — no image protocol dependency.
|
|
26
|
+
WFW_LOGO_LINES=(
|
|
27
|
+
'████████████ ██████████ ▄█████████████'
|
|
28
|
+
'████████████ ███████████ ▄█████████████'
|
|
29
|
+
'████████████ ████████████ ▄█████████████'
|
|
30
|
+
'████████████ █████████████ ▄█████████████'
|
|
31
|
+
'████████████ ██████████████▄█████████████'
|
|
32
|
+
'████████████████████████████████████████'
|
|
33
|
+
' ▄█████████████████████████████'
|
|
34
|
+
' ▄▄██████████████████████████████'
|
|
35
|
+
'▄▄▄██████████████████████████████████'
|
|
36
|
+
'█████████████████████▀▄█████████████'
|
|
37
|
+
'███████████████████▀ ▄█████████████'
|
|
38
|
+
'████████████████▀▀ ▄█████████████'
|
|
39
|
+
'█████████████▀▀ ▄█████████████'
|
|
40
|
+
'████████▀▀ ▄█████████████'
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# wfw_logo [color] — prints the Webflow "W" mark in the given color
|
|
44
|
+
# (defaults to brand blue). Prints nothing when colors are disabled — the
|
|
45
|
+
# glyph reads as noise without color, so callers should have a plain-text
|
|
46
|
+
# fallback for non-TTY/NO_COLOR contexts.
|
|
47
|
+
wfw_logo() {
|
|
48
|
+
local color="${1:-$WFW_C_BRAND}"
|
|
49
|
+
[[ -z "$WFW_C_RESET" ]] && return 0
|
|
50
|
+
local line
|
|
51
|
+
for line in "${WFW_LOGO_LINES[@]}"; do
|
|
52
|
+
printf "%s%s%s\n" "$color" "$line" "$WFW_C_RESET"
|
|
53
|
+
done
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
wfw_say_ok() { echo "${WFW_C_GREEN}ok${WFW_C_RESET} $*"; }
|
|
57
|
+
wfw_say_err() { echo "${WFW_C_RED}error${WFW_C_RESET} $*" >&2; }
|
|
58
|
+
wfw_say_warn() { echo "${WFW_C_YELLOW}warn${WFW_C_RESET} $*" >&2; }
|
|
59
|
+
wfw_say_hint() { echo "${WFW_C_YELLOW}hint${WFW_C_RESET} $*" >&2; }
|
|
60
|
+
wfw_say_next() { echo "${WFW_C_CYAN}next${WFW_C_RESET} $*"; }
|
|
61
|
+
|
|
62
|
+
# wfw_status_color <word> -> colorizes ok/pass/available/available green,
|
|
63
|
+
# fail/error/taken red, anything else (e.g. "never") dim gray.
|
|
64
|
+
wfw_status_color() {
|
|
65
|
+
local s="$1"
|
|
66
|
+
case "$s" in
|
|
67
|
+
ok|pass|available) echo "${WFW_C_GREEN}${s}${WFW_C_RESET}" ;;
|
|
68
|
+
fail|error|taken) echo "${WFW_C_RED}${s}${WFW_C_RESET}" ;;
|
|
69
|
+
*) echo "${WFW_C_GRAY}${s}${WFW_C_RESET}" ;;
|
|
70
|
+
esac
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# wfw_status_color_padded <status> <width> — colorize, then pad on VISIBLE
|
|
74
|
+
# length (not the ANSI-code length) so table columns stay aligned.
|
|
75
|
+
wfw_status_color_padded() {
|
|
76
|
+
local s="$1"
|
|
77
|
+
local width="$2"
|
|
78
|
+
local pad=$(( width - ${#s} ))
|
|
79
|
+
(( pad < 0 )) && pad=0
|
|
80
|
+
printf "%s%s" "$(wfw_status_color "$s")" "$(printf "%${pad}s" "")"
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
wfw_version() {
|
|
84
|
+
local pkg="$WFW_LIB_DIR/../package.json"
|
|
85
|
+
if [[ -f "$pkg" ]]; then
|
|
86
|
+
jq -r '.version' "$pkg" 2>/dev/null || echo "0.0.0-dev"
|
|
87
|
+
else
|
|
88
|
+
echo "0.0.0-dev"
|
|
89
|
+
fi
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
# wfw_wait_with_logo <background-pid> — redraws the logo, alternating
|
|
93
|
+
# brand/dim color for a "breathing" effect, until the given background job
|
|
94
|
+
# exits. No-op (prints nothing) when colors are disabled — caller should
|
|
95
|
+
# print its own plain-text waiting message before calling this.
|
|
96
|
+
wfw_wait_with_logo() {
|
|
97
|
+
local pid="$1" n="${#WFW_LOGO_LINES[@]}" frame=0 status=0
|
|
98
|
+
if [[ -z "$WFW_C_RESET" ]]; then
|
|
99
|
+
if wait "$pid"; then status=0; else status=$?; fi
|
|
100
|
+
return $status
|
|
101
|
+
fi
|
|
102
|
+
while kill -0 "$pid" 2>/dev/null; do
|
|
103
|
+
if (( frame % 2 == 0 )); then wfw_logo "$WFW_C_BRAND"; else wfw_logo "$WFW_C_BRAND_DIM"; fi
|
|
104
|
+
frame=$(( frame + 1 ))
|
|
105
|
+
sleep 0.6
|
|
106
|
+
printf "\033[%dA" "$n"
|
|
107
|
+
done
|
|
108
|
+
if wait "$pid"; then status=0; else status=$?; fi
|
|
109
|
+
printf "\033[0J" # clear from cursor to end of screen (removes last logo frame)
|
|
110
|
+
return $status
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
wfw_banner() {
|
|
114
|
+
if [[ -n "$WFW_C_RESET" ]]; then
|
|
115
|
+
wfw_logo
|
|
116
|
+
echo "${WFW_C_BOLD}flowmcp${WFW_C_RESET} ${WFW_C_DIM}v$(wfw_version)${WFW_C_RESET} ${WFW_C_YELLOW}·${WFW_C_RESET} ${WFW_C_CYAN}by forhuman${WFW_C_RESET}"
|
|
117
|
+
else
|
|
118
|
+
echo "flowmcp v$(wfw_version) · by forhuman"
|
|
119
|
+
fi
|
|
120
|
+
echo "${WFW_C_DIM}$(wfw_t tagline)${WFW_C_RESET}"
|
|
121
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@forhuman/flowmcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Manage multiple Webflow MCP server connections (one per client/org) without ever letting an API token pass through agent context.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"bin": {
|
|
7
|
+
"flowmcp": "bin/flowmcp",
|
|
8
|
+
"fmcp": "bin/flowmcp"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin",
|
|
12
|
+
"commands",
|
|
13
|
+
"lib",
|
|
14
|
+
"SKILL.md",
|
|
15
|
+
"README.md",
|
|
16
|
+
"LICENSE",
|
|
17
|
+
"CONTRIBUTING.md",
|
|
18
|
+
"friction.md",
|
|
19
|
+
"cases"
|
|
20
|
+
],
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=18"
|
|
26
|
+
},
|
|
27
|
+
"os": [
|
|
28
|
+
"darwin",
|
|
29
|
+
"linux"
|
|
30
|
+
],
|
|
31
|
+
"keywords": [
|
|
32
|
+
"webflow",
|
|
33
|
+
"mcp",
|
|
34
|
+
"model-context-protocol",
|
|
35
|
+
"claude-code",
|
|
36
|
+
"claude-desktop",
|
|
37
|
+
"cursor",
|
|
38
|
+
"cli",
|
|
39
|
+
"skill",
|
|
40
|
+
"agency",
|
|
41
|
+
"keychain"
|
|
42
|
+
],
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/fiorellacisneros/flowmcp.git"
|
|
46
|
+
},
|
|
47
|
+
"homepage": "https://github.com/fiorellacisneros/flowmcp#readme",
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/fiorellacisneros/flowmcp/issues"
|
|
50
|
+
}
|
|
51
|
+
}
|