diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml
index 24aecec..c2cfa53 100644
--- a/.idea/dataSources.xml
+++ b/.idea/dataSources.xml
@@ -18,7 +18,15 @@
jdbc:sqlite:./data/agent.db
$ProjectFileDir$
-
+
+ sqlite.xerial
+ true
+ true
+ org.sqlite.JDBC
+ jdbc:sqlite:./data/agent.db
+ $ProjectFileDir$
+
+
sqlite.xerial
true
true
diff --git a/agent/pom.xml b/agent/pom.xml
index 079ec96..47675d7 100644
--- a/agent/pom.xml
+++ b/agent/pom.xml
@@ -54,11 +54,23 @@
org.springframework.boot
spring-boot-starter-web
+
+
+
+ io.modelcontextprotocol.sdk
+ mcp
+
+
+ io.modelcontextprotocol.sdk
+ mcp-spring-webflux
+
+
+
org.springdoc
springdoc-openapi-starter-webmvc-ui
- 2.6.0
+ 2.8.9
@@ -74,6 +86,17 @@
10.16.0
+
+ org.testcontainers
+ junit-jupiter
+ 1.21.3
+
+
+ org.testcontainers
+ testcontainers
+ 1.21.3
+
+
org.projectlombok
@@ -149,6 +172,13 @@
1.6.0
pom
import
+
+
+ io.modelcontextprotocol.sdk
+ mcp-bom
+ 0.10.0
+ pom
+ import
diff --git a/agent/src/main/java/com/clortox/agent/agent/controllers/AgentController.java b/agent/src/main/java/com/clortox/agent/agent/controllers/AgentController.java
deleted file mode 100644
index cdf5910..0000000
--- a/agent/src/main/java/com/clortox/agent/agent/controllers/AgentController.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.clortox.agent.agent.controllers;
-
-import com.clortox.agent.agent.state.SmartAgent;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-@RestController("Agent")
-public class AgentController {
-
- @Autowired
- private SmartAgent agent;
-
-
- @GetMapping(path = "/assistant")
- public ResponseEntity> get(String message) {
- return ResponseEntity.status(HttpStatus.OK).body(agent.invoke(message));
-
-// return null;
- }
-}
diff --git a/agent/src/main/java/com/clortox/agent/agent/controllers/OllamaCompatibleApi.java b/agent/src/main/java/com/clortox/agent/agent/controllers/OllamaCompatibleApi.java
new file mode 100644
index 0000000..7a0f38d
--- /dev/null
+++ b/agent/src/main/java/com/clortox/agent/agent/controllers/OllamaCompatibleApi.java
@@ -0,0 +1,39 @@
+package com.clortox.agent.agent.controllers;
+
+import com.clortox.agent.agent.dto.ollama.ModelDetails;
+import com.clortox.agent.agent.dto.ollama.ModelTag;
+import com.clortox.agent.agent.dto.ollama.TagsResponse;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.time.OffsetDateTime;
+import java.util.List;
+
+@RestController
+@RequestMapping("/ollama/api")
+public class OllamaCompatibleApi {
+
+ @GetMapping("/tags")
+ public TagsResponse listModels() {
+ return new TagsResponse(List.of(
+ new ModelTag(
+ "SmartAgent:latest",
+ OffsetDateTime.now().toString(),
+ 1024,
+ "sha256:deadbeef1",
+ new ModelDetails(
+ "gguf",
+ "llama",
+ List.of("llama"),
+ "8B",
+ "Q4_0"
+ )
+ )
+ ));
+ }
+
+
+
+
+}
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ChatMessage.java b/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ChatMessage.java
new file mode 100644
index 0000000..02578bc
--- /dev/null
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ChatMessage.java
@@ -0,0 +1,13 @@
+package com.clortox.agent.agent.dto.ollama;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ChatMessage {
+ private ChatRole role;
+ private String content;
+}
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ChatRequest.java b/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ChatRequest.java
new file mode 100644
index 0000000..5bfa405
--- /dev/null
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ChatRequest.java
@@ -0,0 +1,16 @@
+package com.clortox.agent.agent.dto.ollama;
+
+import lombok.Builder;
+
+import java.util.List;
+import java.util.Map;
+
+@Builder
+public record ChatRequest(
+ String model,
+ List messages,
+ Boolean stream,
+ Map options,
+ String format,
+ String keep_alive
+) {}
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ChatResponse.java b/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ChatResponse.java
new file mode 100644
index 0000000..d5c233c
--- /dev/null
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ChatResponse.java
@@ -0,0 +1,11 @@
+package com.clortox.agent.agent.dto.ollama;
+
+import lombok.Builder;
+
+@Builder
+public record ChatResponse(
+ String model,
+ String created_at,
+ ChatMessage message,
+ Boolean done
+) {}
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ChatRole.java b/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ChatRole.java
new file mode 100644
index 0000000..794acd2
--- /dev/null
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ChatRole.java
@@ -0,0 +1,31 @@
+package com.clortox.agent.agent.dto.ollama;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+
+public enum ChatRole {
+ SYSTEM("system"),
+ USER("user"),
+ ASSISTANT("assistant"),
+ TOOL("tool");
+
+ private String friendlyName;
+
+ ChatRole(String friendlyString) {
+ this.friendlyName = friendlyString;
+ }
+
+ @JsonValue
+ public String getFriendlyName() {
+ return friendlyName;
+ }
+
+ @JsonCreator
+ public static ChatRole fromFriendlyName(String name) {
+ for(ChatRole role : ChatRole.values()) {
+ if(role.friendlyName.equals(name)) return role;
+ }
+ throw new IllegalStateException("Unknown ChatRole " + name);
+ }
+
+}
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ModelDetails.java b/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ModelDetails.java
new file mode 100644
index 0000000..104dd61
--- /dev/null
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ModelDetails.java
@@ -0,0 +1,16 @@
+package com.clortox.agent.agent.dto.ollama;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@AllArgsConstructor
+public class ModelDetails {
+ private String format;
+ private String family;
+ private List families;
+ private String parameter_size;
+ private String quantization_level;
+}
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ModelTag.java b/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ModelTag.java
new file mode 100644
index 0000000..f6ece9c
--- /dev/null
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/ollama/ModelTag.java
@@ -0,0 +1,17 @@
+package com.clortox.agent.agent.dto.ollama;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class ModelTag {
+ private String name;
+ /**
+ * ISO format
+ */
+ private String modified_at;
+ private long size;
+ private String digest;
+ private ModelDetails details;
+}
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/ollama/TagsResponse.java b/agent/src/main/java/com/clortox/agent/agent/dto/ollama/TagsResponse.java
new file mode 100644
index 0000000..d50b15e
--- /dev/null
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/ollama/TagsResponse.java
@@ -0,0 +1,6 @@
+package com.clortox.agent.agent.dto.ollama;
+
+import java.util.List;
+
+public record TagsResponse(List models) {
+}
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/ChatCompletionChunk.java b/agent/src/main/java/com/clortox/agent/agent/dto/openai/ChatCompletionChunk.java
similarity index 71%
rename from agent/src/main/java/com/clortox/agent/agent/dto/ChatCompletionChunk.java
rename to agent/src/main/java/com/clortox/agent/agent/dto/openai/ChatCompletionChunk.java
index 961a179..781dd8a 100644
--- a/agent/src/main/java/com/clortox/agent/agent/dto/ChatCompletionChunk.java
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/openai/ChatCompletionChunk.java
@@ -1,7 +1,10 @@
-package com.clortox.agent.agent.dto;
+package com.clortox.agent.agent.dto.openai;
import com.fasterxml.jackson.annotation.JsonInclude;
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
import java.util.List;
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/ChatCompletionRequest.java b/agent/src/main/java/com/clortox/agent/agent/dto/openai/ChatCompletionRequest.java
similarity index 75%
rename from agent/src/main/java/com/clortox/agent/agent/dto/ChatCompletionRequest.java
rename to agent/src/main/java/com/clortox/agent/agent/dto/openai/ChatCompletionRequest.java
index f64a829..f1bba5a 100644
--- a/agent/src/main/java/com/clortox/agent/agent/dto/ChatCompletionRequest.java
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/openai/ChatCompletionRequest.java
@@ -1,9 +1,11 @@
-package com.clortox.agent.agent.dto;
+package com.clortox.agent.agent.dto.openai;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonValue;
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
import java.util.List;
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/ChatCompletionResponse.java b/agent/src/main/java/com/clortox/agent/agent/dto/openai/ChatCompletionResponse.java
similarity index 62%
rename from agent/src/main/java/com/clortox/agent/agent/dto/ChatCompletionResponse.java
rename to agent/src/main/java/com/clortox/agent/agent/dto/openai/ChatCompletionResponse.java
index a696247..8e45046 100644
--- a/agent/src/main/java/com/clortox/agent/agent/dto/ChatCompletionResponse.java
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/openai/ChatCompletionResponse.java
@@ -1,16 +1,13 @@
-package com.clortox.agent.agent.dto;
-
-package com.example.openai.dto;
+package com.clortox.agent.agent.dto.openai;
import com.fasterxml.jackson.annotation.JsonInclude;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonValue;
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
import java.util.List;
-// ========= NON-STREAMING RESPONSE DTO =========
-
@Data
@NoArgsConstructor
@AllArgsConstructor
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/Choice.java b/agent/src/main/java/com/clortox/agent/agent/dto/openai/Choice.java
similarity index 69%
rename from agent/src/main/java/com/clortox/agent/agent/dto/Choice.java
rename to agent/src/main/java/com/clortox/agent/agent/dto/openai/Choice.java
index c760e42..9452064 100644
--- a/agent/src/main/java/com/clortox/agent/agent/dto/Choice.java
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/openai/Choice.java
@@ -1,8 +1,11 @@
-package com.clortox.agent.agent.dto;
+package com.clortox.agent.agent.dto.openai;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/ChunkChoice.java b/agent/src/main/java/com/clortox/agent/agent/dto/openai/ChunkChoice.java
similarity index 69%
rename from agent/src/main/java/com/clortox/agent/agent/dto/ChunkChoice.java
rename to agent/src/main/java/com/clortox/agent/agent/dto/openai/ChunkChoice.java
index 846c734..b8653f2 100644
--- a/agent/src/main/java/com/clortox/agent/agent/dto/ChunkChoice.java
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/openai/ChunkChoice.java
@@ -1,8 +1,11 @@
-package com.clortox.agent.agent.dto;
+package com.clortox.agent.agent.dto.openai;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/Delta.java b/agent/src/main/java/com/clortox/agent/agent/dto/openai/Delta.java
similarity index 62%
rename from agent/src/main/java/com/clortox/agent/agent/dto/Delta.java
rename to agent/src/main/java/com/clortox/agent/agent/dto/openai/Delta.java
index 49c45e0..6acb58c 100644
--- a/agent/src/main/java/com/clortox/agent/agent/dto/Delta.java
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/openai/Delta.java
@@ -1,7 +1,10 @@
-package com.clortox.agent.agent.dto;
+package com.clortox.agent.agent.dto.openai;
import com.fasterxml.jackson.annotation.JsonInclude;
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/FinishReason.java b/agent/src/main/java/com/clortox/agent/agent/dto/openai/FinishReason.java
similarity index 87%
rename from agent/src/main/java/com/clortox/agent/agent/dto/FinishReason.java
rename to agent/src/main/java/com/clortox/agent/agent/dto/openai/FinishReason.java
index f7b7ba6..37fdb49 100644
--- a/agent/src/main/java/com/clortox/agent/agent/dto/FinishReason.java
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/openai/FinishReason.java
@@ -1,4 +1,4 @@
-package com.clortox.agent.agent.dto;
+package com.clortox.agent.agent.dto.openai;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor;
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/Message.java b/agent/src/main/java/com/clortox/agent/agent/dto/openai/Message.java
similarity index 88%
rename from agent/src/main/java/com/clortox/agent/agent/dto/Message.java
rename to agent/src/main/java/com/clortox/agent/agent/dto/openai/Message.java
index 95b0911..abd8d9a 100644
--- a/agent/src/main/java/com/clortox/agent/agent/dto/Message.java
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/openai/Message.java
@@ -1,4 +1,4 @@
-package com.clortox.agent.agent.dto;
+package com.clortox.agent.agent.dto.openai;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/Role.java b/agent/src/main/java/com/clortox/agent/agent/dto/openai/Role.java
similarity index 86%
rename from agent/src/main/java/com/clortox/agent/agent/dto/Role.java
rename to agent/src/main/java/com/clortox/agent/agent/dto/openai/Role.java
index 2f78889..a195210 100644
--- a/agent/src/main/java/com/clortox/agent/agent/dto/Role.java
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/openai/Role.java
@@ -1,4 +1,4 @@
-package com.clortox.agent.agent.dto;
+package com.clortox.agent.agent.dto.openai;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.AllArgsConstructor;
diff --git a/agent/src/main/java/com/clortox/agent/agent/dto/Usage.java b/agent/src/main/java/com/clortox/agent/agent/dto/openai/Usage.java
similarity index 73%
rename from agent/src/main/java/com/clortox/agent/agent/dto/Usage.java
rename to agent/src/main/java/com/clortox/agent/agent/dto/openai/Usage.java
index a0842cc..5b553b0 100644
--- a/agent/src/main/java/com/clortox/agent/agent/dto/Usage.java
+++ b/agent/src/main/java/com/clortox/agent/agent/dto/openai/Usage.java
@@ -1,8 +1,11 @@
-package com.clortox.agent.agent.dto;
+package com.clortox.agent.agent.dto.openai;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
-import lombok.*;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
diff --git a/agent/src/main/java/com/clortox/agent/agent/state/SmartAgent.java b/agent/src/main/java/com/clortox/agent/agent/implementations/SmartAgent.java
similarity index 94%
rename from agent/src/main/java/com/clortox/agent/agent/state/SmartAgent.java
rename to agent/src/main/java/com/clortox/agent/agent/implementations/SmartAgent.java
index 5a1eb7e..6296dbf 100644
--- a/agent/src/main/java/com/clortox/agent/agent/state/SmartAgent.java
+++ b/agent/src/main/java/com/clortox/agent/agent/implementations/SmartAgent.java
@@ -1,4 +1,4 @@
-package com.clortox.agent.agent.state;
+package com.clortox.agent.agent.implementations;
import com.clortox.agent.tools.ISmartAgentTool;
import dev.langchain4j.data.message.SystemMessage;
@@ -27,7 +27,7 @@ public class SmartAgent {
# Personality
- You are a very smart cute anime girl. You talk like an anime girl.
+ You are a kind helpful assistant
""";
private final CompiledGraph agent;
@@ -63,7 +63,4 @@ public class SmartAgent {
AgentExecutor.State state = finalState.orElseThrow();
return state.finalResponse().orElse("Agent failed");
}
-
-
-
}
diff --git a/agent/src/main/java/com/clortox/agent/common/config/GenericControllerAdvice.java b/agent/src/main/java/com/clortox/agent/common/config/GenericControllerAdvice.java
index 024a6cd..3dd9149 100644
--- a/agent/src/main/java/com/clortox/agent/common/config/GenericControllerAdvice.java
+++ b/agent/src/main/java/com/clortox/agent/common/config/GenericControllerAdvice.java
@@ -9,11 +9,13 @@ import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
-import java.net.http.HttpResponse;
@ControllerAdvice
public class GenericControllerAdvice {
+ public GenericControllerAdvice() {
+
+ }
@ExceptionHandler(Throwable.class)
public ResponseEntity generalError(Throwable t, HttpServletRequest request, HttpServletResponse response) {
diff --git a/agent/src/main/java/com/clortox/agent/agent/llm/LLMConfiguration.java b/agent/src/main/java/com/clortox/agent/llm/LLMConfiguration.java
similarity index 83%
rename from agent/src/main/java/com/clortox/agent/agent/llm/LLMConfiguration.java
rename to agent/src/main/java/com/clortox/agent/llm/LLMConfiguration.java
index 29feefa..b330534 100644
--- a/agent/src/main/java/com/clortox/agent/agent/llm/LLMConfiguration.java
+++ b/agent/src/main/java/com/clortox/agent/llm/LLMConfiguration.java
@@ -1,22 +1,16 @@
-package com.clortox.agent.agent.llm;
+package com.clortox.agent.llm;
-import dev.langchain4j.http.client.HttpClientBuilder;
import dev.langchain4j.http.client.spring.restclient.SpringRestClient;
import dev.langchain4j.http.client.spring.restclient.SpringRestClientBuilder;
-import dev.langchain4j.model.chat.Capability;
import dev.langchain4j.model.chat.ChatModel;
import dev.langchain4j.model.ollama.OllamaChatModel;
import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.http.client.HttpClientSettings;
-import org.springframework.boot.http.client.JdkHttpClientBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.VirtualThreadTaskExecutor;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestClient;
-import java.net.http.HttpClient;
-import java.util.Set;
@Configuration
public class LLMConfiguration {
diff --git a/agent/src/main/java/com/clortox/agent/mcp/McpConfig.java b/agent/src/main/java/com/clortox/agent/mcp/McpConfig.java
new file mode 100644
index 0000000..9fa8a27
--- /dev/null
+++ b/agent/src/main/java/com/clortox/agent/mcp/McpConfig.java
@@ -0,0 +1,59 @@
+package com.clortox.agent.mcp;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.modelcontextprotocol.server.McpAsyncServer;
+import io.modelcontextprotocol.server.McpServer;
+import io.modelcontextprotocol.server.McpServerFeatures;
+import io.modelcontextprotocol.server.McpSyncServer;
+import io.modelcontextprotocol.server.transport.WebFluxSseServerTransportProvider;
+import io.modelcontextprotocol.spec.McpSchema;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.reactive.function.server.RouterFunction;
+import reactor.core.publisher.Mono;
+
+import java.util.List;
+
+@Slf4j
+@Configuration
+public class McpConfig {
+
+ @Bean
+ WebFluxSseServerTransportProvider webFluxSseServerTransportProvider(ObjectMapper mapper) {
+ return new WebFluxSseServerTransportProvider(mapper, "/mpc/message");
+ }
+
+ @Bean
+ RouterFunction> mcpRouterFunction(WebFluxSseServerTransportProvider transportProvider) {
+ return transportProvider.getRouterFunction();
+ }
+
+ @Bean
+ McpAsyncServer mcpSyncServer(WebFluxSseServerTransportProvider transportProvider) {
+ var server = McpServer.async(transportProvider)
+ .serverInfo("Clortox's MCP Server", "1.0.0")
+ .capabilities(McpSchema.ServerCapabilities.builder()
+ .logging()
+ .prompts(false)
+ .tools(true)
+ .resources(false, true)
+ .build()
+ ).build();
+
+ var resourceSpec = new McpServerFeatures.AsyncResourceSpecification(
+ new McpSchema.Resource("clortox://vault", "valut", "Contents of obisidian Valut", "plain/text", null),
+ (exchange, request) -> {
+ var response = new McpSchema.ReadResourceResult(List.of(
+ ));
+ return Mono.justOrEmpty(response);
+ }
+ );
+
+ server.addResource(resourceSpec)
+ .doOnSubscribe(v -> log.info("Registered resource"))
+ .subscribe();
+
+ return server;
+ }
+}
diff --git a/agent/src/main/resources/application.yml b/agent/src/main/resources/application.yml
index 8a33bf4..1ebfd47 100644
--- a/agent/src/main/resources/application.yml
+++ b/agent/src/main/resources/application.yml
@@ -27,7 +27,6 @@ springdoc:
swagger-ui:
path: /swagger-ui
-
agent:
prompt:
smartAgent: "${SMART_AGENT_PROMPT_PATH:./data/smartAgent.md}"
diff --git a/agent/src/test/java/com/clortox/agent/AgentApplicationTests.java b/agent/src/test/java/com/clortox/agent/AgentApplicationTests.java
index 40b041a..2025258 100644
--- a/agent/src/test/java/com/clortox/agent/AgentApplicationTests.java
+++ b/agent/src/test/java/com/clortox/agent/AgentApplicationTests.java
@@ -1,5 +1,6 @@
package com.clortox.agent;
+import com.clortox.agent.testconfig.FlywayTestConfiguration;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
diff --git a/agent/src/test/java/com/clortox/agent/BaseTest.java b/agent/src/test/java/com/clortox/agent/BaseTest.java
new file mode 100644
index 0000000..22a0608
--- /dev/null
+++ b/agent/src/test/java/com/clortox/agent/BaseTest.java
@@ -0,0 +1,6 @@
+package com.clortox.agent;
+
+public abstract class BaseTest {
+
+
+}
diff --git a/agent/src/test/java/com/clortox/agent/llm/LLMConfigTest.java b/agent/src/test/java/com/clortox/agent/llm/LLMConfigTest.java
new file mode 100644
index 0000000..bfcfc38
--- /dev/null
+++ b/agent/src/test/java/com/clortox/agent/llm/LLMConfigTest.java
@@ -0,0 +1,66 @@
+package com.clortox.agent.llm;
+
+import com.clortox.agent.BaseTest;
+import dev.langchain4j.model.chat.ChatModel;
+import net.bytebuddy.description.type.TypeList;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.DynamicPropertyRegistrar;
+import org.springframework.test.context.DynamicPropertyRegistry;
+import org.springframework.test.context.DynamicPropertySource;
+import org.testcontainers.containers.BindMode;
+import org.testcontainers.containers.GenericContainer;
+import org.testcontainers.containers.wait.strategy.Wait;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
+import org.testcontainers.utility.DockerImageName;
+
+import java.util.function.Supplier;
+
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+
+@Testcontainers
+@SpringBootTest
+public class LLMConfigTest extends BaseTest {
+
+ private static final int OLLAMA_PORT = 11434;
+ private static final String MODEL = System.getProperty("agent.ollama.model", "qwen3:0.6b");
+
+ @Autowired
+ private ChatModel chatModel;
+
+ @Container
+ static GenericContainer> OLLAMA = new GenericContainer<>(DockerImageName.parse("ollama/ollama:latest"))
+ .withExposedPorts(OLLAMA_PORT)
+ .withEnv("OLLAMA_KEEP_ALIVE", "5m")
+ .withEnv("OLLAMA_MODELS", "/models")
+ .withFileSystemBind("~/.ollama", "/models", BindMode.READ_WRITE)
+ .waitingFor(Wait.forHttp("/").forStatusCode(200));
+
+ @DynamicPropertySource
+ static void props(DynamicPropertyRegistry r) {
+ Supplier