mcp-new 1.2.2 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -1
- package/dist/{chunk-3JG4FVS2.js → chunk-YISSMIHU.js} +222 -46
- package/dist/cli.js +334 -15
- package/dist/index.d.ts +25 -7
- package/dist/index.js +17 -3
- package/package.json +1 -1
- package/templates/csharp/.env.example +6 -0
- package/templates/csharp/.gitignore.ejs +53 -0
- package/templates/csharp/McpServer.csproj.ejs +19 -0
- package/templates/csharp/README.md.ejs +136 -0
- package/templates/csharp/src/Program.cs.ejs +117 -0
- package/templates/elixir/.env.example +6 -0
- package/templates/elixir/.gitignore.ejs +33 -0
- package/templates/elixir/README.md.ejs +154 -0
- package/templates/elixir/config/config.exs.ejs +9 -0
- package/templates/elixir/config/dev.exs.ejs +3 -0
- package/templates/elixir/config/prod.exs.ejs +3 -0
- package/templates/elixir/lib/application.ex.ejs +19 -0
- package/templates/elixir/lib/cli.ex.ejs +17 -0
- package/templates/elixir/lib/server.ex.ejs +112 -0
- package/templates/elixir/mix.exs.ejs +32 -0
- package/templates/java/gradle/.env.example +6 -0
- package/templates/java/gradle/.gitignore.ejs +48 -0
- package/templates/java/gradle/README.md.ejs +132 -0
- package/templates/java/gradle/build.gradle.ejs +46 -0
- package/templates/java/gradle/settings.gradle.ejs +1 -0
- package/templates/java/gradle/src/main/java/com/example/mcp/McpServer.java.ejs +149 -0
- package/templates/java/gradle/src/main/resources/logback.xml +13 -0
- package/templates/java/maven/.env.example +6 -0
- package/templates/java/maven/.gitignore.ejs +53 -0
- package/templates/java/maven/README.md.ejs +131 -0
- package/templates/java/maven/pom.xml.ejs +86 -0
- package/templates/java/maven/src/main/java/com/example/mcp/McpServer.java.ejs +149 -0
- package/templates/java/maven/src/main/resources/logback.xml +13 -0
- package/templates/kotlin/gradle/.env.example +6 -0
- package/templates/kotlin/gradle/.gitignore.ejs +45 -0
- package/templates/kotlin/gradle/README.md.ejs +138 -0
- package/templates/kotlin/gradle/build.gradle.kts.ejs +48 -0
- package/templates/kotlin/gradle/settings.gradle.kts.ejs +1 -0
- package/templates/kotlin/gradle/src/main/kotlin/com/example/mcp/McpServer.kt.ejs +141 -0
- package/templates/kotlin/gradle/src/main/resources/logback.xml +13 -0
- package/templates/kotlin/maven/.env.example +6 -0
- package/templates/kotlin/maven/.gitignore.ejs +50 -0
- package/templates/kotlin/maven/README.md.ejs +96 -0
- package/templates/kotlin/maven/pom.xml.ejs +105 -0
- package/templates/kotlin/maven/src/main/kotlin/com/example/mcp/McpServer.kt.ejs +141 -0
- package/templates/kotlin/maven/src/main/resources/logback.xml +13 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# <%= name %>
|
|
2
|
+
|
|
3
|
+
<%= description || 'MCP Server generated by mcp-new' %>
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- .NET 8.0 SDK or higher
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Restore dependencies
|
|
13
|
+
dotnet restore
|
|
14
|
+
|
|
15
|
+
# Build
|
|
16
|
+
dotnet build
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Running the Server
|
|
20
|
+
|
|
21
|
+
### Development
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
dotnet run
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Production
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Build release version
|
|
31
|
+
dotnet publish -c Release -o publish
|
|
32
|
+
|
|
33
|
+
# Run
|
|
34
|
+
./publish/<%= name %>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Configuration with Claude Desktop
|
|
38
|
+
|
|
39
|
+
Add this to your Claude Desktop config file:
|
|
40
|
+
|
|
41
|
+
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
42
|
+
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"mcpServers": {
|
|
47
|
+
"<%= name %>": {
|
|
48
|
+
"command": "dotnet",
|
|
49
|
+
"args": ["run", "--project", "/path/to/<%= name %>"]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Or with published binary:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"mcpServers": {
|
|
60
|
+
"<%= name %>": {
|
|
61
|
+
"command": "/path/to/<%= name %>/publish/<%= name %>"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Available Tools
|
|
68
|
+
|
|
69
|
+
<% if (includeExampleTool) { %>
|
|
70
|
+
### example_tool
|
|
71
|
+
An example tool that echoes the input
|
|
72
|
+
|
|
73
|
+
**Parameters:**
|
|
74
|
+
- `query` (string, required): The query to echo
|
|
75
|
+
<% } %>
|
|
76
|
+
|
|
77
|
+
<% tools.forEach(function(tool) { %>
|
|
78
|
+
### <%= tool.name %>
|
|
79
|
+
<%= tool.description %>
|
|
80
|
+
|
|
81
|
+
**Parameters:**
|
|
82
|
+
<% tool.parameters.forEach(function(param) { %>
|
|
83
|
+
- `<%= param.name %>` (<%= param.type %><%= param.required ? ', required' : '' %>): <%= param.description %>
|
|
84
|
+
<% }); %>
|
|
85
|
+
<% }); %>
|
|
86
|
+
|
|
87
|
+
## Project Structure
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
<%= name %>/
|
|
91
|
+
├── <%= name %>.csproj # Project file
|
|
92
|
+
├── src/
|
|
93
|
+
│ └── Program.cs # Main server file
|
|
94
|
+
├── .gitignore
|
|
95
|
+
├── .env.example
|
|
96
|
+
└── README.md
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Development
|
|
100
|
+
|
|
101
|
+
### Adding a New Tool
|
|
102
|
+
|
|
103
|
+
1. Open `src/Program.cs`
|
|
104
|
+
2. Add a new tool registration in the `RegisterTools` method:
|
|
105
|
+
|
|
106
|
+
```csharp
|
|
107
|
+
services.AddMcpTool("my_new_tool", "Description of my tool", async (args, cancellationToken) =>
|
|
108
|
+
{
|
|
109
|
+
var param1 = args.GetProperty("param1").GetString();
|
|
110
|
+
// Your tool logic here
|
|
111
|
+
return new ToolResult
|
|
112
|
+
{
|
|
113
|
+
Content = new[]
|
|
114
|
+
{
|
|
115
|
+
new TextContent { Text = $"Result: {param1}" }
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
},
|
|
119
|
+
new ToolInputSchema
|
|
120
|
+
{
|
|
121
|
+
Type = "object",
|
|
122
|
+
Properties = new Dictionary<string, ToolPropertySchema>
|
|
123
|
+
{
|
|
124
|
+
["param1"] = new ToolPropertySchema
|
|
125
|
+
{
|
|
126
|
+
Type = "string",
|
|
127
|
+
Description = "Parameter description"
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
Required = new[] { "param1" }
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
MIT
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
using Microsoft.Extensions.DependencyInjection;
|
|
2
|
+
using Microsoft.Extensions.Hosting;
|
|
3
|
+
using Microsoft.Extensions.Logging;
|
|
4
|
+
using ModelContextProtocol.Server;
|
|
5
|
+
using System.Text.Json;
|
|
6
|
+
|
|
7
|
+
namespace <%= namespace %>;
|
|
8
|
+
|
|
9
|
+
/// <summary>
|
|
10
|
+
/// <%= name %> MCP Server
|
|
11
|
+
/// <%= description || 'Generated by mcp-new' %>
|
|
12
|
+
/// </summary>
|
|
13
|
+
class Program
|
|
14
|
+
{
|
|
15
|
+
static async Task Main(string[] args)
|
|
16
|
+
{
|
|
17
|
+
var builder = Host.CreateApplicationBuilder(args);
|
|
18
|
+
|
|
19
|
+
builder.Logging.AddConsole();
|
|
20
|
+
builder.Logging.SetMinimumLevel(LogLevel.Information);
|
|
21
|
+
|
|
22
|
+
builder.Services.AddMcpServer(options =>
|
|
23
|
+
{
|
|
24
|
+
options.ServerInfo = new ServerInfo
|
|
25
|
+
{
|
|
26
|
+
Name = "<%= name %>",
|
|
27
|
+
Version = "1.0.0"
|
|
28
|
+
};
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Register tools
|
|
32
|
+
RegisterTools(builder.Services);
|
|
33
|
+
|
|
34
|
+
var host = builder.Build();
|
|
35
|
+
|
|
36
|
+
<% if (transport === 'stdio') { %>
|
|
37
|
+
// Start STDIO server
|
|
38
|
+
Console.Error.WriteLine("<%= name %> MCP server running on stdio");
|
|
39
|
+
await host.RunMcpServerAsync();
|
|
40
|
+
<% } else { %>
|
|
41
|
+
// Start SSE server
|
|
42
|
+
Console.Error.WriteLine("<%= name %> MCP server running on SSE at http://localhost:8080");
|
|
43
|
+
await host.RunMcpSseServerAsync(8080);
|
|
44
|
+
<% } %>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
static void RegisterTools(IServiceCollection services)
|
|
48
|
+
{
|
|
49
|
+
<% if (includeExampleTool) { %>
|
|
50
|
+
// Register example_tool
|
|
51
|
+
services.AddMcpTool("example_tool", "An example tool that echoes the input", async (args, cancellationToken) =>
|
|
52
|
+
{
|
|
53
|
+
var query = args.GetProperty("query").GetString() ?? "";
|
|
54
|
+
return new ToolResult
|
|
55
|
+
{
|
|
56
|
+
Content = new[]
|
|
57
|
+
{
|
|
58
|
+
new TextContent { Text = $"Echo: {query}" }
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
new ToolInputSchema
|
|
63
|
+
{
|
|
64
|
+
Type = "object",
|
|
65
|
+
Properties = new Dictionary<string, ToolPropertySchema>
|
|
66
|
+
{
|
|
67
|
+
["query"] = new ToolPropertySchema
|
|
68
|
+
{
|
|
69
|
+
Type = "string",
|
|
70
|
+
Description = "The query to echo"
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
Required = new[] { "query" }
|
|
74
|
+
});
|
|
75
|
+
<% } %>
|
|
76
|
+
|
|
77
|
+
<% tools.forEach(function(tool) { %>
|
|
78
|
+
// Register <%= tool.name %>
|
|
79
|
+
services.AddMcpTool("<%= tool.name %>", "<%= tool.description %>", async (args, cancellationToken) =>
|
|
80
|
+
{
|
|
81
|
+
// TODO: Implement <%= tool.name %> logic
|
|
82
|
+
<% tool.parameters.forEach(function(param) { %>
|
|
83
|
+
<% if (param.type === 'number') { %>
|
|
84
|
+
var <%= param.name %> = args.GetProperty("<%= param.name %>").GetDouble();
|
|
85
|
+
<% } else if (param.type === 'boolean') { %>
|
|
86
|
+
var <%= param.name %> = args.GetProperty("<%= param.name %>").GetBoolean();
|
|
87
|
+
<% } else { %>
|
|
88
|
+
var <%= param.name %> = args.GetProperty("<%= param.name %>").GetString();
|
|
89
|
+
<% } %>
|
|
90
|
+
<% }); %>
|
|
91
|
+
|
|
92
|
+
return new ToolResult
|
|
93
|
+
{
|
|
94
|
+
Content = new[]
|
|
95
|
+
{
|
|
96
|
+
new TextContent { Text = $"<%= tool.name %> called with: {args}" }
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
new ToolInputSchema
|
|
101
|
+
{
|
|
102
|
+
Type = "object",
|
|
103
|
+
Properties = new Dictionary<string, ToolPropertySchema>
|
|
104
|
+
{
|
|
105
|
+
<% tool.parameters.forEach(function(param, index) { %>
|
|
106
|
+
["<%= param.name %>"] = new ToolPropertySchema
|
|
107
|
+
{
|
|
108
|
+
Type = "<%= param.type %>",
|
|
109
|
+
Description = "<%= param.description %>"
|
|
110
|
+
}<%= index < tool.parameters.length - 1 ? ',' : '' %>
|
|
111
|
+
<% }); %>
|
|
112
|
+
},
|
|
113
|
+
Required = new[] { <%= tool.parameters.filter(p => p.required).map(p => '"' + p.name + '"').join(', ') %> }
|
|
114
|
+
});
|
|
115
|
+
<% }); %>
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
/deps/
|
|
3
|
+
/_build/
|
|
4
|
+
/cover/
|
|
5
|
+
/doc/
|
|
6
|
+
|
|
7
|
+
# Dialyzer
|
|
8
|
+
/priv/plts/
|
|
9
|
+
|
|
10
|
+
# Generated files
|
|
11
|
+
*.beam
|
|
12
|
+
*.ez
|
|
13
|
+
erl_crash.dump
|
|
14
|
+
|
|
15
|
+
# Release
|
|
16
|
+
/rel/
|
|
17
|
+
|
|
18
|
+
# IDE
|
|
19
|
+
.idea/
|
|
20
|
+
*.iml
|
|
21
|
+
.vscode/
|
|
22
|
+
*.swp
|
|
23
|
+
*.swo
|
|
24
|
+
*~
|
|
25
|
+
|
|
26
|
+
# OS
|
|
27
|
+
.DS_Store
|
|
28
|
+
Thumbs.db
|
|
29
|
+
|
|
30
|
+
# Environment
|
|
31
|
+
.env
|
|
32
|
+
.env.local
|
|
33
|
+
*.secret.exs
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# <%= name %>
|
|
2
|
+
|
|
3
|
+
<%= description || 'MCP Server generated by mcp-new' %>
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Elixir 1.15 or higher
|
|
8
|
+
- Erlang/OTP 25 or higher
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
# Install dependencies
|
|
14
|
+
mix deps.get
|
|
15
|
+
|
|
16
|
+
# Compile
|
|
17
|
+
mix compile
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Running the Server
|
|
21
|
+
|
|
22
|
+
### Development
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Run in interactive mode
|
|
26
|
+
iex -S mix
|
|
27
|
+
|
|
28
|
+
# Or run directly
|
|
29
|
+
mix run --no-halt
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Production
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
# Build release
|
|
36
|
+
MIX_ENV=prod mix release
|
|
37
|
+
|
|
38
|
+
# Or build escript
|
|
39
|
+
mix escript.build
|
|
40
|
+
|
|
41
|
+
# Run escript
|
|
42
|
+
./<%= packageName %>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Configuration with Claude Desktop
|
|
46
|
+
|
|
47
|
+
Add this to your Claude Desktop config file:
|
|
48
|
+
|
|
49
|
+
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
50
|
+
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"mcpServers": {
|
|
55
|
+
"<%= name %>": {
|
|
56
|
+
"command": "mix",
|
|
57
|
+
"args": ["run", "--no-halt"],
|
|
58
|
+
"cwd": "/path/to/<%= name %>"
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Or with escript:
|
|
65
|
+
|
|
66
|
+
```json
|
|
67
|
+
{
|
|
68
|
+
"mcpServers": {
|
|
69
|
+
"<%= name %>": {
|
|
70
|
+
"command": "/path/to/<%= name %>/<%= packageName %>"
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Available Tools
|
|
77
|
+
|
|
78
|
+
<% if (includeExampleTool) { %>
|
|
79
|
+
### example_tool
|
|
80
|
+
An example tool that echoes the input
|
|
81
|
+
|
|
82
|
+
**Parameters:**
|
|
83
|
+
- `query` (string, required): The query to echo
|
|
84
|
+
<% } %>
|
|
85
|
+
|
|
86
|
+
<% tools.forEach(function(tool) { %>
|
|
87
|
+
### <%= tool.name %>
|
|
88
|
+
<%= tool.description %>
|
|
89
|
+
|
|
90
|
+
**Parameters:**
|
|
91
|
+
<% tool.parameters.forEach(function(param) { %>
|
|
92
|
+
- `<%= param.name %>` (<%= param.type %><%= param.required ? ', required' : '' %>): <%= param.description %>
|
|
93
|
+
<% }); %>
|
|
94
|
+
<% }); %>
|
|
95
|
+
|
|
96
|
+
## Project Structure
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
<%= name %>/
|
|
100
|
+
├── mix.exs # Project configuration
|
|
101
|
+
├── config/
|
|
102
|
+
│ ├── config.exs # Base configuration
|
|
103
|
+
│ ├── dev.exs # Development config
|
|
104
|
+
│ └── prod.exs # Production config
|
|
105
|
+
├── lib/
|
|
106
|
+
│ ├── application.ex # Application entry point
|
|
107
|
+
│ ├── server.ex # MCP Server implementation
|
|
108
|
+
│ └── cli.ex # CLI entry point
|
|
109
|
+
├── .gitignore
|
|
110
|
+
├── .env.example
|
|
111
|
+
└── README.md
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Development
|
|
115
|
+
|
|
116
|
+
### Adding a New Tool
|
|
117
|
+
|
|
118
|
+
1. Open `lib/server.ex`
|
|
119
|
+
2. Add a new tool to the `register_tools` function:
|
|
120
|
+
|
|
121
|
+
```elixir
|
|
122
|
+
%{
|
|
123
|
+
name: "my_new_tool",
|
|
124
|
+
description: "Description of my tool",
|
|
125
|
+
input_schema: %{
|
|
126
|
+
type: "object",
|
|
127
|
+
properties: %{
|
|
128
|
+
param1: %{
|
|
129
|
+
type: "string",
|
|
130
|
+
description: "Parameter description"
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
required: ["param1"]
|
|
134
|
+
},
|
|
135
|
+
handler: &handle_my_new_tool/1
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
3. Add the handler function:
|
|
140
|
+
|
|
141
|
+
```elixir
|
|
142
|
+
defp handle_my_new_tool(%{"param1" => param1}) do
|
|
143
|
+
# Your tool logic here
|
|
144
|
+
{:ok, %{
|
|
145
|
+
content: [
|
|
146
|
+
%{type: "text", text: "Result: #{param1}"}
|
|
147
|
+
]
|
|
148
|
+
}}
|
|
149
|
+
end
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## License
|
|
153
|
+
|
|
154
|
+
MIT
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
defmodule <%= namespace %>.Application do
|
|
2
|
+
@moduledoc """
|
|
3
|
+
<%= name %> MCP Server Application
|
|
4
|
+
<%= description || 'Generated by mcp-new' %>
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
use Application
|
|
8
|
+
require Logger
|
|
9
|
+
|
|
10
|
+
@impl true
|
|
11
|
+
def start(_type, _args) do
|
|
12
|
+
children = [
|
|
13
|
+
{<%= namespace %>.Server, []}
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
opts = [strategy: :one_for_one, name: <%= namespace %>.Supervisor]
|
|
17
|
+
Supervisor.start_link(children, opts)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
defmodule <%= namespace %>.CLI do
|
|
2
|
+
@moduledoc """
|
|
3
|
+
CLI entry point for <%= name %> MCP Server
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
require Logger
|
|
7
|
+
|
|
8
|
+
def main(_args) do
|
|
9
|
+
Logger.info("<%= name %> MCP server running on stdio")
|
|
10
|
+
|
|
11
|
+
# Start the application
|
|
12
|
+
Application.ensure_all_started(:<%= packageName %>)
|
|
13
|
+
|
|
14
|
+
# Keep the process alive
|
|
15
|
+
Process.sleep(:infinity)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
defmodule <%= namespace %>.Server do
|
|
2
|
+
@moduledoc """
|
|
3
|
+
MCP Server implementation for <%= name %>
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
use GenServer
|
|
7
|
+
require Logger
|
|
8
|
+
|
|
9
|
+
def start_link(opts \\ []) do
|
|
10
|
+
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
@impl true
|
|
14
|
+
def init(_opts) do
|
|
15
|
+
Logger.info("<%= name %> MCP server starting...")
|
|
16
|
+
|
|
17
|
+
# Register tools
|
|
18
|
+
tools = register_tools()
|
|
19
|
+
|
|
20
|
+
{:ok, %{tools: tools}}
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
defp register_tools do
|
|
24
|
+
[
|
|
25
|
+
<% if (includeExampleTool) { %>
|
|
26
|
+
%{
|
|
27
|
+
name: "example_tool",
|
|
28
|
+
description: "An example tool that echoes the input",
|
|
29
|
+
input_schema: %{
|
|
30
|
+
type: "object",
|
|
31
|
+
properties: %{
|
|
32
|
+
query: %{
|
|
33
|
+
type: "string",
|
|
34
|
+
description: "The query to echo"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
required: ["query"]
|
|
38
|
+
},
|
|
39
|
+
handler: &handle_example_tool/1
|
|
40
|
+
},
|
|
41
|
+
<% } %>
|
|
42
|
+
<% tools.forEach(function(tool) { %>
|
|
43
|
+
%{
|
|
44
|
+
name: "<%= tool.name %>",
|
|
45
|
+
description: "<%= tool.description %>",
|
|
46
|
+
input_schema: %{
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: %{
|
|
49
|
+
<% tool.parameters.forEach(function(param, index) { %>
|
|
50
|
+
<%= param.name %>: %{
|
|
51
|
+
type: "<%= param.type %>",
|
|
52
|
+
description: "<%= param.description %>"
|
|
53
|
+
}<%= index < tool.parameters.length - 1 ? ',' : '' %>
|
|
54
|
+
<% }); %>
|
|
55
|
+
},
|
|
56
|
+
required: [<%= tool.parameters.filter(p => p.required).map(p => '"' + p.name + '"').join(', ') %>]
|
|
57
|
+
},
|
|
58
|
+
handler: &handle_<%= tool.name %>/1
|
|
59
|
+
},
|
|
60
|
+
<% }); %>
|
|
61
|
+
]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
<% if (includeExampleTool) { %>
|
|
65
|
+
defp handle_example_tool(%{"query" => query}) do
|
|
66
|
+
{:ok, %{
|
|
67
|
+
content: [
|
|
68
|
+
%{type: "text", text: "Echo: #{query}"}
|
|
69
|
+
]
|
|
70
|
+
}}
|
|
71
|
+
end
|
|
72
|
+
<% } %>
|
|
73
|
+
|
|
74
|
+
<% tools.forEach(function(tool) { %>
|
|
75
|
+
defp handle_<%= tool.name %>(args) do
|
|
76
|
+
# TODO: Implement <%= tool.name %> logic
|
|
77
|
+
<% tool.parameters.forEach(function(param) { %>
|
|
78
|
+
_<%= param.name %> = Map.get(args, "<%= param.name %>")
|
|
79
|
+
<% }); %>
|
|
80
|
+
|
|
81
|
+
{:ok, %{
|
|
82
|
+
content: [
|
|
83
|
+
%{type: "text", text: "<%= tool.name %> called with: #{inspect(args)}"}
|
|
84
|
+
]
|
|
85
|
+
}}
|
|
86
|
+
end
|
|
87
|
+
<% }); %>
|
|
88
|
+
|
|
89
|
+
# Handle incoming MCP messages
|
|
90
|
+
@impl true
|
|
91
|
+
def handle_info({:mcp, :list_tools}, state) do
|
|
92
|
+
tools = Enum.map(state.tools, fn tool ->
|
|
93
|
+
%{
|
|
94
|
+
name: tool.name,
|
|
95
|
+
description: tool.description,
|
|
96
|
+
inputSchema: tool.input_schema
|
|
97
|
+
}
|
|
98
|
+
end)
|
|
99
|
+
|
|
100
|
+
{:noreply, state, {:reply, %{tools: tools}}}
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
@impl true
|
|
104
|
+
def handle_info({:mcp, :call_tool, name, arguments}, state) do
|
|
105
|
+
result = case Enum.find(state.tools, fn t -> t.name == name end) do
|
|
106
|
+
nil -> {:error, "Unknown tool: #{name}"}
|
|
107
|
+
tool -> tool.handler.(arguments)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
{:noreply, state, {:reply, result}}
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
defmodule <%= namespace %>.MixProject do
|
|
2
|
+
use Mix.Project
|
|
3
|
+
|
|
4
|
+
def project do
|
|
5
|
+
[
|
|
6
|
+
app: :<%= packageName %>,
|
|
7
|
+
version: "1.0.0",
|
|
8
|
+
elixir: "~> 1.15",
|
|
9
|
+
start_permanent: Mix.env() == :prod,
|
|
10
|
+
deps: deps(),
|
|
11
|
+
escript: escript()
|
|
12
|
+
]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def application do
|
|
16
|
+
[
|
|
17
|
+
extra_applications: [:logger],
|
|
18
|
+
mod: {<%= namespace %>.Application, []}
|
|
19
|
+
]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
defp deps do
|
|
23
|
+
[
|
|
24
|
+
{:mcp, "~> 0.1.0"},
|
|
25
|
+
{:jason, "~> 1.4"}
|
|
26
|
+
]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
defp escript do
|
|
30
|
+
[main_module: <%= namespace %>.CLI]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Compiled class files
|
|
2
|
+
*.class
|
|
3
|
+
|
|
4
|
+
# Log files
|
|
5
|
+
*.log
|
|
6
|
+
|
|
7
|
+
# BlueJ files
|
|
8
|
+
*.ctxt
|
|
9
|
+
|
|
10
|
+
# Mobile Tools for Java (J2ME)
|
|
11
|
+
.mtj.tmp/
|
|
12
|
+
|
|
13
|
+
# Package Files
|
|
14
|
+
*.jar
|
|
15
|
+
*.war
|
|
16
|
+
*.nar
|
|
17
|
+
*.ear
|
|
18
|
+
*.zip
|
|
19
|
+
*.tar.gz
|
|
20
|
+
*.rar
|
|
21
|
+
|
|
22
|
+
# Gradle
|
|
23
|
+
.gradle/
|
|
24
|
+
build/
|
|
25
|
+
gradle-app.setting
|
|
26
|
+
!gradle-wrapper.jar
|
|
27
|
+
.gradletasknamecache
|
|
28
|
+
|
|
29
|
+
# IDE
|
|
30
|
+
.idea/
|
|
31
|
+
*.iml
|
|
32
|
+
*.ipr
|
|
33
|
+
*.iws
|
|
34
|
+
.project
|
|
35
|
+
.classpath
|
|
36
|
+
.settings/
|
|
37
|
+
.vscode/
|
|
38
|
+
*.swp
|
|
39
|
+
*.swo
|
|
40
|
+
*~
|
|
41
|
+
|
|
42
|
+
# OS
|
|
43
|
+
.DS_Store
|
|
44
|
+
Thumbs.db
|
|
45
|
+
|
|
46
|
+
# Environment
|
|
47
|
+
.env
|
|
48
|
+
.env.local
|