@josephyan/qingflow-cli 0.2.0-beta.984 → 0.2.0-beta.986
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 +2 -2
- package/docs/local-agent-install.md +70 -11
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/qingflow_mcp/__init__.py +1 -1
- package/src/qingflow_mcp/builder_facade/service.py +47 -21
- package/src/qingflow_mcp/cli/commands/auth.py +14 -43
- package/src/qingflow_mcp/cli/commands/task.py +4 -1
- package/src/qingflow_mcp/cli/commands/workspace.py +0 -8
- package/src/qingflow_mcp/cli/formatters.py +0 -21
- package/src/qingflow_mcp/config.py +39 -0
- package/src/qingflow_mcp/errors.py +2 -2
- package/src/qingflow_mcp/public_surface.py +2 -6
- package/src/qingflow_mcp/response_trim.py +1 -8
- package/src/qingflow_mcp/server.py +1 -1
- package/src/qingflow_mcp/server_app_builder.py +4 -28
- package/src/qingflow_mcp/server_app_user.py +4 -28
- package/src/qingflow_mcp/session_store.py +31 -5
- package/src/qingflow_mcp/tools/ai_builder_tools.py +117 -1
- package/src/qingflow_mcp/tools/app_tools.py +51 -1
- package/src/qingflow_mcp/tools/approval_tools.py +82 -1
- package/src/qingflow_mcp/tools/auth_tools.py +258 -288
- package/src/qingflow_mcp/tools/base.py +204 -4
- package/src/qingflow_mcp/tools/code_block_tools.py +21 -0
- package/src/qingflow_mcp/tools/custom_button_tools.py +24 -1
- package/src/qingflow_mcp/tools/directory_tools.py +28 -1
- package/src/qingflow_mcp/tools/feedback_tools.py +8 -0
- package/src/qingflow_mcp/tools/file_tools.py +25 -1
- package/src/qingflow_mcp/tools/import_tools.py +40 -1
- package/src/qingflow_mcp/tools/navigation_tools.py +34 -1
- package/src/qingflow_mcp/tools/package_tools.py +37 -1
- package/src/qingflow_mcp/tools/portal_tools.py +28 -1
- package/src/qingflow_mcp/tools/qingbi_report_tools.py +38 -1
- package/src/qingflow_mcp/tools/record_tools.py +255 -2
- package/src/qingflow_mcp/tools/repository_dev_tools.py +21 -2
- package/src/qingflow_mcp/tools/resource_read_tools.py +23 -1
- package/src/qingflow_mcp/tools/role_tools.py +19 -1
- package/src/qingflow_mcp/tools/solution_tools.py +56 -1
- package/src/qingflow_mcp/tools/task_context_tools.py +205 -6
- package/src/qingflow_mcp/tools/task_tools.py +49 -3
- package/src/qingflow_mcp/tools/view_tools.py +56 -1
- package/src/qingflow_mcp/tools/workflow_tools.py +65 -1
- package/src/qingflow_mcp/tools/workspace_tools.py +14 -225
|
@@ -56,38 +56,18 @@ def build_builder_server() -> FastMCP:
|
|
|
56
56
|
feedback = FeedbackTools(backend, mcp_side="App Builder MCP")
|
|
57
57
|
|
|
58
58
|
@server.tool()
|
|
59
|
-
def
|
|
59
|
+
def auth_use_credential(
|
|
60
60
|
profile: str = DEFAULT_PROFILE,
|
|
61
61
|
base_url: str | None = None,
|
|
62
62
|
qf_version: str | None = None,
|
|
63
|
-
|
|
64
|
-
password: str = "",
|
|
65
|
-
persist: bool = True,
|
|
66
|
-
) -> dict:
|
|
67
|
-
return auth.auth_login(
|
|
68
|
-
profile=profile,
|
|
69
|
-
base_url=base_url,
|
|
70
|
-
qf_version=qf_version,
|
|
71
|
-
email=email,
|
|
72
|
-
password=password,
|
|
73
|
-
persist=persist,
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
@server.tool()
|
|
77
|
-
def auth_use_token(
|
|
78
|
-
profile: str = DEFAULT_PROFILE,
|
|
79
|
-
base_url: str | None = None,
|
|
80
|
-
qf_version: str | None = None,
|
|
81
|
-
token: str = "",
|
|
82
|
-
ws_id: int | None = None,
|
|
63
|
+
credential: str = "",
|
|
83
64
|
persist: bool = False,
|
|
84
65
|
) -> dict:
|
|
85
|
-
return auth.
|
|
66
|
+
return auth.auth_use_credential(
|
|
86
67
|
profile=profile,
|
|
87
68
|
base_url=base_url,
|
|
88
69
|
qf_version=qf_version,
|
|
89
|
-
|
|
90
|
-
ws_id=ws_id,
|
|
70
|
+
credential=credential,
|
|
91
71
|
persist=persist,
|
|
92
72
|
)
|
|
93
73
|
|
|
@@ -113,10 +93,6 @@ def build_builder_server() -> FastMCP:
|
|
|
113
93
|
include_external=include_external,
|
|
114
94
|
)
|
|
115
95
|
|
|
116
|
-
@server.tool()
|
|
117
|
-
def workspace_select(profile: str = DEFAULT_PROFILE, ws_id: int = 0) -> dict:
|
|
118
|
-
return workspace.workspace_select(profile=profile, ws_id=ws_id)
|
|
119
|
-
|
|
120
96
|
@server.tool()
|
|
121
97
|
def file_upload_local(
|
|
122
98
|
profile: str = DEFAULT_PROFILE,
|
|
@@ -191,38 +191,18 @@ If the current MCP capability is unsupported, the workflow is awkward, or the us
|
|
|
191
191
|
directory_tools = wrap_trimmed_methods(DirectoryTools(sessions, backend), USER_SERVER_METHOD_MAP)
|
|
192
192
|
|
|
193
193
|
@server.tool()
|
|
194
|
-
def
|
|
194
|
+
def auth_use_credential(
|
|
195
195
|
profile: str = DEFAULT_PROFILE,
|
|
196
196
|
base_url: str | None = None,
|
|
197
197
|
qf_version: str | None = None,
|
|
198
|
-
|
|
199
|
-
password: str = "",
|
|
200
|
-
persist: bool = True,
|
|
201
|
-
) -> dict:
|
|
202
|
-
return auth.auth_login(
|
|
203
|
-
profile=profile,
|
|
204
|
-
base_url=base_url,
|
|
205
|
-
qf_version=qf_version,
|
|
206
|
-
email=email,
|
|
207
|
-
password=password,
|
|
208
|
-
persist=persist,
|
|
209
|
-
)
|
|
210
|
-
|
|
211
|
-
@server.tool()
|
|
212
|
-
def auth_use_token(
|
|
213
|
-
profile: str = DEFAULT_PROFILE,
|
|
214
|
-
base_url: str | None = None,
|
|
215
|
-
qf_version: str | None = None,
|
|
216
|
-
token: str = "",
|
|
217
|
-
ws_id: int | None = None,
|
|
198
|
+
credential: str = "",
|
|
218
199
|
persist: bool = False,
|
|
219
200
|
) -> dict:
|
|
220
|
-
return auth.
|
|
201
|
+
return auth.auth_use_credential(
|
|
221
202
|
profile=profile,
|
|
222
203
|
base_url=base_url,
|
|
223
204
|
qf_version=qf_version,
|
|
224
|
-
|
|
225
|
-
ws_id=ws_id,
|
|
205
|
+
credential=credential,
|
|
226
206
|
persist=persist,
|
|
227
207
|
)
|
|
228
208
|
|
|
@@ -248,10 +228,6 @@ If the current MCP capability is unsupported, the workflow is awkward, or the us
|
|
|
248
228
|
include_external=include_external,
|
|
249
229
|
)
|
|
250
230
|
|
|
251
|
-
@server.tool()
|
|
252
|
-
def workspace_select(profile: str = DEFAULT_PROFILE, ws_id: int = 0) -> dict:
|
|
253
|
-
return workspace.workspace_select(profile=profile, ws_id=ws_id)
|
|
254
|
-
|
|
255
231
|
@server.tool()
|
|
256
232
|
def app_list(profile: str = DEFAULT_PROFILE) -> dict:
|
|
257
233
|
return apps.app_list(profile=profile)
|
|
@@ -29,6 +29,9 @@ class SessionProfile:
|
|
|
29
29
|
base_url: str
|
|
30
30
|
qf_version: str | None
|
|
31
31
|
qf_version_source: str | None
|
|
32
|
+
token: str | None
|
|
33
|
+
login_token: str | None
|
|
34
|
+
credential: str | None
|
|
32
35
|
uid: int
|
|
33
36
|
email: str | None
|
|
34
37
|
nick_name: str | None
|
|
@@ -45,6 +48,9 @@ class SessionProfile:
|
|
|
45
48
|
base_url=value["base_url"],
|
|
46
49
|
qf_version=value.get("qf_version"),
|
|
47
50
|
qf_version_source=value.get("qf_version_source"),
|
|
51
|
+
token=value.get("token"),
|
|
52
|
+
login_token=value.get("login_token"),
|
|
53
|
+
credential=value.get("credential"),
|
|
48
54
|
uid=value["uid"],
|
|
49
55
|
email=value.get("email"),
|
|
50
56
|
nick_name=value.get("nick_name"),
|
|
@@ -60,6 +66,7 @@ class SessionProfile:
|
|
|
60
66
|
class BackendSession:
|
|
61
67
|
token: str
|
|
62
68
|
login_token: str | None
|
|
69
|
+
credential: str | None
|
|
63
70
|
profile: str
|
|
64
71
|
base_url: str
|
|
65
72
|
qf_version: str | None
|
|
@@ -85,6 +92,7 @@ class SessionStore:
|
|
|
85
92
|
qf_version_source: str | None = None,
|
|
86
93
|
token: str,
|
|
87
94
|
login_token: str | None,
|
|
95
|
+
credential: str | None = None,
|
|
88
96
|
uid: int,
|
|
89
97
|
email: str | None,
|
|
90
98
|
nick_name: str | None,
|
|
@@ -99,14 +107,22 @@ class SessionStore:
|
|
|
99
107
|
self._set_secret(self._login_token_key(profile), login_token)
|
|
100
108
|
else:
|
|
101
109
|
self._delete_secret(self._login_token_key(profile))
|
|
110
|
+
if credential:
|
|
111
|
+
self._set_secret(self._credential_key(profile), credential)
|
|
112
|
+
else:
|
|
113
|
+
self._delete_secret(self._credential_key(profile))
|
|
102
114
|
else:
|
|
103
115
|
self._delete_secret(self._token_key(profile))
|
|
104
116
|
self._delete_secret(self._login_token_key(profile))
|
|
117
|
+
self._delete_secret(self._credential_key(profile))
|
|
105
118
|
session_profile = SessionProfile(
|
|
106
119
|
profile=profile,
|
|
107
120
|
base_url=normalize_base_url(base_url) or base_url,
|
|
108
121
|
qf_version=(str(qf_version).strip() or None) if qf_version is not None else None,
|
|
109
122
|
qf_version_source=(str(qf_version_source).strip() or None) if qf_version_source is not None else None,
|
|
123
|
+
token=str(token).strip() or None,
|
|
124
|
+
login_token=(str(login_token).strip() or None) if login_token is not None else None,
|
|
125
|
+
credential=(str(credential).strip() or None) if credential is not None else None,
|
|
110
126
|
uid=uid,
|
|
111
127
|
email=email,
|
|
112
128
|
nick_name=nick_name,
|
|
@@ -117,8 +133,9 @@ class SessionStore:
|
|
|
117
133
|
updated_at=now,
|
|
118
134
|
)
|
|
119
135
|
self._memory_sessions[profile] = BackendSession(
|
|
120
|
-
token=token,
|
|
121
|
-
login_token=login_token,
|
|
136
|
+
token=session_profile.token or token,
|
|
137
|
+
login_token=session_profile.login_token,
|
|
138
|
+
credential=session_profile.credential,
|
|
122
139
|
profile=profile,
|
|
123
140
|
base_url=session_profile.base_url,
|
|
124
141
|
qf_version=session_profile.qf_version,
|
|
@@ -146,14 +163,19 @@ class SessionStore:
|
|
|
146
163
|
memory_session.qf_version = session_profile.qf_version
|
|
147
164
|
memory_session.qf_version_source = session_profile.qf_version_source
|
|
148
165
|
return memory_session
|
|
149
|
-
if not session_profile
|
|
166
|
+
if not session_profile:
|
|
150
167
|
return None
|
|
151
|
-
token = self._get_secret(self._token_key(profile))
|
|
168
|
+
token = self._get_secret(self._token_key(profile)) if session_profile.persisted else None
|
|
169
|
+
if not token:
|
|
170
|
+
token = session_profile.token
|
|
152
171
|
if not token:
|
|
153
172
|
return None
|
|
173
|
+
login_token = self._get_secret(self._login_token_key(profile)) if session_profile.persisted else None
|
|
174
|
+
credential = self._get_secret(self._credential_key(profile)) if session_profile.persisted else None
|
|
154
175
|
backend_session = BackendSession(
|
|
155
176
|
token=token,
|
|
156
|
-
login_token=
|
|
177
|
+
login_token=login_token or session_profile.login_token,
|
|
178
|
+
credential=credential or session_profile.credential,
|
|
157
179
|
profile=profile,
|
|
158
180
|
base_url=session_profile.base_url,
|
|
159
181
|
qf_version=session_profile.qf_version,
|
|
@@ -234,6 +256,7 @@ class SessionStore:
|
|
|
234
256
|
self._logged_out_profiles.discard(profile)
|
|
235
257
|
self._delete_secret(self._token_key(profile))
|
|
236
258
|
self._delete_secret(self._login_token_key(profile))
|
|
259
|
+
self._delete_secret(self._credential_key(profile))
|
|
237
260
|
payload = self._load_profiles()
|
|
238
261
|
profiles = payload.get("profiles", {})
|
|
239
262
|
if profile in profiles:
|
|
@@ -249,6 +272,9 @@ class SessionStore:
|
|
|
249
272
|
def _login_token_key(self, profile: str) -> str:
|
|
250
273
|
return f"{profile}:login-token"
|
|
251
274
|
|
|
275
|
+
def _credential_key(self, profile: str) -> str:
|
|
276
|
+
return f"{profile}:credential"
|
|
277
|
+
|
|
252
278
|
def _upsert_profile(self, profile: SessionProfile) -> None:
|
|
253
279
|
payload = self._load_profiles()
|
|
254
280
|
payload.setdefault("profiles", {})[profile.profile] = asdict(profile)
|