This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
The following commit(s) were added to refs/heads/master by this push:
new 7c5b8d8b fix(mcp-server-contributions): remove bundle and component
resources
7c5b8d8b is described below
commit 7c5b8d8bceb4dc0f766f8062aed89776634ba277
Author: Robert Munteanu <[email protected]>
AuthorDate: Fri Mar 13 13:30:40 2026 +0100
fix(mcp-server-contributions): remove bundle and component resources
The OsgiBundleDiagnosticContribution should be enough for diagnosing
OSGi-related issues
---
.../impl/contribs/BundleResourceContribution.java | 142 ---------------------
.../mcp/server/impl/contribs/BundleState.java | 57 ---------
.../contribs/ComponentResourceContribution.java | 125 ------------------
3 files changed, 324 deletions(-)
diff --git
a/mcp-server-contributions/src/main/java/org/apache/sling/mcp/server/impl/contribs/BundleResourceContribution.java
b/mcp-server-contributions/src/main/java/org/apache/sling/mcp/server/impl/contribs/BundleResourceContribution.java
deleted file mode 100644
index 1d37db39..00000000
---
a/mcp-server-contributions/src/main/java/org/apache/sling/mcp/server/impl/contribs/BundleResourceContribution.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sling.mcp.server.impl.contribs;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.Locale;
-import java.util.Optional;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import io.modelcontextprotocol.server.McpStatelessServerFeatures;
-import
io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncCompletionSpecification;
-import
io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncResourceSpecification;
-import
io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncResourceTemplateSpecification;
-import io.modelcontextprotocol.spec.McpSchema;
-import io.modelcontextprotocol.spec.McpSchema.ReadResourceResult;
-import io.modelcontextprotocol.spec.McpSchema.Resource;
-import io.modelcontextprotocol.spec.McpSchema.ResourceTemplate;
-import io.modelcontextprotocol.spec.McpSchema.TextResourceContents;
-import org.apache.sling.mcp.server.spi.McpServerContribution;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.wiring.BundleRevision;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-
-@Component
-public class BundleResourceContribution implements McpServerContribution {
-
- private static final String URI_BUNDLES_ALL = "bundles://all";
- private static final String RESOURCE_TEMPLATE_BUNDLES_STATE_PREFIX =
"bundles://state/";
- private static final String RESOURCE_TEMPLATE_BUNDLES_STATE_PATTERN =
- RESOURCE_TEMPLATE_BUNDLES_STATE_PREFIX + "{state}";
-
- private BundleContext ctx;
-
- @Activate
- public BundleResourceContribution(BundleContext ctx) {
- this.ctx = ctx;
- }
-
- @Override
- public List<SyncResourceSpecification> getSyncResourceSpecification() {
-
- return List.of(new
McpStatelessServerFeatures.SyncResourceSpecification(
- new Resource.Builder()
- .name("bundles")
- .uri(URI_BUNDLES_ALL)
- .description(
- "List all OSGi bundles with symbolic name,
version, and state. Fragment bundles are marked with [Fragment]")
- .mimeType("text/plain")
- .build(),
- (context, request) -> {
- String bundleInfo =
-
Stream.of(ctx.getBundles()).map(this::describe).collect(Collectors.joining("\n"));
-
- TextResourceContents contents = new
TextResourceContents(URI_BUNDLES_ALL, "text/plain", bundleInfo);
-
- return new McpSchema.ReadResourceResult(List.of(contents));
- }));
- }
-
- @Override
- public List<SyncResourceTemplateSpecification>
getSyncResourceTemplateSpecification() {
- return List.of(new
McpStatelessServerFeatures.SyncResourceTemplateSpecification(
- new ResourceTemplate.Builder()
- .uriTemplate(RESOURCE_TEMPLATE_BUNDLES_STATE_PATTERN)
- .name("bundles")
- .build(),
- (context, request) -> {
- String requestedState =
request.uri().substring(RESOURCE_TEMPLATE_BUNDLES_STATE_PREFIX.length());
- try {
- BundleState bundleState =
BundleState.valueOf(requestedState.toUpperCase(Locale.ENGLISH));
- if (!bundleState.isValid()) {
- throw new IllegalArgumentException("Invalid bundle
state: " + requestedState);
- }
- String bundleInfo = Arrays.stream(ctx.getBundles())
- .filter(b -> b.getState() ==
bundleState.getState())
- .map(this::describe)
- .collect(Collectors.joining("\n"));
-
- TextResourceContents contents =
- new TextResourceContents(request.uri(),
"text/plain", bundleInfo);
-
- return new ReadResourceResult(List.of(contents));
- } catch (IllegalArgumentException e) {
- return new ReadResourceResult(List.of(new
TextResourceContents(
- request.uri(), "text/plain", "Invalid bundle
state requested: " + requestedState)));
- }
- }));
- }
-
- @Override
- public List<SyncCompletionSpecification> getSyncCompletionSpecification() {
-
- return List.of(new
McpStatelessServerFeatures.SyncCompletionSpecification(
- new McpSchema.ResourceReference("ref/resource",
RESOURCE_TEMPLATE_BUNDLES_STATE_PATTERN),
- (context, request) -> {
-
- // expect argument name to always be "state"
- String requestedState = request.argument().value();
- List<String> states = Stream.of(BundleState.values())
- .filter(BundleState::isValid)
- .map(s -> s.name().toLowerCase(Locale.ENGLISH))
- .toList();
- if (requestedState != null && !requestedState.isEmpty()) {
- states = states.stream()
- .filter(s ->
s.startsWith(requestedState.toLowerCase(Locale.ENGLISH)))
- .toList();
- }
- return new McpSchema.CompleteResult(
- new
McpSchema.CompleteResult.CompleteCompletion(states, states.size(), false));
- }));
- }
-
- private String describe(Bundle b) {
- boolean isFragment =
Optional.ofNullable(b.adapt(BundleRevision.class)).stream()
- .map(br -> (br.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0)
- .findAny()
- .orElse(false);
- String additionalInfo = isFragment ? " [Fragment]" : "";
- return "Bundle " + b.getSymbolicName() + additionalInfo + " (version "
+ b.getVersion() + ") is in state "
- + BundleState.fromState(b.getState()) + " (" + b.getState() +
")";
- }
-}
diff --git
a/mcp-server-contributions/src/main/java/org/apache/sling/mcp/server/impl/contribs/BundleState.java
b/mcp-server-contributions/src/main/java/org/apache/sling/mcp/server/impl/contribs/BundleState.java
deleted file mode 100644
index 29e5bba8..00000000
---
a/mcp-server-contributions/src/main/java/org/apache/sling/mcp/server/impl/contribs/BundleState.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sling.mcp.server.impl.contribs;
-
-import org.osgi.framework.Bundle;
-
-/**
- * Enum representing OSGi bundle states.
- */
-public enum BundleState {
- UNINSTALLED(Bundle.UNINSTALLED),
- INSTALLED(Bundle.INSTALLED),
- RESOLVED(Bundle.RESOLVED),
- STARTING(Bundle.STARTING),
- STOPPING(Bundle.STOPPING),
- ACTIVE(Bundle.ACTIVE),
- UNKNOWN(-1);
-
- private final int state;
-
- BundleState(int state) {
- this.state = state;
- }
-
- public static BundleState fromState(int state) {
- for (BundleState bs : values()) {
- if (bs.state == state) {
- return bs;
- }
- }
- return UNKNOWN;
- }
-
- public boolean isValid() {
- return this != UNKNOWN;
- }
-
- public int getState() {
- return state;
- }
-}
diff --git
a/mcp-server-contributions/src/main/java/org/apache/sling/mcp/server/impl/contribs/ComponentResourceContribution.java
b/mcp-server-contributions/src/main/java/org/apache/sling/mcp/server/impl/contribs/ComponentResourceContribution.java
deleted file mode 100644
index e0c18bce..00000000
---
a/mcp-server-contributions/src/main/java/org/apache/sling/mcp/server/impl/contribs/ComponentResourceContribution.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.sling.mcp.server.impl.contribs;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.Locale;
-import java.util.stream.Collectors;
-
-import io.modelcontextprotocol.server.McpStatelessServerFeatures;
-import
io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncResourceSpecification;
-import
io.modelcontextprotocol.server.McpStatelessServerFeatures.SyncResourceTemplateSpecification;
-import io.modelcontextprotocol.spec.McpSchema;
-import io.modelcontextprotocol.spec.McpSchema.ReadResourceResult;
-import io.modelcontextprotocol.spec.McpSchema.Resource;
-import io.modelcontextprotocol.spec.McpSchema.ResourceTemplate;
-import io.modelcontextprotocol.spec.McpSchema.TextResourceContents;
-import org.apache.sling.mcp.server.spi.McpServerContribution;
-import org.osgi.service.component.annotations.Activate;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Reference;
-import org.osgi.service.component.runtime.ServiceComponentRuntime;
-import org.osgi.service.component.runtime.dto.ComponentDescriptionDTO;
-
-@Component
-public class ComponentResourceContribution implements McpServerContribution {
-
- private static String getStateString(int state) {
- return switch (state) {
- case 1 -> "UNSATISFIED_CONFIGURATION";
- case 2 -> "UNSATISFIED_REFERENCE";
- case 4 -> "SATISFIED";
- case 8 -> "ACTIVE";
- case 16 -> "REGISTERED";
- case 32 -> "FACTORY";
- case 64 -> "DISABLED";
- case 128 -> "ENABLING";
- case 256 -> "ENABLED";
- case 512 -> "DISABLING";
- default -> "UNKNOWN";
- };
- }
-
- @Reference
- private ServiceComponentRuntime scr;
-
- @Activate
- public ComponentResourceContribution() {}
-
- @Override
- public List<SyncResourceSpecification> getSyncResourceSpecification() {
-
- return List.of(new
McpStatelessServerFeatures.SyncResourceSpecification(
- new Resource.Builder()
- .name("component")
- .uri("component://")
- .description("OSGi component status")
- .mimeType("text/plain")
- .build(),
- (context, request) -> {
- Collection<ComponentDescriptionDTO> components =
scr.getComponentDescriptionDTOs();
- String componentInfo = components.stream()
- .map(c -> {
- String state =
scr.getComponentConfigurationDTOs(c).stream()
- .map(config ->
getStateString(config.state))
- .collect(Collectors.joining(", "));
- return "Component " + c.name + " is in
state(s): " + state;
- })
- .collect(Collectors.joining("\n"));
-
- TextResourceContents contents =
- new TextResourceContents("component://",
"text/plain", componentInfo);
-
- return new McpSchema.ReadResourceResult(List.of(contents));
- }));
- }
-
- @Override
- public List<SyncResourceTemplateSpecification>
getSyncResourceTemplateSpecification() {
- return List.of(new
McpStatelessServerFeatures.SyncResourceTemplateSpecification(
- new ResourceTemplate.Builder()
- .uriTemplate("components://state/{state}")
- .name("components")
- .build(),
- (context, request) -> {
- String componentInfo = "";
- String uri = request.uri().toLowerCase(Locale.ENGLISH);
-
- if (uri.startsWith("components://state/")) {
- String requestedState =
uri.substring("components://state/".length());
- Collection<ComponentDescriptionDTO> components =
scr.getComponentDescriptionDTOs();
-
- componentInfo = components.stream()
- .flatMap(c ->
scr.getComponentConfigurationDTOs(c).stream()
- .filter(config ->
getStateString(config.state)
- .toLowerCase(Locale.ENGLISH)
- .equals(requestedState))
- .map(config -> "Component " + c.name +
" is in state: "
- +
getStateString(config.state)))
- .collect(Collectors.joining("\n"));
- }
-
- TextResourceContents contents =
- new TextResourceContents(request.uri(),
"text/plain", componentInfo);
-
- return new ReadResourceResult(List.of(contents));
- }));
- }
-}