Skip to content

dbbaskette/mcp-client

✨ Interactive MCP Client

Java 21 Spring Boot Spring AI MCP Release License

Test and interact with MCP servers directly — no LLM required.
Built with Spring Boot + Spring AI + WebFlux. Supports STDIO, SSE, and Streamable HTTP transports.

┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃  🚀 Interactive Model Context Protocol (MCP) Client  ┃
┃      Debug • Inspect • Call • Validate • Repeat      ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛


🔗 Table of Contents


⚡ Highlights

  • 🧵 Multiple transports: STDIO, SSE, Streamable HTTP
  • 🧪 Built for testing MCP servers without an LLM
  • 🔐 First-class support for JWT Bearer authentication (works with API gateways / protected servers)
  • 🧭 Interactive CLI: list tools, describe tools, invoke tools with JSON
  • 🧱 Spring profile-based configuration for clean separation
  • 🛡️ Resilient SSE handling with compatibility tweaks for diverse servers

🧰 Requirements

  • Java 21+
  • Maven 3.6+
  • Node.js (only if testing STDIO servers like npm MCP servers)

Set environment variables as needed:

# If using Anthropic (optional LLM use in other contexts)
export ANTHROPIC_API_KEY=your-anthropic-api-key

# If testing Brave Search server via STDIO
export BRAVE_API_KEY=your-brave-api-key

# If connecting to a JWT-protected SSE server
export SERVER_JWT=your-jwt-token

🚀 Quick Start

# Clone
git clone https://github.com/dbbaskette/mcp-client.git
cd mcp-client

# Run (default: stdio profile)
./mcp-client.sh

# Run with SSE
./mcp-client.sh --profile sse

# Rebuild and run (any profile)
./mcp-client.sh --rebuild -p sse

Pro tip: add -v/--verbose to the script for extra logs during local debugging.


🧩 Transports & Profiles

  • 🔌 stdio: process-based servers (great for npm MCP servers)
  • 📡 sse: Server-Sent Events over HTTP (great for web MCP servers)
  • 🌊 streamable: HTTP with streaming responses (experimental servers)

Files live under src/main/resources:

  • application-stdio.properties
  • application-sse.properties
  • application-streamable.properties

🔐 SSE Configuration (Auth & No-Auth)

Below are two common SSE setups.

Authenticated SSE (JWT Bearer)

Some servers authenticate at a base path (e.g., /mcp) and stream at /sse.

# src/main/resources/application-sse.properties
spring.ai.mcp.client.sse.connections.secure.url=http://your-host:8585/mcp
spring.ai.mcp.client.sse.connections.secure.sse-endpoint=/sse
spring.ai.mcp.client.sse.connections.secure.headers.Authorization=Bearer ${SERVER_JWT}

# Optional resilience
apring.ai.mcp.client.sse.connections.secure.timeout=60s
spring.ai.mcp.client.sse.connections.secure.connect-timeout=30s
spring.ai.mcp.client.sse.connections.secure.read-timeout=60s

Public SSE (No Auth)

If your server doesn’t require authentication, configure it like this:

# src/main/resources/application-sse.properties
spring.ai.mcp.client.sse.connections.public.url=http://localhost:8080
spring.ai.mcp.client.sse.connections.public.sse-endpoint=/sse

Global application settings (already tuned for clean output and resilience) in application.properties:

spring.application.name=mcp-client
spring.ai.mcp.client.toolcallback.enabled=true
spring.ai.mcp.client.type=SYNC

# Trim noisy logs, keep essentials
logging.level.io.modelcontextprotocol.client=INFO
logging.level.io.modelcontextprotocol.spec=INFO
logging.level.org.springframework.ai.mcp=INFO
logging.level.reactor.core.publisher.Operators=WARN

# Resilient SSE handling
spring.ai.mcp.client.connection.resilient=true
spring.ai.mcp.client.sse.lenient-parsing=true

Note: Some SSE servers may emit occasional events with missing event: types; the client is configured to ignore benign anomalies.


🖥️ CLI Usage

Start the client and use the interactive shell:

mcp-client> help
mcp-client> list-tools
mcp-client> describe-tool <toolName>
mcp-client> tool <toolName> {"param":"value"}
mcp-client> status
mcp-client> exit

Script options:

./mcp-client.sh [OPTIONS]
  -p, --profile <stdio|sse|streamable>
  --rebuild                 # clean build before run
  -v, --verbose             # verbose script logging
  -h, --help                # help

🧪 Examples

  • List all available tools from connected servers:
mcp-client> list-tools
  • Describe a tool’s input schema and usage:
mcp-client> describe-tool spring_ai_mcp_client_example_tool
  • Invoke a tool with JSON parameters:
mcp-client> tool spring_ai_mcp_client_example_tool {"query":"warehouses","limit":5}

🧯 Troubleshooting

  • 500 on SSE endpoint: Ensure a valid Authorization header (for protected servers) and correct base/endpoint paths.
  • Random SSE event anomalies: Client ignores benign null/missing-type events by default.
  • Timeouts while listing tools: increase timeouts in your SSE connection block.
  • Still stuck? Run with --rebuild and verify your env vars: echo $SERVER_JWT.

❓ FAQ

  • Do I need an LLM?
    No. This client is purposely LLM-free for server testing and validation.

  • Can I add my own servers easily?
    Yes — add them to the appropriate profile properties file.

  • Can I use this for other JWT-protected SSE servers?
    Absolutely. Set the Authorization header and correct base/endpoint paths.


🗂️ Project Structure

src/main/java/com/baskettecase/mcpclient/
├─ McpClientApplication.java        # Main Spring Boot app
├─ cli/
│  └─ CliRunner.java                # Interactive CLI
└─ config/
   ├─ McpConnectionConfigService.java
   ├─ McpErrorHandlingConfig.java    # SSE event compatibility handling
   ├─ SslConfiguration.java          # SSL relax (opt-in via properties)
   └─ WebClientConfig.java           # Global WebClient customization

src/main/resources/
├─ application.properties            # Common settings
├─ application-stdio.properties      # STDIO profile config
├─ application-sse.properties        # SSE profile config (JWT-ready)
└─ application-streamable.properties # Streamable HTTP profile config

🤝 Contributing

  • Fork the repo, create a feature branch, commit, and open a PR
  • Use clear commit messages (e.g., feat: add X, fix: handle Y)
git checkout -b feat/my-improvement
# make changes
git commit -m "feat: my improvement"
git push origin feat/my-improvement

📄 License

Licensed under the Apache 2.0 License. See LICENSE for details.


🔗 Useful Links

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors