MCP Tool Integration#
When a Dify app is published as an MCP server, Dify dynamically generates a JSON Schemaβbased inputSchema for the tool by converting the app's user_input_form variable list. The core logic lives in api/core/mcp/server/streamable_http.py β specifically in convert_input_form_to_parameters() and build_parameter_schema().
Variable Type Mapping#
convert_input_form_to_parameters() iterates user_input_form and maps each VariableEntity to a JSON Schema property:
| Dify Variable Type | JSON Schema Type | Notes |
|---|---|---|
text-input, paragraph | "string" | Plain string field |
select | "string" with "enum" | item.options list included as enum values |
number | "number" | |
checkbox | "boolean" | |
json-object | "object" | If item.json_schema is set, properties, required, and additionalProperties keys are forwarded directly |
file, file_list, external_data_tool | (skipped) | Not representable over MCP; silently omitted |
Variable descriptions come from mcp_server.parameters_dict (a dict[str, str] keyed by variable name). If a variable was added after the MCP server was last saved, its description defaults to an empty string rather than raising an error .
Required fields are collected from item.required and passed into the JSON Schema "required" array .
App-Mode Schema Differences#
build_parameter_schema() applies the converted parameters differently based on AppMode:
WORKFLOWandCOMPLETIONβinputSchemacontains only the declared input variables .CHAT,ADVANCED_CHAT,AGENT_CHATβ a required"query"string parameter ("User Input/Question content") is prepended to the schema; all other variables follow as additional fields ."query"is always required.
Argument routing in prepare_tool_arguments() mirrors this:
WORKFLOWβ{"inputs": <all arguments>}COMPLETIONβ{"query": "", "inputs": <all arguments>}- Chat modes β
queryis popped from arguments; remainder goes intoinputs
Tool Registration (tools/list)#
handle_list_tools() assembles the Tool object returned to MCP clients:
nameβ the Dify app namedescriptionβ frommcp_server.descriptioninputSchemaβ the output ofbuild_parameter_schema()abovetitle/outputSchemaβ set only for protocol2025-06-18+ clients; stripped viaexclude_noneserialization for older clients
The Tool Pydantic model is defined in api/core/mcp/types.py and includes name, title, description, inputSchema, outputSchema, and annotations fields.
Support Constraints#
| Constraint | Detail |
|---|---|
| File inputs unsupported | FILE, FILE_LIST, EXTERNAL_DATA_TOOL variable types cannot be transmitted over the MCP JSON-RPC interface and are silently skipped |
| One tool per server | Each MCP server exposes exactly one tool (the bound Dify app) β ListToolsResult always returns a single-element tools list |
json-object schema passthrough | Only properties, required, and additionalProperties are forwarded from the Dify variable's json_schema; other JSON Schema keywords are dropped |
| Active server required | Only servers with status = active accept requests; inactive servers are rejected at the HTTP controller layer |
Key Source Files#
| File | Purpose |
|---|---|
api/core/mcp/server/streamable_http.py | Variable-to-schema conversion, tool schema assembly, tools/list and tools/call handlers |
api/core/mcp/types.py | Tool, ListToolsResult, CallToolResult Pydantic models |
api/controllers/mcp/mcp.py | HTTP entry point; extracts user_input_form and routes to handle_mcp_request() |
api/models/model.py | AppMCPServer DB model; parameters JSON field (variable name β description map) |