# How MCP Prompts Are Converted into Callable Tools with Argument Validation in Dify

> Discover how Dify converts MCP prompts into callable tools with automatic argument validation. Learn how JSON Schema ensures input accuracy before prompt execution.

- Repository: [Junjie.M/dify-plugin-tools-mcp_sse](https://github.com/junjiem/dify-plugin-tools-mcp_sse)
- Tags: how-to-guide
- Published: 2026-03-05

---

**MCP prompt templates are dynamically converted into callable tools by generating JSON Schema definitions from declared arguments, prefixing tool names with `prompt__`, and enforcing input validation against that schema before executing the prompt on the MCP server.**

The junjiem/dify-plugin-tools-mcp_sse plugin enables Dify agents to interact with MCP servers that expose prompt templates. When configured to treat prompts as tools, the plugin converts MCP prompts into callable tools with automatic argument validation, allowing LLMs to invoke structured prompt templates using standard tool-calling semantics.

## Enabling Prompt-to-Tool Conversion in McpClients

The conversion process begins when the `McpClients` class is instantiated with the `prompts_as_tools` parameter set to `True`. This flag signals the client to fetch prompt definitions from connected MCP servers and transform them into tool-compatible structures.

Located in [`utils/mcp_client.py`](https://github.com/junjiem/dify-plugin-tools-mcp_sse/blob/main/utils/mcp_client.py), the `McpClients` class manages server connections and tool discovery. When `fetch_tools()` is invoked, it iterates through configured servers and, if `prompts_as_tools` is enabled, calls `client.list_prompts()` to retrieve available prompt templates alongside standard tools.

## Fetching and Transforming MCP Prompt Definitions

For each prompt returned by the MCP server, the plugin constructs a synthetic tool definition that conforms to Dify's tool interface. This transformation occurs within the `fetch_tools` method and involves three critical steps: schema generation, namespacing, and action classification.

### Generating JSON Schema from Prompt Arguments

The plugin inspects each prompt's declared arguments to build a JSON Schema that Dify uses for input validation. For every argument in the prompt's `arguments` list, the plugin creates a property with `type: "string"` and includes the argument description.

If the MCP server marks an argument as required, the plugin adds the argument name to the schema's `required` array. This schema is embedded in the tool's `inputSchema` field, enabling Dify's tool registry to validate incoming arguments before execution.

```python

# utils/mcp_client.py – schema construction logic

properties = {}
required = []
for arg in prompt.get("arguments", []):
    properties[arg["name"]] = {
        "type": "string",
        "description": arg.get("description", ""),
    }
    if arg.get("required", False):
        required.append(arg["name"])

tool = {
    "name": name,
    "description": f"Use the prompt template '{prompt['name']}' from MCP Server.",
    "inputSchema": {
        "type": "object",
        "properties": properties,
        "required": required,
    },
}

```

### Namespacing and ActionType Classification

To prevent naming collisions between prompts and standard tools, the plugin prefixes each prompt-based tool with `prompt__`. For example, a prompt named `summarize_article` becomes `prompt__summarize_article`. If collisions persist across multiple servers, the server name is prepended as well (e.g., `serverName__prompt__summarize_article`).

Each synthesized tool is stored in the internal `_tool_actions` dictionary as a `ToolAction` object with `action_type` set to `ActionType.PROMPT`. This classification distinguishes prompt invocations from standard tool calls during execution.

## Argument Validation and Tool Execution

Once registered, prompt-based tools follow the same execution pipeline as standard tools, with validation occurring before the MCP server is contacted.

### Schema Validation Before RPC Calls

When the LLM invokes a prompt-based tool, Dify's tool registry validates the provided arguments against the JSON Schema generated during the fetch phase. This validation occurs before `McpClients.execute_tool` is called, ensuring that missing required fields or type mismatches trigger an immediate error without consuming MCP server resources.

If validation passes, `execute_tool` retrieves the stored `ToolAction` and dispatches the call based on the `action_type`.

### Executing Prompts via get_prompt()

For prompt actions, the execution path invokes `client.get_prompt()` with the original prompt name and the validated arguments. The MCP server renders the prompt template using the provided arguments and returns a list of chat-style messages.

The plugin concatenates these messages into a single text block, prefixing each with its role (e.g., `assistant:`, `user:`), and returns the result to Dify as a standard tool response.

```python

# utils/mcp_client.py – prompt execution path

elif action_type == ActionType.PROMPT:
    prompt = tool_action.action_feature
    messages = client.get_prompt(prompt["name"], tool_args)
    text = ""
    for message in messages:
        role = message["role"]
        content = message["content"]
        text += f"{role}: {content.get('text', str(content))}\n"
    tool_contents.append({"type": "text", "text": text.strip()})

```

## Complete Implementation Example

The following example demonstrates initializing the MCP client with prompt-to-tool conversion enabled, retrieving the generated tool catalog, and invoking a prompt-based tool with automatic argument validation.

```python
from utils.mcp_client import McpClients

# Initialize client with prompt-to-tool conversion enabled

clients = McpClients(
    servers_config={
        "exampleSrv": {"url": "http://mcp.example.com", "transport": "sse"}
    },
    prompts_as_tools=True,  # Enable conversion

)

# Fetch tools including synthesized prompt tools

tool_catalog = clients.fetch_tools()
print([t["name"] for t in tool_catalog if t["name"].startswith("prompt__")])

# Output: ['prompt__summarize_article', 'prompt__create_summary']

# Execute a prompt-based tool with validated arguments

result = clients.execute_tool(
    "prompt__summarize_article",
    {"url": "https://example.com/article", "length": "short"}
)
print(result[0]["text"])

# Output: "assistant: Here is a short summary of the article …"

```

If a required argument is omitted, Dify's validation layer raises an error before the MCP server is contacted:

```text
ToolError: Argument validation failed – missing required property "url".

```

## Summary

- **Enable conversion** by setting `prompts_as_tools=True` when instantiating `McpClients` in [`utils/mcp_client.py`](https://github.com/junjiem/dify-plugin-tools-mcp_sse/blob/main/utils/mcp_client.py).
- **Automatic schema generation** creates JSON Schema definitions from prompt arguments, marking required fields based on the MCP server's declarations.
- **Namespacing** prevents collisions by prefixing prompt tools with `prompt__` and optionally the server name.
- **Pre-execution validation** ensures arguments conform to the schema before RPC calls are made to the MCP server.
- **Execution flow** maps tool calls to `client.get_prompt()`, rendering the template server-side and returning concatenated messages to the LLM.

## Frequently Asked Questions

### How does the plugin prevent naming conflicts between prompts and standard tools?

The plugin prefixes every prompt-based tool with `prompt__` during the conversion process. If a name collision still occurs across multiple MCP servers, it prepends the server name to create a unique identifier (e.g., `serverName__prompt__prompt_name`). This ensures that prompt tools remain distinct from standard MCP tools and from each other.

### What happens if an argument fails validation?

Dify's tool registry validates incoming arguments against the JSON Schema generated when the prompt was converted into a tool. If a required argument is missing or a type mismatch occurs, the validation fails immediately and raises a `ToolError` before `McpClients.execute_tool` invokes the MCP server. This prevents malformed requests from consuming server resources or producing invalid prompt renders.

### Can prompts with no arguments be converted into tools?

Yes. When a prompt has no declared arguments, the plugin generates an empty `properties` dictionary and an empty `required` array in the JSON Schema. The resulting tool accepts an empty argument object `{}` and executes the prompt template without parameters when invoked, returning the static or server-rendered content to the LLM.

### Where is the prompt execution logic located?

The execution logic resides in the `execute_tool` method of the `McpClients` class within [`utils/mcp_client.py`](https://github.com/junjiem/dify-plugin-tools-mcp_sse/blob/main/utils/mcp_client.py). When the `action_type` is `ActionType.PROMPT`, the method calls `client.get_prompt()` with the prompt name and validated arguments, then processes the returned message list into a text response for Dify.