Agent App MCP tool schema ignores Agent Soul app variables (required ones fail every tools/call)

オープン
#42,387 コメント 1 件 リアクション 1 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
68/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
python
領域
api, backend

調査の方向性

Start in controllers/mcp/mcp.py at MCPAppApi._get_user_input_form and trace how tools/list builds its schema from the legacy row. Compare it with AppDefinitionQueryService.get_public_parameters and the Agent Soul projection in services/app_service.py; done means tools/list exposes the declared variables, types, and required flags while preserving the existing query field.

索引モデルが issue の本文から書いたものです。

説明

Found while working on #42380 / #42383; this one is a different code path and is not fixed by that PR.

What happens

An Agent App can declare app variables on its Agent Soul (AgentSoulConfig.app_variables). When such an app is registered as an MCP server, tools/list never advertises them: the tool schema only has query. That part is observable today, independently of #42380.

The runtime does enforce those variables — AgentAppGenerator validates inputs against the Soul projection — so a required variable makes the call fail, and a schema-driven client has no way to discover the missing parameter:

{"jsonrpc": "2.0", "id": 1, "error": {"code": -32602, "message": "branch_id is required in input form"}}

On current main that error is masked by the call-path bug in #42380: tools/call fails earlier with "Agent App only supports streaming mode" (fixed by #42383). The schema gap is not masked — tools/list answers today, just without the declared variables.

Steps to reproduce
  1. Create an Agent App whose Soul declares branch_id (text-input, required). Today this is done through the console API or DSL import; the composer has no app-variables module yet.
  2. Register the app as an MCP server and call tools/list — the schema lists only query.
  3. Once the call path is fixed (#42383), call the tool without branch_id — the client gets the INVALID_PARAMS error above.

A client that already knows the variable name can still pass it, because prepare_tool_arguments copies unknown arguments into inputs. The failure is that the schema never reveals it.

Where it comes from

controllers/mcp/mcp.py::_get_user_input_form resolves the form for every non-workflow mode from the legacy row:

features_dict = app.app_model_config.to_dict()
raw_user_input_form = features_dict.get("user_input_form", [])

An Agent App's legacy row is created empty (services/app_service.py, the AppMode.AGENT branch): its model, prompt and variables live in the bound Agent Soul. The runtime projects the Soul instead — AgentAppConfigManager fills user_input_form from agent_app_variables_to_user_input_form(agent_soul.app_variables) — so the variable really is required by the time the tool call runs.

The rest of the platform already resolves this through the app-definition layer:

face resolver Soul variables visible
service API GET /parameters app_definitions.get_public_parameters -> _get_public_agent_parameter_config (published Soul) yes
webapp parameters (controllers/web/app.py) same yes
OpenAPI get app / input_schema controllers/openapi/_input_schema.py::resolve_app_config (legacy row) not reachable: SupportedAppType excludes the roster-owned agent type
MCP tools/list controllers/mcp/mcp.py::_get_user_input_form (legacy row) no
Executed evidence

Probing the real helpers (MCPAppApi._get_user_input_form, agent_app_variables_to_user_input_form, build_parameter_schema) and calling AgentAppGenerator._prepare_user_inputs directly, since a live tools/call on current main fails earlier for the reason above. Two DB-backed lookups are stubbed (the feature-row lookup, and the annotation-reply lookup inside AppModelConfig.to_dict):

1) what the Agent Soul declares, projected by the platform owner
    [{"text-input": {"label": "branch_id", "variable": "branch_id", "required": true}}]
2) what the MCP controller reads for the same Agent App
   raw form: []
3) the tool schema that reaches the MCP client
    {"type": "object", "properties": {"query": {"type": "string", "description": "User Input/Question content"}}, "required": ["query"]}
4) the schema the client would get with the projected form
    {"type": "object", "properties": {"query": {...}, "branch_id": {"description": "", "type": "string"}}, "required": ["query", "branch_id"]}
5) what the app requires when the tool call omits the variable
   -> ValueError: branch_id is required in input form
Expected behavior

tools/list advertises the Soul variables with their types and required flags, matching what the runtime enforces.

Fix direction

For AppMode.AGENT, _get_user_input_form could resolve the form through the app-definition owner (AppDefinitionQueryService.get_public_parameters, which returns user_input_form from the published Soul) instead of reading the legacy row. Two things to keep in mind:

  • that reader raises AppDefinitionNotPublishedError / AppDefinitionUnavailableError when the Agent has no active snapshot; MCP should surface that rather than answering with an empty form (note the MCP route renders MCPRequestError as an opaque HTTP 500 today — pre-existing for every validation error in that controller);
  • _convert_user_input_form already handles the form keys the projection emits (text-input, paragraph, number, checkbox).
Open question

For Agent Apps today, app variables are validated and passed to input moderation, but they do not reach the agent: AgentAppRuntimeRequestBuilder sends agent_soul_prompt / user_prompt and no variable layer, and the Agent App runner does not render a prompt template with them. So fixing the schema makes the advertised contract match the enforced one, but does not by itself let callers influence the run. That part belongs to #41779 (tool_input_bindings); worth deciding whether the schema fix should wait for it or land first as a bug fix.

Related

#41779 asks for application-controlled values bound to MCP tool parameters — a larger feature (per-tool bindings plus a composer UI for declaring variables). This issue is narrower: the MCP tool schema is built from the wrong source, so the declared variables never reach the client.

主要言語
TypeScript
スター
157k
フォーク
24.7k
平均マージ
22時間 32分
マージ済み PR(30日)
611

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

langgenius/dify のほかの issue

langgenius/dify の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。