Skip to content

Commit 39cc8b4

Browse files
authored
Merge branch 'zeromicro:master' into feat/k8s-resolver-local-fallback
2 parents 8d94c79 + 94e2f5b commit 39cc8b4

File tree

12 files changed

+251
-41
lines changed

12 files changed

+251
-41
lines changed

mcp/server.go

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -85,20 +85,7 @@ func (s *mcpServerImpl) setupSSETransport() {
8585
return s.mcpServer
8686
}, nil)
8787

88-
// Register the SSE endpoint
89-
s.httpServer.AddRoute(rest.Route{
90-
Method: http.MethodGet,
91-
Path: s.conf.Mcp.SseEndpoint,
92-
Handler: handler.ServeHTTP,
93-
}, rest.WithSSE(), rest.WithTimeout(s.conf.Mcp.SseTimeout))
94-
95-
// The SSE handler also handles POST requests to message endpoints
96-
// We need to route those as well
97-
s.httpServer.AddRoute(rest.Route{
98-
Method: http.MethodPost,
99-
Path: s.conf.Mcp.SseEndpoint,
100-
Handler: handler.ServeHTTP,
101-
}, rest.WithTimeout(s.conf.Mcp.MessageTimeout))
88+
s.registerRoutes(handler, s.conf.Mcp.SseEndpoint)
10289
}
10390

10491
// setupStreamableTransport configures the server to use Streamable HTTP transport (2025-03-26 spec)
@@ -109,16 +96,20 @@ func (s *mcpServerImpl) setupStreamableTransport() {
10996
return s.mcpServer
11097
}, nil)
11198

112-
// Register the message endpoint (handles both GET for SSE and POST for messages)
99+
s.registerRoutes(handler, s.conf.Mcp.MessageEndpoint)
100+
}
101+
102+
func (s *mcpServerImpl) registerRoutes(handler http.Handler, endpoint string) {
103+
// Register the endpoint (handles both GET for SSE and POST for messages)
113104
s.httpServer.AddRoute(rest.Route{
114105
Method: http.MethodGet,
115-
Path: s.conf.Mcp.MessageEndpoint,
106+
Path: endpoint,
116107
Handler: handler.ServeHTTP,
117108
}, rest.WithSSE(), rest.WithTimeout(s.conf.Mcp.SseTimeout))
118109

119110
s.httpServer.AddRoute(rest.Route{
120111
Method: http.MethodPost,
121-
Path: s.conf.Mcp.MessageEndpoint,
112+
Path: endpoint,
122113
Handler: handler.ServeHTTP,
123114
}, rest.WithTimeout(s.conf.Mcp.MessageTimeout))
124115
}

mcp/server_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,3 +372,22 @@ func TestConfig(t *testing.T) {
372372
assert.Equal(t, "/sse", c.Mcp.SseEndpoint)
373373
assert.Equal(t, "/message", c.Mcp.MessageEndpoint)
374374
}
375+
376+
type mockMcpServer struct{}
377+
378+
func (m *mockMcpServer) Start() {}
379+
func (m *mockMcpServer) Stop() {}
380+
381+
func TestAddToolWithCustomServer(t *testing.T) {
382+
server := &mockMcpServer{}
383+
// Should not panic, but log error
384+
defer func() {
385+
if r := recover(); r != nil {
386+
t.Errorf("AddTool panicked with custom server: %v", r)
387+
}
388+
}()
389+
390+
AddTool(server, &Tool{Name: "test"}, func(ctx context.Context, req *CallToolRequest, args struct{}) (*CallToolResult, any, error) {
391+
return nil, nil, nil
392+
})
393+
}

mcp/types.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55

66
sdkmcp "github.com/modelcontextprotocol/go-sdk/mcp"
7+
"github.com/zeromicro/go-zero/core/logx"
78
)
89

910
// Re-export commonly used SDK types for convenience
@@ -93,5 +94,7 @@ func AddTool[In, Out any](server McpServer, tool *Tool, handler func(context.Con
9394
// Access internal server - only works with mcpServerImpl
9495
if impl, ok := server.(*mcpServerImpl); ok {
9596
sdkmcp.AddTool(impl.mcpServer, tool, handler)
97+
} else {
98+
logx.Error("AddTool: server must be of type *mcpServerImpl to use this helper")
9699
}
97100
}

tools/goctl/go.mod

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
module github.com/zeromicro/go-zero/tools/goctl
22

3-
go 1.21
3+
go 1.23
44

55
require (
66
github.com/DATA-DOG/go-sqlmock v1.5.2
77
github.com/emicklei/proto v1.14.2
88
github.com/fatih/structtag v1.2.0
99
github.com/go-openapi/spec v0.21.1-0.20250328170532-a3928469592e
10-
github.com/go-sql-driver/mysql v1.9.0
10+
github.com/go-sql-driver/mysql v1.9.3
1111
github.com/gookit/color v1.6.0
1212
github.com/iancoleman/strcase v0.3.0
1313
github.com/spf13/cobra v1.10.2
@@ -19,7 +19,7 @@ require (
1919
github.com/zeromicro/go-zero v1.9.4
2020
golang.org/x/text v0.22.0
2121
google.golang.org/grpc v1.65.0
22-
google.golang.org/protobuf v1.36.5
22+
google.golang.org/protobuf v1.36.11
2323
gopkg.in/yaml.v2 v2.4.0
2424
)
2525

@@ -44,7 +44,7 @@ require (
4444
github.com/gogo/protobuf v1.3.2 // indirect
4545
github.com/golang/protobuf v1.5.4 // indirect
4646
github.com/google/gnostic-models v0.6.8 // indirect
47-
github.com/google/go-cmp v0.6.0 // indirect
47+
github.com/google/go-cmp v0.7.0 // indirect
4848
github.com/google/gofuzz v1.2.0 // indirect
4949
github.com/google/uuid v1.6.0 // indirect
5050
github.com/grafana/pyroscope-go v1.2.7 // indirect

tools/goctl/go.sum

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ github.com/go-openapi/spec v0.21.1-0.20250328170532-a3928469592e h1:auobAirzhPsL
5050
github.com/go-openapi/spec v0.21.1-0.20250328170532-a3928469592e/go.mod h1:NAKTe9SplQBxIUlHlsuId1jk1I7bWTVV/2q/GtdRi6g=
5151
github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
5252
github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
53-
github.com/go-sql-driver/mysql v1.9.0 h1:Y0zIbQXhQKmQgTp44Y1dp3wTXcn804QoTptLZT1vtvo=
54-
github.com/go-sql-driver/mysql v1.9.0/go.mod h1:pDetrLJeA3oMujJuvXc8RJoasr589B6A9fwzD3QMrqw=
53+
github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo=
54+
github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
5555
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
5656
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
5757
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -62,8 +62,8 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6
6262
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
6363
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
6464
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
65-
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
66-
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
65+
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
66+
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
6767
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
6868
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
6969
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -281,8 +281,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d h1:
281281
google.golang.org/genproto/googleapis/rpc v0.0.0-20240711142825-46eb208f015d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
282282
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
283283
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
284-
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
285-
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
284+
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
285+
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
286286
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
287287
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
288288
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

tools/goctl/rpc/README.md

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Goctl Rpc是`goctl`脚手架下的一个rpc服务代码生成模块,支持prot
5353
```Bash
5454
$ goctl rpc template -o=user.proto
5555
```
56-
56+
5757
```proto
5858
syntax = "proto3";
5959
@@ -72,7 +72,7 @@ service User {
7272
rpc Ping(Request) returns(Response);
7373
}
7474
```
75-
75+
7676

7777
* 生成rpc服务代码
7878

@@ -96,35 +96,60 @@ Examples:
9696
goctl rpc protoc xx.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=.
9797

9898
Flags:
99-
--branch string The branch of the remote repo, it does work with --remote
100-
-h, --help help for protoc
101-
--home string The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
102-
-m, --multiple Generated in multiple rpc service mode
103-
--remote string The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
104-
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
105-
--style string The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md] (default "gozero")
106-
-v, --verbose Enable log output
107-
--zrpc_out string The zrpc output directory
99+
--branch string The branch of the remote repo, it does work with --remote
100+
-h, --help help for protoc
101+
--home string The goctl home path of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
102+
-m, --multiple Generated in multiple rpc service mode
103+
--name-from-filename Use proto filename instead of package name for service naming (legacy behavior)
104+
--remote string The remote git repo of the template, --home and --remote cannot be set at the same time, if they are, --remote has higher priority
105+
The git repo directory must be consistent with the https://github.com/zeromicro/go-zero-template directory structure
106+
--style string The file naming format, see [https://github.com/zeromicro/go-zero/tree/master/tools/goctl/config/readme.md] (default "gozero")
107+
-v, --verbose Enable log output
108+
--zrpc_out string The zrpc output directory
108109
```
109110
110111
### 参数说明
111112
112113
* --branch 指定远程仓库模板分支
113114
* --home 指定goctl模板根目录
114115
* -m, --multiple 指定生成多个rpc服务模式, 默认为 false, 如果为 false, 则只支持生成一个rpc service, 如果为 true, 则支持生成多个 rpc service,且多个 rpc service 会分组。
116+
* --name-from-filename 使用proto文件名而非package名称来命名服务(旧版行为)。默认使用package名称,这样可以支持多个proto文件共享同一个package。
115117
* --style 指定文件输出格式
116118
* -v, --verbose 显示日志
117119
* --zrpc_out 指定zrpc输出目录
118120
119121
> ## --multiple
120122
> 是否开启多个 rpc service 生成,如果开启,则满足一下新特性
121-
> 1. 支持 1 到多个 rpc service
123+
> 1. 支持 1 到多个 rpc service
122124
> 2. 生成 rpc 服务会按照服务名称分组(尽管只有一个 rpc service)
123125
> 3. rpc client 的文件目录变更为固定名称 `client`
124-
>
126+
>
125127
> 如果不开启,则和旧版本 rpc 生成逻辑一样(兼容)
126128
> 1. 有且只能有一个 rpc service
127129
130+
> ## Service Naming (Multi-Proto File Support)
131+
>
132+
> By default, the service name is derived from the **proto package name** (e.g., `package user;` → service name `user`).
133+
> This enables splitting a large proto file into multiple smaller files that share the same package name,
134+
> which is particularly useful for AI-assisted development where smaller files are easier to process.
135+
>
136+
> **Example: Multiple proto files with same package**
137+
> ```
138+
> protos/
139+
> ├── user_base.proto # package user;
140+
> ├── user_auth.proto # package user;
141+
> └── user_profile.proto # package user;
142+
> ```
143+
> All three files will generate into a single `user` service.
144+
>
145+
> **Legacy behavior (--name-from-filename)**
146+
>
147+
> If you need the old behavior where service name is derived from the proto filename,
148+
> use the `--name-from-filename` flag:
149+
> ```bash
150+
> goctl rpc protoc user.proto --go_out=./pb --go-grpc_out=./pb --zrpc_out=. --name-from-filename
151+
> ```
152+
128153
129154
## rpc 服务生成 example
130155
详情见 [example/rpc](https://github.com/zeromicro/go-zero/tree/master/tools/goctl/example)

tools/goctl/rpc/cli/cli.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ var (
4848
VarBoolClient bool
4949
// VarStringModule describes the module name for go.mod.
5050
VarStringModule string
51+
// VarBoolNameFromFilename describes whether to derive service name from proto filename
52+
// instead of the proto package name. Default is false (uses package name).
53+
VarBoolNameFromFilename bool
5154
)
5255

5356
// RPCNew is to generate rpc greet service, this greet service can speed
@@ -94,6 +97,7 @@ func RPCNew(_ *cobra.Command, args []string) error {
9497
ctx.ProtocCmd = fmt.Sprintf("protoc -I=%s %s --go_out=%s --go-grpc_out=%s", filepath.Dir(src), filepath.Base(src), filepath.Dir(src), filepath.Dir(src))
9598
ctx.IsGenClient = VarBoolClient
9699
ctx.Module = VarStringModule
100+
ctx.NameFromFilename = VarBoolNameFromFilename
97101

98102
grpcOptList := VarStringSliceGoGRPCOpt
99103
if len(grpcOptList) > 0 {

tools/goctl/rpc/cli/zrpc.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ func ZRPC(_ *cobra.Command, args []string) error {
104104
ctx.ProtocCmd = strings.Join(protocArgs, " ")
105105
ctx.IsGenClient = VarBoolClient
106106
ctx.Module = VarStringModule
107+
ctx.NameFromFilename = VarBoolNameFromFilename
107108
g := generator.NewGenerator(style, verbose)
108109
return g.Generate(&ctx)
109110
}

tools/goctl/rpc/cmd.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ func init() {
4242
newCmdFlags.StringVar(&cli.VarStringBranch, "branch")
4343
newCmdFlags.StringVar(&cli.VarStringModule, "module")
4444
newCmdFlags.BoolVarP(&cli.VarBoolVerbose, "verbose", "v")
45+
newCmdFlags.BoolVar(&cli.VarBoolNameFromFilename, "name-from-filename")
4546
newCmdFlags.MarkHidden("go_opt")
4647
newCmdFlags.MarkHidden("go-grpc_opt")
4748
newCmdFlags.BoolVarPWithDefaultValue(&cli.VarBoolClient, "client", "c", true)
@@ -60,6 +61,7 @@ func init() {
6061
protocCmdFlags.StringVar(&cli.VarStringBranch, "branch")
6162
protocCmdFlags.StringVar(&cli.VarStringModule, "module")
6263
protocCmdFlags.BoolVarP(&cli.VarBoolVerbose, "verbose", "v")
64+
protocCmdFlags.BoolVar(&cli.VarBoolNameFromFilename, "name-from-filename")
6365
protocCmdFlags.MarkHidden("go_out")
6466
protocCmdFlags.MarkHidden("go-grpc_out")
6567
protocCmdFlags.MarkHidden("go_opt")

tools/goctl/rpc/generator/gen.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ type ZRpcContext struct {
3232
IsGenClient bool
3333
// Module is the custom module name for go.mod
3434
Module string
35+
// NameFromFilename uses proto filename instead of package name for service naming.
36+
// Default is false (uses package name, which supports multi-proto files).
37+
NameFromFilename bool
3538
}
3639

3740
// Generate generates a rpc service, through the proto file,

0 commit comments

Comments
 (0)