kotlin-sdk/AGENTS.md
Pavel Gorgulov 62e4e50c67
docs: update AGENTS.md (#612)
Improve AGENTS.md

## Motivation and Context
The previous AGENTS.md contained many elements contradicting [best
practices](https://code.claude.com/docs/en/best-practices).

AGENTS.md/CLAUDE.md is loaded into the context on every request, so a
~300+ line file is too large and fills the context window.
> Keep it concise. For each line, ask: “Would removing this cause Claude
to make mistakes?” If not, cut it. Bloated CLAUDE.md files cause Claude
to ignore your actual instructions!

> Most best practices are based on one constraint: Claude’s context
window fills up fast, and performance degrades as it fills.

> The over-specified CLAUDE.md. If your CLAUDE.md is too long, Claude
ignores half of it because important rules get lost in the noise.

Since the file is loaded on every request, it should be general-purpose
rather than targeting specific use cases.

> CLAUDE.md is loaded every session, so only include things that apply
broadly.

AI coding agents are used not only for writing tests and
implementations.

- AGENTS.md should not contain behavioral instructions, especially like
`Tests first, always.`. This causes the agent to trigger test runs even
when not required, increasing request time and token consumption
significantly due to large test outputs. For example, on a simple
codebase question, the agent ran the full test suite and I waited over
10 minutes for a response.
- `Uphold SOLID principles` — self-evident rules, explaining what SOLID
stands for is redundant since AI coding agents are already trained on
this knowledge.
> Exclude: "Standard language conventions Claude already knows"

> Exclude: "Self-evident practices like 'write clean code'"

- Mentioning specific MCP servers (jetbrains, intellij-index) can
mislead the agent if they are not installed in the environment.
Additionally, [Anthropic
recommends](https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf)
mentioning the use of MCP in skills.
- The large Kotest patterns block targets a specific use case and is
unnecessary for other agent interactions. Moreover, the agent already
looks at neighboring test classes and can learn patterns from existing
tests
- The large Module documentation block covers a very rare use case.
- The KDoc block — the agent can derive this information from the
codebase, this should be a skill instead

These and other changes follow the best practices.

## Types of changes
- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [x] Documentation update

## Checklist
- [x] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [x] My code follows the repository's style guidelines
- [x] New and existing tests pass locally
- [x] I have added appropriate error handling
- [x] I have added or updated documentation as needed

## Additional context
https://code.claude.com/docs/en/best-practices

https://resources.anthropic.com/hubfs/The-Complete-Guide-to-Building-Skill-for-Claude.pdf
https://agents.md/#examples
2026-03-20 15:01:58 +01:00

3.8 KiB

AGENTS: Development Guidelines for AI Contributors

This file provides guidance to AI coding agents working with code in this repository.

Project

Kotlin Multiplatform SDK for the Model Context Protocol (MCP). Targets JVM, Native (macOS/Linux/Windows), JS, and Wasm. Implements both MCP clients and servers with pluggable transports.

Build Commands

./gradlew ktlintCheck                # Lint check
./gradlew detekt                     # Static analysis
./gradlew ktlintFormat               # Auto-fix lint issues
./gradlew apiCheck                   # Check public API compatibility (run before committing)
./gradlew apiDump                    # Update API dump after intentional API changes
./gradlew koverLog                   # Print coverage summary
./gradlew koverXmlReport            # Generate XML coverage report

Run a single test class:

./gradlew :kotlin-sdk-server:jvmTest --tests "io.modelcontextprotocol.kotlin.sdk.server.StdioServerTransportTest"

Run a single test method:

./gradlew :kotlin-sdk-core:jvmTest --tests "*.ProtocolTest.should preserve existing meta when adding progress token"

Conformance tests (requires Node.js + npx):

./conformance-test/run-conformance.sh all           # All suites sequentially
./conformance-test/run-conformance.sh server         # Server suite only
./conformance-test/run-conformance.sh client         # Client core suite (initialize, tools_call, elicitation, sse-retry)
./conformance-test/run-conformance.sh client-auth    # Client auth suite (20 OAuth scenarios)

Module Structure

kotlin-sdk-core      Core: protocol types, JSON-RPC, Transport abstraction, Protocol base class
kotlin-sdk-client    Client: MCP client implementation (tools, prompts, resources, sampling)
kotlin-sdk-server    Server: MCP server implementation (feature registries, sessions)
kotlin-sdk-testing   ChannelTransport for in-memory client-server testing
kotlin-sdk           Umbrella module aggregating client + server
test-utils           Shared test helpers (mockk, kotest, awaitility)
conformance-test     MCP specification compliance tests (external runner)
integration-test     End-to-end tests
samples/             Runnable examples (servers and clients)

Architecture

Layered design:

Application (tools, prompts, resources)
  → Client / Server  (typed MCP operations, capability enforcement)
    → Protocol        (JSON-RPC framing, request correlation, timeouts)
      → Transport     (pluggable I/O: stdio, SSE, Streamable HTTP, WebSocket)

Code Conventions

  • Explicit API mode (Strict): all public declarations must have explicit visibility modifiers and return types
  • DSL builders: prefer DSL builder style (lambda blocks) over direct constructors
  • Multi-dollar interpolation: use $$"""...""" for strings containing literal $ (e.g., JSON with $ref, $defs)
  • McpJson has explicitNulls = false: null properties must be absent from JSON, not "field": null
  • Logging: use io.github.oshai.kotlinlogging.KotlinLogging
  • Structured concurrency: every coroutine must have a bounded scope and lifetime; always re-throw CancellationException; never hold Mutex across suspension points

Testing

  • JVM first: run jvmTest instead of test — full multiplatform test runs are slow and rarely needed during development
  • Test naming: use backtick syntax — fun \should return 200 OK`()`
  • Frameworks: JUnit 5 (runner) + Kotest (assertions) + MockK (mocking) + Awaitility (async waits)
  • In-memory testing: ChannelTransport.createLinkedPair() connects client and server without network

Skills

  • /mcp-docs — fetches live MCP specification and docs; use when implementing or debugging MCP protocol features