SystemTce/dify-skills

Habilidades de integração e extensão do Dify - Integração de API, Protocolo MCP, Integração de Serviços Externos

O que é dify-skills?

Este skill fornece um guia abrangente para integrar e estender o Dify com sistemas e serviços externos. Ele cobre a integração via API REST, incluindo chamadas síncronas e streaming com Server-Sent Events (SSE), além de webhooks para disparo e callback de workflows. O destaque é a implementação completa do protocolo MCP (Model Context Protocol), permitindo que o Dify atue tanto como servidor, expondo ferramentas e recursos para assistentes de IA, quanto como cliente, invocando ferramentas de servidores MCP externos. Além disso, o skill inclui exemplos práticos de integração com bancos de dados como PostgreSQL e Redis, serviços de armazenamento como S3/MinIO e filas de mensagens como RabbitMQ e Kafka, usando a estrutura de plugins do Dify. É ideal para desenvolvedores que desejam conectar o Dify a qualquer sistema, criando workflows poderosos e flexíveis com suporte a Claude Code, Cursor, Codex e outras plataformas.

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

Installed? Explore more Programação e Desenvolvimento skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Habilidade de Integração e Extensão do Dify

Guia de integração com sistemas e serviços externos

Navegação Rápida


Integração de API

O Dify fornece uma API REST completa, suportando integração de aplicativos e orquestração de workflows.

Endpoints Principais da API

EndpointMétodoDescrição
/v1/chat-messagesPOSTEnviar mensagens de chat
/v1/completionsPOSTEnviar requisições de completude
/v1/workflows/runPOSTExecutar workflow
/v1/parametersGETObter parâmetros do aplicativo
/v1/file-uploadPOSTUpload de arquivo

Integração com 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):
        """Envia uma mensagem 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):
        """Executa um 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()

Exemplo de uso:

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

# Envia uma mensagem de chat
result = client.chat_message(
    query="Olá",
    user="user123",
    conversation_id=None  # Nova conversa
)
print(result)

Integração com Webhook

Webhooks são usados para receber notificações quando eventos específicos ocorrem, suportando disparo de workflows e callbacks de eventos.

Disparo de Workflow via Webhook

# Configuração do workflow
nodes:
  - id: webhook-trigger
    data:
      type: webhook-trigger
      method: POST
      path: /webhook/my-workflow
      parameters:
        - name: data
          type: string
          required: true

Tratamento de Callback Webhook

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/webhook/callback', methods=['POST'])
def handle_webhook():
    """Processa callback do Webhook do Dify"""
    payload = request.json

    # Verifica assinatura
    signature = request.headers.get('X-Dify-Signature')
    if not verify_signature(payload, signature):
        return jsonify({"error": "Assinatura inválida"}), 401

    # Processa evento
    event_type = payload.get('event')
    if event_type == 'workflow.finished':
        # Tratamento de conclusão de workflow
        result = payload.get('data', {}).get('output', {})
        process_result(result)

    return jsonify({"status": "success"})

Tipos de Evento Webhook

EventoDescriçãoMomento do Disparo
workflow.startedWorkflow iniciadoQuando o workflow é iniciado
workflow.finishedWorkflow concluídoQuando o workflow termina normalmente
workflow.failedWorkflow falhouQuando a execução do workflow falha
node.startedNó iniciadoQuando um nó começa a executar
node.finishedNó concluídoQuando a execução de um nó termina

Resposta em Streaming

Suporta Server-Sent Events (SSE) para saída em tempo real.

import requests
import json

def stream_chat(client: DifyClient, query: str, user: str):
    """Requisição de chat em streaming"""
    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:
            # Analisa formato SSE
            data = line.decode('utf-8')
            if data.startswith('data: '):
                event = json.loads(data[6:])
                yield event

# Exemplo de uso
for event in stream_chat(client, "Conte uma história", "user123"):
    if event.get('event') == 'message':
        print(event.get('data', {}).get('answer'), end='', flush=True)

Formato do Evento SSE:

{
  "event": "message",
  "task_id": "abc123",
  "message_id": "msg_xxx",
  "conversation_id": "conv_xxx",
  "answer": "Conteúdo do texto gerado",
  "created_at": 1234567890
}

Protocolo MCP

Model Context Protocol (MCP) é um protocolo padronizado para integração de assistentes de IA com sistemas externos.

Implementação do Servidor MCP

O Dify pode atuar como um Servidor MCP, fornecendo ferramentas e recursos para serem chamados pela 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):
        """Inicia o Servidor MCP"""
        @self.server.list_tools()
        async def list_tools() -> list[Tool]:
            return [
                Tool(
                    name="dify_chat",
                    description="Conversa com o aplicativo Dify",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "query": {"type": "string", "description": "Consulta do usuário"},
                            "user": {"type": "string", "description": "Identificador do usuário"}
                        },
                        "required": ["query", "user"]
                    }
                ),
                Tool(
                    name="dify_run_workflow",
                    description="Executa um workflow do Dify",
                    inputSchema={
                        "type": "object",
                        "properties": {
                            "inputs": {"type": "object", "description": "Parâmetros de entrada do workflow"},
                            "user": {"type": "string", "description": "Identificador do usuário"}
                        },
                        "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"Ferramenta desconhecida: {name}")

        # Inicia o serviço
        await stdio_server(self.server.run())

# Executa o servidor
if __name__ == "__main__":
    client = DifyClient("https://api.dify.ai/v1", "app-xxxxx")
    server = DifyMCPServer(client)
    asyncio.run(server.start())

Implementação do Cliente MCP

O Dify pode chamar ferramentas fornecidas por um Servidor MCP externo.

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):
        """Chama uma ferramenta 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

# Exemplo de uso
async def main():
    client = DifyMCPClient(
        server_command="node",
        server_args=["mcp-server.js"]
    )
    result = await client.call_tool("get_weather", {"city": "Pequim"})
    print(result)

asyncio.run(main())

Configuração de Comunicação Bidirecional

Configure um nó MCP em um workflow do 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: Ferramenta de busca
          input_schema:
            type: object
            properties:
              query:
                type: string

Integração de Serviços Externos

Integração com Banco de Dados

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]:
        # Obtém parâmetros de conexão
        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")

        # Estabelece conexão
        conn = psycopg2.connect(
            host=host,
            port=port,
            database=database,
            user=user,
            password=password
        )

        try:
            # Executa consulta
            query = tool_parameters.get("query")
            cursor = conn.cursor()
            cursor.execute(query)

            # Obtém resultados
            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"linhas afetadas: {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("deletado")

Integração com Serviço de Armazenamento

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"Enviado para {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})

Integração com Fila de Mensagens

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("Mensagem publicada")
        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("Nenhuma mensagem")

        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("Mensagem publicada")
        elif operation == "consume":
            consumer = KafkaConsumer(
                topic,
                bootstrap_servers=self.runtime_credentials.get("servers"),
                auto_offset_reset='earliest',
                consumer_timeout_ms=5000
            )
            messages = []
            for msg in consumer:
                messages.append({
                    "value": msg.value.decode('utf-8'),
                    "key": msg.key.decode('utf-8') if msg.key else None,
                    "offset": msg.offset
                })
            consumer.close()
            yield self.create_json_message({"messages": messages})

Casos de Integração

Assistente Inteligente com Banco de Dados

Integre dados empresariais com um assistente de IA do Dify:

# Configuração do workflow
nodes:
  - id: user-query
    type: start
    data:
      inputs:
        - name: question
          type: string
          required: true

  - id: database-lookup
    type: tool
    data:
      provider: database
      tool: DatabaseTool
      inputs:
        query: |-
          SELECT * FROM products
          WHERE description ILIKE '%{{question}}%'

  - id: generate-response
    type: llm
    data:
      prompt: |-
        Dados da consulta:
        {{#database-lookup.output#}}
        
        Com base nos dados acima, responda: {{question}}

Pipeline de Processamento de Arquivos

Use armazenamento em nuvem e filas para construir um pipeline:

nodes:
  - id: file-upload
    type: tool
    data:
      provider: s3
      tool: S3Tool
      inputs:
        operation: upload
        bucket: uploads
        key: "{{$context.date}}/{{$context.file.name}}"

  - id: send-task
    type: tool
    data:
      provider: rabbitmq
      tool: RabbitMQTool
      inputs:
        operation: publish
        queue: file-processing
        message: |-
          {
            "bucket": "uploads",
            "key": "{{file-upload.output.key}}",
            "timestamp": "{{$context.date}}"
          }

Configuração de Ferramentas MCP

Conecte-se a ferramentas MCP externas:

nodes:
  - id: mcp-search
    type: tool
    data:
      provider_type: mcp
      server_config:
        type: stdio
        command: python
        args: ["mcp_search_server.py"]
      tools:
        - name: web_search
          inputs:
            query: "{{user_query}}"
            max_results: 5

Solução de Problemas

ProblemaCausa PossívelSolução
Falha na conexão da APIChave de API incorretaVerifique a chave de API e as permissões
Timeout do WebhookRede instávelAumente o tempo limite ou adicione mecanismo de retry
Ferramenta MCP não encontradaNome da ferramenta incorretoVerifique a lista de ferramentas do servidor MCP
Conexão com banco de dados recusadaConfiguração de segurança incorretaVerifique a lista de permissões de IP e as configurações de firewall

Problemas Comuns

Erro na Integração de API

erro: requests.exceptions.ConnectionError
solução: Verifique se a URL de API está correta e se a rede está acessível

Falha no Webhook

{
  "error": "Assinatura inválida",
  "solution": "Verifique se o token do Webhook está configurado e passado corretamente"
}

Problema no MCP

# erro: mcp.client.session.McpError: Ferramenta não encontrada
# solução: Confirme que o nome da ferramenta no servidor MCP corresponde ao nome usado na chamada

Depuração

Ative logs detalhados para depuração:

import logging
logging.basicConfig(level=logging.DEBUG)

# Inicia o servidor MCP com logs
server = DifyMCPServer(client)
logging.debug("Servidor MCP iniciado")

Licença

Este skill está sob a licença MIT. Consulte o arquivo LICENSE para mais detalhes.

Individual skills in this repo

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

Habilidades Relacionadas