From 7eb1efd9aa5aa285b6fd15f87d791165337824f4 Mon Sep 17 00:00:00 2001 From: Roger Vinas Date: Tue, 15 Apr 2025 22:51:46 +0200 Subject: [PATCH 1/7] mcp-server test --- mcp-server/build.gradle.kts | 4 + .../rogervinas/McpServerApplicationTest.kt | 93 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 mcp-server/src/test/kotlin/com/rogervinas/McpServerApplicationTest.kt diff --git a/mcp-server/build.gradle.kts b/mcp-server/build.gradle.kts index da2a40e..1e7ee4c 100644 --- a/mcp-server/build.gradle.kts +++ b/mcp-server/build.gradle.kts @@ -32,6 +32,10 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter") testImplementation("org.junit.jupiter:junit-jupiter-params") testRuntimeOnly("org.junit.platform:junit-platform-launcher") + + testImplementation("org.mockito:mockito-core:5.17.0") + testImplementation("org.mockito:mockito-junit-jupiter:5.17.0") + testImplementation("com.nhaarman.mockitokotlin2:mockito-kotlin:2.2.0") } dependencyManagement { diff --git a/mcp-server/src/test/kotlin/com/rogervinas/McpServerApplicationTest.kt b/mcp-server/src/test/kotlin/com/rogervinas/McpServerApplicationTest.kt new file mode 100644 index 0000000..ffbc5b6 --- /dev/null +++ b/mcp-server/src/test/kotlin/com/rogervinas/McpServerApplicationTest.kt @@ -0,0 +1,93 @@ +package com.rogervinas + +import com.nhaarman.mockitokotlin2.argumentCaptor +import com.nhaarman.mockitokotlin2.whenever +import com.rogervinas.tools.BookingService +import io.modelcontextprotocol.client.McpClient +import io.modelcontextprotocol.client.McpSyncClient +import io.modelcontextprotocol.client.transport.HttpClientSseClientTransport +import io.modelcontextprotocol.spec.McpSchema.CallToolRequest +import io.modelcontextprotocol.spec.McpSchema.TextContent +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.MethodOrderer +import org.junit.jupiter.api.Order +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.TestInstance +import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS +import org.junit.jupiter.api.TestMethodOrder +import org.mockito.Mockito.doReturn +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT +import org.springframework.boot.test.web.server.LocalServerPort +import org.springframework.test.context.bean.override.mockito.MockitoBean +import java.time.LocalDate +import java.util.function.Consumer + + +@SpringBootTest(webEnvironment = RANDOM_PORT) +@TestInstance(PER_CLASS) +@TestMethodOrder(MethodOrderer.OrderAnnotation::class) +class McpServerApplicationTest { + + @LocalServerPort + val port: Int = 0 + + val client: McpSyncClient by lazy { + McpClient.sync(HttpClientSseClientTransport("http://localhost:$port")).build().apply { + initialize() + ping() + } + } + + @AfterAll + fun closeClient() { + client.closeGracefully() + } + + @MockitoBean + lateinit var bookingService: BookingService + + @Test + @Order(0) + fun `should list tools`() { + assertThat(client.listTools().tools).singleElement().satisfies(Consumer { + assertThat(it.name).isEqualTo("book") + assertThat(it.description).isEqualTo("make a reservation for accommodation for a given city and date") + }) + } + + @Test + fun `should book`() { + val bookResult = "Booking is done!" + val cityCaptor = argumentCaptor() + val checkinDateCaptor = argumentCaptor() + val checkoutDateCaptor = argumentCaptor() + doReturn(bookResult) + .whenever(bookingService) + .book(cityCaptor.capture(), checkinDateCaptor.capture(), checkoutDateCaptor.capture()) + + val city = "Barcelona" + val checkinDate = "2025-04-15" + val checkoutDate = "2025-04-18" + val result = client.callTool( + CallToolRequest( + "book", + mapOf( + "city" to city, + "checkinDate" to checkinDate, + "checkoutDate" to checkoutDate + ) + ) + ) + + assertThat(result.isError).isFalse() + assertThat(result.content).singleElement().isInstanceOfSatisfying(TextContent::class.java) { + // TODO why is text double quoted? + assertThat(it.text).isEqualTo("\"$bookResult\"") + } + assertThat(cityCaptor.allValues).singleElement().isEqualTo(city) + assertThat(checkinDateCaptor.allValues).singleElement().isEqualTo(LocalDate.parse(checkinDate)) + assertThat(checkoutDateCaptor.allValues).singleElement().isEqualTo(LocalDate.parse(checkoutDate)) + } +} From cb38bdf0d0ddd97e1d3460c75ec9b4e89a7ecbef Mon Sep 17 00:00:00 2001 From: Roger Vinas Date: Tue, 15 Apr 2025 22:58:13 +0200 Subject: [PATCH 2/7] Split workflows --- .../workflows/{ci.yml => ci-chat-server.yml} | 12 ++++--- .github/workflows/ci-mcp-server.yml | 32 +++++++++++++++++++ 2 files changed, 39 insertions(+), 5 deletions(-) rename .github/workflows/{ci.yml => ci-chat-server.yml} (80%) create mode 100644 .github/workflows/ci-mcp-server.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci-chat-server.yml similarity index 80% rename from .github/workflows/ci.yml rename to .github/workflows/ci-chat-server.yml index 94f8bdb..a3da732 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci-chat-server.yml @@ -3,8 +3,14 @@ name: CI on: push: branches: [ main ] + paths: + - .github/workflows/ci-chat-server.yml + - chat-server/** pull_request: branches: [ main ] + paths: + - .github/workflows/ci-chat-server.yml + - chat-server/** jobs: build: @@ -29,11 +35,7 @@ jobs: java-version: 21 distribution: temurin - - name: Build mcp-server - working-directory: mcp-server - run: ./gradlew build --no-daemon - - - name: Build chat-server + - name: Build working-directory: chat-server run: ./gradlew build --no-daemon diff --git a/.github/workflows/ci-mcp-server.yml b/.github/workflows/ci-mcp-server.yml new file mode 100644 index 0000000..50de6a3 --- /dev/null +++ b/.github/workflows/ci-mcp-server.yml @@ -0,0 +1,32 @@ +name: mcp-server + +on: + push: + branches: [ main ] + paths: + - .github/workflows/ci-mcp-server.yml + - mcp-server/** + pull_request: + branches: [ main ] + paths: + - .github/workflows/ci-mcp-server.yml + - mcp-server/** + +jobs: + build: + name: build + runs-on: ubuntu-latest + steps: + + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Java + uses: actions/setup-java@v4 + with: + java-version: 21 + distribution: temurin + + - name: Build + working-directory: mcp-server + run: ./gradlew build --no-daemon From 085bcffb58d55b0ee6d139210db99e2f228a0cee Mon Sep 17 00:00:00 2001 From: Roger Vinas Date: Tue, 15 Apr 2025 22:58:58 +0200 Subject: [PATCH 3/7] Rename --- .github/workflows/ci-chat-server.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-chat-server.yml b/.github/workflows/ci-chat-server.yml index a3da732..5c0887c 100644 --- a/.github/workflows/ci-chat-server.yml +++ b/.github/workflows/ci-chat-server.yml @@ -1,4 +1,4 @@ -name: CI +name: chat-server on: push: From 89b4097f8b867138285a4cbc710d926e83c58666 Mon Sep 17 00:00:00 2001 From: Roger Vinas Date: Tue, 15 Apr 2025 23:02:15 +0200 Subject: [PATCH 4/7] Gradle cache --- .github/workflows/ci-chat-server.yml | 1 + .github/workflows/ci-mcp-server.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/ci-chat-server.yml b/.github/workflows/ci-chat-server.yml index 5c0887c..385251e 100644 --- a/.github/workflows/ci-chat-server.yml +++ b/.github/workflows/ci-chat-server.yml @@ -34,6 +34,7 @@ jobs: with: java-version: 21 distribution: temurin + cache: gradle - name: Build working-directory: chat-server diff --git a/.github/workflows/ci-mcp-server.yml b/.github/workflows/ci-mcp-server.yml index 50de6a3..b1e836f 100644 --- a/.github/workflows/ci-mcp-server.yml +++ b/.github/workflows/ci-mcp-server.yml @@ -26,6 +26,7 @@ jobs: with: java-version: 21 distribution: temurin + cache: gradle - name: Build working-directory: mcp-server From 8ae114f968c8e4c0b9f680be195a8b46ce90f614 Mon Sep 17 00:00:00 2001 From: Roger Vinas Date: Tue, 15 Apr 2025 23:04:27 +0200 Subject: [PATCH 5/7] Rename --- .github/workflows/ci-chat-server.yml | 2 +- .github/workflows/ci-mcp-server.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-chat-server.yml b/.github/workflows/ci-chat-server.yml index 385251e..ca72134 100644 --- a/.github/workflows/ci-chat-server.yml +++ b/.github/workflows/ci-chat-server.yml @@ -1,4 +1,4 @@ -name: chat-server +name: CI on: push: diff --git a/.github/workflows/ci-mcp-server.yml b/.github/workflows/ci-mcp-server.yml index b1e836f..1d57306 100644 --- a/.github/workflows/ci-mcp-server.yml +++ b/.github/workflows/ci-mcp-server.yml @@ -1,4 +1,4 @@ -name: mcp-server +name: CI on: push: From 9d5a71f96cd16ada2921b2102288664cc9ab2ebc Mon Sep 17 00:00:00 2001 From: Roger Vinas Date: Tue, 15 Apr 2025 23:05:31 +0200 Subject: [PATCH 6/7] Cache name --- .github/workflows/ci-chat-server.yml | 1 + .github/workflows/ci-mcp-server.yml | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/workflows/ci-chat-server.yml b/.github/workflows/ci-chat-server.yml index ca72134..9dfd88b 100644 --- a/.github/workflows/ci-chat-server.yml +++ b/.github/workflows/ci-chat-server.yml @@ -35,6 +35,7 @@ jobs: java-version: 21 distribution: temurin cache: gradle + cache-dependency-path: chat-server/build.gradle.kts - name: Build working-directory: chat-server diff --git a/.github/workflows/ci-mcp-server.yml b/.github/workflows/ci-mcp-server.yml index 1d57306..4f824c9 100644 --- a/.github/workflows/ci-mcp-server.yml +++ b/.github/workflows/ci-mcp-server.yml @@ -27,6 +27,7 @@ jobs: java-version: 21 distribution: temurin cache: gradle + cache-dependency-path: mcp-server/build.gradle.kts - name: Build working-directory: mcp-server From e796ce036cce30d4191f97c17870211119ec5b5f Mon Sep 17 00:00:00 2001 From: Roger Vinas Date: Tue, 15 Apr 2025 23:08:55 +0200 Subject: [PATCH 7/7] Rename --- .github/workflows/ci-chat-server.yml | 2 +- .github/workflows/ci-mcp-server.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-chat-server.yml b/.github/workflows/ci-chat-server.yml index 9dfd88b..b9ec39e 100644 --- a/.github/workflows/ci-chat-server.yml +++ b/.github/workflows/ci-chat-server.yml @@ -1,4 +1,4 @@ -name: CI +name: chat-server on: push: diff --git a/.github/workflows/ci-mcp-server.yml b/.github/workflows/ci-mcp-server.yml index 4f824c9..46fc508 100644 --- a/.github/workflows/ci-mcp-server.yml +++ b/.github/workflows/ci-mcp-server.yml @@ -1,4 +1,4 @@ -name: CI +name: mcp-server on: push: