feat: add Spring Boot MCP Toolbox PostgreSQL example application - #87
Merged
stenalpjolly merged 6 commits intoSep 13, 2026
Conversation
anubhav756
approved these changes
Sep 11, 2026
- Define domain-specific PostgreSQL tools in tools.yaml (get-all-products, get-product-by-id, get-products-by-category, add-product, delete-product-by-id, list_tables, get-table-schema) - Update ProductCatalogService to invoke declarative tools with typed arguments instead of raw SQL strings - Update scripts/start-containers.sh to mount tools.yaml and execute toolbox with --config - Update unit tests (ProductCatalogServiceTest) and live integration tests (SpringBootPostgresApplicationTests) to assert declarative tool behavior - Document declarative tools architecture and configuration in README.md
…tracts
- Add .orTimeout(10, TimeUnit.SECONDS) across all asynchronous MCP client calls
- Offload CPU-bound Jackson deserialization to ForkJoinPool via .thenApplyAsync
- Enforce database integrity with price/stock CHECK constraints and category index in schema.sql
- Mark mandatory parameters with explicit required: true in tools.yaml
- Wire delete-product-by-id end-to-end through service and DELETE /api/products/{id} endpoint
- Refactor POST /api/products to return 201 Created with Location header and entity body
- Make integration tests hermetic without sequential @TestMethodOrder coupling
- Eliminate flaky substring checks with Jackson JsonNode structural assertions
- Parameterize credentials in start-containers.sh with environment variable defaults
- Add release-please version annotation to mcp-toolbox-sdk-java dependency in pom.xml - Add Maven dependency code snippet with release-please annotation in README.md - Add demo-applications/spring-boot-postgres files to extra-files in release-please-config.json
- Align product ID type to Long across ProductCatalogService and ProductController - Robustly parse delete response JSON payload using ObjectMapper and verify deleted ID - Segregate standalone unit tests and container integration tests with Surefire and Failsafe - Replace deprecated Docker --link flag with user-defined bridge network in container scripts - Update README with segregated test commands
stenalpjolly
force-pushed
the
stenalpjolly/stenalpjolly_spring-boot-postgres-example
branch
from
September 11, 2026 16:08
436897a to
a8eb675
Compare
Contributor
Author
|
@anubhav756 Thank you for the review and suggestions! I have addressed all 4 review comments and rebased the branch onto latest
All local unit tests and build validations are passing cleanly. |
Add a unit test asserting deleteProductById returns false when the delete-product-by-id tool returns an unparseable payload, exercising the previously uncovered JsonProcessingException branch.
stenalpjolly
deleted the
stenalpjolly/stenalpjolly_spring-boot-postgres-example
branch
September 13, 2026 05:22
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a comprehensive, hardened Spring Boot 3 example application demonstrating seamless integration with the Java MCP Toolbox SDK (
com.google.cloud.mcp:mcp-toolbox-sdk-java:1.0.0), connecting to a containerized MCP Toolbox server configured with declarative tools (tools.yaml) backed by a PostgreSQL instance.Expectation & Implementation
demo-applications/spring-boot-postgres/configuringMcpToolboxClientas a Spring-managed bean.tools.yaml): Defines domain-specific PostgreSQL tools (get-all-products,get-product-by-id,get-products-by-category,add-product,delete-product-by-id,list_tables,get-table-schema) with explicitrequired: trueparameter constraints, parameterized SQL ($1, $2, ...), andRETURNINGclauses.ProductCatalogService): Implements product catalog operations via MCP JSON-RPC tools using async-first non-blockingCompletableFuturemethods, defensive.orTimeout(10, TimeUnit.SECONDS)boundaries,.thenApplyAsyncthread handoffs for CPU Jackson deserialization, and fail-fast exception propagation.ProductController): Exposes REST endpoints (GET /api/tools,GET /api/products,GET /api/products/{id},GET /api/products/category/{category},POST /api/products,DELETE /api/products/{id}).POSTreturns201 CREATEDwith an RFC-compliantLocation: /api/products/{id}header and persisted entity body;DELETEreturns204 NO_CONTENTor404 NOT_FOUND.schema.sql): Enforces database-level invariants (CHECK (price >= 0),CHECK (stock >= 0)) and provisions an indexidx_products_categoryon theproductstable.scripts/start-containers.shandscripts/stop-containers.shwith parameterized credentials (${POSTGRES_USER:-mcpuser}), read-only volume mounting (:ro), and healthcheck readiness probes.<x-please>): Configureddemo-applications/spring-boot-postgres/pom.xmlandREADME.mdwith<!-- {x-version-update:mcp-toolbox-sdk-java:current} -->annotations and registered them inrelease-please-config.jsonextra-files to automate SDK version updates on subsequent releases.Test cases
ProductCatalogServiceTest): 14 tests mockingMcpToolboxClientwith Mockito, verifying:get-product-by-idget-products-by-categoryadd-producttool returningProductadd-producttable_name) forget-table-schematooldelete-product-by-idtool and 404 handlingSpringBootPostgresApplicationTests): 15 self-contained, state-independent tests against real Docker containers verifying:get-all-productsadd-productand querying them backget-table-schemawith JacksonJsonNodestructural assertions/api/tools/api/products/api/products/{id}/api/products/category/{category}/api/productsreturning 201 Created, Location header, and body/api/productsinput validation rejection (HTTP 400)/api/productsnull price rejection (HTTP 400)/api/products/{id}returning 204 No Content and subsequent 404 Not FoundNULLAcceptance criteria
mvn clean test -Dnet.bytebuddy.experimental=true)src/main/java) untouched with 0 Checkstyle violations and 0 test regressions (130/130 root tests passing)google-java-formatand under 350 lines (below 700-line ceiling)x-version-updateannotations andrelease-please-config.jsoninclusionBreaking changes
None. This adds a self-contained example application under
demo-applications/spring-boot-postgres/and introduces no breaking changes to the core SDK public APIs.