@josephyan/qingflow-cli 0.2.0-beta.55

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.
Files changed (79) hide show
  1. package/README.md +30 -0
  2. package/docs/local-agent-install.md +235 -0
  3. package/entry_point.py +13 -0
  4. package/npm/bin/qingflow.mjs +5 -0
  5. package/npm/lib/runtime.mjs +204 -0
  6. package/npm/scripts/postinstall.mjs +16 -0
  7. package/package.json +34 -0
  8. package/pyproject.toml +67 -0
  9. package/qingflow +15 -0
  10. package/src/qingflow_mcp/__init__.py +5 -0
  11. package/src/qingflow_mcp/__main__.py +5 -0
  12. package/src/qingflow_mcp/backend_client.py +547 -0
  13. package/src/qingflow_mcp/builder_facade/__init__.py +3 -0
  14. package/src/qingflow_mcp/builder_facade/models.py +985 -0
  15. package/src/qingflow_mcp/builder_facade/service.py +8243 -0
  16. package/src/qingflow_mcp/cli/__init__.py +1 -0
  17. package/src/qingflow_mcp/cli/commands/__init__.py +15 -0
  18. package/src/qingflow_mcp/cli/commands/app.py +40 -0
  19. package/src/qingflow_mcp/cli/commands/auth.py +78 -0
  20. package/src/qingflow_mcp/cli/commands/builder.py +184 -0
  21. package/src/qingflow_mcp/cli/commands/common.py +47 -0
  22. package/src/qingflow_mcp/cli/commands/imports.py +86 -0
  23. package/src/qingflow_mcp/cli/commands/record.py +202 -0
  24. package/src/qingflow_mcp/cli/commands/task.py +87 -0
  25. package/src/qingflow_mcp/cli/commands/workspace.py +33 -0
  26. package/src/qingflow_mcp/cli/context.py +48 -0
  27. package/src/qingflow_mcp/cli/formatters.py +269 -0
  28. package/src/qingflow_mcp/cli/json_io.py +50 -0
  29. package/src/qingflow_mcp/cli/main.py +147 -0
  30. package/src/qingflow_mcp/config.py +221 -0
  31. package/src/qingflow_mcp/errors.py +66 -0
  32. package/src/qingflow_mcp/import_store.py +121 -0
  33. package/src/qingflow_mcp/json_types.py +18 -0
  34. package/src/qingflow_mcp/list_type_labels.py +76 -0
  35. package/src/qingflow_mcp/server.py +211 -0
  36. package/src/qingflow_mcp/server_app_builder.py +387 -0
  37. package/src/qingflow_mcp/server_app_user.py +317 -0
  38. package/src/qingflow_mcp/session_store.py +289 -0
  39. package/src/qingflow_mcp/solution/__init__.py +6 -0
  40. package/src/qingflow_mcp/solution/build_assembly_store.py +181 -0
  41. package/src/qingflow_mcp/solution/compiler/__init__.py +282 -0
  42. package/src/qingflow_mcp/solution/compiler/chart_compiler.py +96 -0
  43. package/src/qingflow_mcp/solution/compiler/form_compiler.py +466 -0
  44. package/src/qingflow_mcp/solution/compiler/icon_utils.py +113 -0
  45. package/src/qingflow_mcp/solution/compiler/navigation_compiler.py +57 -0
  46. package/src/qingflow_mcp/solution/compiler/package_compiler.py +19 -0
  47. package/src/qingflow_mcp/solution/compiler/portal_compiler.py +60 -0
  48. package/src/qingflow_mcp/solution/compiler/view_compiler.py +51 -0
  49. package/src/qingflow_mcp/solution/compiler/workflow_compiler.py +173 -0
  50. package/src/qingflow_mcp/solution/design_session.py +222 -0
  51. package/src/qingflow_mcp/solution/design_store.py +100 -0
  52. package/src/qingflow_mcp/solution/executor.py +2339 -0
  53. package/src/qingflow_mcp/solution/normalizer.py +23 -0
  54. package/src/qingflow_mcp/solution/requirements_builder.py +536 -0
  55. package/src/qingflow_mcp/solution/run_store.py +244 -0
  56. package/src/qingflow_mcp/solution/spec_models.py +853 -0
  57. package/src/qingflow_mcp/tools/__init__.py +1 -0
  58. package/src/qingflow_mcp/tools/ai_builder_tools.py +2063 -0
  59. package/src/qingflow_mcp/tools/app_tools.py +850 -0
  60. package/src/qingflow_mcp/tools/approval_tools.py +833 -0
  61. package/src/qingflow_mcp/tools/auth_tools.py +697 -0
  62. package/src/qingflow_mcp/tools/base.py +81 -0
  63. package/src/qingflow_mcp/tools/code_block_tools.py +679 -0
  64. package/src/qingflow_mcp/tools/directory_tools.py +648 -0
  65. package/src/qingflow_mcp/tools/feedback_tools.py +230 -0
  66. package/src/qingflow_mcp/tools/file_tools.py +385 -0
  67. package/src/qingflow_mcp/tools/import_tools.py +1971 -0
  68. package/src/qingflow_mcp/tools/navigation_tools.py +177 -0
  69. package/src/qingflow_mcp/tools/package_tools.py +240 -0
  70. package/src/qingflow_mcp/tools/portal_tools.py +131 -0
  71. package/src/qingflow_mcp/tools/qingbi_report_tools.py +269 -0
  72. package/src/qingflow_mcp/tools/record_tools.py +12739 -0
  73. package/src/qingflow_mcp/tools/role_tools.py +94 -0
  74. package/src/qingflow_mcp/tools/solution_tools.py +3887 -0
  75. package/src/qingflow_mcp/tools/task_context_tools.py +1423 -0
  76. package/src/qingflow_mcp/tools/task_tools.py +843 -0
  77. package/src/qingflow_mcp/tools/view_tools.py +280 -0
  78. package/src/qingflow_mcp/tools/workflow_tools.py +312 -0
  79. package/src/qingflow_mcp/tools/workspace_tools.py +219 -0
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # Qingflow CLI
2
+
3
+ Install:
4
+
5
+ ```bash
6
+ npm install @josephyan/qingflow-cli@0.2.0-beta.55
7
+ ```
8
+
9
+ Run:
10
+
11
+ ```bash
12
+ npx -y -p @josephyan/qingflow-cli@0.2.0-beta.55 qingflow
13
+ ```
14
+
15
+ Environment:
16
+
17
+ - `QINGFLOW_MCP_DEFAULT_BASE_URL`
18
+ - `QINGFLOW_MCP_DEFAULT_QF_VERSION`
19
+ - `QINGFLOW_MCP_HOME`
20
+
21
+ This package bootstraps a local Python runtime on first install and then starts the `qingflow` command line interface.
22
+
23
+ Bundled skills:
24
+
25
+ - none
26
+
27
+ Note:
28
+
29
+ - The skill files are included in the npm package.
30
+ - On install, the package copies them to `$CODEX_HOME/skills` (or `~/.codex/skills` if `CODEX_HOME` is unset).
@@ -0,0 +1,235 @@
1
+ # 本地智能体安装
2
+
3
+ 这个目录下现在有三个本地命令入口:
4
+
5
+ 1. 统一 CLI:`qingflow`
6
+ 2. 记录/待办优先的 `qingflow-app-user-mcp`
7
+ 3. 精简 builder 的 `qingflow-app-builder-mcp`
8
+
9
+ ## npm 安装器适用场景
10
+
11
+ 适合这类本地 agent / gateway:
12
+
13
+ - Claude Desktop
14
+ - Cline / Roo / Cursor 这类本地 MCP 客户端
15
+ - OpenClaw 风格的本地 agent 容器或本地 gateway
16
+ - 任何支持 `command + args + env` 的 stdio MCP 客户端
17
+
18
+ ## 前置条件
19
+
20
+ - Node.js >= 16.16
21
+ - Python >= 3.11
22
+ - 安装过程中可以访问 PyPI
23
+
24
+ 如果机器上没有默认 `python3` / `python`,可以先设置:
25
+
26
+ ```bash
27
+ export QINGFLOW_MCP_PYTHON=/path/to/python3.11
28
+ ```
29
+
30
+ ## 安装方式
31
+
32
+ ### 方式 1:在源码目录预热运行环境
33
+
34
+ ```bash
35
+ cd qingflow-support/mcp-server
36
+ npm install
37
+ ```
38
+
39
+ 这个模式适合你已经有源码 checkout,只想让当前目录具备本地 agent 可调用的运行时。
40
+
41
+ ### 方式 2:全局安装到当前机器
42
+
43
+ ```bash
44
+ cd qingflow-support/mcp-server
45
+ npm install -g .
46
+ ```
47
+
48
+ ### 方式 3:安装到某个本地 agent workspace
49
+
50
+ ```bash
51
+ npm install /absolute/path/to/qingflow-support/mcp-server
52
+ ```
53
+
54
+ ### 方式 4:离线分发 tgz 安装包
55
+
56
+ 先在源码目录打包:
57
+
58
+ ```bash
59
+ cd qingflow-support/mcp-server
60
+ npm run pack:npm
61
+ ```
62
+
63
+ 会生成:
64
+
65
+ ```bash
66
+ dist/npm/josephyan-qingflow-cli-<version>.tgz
67
+ dist/npm/josephyan-qingflow-app-user-mcp-<version>.tgz
68
+ dist/npm/josephyan-qingflow-app-builder-mcp-<version>.tgz
69
+ ```
70
+
71
+ 然后在目标机器安装:
72
+
73
+ ```bash
74
+ npm install /absolute/path/to/dist/npm/josephyan-qingflow-cli-<version>.tgz
75
+ npm install /absolute/path/to/dist/npm/josephyan-qingflow-app-user-mcp-<version>.tgz
76
+ npm install /absolute/path/to/dist/npm/josephyan-qingflow-app-builder-mcp-<version>.tgz
77
+ ```
78
+
79
+ 安装时会自动:
80
+
81
+ 1. 创建 `.npm-python/`
82
+ 2. 在其中建立 Python 虚拟环境
83
+ 3. 执行 `pip install .`
84
+ 4. 在安装位置暴露 `qingflow`、`qingflow-app-user-mcp`、`qingflow-app-builder-mcp` 命令
85
+
86
+ ## 本地验证
87
+
88
+ 如果你在源码目录执行了 `npm install`,可直接这样启动:
89
+
90
+ ```bash
91
+ cd qingflow-support/mcp-server
92
+ node ./npm/bin/qingflow.mjs --help
93
+ node ./npm/bin/qingflow-app-user-mcp.mjs
94
+ node ./npm/bin/qingflow-app-builder-mcp.mjs
95
+ ```
96
+
97
+ 如果你是全局安装:
98
+
99
+ ```bash
100
+ qingflow --help
101
+ qingflow-app-user-mcp
102
+ qingflow-app-builder-mcp
103
+ ```
104
+
105
+ 如果你是把包安装到了某个本地 agent workspace,命令通常位于:
106
+
107
+ ```bash
108
+ /absolute/path/to/agent-workspace/node_modules/.bin/qingflow
109
+ /absolute/path/to/agent-workspace/node_modules/.bin/qingflow-app-user-mcp
110
+ /absolute/path/to/agent-workspace/node_modules/.bin/qingflow-app-builder-mcp
111
+ ```
112
+
113
+ 如果你是从 tgz 安装到某个空目录,命令通常位于:
114
+
115
+ ```bash
116
+ /absolute/path/to/install-dir/node_modules/.bin/qingflow
117
+ /absolute/path/to/install-dir/node_modules/.bin/qingflow-app-user-mcp
118
+ /absolute/path/to/install-dir/node_modules/.bin/qingflow-app-builder-mcp
119
+ ```
120
+
121
+ 这是 stdio MCP server,正常情况下不会输出欢迎信息,而是等待客户端连接。
122
+
123
+ ## 客户端配置
124
+
125
+ ### 通用 stdio MCP 客户端
126
+
127
+ 如果你直接使用源码 checkout:
128
+
129
+ ```json
130
+ {
131
+ "mcpServers": {
132
+ "qingflow": {
133
+ "command": "node",
134
+ "args": [
135
+ "/absolute/path/to/qingflow-support/mcp-server/npm/bin/qingflow-app-user-mcp.mjs"
136
+ ],
137
+ "env": {
138
+ "QINGFLOW_MCP_DEFAULT_BASE_URL": "https://qingflow.com/api",
139
+ "QINGFLOW_MCP_HOME": "/absolute/path/to/.qingflow-mcp"
140
+ }
141
+ }
142
+ }
143
+ }
144
+ ```
145
+
146
+ 如果你已经全局安装:
147
+
148
+ ```json
149
+ {
150
+ "mcpServers": {
151
+ "qingflow": {
152
+ "command": "qingflow-app-user-mcp",
153
+ "args": [],
154
+ "env": {
155
+ "QINGFLOW_MCP_DEFAULT_BASE_URL": "https://qingflow.com/api",
156
+ "QINGFLOW_MCP_HOME": "/absolute/path/to/.qingflow-mcp"
157
+ }
158
+ }
159
+ }
160
+ }
161
+ ```
162
+
163
+ 如果你把包安装到了某个本地 agent workspace:
164
+
165
+ ```json
166
+ {
167
+ "mcpServers": {
168
+ "qingflow": {
169
+ "command": "/absolute/path/to/agent-workspace/node_modules/.bin/qingflow-app-user-mcp",
170
+ "args": [],
171
+ "env": {
172
+ "QINGFLOW_MCP_DEFAULT_BASE_URL": "https://qingflow.com/api",
173
+ "QINGFLOW_MCP_HOME": "/absolute/path/to/.qingflow-mcp"
174
+ }
175
+ }
176
+ }
177
+ }
178
+ ```
179
+
180
+ ### 使用 npx
181
+
182
+ 如果不做全局安装,也可以直接运行独立包:
183
+
184
+ ```json
185
+ {
186
+ "mcpServers": {
187
+ "qingflow-user": {
188
+ "command": "npx",
189
+ "args": [
190
+ "-y",
191
+ "@josephyan/qingflow-app-user-mcp"
192
+ ],
193
+ "env": {
194
+ "QINGFLOW_MCP_DEFAULT_BASE_URL": "https://qingflow.com/api"
195
+ }
196
+ },
197
+ "qingflow-builder": {
198
+ "command": "npx",
199
+ "args": [
200
+ "-y",
201
+ "@josephyan/qingflow-app-builder-mcp"
202
+ ],
203
+ "env": {
204
+ "QINGFLOW_MCP_DEFAULT_BASE_URL": "https://qingflow.com/api"
205
+ }
206
+ }
207
+ }
208
+ }
209
+ ```
210
+
211
+ 说明:
212
+ - 源码目录 `npm install` 不会把命令加到全局 PATH;这种模式请用 `node ./npm/bin/qingflow.mjs`、`node ./npm/bin/qingflow-app-user-mcp.mjs` 或 `node ./npm/bin/qingflow-app-builder-mcp.mjs`
213
+ - `npx` 方式适合临时安装或容器化本地 agent
214
+ - 全局安装方式更适合长期固定使用的本机开发环境
215
+
216
+ ## 排障
217
+
218
+ 如果安装失败,优先检查:
219
+
220
+ 1. `node -v`
221
+ 2. `python3 --version`
222
+ 3. `pip` 是否能访问 PyPI
223
+ 4. 是否设置了错误的 `QINGFLOW_MCP_PYTHON`
224
+
225
+ 如果需要重装 Python 侧运行环境,可以删掉:
226
+
227
+ ```bash
228
+ rm -rf .npm-python
229
+ ```
230
+
231
+ 然后重新执行:
232
+
233
+ ```bash
234
+ npm install
235
+ ```
package/entry_point.py ADDED
@@ -0,0 +1,13 @@
1
+ import sys
2
+ import os
3
+
4
+ # Ensure the 'src' directory is in the Python search path
5
+ # PyInstaller will pick up everything in src/qingflow_mcp as the package
6
+ src_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "src"))
7
+ if src_path not in sys.path:
8
+ sys.path.insert(0, src_path)
9
+
10
+ from qingflow_mcp.server import main
11
+
12
+ if __name__ == "__main__":
13
+ main()
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import { spawnServer, getPackageRoot } from "../lib/runtime.mjs";
3
+
4
+ const packageRoot = getPackageRoot(import.meta.url);
5
+ spawnServer(packageRoot, process.argv.slice(2), "qingflow");
@@ -0,0 +1,204 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { spawn, spawnSync } from "node:child_process";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const WINDOWS = process.platform === "win32";
7
+
8
+ function runChecked(command, args, options = {}) {
9
+ const result = spawnSync(command, args, {
10
+ stdio: "inherit",
11
+ ...options,
12
+ });
13
+ if (result.error) {
14
+ throw result.error;
15
+ }
16
+ if (result.status !== 0) {
17
+ throw new Error(`Command failed: ${command} ${args.join(" ")}`);
18
+ }
19
+ }
20
+
21
+ function commandWorks(command, args) {
22
+ const result = spawnSync(command, args, {
23
+ stdio: "ignore",
24
+ });
25
+ return result.status === 0;
26
+ }
27
+
28
+ export function getPackageRoot(metaUrl) {
29
+ return path.resolve(path.dirname(fileURLToPath(metaUrl)), "..", "..");
30
+ }
31
+
32
+ export function getCodexHome() {
33
+ const configured = process.env.CODEX_HOME?.trim();
34
+ if (configured) {
35
+ return path.resolve(configured);
36
+ }
37
+ const home = process.env.HOME || process.env.USERPROFILE;
38
+ if (!home) {
39
+ throw new Error("Cannot resolve CODEX_HOME because HOME is not set.");
40
+ }
41
+ return path.join(home, ".codex");
42
+ }
43
+
44
+ export function installBundledSkills(packageRoot) {
45
+ const skillsSrc = path.join(packageRoot, "skills");
46
+ if (!fs.existsSync(skillsSrc)) {
47
+ return { installed: [], skipped: true, destination: null };
48
+ }
49
+
50
+ const codexHome = getCodexHome();
51
+ const skillsDestRoot = path.join(codexHome, "skills");
52
+ fs.mkdirSync(skillsDestRoot, { recursive: true });
53
+
54
+ const installed = [];
55
+ for (const entry of fs.readdirSync(skillsSrc, { withFileTypes: true })) {
56
+ if (!entry.isDirectory()) {
57
+ continue;
58
+ }
59
+ const src = path.join(skillsSrc, entry.name);
60
+ const dest = path.join(skillsDestRoot, entry.name);
61
+ fs.rmSync(dest, { recursive: true, force: true });
62
+ fs.cpSync(src, dest, { recursive: true });
63
+ installed.push(entry.name);
64
+ }
65
+
66
+ return { installed, skipped: false, destination: skillsDestRoot };
67
+ }
68
+
69
+ export function getVenvDir(packageRoot) {
70
+ return path.join(packageRoot, ".npm-python");
71
+ }
72
+
73
+ export function getVenvPython(packageRoot) {
74
+ return WINDOWS
75
+ ? path.join(getVenvDir(packageRoot), "Scripts", "python.exe")
76
+ : path.join(getVenvDir(packageRoot), "bin", "python");
77
+ }
78
+
79
+ export function getVenvServerCommand(packageRoot, commandName = "qingflow-mcp") {
80
+ return WINDOWS
81
+ ? path.join(getVenvDir(packageRoot), "Scripts", `${commandName}.exe`)
82
+ : path.join(getVenvDir(packageRoot), "bin", commandName);
83
+ }
84
+
85
+ function readPackageVersion(packageRoot) {
86
+ const packageJsonPath = path.join(packageRoot, "package.json");
87
+ try {
88
+ const payload = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
89
+ return typeof payload.version === "string" && payload.version.trim() ? payload.version.trim() : null;
90
+ } catch {
91
+ return null;
92
+ }
93
+ }
94
+
95
+ function getVenvPip(packageRoot) {
96
+ return WINDOWS
97
+ ? path.join(getVenvDir(packageRoot), "Scripts", "pip.exe")
98
+ : path.join(getVenvDir(packageRoot), "bin", "pip");
99
+ }
100
+
101
+ export function findPython() {
102
+ const preferred = process.env.QINGFLOW_MCP_PYTHON?.trim();
103
+ const candidates = preferred
104
+ ? [{ command: preferred, args: [], label: preferred }]
105
+ : WINDOWS
106
+ ? [
107
+ { command: "py", args: ["-3", "-V"], label: "py -3" },
108
+ { command: "python", args: ["-V"], label: "python" },
109
+ { command: "python3", args: ["-V"], label: "python3" },
110
+ ]
111
+ : [
112
+ { command: "python3", args: ["-V"], label: "python3" },
113
+ { command: "python", args: ["-V"], label: "python" },
114
+ ];
115
+
116
+ for (const candidate of candidates) {
117
+ if (commandWorks(candidate.command, candidate.args)) {
118
+ if (candidate.command === "py") {
119
+ return { command: "py", args: ["-3"], label: candidate.label };
120
+ }
121
+ return { command: candidate.command, args: [], label: candidate.label };
122
+ }
123
+ }
124
+
125
+ throw new Error(
126
+ "Python 3.11+ was not found. Set QINGFLOW_MCP_PYTHON to a Python 3 executable before running npm install."
127
+ );
128
+ }
129
+
130
+ export function ensurePythonEnv(packageRoot, { force = false, commandName = "qingflow-mcp" } = {}) {
131
+ const python = findPython();
132
+ const venvDir = getVenvDir(packageRoot);
133
+ const venvPython = getVenvPython(packageRoot);
134
+ const serverCommand = getVenvServerCommand(packageRoot, commandName);
135
+ const stampPath = path.join(venvDir, ".bootstrap.json");
136
+ const packageVersion = readPackageVersion(packageRoot);
137
+ let stampVersion = null;
138
+ if (fs.existsSync(stampPath)) {
139
+ try {
140
+ const payload = JSON.parse(fs.readFileSync(stampPath, "utf8"));
141
+ stampVersion = typeof payload.package_version === "string" && payload.package_version.trim() ? payload.package_version.trim() : null;
142
+ } catch {
143
+ stampVersion = null;
144
+ }
145
+ }
146
+
147
+ if (!force && fs.existsSync(serverCommand) && fs.existsSync(stampPath) && stampVersion && stampVersion === packageVersion) {
148
+ return serverCommand;
149
+ }
150
+
151
+ if (force && fs.existsSync(venvDir)) {
152
+ fs.rmSync(venvDir, { recursive: true, force: true });
153
+ }
154
+
155
+ if (!fs.existsSync(venvPython)) {
156
+ runChecked(python.command, [...python.args, "-m", "venv", venvDir], { cwd: packageRoot });
157
+ }
158
+
159
+ const pip = getVenvPip(packageRoot);
160
+ runChecked(pip, ["install", "--disable-pip-version-check", "."], { cwd: packageRoot });
161
+
162
+ fs.writeFileSync(
163
+ stampPath,
164
+ JSON.stringify(
165
+ {
166
+ installed_at: new Date().toISOString(),
167
+ installer: "npm",
168
+ package_version: packageVersion,
169
+ },
170
+ null,
171
+ 2
172
+ )
173
+ );
174
+
175
+ if (!fs.existsSync(serverCommand)) {
176
+ throw new Error(`Bootstrap finished but ${serverCommand} was not created.`);
177
+ }
178
+
179
+ return serverCommand;
180
+ }
181
+
182
+ export function spawnServer(packageRoot, args, commandName = "qingflow-mcp") {
183
+ const serverCommand = fs.existsSync(getVenvServerCommand(packageRoot, commandName))
184
+ ? getVenvServerCommand(packageRoot, commandName)
185
+ : ensurePythonEnv(packageRoot, { commandName });
186
+
187
+ const child = spawn(serverCommand, args, {
188
+ stdio: "inherit",
189
+ env: process.env,
190
+ });
191
+
192
+ child.on("exit", (code, signal) => {
193
+ if (signal) {
194
+ process.kill(process.pid, signal);
195
+ return;
196
+ }
197
+ process.exit(code ?? 0);
198
+ });
199
+
200
+ child.on("error", (error) => {
201
+ console.error(`[qingflow-mcp] Failed to start server: ${error.message}`);
202
+ process.exit(1);
203
+ });
204
+ }
@@ -0,0 +1,16 @@
1
+ import { ensurePythonEnv, getPackageRoot, installBundledSkills } from "../lib/runtime.mjs";
2
+
3
+ const packageRoot = getPackageRoot(import.meta.url);
4
+
5
+ try {
6
+ console.log("[qingflow-mcp] Bootstrapping Python runtime...");
7
+ ensurePythonEnv(packageRoot, { commandName: "qingflow" });
8
+ console.log("[qingflow-mcp] Python runtime is ready.");
9
+ const skills = installBundledSkills(packageRoot);
10
+ if (!skills.skipped) {
11
+ console.log(`[qingflow-mcp] Installed skills to ${skills.destination}: ${skills.installed.join(", ")}`);
12
+ }
13
+ } catch (error) {
14
+ console.error(`[qingflow-mcp] postinstall failed: ${error.message}`);
15
+ process.exit(1);
16
+ }
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@josephyan/qingflow-cli",
3
+ "version": "0.2.0-beta.55",
4
+ "description": "Human-friendly Qingflow command line interface for auth, record operations, import, tasks, and stable builder flows.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "qingflow": "./npm/bin/qingflow.mjs"
9
+ },
10
+ "scripts": {
11
+ "postinstall": "node ./npm/scripts/postinstall.mjs"
12
+ },
13
+ "files": [
14
+ "README.md",
15
+ "pyproject.toml",
16
+ "entry_point.py",
17
+ "src/qingflow_mcp/**/*.py",
18
+ "src/qingflow_mcp/py.typed",
19
+ "qingflow",
20
+ "npm/",
21
+ "docs/local-agent-install.md",
22
+ "skills/"
23
+ ],
24
+ "engines": {
25
+ "node": ">=16.16.0"
26
+ },
27
+ "keywords": [
28
+ "mcp",
29
+ "qingflow",
30
+ "agent",
31
+ "stdio",
32
+ "cli"
33
+ ]
34
+ }
package/pyproject.toml ADDED
@@ -0,0 +1,67 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "qingflow-mcp"
7
+ version = "0.2.0b55"
8
+ description = "User-authenticated MCP server for Qingflow"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.11"
12
+ authors = [
13
+ { name = "Qingflow", email = "support@qingflow.com" }
14
+ ]
15
+ keywords = ["mcp", "qingflow", "automation", "workflow"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Intended Audience :: Developers",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ "Programming Language :: Python :: 3.13",
23
+ "Topic :: Software Development :: Libraries :: Python Modules",
24
+ ]
25
+ dependencies = [
26
+ "mcp>=1.9.4,<2.0.0",
27
+ "httpx>=0.27,<1.0",
28
+ "keyring>=25.5,<26.0",
29
+ "openpyxl>=3.1,<4.0",
30
+ "pydantic>=2.8,<3.0",
31
+ "pycryptodome>=3.20,<4.0",
32
+ "python-socketio[client]>=5.11,<6.0",
33
+ ]
34
+
35
+ [project.optional-dependencies]
36
+ dev = [
37
+ "pytest>=8.3,<9.0",
38
+ "respx>=0.22,<1.0",
39
+ ]
40
+ build = [
41
+ "pyinstaller>=6.0,<7.0",
42
+ "build>=1.0,<2.0",
43
+ "twine>=5.0,<6.0",
44
+ ]
45
+
46
+ [project.scripts]
47
+ qingflow-app-user-mcp = "qingflow_mcp.server_app_user:main"
48
+ qingflow-app-builder-mcp = "qingflow_mcp.server_app_builder:main"
49
+ qingflow = "qingflow_mcp.cli.main:main"
50
+
51
+ [project.urls]
52
+ Homepage = "https://github.com/qingflow/qingflow-mcp"
53
+ Documentation = "https://github.com/qingflow/qingflow-mcp#readme"
54
+ Repository = "https://github.com/qingflow/qingflow-mcp"
55
+ Issues = "https://github.com/qingflow/qingflow-mcp/issues"
56
+
57
+ [tool.setuptools.package-dir]
58
+ "" = "src"
59
+
60
+ [tool.setuptools.packages.find]
61
+ where = ["src"]
62
+
63
+ [tool.setuptools.package-data]
64
+ qingflow_mcp = ["py.typed"]
65
+
66
+ [tool.pytest.ini_options]
67
+ testpaths = ["tests"]
package/qingflow ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ ROOT_DIR="$(cd "$(dirname "$0")" && pwd)"
4
+ if [[ -n "${PYTHON_BIN:-}" ]]; then
5
+ PYTHON="${PYTHON_BIN}"
6
+ elif [[ -x "$ROOT_DIR/.venv/bin/python" ]]; then
7
+ PYTHON="$ROOT_DIR/.venv/bin/python"
8
+ elif command -v python3 >/dev/null 2>&1; then
9
+ PYTHON="$(command -v python3)"
10
+ else
11
+ echo "qingflow: python interpreter not found. Set PYTHON_BIN or create $ROOT_DIR/.venv" >&2
12
+ exit 1
13
+ fi
14
+ export PYTHONPATH="$ROOT_DIR/src${PYTHONPATH:+:$PYTHONPATH}"
15
+ exec "$PYTHON" -m qingflow_mcp.cli.main "$@"
@@ -0,0 +1,5 @@
1
+ from __future__ import annotations
2
+
3
+ __all__ = ["__version__"]
4
+
5
+ __version__ = "0.2.0b48"
@@ -0,0 +1,5 @@
1
+ """Entry point for running qingflow_mcp as a module."""
2
+ from qingflow_mcp.server import main
3
+
4
+ if __name__ == "__main__":
5
+ main()