Install
$ agentstack add mcp-rwachters-mcp-tutorials ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ● Shell / process execution Used
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
MCP Tutorials (Kotlin)
Welcome to mcp-tutorials, a collection of educational projects demonstrating various aspects of the Model Context Protocol (MCP) using the Kotlin SDK. Each "part" in this repository focuses on a specific feature or interaction pattern of MCP.
Part 1: Generic STDIO Client with "Hello World" Server
This first tutorial (located in the part1 module) showcases a generalized MCP client written in Kotlin that can connect to any STDIO-based MCP server. For demonstration purposes, it's designed to interact with the simple "greet" tool provided by the HelloWorldServer from our companion mcp-hello-world project.
This example is ideal for understanding:
- How to build a flexible MCP client capable of launching external servers as subprocesses.
- Dynamic discovery and interactive invocation of server-provided tools.
- Basic MCP client-server communication using standard I/O.
Table of Contents
- [What is MCP?](#what-is-mcp)
- [Project Structure](#project-structure)
- [Prerequisites](#prerequisites)
- [Building the Project](#building-the-project)
- [Running Part 1](#running-part-1)
- [How Part 1 Works](#how-part-1-works)
- [Troubleshooting](#troubleshooting)
- [Further Learning](#further-learning)
What is MCP?
The Model Context Protocol (MCP) is an open-source standard for connecting AI applications to external systems. It provides a standardized way for AI applications (like LLMs) to access data sources, tools, and workflows, enabling them to retrieve information and perform tasks in the external world.
Think of MCP as a universal adapter for AI models, allowing them to extend their capabilities beyond their internal knowledge to interact with real-world systems.
Project Structure
This project has a multi-module Gradle setup. For this tutorial, we focus on the part1 module:
mcp-tutorials/
├── build.gradle.kts // Root Gradle configuration
├── settings.gradle.kts // Gradle settings for multi-module project
├── part1/ // The first tutorial module (our client)
│ ├── build.gradle.kts
│ └── src/main/kotlin/eu/torvian/mcp/tutorials/part1/
│ ├── Main.kt // Entry point for the generic client
│ ├── ServerConfig.kt // Data class for subprocess configuration
│ └── StdioMcpClient.kt // The generalized MCP client implementation
├── docs/ // (Future) Additional documentation specific to these tutorials
└── gradle/
├── libs.versions.toml // Version catalog for dependencies
└── wrapper/ // Gradle wrapper files
Note: The HelloWorldServer used in this tutorial is from a separate project. You will need to build its JAR separately.
Prerequisites
- Java 17 or later: Required for running Kotlin applications on the JVM.
- Gradle: (Optional) If you don't use the provided Gradle wrapper, ensure you have Gradle installed.
- Basic understanding of Kotlin: Familiarity with Kotlin syntax and concepts will be helpful.
mcp-hello-world-server.jar: The server JAR from themcp-hello-worldproject. You can obtain it by cloning and building that repository:
``bash git clone https://github.com/rwachters/mcp-hello-world.git cd mcp-hello-world ./gradlew :server:jar # The server JAR will be at server/build/libs/mcp-hello-world-server.jar cd .. # Return to mcp-tutorials root ``
Building the Project
This project uses Gradle to build a "fat JAR" for the part1 client, which includes all necessary dependencies to run independently.
- Clone this repository:
``bash git clone https://github.com/rwachters/mcp-tutorials.git cd mcp-tutorials ``
- Build the
part1client JAR:
``bash ./gradlew :part1:jar ` This will produce part1/build/libs/part1.jar` (or similar, depending on your build configuration).
Running Part 1
To run part1, you will execute its client JAR and provide the command needed to launch an MCP server as an argument. For this tutorial, we'll use the HelloWorldServer JAR from the mcp-hello-world project.
- Ensure you have built the
part1client JAR (as per [Building the Project](#building-the-project)). - Ensure you have the
mcp-hello-world-server.jar(as per [Prerequisites](#prerequisites)). For simplicity in the example below, we assume you've copied it to the root of themcp-tutorialsproject (or you can provide its full path). - Execute the
part1client application:
``bash # Assuming mcp-hello-world-server.jar is in the root of mcp-tutorials java -jar part1/build/libs/part1.jar java -jar mcp-hello-world-server.jar ` The client will start, launch the server as a child process, connect to it, and then enter an interactive loop. The combined output from both the client and its server subprocess will appear in the same terminal: ` Client: Starting server process: java -jar mcp-hello-world-server.jar Client: Server process started with PID: 12345 Starting Hello World MCP Server... Client: Successfully connected to MCP server. Client: Discovered tools from server: greet --- Interactive Tool Caller --- Type a tool name to call it, or 'quit' to exit. > Enter tool name: greet > Enter value for 'name' (string, REQUIRED): Alice Client: Calling tool 'greet' with arguments: {name=Alice} Server: Called 'greet' with name='Alice'. Responding with: 'Hello, Alice!' Server Response: Hello, Alice! > Enter tool name: quit Client: MCP connection closed. Client: Server subprocess terminated. ``
Other Server Examples (Conceptual)
You can use the part1 client with any STDIO-based MCP server by adjusting the command-line arguments. Remember to set any required environment variables in your shell before running the client.
- Generic Docker Server:
``bash # Set your API key in the shell first (e.g., export MY_API_KEY="your_secret") java -jar part1/build/libs/part1.jar docker run -i --rm -e MY_API_KEY my/mcp-server-image ` (Note: -i is for interactive mode, -e MYAPIKEY tells Docker to pass the host's MYAPIKEY` env var into the container.)
- UV Server Example:
``bash # Set Python path or virtual environment activation in the shell if needed java -jar part1/build/libs/part1.jar uv python -m my_uv_mcp_server_module ``
How Part 1 Works
mcp-hello-world-server.jar(frommcp-hello-worldproject):- This is a separate MCP server application.
- It initializes an
MCP Serverinstance with basic capabilities. - Defines a
Toolnamedgreetwith anameargument, using the MCP Kotlin SDK's schema definition. - Registers a lambda function for the
greettool that extracts thenameargument and returns a "Hello, \[name]!"TextContentas aCallToolResult. - Connects to a
StdioServerTransport, which allows it to communicate via standard input/output streams with a client. - Important: Its initial
println("Starting...")message is written toSystem.errto avoid interfering with the client's MCP protocol parsing onSystem.out.
StdioMcpClient.kt(in thispart1module):- Initializes an
MCP Clientinstance. - In
connectToServer(), it launches the specified MCP server command (e.g.,java -jar mcp-hello-world-server.jar) as a separate child process usingProcessBuilder. - It then sets up a
StdioClientTransportto communicate with the server subprocess's standard I/O streams. Any environment variables set in the client's shell environment will be inherited by the server subprocess. - After connecting, it calls
mcp.listTools()to dynamically discover all tools offered by the server. - The
interactiveToolLoop()allows the user to input a tool name and, based on the tool'sinputSchema, prompts for necessary arguments. It then callsmcp.callTool()to execute the server's chosen tool. - The structured
CallToolResultfrom the server is then processed, and itsTextContent(or error messages) is printed to the console.
build.gradle.kts(Fat JARs):- The Gradle build script for the
part1module is configured to create a "fat JAR". This means all dependencies (likekotlin-stdlib,kotlinx-coroutines-core, and the MCP Kotlin SDK itself) are bundled directly into thepart1.jarfile. This makes it easily runnable withjava -jar. - Special
excluderules are applied in thejartask to preventDuplicate entryerrors during the build, particularly forMETA-INFfiles andmodule-info.classfiles that often cause conflicts when merging JARs.
Troubleshooting
NoClassDefFoundError: This typically means your JAR is not a "fat JAR" and is missing runtime dependencies. Ensure you're building with the fat JAR configuration inpart1/build.gradle.ktsand using./gradlew :part1:jar.Duplicate entryduring build: Check yourpart1/build.gradle.ktsjartask for thefrom(configurations.runtimeClasspath.get()...)block and ensure theexcluderules forMETA-INFfiles are present and correct.- Client fails to connect (hangs or errors):
- Ensure the command and arguments you provide to the client for launching the server are absolutely correct and fully specify how to start the target MCP server.
- Verify there are no unexpected issues starting the subprocess (e.g., permissions,
java,docker,uvcommands not in your system's PATH). - Crucially: The
StdioMcpClientexpects only valid MCP JSON-RPC messages on the server'sstdout. If the server prints any plain text (e.g., startup logs, warnings) tostdoutbefore or during the MCP handshake, the client's MCP parser will likely fail or hang. Ensure such output is directed tostderrby the server. (OurHelloWorldServerdoes this correctly by writing startup messages toSystem.err). - SLF4J warnings:
SLF4J(W): No SLF4J providers were found.is a common warning. SLF4J is a logging facade. To remove the warning, you can add a logging implementation likeslf4j-simpleto yourpart1/build.gradle.ktsdependencies (e.g.,implementation("org.slf4j:slf4j-simple:2.0.13")). This is purely for logging output and doesn't affect the core MCP functionality.
Further Learning
- Model Context Protocol Documentation: https://modelcontextprotocol.io/introduction
- MCP Kotlin SDK GitHub: https://github.com/modelcontextprotocol/kotlin-sdk
- Kotlin Coroutines Documentation: https://kotlinlang.org/docs/coroutines-guide.html
- Related Project: MCP Hello World (Kotlin): For the source code of the
HelloWorldServerused in this tutorial, and a simpler client/server example, visit https://github.com/rwachters/mcp-hello-world.
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: rwachters
- Source: rwachters/mcp-tutorials
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.