Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions mcp-server/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
= mcp-server: quickstart for MCP server
:toc: left
:icons: font
:idprefix:
:idseparator: -
:keywords: mcp
:level: Intermediate
:technologies: Jakarta REST, MCP
:archiveType: war

[abstract]
The `mcp-server` quickstart demonstrates how to implement MCP server resources with WildFly.

== Build the Application

[source,shell]
----
mvn clean package
----

== Run WildFly

[source,shell]
----
./target/server/bin/standalone.sh --stability=experimental
----

== Connect with the MCP introspector

You can use the MCP inspector to test your tools

[source,shell]
----
npx @modelcontextprotocol/inspector
----

Once you are on the http://127.0.0.1:6274[MPC inspector UI], you can connect to your WildFly server with the Streamable HTTP transport type using the parameters:

* Transport Type: **Streamable HTTP**
* URL: **http://localhost:8080/mcp-server/stream**

Alternatively, you can connect with the Server-Sent Events (SSE) transport type using the parameters:

* Transport Type: **SSE**
* URL: **http://localhost:8080/mcp-server/sse**

You should see all those tools.

== Connect with Claude Code

If you are using Claude Code, you can add this MCP server with:

[source,shell]
----
claude mcp add --scope project --transport http wildfly-quickstart http://localhost:8080/mcp-server/stream
----

You can then ask `claude` questions such as:

* `What is the weather forecast for tomorrow at San Antonio?`
* `Are there any weather alerts for Denver?`
* `What is the length of the string "abcdef"?`

188 changes: 188 additions & 0 deletions mcp-server/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.wildfly.quickstarts</groupId>
<artifactId>wildfly-quickstart-parent</artifactId>
<!--
Maintain separation between the artifact id and the version to help prevent
merge conflicts between commits changing the GA and those changing the V.
-->
<version>12</version>
<relativePath/>
</parent>

<artifactId>mcp-server</artifactId>
<version>40.0.1.Final-SNAPSHOT</version>
<packaging>war</packaging>

<name>Quickstart: mcp-server</name>

<properties>
<!-- the Maven project should use the minimum Java SE version supported -->
<maven.compiler.release>17</maven.compiler.release>
<!-- the version for the Server -->
<version.server>40.0.0.Final</version.server>
<!-- the versions for the BOMs, Packs and Plugins -->
<version.bom.ee>${version.server}</version.bom.ee>
<version.bom.expansion>${version.server}</version.bom.expansion>
<version.plugin.wildfly>6.0.0.Final</version.plugin.wildfly>
<version.ai.feature-pack>0.11.0-SNAPSHOT</version.ai.feature-pack>
<checkstyle.skip>true</checkstyle.skip>
</properties>

<dependencyManagement>
<dependencies>
<!-- importing the Expansion BOM adds MicroProfile specs -->
<dependency>
<groupId>org.wildfly.bom</groupId>
<artifactId>wildfly-expansion</artifactId>
<version>${version.bom.expansion}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- importing the ee-with-tools BOM adds specs and other useful artifacts as managed dependencies -->
<dependency>
<groupId>org.wildfly.bom</groupId>
<artifactId>wildfly-ee-with-tools</artifactId>
<version>${version.bom.ee}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.wildfly.generative-ai</groupId>
<artifactId>wildfly-ai-bom</artifactId>
<version>${version.ai.feature-pack}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>jakarta.ws.rs</groupId>
<artifactId>jakarta.ws.rs-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>jakarta.json</groupId>
<artifactId>jakarta.json-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mcp-java</groupId>
<artifactId>mcp-server-api</artifactId>
<scope>provided</scope>
</dependency>

<!-- Tests -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
<type>jar</type>
</dependency>
</dependencies>

<build>
<!-- Set the name of the archive -->
<finalName>${project.artifactId}</finalName>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<version>${version.plugin.wildfly}</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<configuration>
<!-- adds versions properties as attributes for substitutions in README.adoc source blocks -->
<attributes>
<versionExpansionBom>${version.bom.expansion}</versionExpansionBom>
</attributes>
</configuration>
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>provisioned-server</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.wildfly.plugins</groupId>
<artifactId>wildfly-maven-plugin</artifactId>
<configuration>
<feature-packs>
<feature-pack>
<location>org.wildfly:wildfly-galleon-pack:${version.server}</location>
</feature-pack>
<feature-pack>
<location>org.wildfly.generative-ai:wildfly-ai-feature-pack:${version.ai.feature-pack}</location>
</feature-pack>
</feature-packs>
<layers>
<layer>jaxrs-server</layer>
<layer>mcp-server</layer>
</layers>
<stability>experimental</stability>
</configuration>
<executions>
<execution>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>integration-testing</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<configuration>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<repositories>
<repository>
<id>jboss-public-maven-repository</id>
<name>JBoss Public Maven Repository</name>
<url>https://repository.jboss.org/nexus/content/groups/public/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>jboss-public-maven-repository</id>
<name>JBoss Public Maven Repository</name>
<url>https://repository.jboss.org/nexus/content/groups/public/</url>
</pluginRepository>
</pluginRepositories>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2025 JBoss by Red Hat.
*
* Licensed 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.wildfly.quickstart.mcp;


import org.mcp_java.server.tools.Tool;
import org.mcp_java.server.tools.ToolArg;

/*
* Example of a closed-world tool that does not rely on any external system
*/
public class SimpleTool {

@Tool(name = "length-of-string",
description = "Calculates the length of a string",
annotations = @Tool.Annotations(openWorldHint = false, readOnlyHint = true, destructiveHint = false, idempotentHint = true))
int stringLength(@ToolArg(description = "the string the length of of which we want to calculate") String string) {
return string.length();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.wildfly.quickstart.mcp;

import jakarta.json.Json;
import jakarta.ws.rs.ApplicationPath;
import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.ext.Provider;
import jakarta.ws.rs.ext.ReaderInterceptor;
import jakarta.ws.rs.ext.ReaderInterceptorContext;

import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

@ApplicationPath("/")
public class WeatherApplication extends Application {

/**
* Interceptor to handle "application/geo+json" content as a {@code JsonObject}.
*/
@Provider
public static class GeoJsonReaderInterceptor implements ReaderInterceptor {
public static final MediaType APPLICATION_GEO_JSON_TYPE = new MediaType("application", "geo+json");
@Override
public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException {
if (context.getMediaType().isCompatible(APPLICATION_GEO_JSON_TYPE)) {
InputStreamReader reader = new InputStreamReader(context.getInputStream(), StandardCharsets.UTF_8);
return Json.createReader(reader).readObject();
}
return context.proceed();
}
}
}
Loading
Loading