diff --git a/tools/generate-doap.sh b/tools/generate-doap.sh
new file mode 100755
index 000000000..dc3480e85
--- /dev/null
+++ b/tools/generate-doap.sh
@@ -0,0 +1,106 @@
+#!/bin/bash
+
+write_doap_head()
+{
+ cat >"$1" <<-'EOF'
+
+
+
+ ejabberd
+ XMPP Server with MQTT Broker and SIP Service
+ Robust, Ubiquitous and Massively Scalable Messaging Platform (XMPP Server, MQTT Broker, SIP Service)
+ 2002-11-16
+ BSD
+ Linux
+ macOS
+ Windows
+ Erlang
+ C
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+EOF
+}
+
+write_doap_tail()
+{
+ cat >>"$1" <<-'EOF'
+
+
+EOF
+}
+
+write_rfcs()
+{
+ rfc=rfc$1
+ out=$2
+ int=$(echo $1 | sed 's/^0*//')
+
+ imp=$(grep "\-protocol({rfc, $int," $BASE/src/* | sed "s/.*src\/\(.*\).erl.*'\([0-9.-]*\)'.*/\1 \2/")
+ [ "$imp" == "" ] && imp="NA 0.0"
+
+ echo " " >>$out
+}
+
+write_xeps()
+{
+ xep=xep-$1
+ out=$2
+ int=$(echo $1 | sed 's/^0*//')
+
+ imp=$(grep "\-protocol({xep, $int," $BASE/src/* | sed "s/.*src\/\(.*\).erl.*'\([0-9.-]*\)'.*/\1 \2/")
+ [ "$imp" == "" ] && imp="NA 0.0"
+
+ sourcefiles=$(grep "\-protocol({xep, $int," $BASE/src/* | sed "s/.*src\/\(.*\).erl.*'\([0-9.-]*\)'.*/\1/" | tr '\012' ',' | sed 's|,$||' | sed 's|,|, |g' | sed 's|^ejabberd$||')
+ versions=$(grep "\-protocol({xep, $int," $BASE/src/* | sed "s/.*src\/\(.*\).erl.*'\([0-9.-]*\)'.*/\2/" | head -1)
+
+ echo " " >>$out
+ echo " " >>$out
+ echo " " >>$out
+ echo " $versions" >>$out
+ echo " " >>$out
+ echo " " >>$out
+ echo " $sourcefiles" >>$out
+ echo " " >>$out
+ echo " " >>$out
+}
+
+[ $# -eq 1 ] && BASE="$1" || BASE="$PWD"
+[ -d $BASE/doc ] || mkdir $BASE/doc
+temp=tools/ejabberd.temp
+final=ejabberd.doap
+
+write_doap_head $final
+
+for x_num in $(grep "\-protocol({rfc" $BASE/src/* | sed "s/,//" | awk '{printf("%04d\n", $2)}' | sort -u)
+do
+ write_rfcs $x_num $temp
+done
+echo "" >>$temp
+
+for x_num in $(grep "\-protocol({xep" $BASE/src/* | sed "s/,//" | awk '{printf("%04d\n", $2)}' | sort -u)
+do
+ write_xeps $x_num $temp
+done
+
+cat $temp >>$final
+rm $temp
+
+write_doap_tail $final