{
  "markdown": "# kotlin-lib-mcp\n\n[![CI](https://github.com/aoreshkov/kotlin-lib-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/aoreshkov/kotlin-lib-mcp/actions/workflows/ci.yml)\n[![CodeQL](https://github.com/aoreshkov/kotlin-lib-mcp/actions/workflows/codeql.yml/badge.svg)](https://github.com/aoreshkov/kotlin-lib-mcp/actions/workflows/codeql.yml)\n[![Release](https://img.shields.io/github/v/release/aoreshkov/kotlin-lib-mcp)](https://github.com/aoreshkov/kotlin-lib-mcp/releases/latest)\n[![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE)\n[![Kotlin](https://img.shields.io/badge/kotlin-2.4-7F52FF.svg?logo=kotlin)](https://kotlinlang.org)\n[![GitHub MCP Registry](https://img.shields.io/badge/GitHub_MCP_Registry-listed-24292F.svg?logo=github)](https://github.com/mcp/aoreshkov/kotlin-lib-mcp)\n\nGive your AI agent the **real sources** of any Maven-published Kotlin/Java library.\n\nAn [MCP](https://modelcontextprotocol.io) server that, on request, downloads the sources of a\nlibrary (e.g. `io.ktor:ktor-client-core:3.5.1`), parses them with the Kotlin **Analysis API**\n(standalone K2/FIR mode), and exposes structured information — public API surface, KDoc,\ndependencies/metadata, raw source + search — to MCP clients: Claude Code, Claude Desktop,\nIntelliJ IDEA (AI Assistant / Junie), VS Code and GitHub Copilot. An optional Compose Desktop\ndashboard runs the same server in-process.\n\n**[Ten tools](#tools)** — `fetch_library` · `list_packages` · `list_declarations` ·\n`get_api_signature` · `get_kdoc` · `get_source` · `search_source` · `get_dependencies` ·\n`list_versions` · `get_latest_version` — plus MCP resources and a prompt.\n\n[<img src=\"https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=flat-square\" alt=\"Install in VS Code\">](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522kotlin-lib%2522%252C%2522command%2522%253A%2522docker%2522%252C%2522args%2522%253A%255B%2522run%2522%252C%2522-i%2522%252C%2522--rm%2522%252C%2522-v%2522%252C%2522kotlin-lib-mcp-cache%253A%252Fhome%252Fmcp%252F.cache%2522%252C%2522ghcr.io%252Faoreshkov%252Fkotlin-lib-mcp%2522%255D%257D)\n[<img src=\"https://img.shields.io/badge/VS_Code_Insiders-Install_Server-24bfa5?style=flat-square\" alt=\"Install in VS Code Insiders\">](https://insiders.vscode.dev/redirect?url=vscode-insiders%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522kotlin-lib%2522%252C%2522command%2522%253A%2522docker%2522%252C%2522args%2522%253A%255B%2522run%2522%252C%2522-i%2522%252C%2522--rm%2522%252C%2522-v%2522%252C%2522kotlin-lib-mcp-cache%253A%252Fhome%252Fmcp%252F.cache%2522%252C%2522ghcr.io%252Faoreshkov%252Fkotlin-lib-mcp%2522%255D%257D)\n\nThose install the Docker image. For Claude Code, IntelliJ IDEA, or to run the release zip without\nDocker, see [Quick start](#quick-start-no-build-required).\n\n<!-- mcp-name: io.github.aoreshkov/kotlin-lib-mcp -->\n\n![Claude Code fetching a library and reading KDoc via kotlin-lib-mcp](assets/demo.gif)\n\n<details><summary>Compose Desktop dashboard</summary>\n\n![The dashboard: in-process MCP server, pre-warm form, cache browser and live logs](assets/dashboard.png)\n\n</details>\n\n## Why this and not a docs-lookup server?\n\nMost documentation MCP servers scrape rendered doc sites or feed the model pre-digested\nsummaries. This one works from the **published sources jar** — the ground truth:\n\n- **Resolved signatures, not regex guesses.** Declarations are analyzed with the same\n  Analysis API that powers the Kotlin IDE, so `get_api_signature` returns real, type-resolved\n  signatures (with graceful best-effort fallback when transitive dependencies are missing).\n- **KMP-aware.** Kotlin Multiplatform libraries publish per-target sources jars; these are\n  resolved properly via `.module` Gradle metadata, and every symbol is tagged with its targets.\n- **KDoc as data.** Summaries, descriptions and tags are extracted per declaration — not\n  whole HTML pages.\n- **Exact version you asked for, offline after the first fetch.** Everything is cached on\n  disk keyed by `group/artifact/version`; no re-downloads, no drift between the docs and the\n  version you actually depend on.\n- **Raw source when you need it.** `get_source` and bounded `search_source` let the agent\n  read the actual implementation, not just the API.\n\n## Quick start (no build required)\n\n**Option 1 — Claude Code plugin.** The server plus skills that make Claude reach for it, two\ncommands (`/kotlin-lib:api`, `/kotlin-lib:migrate`) and a setup helper. Needs Docker:\n\n```\n/plugin marketplace add aoreshkov/kotlin-lib-mcp\n/plugin install kotlin-lib@kotlin-lib-mcp\n```\n\nSee [`plugin/README.md`](plugin/README.md) for what it bundles.\n\n**Option 2 — release zip.** Download the latest\n[release](https://github.com/aoreshkov/kotlin-lib-mcp/releases/latest), unzip (needs a\nJava 21+ runtime), then:\n\n```sh\nclaude mcp add kotlin-lib -- /path/to/kotlin-lib-mcp-server-<version>/bin/server --transport stdio\n```\n\n**Option 3 — Docker.**\n\n```sh\nclaude mcp add kotlin-lib -- docker run -i --rm -v kotlin-lib-mcp-cache:/home/mcp/.cache ghcr.io/aoreshkov/kotlin-lib-mcp\n```\n\n**Option 4 — IntelliJ IDEA / Android Studio.** JetBrains IDEs are MCP clients too — which is where\nmost Kotlin gets written. Open **Settings | Tools | AI Assistant | Model Context Protocol (MCP)**,\nclick **Add**, pick the **stdio** transport and paste:\n\n```json\n{\n  \"mcpServers\": {\n    \"kotlin-lib\": {\n      \"command\": \"docker\",\n      \"args\": [\"run\", \"-i\", \"--rm\", \"-v\", \"kotlin-lib-mcp-cache:/home/mcp/.cache\", \"ghcr.io/aoreshkov/kotlin-lib-mcp\"]\n    }\n  }\n}\n```\n\nChoose global or project level, **Apply**, and the tools appear in the AI Assistant chat. Junie\ntakes the same JSON in its own MCP settings. Swap `command`/`args` for the release-zip launcher\n(`bin/server --transport stdio`) if you'd rather not use Docker.\n\n**Option 5 — MCP Registry.** The server is published to the\n[official MCP registry](https://registry.modelcontextprotocol.io) as\n`io.github.aoreshkov/kotlin-lib-mcp`, and listed in the\n[GitHub MCP Registry](https://github.com/mcp/aoreshkov/kotlin-lib-mcp); registry-aware clients can\ninstall it from there.\n\nOr in `.mcp.json` / Claude Desktop config:\n\n```json\n{\n  \"mcpServers\": {\n    \"kotlin-lib\": {\n      \"command\": \"C:/path/to/kotlin-lib-mcp-server-<version>/bin/server.bat\",\n      \"args\": [\"--transport\", \"stdio\"]\n    }\n  }\n}\n```\n\nFor remote use, run the http transport (`--transport http --port 3000`) and point the client\nat `http://127.0.0.1:3000/mcp` — DNS-rebinding protection admits localhost hosts by default;\n`--allowed-host`/`--allowed-origin` extend the allowlist for non-localhost deployments.\n\nCLI flags: `--transport stdio|http`, `--port <int>` (default 3000), `--allowed-host <host>` /\n`--allowed-origin <url>` (repeatable; extend the http transport's localhost-only defaults),\n`--cache-dir <path>`, `--repo <url>` (repeatable; Maven Central is the default),\n`--forward-logs-to-client` (opt into mirroring logs to the client; off by default, stderr-only),\n`--otel` (opt into OTLP/HTTP trace export; off by default — see [Telemetry](#telemetry)), `--help`.\n\n## Tools\n\nAll tools take a Maven `coordinate` (`group:artifact:version`). Call **`fetch_library`** first —\nit downloads, extracts and analyzes the sources once; every other tool answers from the cached\nindex. `fetch_library`, `list_versions` and `get_latest_version` also accept `group:artifact`, and\n`fetch_library` accepts `group:artifact:latest` to resolve the latest stable release.\n\n| Tool | Purpose |\n|---|---|\n| `fetch_library` | Download + analyze + cache; returns a summary. Idempotent. Version may be omitted or `latest` |\n| `list_packages` | Packages with declaration counts and KMP targets |\n| `list_declarations` | Declarations with signatures; filter by `package` and `visibility` |\n| `get_api_signature` | Resolved signature of one declaration by FQ name |\n| `get_kdoc` | KDoc (summary, description, tags) of one declaration |\n| `get_source` | Raw source of a file (`path`) or one declaration (`fqName`) |\n| `search_source` | Substring/regex search; bounded, returns `file:line` snippets |\n| `get_dependencies` | Dependency tree from `.pom`/`.module`; bounded `depth` |\n| `list_versions` | Published versions from `maven-metadata.xml`, newest-first |\n| `get_latest_version` | Latest stable release (and newest overall) from `maven-metadata.xml` |\n\nEvery tool ships the metadata the MCP spec encourages clients to use: a display `title`,\n**behavior annotations** (`readOnlyHint: true` everywhere except `fetch_library`, which is\nadditive-only — `destructiveHint: false`, `idempotentHint: true`; tools that reach Maven\nrepositories set `openWorldHint: true`, cache-only tools `false`), a typed **`outputSchema`**\nderived from the response DTO's serializer, and an **icon**. Results carry both pretty-printed JSON\ntext and the matching `structuredContent` object, so structured-output clients and plain-text\nclients see the same payload.\n\n`fetch_library` also reports **progress notifications** (download → analyze → cache) when the\nclient sends a `progressToken`. Logs go to **stderr** by default (which the spec blesses for all\nstdio logging); the deprecated MCP **logging capability** — mirroring logs to clients as\n`notifications/message` (respecting `logging/setLevel`) — is **opt-in** via `--forward-logs-to-client`,\nfor stdio clients that surface MCP log messages but drop stderr.\n\n### Elicitation\n\nWhen `fetch_library` is called without a version (`io.ktor:ktor-client-core`, or `…:latest`) it has\nto guess. If the client advertised the **`elicitation`** capability, it asks instead: an\n`elicitation/create` **form-mode** request carrying a single-select version picker — the titled\n`oneOf` shape from SEP-1330, with the latest stable release pre-selected as the schema `default`.\n\n| The user | The server |\n|---|---|\n| **accepts** a version | fetches exactly that one |\n| **declines** | fetches the latest stable release, as it always did |\n| **cancels** (dismissed the dialog) | downloads nothing and returns a tool error saying to call `fetch_library` again with an explicit `group:artifact:version` |\n\nThere is no flag: capability negotiation *is* the opt-in. A client that advertises nothing — or\nadvertises **url-mode only**, which servers must not answer with a form — keeps the previous silent\nlatest-stable behavior exactly. Only public Maven version numbers are ever requested, so form mode\nis appropriate; URL mode exists for credentials and third-party authorization, and is deliberately\nunused here. Accepted values are validated against the offered list before they reach a repository\nURL, and a client that errors mid-question falls back to the default rather than failing the fetch.\n\nUnder `--tasks`, a task-augmented `fetch_library` parks in the **`input_required`** status while the\nquestion is outstanding and returns to `working` once answered; the `elicitation/create` carries the\n`io.modelcontextprotocol/related-task` `_meta` tying it to the task.\n\n### Tasks\n\nPass **`--tasks`** to accept task-augmented `tools/call` for `fetch_library` (SEP-1686) and answer\n`tasks/get` / `tasks/result` / `tasks/list` / `tasks/cancel`. Works on both transports.\n\nTask records are **persisted** under `<cache-dir>/tasks`, so a completed task and its result are\nstill retrievable after the server restarts. A task that was still running when the server stopped\ncomes back as `failed` — its work did not survive, only the record did. Records are dropped once\ntheir TTL elapses (10 minutes by default, 1 hour maximum).\n\n> **Task IDs are bearer tokens for tasks that outlive their session.** A task belongs to the MCP\n> session that created it, and while that session is connected no other session can read, list or\n> cancel it. But a session ID is per-connection: after a restart your client reconnects with a new\n> one, so a recovered task is instead reachable by **anyone presenting its exact task ID**. That is\n> the model the MCP spec prescribes for servers with no authorization context — which this one is,\n> being loopback-first with no auth — and task IDs are 122-bit `SecureRandom` UUIDs accordingly.\n> `tasks/list` never returns recovered tasks, only the calling session's own. If you expose this\n> server beyond loopback, put authentication in front of it.\n\n> **Note on concurrency.** A server-initiated request from inside a tool call only works because the\n> SDK dispatches inbound requests concurrently once the session is initialized — otherwise the\n> client's reply would be stuck behind the very handler waiting for it. Besides making elicitation\n> possible, this means `ping`, `tasks/get` and `notifications/cancelled` are answered promptly\n> during a long `fetch_library` instead of queueing behind it, and a `fetch_library` the client\n> cancels actually stops.\n\n## Telemetry\n\nPass **`--otel`** to export a trace span for every MCP request (`tools/call`, `resources/read`,\n`prompts/get`, `completion/complete`) over **OTLP/HTTP**. It is off by default, and off means\ninert: no SDK, no exporter threads, no network.\n\nConfiguration is the standard OpenTelemetry environment surface — there are no bespoke flags:\n\n```bash\nexport OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318   # '/v1/traces' is appended for you\nexport OTEL_SERVICE_NAME=kotlin-lib-mcp                    # this is also the default\nexport OTEL_RESOURCE_ATTRIBUTES=deployment.environment=dev\nserver --transport stdio --otel\n```\n\nThe protocol defaults to `http/protobuf`, the endpoint to `http://localhost:4318`, and the\nexporter uses the JDK's built-in HTTP client (no OkHttp on the classpath). Everything is\noverridable: `OTEL_EXPORTER_OTLP_HEADERS` for a hosted collector's API key, `OTEL_TRACES_EXPORTER`,\n`OTEL_BSP_SCHEDULE_DELAY`, and so on.\n\n> **Endpoint gotcha.** With the generic `OTEL_EXPORTER_OTLP_ENDPOINT`, `/v1/traces` is appended\n> automatically. With the per-signal `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT`, the URL is used\n> **as-is** — you must spell out the path yourself. This is the most common OTLP misconfiguration.\n\nSpans follow the [MCP semantic conventions][mcp-semconv]: named `{method} {target}` (e.g.\n`tools/call fetch_library`), `SpanKind.SERVER`, and carrying `mcp.method.name`, `gen_ai.tool.name`,\n`mcp.session.id`, and `network.transport` (`pipe` for stdio, `tcp` for http). A tool that returns\n`isError` is marked `error.type=tool_error`. Inbound trace context is picked up from the JSON-RPC\n`params._meta` bag (`traceparent`/`tracestate`, per [SEP-414][sep-414]), so a client that traces\nits own work gets one connected trace.\n\nThose `mcp.*` and `gen_ai.*` attributes are still **Development** status upstream and may be\nrenamed — one more reason the whole feature is opt-in.\n\n[mcp-semconv]: https://github.com/open-telemetry/semantic-conventions-genai/blob/main/docs/gen-ai/mcp.md\n[sep-414]: https://modelcontextprotocol.io/community/seps/414-request-meta\n\n**Resources:** each cached library is readable at\n`kotlinlib://{group}/{artifact}/{version}/index` (the parsed index as JSON); the list updates as\nlibraries are fetched, and the same URI shape is published as a **resource template**, so any\ncached coordinate is directly addressable. **Prompt:** `explain_public_api(coordinate, package?)`\nrenders an explanation request grounded in the cached signatures and KDoc.\n\n**Icons:** the server, every tool, the prompt and the library-index resource/template each declare\nan [SEP-973][sep-973] icon, so a client can show the surface visually instead of as a wall of\nsnake\\_case. They are inlined as **`data:` URIs** rather than hosted URLs — a stdio server has no\norigin, and the spec asks consumers to prefer same-origin icons and fetch them without credentials,\nso inlining removes the third-party fetch entirely and keeps the icons working offline and inside\nthe container image. The payload is **PNG**, the one format icon-rendering clients *must* support\n(`image/svg+xml` is only a SHOULD, and the spec warns it may carry executable content). The glyphs\nare drawn by [`tools/src/main/kotlin/GenerateIcons.kt`](tools/src/main/kotlin/GenerateIcons.kt)\n(`./gradlew :tools:generateIcons`) and kept small —\nabout 800 bytes encoded each, since they ride in every `tools/list`.\n\n[sep-973]: https://modelcontextprotocol.io/specification/2025-11-25/basic#icons\n\n## Building from source\n\n```sh\n./gradlew build                                    # build everything\n./gradlew test                                     # unit tests\n./gradlew :server:run --args=\"--transport stdio\"   # local MCP over stdio (default)\n./gradlew :server:run --args=\"--transport http --port 3000\"   # Streamable HTTP at /mcp\n./gradlew :dashboard:run                           # Compose Desktop UI\n./gradlew :server:installDist                      # standalone launcher in server/build/install/server/bin\n```\n\nRequires JDK 21 (resolved automatically via Gradle toolchains).\n\n| Module | What it is |\n|---|---|\n| `core/` | KMP library: domain model + ports (`commonMain`); Maven fetcher, zip extractor, Analysis API analyzer, on-disk cache (`jvmMain`) |\n| `server/` | JVM app: MCP tools/resources/prompts + stdio and Streamable HTTP transports |\n| `dashboard/` | Compose Desktop control panel embedding the server (optional) |\n| `tools/` | Generator for the SEP-973 icon PNGs the server advertises. The module never ships; its output does |\n\n## Cache\n\nDownloads and the parsed index live under the OS cache dir + `kotlin-lib-mcp`\n(`%LOCALAPPDATA%\\kotlin-lib-mcp` on Windows, `~/Library/Caches/kotlin-lib-mcp` on macOS,\n`$XDG_CACHE_HOME/kotlin-lib-mcp` elsewhere), keyed by `group/artifact/version` — browsable and\nsafe to delete. `--cache-dir` overrides it. Under `--tasks`, task records live in a `tasks/`\nsubdirectory of the same root.\n\n## Notes\n\n- **stdio rule:** stdout carries only MCP protocol frames; all logging goes to stderr\n  (Kermit → SLF4J → Logback, `logback.xml`).\n- Kotlin and the Analysis API artifacts are version-locked in `gradle/libs.versions.toml` —\n  bump them together. Symbols whose types can't be resolved (missing transitive deps) degrade\n  to `bestEffort: true` PSI signatures instead of failing.\n\n## Privacy\n\n**Nothing about you is collected, stored remotely, or shared.** There is no analytics, no\nphone-home, no account, and no credential of any kind.\n\n- **What leaves your machine.** Only requests to the Maven repositories you point it at (Maven\n  Central by default, `--repo` to change): the `maven-metadata.xml`, `.pom`/`.module` metadata and\n  sources jar for the coordinates you ask about. Those repositories see the coordinate and your IP,\n  under their own privacy policies. Pulling the Docker image likewise talks to GHCR. That is the\n  complete list of outbound traffic.\n- **What it reads.** Downloaded library sources only. It does not read, index or transmit your\n  project's code — it has no access to it.\n- **What it stores, and where.** Downloaded artifacts and the parsed index, on your disk only,\n  under the OS cache directory (see [Cache](#cache)) or `--cache-dir`. Under `--tasks`, task\n  records live in a `tasks/` subdirectory. Nothing is written anywhere else.\n- **Retention.** Cached libraries stay until you delete them — the directory is browsable and safe\n  to remove at any time. Task records are dropped once their TTL elapses (10 minutes by default,\n  1 hour maximum).\n- **Logs.** stderr on your machine. `--forward-logs-to-client` (opt-in) mirrors them to your MCP\n  client; `--otel` (opt-in) exports trace spans to the OTLP collector *you* configure, and carries\n  no personal data — method names, tool names, session id, transport. Both are off by default.\n- **Contact.** Questions: [open an issue](https://github.com/aoreshkov/kotlin-lib-mcp/issues).\n  Security or privacy reports: [private vulnerability reporting](SECURITY.md).\n\n## Contributing\n\nContributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md). Release history lives in\n[CHANGELOG.md](CHANGELOG.md); security reports go through\n[private vulnerability reporting](SECURITY.md).\n\n## Support\n\nIf `kotlin-lib-mcp` saves you time, consider\n[sponsoring its maintenance](https://github.com/sponsors/aoreshkov). Sponsorship funds\nkeeping the Analysis API version-lock current with new Kotlin releases and the\nsupply-chain-hardened release pipeline. Every tier is appreciated.\n\n## License\n\n[Apache-2.0](LICENSE)\n",
  "bytes": 20349,
  "sha": "928bb805bbee0a229e7c0aeb98e34774d4c6a5999ac8c9a639090829fc356c56",
  "repo_slug": "aoreshkov/kotlin-lib-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_aoreshkov_kotlin_lib_mcp_ac251d07/readme"
}