Skip to content

Commit 3efad77

Browse files
docs: align README, docs, and llms with current behavior
Fix completion URI matching, base package resolution, and component lifecycle notes. Document mvnw, Spotless validate, and 0.18.0-SNAPSHOT development version. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent d59fa65 commit 3efad77

8 files changed

Lines changed: 100 additions & 38 deletions

File tree

README.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ English · [简体中文](README.zh-CN.md)
2424

2525
This SDK is a lightweight, annotation-based framework that simplifies MCP server development in Java. Define, develop, and integrate your MCP Resources / Prompts / Tools with minimal code — **no Spring Framework required**.
2626

27-
> **Workflow:** Add dependency → Configure `mcp-server.yml` → Annotate Resources / Tools / Prompts → Run with `McpApplication`
27+
> **Workflow:** Add dependency → Configure `mcp-server.yml` → Annotate Resources / Tools / Prompts / Completions → Run with `McpApplication`
2828
2929
[📖 Documentation](https://thought2code.github.io/mcp-annotated-java-sdk-docs) · [💡 Examples](https://github.com/thought2code/mcp-java-sdk-examples/tree/main/mcp-server-filesystem/mcp-server-filesystem-annotated-sdk-implementation) · [🐛 Report Issues](https://github.com/thought2code/mcp-annotated-java-sdk/issues)
3030

@@ -75,6 +75,8 @@ This SDK is a lightweight, annotation-based framework that simplifies MCP server
7575
implementation 'io.github.thought2code:mcp-annotated-java-sdk:0.17.0'
7676
```
7777

78+
Use the [Maven Central](https://central.sonatype.com/artifact/io.github.thought2code/mcp-annotated-java-sdk) badge above for the latest release. This repository’s development version is `0.18.0-SNAPSHOT`.
79+
7880
#### Step 2: Create Configuration File
7981

8082
Create `mcp-server.yml` in your `src/main/resources`:
@@ -289,7 +291,9 @@ The SDK creates **one instance per component class** (no-arg constructor) and re
289291
- Do not store per-request data in instance fields without proper synchronization.
290292
- Delegate shared mutable state to thread-safe services when needed.
291293

292-
`McpApplicationContext.from(...)` currently uses this default singleton-per-class factory. There is no built-in Spring/CDI wiring in the public API today.
294+
`McpApplicationContext.from(...)` currently uses this default singleton-per-class factory. Component classes must provide a **public no-arg constructor**. There is no built-in Spring/CDI wiring in the public API today.
295+
296+
`McpApplication.run(mainClass, args)` loads `mcp-server.yml` by default; pass a third argument to use another classpath config file name.
293297

294298
#### MCP Java SDK 2.x (milestone)
295299

@@ -328,12 +332,18 @@ your-mcp-project/
328332

329333
## 🧪 Testing
330334

331-
Run the test suite:
335+
Run the unit test suite (this project requires the Maven Wrapper — do not use a system `mvn` install):
332336

333337
```bash
334338
./mvnw clean test
335339
```
336340

341+
On Windows:
342+
343+
```bash
344+
mvnw.cmd clean test
345+
```
346+
337347
## ❓ FAQ
338348

339349
### Q: Do I need Spring Framework?
@@ -389,7 +399,7 @@ We welcome and appreciate contributions! Please follow these steps to contribute
389399
git clone https://github.com/thought2code/mcp-annotated-java-sdk.git
390400
cd mcp-annotated-java-sdk
391401
392-
# Build the project
402+
# Build the project (Spotless formatting is checked at the validate phase)
393403
./mvnw clean install
394404
395405
# Run tests

README.zh-CN.md

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
本 SDK 是一个轻量级的注解框架,用于简化 Java 中的 MCP 服务端开发。你可以用极少的代码定义、开发并集成 MCP 资源(Resources)、提示词(Prompts)与工具(Tools),且**无需 Spring 框架**
2626

27-
> **工作流:** 添加依赖 → 配置 `mcp-server.yml` → 注解 Resources / Tools / Prompts → 通过 `McpApplication` 启动
27+
> **工作流:** 添加依赖 → 配置 `mcp-server.yml` → 注解 Resources / Tools / Prompts / Completions → 通过 `McpApplication` 启动
2828
2929
[📖 文档](https://thought2code.github.io/mcp-annotated-java-sdk-docs) · [💡 示例](https://github.com/thought2code/mcp-java-sdk-examples/tree/main/mcp-server-filesystem/mcp-server-filesystem-annotated-sdk-implementation) · [🐛 提交 Issue](https://github.com/thought2code/mcp-annotated-java-sdk/issues)
3030

@@ -77,6 +77,8 @@
7777
implementation 'io.github.thought2code:mcp-annotated-java-sdk:0.17.0'
7878
```
7979

80+
依赖版本请以 [Maven Central](https://central.sonatype.com/artifact/io.github.thought2code/mcp-annotated-java-sdk) 徽章为准;本仓库当前开发版本为 `0.18.0-SNAPSHOT`
81+
8082
#### 第 2 步:创建配置文件
8183

8284
`src/main/resources` 下创建 `mcp-server.yml`
@@ -291,7 +293,9 @@ SDK 为每个组件类创建 **唯一实例**(无参构造),该类上所
291293
- 不要在实例字段中存放未同步的 per-request 数据。
292294
- 需要共享可变状态时,请委托给线程安全的服务层。
293295

294-
当前 `McpApplicationContext.from(...)` 使用默认的单例-per-class 工厂;公开 API 尚未内置 Spring/CDI 集成。
296+
当前 `McpApplicationContext.from(...)` 使用默认的单例-per-class 工厂;组件类需提供 **public 无参构造器**。公开 API 尚未内置 Spring/CDI 集成。
297+
298+
`McpApplication.run(mainClass, args)` 默认加载 `mcp-server.yml`;可通过第三个参数指定 classpath 中的其他配置文件名。
295299

296300
#### MCP Java SDK 2.x(里程碑版本)
297301

@@ -328,13 +332,17 @@ your-mcp-project/
328332
329333
## 🧪 测试
330334
331-
运行测试
335+
运行单元测试(请使用 Maven Wrapper 构建,勿使用系统安装的 `mvn`)
332336
333337
```bash
334338
./mvnw clean test
335339
```
336340

337-
Windows 下可使用 `mvnw.cmd clean test`
341+
Windows:
342+
343+
```bash
344+
mvnw.cmd clean test
345+
```
338346

339347
## ❓ 常见问题
340348

@@ -392,7 +400,7 @@ Windows 下可使用 `mvnw.cmd clean test`。
392400
git clone https://github.com/thought2code/mcp-annotated-java-sdk.git
393401
cd mcp-annotated-java-sdk
394402

395-
# 构建项目
403+
# 构建项目(validate 阶段会执行 Spotless 格式检查)
396404
./mvnw clean install
397405

398406
# 运行测试

docs/components.md

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ public class MyResources {
3838
| `name` | Resource name (defaults to method name) | No |
3939
| `title` | Resource title (defaults to `name`) | No |
4040
| `mimeType` | MIME type of the resource content | No (default `text/plain`) |
41+
| `roles` | Roles allowed to access the resource | No (default `ASSISTANT`, `USER`) |
42+
| `priority` | Resource priority | No (default `1.0`) |
4143

4244
## Tools
4345

@@ -150,7 +152,12 @@ Handlers must **return** `CompletionResult` and take **exactly one** parameter o
150152

151153
### Resource Completions
152154

155+
`@McpResourceCompletion.uri` must match the **`uri` on `@McpResource` exactly** (including URI templates such as `file://{path}`).
156+
157+
Pair the completion handler with a resource that uses the same URI pattern:
158+
153159
```java
160+
import com.github.thought2code.mcp.annotated.annotation.McpResource;
154161
import com.github.thought2code.mcp.annotated.annotation.McpResourceCompletion;
155162
import com.github.thought2code.mcp.annotated.server.component.completion.CompletionResult;
156163
import io.modelcontextprotocol.spec.McpSchema;
@@ -161,8 +168,13 @@ import java.nio.file.Paths;
161168
import java.util.List;
162169
import java.util.stream.Collectors;
163170

164-
public class MyCompletions {
165-
@McpResourceCompletion(uri = "file://")
171+
public class MyFileResources {
172+
@McpResource(uri = "file://{path}", description = "Read a file by path")
173+
public String readFile() {
174+
return "file content";
175+
}
176+
177+
@McpResourceCompletion(uri = "file://{path}")
166178
public CompletionResult completeFileUri(McpSchema.CompleteRequest.CompleteArgument argument) {
167179
String prefix = argument.value() != null ? argument.value() : "";
168180
try {
@@ -185,7 +197,7 @@ public class MyCompletions {
185197

186198
### Prompt Completions
187199

188-
`@McpPromptCompletion.name` must match the **registered prompt name** (by default, the Java method name of the `@McpPrompt` method). Filter by `argument.name()` when one prompt has multiple parameters.
200+
`@McpPromptCompletion.name` must match the **registered prompt name** the `@McpPrompt.name` attribute when set, otherwise the `@McpPrompt` method name. Filter by `argument.name()` when one prompt has multiple parameters (the name must match the `@McpPromptParam.name` being completed).
189201

190202
```java
191203
import com.github.thought2code.mcp.annotated.annotation.McpPromptCompletion;
@@ -215,8 +227,9 @@ After defining MCP components, they will be automatically registered to the serv
215227

216228
### One instance per component class
217229

218-
The SDK creates a single object per component class (via its no-arg constructor) and invokes all annotated methods on that class through the same instance. **Concurrent requests share one object**, so:
230+
The SDK creates a single object per component class (via its **public no-arg constructor**) and invokes all annotated methods on that class through the same instance. **Concurrent requests share one object**, so:
219231

232+
- Component classes must expose an accessible no-arg constructor.
220233
- Keep component classes stateless when possible.
221234
- Any mutable instance fields must be thread-safe, or you must synchronize access.
222235
- Do not treat instance fields as per-request storage.
@@ -235,7 +248,13 @@ If you need to specify a specific package path, you can use the following method
235248
@McpServerApplication(basePackage = "com.example.mcp.components")
236249
```
237250

238-
If no package path is specified, the package of the class passed to `McpApplication.run()` is used as the default registration scope.
251+
Resolution order when both are available on the main class:
252+
253+
1. `basePackageClass` (when not `Object.class`) — package of that class
254+
2. non-blank `basePackage`
255+
3. package of the class passed to `McpApplication.run()`
256+
257+
Subpackages under the resolved base package are included; classes in other packages are ignored.
239258

240259
## Structured Content
241260

docs/getting-started.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ This guide will help you build your first MCP server in 5 minutes.
2929
implementation 'io.github.thought2code:mcp-annotated-java-sdk:0.17.0'
3030
```
3131

32+
Use the [Maven Central artifact page](https://central.sonatype.com/artifact/io.github.thought2code/mcp-annotated-java-sdk) for the latest release version. This repository’s development version is `0.18.0-SNAPSHOT`.
33+
3234
## 5-Minutes Tutorial
3335

3436
### Step 1: Create Configuration File
@@ -118,6 +120,8 @@ public class MyPrompts {
118120

119121
Run `MyFirstMcpServer` from your IDE, or use `java -cp ...` with your compiled classes and dependencies on the classpath. Use an executable JAR setup in your own project if you need `java -jar` with a single file.
120122

123+
To load a non-default configuration file name, use `McpApplication.run(MyFirstMcpServer.class, args, "custom-mcp-server.yml")`.
124+
121125
## Server Modes
122126

123127
This SDK supports three MCP server modes. If you omit `mode` in `mcp-server.yml`, the server defaults to **STREAMABLE** (see the configuration table below).
@@ -203,7 +207,7 @@ Use **SYNC** by default. Choose **ASYNC** only when your deployment requires the
203207

204208
### Component instances and concurrency
205209

206-
The SDK creates **one instance per component class** and reuses it for all requests. Concurrent MCP calls share that object. Keep components **stateless** or **thread-safe**; avoid unsynchronized per-request instance fields.
210+
The SDK creates **one instance per component class** (via a **public no-arg constructor**) and reuses it for all requests. Concurrent MCP calls share that object. Keep components **stateless** or **thread-safe**; avoid unsynchronized per-request instance fields.
207211

208212
### MCP Java SDK 2.x (milestone)
209213

docs/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,6 @@ Want to get started quickly? Check out the [Getting Started Guide](./getting-sta
6767
## 🔗 Quick Links
6868

6969
- [Getting Started Guide](./getting-started.md) - Build your first MCP server
70-
- [Core Components](./components.md) - Learn about Resources, Tools, and Prompts
70+
- [Core Components](./components.md) - Resources, Tools, Prompts, and Completions
7171
- [GitHub Repository](https://github.com/thought2code/mcp-annotated-java-sdk) - Source code and examples
7272
- [Examples](https://github.com/thought2code/mcp-java-sdk-examples) - Real-world examples

llms-full.txt

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ The Model Context Protocol (MCP) is a standardized protocol for building servers
5151
implementation 'io.github.thought2code:mcp-annotated-java-sdk:0.17.0'
5252
```
5353

54+
Latest release: https://central.sonatype.com/artifact/io.github.thought2code/mcp-annotated-java-sdk (repo development version: 0.18.0-SNAPSHOT).
55+
5456
## Quick Start Tutorial
5557

5658
### Step 1: Create Configuration File
@@ -159,6 +161,8 @@ public class MyPrompts {
159161

160162
Run `MyFirstMcpServer` from your IDE, or use `java -cp ...` with your compiled classes and dependencies on the classpath. Use an executable JAR setup in your own project if you need `java -jar` with a single file.
161163

164+
Optional: `McpApplication.run(MyFirstMcpServer.class, args, "custom-mcp-server.yml")` to load a different config file (default `mcp-server.yml`).
165+
162166
## Core Components
163167

164168
### Resources
@@ -174,6 +178,8 @@ Resource components are used to expose data to LLMs, similar to GET requests in
174178
| `name` | Resource name (defaults to method name) | No |
175179
| `title` | Resource title (defaults to `name`) | No |
176180
| `mimeType` | MIME type of the resource content | No (default `text/plain`) |
181+
| `roles` | Roles allowed to access the resource | No (default `ASSISTANT`, `USER`) |
182+
| `priority` | Resource priority | No (default `1.0`) |
177183

178184
### Tools
179185

@@ -223,39 +229,35 @@ Handlers must **return** `CompletionResult` and take **exactly one** parameter o
223229

224230
#### Resource Completions
225231

232+
`@McpResourceCompletion.uri` must match the paired `@McpResource.uri` exactly (including URI templates).
233+
226234
```java
235+
import com.github.thought2code.mcp.annotated.annotation.McpResource;
227236
import com.github.thought2code.mcp.annotated.annotation.McpResourceCompletion;
228237
import com.github.thought2code.mcp.annotated.server.component.completion.CompletionResult;
229238
import io.modelcontextprotocol.spec.McpSchema;
230-
import java.nio.file.Files;
231-
import java.nio.file.Path;
232-
import java.nio.file.Paths;
233239
import java.util.List;
234-
import java.util.stream.Collectors;
235-
236-
@McpResourceCompletion(uri = "file://")
237-
public CompletionResult completeFileUri(McpSchema.CompleteRequest.CompleteArgument argument) {
238-
String prefix = argument.value() != null ? argument.value() : "";
239-
try {
240-
List<String> paths =
241-
Files.list(Paths.get(prefix.isEmpty() ? "." : prefix))
242-
.map(Path::toString)
243-
.limit(50)
244-
.collect(Collectors.toList());
240+
241+
public class MyFileResources {
242+
@McpResource(uri = "file://{path}", description = "Read a file by path")
243+
public String readFile() {
244+
return "file content";
245+
}
246+
247+
@McpResourceCompletion(uri = "file://{path}")
248+
public CompletionResult completeFileUri(McpSchema.CompleteRequest.CompleteArgument argument) {
245249
return CompletionResult.builder()
246-
.values(paths)
247-
.total(paths.size())
250+
.values(List.of("file://a", "file://b"))
251+
.total(2)
248252
.hasMore(false)
249253
.build();
250-
} catch (Exception e) {
251-
return CompletionResult.empty();
252254
}
253255
}
254256
```
255257

256258
#### Prompt Completions
257259

258-
`@McpPromptCompletion.name` must match the **registered prompt name** (by default, the Java method name of the `@McpPrompt` method). Filter by `argument.name()` when one prompt has multiple parameters.
260+
`@McpPromptCompletion.name` must match the registered prompt name (`@McpPrompt.name` when set, otherwise the `@McpPrompt` method name). Filter by `argument.name()` when one prompt has multiple parameters (must match `@McpPromptParam.name`).
259261

260262
```java
261263
import com.github.thought2code.mcp.annotated.annotation.McpPromptCompletion;
@@ -414,6 +416,14 @@ public String divide(
414416

415417
After defining MCP components, they will be automatically registered to the server. You just need to ensure that the component classes are within the registration scope of the server application.
416418

419+
### One instance per component class
420+
421+
The SDK creates one object per component class (public no-arg constructor) and reuses it for all requests. Concurrent MCP calls share that object — keep components stateless or thread-safe.
422+
423+
### SYNC vs ASYNC server type
424+
425+
`type: ASYNC` uses the async MCP server API; handlers wrap blocking Java methods in `Mono.fromCallable(...)`. Annotated methods do not return `Mono`/`Flux`.
426+
417427
### Specify Package Path
418428

419429
```java
@@ -422,7 +432,7 @@ After defining MCP components, they will be automatically registered to the serv
422432
@McpServerApplication(basePackage = "com.example.mcp.components")
423433
```
424434

425-
If no package path is specified, the package of the class passed to `McpApplication.run()` is used as the default registration scope.
435+
Resolution order: `basePackageClass` (when not `Object.class`) → non-blank `basePackage` → package of `McpApplication.run()` main class. Subpackages under the resolved base package are included.
426436

427437
## Project Structure
428438

llms.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ A lightweight, annotation-based Java framework that simplifies MCP (Model Contex
3434
implementation 'io.github.thought2code:mcp-annotated-java-sdk:0.17.0'
3535
```
3636

37+
Latest release: https://central.sonatype.com/artifact/io.github.thought2code/mcp-annotated-java-sdk (repo development version: 0.18.0-SNAPSHOT).
38+
3739
### Create MCP Server
3840

3941
```java
@@ -95,6 +97,13 @@ public String generateCode(
9597
| `@McpJsonSchemaDefinition` | Marks a type as a custom JSON Schema definition |
9698
| `@McpJsonSchemaProperty` | Describes a field in a JSON Schema definition |
9799

100+
## Completions
101+
102+
When `capabilities.completion: true`, handlers return `CompletionResult` and accept one `McpSchema.CompleteRequest.CompleteArgument` parameter.
103+
104+
- `@McpResourceCompletion.uri` must match the paired `@McpResource.uri` exactly (including templates like `file://{path}`).
105+
- `@McpPromptCompletion.name` must match the registered prompt name (`@McpPrompt.name`, or else the `@McpPrompt` method name). Filter with `argument.name()` for multi-parameter prompts.
106+
98107
## Server Modes
99108

100109
If `mode` is omitted in `mcp-server.yml`, the server defaults to **STREAMABLE**.
@@ -129,7 +138,8 @@ change-notification:
129138

130139
## Important Notes
131140

132-
- Use `McpApplication.run()` as the server entry point; component registration scope is resolved through `@McpServerApplication`
141+
- Use `McpApplication.run()` as the server entry point; optional third argument overrides the config file name (default `mcp-server.yml`)
142+
- Component registration scope: `basePackageClass` → `basePackage` → main class package; one instance per component class (public no-arg constructor)
133143
- `instructions` must be a non-blank string in `mcp-server.yml` (validated at startup)
134144
- SSE mode and related APIs (`ServerMode.SSE`, `McpSseServer`, `ServerSse`, `sse.*` config) are deprecated with `forRemoval = true` since 0.16.0; use STREAMABLE for new HTTP deployments
135145
- Built on MCP Java SDK **2.0.0-M3** (milestone) — pin versions and retest when upgrading

src/main/java/com/github/thought2code/mcp/annotated/annotation/McpToolParam.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
*
1313
* <p>The parameter's name must be specified explicitly. Parameter metadata such as description and
1414
* required status can be specified via the corresponding attributes. If omitted, these metadata
15-
* fields will default to the value of the {@code name} attribute and {@code false}.
15+
* fields will default to the value of the {@code name} attribute and {@code true} for {@code
16+
* required}.
1617
*
1718
* <p>Example usage:
1819
*

0 commit comments

Comments
 (0)