Index: tools/langserver/src/json.hpp
===================================================================
--- tools/langserver/src/json.hpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
+++ tools/langserver/src/json.hpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <nlohmann/json.hpp>
+
+namespace json {
+      auto parse(const std::vector<char> & buff) {
+            return nlohmann::json::parse(buff.begin(), buff.end());
+      }
+
+      using obj = nlohmann::json;
+}
Index: tools/langserver/src/log.cpp
===================================================================
--- tools/langserver/src/log.cpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
+++ tools/langserver/src/log.cpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
@@ -0,0 +1,24 @@
+#include "log.hpp"
+
+#include <iostream>
+#include <fstream>
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+
+int g_argc;
+char** g_argv;
+
+static std::ofstream create() {
+      struct passwd *pw = getpwuid(getuid());
+      const char *homedir = pw->pw_dir;
+
+      std::string target = std::string(homedir) + "/.cfa-ls.log";
+      return std::ofstream{ target };
+}
+
+std::ostream & log() {
+      static std::ofstream log = create();
+      return log;
+}
Index: tools/langserver/src/log.hpp
===================================================================
--- tools/langserver/src/log.hpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
+++ tools/langserver/src/log.hpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
@@ -0,0 +1,7 @@
+#pragma once
+
+#include <iostream>
+
+extern std::ostream & log();
+extern int g_argc;
+extern char** g_argv;
Index: tools/langserver/src/main.cpp
===================================================================
--- tools/langserver/src/main.cpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
+++ tools/langserver/src/main.cpp	(revision b52abe09e566fb9c0f5bb6ff0da4ce67bdd511bb)
@@ -0,0 +1,89 @@
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include "json.hpp"
+#include "log.hpp"
+
+static void request(std::vector<char> & buf);
+
+namespace server {
+	json::obj init(const json::obj & ) {
+		return {
+			{ "capabilities", json::obj::array() },
+			{ "serverInfo", {
+				{ "name", "Cforall Language Server" },
+				{ "version", "0.1" }
+			}}
+		};
+	}
+}
+
+std::unordered_map<std::string, json::obj (*)( const json::obj & )> actions {
+	{ "initialize", server::init }
+};
+
+int main(int argc, char * argv[]) {
+	g_argc = argc;
+	g_argv = argv;
+
+	log() << "Language Server called with args:" << std::endl;
+	for(int i = 0; i < argc; i++) {
+		log() << "\t- " << argv[i] << std::endl;
+	}
+
+	std::vector<char> buffer;
+	while(true) {
+		request(buffer);
+		if(buffer.size() == 0) break;
+
+		auto top = json::parse(buffer);
+
+		auto action = actions.find( top["method"] );
+		if(action != actions.end()) {
+			log() << "Executing request '" << action->first << "'" << std::endl;
+			json::obj response = {
+				{"id", top["id"] }
+			};
+
+			try{
+				response["result"] = action->second( top["params"] );
+			} catch( const json::obj & error ) {
+				response["result"] = "";
+				response["error"] = error;
+			}
+			log() << "Responding with : " << response.dump(4) << std::endl;
+			std::cout << response.dump() << std::endl;
+		}
+		else {
+			log() << "WARNING no action for method '" << top["method"].dump(4) << "'" << std::endl;
+		}
+	}
+
+	log() << "Language Server closing after end of file" << std::endl;
+
+	return 0;
+}
+
+static void request(std::vector<char> & buffer) {
+	std::string lenstr;
+	std::getline( std::cin, lenstr );
+	if(std::cin.eof()) { buffer.clear(); return; };
+
+	if (lenstr.rfind("Content-Length: ", 0) != 0) {
+		log() << "Expected content length bug got '" << lenstr << "' instead " << std::endl;
+		std::exit(EXIT_FAILURE);
+	}
+
+	size_t idx = sizeof("Content-Length:");
+	size_t end;
+	size_t len = std::stoul(lenstr.substr(idx), &end);
+	if(lenstr.length() != (idx + end + 1)) {
+		log() << "Inconsistent size of integer in content length: " << lenstr.length() << " vs " << (idx + end) << std::endl;
+	}
+
+	log() << "New request of " << len << " bytes" << std::endl;
+	buffer.resize( len + 2 );
+	std::cin.read(buffer.data(), buffer.size());
+	return;
+}
