@@ -19,34 +19,34 @@ standardized protocol interface.
1919
2020* [ Overview] ( #overview )
2121* [ Installation] ( #installation )
22- * [ Artifacts] ( #artifacts )
23- * [ Gradle setup (JVM)] ( #gradle-setup-jvm )
24- * [ Multiplatform] ( #multiplatform )
25- * [ Ktor dependencies] ( #ktor-dependencies )
22+ * [ Artifacts] ( #artifacts )
23+ * [ Gradle setup (JVM)] ( #gradle-setup-jvm )
24+ * [ Multiplatform] ( #multiplatform )
25+ * [ Ktor dependencies] ( #ktor-dependencies )
2626* [ Quickstart] ( #quickstart )
27- * [ Creating a Client] ( #creating-a-client )
28- * [ Creating a Server] ( #creating-a-server )
27+ * [ Creating a Client] ( #creating-a-client )
28+ * [ Creating a Server] ( #creating-a-server )
2929* [ Core Concepts] ( #core-concepts )
30- * [ MCP Primitives] ( #mcp-primitives )
31- * [ Capabilities] ( #capabilities )
32- * [ Server Capabilities] ( #server-capabilities )
33- * [ Client Capabilities] ( #client-capabilities )
34- * [ Server Features] ( #server-features )
35- * [ Prompts] ( #prompts )
36- * [ Resources] ( #resources )
37- * [ Tools] ( #tools )
38- * [ Completion] ( #completion )
39- * [ Logging] ( #logging )
40- * [ Pagination] ( #pagination )
41- * [ Client Features] ( #client-features )
42- * [ Roots] ( #roots )
43- * [ Sampling] ( #sampling )
30+ * [ MCP Primitives] ( #mcp-primitives )
31+ * [ Capabilities] ( #capabilities )
32+ * [ Server Capabilities] ( #server-capabilities )
33+ * [ Client Capabilities] ( #client-capabilities )
34+ * [ Server Features] ( #server-features )
35+ * [ Prompts] ( #prompts )
36+ * [ Resources] ( #resources )
37+ * [ Tools] ( #tools )
38+ * [ Completion] ( #completion )
39+ * [ Logging] ( #logging )
40+ * [ Pagination] ( #pagination )
41+ * [ Client Features] ( #client-features )
42+ * [ Roots] ( #roots )
43+ * [ Sampling] ( #sampling )
4444* [ Transports] ( #transports )
45- * [ STDIO Transport] ( #stdio-transport )
46- * [ Streamable HTTP Transport] ( #streamable-http-transport )
47- * [ SSE Transport] ( #sse-transport )
48- * [ WebSocket Transport] ( #websocket-transport )
49- * [ ChannelTransport (testing)] ( #channeltransport-testing )
45+ * [ STDIO Transport] ( #stdio-transport )
46+ * [ Streamable HTTP Transport] ( #streamable-http-transport )
47+ * [ SSE Transport] ( #sse-transport )
48+ * [ WebSocket Transport] ( #websocket-transport )
49+ * [ ChannelTransport (testing)] ( #channeltransport-testing )
5050* [ Connecting your server] ( #connecting-your-server )
5151* [ Examples] ( #examples )
5252* [ Documentation] ( #documentation )
@@ -188,24 +188,19 @@ the [simple-streamable-server](samples/simple-streamable-server) sample.
188188<!-- - CLEAR -->
189189
190190``` kotlin
191- import io.ktor.serialization.kotlinx.json.json
192- import io.ktor.server.application.install
193191import io.ktor.server.cio.CIO
194192import io.ktor.server.engine.embeddedServer
195- import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
196193import io.modelcontextprotocol.kotlin.sdk.server.Server
197194import io.modelcontextprotocol.kotlin.sdk.server.ServerOptions
198195import io.modelcontextprotocol.kotlin.sdk.server.mcpStreamableHttp
199196import io.modelcontextprotocol.kotlin.sdk.types.CallToolResult
200197import io.modelcontextprotocol.kotlin.sdk.types.Implementation
201- import io.modelcontextprotocol.kotlin.sdk.types.McpJson
202198import io.modelcontextprotocol.kotlin.sdk.types.ServerCapabilities
203199import io.modelcontextprotocol.kotlin.sdk.types.TextContent
204200import io.modelcontextprotocol.kotlin.sdk.types.ToolSchema
205201import kotlinx.serialization.json.buildJsonObject
206202import kotlinx.serialization.json.put
207203
208-
209204fun main (args : Array <String >) {
210205 val port = args.firstOrNull()?.toIntOrNull() ? : 3000
211206 val mcpServer = Server (
@@ -231,11 +226,8 @@ fun main(args: Array<String>) {
231226 ) { request ->
232227 CallToolResult (content = listOf (TextContent (" Hello, world!" )))
233228 }
234-
229+
235230 embeddedServer(CIO , host = " 127.0.0.1" , port = port) {
236- install(ContentNegotiation ) {
237- json(McpJson )
238- }
239231 mcpStreamableHttp {
240232 mcpServer
241233 }
@@ -774,8 +766,10 @@ CLI tooling that spawns a helper process. No networking setup is required.
774766
775767` StreamableHttpClientTransport ` and the Ktor ` mcpStreamableHttp() ` / ` mcpStatelessStreamableHttp() ` helpers expose MCP
776768over a single HTTP endpoint with optional JSON-only or SSE streaming responses. This is the recommended choice for
777- remote deployments and integrates nicely with proxies or service meshes. Both accept a ` path ` parameter (default:
778- ` "/mcp" ` ) to mount the endpoint at any URL:
769+ remote deployments and integrates nicely with proxies or service meshes.
770+
771+ These helpers automatically install ` ContentNegotiation ` with ` McpJson ` — do not install it yourself, or a warning will
772+ be logged. Both accept a ` path ` parameter (default: ` "/mcp" ` ) to mount the endpoint at any URL:
779773
780774<!-- - CLEAR -->
781775<!-- - INCLUDE
@@ -809,11 +803,30 @@ embeddedServer(CIO, port = 3000) {
809803-->
810804<!-- - KNIT example-server-routes-01.kt -->
811805
806+ ** CORS for browser-based clients (e.g. MCP Inspector):** if you connect from a browser-based
807+ client you need to install the Ktor CORS plugin so that MCP-specific headers are allowed and exposed:
808+
809+ ``` kotlin
810+ install(CORS ) {
811+ anyHost() // restrict to specific origins in production
812+ allowMethod(HttpMethod .Options )
813+ allowMethod(HttpMethod .Get )
814+ allowMethod(HttpMethod .Post )
815+ allowMethod(HttpMethod .Delete )
816+ allowNonSimpleContentTypes = true
817+ allowHeader(" Mcp-Session-Id" )
818+ allowHeader(" Mcp-Protocol-Version" )
819+ exposeHeader(" Mcp-Session-Id" )
820+ exposeHeader(" Mcp-Protocol-Version" )
821+ }
822+ ```
823+
812824### SSE Transport
813825
814826Server-Sent Events remain available for backwards compatibility with older MCP clients. Two Ktor helpers are provided:
815827
816- - ** ` Application.mcp { } ` ** — installs the SSE plugin automatically and registers MCP endpoints at ` / ` .
828+ - ** ` Application.mcp { } ` ** — installs SSE and ` ContentNegotiation ` with ` McpJson ` automatically, then registers MCP
829+ endpoints at ` / ` . Do not install ` ContentNegotiation ` yourself — the SDK handles it.
817830- ** ` Route.mcp { } ` ** — registers MCP endpoints at the current route path; requires ` install(SSE) ` in the application
818831 first. Use this to host MCP alongside other routes or under a path prefix:
819832
0 commit comments