SystemTce/dify-skills

Compétences d'intégration et d'extension pour Dify - Intégration API, protocole MCP, intégration de services externes

Qu'est-ce que dify-skills ?

Ce SKILL fournit un guide complet pour intégrer et étendre la plateforme Dify avec des systèmes et services externes. Il couvre trois domaines principaux : l'intégration via l'API REST complète de Dify (y compris les points de terminaison pour les messages de chat, les complétions, l'exécution de workflows, la gestion des paramètres et des fichiers), le protocole MCP (Model Context Protocol) pour une communication standardisée entre l'IA et les outils externes (avec des exemples d'implémentation de serveur et client MCP), et l'intégration de services externes comme les bases de données (PostgreSQL, MySQL, Redis), les services de stockage (S3/MinIO) et les files d'attente de messages (RabbitMQ, Kafka). Le document inclut des exemples de code détaillés en Python, des schémas de configuration YAML pour les workflows Dify, et des directives de dépannage. Ce SKILL est utile aux développeurs qui souhaitent connecter Dify à d'autres applications, automatiser des processus via des webhooks, ou étendre les capacités de Dify avec des outils MCP personnalisés, et il est spécifiquement conçu pour la plateforme Dify.

Compatible avec✓Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/SystemTce/dify-skills/tree/main/05-integration

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

SKILL d'intégration et d'extension Dify

Guide d'intégration avec les systèmes et services externes

Navigation rapide


Intégration API

Dify fournit une API REST complète, prenant en charge l'intégration d'applications et l'orchestration de workflows.

Points de terminaison API principaux

Point de terminaisonMéthodeDescription
/v1/chat-messagesPOSTEnvoyer un message de chat
/v1/completionsPOSTEnvoyer une demande de complétion
/v1/workflows/runPOSTExécuter un workflow
/v1/parametersGETObtenir les paramètres de l'application
/v1/file-uploadPOSTTéléchargement de fichier

Intégration API REST

import requests
import json

class DifyClient:
    def __init__(self, base_url: str, api_key: str):
        self.base_url = base_url.rstrip('/')
        self.headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json"
        }

    def chat_message(self, query: str, user: str, **kwargs):
        """Envoyer un message de chat"""
        payload = {
            "query": query,
            "user": user,
            **kwargs
        }
        response = requests.post(
            f"{self.base_url}/v1/chat-messages",
            headers=self.headers,
            json=payload
        )
        return response.json()

    def run_workflow(self, workflow_id: str, inputs: dict, user: str):
        """Exécuter un workflow"""
        payload = {
            "inputs": inputs,
            "user": user,
            "response_mode": "blocking"
        }
        response = requests.post(
            f"{self.base_url}/v1/workflows/run",
            headers=self.headers,
            json=payload
        )
        return response.json()

Exemple d'utilisation :

# Initialiser le client
client = DifyClient(
    base_url="https://api.dify.ai/v1",
    api_key="app-xxxxx"
)

# Envoyer un message de chat
result = client.chat_message(
    query="Bonjour",
    user="user123",
    conversation_id=None  # Nouvelle conversation
)
print(result)

Intégration Webhook

Les webhooks sont utilisés pour recevoir des notifications lors d'événements spécifiques, et prennent en charge le déclenchement de workflows et les rappels d'événements.

Déclenchement de workflow par Webhook

# Configuration du workflow
nodes:
  - id: webhook-trigger
    data:
      type: webhook-trigger
      method: POST
      path: /webhook/mon-workflow
      parameters:
        - name: data
          type: string
          required: true

Gestion des rappels Webhook

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/webhook/callback', methods=['POST'])
def handle_webhook():
    """Gérer un rappel Webhook Dify"""
    payload = request.json

    # Vérifier la signature
    signature = request.headers.get('X-Dify-Signature')
    if not verify_signature(payload, signature):
        return jsonify({"error": "Signature invalide"}), 401

    # Traiter l'événement
    event_type = payload.get('event')
    if event_type == 'workflow.finished':
        # Traitement de la fin du workflow
        result = payload.get('data', {}).get('output', {})
        process_result(result)

    return jsonify({"status": "succès"})

Types d'événements Webhook

ÉvénementDescriptionMoment du déclenchement
workflow.startedDébut du workflowAu démarrage du workflow
workflow.finishedFin du workflowLorsque le workflow se termine normalement
workflow.failedÉchec du workflowLorsque l'exécution du workflow échoue
node.startedDébut du nœudAu début de l'exécution du nœud
node.finishedFin du nœudLorsque le nœud termine son exécution

Réponses en continu

Prise en charge des Server-Sent Events (SSE) pour une sortie en continu en temps réel.

import requests
import json

def stream_chat(client: DifyClient, query: str, user: str):
    """Requête de chat en continu"""
    payload = {
        "query": query,
        "user": user,
        "response_mode": "streaming"
    }

    response = requests.post(
        f"{client.base_url}/v1/chat-messages",
        headers=client.headers,
        json=payload,
        stream=True
    )

    for line in response.iter_lines():
        if line:
            # Analyser le format SSE
            data = line.decode('utf-8')
            if data.startswith('data: '):
                event = json.loads(data[6:])
                yield event

# Exemple d'utilisation
for event in stream_chat(client, "Raconte une histoire", "user123"):
    if event.get('event') == 'message':
        print(event.get('data', {}).get('answer'), end='', flush=True)

Format de l'événement SSE :

{
  "event": "message",
  "task_id": "abc123",
  "message_id": "msg_xxx",
  "conversation_id": "conv_xxx",
  "answer": "Contenu du texte généré",
  "created_at": 1234567890
}

Protocole MCP

Model Context Protocol (MCP) est un protocole standardisé pour l'intégration des assistants IA avec les systèmes externes.

Implémentation du serveur MCP

Dify peut agir comme un serveur MCP, fournissant des outils et des ressources pour les appels IA.

from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
import asyncio

class DifyMCPServer:
    def __init__(self, dify_client: DifyClient):
        self.client = dify_client
        self.server = Server("dify-mcp")

    async def start(self):
        """Démarrer le serveur MCP"""
        @self.server.list_tools()
        async def list_tools() -> list[Tool]:
            return [
                Tool(
                    name="dify_chat",
                    description="Discuter avec l'application Dify",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "query": {"type": "string", "description": "Requête utilisateur"},
                            "user": {"type": "string", "description": "Identifiant utilisateur"}
                        },
                        "required": ["query", "user"]
                    }
                ),
                Tool(
                    name="dify_run_workflow",
                    description="Exécuter un workflow Dify",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "inputs": {"type": "object", "description": "Paramètres d'entrée du workflow"},
                            "user": {"type": "string", "description": "Identifiant utilisateur"}
                        },
                        "required": ["inputs", "user"]
                    }
                )
            ]

        @self.server.call_tool()
        async def call_tool(name: str, arguments: dict) -> list[TextContent]:
            if name == "dify_chat":
                result = self.client.chat_message(
                    query=arguments["query"],
                    user=arguments["user"]
                )
                return [TextContent(type="text", text=json.dumps(result))]
            elif name == "dify_run_workflow":
                result = self.client.run_workflow(
                    workflow_id=arguments.get("workflow_id", ""),
                    inputs=arguments["inputs"],
                    user=arguments["user"]
                )
                return [TextContent(type="text", text=json.dumps(result))]
            else:
                raise ValueError(f"Outil inconnu : {name}")

        # Démarrer le service
        await stdio_server(self.server.run())

# Exécuter le serveur
if __name__ == "__main__":
    client = DifyClient("https://api.dify.ai/v1", "app-xxxxx")
    server = DifyMCPServer(client)
    asyncio.run(server.start())

Implémentation du client MCP

Dify peut appeler des outils fournis par des serveurs MCP externes.

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
import asyncio

class DifyMCPClient:
    def __init__(self, server_command: str, server_args: list[str]):
        self.server_params = StdioServerParameters(
            command=server_command,
            args=server_args
        )

    async def call_tool(self, tool_name: str, arguments: dict):
        """Appeler un outil MCP"""
        async with stdio_client(self.server_params) as (read, write):
            async with ClientSession(read, write) as session:
                await session.initialize()
                result = await session.call_tool(tool_name, arguments)
                return result

# Exemple d'utilisation
async def main():
    client = DifyMCPClient(
        server_command="node",
        server_args=["mcp-server.js"]
    )
    result = await client.call_tool("get_weather", {"city": "Pékin"})
    print(result)

asyncio.run(main())

Configuration de la communication bidirectionnelle

Configuration d'un nœud MCP dans un workflow Dify :

nodes:
  - id: mcp-tool
    data:
      type: tool
      provider_type: mcp
      server_config:
        type: stdio
        command: python
        args: ["mcp_server.py"]
      tools:
        - name: search
          description: Outil de recherche
          input_schema:
            type: object
            properties:
              query:
                type: string

Intégration de services externes

Intégration de bases de données

PostgreSQL/MySQL

import psycopg2
from dify_plugin import Tool
from typing import Generator

class DatabaseTool(Tool):
    def _invoke(
        self,
        tool_parameters: dict
    ) -> Generator[ToolInvokeMessage, None, None]:
        # Obtenir les paramètres de connexion
        host = self.runtime_credentials.get("host")
        port = self.runtime_credentials.get("port")
        database = self.runtime_credentials.get("database")
        user = self.runtime_credentials.get("user")
        password = self.runtime_credentials.get("password")

        # Établir la connexion
        conn = psycopg2.connect(
            host=host,
            port=port,
            database=database,
            user=user,
            password=password
        )

        try:
            # Exécuter la requête
            query = tool_parameters.get("query")
            cursor = conn.cursor()
            cursor.execute(query)

            # Obtenir le résultat
            if query.strip().upper().startswith("SELECT"):
                columns = [desc[0] for desc in cursor.description]
                results = cursor.fetchall()
                yield self.create_json_message({
                    "columns": columns,
                    "data": results
                })
            else:
                conn.commit()
                yield self.create_text_message(f"lignes affectées : {cursor.rowcount}")
        finally:
            conn.close()

Redis

import redis
from dify_plugin import Tool

class RedisTool(Tool):
    def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
        r = redis.Redis(
            host=self.runtime_credentials.get("host"),
            port=self.runtime_credentials.get("port"),
            password=self.runtime_credentials.get("password"),
            db=self.runtime_credentials.get("db", 0)
        )

        operation = tool_parameters.get("operation")
        key = tool_parameters.get("key")

        if operation == "get":
            value = r.get(key)
            yield self.create_text_message(value.decode() if value else "")
        elif operation == "set":
            value = tool_parameters.get("value")
            r.set(key, value)
            yield self.create_text_message("OK")
        elif operation == "delete":
            r.delete(key)
            yield self.create_text_message("supprimé")

Intégration de services de stockage

S3/MinIO

import boto3
from dify_plugin import Tool

class S3Tool(Tool):
    def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
        s3 = boto3.client(
            's3',
            endpoint_url=self.runtime_credentials.get("endpoint"),
            aws_access_key_id=self.runtime_credentials.get("access_key"),
            aws_secret_access_key=self.runtime_credentials.get("secret_key")
        )

        operation = tool_parameters.get("operation")
        bucket = tool_parameters.get("bucket")
        key = tool_parameters.get("key")

        if operation == "upload":
            content = tool_parameters.get("content")
            s3.put_object(Bucket=bucket, Key=key, Body=content)
            yield self.create_text_message(f"Téléchargé vers {bucket}/{key}")
        elif operation == "download":
            response = s3.get_object(Bucket=bucket, Key=key)
            content = response['Body'].read()
            yield self.create_binary_message(content)
        elif operation == "list":
            response = s3.list_objects_v2(Bucket=bucket)
            keys = [obj['Key'] for obj in response.get('Contents', [])]
            yield self.create_json_message({"keys": keys})

Intégration de files d'attente de messages

RabbitMQ

import pika
from dify_plugin import Tool

class RabbitMQTool(Tool):
    def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
        credentials = pika.PlainCredentials(
            self.runtime_credentials.get("username"),
            self.runtime_credentials.get("password")
        )
        connection = pika.BlockingConnection(
            pika.ConnectionParameters(
                host=self.runtime_credentials.get("host"),
                port=self.runtime_credentials.get("port"),
                credentials=credentials
            )
        )
        channel = connection.channel()

        operation = tool_parameters.get("operation")
        queue = tool_parameters.get("queue")

        if operation == "publish":
            message = tool_parameters.get("message")
            channel.queue_declare(queue=queue, durable=True)
            channel.basic_publish(
                exchange='',
                routing_key=queue,
                body=message,
                properties=pika.BasicProperties(delivery_mode=2)
            )
            yield self.create_text_message("Message publié")
        elif operation == "consume":
            method, properties, body = channel.basic_get(queue=queue)
            if body:
                yield self.create_text_message(body.decode())
                channel.basic_ack(method.delivery_tag)
            else:
                yield self.create_text_message("Aucun message")

        connection.close()

Kafka

from kafka import KafkaProducer, KafkaConsumer
from dify_plugin import Tool
import json

class KafkaTool(Tool):
    def _invoke(self, tool_parameters: dict) -> Generator[ToolInvokeMessage, None, None]:
        operation = tool_parameters.get("operation")
        topic = tool_parameters.get("topic")

        if operation == "publish":
            message = tool_parameters.get("message")
            producer = KafkaProducer(
                bootstrap_servers=self.runtime_credentials.get("servers"),
                value_serializer=lambda v: json.dumps(v).encode('utf-8')
            )
            producer.send(topic, value={"message": message})
            producer.flush()
            producer.close()
            yield self.create_text_message("Message publié")

Individual skills in this repo

This repo contains 5 individual skills — each has its own dedicated page.

Skills associés