diff --git a/examples/emcute/Makefile b/examples/emcute/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..a8b49a81d7647696177751d538c119313a762cdc
--- /dev/null
+++ b/examples/emcute/Makefile
@@ -0,0 +1,44 @@
+# name of your application
+APPLICATION = emcute
+
+# If no BOARD is found in the environment, use this default:
+BOARD ?= native
+
+# This has to be the absolute path to the RIOT base directory:
+RIOTBASE ?= $(CURDIR)/../..
+
+BOARD_INSUFFICIENT_MEMORY := arduino-duemilanove arduino-mega2560 arduino-uno \
+                             chronos msb-430 msb-430h nucleo-f030 nucleo-f070 \
+                             nucleo-f072 nucleo-f334 nucleo32-f031 nucleo32-f303 \
+                             nucleo32-f042 stm32f0discovery telosb \
+                             waspmote-pro weio wsn430-v1_3b wsn430-v1_4 z1
+
+# Include packages that pull up and auto-init the link layer.
+# NOTE: 6LoWPAN will be included if IEEE802.15.4 devices are present
+USEMODULE += gnrc_netdev_default
+USEMODULE += auto_init_gnrc_netif
+# Specify the mandatory networking modules for IPv6 and UDP
+USEMODULE += gnrc_sock_udp
+USEMODULE += gnrc_ipv6_default
+# Include MQTT-SN
+USEMODULE += emcute
+# Add also the shell, some shell commands
+USEMODULE += shell
+USEMODULE += shell_commands
+USEMODULE += ps
+# For testing we also include the ping6 command and some stats
+USEMODULE += gnrc_icmpv6_echo
+
+# Comment this out to disable code in RIOT that does safety checking
+# which is not needed in a production environment but helps in the
+# development process:
+CFLAGS += -DDEVELHELP
+
+# Comment this out to join RPL DODAGs even if DIOs do not contain
+# DODAG Configuration Options (see the doc for more info)
+# CFLAGS += -DGNRC_RPL_DODAG_CONF_OPTIONAL_ON_JOIN
+
+# Change this to 0 show compiler invocation lines by default:
+QUIET ?= 1
+
+include $(RIOTBASE)/Makefile.include
diff --git a/examples/emcute/README.md b/examples/emcute/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..9493646339740b8159e9c287ac130703e674ec7e
--- /dev/null
+++ b/examples/emcute/README.md
@@ -0,0 +1,97 @@
+## About
+This application demonstrates the usage of the emCute (MQTT-SN) module in RIOT.
+
+## Setup
+For using this example, two prerequisites have to be fullfilled:
+
+1. You need a running MQTT broker that supports MQTT-SN or a running MQTT-SN
+   gateway that is connected to a running MQTT broker
+2. Your RIOT node needs to be able to speak to that broker/gateway
+
+
+### Setting up a broker
+In general, any MQTT-SN capable broker or broker/gateway setup will do.
+Following a quick instruction on how-to setup the Mosquitto Real Simple Message
+Broker:
+
+1. Get the RSMB here: https://github.com/eclipse/mosquitto.rsmb:
+```
+git clone https://github.com/eclipse/mosquitto.rsmb.git
+```
+
+2. Go into the source folder and build the RSMB
+```
+cd mosquitto.rsmb/rsmb/src
+make
+```
+
+3. Create a config file. In this case we run the RSMB as MQTT and MQTT-SN
+   capable broker, using port 1885 for MQTT-SN and 1886 for MQTT and enabling
+   IPv6, so save the following to `config.conf`:
+```
+# add some debug output
+trace_output protocol
+
+# listen for MQTT-SN traffic on UDP port 1885
+listener 1885 INADDR_ANY mqtts
+  ipv6 true
+
+# listen to MQTT connections on tcp port 1886
+listener 1886 INADDR_ANY
+  ipv6 true
+```
+
+4. Start the broker:
+```
+./broker_mqtts config.conf
+```
+
+You can refer to
+https://rawgit.com/MichalFoksa/rsmb/master/rsmb/doc/gettingstarted.htm for more
+configuration options.
+
+
+### Setting up RIOT `native`
+When running this example under native, we must configure some global addresses,
+as the RSMB doesn't seems to be able to handle link-local addresses. So for a
+single RIOT native instance, we can do the following:
+
+1. Setup `tap` and `tabbr` devices using RIOT's `tapsetup` script:
+```
+./RIOTDIR/dist/tools/tapsetup/tapsetup
+```
+
+2. Assign a site-global prefix to the `tabbr0` interface (the name could be
+   different on OSX etc):
+```
+sudo ip a a fec0:affe::1/64 dev tapbr0
+```
+
+3. Assign a site-global address with the same prefix to the RIOT `native`
+   instance:
+```
+ifconfig 5 add fec0:affe::99
+```
+
+
+## Usage
+This example maps all available MQTT-SN functions to shell commands. Simply type
+`help` to see the available commands. The most important steps are explained
+below:
+
+- To connect to a broker, use the `con` command:
+```
+con fec0:affe::1 1885
+```
+
+- To subscribe to a topic, run `sub` with the topic name as parameter, e.g.
+```
+sub hello/world
+```
+
+- For publishing, use the `pub` command:
+```
+pub hello/world "One more beer, please."
+```
+
+That's it, happy publishing!
diff --git a/examples/emcute/main.c b/examples/emcute/main.c
new file mode 100644
index 0000000000000000000000000000000000000000..9184a8c1074b21a97e38b1d4c096aa42970c71bd
--- /dev/null
+++ b/examples/emcute/main.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2015 Freie Universität Berlin
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/**
+ * @ingroup     examples
+ * @{
+ *
+ * @file
+ * @brief       Example application for demonstrating the RIOT network stack
+ *
+ * @author      Hauke Petersen <hauke.petersen@fu-berlin.de>
+ *
+ * @}
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "shell.h"
+#include "msg.h"
+#include "net/emcute.h"
+#include "net/ipv6/addr.h"
+
+#define EMCUTE_PORT         (1883U)
+#define EMCUTE_ID           ("gertrud")
+#define EMCUTE_PRIO         (THREAD_PRIORITY_MAIN - 1)
+
+#define NUMOFSUBS           (16U)
+#define TOPIC_MAXLEN        (64U)
+
+static char stack[THREAD_STACKSIZE_DEFAULT];
+static msg_t queue[8];
+
+static emcute_sub_t subscriptions[NUMOFSUBS];
+static char topics[NUMOFSUBS][TOPIC_MAXLEN];
+
+static void *emcute_thread(void *arg)
+{
+    (void)arg;
+    emcute_run(EMCUTE_PORT, EMCUTE_ID);
+    return NULL;    /* should never be reached */
+}
+
+static void on_pub(const emcute_topic_t *topic, void *data, size_t len)
+{
+    char *in = (char *)data;
+
+    printf("### got publication for topic '%s' [%i] ###\n",
+           topic->name, (int)topic->id);
+    for (size_t i = 0; i < len; i++) {
+        printf("%c", in[i]);
+    }
+    puts("");
+}
+
+static unsigned get_qos(const char *str)
+{
+    int qos = atoi(str);
+    switch (qos) {
+        case 1:     return EMCUTE_QOS_1;
+        case 2:     return EMCUTE_QOS_2;
+        default:    return EMCUTE_QOS_0;
+    }
+}
+
+static int cmd_con(int argc, char **argv)
+{
+    sock_udp_ep_t gw = { .family = AF_INET6, .port = EMCUTE_PORT };
+    char *topic = NULL;
+    char *message = NULL;
+    size_t len = 0;
+
+    if (argc < 2) {
+        printf("usage: %s <ipv6 addr> [port] [<will topic> <will message>]\n",
+                argv[0]);
+        return 1;
+    }
+
+    /* parse address */
+    if (ipv6_addr_from_str((ipv6_addr_t *)&gw.addr.ipv6, argv[1]) == NULL) {
+        printf("error parsing IPv6 address\n");
+        return 1;
+    }
+
+    if (argc >= 3) {
+        gw.port = (uint16_t)atoi(argv[2]);
+    }
+    if (argc >= 5) {
+        topic = argv[3];
+        message = argv[4];
+        len = strlen(message);
+    }
+
+    if (emcute_con(&gw, true, topic, message, len, 0) != EMCUTE_OK) {
+        printf("error: unable to connect to [%s]:%i\n", argv[1], (int)gw.port);
+    }
+    printf("Successfully connected to gateway at [%s]:%i\n",
+           argv[1], (int)gw.port);
+
+    return 0;
+}
+
+static int cmd_discon(int argc, char **argv)
+{
+    (void)argc;
+    (void)argv;
+
+    int res = emcute_discon();
+    if (res == EMCUTE_NOGW) {
+        puts("error: not connected to any broker");
+        return 1;
+    }
+    else if (res != EMCUTE_OK) {
+        puts("error: unable to disconnect");
+        return 1;
+    }
+    puts("Disconnect successful");
+    return 0;
+}
+
+static int cmd_pub(int argc, char **argv)
+{
+    emcute_topic_t t;
+    unsigned flags = EMCUTE_QOS_0;
+
+    if (argc < 3) {
+        printf("usage: %s <topic name> <data> [QoS level]\n", argv[0]);
+        return 1;
+    }
+
+    /* parse QoS level */
+    if (argc >= 4) {
+        flags |= get_qos(argv[3]);
+    }
+
+    printf("pub with topic: %s and name %s and flags 0x%02x\n", argv[1], argv[2], (int)flags);
+
+    /* step 1: get topic id */
+    t.name = argv[1];
+    if (emcute_reg(&t) != EMCUTE_OK) {
+        puts("error: unable to obtain topic ID");
+        return 1;
+    }
+
+    /* step 2: publish data */
+    if (emcute_pub(&t, argv[2], strlen(argv[2]), flags) != EMCUTE_OK) {
+        printf("error: unable to publish data to topic '%s [%i]'\n",
+                t.name, (int)t.id);
+        return 1;
+    }
+
+    printf("Published %i bytes to topic '%s [%i]'\n",
+            (int)strlen(argv[2]), t.name, t.id);
+
+    return 0;
+}
+
+static int cmd_sub(int argc, char **argv)
+{
+    unsigned flags = EMCUTE_QOS_0;
+
+    if (argc < 2) {
+        printf("usage: %s <topic name> [QoS level]\n", argv[0]);
+        return 1;
+    }
+
+    if (strlen(argv[1]) > TOPIC_MAXLEN) {
+        puts("error: topic name exceeds maximum possible size");
+        return 1;
+    }
+    if (argc >= 3) {
+        flags |= get_qos(argv[2]);
+    }
+
+    /* find empty subscription slot */
+    unsigned i = 0;
+    for (; (i < NUMOFSUBS) && (subscriptions[i].topic.id != 0); i++) {}
+    if (i == NUMOFSUBS) {
+        puts("error: no memory to store new subscriptions");
+        return 1;
+    }
+
+    subscriptions[i].cb = on_pub;
+    strcpy(topics[i], argv[1]);
+    subscriptions[i].topic.name = topics[i];
+    if (emcute_sub(&subscriptions[i], flags) != EMCUTE_OK) {
+        printf("error: unable to subscribe to %s\n", argv[1]);
+        return 1;
+    }
+
+    printf("Now subscribed to %s\n", argv[1]);
+    return 0;
+}
+
+static int cmd_unsub(int argc, char **argv)
+{
+    if (argc < 2) {
+        printf("usage %s <topic name>\n", argv[0]);
+        return 1;
+    }
+
+    /* find subscriptions entry */
+    for (unsigned i = 0; i < NUMOFSUBS; i++) {
+        if (subscriptions[i].topic.name &&
+            (strcmp(subscriptions[i].topic.name, argv[1]) == 0)) {
+            if (emcute_unsub(&subscriptions[i]) == EMCUTE_OK) {
+                memset(&subscriptions[i], 0, sizeof(emcute_sub_t));
+                printf("Unsubscribed from '%s'\n", argv[1]);
+            }
+            else {
+                printf("Unsubscription form '%s' failed\n", argv[1]);
+            }
+            return 0;
+        }
+    }
+
+    printf("error: no subscription for topic '%s' found\n", argv[1]);
+    return 1;
+}
+
+static int cmd_will(int argc, char **argv)
+{
+    if (argc < 3) {
+        printf("usage %s <will topic name> <will message content>\n", argv[0]);
+        return 1;
+    }
+
+    if (emcute_willupd_topic(argv[1], 0) != EMCUTE_OK) {
+        puts("error: unable to update the last will topic");
+        return 1;
+    }
+    if (emcute_willupd_msg(argv[2], strlen(argv[2])) != EMCUTE_OK) {
+        puts("error: unable to update the last will message");
+        return 1;
+    }
+
+    puts("Successfully updated last will topic and message");
+    return 0;
+}
+
+static const shell_command_t shell_commands[] = {
+    { "con", "connect to MQTT broker", cmd_con },
+    { "discon", "disconnect from the current broker", cmd_discon },
+    { "pub", "publish something", cmd_pub },
+    { "sub", "subscribe topic", cmd_sub },
+    { "unsub", "unsubscribe from topic", cmd_unsub },
+    { "will", "register a last will", cmd_will },
+    { NULL, NULL, NULL }
+};
+
+int main(void)
+{
+    puts("MQTT-SN example application\n");
+    puts("Type 'help' to get started. Have a look at the README.md for more"
+         "information.");
+
+    /* the main thread needs a msg queue to be able to run `ping6`*/
+    msg_init_queue(queue, (sizeof(queue) / sizeof(msg_t)));
+
+    /* initialize our subscription buffers */
+    memset(subscriptions, 0, (NUMOFSUBS * sizeof(emcute_sub_t)));
+
+    /* start the emcute thread */
+    thread_create(stack, sizeof(stack), EMCUTE_PRIO, 0,
+                  emcute_thread, NULL, "emcute");
+
+    /* start shell */
+    char line_buf[SHELL_DEFAULT_BUFSIZE];
+    shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE);
+
+    /* should be never reached */
+    return 0;
+}