Skip to content

Commit 8698b96

Browse files
authored
modularize sdk (#208)
* Modularize SDK: migrated client and server implementations to separate modules. Removed old configuration files and reorganized the source code structure * add support native targets and update js/wasm configurations * Refactor sample projects: add samples as composite builds, replace hardcoded dependencies with version catalog, remove obsolete gradle wrapper files * Update .gitignore: exclude SWE agent directories (.claude/ and .junie/) * Refine CodeQL workflow: update Kotlin build steps to target individual modules separately instead of building all at once
1 parent 641df74 commit 8698b96

File tree

92 files changed

+979
-2003
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

92 files changed

+979
-2003
lines changed

.github/workflows/codeql.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,13 @@ jobs:
5353
- name: Build Kotlin sources
5454
run: |
5555
./gradlew \
56-
:build -Pkotlin.incremental=false \
57-
--no-daemon --stacktrace --parallel
56+
:kotlin-sdk-core:compileKotlinJvm \
57+
:kotlin-sdk-client:compileKotlinJvm \
58+
:kotlin-sdk-server:compileKotlinJvm \
59+
:kotlin-sdk:compileKotlinJvm \
60+
:kotlin-sdk-test:compileKotlinJvm \
61+
-Pkotlin.incremental=false \
62+
--no-daemon --stacktrace
5863
5964
- name: Analyze
6065
uses: github/codeql-action/analyze@v3

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,7 @@ bin/
5050
### Node.js ###
5151
node_modules
5252
dist
53+
54+
### SWE agents ###
55+
.claude/
56+
.junie/

build.gradle.kts

Lines changed: 4 additions & 278 deletions
Original file line numberDiff line numberDiff line change
@@ -1,278 +1,4 @@
1-
@file:OptIn(ExperimentalWasmDsl::class)
2-
3-
import org.jetbrains.dokka.gradle.engine.parameters.VisibilityModifier
4-
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
5-
import org.jetbrains.kotlin.gradle.dsl.ExplicitApiMode
6-
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
7-
import org.jreleaser.model.Active
8-
9-
plugins {
10-
alias(libs.plugins.kotlin.multiplatform)
11-
alias(libs.plugins.kotlin.serialization)
12-
alias(libs.plugins.kotlin.atomicfu)
13-
alias(libs.plugins.dokka)
14-
alias(libs.plugins.jreleaser)
15-
`maven-publish`
16-
signing
17-
alias(libs.plugins.kotlinx.binary.compatibility.validator)
18-
}
19-
20-
group = "io.modelcontextprotocol"
21-
version = "0.6.0"
22-
23-
val javadocJar by tasks.registering(Jar::class) {
24-
archiveClassifier.set("javadoc")
25-
}
26-
27-
publishing {
28-
publications.withType(MavenPublication::class).all {
29-
if (name.contains("jvm", ignoreCase = true)) {
30-
artifact(javadocJar)
31-
}
32-
pom.configureMavenCentralMetadata()
33-
signPublicationIfKeyPresent()
34-
}
35-
36-
repositories {
37-
maven(url = layout.buildDirectory.dir("staging-deploy"))
38-
}
39-
}
40-
41-
jreleaser {
42-
gitRootSearch = true
43-
strict = true
44-
45-
signing {
46-
active = Active.ALWAYS
47-
armored = true
48-
artifacts = true
49-
files = true
50-
}
51-
52-
deploy {
53-
active.set(Active.ALWAYS)
54-
maven {
55-
active.set(Active.ALWAYS)
56-
mavenCentral {
57-
val ossrh by creating {
58-
active.set(Active.ALWAYS)
59-
url.set("https://central.sonatype.com/api/v1/publisher")
60-
applyMavenCentralRules = false
61-
maxRetries = 240
62-
stagingRepository(layout.buildDirectory.dir("staging-deploy").get().asFile.path)
63-
// workaround: https://github.com/jreleaser/jreleaser/issues/1784
64-
afterEvaluate {
65-
publishing.publications.forEach { publication ->
66-
if (publication is MavenPublication) {
67-
val pubName = publication.name
68-
69-
if (!pubName.contains("jvm", ignoreCase = true)
70-
&& !pubName.contains("metadata", ignoreCase = true)
71-
&& !pubName.contains("kotlinMultiplatform", ignoreCase = true)
72-
) {
73-
74-
artifactOverride {
75-
artifactId = when {
76-
pubName.contains("wasm", ignoreCase = true) ->
77-
"${project.name}-wasm-${pubName.lowercase().substringAfter("wasm")}"
78-
79-
else -> "${project.name}-${pubName.lowercase()}"
80-
}
81-
jar = false
82-
verifyPom = false
83-
sourceJar = false
84-
javadocJar = false
85-
}
86-
}
87-
}
88-
}
89-
}
90-
}
91-
}
92-
}
93-
}
94-
95-
release {
96-
github {
97-
changelog.enabled = false
98-
skipRelease = true
99-
skipTag = true
100-
overwrite = false
101-
token = "none"
102-
}
103-
}
104-
105-
checksum {
106-
individual = false
107-
artifacts = false
108-
files = false
109-
}
110-
}
111-
112-
fun MavenPom.configureMavenCentralMetadata() {
113-
name by project.name
114-
description by "Kotlin implementation of the Model Context Protocol (MCP)"
115-
url by "https://github.com/modelcontextprotocol/kotlin-sdk"
116-
117-
licenses {
118-
license {
119-
name by "MIT License"
120-
url by "https://github.com/modelcontextprotocol/kotlin-sdk/blob/main/LICENSE"
121-
distribution by "repo"
122-
}
123-
}
124-
125-
developers {
126-
developer {
127-
id by "Anthropic"
128-
name by "Anthropic Team"
129-
organization by "Anthropic"
130-
organizationUrl by "https://www.anthropic.com"
131-
}
132-
}
133-
134-
scm {
135-
url by "https://github.com/modelcontextprotocol/kotlin-sdk"
136-
connection by "scm:git:git://github.com/modelcontextprotocol/kotlin-sdk.git"
137-
developerConnection by "scm:git:[email protected]:modelcontextprotocol/kotlin-sdk.git"
138-
}
139-
}
140-
141-
fun MavenPublication.signPublicationIfKeyPresent() {
142-
val signingKey = project.getSensitiveProperty("GPG_SECRET_KEY")
143-
val signingKeyPassphrase = project.getSensitiveProperty("SIGNING_PASSPHRASE")
144-
145-
if (!signingKey.isNullOrBlank()) {
146-
the<SigningExtension>().apply {
147-
useInMemoryPgpKeys(signingKey, signingKeyPassphrase)
148-
149-
sign(this@signPublicationIfKeyPresent)
150-
}
151-
}
152-
}
153-
154-
fun Project.getSensitiveProperty(name: String?): String? {
155-
if (name == null) {
156-
error("Expected not null property '$name' for publication repository config")
157-
}
158-
159-
return project.findProperty(name) as? String
160-
?: System.getenv(name)
161-
?: System.getProperty(name)
162-
}
163-
164-
infix fun <T> Property<T>.by(value: T) {
165-
set(value)
166-
}
167-
168-
tasks.withType<Test>().configureEach {
169-
useJUnitPlatform()
170-
}
171-
172-
abstract class GenerateLibVersionTask @Inject constructor(
173-
@get:Input val libVersion: String,
174-
@get:OutputDirectory val sourcesDir: File,
175-
) : DefaultTask() {
176-
@TaskAction
177-
fun generate() {
178-
val sourceFile = File(sourcesDir.resolve("io/modelcontextprotocol/kotlin/sdk"), "LibVersion.kt")
179-
180-
if (!sourceFile.exists()) {
181-
sourceFile.parentFile.mkdirs()
182-
sourceFile.createNewFile()
183-
}
184-
185-
sourceFile.writeText(
186-
"""
187-
package io.modelcontextprotocol.kotlin.sdk
188-
189-
public const val LIB_VERSION: String = "$libVersion"
190-
191-
""".trimIndent()
192-
)
193-
}
194-
}
195-
196-
dokka {
197-
moduleName.set("MCP Kotlin SDK")
198-
199-
dokkaSourceSets.configureEach {
200-
sourceLink {
201-
localDirectory.set(file("src/main/kotlin"))
202-
remoteUrl("https://github.com/modelcontextprotocol/kotlin-sdk")
203-
remoteLineSuffix.set("#L")
204-
documentedVisibilities(VisibilityModifier.Public)
205-
}
206-
}
207-
dokkaPublications.html {
208-
outputDirectory.set(project.layout.projectDirectory.dir("docs"))
209-
}
210-
}
211-
212-
val sourcesDir = File(project.layout.buildDirectory.asFile.get(), "generated-sources/libVersion")
213-
214-
val generateLibVersionTask =
215-
tasks.register<GenerateLibVersionTask>("generateLibVersion", version.toString(), sourcesDir)
216-
217-
kotlin {
218-
jvm {
219-
compilerOptions {
220-
jvmTarget = JvmTarget.JVM_1_8
221-
}
222-
}
223-
224-
iosArm64()
225-
iosX64()
226-
iosSimulatorArm64()
227-
228-
js(IR) {
229-
nodejs {
230-
testTask {
231-
useMocha {
232-
timeout = "30s"
233-
}
234-
}
235-
}
236-
}
237-
238-
wasmJs {
239-
nodejs()
240-
}
241-
242-
explicitApi = ExplicitApiMode.Strict
243-
244-
jvmToolchain(21)
245-
246-
sourceSets {
247-
commonMain {
248-
kotlin.srcDir(generateLibVersionTask.map { it.sourcesDir })
249-
dependencies {
250-
api(libs.kotlinx.serialization.json)
251-
api(libs.kotlinx.collections.immutable)
252-
api(libs.ktor.client.cio)
253-
api(libs.ktor.server.cio)
254-
api(libs.ktor.server.sse)
255-
api(libs.ktor.server.websockets)
256-
257-
implementation(libs.kotlin.logging)
258-
}
259-
}
260-
261-
commonTest {
262-
dependencies {
263-
implementation(libs.kotlin.test)
264-
implementation(libs.ktor.server.test.host)
265-
implementation(libs.kotlinx.coroutines.test)
266-
implementation(libs.kotest.assertions.json)
267-
}
268-
}
269-
270-
jvmTest {
271-
dependencies {
272-
implementation(libs.ktor.client.mock)
273-
implementation(libs.mockk)
274-
implementation(libs.slf4j.simple)
275-
}
276-
}
277-
}
278-
}
1+
allprojects {
2+
group = "io.modelcontextprotocol"
3+
version = "0.6.0"
4+
}

buildSrc/build.gradle.kts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
plugins {
2+
`kotlin-dsl`
3+
}
4+
5+
repositories {
6+
gradlePluginPortal()
7+
mavenCentral()
8+
}
9+
10+
dependencies {
11+
implementation(libs.kotlin.gradle)
12+
implementation(libs.kotlin.serialization)
13+
implementation(libs.kotlinx.atomicfu.gradle)
14+
implementation(libs.dokka.gradle)
15+
implementation(libs.jreleaser.gradle)
16+
}

buildSrc/settings.gradle.kts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
dependencyResolutionManagement {
2+
versionCatalogs {
3+
create("libs") {
4+
from(files("../gradle/libs.versions.toml"))
5+
}
6+
}
7+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import org.jetbrains.dokka.gradle.engine.parameters.VisibilityModifier
2+
3+
plugins {
4+
id("org.jetbrains.dokka")
5+
}
6+
7+
dokka {
8+
moduleName.set("MCP Kotlin SDK - ${project.name}")
9+
10+
dokkaSourceSets.configureEach {
11+
sourceLink {
12+
localDirectory = projectDir.resolve("src")
13+
remoteUrl("https://github.com/modelcontextprotocol/kotlin-sdk/tree/main/${project.name}/src")
14+
remoteLineSuffix = "#L"
15+
}
16+
17+
documentedVisibilities(VisibilityModifier.Public)
18+
}
19+
20+
dokkaPublications.html {
21+
outputDirectory = rootProject.layout.projectDirectory.dir("docs/${project.name}")
22+
}
23+
}

0 commit comments

Comments
 (0)