Skip to content

Commit 967e9cc

Browse files
committed
Update README.md, DEVELOPING_TOOLS.md and dispatcher scripts to version 1.7.17
1 parent 39743f3 commit 967e9cc

File tree

3 files changed

+190
-200
lines changed

3 files changed

+190
-200
lines changed

DEVELOPING_TOOLS.md

Lines changed: 85 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -1,208 +1,148 @@
1-
# Developing MCP Tools for tinystruct-mcp
1+
# Developing MCP Tools with tinystruct
22

3-
This guide explains how to extend the tinystruct-mcp server by developing your own MCP tools using the modern `@Action` annotation pattern.
3+
This guide providing step-by-step instructions on how to extend the **tinystruct-mcp** server by developing your own custom MCP tools using the annotation-driven pattern.
44

55
---
66

7-
## 1. Create a Custom Tool
7+
## 🏗 Understanding the Architecture
88

9-
To add new functionality, create a class that extends `MCPTool` and use `@Action` annotations for each operation:
9+
A tinystruct MCP implementation typically consists of two main components:
10+
1. **`MCPTool`**: A class (often an inner class) that defines the actual operations (actions) using `@Action` and `@Argument` annotations.
11+
2. **`MCPServer`**: The main application class that handles initialization and registration of tools and prompts.
12+
13+
---
14+
15+
## 🛠 1. Create a Custom Tool
16+
17+
Extend the `MCPTool` class and define your operations. Each method annotated with `@Action` becomes a tool available to the AI.
1018

1119
```java
1220
import org.tinystruct.mcp.MCPTool;
13-
import org.tinystruct.data.component.Builder;
1421
import org.tinystruct.system.annotation.Action;
1522
import org.tinystruct.system.annotation.Argument;
23+
import java.util.logging.Logger;
1624

17-
public class EchoTool extends MCPTool {
18-
19-
/**
20-
* Constructs a new EchoTool with local execution support.
21-
*/
22-
public EchoTool() {
23-
// Note the true parameter at the end to enable local execution
24-
super("echo", "A tool that echoes back input");
25-
}
26-
27-
/**
28-
* Constructs a new EchoTool with a client.
29-
*
30-
* @param client The MCP client
31-
*/
32-
public EchoTool(MCPClient client) {
33-
// Note the true parameter at the end to enable local execution
34-
super("echo", "A tool that echoes back input", null, client, true);
35-
}
25+
public class WeatherTool extends MCPTool {
26+
private static final Logger LOGGER = Logger.getLogger(WeatherTool.class.getName());
3627

37-
/**
38-
* Echoes back the input message.
39-
* @param message The message to echo
40-
* @return The echoed message
41-
*/
42-
@Action(value = "echo/message", description = "Echo back the input message", arguments = {
43-
@Argument(key = "message", description = "The message to echo", type = "string")
44-
})
45-
public String echoMessage(String message) {
46-
return message;
28+
public WeatherTool() {
29+
// Initialize with tool name and description
30+
super("weather", "A tool for retrieving weather information");
4731
}
4832

49-
/**
50-
* Echoes back the input with a prefix.
51-
* @param message The message to echo
52-
* @param prefix The prefix to add
53-
* @return The prefixed message
54-
*/
55-
@Action(value = "echo/with-prefix", description = "Echo back the input with a prefix", arguments = {
56-
@Argument(key = "message", description = "The message to echo", type = "string"),
57-
@Argument(key = "prefix", description = "The prefix to add", type = "string")
33+
@Action(value = "weather/get", description = "Get current weather for a city", arguments = {
34+
@Argument(key = "city", description = "The name of the city", type = "string"),
35+
@Argument(key = "unit", description = "Temperature unit (celsius/fahrenheit)", type = "string")
5836
})
59-
public String echoWithPrefix(String message, String prefix) {
60-
return prefix + ": " + message;
37+
public String getWeather(String city, String unit) {
38+
LOGGER.info("Fetching weather for " + city + " in " + unit);
39+
// Implement your logic here
40+
return "The weather in " + city + " is sunny, 25° " + (unit.equals("fahrenheit") ? "F" : "C");
6141
}
6242
}
6343
```
6444

6545
---
6646

67-
## 2. Register Your Tool in the Server
47+
## 🔌 2. Register the Tool in the Server
6848

69-
In your server class (extending `MCPServerApplication`), register your tool in the `init()` method:
49+
To make your tool active, you must register it within an `MCPServer` implementation's `init()` method.
7050

7151
```java
72-
public class MyMCPServer extends MCPServerApplication {
52+
import org.tinystruct.mcp.MCPServer;
53+
54+
public class MyMCPServer extends MCPServer {
7355
@Override
7456
public void init() {
7557
super.init();
76-
this.registerToolMethods(new EchoTool());
77-
// Register other tools or prompts as needed
58+
59+
// Register your custom tool
60+
this.registerTool(new WeatherTool());
61+
62+
// Optionally register other tools or prompts
7863
}
7964
}
8065
```
8166

8267
---
8368

84-
## 3. Key Features of Modern MCP Tools
69+
## 🚀 3. Start Your Server
8570

86-
### Constructor Pattern
87-
- **Default constructor**: `super("tool-name", "Tool description")` enables local execution
88-
- **Client constructor**: `super("tool-name", "Tool description", null, client, true)` for client-based execution
71+
Once your tool is registered, you can start your server using the dispatcher.
8972

90-
### @Action Annotations
91-
- **Automatic schema generation**: No need to manually build schemas
92-
- **Method-based operations**: Each `@Action` method becomes a separate tool operation
93-
- **Parameter validation**: `@Argument` annotations define parameter types and descriptions
73+
### Using the Dispatcher (Recommended)
9474

95-
### Automatic Features
96-
- **Name and description**: Set in constructor, no need to override `getName()` or `getDescription()`
97-
- **Schema generation**: Built automatically from `@Action` and `@Argument` annotations
98-
- **Local execution**: Enabled by default for better performance
99-
100-
---
75+
After compiling your project, use the `bin/dispatcher` script to load your server class:
10176

102-
## 4. Add Custom Prompts (Optional)
77+
```sh
78+
# On Linux/macOS
79+
bin/dispatcher start --import org.tinystruct.system.HttpServer --import com.yourpackage.MyMCPServer --server-port 777
10380

104-
You can also register prompts for user interaction or automation:
105-
106-
```java
107-
Builder promptSchema = new Builder();
108-
Builder properties = new Builder();
109-
Builder nameParam = new Builder();
110-
nameParam.put("type", "string");
111-
nameParam.put("description", "The name to greet");
112-
properties.put("name", nameParam);
113-
promptSchema.put("type", "object");
114-
promptSchema.put("properties", properties);
115-
promptSchema.put("required", new String[]{"name"});
116-
117-
MCPPrompt greetingPrompt = new MCPPrompt(
118-
"greeting",
119-
"A greeting prompt",
120-
"Hello, {{name}}!",
121-
promptSchema,
122-
null
123-
) {
124-
@Override
125-
protected boolean supportsLocalExecution() { return true; }
126-
};
127-
this.registerPrompt(greetingPrompt);
81+
# On Windows
82+
bin\dispatcher.cmd start --import org.tinystruct.system.HttpServer --import com.yourpackage.MyMCPServer --server-port 777
12883
```
12984

13085
---
13186

132-
## 5. Best Practices
87+
## 📝 4. Defining Arguments and Schemas
13388

134-
### Tool Design
135-
- **Single responsibility**: Each tool should focus on one domain (e.g., file operations, Git operations)
136-
- **Consistent naming**: Use `tool-name/operation` format for action values
137-
- **Clear descriptions**: Provide helpful descriptions for tools and arguments
138-
- **Error handling**: Wrap internal operations in try-catch blocks
89+
The `@Argument` annotation is crucial as it automatically generates the JSON schema required by the Model Context Protocol.
13990

140-
### Method Structure
91+
### Supported Types:
92+
* **`string`**: For text values.
93+
* **`number`**: For integers, doubles, and floats.
94+
* **`boolean`**: For true/false values.
95+
* **`object`**: For complex data structures (use `org.tinystruct.data.component.Builder`).
96+
97+
### Example with Complex Objects:
14198
```java
142-
@Action(value = "tool/operation", description = "What this operation does", arguments = {
143-
@Argument(key = "param1", description = "Description of param1", type = "string"),
144-
@Argument(key = "param2", description = "Description of param2", type = "number")
99+
@Action(value = "data/process", description = "Process complex data", arguments = {
100+
@Argument(key = "payload", description = "The JSON payload", type = "object")
145101
})
146-
public ReturnType operationName(String param1, int param2) throws MCPException {
147-
try {
148-
// Implementation logic here
149-
return result;
150-
} catch (Exception e) {
151-
LOGGER.log(Level.SEVERE, "Error in operation: " + e.getMessage(), e);
152-
throw new MCPException("Error in operation: " + e.getMessage());
153-
}
102+
public Builder processData(Builder payload) {
103+
// Logic to process the Builder object
104+
return payload;
154105
}
155106
```
156107

157-
### Parameter Types
158-
- **string**: Text values
159-
- **number**: Numeric values (int, double, etc.)
160-
- **boolean**: True/false values
161-
- **object**: Complex objects (use Builder)
162-
163108
---
164109

165-
## 6. Recommended Workflow
110+
## 💡 Best Practices
166111

167-
1. **Extend `MCPServerApplication`** and implement the `init()` method
168-
2. **Create tool class** extending `MCPTool` with proper constructors
169-
3. **Add `@Action` methods** for each operation with `@Argument` annotations
170-
4. **Register tools** using `registerToolMethods()` in `init()`
171-
5. **Optionally register prompts** for user interaction
172-
6. **Start the server** via Java or CLI
173-
7. **Configure** via properties or `Settings`
112+
1. **Namespacing**: Use the `toolname/action` format for `value` in `@Action` (e.g., `github/clone`).
113+
2. **Clear Descriptions**: Provide detailed descriptions for both tools and arguments; these are used by the LLM to understand when and how to call your tool.
114+
3. **Local Execution**: The tinystruct MCP implementation supports local execution by default. Ensure your tool methods are thread-safe.
115+
4. **Error Handling**: Wrap your logic in try-catch blocks and throw `MCPException` for errors that should be reported back to the LLM.
116+
5. **Logging**: Use `java.util.logging` to provide visibility into tool execution on the server side.
174117

175118
---
176119

177-
## 7. Example: Complete Calculator Tool
120+
## 🎯 Complete Example: Calculator
178121

179122
```java
180-
public class CalculatorTool extends MCPTool {
181-
182-
public CalculatorTool() {
183-
super("calculator", "A calculator that performs arithmetic operations");
184-
}
185-
186-
public CalculatorTool(MCPClient client) {
187-
super("calculator", "A calculator that performs arithmetic operations", null, client, true);
188-
}
189-
190-
@Action(value = "calculator/add", description = "Add two numbers", arguments = {
191-
@Argument(key = "a", description = "The first operand", type = "number"),
192-
@Argument(key = "b", description = "The second operand", type = "number")
193-
})
194-
public double add(double a, double b) {
195-
return a + b;
123+
public class Calculator extends MCPServer {
124+
@Override
125+
public void init() {
126+
super.init();
127+
this.registerTool(new CalcTool());
196128
}
197129

198-
@Action(value = "calculator/multiply", description = "Multiply two numbers", arguments = {
199-
@Argument(key = "a", description = "The first operand", type = "number"),
200-
@Argument(key = "b", description = "The second operand", type = "number")
201-
})
202-
public double multiply(double a, double b) {
203-
return a * b;
130+
public static class CalcTool extends MCPTool {
131+
public CalcTool() {
132+
super("calc", "Basic arithmetic operations");
133+
}
134+
135+
@Action(value = "calc/add", description = "Add two numbers", arguments = {
136+
@Argument(key = "a", description = "First number", type = "number"),
137+
@Argument(key = "b", description = "Second number", type = "number")
138+
})
139+
public double add(double a, double b) {
140+
return a + b;
141+
}
204142
}
205143
}
206144
```
207145

208-
**MCP stands for Model Context Protocol.**
146+
---
147+
148+
**Note**: *MCP stands for Model Context Protocol.*

0 commit comments

Comments
 (0)