kotlin-sdk/samples
Repository files (latest commit first)
Filename Latest commit message Latest commit date
dependabot[bot] c61a7ca00c
chore(deps): bump mcp-kotlin from 0.14.0 to 0.15.0 in /samples/weather-stdio-server (#929)
Bumps `mcp-kotlin` from 0.14.0 to 0.15.0.
Updates `io.modelcontextprotocol:kotlin-sdk-client` from 0.14.0 to
0.15.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/modelcontextprotocol/kotlin-sdk/releases">io.modelcontextprotocol:kotlin-sdk-client's
releases</a>.</em></p>
<blockquote>
<h2>0.15.0</h2>
<h2>Description</h2>
<p>This release makes inbound message handling concurrent after the
initialization handshake, adds SSE heartbeats and elicitation schema
validation, and fixes several Streamable HTTP response and
session-lifecycle bugs.</p>
<h3>Breaking Changes</h3>
<p><strong>Concurrent inbound dispatch</strong> by <a
href="https://github.com/devcrocod"><code>@​devcrocod</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/884">#884</a></p>
<p>Inbound messages were processed serially on the transport read loop,
so one slow or peer-awaiting handler (sampling, elicitation, roots)
blocked every later message on the connection, including the responses
and <code>notifications/cancelled</code> those handlers depend on. After
the handshake, handlers may now run concurrently; processing stays
serial during initialization.</p>
<ul>
<li><code>ProtocolOptions</code> / <code>ClientOptions</code> /
<code>ServerOptions</code> gain a <code>handlerCoroutineContext</code>
parameter (defaults to <code>Dispatchers.Default</code>). Concurrency is
bounded internally; there is no opt-out flag by design.</li>
<li><code>RequestHandlerExtra</code> is now a
<code>CoroutineContext.Element</code> and is no longer
user-constructible. It exposes <code>requestId</code>,
<code>method</code>, <code>sendRequest</code>, and
<code>sendNotification</code>, and can be read inside a handler via the
new <code>currentRequestHandlerExtra()</code>.</li>
</ul>
<pre lang="diff"><code>- val extra = RequestHandlerExtra()
+ val extra = currentRequestHandlerExtra()
</code></pre>
<p><strong>Duplicate feature names are rejected at registration</strong>
by <a href="https://github.com/devcrocod"><code>@​devcrocod</code></a>
in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/883">#883</a></p>

<p><code>addTool</code>/<code>addPrompt</code>/<code>addResource</code>/<code>addResourceTemplate</code>
silently replaced an existing entry and emitted a spurious
<code>list_changed</code> notification. They now throw
<code>IllegalArgumentException</code> and leave the existing
registration intact. The batch variants
(<code>addTools</code>/<code>addPrompts</code>/<code>addResources</code>)
are all-or-nothing. To replace a feature, remove it first.</p>
<pre lang="diff"><code>- server.addTool(name = &quot;search&quot;, ...)
// silently overwrote
+ server.removeTool(&quot;search&quot;)
+ server.addTool(name = &quot;search&quot;, ...)
</code></pre>
<p><strong><code>eventStore</code> removed from
<code>mcpStatelessStreamableHttp</code></strong> by <a
href="https://github.com/devcrocod"><code>@​devcrocod</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/909">#909</a></p>
<p>The parameter was never read or written: a stateless endpoint answers
<code>GET</code> with <code>405</code>, so no stream exists to store or
replay events on. The old overload is retained at
<code>DeprecationLevel.ERROR</code> with a <code>ReplaceWith</code>
migration hint. Use <code>mcpStreamableHttp</code> when you need
resumability.</p>
<pre lang="diff"><code>  application.mcpStatelessStreamableHttp(
      path = &quot;/mcp&quot;,
-     eventStore = myEventStore,
  ) { server }
</code></pre>
<h3>Features</h3>
<ul>
<li>Optional SSE heartbeats for Streamable HTTP servers via
<code>mcpStreamableHttp(sseHeartbeatConfig = { ... })</code>, keeping
long-lived streams alive against clients that disconnect on idle.
Heartbeats stay off by default, by <a
href="https://github.com/UnscientificJsZhai"><code>@​UnscientificJsZhai</code></a>
in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/761">#761</a></li>
<li>Accepted form-mode elicitation content is now validated against
<code>requestedSchema</code>; a mismatch fails
<code>createElicitation</code> with <code>McpException</code>
(<code>INVALID_PARAMS</code>) instead of reaching server code unchecked,
by <a href="https://github.com/rea9r"><code>@​rea9r</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/896">#896</a></li>
<li>The Streamable HTTP client now sends the standard
<code>Mcp-Method</code> and <code>Mcp-Name</code> POST headers, by <a
href="https://github.com/AndreKalberer"><code>@​AndreKalberer</code></a>
in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/894">#894</a></li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Stateless Streamable HTTP now closes its per-request session, fixing
unbounded growth of the session registry and notification subscriptions,
by <a
href="https://github.com/KlyneChrysler"><code>@​KlyneChrysler</code></a>
in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/872">#872</a></li>
<li>Streamable HTTP responses keep their status and body when the client
accepts only <code>text/event-stream</code>, by <a
href="https://github.com/devcrocod"><code>@​devcrocod</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/911">#911</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="76b8e7d63a"><code>76b8e7d</code></a>
release: 0.15.0 (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/918">#918</a>)</li>
<li><a
href="dab340f9bf"><code>dab340f</code></a>
fix(server): drop inert eventStore from stateless Streamable HTTP (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/909">#909</a>)</li>
<li><a
href="24c3cd3a69"><code>24c3cd3</code></a>
fix(server): match Accept header as media ranges (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/912">#912</a>)</li>
<li><a
href="7fa438ce00"><code>7fa438c</code></a>
feat(client): send MCP standard POST headers (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/894">#894</a>)</li>
<li><a
href="94745e617c"><code>94745e6</code></a>
chore(deps): bump the kotest group across 1 directory with 3 updates (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/915">#915</a>)</li>
<li><a
href="2b494b7637"><code>2b494b7</code></a>
chore(deps): bump the other-dependencies group across 5 directories with
3 up...</li>
<li><a
href="82fe56e1e8"><code>82fe56e</code></a>
fix(server): preserve Streamable HTTP response status and body (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/911">#911</a>)</li>
<li><a
href="a06d699d6c"><code>a06d699</code></a>
feat: SSE heartbeat (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/761">#761</a>)</li>
<li><a
href="cab669b108"><code>cab669b</code></a>
fix: classify malformed request params as invalid params (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/886">#886</a>)</li>
<li><a
href="b6cb547d58"><code>b6cb547</code></a>
fix(server): preserve id on duplicate initialize errors (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/868">#868</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.14.0...0.15.0">compare
view</a></li>
</ul>
</details>
<br />

Updates `io.modelcontextprotocol:kotlin-sdk-server` from 0.14.0 to
0.15.0
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/modelcontextprotocol/kotlin-sdk/releases">io.modelcontextprotocol:kotlin-sdk-server's
releases</a>.</em></p>
<blockquote>
<h2>0.15.0</h2>
<h2>Description</h2>
<p>This release makes inbound message handling concurrent after the
initialization handshake, adds SSE heartbeats and elicitation schema
validation, and fixes several Streamable HTTP response and
session-lifecycle bugs.</p>
<h3>Breaking Changes</h3>
<p><strong>Concurrent inbound dispatch</strong> by <a
href="https://github.com/devcrocod"><code>@​devcrocod</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/884">#884</a></p>
<p>Inbound messages were processed serially on the transport read loop,
so one slow or peer-awaiting handler (sampling, elicitation, roots)
blocked every later message on the connection, including the responses
and <code>notifications/cancelled</code> those handlers depend on. After
the handshake, handlers may now run concurrently; processing stays
serial during initialization.</p>
<ul>
<li><code>ProtocolOptions</code> / <code>ClientOptions</code> /
<code>ServerOptions</code> gain a <code>handlerCoroutineContext</code>
parameter (defaults to <code>Dispatchers.Default</code>). Concurrency is
bounded internally; there is no opt-out flag by design.</li>
<li><code>RequestHandlerExtra</code> is now a
<code>CoroutineContext.Element</code> and is no longer
user-constructible. It exposes <code>requestId</code>,
<code>method</code>, <code>sendRequest</code>, and
<code>sendNotification</code>, and can be read inside a handler via the
new <code>currentRequestHandlerExtra()</code>.</li>
</ul>
<pre lang="diff"><code>- val extra = RequestHandlerExtra()
+ val extra = currentRequestHandlerExtra()
</code></pre>
<p><strong>Duplicate feature names are rejected at registration</strong>
by <a href="https://github.com/devcrocod"><code>@​devcrocod</code></a>
in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/883">#883</a></p>

<p><code>addTool</code>/<code>addPrompt</code>/<code>addResource</code>/<code>addResourceTemplate</code>
silently replaced an existing entry and emitted a spurious
<code>list_changed</code> notification. They now throw
<code>IllegalArgumentException</code> and leave the existing
registration intact. The batch variants
(<code>addTools</code>/<code>addPrompts</code>/<code>addResources</code>)
are all-or-nothing. To replace a feature, remove it first.</p>
<pre lang="diff"><code>- server.addTool(name = &quot;search&quot;, ...)
// silently overwrote
+ server.removeTool(&quot;search&quot;)
+ server.addTool(name = &quot;search&quot;, ...)
</code></pre>
<p><strong><code>eventStore</code> removed from
<code>mcpStatelessStreamableHttp</code></strong> by <a
href="https://github.com/devcrocod"><code>@​devcrocod</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/909">#909</a></p>
<p>The parameter was never read or written: a stateless endpoint answers
<code>GET</code> with <code>405</code>, so no stream exists to store or
replay events on. The old overload is retained at
<code>DeprecationLevel.ERROR</code> with a <code>ReplaceWith</code>
migration hint. Use <code>mcpStreamableHttp</code> when you need
resumability.</p>
<pre lang="diff"><code>  application.mcpStatelessStreamableHttp(
      path = &quot;/mcp&quot;,
-     eventStore = myEventStore,
  ) { server }
</code></pre>
<h3>Features</h3>
<ul>
<li>Optional SSE heartbeats for Streamable HTTP servers via
<code>mcpStreamableHttp(sseHeartbeatConfig = { ... })</code>, keeping
long-lived streams alive against clients that disconnect on idle.
Heartbeats stay off by default, by <a
href="https://github.com/UnscientificJsZhai"><code>@​UnscientificJsZhai</code></a>
in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/761">#761</a></li>
<li>Accepted form-mode elicitation content is now validated against
<code>requestedSchema</code>; a mismatch fails
<code>createElicitation</code> with <code>McpException</code>
(<code>INVALID_PARAMS</code>) instead of reaching server code unchecked,
by <a href="https://github.com/rea9r"><code>@​rea9r</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/896">#896</a></li>
<li>The Streamable HTTP client now sends the standard
<code>Mcp-Method</code> and <code>Mcp-Name</code> POST headers, by <a
href="https://github.com/AndreKalberer"><code>@​AndreKalberer</code></a>
in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/894">#894</a></li>
</ul>
<h3>Fixed</h3>
<ul>
<li>Stateless Streamable HTTP now closes its per-request session, fixing
unbounded growth of the session registry and notification subscriptions,
by <a
href="https://github.com/KlyneChrysler"><code>@​KlyneChrysler</code></a>
in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/872">#872</a></li>
<li>Streamable HTTP responses keep their status and body when the client
accepts only <code>text/event-stream</code>, by <a
href="https://github.com/devcrocod"><code>@​devcrocod</code></a> in <a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/pull/911">#911</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="76b8e7d63a"><code>76b8e7d</code></a>
release: 0.15.0 (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/918">#918</a>)</li>
<li><a
href="dab340f9bf"><code>dab340f</code></a>
fix(server): drop inert eventStore from stateless Streamable HTTP (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/909">#909</a>)</li>
<li><a
href="24c3cd3a69"><code>24c3cd3</code></a>
fix(server): match Accept header as media ranges (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/912">#912</a>)</li>
<li><a
href="7fa438ce00"><code>7fa438c</code></a>
feat(client): send MCP standard POST headers (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/894">#894</a>)</li>
<li><a
href="94745e617c"><code>94745e6</code></a>
chore(deps): bump the kotest group across 1 directory with 3 updates (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/915">#915</a>)</li>
<li><a
href="2b494b7637"><code>2b494b7</code></a>
chore(deps): bump the other-dependencies group across 5 directories with
3 up...</li>
<li><a
href="82fe56e1e8"><code>82fe56e</code></a>
fix(server): preserve Streamable HTTP response status and body (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/911">#911</a>)</li>
<li><a
href="a06d699d6c"><code>a06d699</code></a>
feat: SSE heartbeat (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/761">#761</a>)</li>
<li><a
href="cab669b108"><code>cab669b</code></a>
fix: classify malformed request params as invalid params (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/886">#886</a>)</li>
<li><a
href="b6cb547d58"><code>b6cb547</code></a>
fix(server): preserve id on duplicate initialize errors (<a
href="https://redirect.github.com/modelcontextprotocol/kotlin-sdk/issues/868">#868</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/modelcontextprotocol/kotlin-sdk/compare/0.14.0...0.15.0">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-03 18:46:44 +02:00
..
kotlin-mcp-client chore(deps): bump io.modelcontextprotocol:kotlin-sdk-client from 0.14.0 to 0.15.0 in /samples/kotlin-mcp-client (#925) 2026-08-03 13:03:13 +02:00
kotlin-mcp-server chore(deps): bump mcp-kotlin from 0.14.0 to 0.15.0 in /samples/kotlin-mcp-server (#926) 2026-08-03 13:20:37 +02:00
kotlinlang-mcp-server chore(deps): bump mcp-kotlin from 0.14.0 to 0.15.0 in /samples/kotlinlang-mcp-server (#927) 2026-08-03 13:39:04 +02:00
notebooks samples: update mcp-kotlin to 0.10.0 across sample projects (#645) 2026-03-30 23:47:31 +03:00
simple-streamable-server chore(deps): bump mcp-kotlin from 0.14.0 to 0.15.0 in /samples/simple-streamable-server (#928) 2026-08-03 17:31:38 +02:00
weather-stdio-server chore(deps): bump mcp-kotlin from 0.14.0 to 0.15.0 in /samples/weather-stdio-server (#929) 2026-08-03 18:46:44 +02:00
README.md sample: kotlinlang mcp server (#713) 2026-04-27 15:07:03 +02:00

Kotlin MCP SDK Samples

Runnable projects demonstrating MCP server and client implementations with the Kotlin MCP SDK. For background on the protocol itself, see the MCP documentation.

Overview

Sample Type Transport MCP Features
simple-streamable-server Server Streamable HTTP Tools, Resources, Prompts, Logging
kotlinlang-mcp-server Server Streamable HTTP Tools
kotlin-mcp-server Server STDIO, SSE Tools, Resources, Prompts
weather-stdio-server Server STDIO Tools
kotlin-mcp-client Client STDIO Tool discovery & invocation
notebooks Client (Notebook) Streamable HTTP Tool discovery & invocation

Getting Started

  • Building a server? Start with simple-streamable-server — it uses the recommended Streamable HTTP transport and covers tools, resources, prompts, and logging.
  • Building a client? Open the notebooks sample for a step-by-step walkthrough, or see kotlin-mcp-client for a full CLI client with Anthropic API integration.

Samples

Simple Streamable HTTP Server

A minimal Streamable HTTP server with optional Bearer token authentication. Demonstrates tools (greet, multi-greet), a prompt template, a resource, and server-to-client logging notifications. Read more →

Kotlinlang MCP Server

A Streamable HTTP server that exposes the official Kotlin documentation (kotlinlang.org) to LLM clients — full-text search via Algolia and page retrieval in markdown. Demonstrates wrapping a real external API in an MCP server with in-memory caching. Read more →

Kotlin MCP Server

A multi-transport server supporting STDIO, SSE (plain), and SSE (Ktor plugin). Useful for exploring different transport modes side by side. Read more →

Weather STDIO Server

A focused STDIO server that exposes weather forecast and alert tools backed by the weather.gov API. Includes Claude Desktop integration instructions. Read more →

Kotlin MCP Client

An interactive CLI client that connects to any MCP server over STDIO and routes queries through Anthropic's Claude API, bridging MCP tools with LLM conversations. Read more →

MCP Client Notebook

A Kotlin notebook that connects to a remote MCP server via Streamable HTTP and demonstrates ping, tool listing, and tool invocation — all in an interactive cell-by-cell format. Read more →