MCP (Model Context Protocol) is a relatively new open standard that allows AI assistants to connect with external data sources and tools. In this article we’re going to show how we can use the Kotlin MCP SDK to create an MCP Server which in turn uses Kotlin Multiplatform (KMP) shared code to obtain the data that the server is providing. Specifically we’re going to add an MCP module to the ClimateTrace KMP sample.
Kotlin MCP module
We’re making use of the following dependency (for the Kotlin MCP SDK)
libs.versions.toml
1
2
mcp = "0.5.0"
mcp-kotlin = { group = "io.modelcontextprotocol", name = "kotlin-sdk", version.ref = "mcp" }
Having added that we can now create our MCP Server instance.
1
2
3
4
5
6
7
8
9
10
11
val server = Server(
Implementation(
name = "ClimateTrace MCP Server",
version = "1.0.0"
),
ServerOptions(
capabilities = ServerCapabilities(
tools = ServerCapabilities.Tools(listChanged = true)
)
)
)
That can be used in turn to add the following tools that we’ll be exposing from the server (MCP also supports exposing resources and prompts).
get-countries
1
2
3
4
5
6
7
8
9
server.addTool(
name = "get-countries",
description = "List of countries"
) {
val countries = climateTraceRepository.fetchCountries()
CallToolResult(
content = countries.map { TextContent("${it.name}, ${it.alpha3}") }
)
}
get-emissions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
server.addTool(
name = "get-emissions",
description = "List emission info for a particular country",
inputSchema = Tool.Input(
properties = JsonObject(
mapOf(
"countryCode" to JsonPrimitive("string"),
"year" to JsonPrimitive("date"),
)
),
required = listOf("countryCode", "year")
)
) { request ->
val countryCode = request.arguments["countryCode"]
val year = request.arguments["year"]
if (countryCode == null || year == null) {
return@addTool CallToolResult(
content = listOf(TextContent("The 'countryCode' and `year` parameters are required."))
)
}
val countryEmissionInfo = climateTraceRepository.fetchCountryEmissionsInfo(
countryCode = countryCode.jsonPrimitive.content,
year = year.jsonPrimitive.content
)
CallToolResult(
content = countryEmissionInfo.map { TextContent(it.emissions.co2.toString()) }
)
}
Note that we’re making use of ClimateTraceRepository
from our shared KMP code to fetch the data needed.
MCP servers are typically accessed over stdio
or sse
. In the stdio
case (as used by Claude Desktop for example) we run the following (wrapping around server
instance we created above).
1
2
3
4
5
6
val transport = StdioServerTransport(
System.`in`.asInput(),
System.out.asSink().buffered()
)
server.connect(transport)
In the case of sse
we use Ktor
server as follows.
1
2
3
4
5
embeddedServer(CIO, host = "0.0.0.0", port = port) {
mcp {
server
}
}.start(wait = true)
Claude Desktop Integration
Now we can use Claude Desktop to test out the integration. We add our MCP server by selecting Edit Config under developer settings. This will allow editing of claude_desktop_config.json
to which we’ll add the following. This will trigger Claude to start our server when it starts up (using jar file created using the gradle :mcp-server:shadowJar
task`).
{
"mcpServers": {
"kotlin-climatetrace": {
"command": "java",
"args": [
"-jar",
"/Users/joreilly/dev/github/ClimateTrace/mcp-server/build/libs/serverAll.jar",
"--stdio"
]
}
}
}
With this in place we can now make climate emission related queries in Claude that will make use, as needed, of the tools we’re exposing from our MCP Server. For example here we’re asking to “Graph France’s emissions from 2020 to 2024”. Note that Claude knew to initially call get-countries
to get the country code it needed for call to get-emissions
.
Claude will also obtain other data it needs as shown for the query below (e.g. it separately fetched population data for those years in response to the query and combined with data served from the MCP server).
Note that this exploration was heavily influenced by this very nice tutorial from the official Kotlin-AI-Examples github repo.
Featured in Kotlin Weekly Issue #461
Related tweet
Kotlin MCP đź’ś Kotlin Multiplatform
— John O'Reilly (@joreilly) May 31, 2025
Wrote a short article on using the Kotlin MCP SDK in a KMP project https://t.co/J2RU9fmlyA