Skip to content

Commit 08620ac

Browse files
committed
feat: add wait MCP
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
1 parent 4bf45e1 commit 08620ac

3 files changed

Lines changed: 109 additions & 1 deletion

File tree

.github/workflows/image.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
runs-on: ubuntu-latest
1818
strategy:
1919
matrix:
20-
mcp: [duckduckgo, weather, memory, homeassistant, scripts, localrecall, twitter, todo, mailbox]
20+
mcp: [duckduckgo, weather, wait, memory, homeassistant, scripts, localrecall, twitter, todo, mailbox]
2121
permissions:
2222
packages: write
2323
contents: read

README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,55 @@ mcp:
101101
}
102102
```
103103

104+
### ⏱️ Wait Server
105+
106+
A simple wait/sleep server that allows AI models to autonomously wait for a specified duration. Useful for waiting for asynchronous operations to complete.
107+
108+
**Features:**
109+
- Wait for a specified duration in seconds (supports fractional seconds)
110+
- Context cancellation support for interruption
111+
- Input validation (positive duration, maximum 1 hour)
112+
- JSON schema validation for inputs/outputs
113+
114+
**Tool:**
115+
- `wait` - Wait for a specified duration in seconds
116+
117+
**Input Format:**
118+
```json
119+
{
120+
"duration": 5.5
121+
}
122+
```
123+
124+
**Output Format:**
125+
```json
126+
{
127+
"message": "Waited for 5.50 seconds"
128+
}
129+
```
130+
131+
**Docker Image:**
132+
```bash
133+
docker run ghcr.io/mudler/mcps/wait:latest
134+
```
135+
136+
**LocalAI configuration (to add to the model config):**
137+
```yaml
138+
mcp:
139+
stdio: |
140+
{
141+
"mcpServers": {
142+
"wait": {
143+
"command": "docker",
144+
"args": [
145+
"run", "-i", "--rm",
146+
"ghcr.io/mudler/mcps/wait:master"
147+
]
148+
}
149+
}
150+
}
151+
```
152+
104153
### 🧠 Memory Server
105154

106155
A persistent memory storage server that allows AI models to store, retrieve, and manage information across sessions using disk-based full-text search.
@@ -992,6 +1041,7 @@ make dev
9921041
# Build specific server
9931042
make MCP_SERVER=duckduckgo build
9941043
make MCP_SERVER=weather build
1044+
make MCP_SERVER=wait build
9951045
make MCP_SERVER=memory build
9961046
make MCP_SERVER=shell build
9971047
make MCP_SERVER=ssh build
@@ -1054,6 +1104,9 @@ Docker images are automatically built and pushed to GitHub Container Registry:
10541104
- `ghcr.io/mudler/mcps/weather:latest` - Latest Weather server
10551105
- `ghcr.io/mudler/mcps/weather:v1.0.0` - Tagged versions
10561106
- `ghcr.io/mudler/mcps/weather:master` - Development versions
1107+
- `ghcr.io/mudler/mcps/wait:latest` - Latest Wait server
1108+
- `ghcr.io/mudler/mcps/wait:v1.0.0` - Tagged versions
1109+
- `ghcr.io/mudler/mcps/wait:master` - Development versions
10571110
- `ghcr.io/mudler/mcps/memory:latest` - Latest Memory server
10581111
- `ghcr.io/mudler/mcps/memory:v1.0.0` - Tagged versions
10591112
- `ghcr.io/mudler/mcps/memory:master` - Development versions

wait/main.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
"time"
8+
9+
"github.com/modelcontextprotocol/go-sdk/mcp"
10+
)
11+
12+
type Input struct {
13+
Duration float64 `json:"duration" jsonschema:"duration to wait in seconds (supports fractional seconds like 0.5, 1.5)"`
14+
}
15+
16+
type Output struct {
17+
Message string `json:"message" jsonschema:"confirmation message indicating the wait completed"`
18+
}
19+
20+
const maxDuration = 3600 // 1 hour in seconds
21+
22+
func Wait(ctx context.Context, req *mcp.CallToolRequest, input Input) (
23+
*mcp.CallToolResult,
24+
Output,
25+
error,
26+
) {
27+
// Validate input
28+
if input.Duration <= 0 {
29+
return nil, Output{}, fmt.Errorf("duration must be positive, got: %f", input.Duration)
30+
}
31+
if input.Duration > maxDuration {
32+
return nil, Output{}, fmt.Errorf("duration exceeds maximum of %d seconds (1 hour), got: %f", maxDuration, input.Duration)
33+
}
34+
35+
// Convert seconds to duration
36+
duration := time.Duration(input.Duration * float64(time.Second))
37+
38+
// Wait with context cancellation support
39+
select {
40+
case <-ctx.Done():
41+
return nil, Output{}, ctx.Err()
42+
case <-time.After(duration):
43+
message := fmt.Sprintf("Waited for %.2f seconds", input.Duration)
44+
return nil, Output{Message: message}, nil
45+
}
46+
}
47+
48+
func main() {
49+
// Create a server with a single tool.
50+
server := mcp.NewServer(&mcp.Implementation{Name: "wait", Version: "v1.0.0"}, nil)
51+
mcp.AddTool(server, &mcp.Tool{Name: "wait", Description: "Wait for a specified duration in seconds"}, Wait)
52+
if err := server.Run(context.Background(), &mcp.StdioTransport{}); err != nil {
53+
log.Fatal(err)
54+
}
55+
}

0 commit comments

Comments
 (0)