Add examples and bundler
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target/
|
||||||
18
LICENSE
Normal file
18
LICENSE
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 shahondin1624
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||||
|
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
||||||
|
following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||||
|
portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||||
|
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
|
||||||
|
EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
|
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
51
README.md
Normal file
51
README.md
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
### Building the project
|
||||||
|
|
||||||
|
To build the project and generate the fat JAR and binaries, run:
|
||||||
|
```bash
|
||||||
|
mvn clean package
|
||||||
|
```
|
||||||
|
|
||||||
|
### Generated Artifacts
|
||||||
|
|
||||||
|
After a successful build, you can find the following artifacts in the `target/` directory:
|
||||||
|
- `mcp-server-app-all.jar`: Executable fat JAR containing all dependencies.
|
||||||
|
- `mcp-server-app`: Linux executable wrapper script.
|
||||||
|
- `mcp-server-app.exe`: Windows executable (console application).
|
||||||
|
|
||||||
|
### Running the server
|
||||||
|
|
||||||
|
Using the fat JAR:
|
||||||
|
```bash
|
||||||
|
java -jar target/mcp-server-app-all.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
Using the Linux executable:
|
||||||
|
```bash
|
||||||
|
./target/mcp-server-app
|
||||||
|
```
|
||||||
|
|
||||||
|
The server will start on port `8080`.
|
||||||
|
|
||||||
|
### MCP Configuration
|
||||||
|
This server is available using
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"test": {
|
||||||
|
"command": "java",
|
||||||
|
"args": ["-jar", "/path/to/mcp-server-app-all.jar"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
or via HTTP:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"test": {
|
||||||
|
"url": "http://127.0.0.1:8080/mcp"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
as mcp config.
|
||||||
144
pom.xml
Normal file
144
pom.xml
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>mcp.app</groupId>
|
||||||
|
<artifactId>mcp-server-app</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.mcp-java</groupId>
|
||||||
|
<artifactId>mcp-server-lib</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Logging implementation -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-simple</artifactId>
|
||||||
|
<version>2.0.9</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.objecthunter</groupId>
|
||||||
|
<artifactId>exp4j</artifactId>
|
||||||
|
<version>0.4.8</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.shahondin1624</groupId>
|
||||||
|
<artifactId>knowledge-graph</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.11.0</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>exec-maven-plugin</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<configuration>
|
||||||
|
<mainClass>mcp.app.McpLauncher</mainClass>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>3.5.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
|
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||||
|
<finalName>mcp-server-app-all</finalName>
|
||||||
|
<transformers>
|
||||||
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
<mainClass>mcp.app.McpLauncher</mainClass>
|
||||||
|
</transformer>
|
||||||
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||||
|
</transformers>
|
||||||
|
<filters>
|
||||||
|
<filter>
|
||||||
|
<artifact>*:*</artifact>
|
||||||
|
<excludes>
|
||||||
|
<exclude>META-INF/*.SF</exclude>
|
||||||
|
<exclude>META-INF/*.DSA</exclude>
|
||||||
|
<exclude>META-INF/*.RSA</exclude>
|
||||||
|
</excludes>
|
||||||
|
</filter>
|
||||||
|
</filters>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>com.akathist.maven.plugins.launch4j</groupId>
|
||||||
|
<artifactId>launch4j-maven-plugin</artifactId>
|
||||||
|
<version>2.5.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>l4j-clui</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>launch4j</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<headerType>console</headerType>
|
||||||
|
<jar>${project.build.directory}/mcp-server-app-all.jar</jar>
|
||||||
|
<outfile>${project.build.directory}/mcp-server-app.exe</outfile>
|
||||||
|
<downloadUrl>http://java.com/download</downloadUrl>
|
||||||
|
<classPath>
|
||||||
|
<mainClass>mcp.app.McpLauncher</mainClass>
|
||||||
|
</classPath>
|
||||||
|
<jre>
|
||||||
|
<minVersion>21</minVersion>
|
||||||
|
<runtimeBits>64</runtimeBits>
|
||||||
|
</jre>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-antrun-plugin</artifactId>
|
||||||
|
<version>3.1.0</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>run</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<target>
|
||||||
|
<echo file="${project.build.directory}/mcp-server-app">#!/bin/sh
|
||||||
|
# Linux wrapper script for mcp-server-app
|
||||||
|
java -jar "$(dirname "$0")/mcp-server-app-all.jar" "$@"
|
||||||
|
</echo>
|
||||||
|
<chmod file="${project.build.directory}/mcp-server-app" perm="755" />
|
||||||
|
</target>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
49
src/main/java/mcp/app/McpLauncher.java
Normal file
49
src/main/java/mcp/app/McpLauncher.java
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
package mcp.app;
|
||||||
|
|
||||||
|
import de.shahondin1624.knowledgegraph.DatabaseLauncher;
|
||||||
|
import mcp.server.McpServlet;
|
||||||
|
import mcp.server.ToolRegistrationServlet;
|
||||||
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
|
import org.eclipse.jetty.servlet.ServletHolder;
|
||||||
|
import org.eclipse.jetty.server.Server;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class McpLauncher {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(McpLauncher.class);
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
logger.info("Starting MCP App Launcher...");
|
||||||
|
new DatabaseLauncher().start();
|
||||||
|
|
||||||
|
// Scan both library tools and app tools
|
||||||
|
Set<String> classpaths = Stream.concat(
|
||||||
|
Stream.of("mcp.tools", "mcp.app.tools", "de.shahondin1624.knowledgegraph.tooling"),
|
||||||
|
args.length > 0 ? Stream.of(args[0].split(",")) : Stream.empty()
|
||||||
|
).collect(Collectors.toSet());
|
||||||
|
|
||||||
|
logger.debug("Configured classpaths: {}", classpaths);
|
||||||
|
|
||||||
|
McpServlet mcpServlet = new McpServlet(classpaths);
|
||||||
|
mcpServlet.setServerName("mcp-app-server");
|
||||||
|
|
||||||
|
Server server = new Server(8080);
|
||||||
|
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||||
|
context.setContextPath("/");
|
||||||
|
server.setHandler(context);
|
||||||
|
|
||||||
|
ServletHolder mcpHolder = new ServletHolder(mcpServlet);
|
||||||
|
context.addServlet(mcpHolder, "/mcp/*");
|
||||||
|
|
||||||
|
ServletHolder registrationHolder = new ServletHolder(new ToolRegistrationServlet(mcpServlet.getToolRegistry()));
|
||||||
|
context.addServlet(registrationHolder, "/mcp/register");
|
||||||
|
|
||||||
|
server.start();
|
||||||
|
logger.info("MCP App Server started on port 8080");
|
||||||
|
server.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
57
src/main/java/mcp/app/tools/CalculatorTool.java
Normal file
57
src/main/java/mcp/app/tools/CalculatorTool.java
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package mcp.app.tools;
|
||||||
|
|
||||||
|
import io.modelcontextprotocol.spec.McpSchema;
|
||||||
|
import mcp.tools.DefaultMcpTool;
|
||||||
|
import mcp.tools.McpValidatedTool;
|
||||||
|
import mcp.tools.helper.SchemaBuilder;
|
||||||
|
import net.objecthunter.exp4j.Expression;
|
||||||
|
import net.objecthunter.exp4j.ExpressionBuilder;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@DefaultMcpTool
|
||||||
|
public class CalculatorTool extends McpValidatedTool {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(CalculatorTool.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "calculator";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String title() {
|
||||||
|
return "Calculator Tool";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String description() {
|
||||||
|
return "Evaluates a mathematical expression. Supports basic operators (+, -, *, /), functions (sin, cos, tan, log, exp), and parentheses.";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public McpSchema.JsonSchema inputSchema() {
|
||||||
|
return new SchemaBuilder()
|
||||||
|
.addProperty("expression", "string", "The mathematical expression to evaluate")
|
||||||
|
.required("expression")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> outputSchema() {
|
||||||
|
return new SchemaBuilder()
|
||||||
|
.returns("number", "The result of the evaluation")
|
||||||
|
.buildMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public McpSchema.CallToolResult callValidated(McpSchema.CallToolRequest request, Map<String, Object> arguments) {
|
||||||
|
String expressionStr = (String) arguments.get("expression");
|
||||||
|
logger.debug("Evaluating expression: {}", expressionStr);
|
||||||
|
|
||||||
|
Expression expression = new ExpressionBuilder(expressionStr).build();
|
||||||
|
double result = expression.evaluate();
|
||||||
|
return success(String.valueOf(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
60
src/main/java/mcp/app/tools/CurrentDateTimeTool.java
Normal file
60
src/main/java/mcp/app/tools/CurrentDateTimeTool.java
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package mcp.app.tools;
|
||||||
|
|
||||||
|
import io.modelcontextprotocol.spec.McpSchema;
|
||||||
|
import mcp.tools.DefaultMcpTool;
|
||||||
|
import mcp.tools.McpValidatedTool;
|
||||||
|
import mcp.tools.helper.SchemaBuilder;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple tool that returns the current date and time.
|
||||||
|
*/
|
||||||
|
@DefaultMcpTool
|
||||||
|
public class CurrentDateTimeTool extends McpValidatedTool {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(CurrentDateTimeTool.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "current_date_time";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String title() {
|
||||||
|
return "Current Date and Time Tool";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String description() {
|
||||||
|
return "Returns the current date and time on the server";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public McpSchema.JsonSchema inputSchema() {
|
||||||
|
return new SchemaBuilder()
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> outputSchema() {
|
||||||
|
return new SchemaBuilder()
|
||||||
|
.returns("string", "The current date and time in ISO-8601 format")
|
||||||
|
.buildMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isIdempotent() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public McpSchema.CallToolResult callValidated(McpSchema.CallToolRequest request, Map<String, Object> arguments) {
|
||||||
|
String now = LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME);
|
||||||
|
logger.info("CurrentDateTimeTool called, returning: {}", now);
|
||||||
|
return success(now);
|
||||||
|
}
|
||||||
|
}
|
||||||
55
src/main/java/mcp/app/tools/EchoTool.java
Normal file
55
src/main/java/mcp/app/tools/EchoTool.java
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
package mcp.app.tools;
|
||||||
|
|
||||||
|
import io.modelcontextprotocol.spec.McpSchema;
|
||||||
|
import mcp.tools.DefaultMcpTool;
|
||||||
|
import mcp.tools.McpValidatedTool;
|
||||||
|
import mcp.tools.helper.SchemaBuilder;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple tool that echoes back the input message.
|
||||||
|
*/
|
||||||
|
@DefaultMcpTool()
|
||||||
|
public class EchoTool extends McpValidatedTool {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(EchoTool.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "echo";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String title() {
|
||||||
|
return "Echo Tool";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String description() {
|
||||||
|
return "Echoes back the input message";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public McpSchema.JsonSchema inputSchema() {
|
||||||
|
return new SchemaBuilder()
|
||||||
|
.addProperty("message", "string", "The message to echo")
|
||||||
|
.required("message")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> outputSchema() {
|
||||||
|
return new SchemaBuilder()
|
||||||
|
.returns("string", "The echoed message")
|
||||||
|
.buildMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public McpSchema.CallToolResult callValidated(McpSchema.CallToolRequest request, Map<String, Object> arguments) {
|
||||||
|
String message = (String) arguments.get("message");
|
||||||
|
logger.debug("EchoTool called with message: {}", message);
|
||||||
|
return success(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/main/resources/simplelogger.properties
Normal file
1
src/main/resources/simplelogger.properties
Normal file
@@ -0,0 +1 @@
|
|||||||
|
org.slf4j.simpleLogger.defaultLogLevel=info
|
||||||
Reference in New Issue
Block a user