diff --git a/features/org.eclipse.pde-feature/feature.xml b/features/org.eclipse.pde-feature/feature.xml
index 0d32f23454..583f28d356 100644
--- a/features/org.eclipse.pde-feature/feature.xml
+++ b/features/org.eclipse.pde-feature/feature.xml
@@ -159,4 +159,11 @@
version="0.0.0"
unpack="false"/>
+
+
diff --git a/ui/org.eclipse.pde.ls/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.ls/META-INF/MANIFEST.MF
index bb5e0e8f55..bb0556277b 100644
--- a/ui/org.eclipse.pde.ls/META-INF/MANIFEST.MF
+++ b/ui/org.eclipse.pde.ls/META-INF/MANIFEST.MF
@@ -1,7 +1,12 @@
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: PDE Language Server
-Bundle-SymbolicName: org.eclipse.pde.ls
+Bundle-SymbolicName: org.eclipse.pde.ls;singleton:=true
Bundle-Version: 1.0.0.qualifier
+Import-Package: aQute.bnd.help;version="2.0.0",
+ aQute.bnd.properties
+Require-Bundle: org.eclipse.lsp4e;bundle-version="0.18.0",
+ org.eclipse.lsp4j;bundle-version="0.21.1",
+ org.eclipse.lsp4j.jsonrpc;bundle-version="0.21.1"
Automatic-Module-Name: org.eclipse.pde.ls
Bundle-RequiredExecutionEnvironment: JavaSE-17
diff --git a/ui/org.eclipse.pde.ls/build.properties b/ui/org.eclipse.pde.ls/build.properties
index 34d2e4d2da..e9863e281e 100644
--- a/ui/org.eclipse.pde.ls/build.properties
+++ b/ui/org.eclipse.pde.ls/build.properties
@@ -1,4 +1,5 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
- .
+ .,\
+ plugin.xml
diff --git a/ui/org.eclipse.pde.ls/plugin.xml b/ui/org.eclipse.pde.ls/plugin.xml
new file mode 100644
index 0000000000..b4c2f9b607
--- /dev/null
+++ b/ui/org.eclipse.pde.ls/plugin.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ui/org.eclipse.pde.ls/src/org/eclipse/pde/ls/BNDLanguageServerClient.java b/ui/org.eclipse.pde.ls/src/org/eclipse/pde/ls/BNDLanguageServerClient.java
new file mode 100644
index 0000000000..a29ff78cb2
--- /dev/null
+++ b/ui/org.eclipse.pde.ls/src/org/eclipse/pde/ls/BNDLanguageServerClient.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2023 Christoph Läubrich and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Christoph Läubrich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.pde.ls;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.util.concurrent.Future;
+
+import org.eclipse.lsp4e.server.StreamConnectionProvider;
+import org.eclipse.lsp4j.jsonrpc.Launcher;
+import org.eclipse.lsp4j.launch.LSPLauncher;
+import org.eclipse.lsp4j.services.LanguageClient;
+import org.eclipse.pde.ls.bnd.BNDLanguageServer;
+
+public class BNDLanguageServerClient implements StreamConnectionProvider {
+
+ private PipedInputStream input;
+ private PipedOutputStream output;
+ private Future listening;
+
+ @Override
+ public InputStream getErrorStream() {
+ return null;
+ }
+
+ @Override
+ public InputStream getInputStream() {
+ return input;
+ }
+
+ @Override
+ public OutputStream getOutputStream() {
+ return output;
+ }
+
+ @Override
+ public void start() throws IOException {
+ System.out.println("BNDLanguageServerClient.start()");
+ BNDLanguageServer server = new BNDLanguageServer();
+ PipedOutputStream pipedOutputStream = new PipedOutputStream();
+ PipedInputStream pipedInputStream = new PipedInputStream();
+ Launcher launcher = LSPLauncher.createServerLauncher(server, pipedInputStream,
+ pipedOutputStream);
+ input = new PipedInputStream(pipedOutputStream);
+ output = new PipedOutputStream(pipedInputStream);
+ listening = launcher.startListening();
+ }
+
+ @Override
+ public void stop() {
+ System.out.println("BNDLanguageServerClient.stop()");
+ // TODO how to properly shutdown?!?
+ listening.cancel(true);
+ try {
+ input.close();
+ } catch (IOException e) {
+ }
+ try {
+ output.close();
+ } catch (IOException e) {
+ }
+ }
+
+}
diff --git a/ui/org.eclipse.pde.ls/src/org/eclipse/pde/ls/bnd/BNDLanguageServer.java b/ui/org.eclipse.pde.ls/src/org/eclipse/pde/ls/bnd/BNDLanguageServer.java
new file mode 100644
index 0000000000..0e98aba072
--- /dev/null
+++ b/ui/org.eclipse.pde.ls/src/org/eclipse/pde/ls/bnd/BNDLanguageServer.java
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2023 Christoph Läubrich and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Christoph Läubrich - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.pde.ls.bnd;
+
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.lsp4j.CompletionOptions;
+import org.eclipse.lsp4j.InitializeParams;
+import org.eclipse.lsp4j.InitializeResult;
+import org.eclipse.lsp4j.SemanticTokenTypes;
+import org.eclipse.lsp4j.SemanticTokensLegend;
+import org.eclipse.lsp4j.SemanticTokensWithRegistrationOptions;
+import org.eclipse.lsp4j.ServerCapabilities;
+import org.eclipse.lsp4j.TextDocumentSyncKind;
+import org.eclipse.lsp4j.services.LanguageServer;
+import org.eclipse.lsp4j.services.TextDocumentService;
+import org.eclipse.lsp4j.services.WorkspaceService;
+
+//See
+// https://github.com/eclipse-lsp4j/lsp4j/blob/main/documentation/README.md#implement-your-language-server
+// https://github.com/AlloyTools/org.alloytools.alloy/tree/master/org.alloytools.alloy.lsp
+// https://github.com/bndtools/bnd/issues/5833
+// https://www.vogella.com/tutorials/EclipseLanguageServer/article.html
+// https://github.com/mickaelistria/eclipse-languageserver-demo/tree/master/Le%20LanguageServer%20de%20Chamrousse
+public class BNDLanguageServer implements LanguageServer {
+
+ private BNDTextDocumentService documentService;
+ private BNDWorkspaceService workspaceService;
+ private ExecutorService executorService;
+
+ public BNDLanguageServer() {
+ executorService = Executors.newWorkStealingPool();
+ documentService = new BNDTextDocumentService(executorService);
+ workspaceService = new BNDWorkspaceService();
+ }
+
+ @Override
+ public CompletableFuture initialize(InitializeParams params) {
+ final InitializeResult res = new InitializeResult(new ServerCapabilities());
+ res.getCapabilities().setCompletionProvider(new CompletionOptions(false, List.of()));
+ res.getCapabilities().setTextDocumentSync(TextDocumentSyncKind.Full);
+ res.getCapabilities().setSemanticTokensProvider(
+ new SemanticTokensWithRegistrationOptions(
+ new SemanticTokensLegend(List.of(SemanticTokenTypes.Keyword), List.of()),
+ Boolean.TRUE));
+ return CompletableFuture.completedFuture(res);
+ }
+
+ @Override
+ public CompletableFuture