2
0
Эх сурвалжийг харах

chore: move mcp servers to go work (#203)

* chore: move mcp servers to go work

* chore: bump go mod

* fix: ci

* fix: ci lint

* feat: show ci auto fix diff

* fix: golang ci binary

* fix: ci

* feat: auto fix code script
zijiren 7 сар өмнө
parent
commit
1befc798e9

+ 74 - 8
.github/workflows/ci.yml

@@ -26,10 +26,10 @@ jobs:
       - name: Checkout
         uses: actions/checkout@v4
 
-      - name: Setup Golang with cache
-        uses: magnetikonline/action-golang-cache@v5
+      - name: Setup Go
+        uses: actions/setup-go@v5
         with:
-          go-version: "1.23"
+          go-version-file: "core/go.mod"
 
       - name: Go test
         working-directory: core
@@ -39,10 +39,62 @@ jobs:
       - name: Run Linter
         uses: golangci/golangci-lint-action@v6
         with:
-          version: v1.64.6
+          version: v1.64.8
           working-directory: core
           args: "--out-format colored-line-number --max-issues-per-linter 0 --max-same-issues 0 --config ./.golangci.yml"
 
+      - name: Run Fix Linter
+        uses: golangci/golangci-lint-action@v6
+        if: ${{ failure() }}
+        with:
+          install-mode: none
+          working-directory: core
+          args: "--fix --out-format colored-line-number --max-issues-per-linter 0 --max-same-issues 0 --config ./.golangci.yml"
+
+      - name: Auto Fix Diff Content
+        if: ${{ failure() }}
+        run: |
+          git diff --color=always
+          exit 1
+
+  golangci-lint-mcpservers:
+    name: Lint MCP Servers
+    runs-on: ubuntu-24.04
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+
+      - name: Setup Go
+        uses: actions/setup-go@v5
+        with:
+          go-version-file: "mcp-servers/go.mod"
+
+      - name: Go test
+        working-directory: mcp-servers
+        run: |
+          go test -v -timeout 30s -count=1 ./...
+
+      - name: Run Linter
+        uses: golangci/golangci-lint-action@v6
+        with:
+          version: v1.64.8
+          working-directory: mcp-servers
+          args: "--out-format colored-line-number --max-issues-per-linter 0 --max-same-issues 0 --config ./.golangci.yml"
+
+      - name: Run Fix Linter
+        uses: golangci/golangci-lint-action@v6
+        if: ${{ failure() }}
+        with:
+          install-mode: none
+          working-directory: mcp-servers
+          args: "--fix --out-format colored-line-number --max-issues-per-linter 0 --max-same-issues 0 --config ./.golangci.yml"
+
+      - name: Auto Fix Diff Content
+        if: ${{ failure() }}
+        run: |
+          git diff --color=always
+          exit 1
+
   golangci-lint-openapimcp:
     name: Lint OpneAPI MCP
     runs-on: ubuntu-24.04
@@ -50,14 +102,28 @@ jobs:
       - name: Checkout
         uses: actions/checkout@v4
 
-      - name: Setup Golang with cache
-        uses: magnetikonline/action-golang-cache@v5
+      - name: Setup Go
+        uses: actions/setup-go@v5
         with:
-          go-version: "1.23"
+          go-version-file: "openapi-mcp/go.mod"
 
       - name: Run Linter
         uses: golangci/golangci-lint-action@v6
         with:
-          version: v1.64.6
+          version: v1.64.8
           working-directory: openapi-mcp
           args: "--out-format colored-line-number --max-issues-per-linter 0 --max-same-issues 0 --config ./.golangci.yml"
+
+      - name: Run Fix Linter
+        uses: golangci/golangci-lint-action@v6
+        if: ${{ failure() }}
+        with:
+          install-mode: none
+          working-directory: openapi-mcp
+          args: "--fix --out-format colored-line-number --max-issues-per-linter 0 --max-same-issues 0 --config ./.golangci.yml"
+
+      - name: Auto Fix Diff Content
+        if: ${{ failure() }}
+        run: |
+          git diff --color=always
+          exit 1

+ 1 - 1
.github/workflows/release-openapi-mcp.yml

@@ -47,7 +47,7 @@ jobs:
       - name: Setup Go
         uses: actions/setup-go@v5
         with:
-          go-version: "1.23"
+          go-version-file: "openapi-mcp/go.mod"
 
       - name: Build
         working-directory: openapi-mcp

+ 1 - 1
.github/workflows/release.yml

@@ -87,7 +87,7 @@ jobs:
       - name: Setup Go
         uses: actions/setup-go@v5
         with:
-          go-version: "1.24"
+          go-version-file: "core/go.mod"
 
       - name: Generate Swagger
         working-directory: core

+ 1 - 2
core/common/mcpproxy/sse_test.go

@@ -1,7 +1,6 @@
 package mcpproxy_test
 
 import (
-	"context"
 	"fmt"
 	"net/http"
 	"net/http/httptest"
@@ -82,7 +81,7 @@ func TestProxySSEEndpoint(t *testing.T) {
 	defer proxyServer.Close()
 
 	// Make a request to the proxy
-	req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, proxyServer.URL, nil)
+	req, err := http.NewRequestWithContext(t.Context(), http.MethodGet, proxyServer.URL, nil)
 	if err != nil {
 		t.Fatalf("Error making request to proxy: %v", err)
 	}

+ 1 - 2
core/common/notify/feishu_test.go

@@ -1,7 +1,6 @@
 package notify_test
 
 import (
-	"context"
 	"os"
 	"testing"
 
@@ -14,7 +13,7 @@ func TestPostToFeiShuv2(t *testing.T) {
 		return
 	}
 	err := notify.PostToFeiShuv2(
-		context.Background(),
+		t.Context(),
 		notify.FeishuColorRed,
 		"Error",
 		"Error Message",

+ 62 - 3
core/controller/embedmcp.go

@@ -12,14 +12,14 @@ import (
 	"github.com/gin-gonic/gin"
 	"github.com/labring/aiproxy/core/common/mcpproxy"
 	statelessmcp "github.com/labring/aiproxy/core/common/stateless-mcp"
-	"github.com/labring/aiproxy/core/mcpservers"
 	"github.com/labring/aiproxy/core/middleware"
 	"github.com/labring/aiproxy/core/model"
+	mcpservers "github.com/labring/aiproxy/mcp-servers"
 	"github.com/mark3labs/mcp-go/mcp"
 	"github.com/mark3labs/mcp-go/server"
 
 	// init embed mcp
-	_ "github.com/labring/aiproxy/core/mcpservers/mcpregister"
+	_ "github.com/labring/aiproxy/mcp-servers/mcpregister"
 )
 
 type EmbedMCPConfigTemplate struct {
@@ -101,6 +101,65 @@ type SaveEmbedMCPRequest struct {
 	InitConfig map[string]string `json:"init_config"`
 }
 
+func GetEmbedConfig(ct mcpservers.ConfigTemplates, initConfig map[string]string) (*model.MCPEmbeddingConfig, error) {
+	reusingConfig := make(map[string]model.MCPEmbeddingReusingConfig)
+	embedConfig := &model.MCPEmbeddingConfig{
+		Init: initConfig,
+	}
+	for key, value := range ct {
+		switch value.Required {
+		case mcpservers.ConfigRequiredTypeInitOnly:
+			if v, ok := initConfig[key]; !ok || v == "" {
+				return nil, fmt.Errorf("config %s is required", key)
+			}
+		case mcpservers.ConfigRequiredTypeReusingOnly:
+			if _, ok := initConfig[key]; ok {
+				return nil, fmt.Errorf("config %s is provided, but it is not allowed", key)
+			}
+			reusingConfig[key] = model.MCPEmbeddingReusingConfig{
+				Name:        value.Name,
+				Description: value.Description,
+				Required:    true,
+			}
+		case mcpservers.ConfigRequiredTypeInitOrReusingOnly:
+			if v, ok := initConfig[key]; ok {
+				if v == "" {
+					return nil, fmt.Errorf("config %s is required", key)
+				}
+				continue
+			}
+			reusingConfig[key] = model.MCPEmbeddingReusingConfig{
+				Name:        value.Name,
+				Description: value.Description,
+				Required:    true,
+			}
+		}
+	}
+	embedConfig.Reusing = reusingConfig
+	return embedConfig, nil
+}
+
+func ToPublicMCP(e mcpservers.EmbedMcp, initConfig map[string]string, enabled bool) (*model.PublicMCP, error) {
+	embedConfig, err := GetEmbedConfig(e.ConfigTemplates, initConfig)
+	if err != nil {
+		return nil, err
+	}
+	pmcp := &model.PublicMCP{
+		ID:          e.ID,
+		Type:        model.PublicMCPTypeEmbed,
+		Name:        e.Name,
+		Readme:      e.Readme,
+		Tags:        e.Tags,
+		EmbedConfig: embedConfig,
+	}
+	if enabled {
+		pmcp.Status = model.PublicMCPStatusEnabled
+	} else {
+		pmcp.Status = model.PublicMCPStatusDisabled
+	}
+	return pmcp, nil
+}
+
 // SaveEmbedMCP godoc
 //
 //	@Summary		Save embed mcp
@@ -125,7 +184,7 @@ func SaveEmbedMCP(c *gin.Context) {
 		return
 	}
 
-	pmcp, err := mcpservers.ToPublicMCP(emcp, req.InitConfig, req.Enabled)
+	pmcp, err := ToPublicMCP(emcp, req.InitConfig, req.Enabled)
 	if err != nil {
 		middleware.ErrorResponse(c, http.StatusInternalServerError, err.Error())
 		return

+ 1 - 1
core/controller/publicmcp-server.go

@@ -17,9 +17,9 @@ import (
 	"github.com/labring/aiproxy/core/common"
 	"github.com/labring/aiproxy/core/common/mcpproxy"
 	statelessmcp "github.com/labring/aiproxy/core/common/stateless-mcp"
-	"github.com/labring/aiproxy/core/mcpservers"
 	"github.com/labring/aiproxy/core/middleware"
 	"github.com/labring/aiproxy/core/model"
+	mcpservers "github.com/labring/aiproxy/mcp-servers"
 	"github.com/labring/aiproxy/openapi-mcp/convert"
 	"github.com/mark3labs/mcp-go/mcp"
 	"github.com/mark3labs/mcp-go/server"

+ 13 - 10
core/go.mod

@@ -1,6 +1,6 @@
 module github.com/labring/aiproxy/core
 
-go 1.23.8
+go 1.24
 
 require (
 	cloud.google.com/go/iam v1.5.2
@@ -18,8 +18,9 @@ require (
 	github.com/jinzhu/copier v0.4.0
 	github.com/joho/godotenv v1.5.1
 	github.com/json-iterator/go v1.1.12
-	github.com/labring/aiproxy/openapi-mcp v0.0.0-20250522093230-014d7f194de3
-	github.com/mark3labs/mcp-go v0.29.0
+	github.com/labring/aiproxy/mcp-servers v0.0.0-00010101000000-000000000000
+	github.com/labring/aiproxy/openapi-mcp v0.0.0-20250527101240-aac8e89068ad
+	github.com/mark3labs/mcp-go v0.30.0
 	github.com/maruel/natural v1.1.1
 	github.com/mattn/go-isatty v0.0.20
 	github.com/patrickmn/go-cache v2.1.0+incompatible
@@ -39,8 +40,8 @@ require (
 	golang.org/x/sync v0.14.0
 	google.golang.org/api v0.234.0
 	gorm.io/driver/mysql v1.5.7
-	gorm.io/driver/postgres v1.5.11
-	gorm.io/gorm v1.26.1
+	gorm.io/driver/postgres v1.6.0
+	gorm.io/gorm v1.30.0
 )
 
 require (
@@ -104,11 +105,11 @@ require (
 	github.com/smarty/assertions v1.15.0 // indirect
 	github.com/spf13/cast v1.8.0 // indirect
 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
-	github.com/ugorji/go/codec v1.2.12 // indirect
+	github.com/ugorji/go/codec v1.2.13 // indirect
 	github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
 	go.opentelemetry.io/auto/sdk v1.1.0 // indirect
-	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
-	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
+	go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
+	go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
 	go.opentelemetry.io/otel v1.36.0 // indirect
 	go.opentelemetry.io/otel/metric v1.36.0 // indirect
 	go.opentelemetry.io/otel/trace v1.36.0 // indirect
@@ -123,13 +124,15 @@ require (
 	golang.org/x/tools v0.33.0 // indirect
 	google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect
 	google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect
-	google.golang.org/grpc v1.72.1 // indirect
+	google.golang.org/grpc v1.72.2 // indirect
 	google.golang.org/protobuf v1.36.6 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
-	modernc.org/libc v1.65.7 // indirect
+	modernc.org/libc v1.65.8 // indirect
 	modernc.org/mathutil v1.7.1 // indirect
 	modernc.org/memory v1.11.0 // indirect
 	modernc.org/sqlite v1.37.1 // indirect
 )
 
 replace github.com/labring/aiproxy/openapi-mcp => ../openapi-mcp
+
+replace github.com/labring/aiproxy/mcp-servers => ../mcp-servers

+ 20 - 20
core/go.sum

@@ -150,8 +150,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
 github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
 github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
 github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
-github.com/mark3labs/mcp-go v0.29.0 h1:sH1NBcumKskhxqYzhXfGc201D7P76TVXiT0fGVhabeI=
-github.com/mark3labs/mcp-go v0.29.0/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
+github.com/mark3labs/mcp-go v0.30.0 h1:Taz7fiefkxY/l8jz1nA90V+WdM2eoMtlvwfWforVYbo=
+github.com/mark3labs/mcp-go v0.30.0/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
 github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo=
 github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg=
 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
@@ -219,25 +219,25 @@ github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A=
 github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg=
 github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
 github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
-github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
-github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+github.com/ugorji/go/codec v1.2.13 h1:6nvAfJXxwEVFG0UdQwvobVN44a+xQAFiQajSG1Z6bU8=
+github.com/ugorji/go/codec v1.2.13/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
 github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
 go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
 go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
 go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
 go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
 go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
-go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
-go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
-go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
-go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
+go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
+go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
+go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
+go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
 go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
 go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
 golang.org/x/arch v0.17.0 h1:4O3dfLzd+lQewptAHqjewQZQDyEdejz3VwgeYwkZneU=
@@ -300,8 +300,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:
 google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34=
 google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
-google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA=
-google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
+google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8=
+google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
 google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
 google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -312,11 +312,11 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gorm.io/driver/mysql v1.5.7 h1:MndhOPYOfEp2rHKgkZIhJ16eVUIRf2HmzgoPmh7FCWo=
 gorm.io/driver/mysql v1.5.7/go.mod h1:sEtPWMiqiN1N1cMXoXmBbd8C6/l+TESwriotuRRpkDM=
-gorm.io/driver/postgres v1.5.11 h1:ubBVAfbKEUld/twyKZ0IYn9rSQh448EdelLYk9Mv314=
-gorm.io/driver/postgres v1.5.11/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI=
+gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4=
+gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo=
 gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
-gorm.io/gorm v1.26.1 h1:ghB2gUI9FkS46luZtn6DLZ0f6ooBJ5IbVej2ENFDjRw=
-gorm.io/gorm v1.26.1/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
+gorm.io/gorm v1.30.0 h1:qbT5aPv1UH8gI99OsRlvDToLxW5zR7FzS9acZDOZcgs=
+gorm.io/gorm v1.30.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
 modernc.org/cc/v4 v4.26.1 h1:+X5NtzVBn0KgsBCBe+xkDC7twLb/jNVj9FPgiwSQO3s=
 modernc.org/cc/v4 v4.26.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
 modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
@@ -325,8 +325,8 @@ modernc.org/fileutil v1.3.1 h1:8vq5fe7jdtEvoCf3Zf9Nm0Q05sH6kGx0Op2CPx1wTC8=
 modernc.org/fileutil v1.3.1/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
 modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
 modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
-modernc.org/libc v1.65.7 h1:Ia9Z4yzZtWNtUIuiPuQ7Qf7kxYrxP1/jeHZzG8bFu00=
-modernc.org/libc v1.65.7/go.mod h1:011EQibzzio/VX3ygj1qGFt5kMjP0lHb0qCW5/D/pQU=
+modernc.org/libc v1.65.8 h1:7PXRJai0TXZ8uNA3srsmYzmTyrLoHImV5QxHeni108Q=
+modernc.org/libc v1.65.8/go.mod h1:011EQibzzio/VX3ygj1qGFt5kMjP0lHb0qCW5/D/pQU=
 modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
 modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
 modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=

+ 0 - 6
core/mcpservers/mcpregister/init.go

@@ -1,6 +0,0 @@
-package mcpregister
-
-import (
-	// register embed mcp
-	_ "github.com/labring/aiproxy/core/mcpservers/aiproxy-openapi"
-)

+ 3 - 4
core/relay/adaptor/text-embeddings-inference/rerank_test.go

@@ -2,7 +2,6 @@ package textembeddingsinference_test
 
 import (
 	"bytes"
-	"context"
 	"io"
 	"net/http"
 	"testing"
@@ -31,7 +30,7 @@ func TestConvertRerankRequestSuccess(t *testing.T) {
 	require.NoError(t, err)
 
 	// Create mock HTTP request with context
-	req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, "/rerank", bytes.NewReader(jsonBody))
+	req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, "/rerank", bytes.NewReader(jsonBody))
 	require.NoError(t, err)
 	req.Header.Set("Content-Type", "application/json")
 
@@ -88,7 +87,7 @@ func TestConvertRerankRequestMissingDocuments(t *testing.T) {
 	require.NoError(t, err)
 
 	// Create mock HTTP request with context
-	req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, "/rerank", bytes.NewReader(jsonBody))
+	req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, "/rerank", bytes.NewReader(jsonBody))
 	require.NoError(t, err)
 	req.Header.Set("Content-Type", "application/json")
 
@@ -112,7 +111,7 @@ func TestConvertRerankRequestInvalidJSON(t *testing.T) {
 	invalidJSON := []byte(`{"model": "test", "documents": [`)
 
 	// Create mock HTTP request with context
-	req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, "/rerank", bytes.NewReader(invalidJSON))
+	req, err := http.NewRequestWithContext(t.Context(), http.MethodPost, "/rerank", bytes.NewReader(invalidJSON))
 	require.NoError(t, err)
 	req.Header.Set("Content-Type", "application/json")
 

+ 2 - 1
go.work

@@ -1,6 +1,7 @@
-go 1.23.8
+go 1.24
 
 use (
 	./core
+	./mcp-servers
 	./openapi-mcp
 )

+ 1 - 0
go.work.sum

@@ -89,6 +89,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I
 github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
 github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546 h1:pXY9qYc/MP5zdvqWEUH6SjNiu7VhSjuVFTFiTcphaLU=
 github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
+github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw=
 github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=

+ 78 - 0
mcp-servers/.golangci.yml

@@ -0,0 +1,78 @@
+run:
+  go: "1.23"
+  timeout: 5m
+  tests: true
+  modules-download-mode: readonly
+
+issues:
+  exclude-dirs-use-default: true
+
+linters:
+  disable-all: true
+  enable:
+    - gofmt
+    - goimports
+    - revive
+    - stylecheck
+    - gosimple
+    - misspell
+    - whitespace
+    - ineffassign
+    - typecheck
+    - errcheck
+    - govet
+    - staticcheck
+    - unused
+    - unconvert
+    - nosprintfhostport
+    - gofumpt
+    - sloglint
+    - unparam
+    - usestdlibvars
+    - usetesting
+    - gocritic
+    - asciicheck
+    - bidichk
+    - gocheckcompilerdirectives
+    - asasalint
+    - durationcheck
+    - exptostd
+    - forbidigo
+    - mirror
+    - errorlint
+    - errchkjson
+    - errname
+    - gosec
+    - sqlclosecheck
+    - rowserrcheck
+    - noctx
+    - bodyclose
+    - prealloc
+    - perfsprint
+    - unconvert
+    - gocyclo
+    - testifylint
+    - thelper
+    - testpackage
+    - tparallel
+    - goheader
+    - gomodguard
+    - musttag
+    - tagalign
+    - iface
+    - importas
+    - loggercheck
+    - canonicalheader
+    - containedctx
+    - copyloopvar
+    - intrange
+    - makezero
+    - nolintlint
+    - predeclared
+    - wastedassign
+    - ginkgolinter
+    - goprintffuncname
+    - inamedparam
+    - promlinter
+    - protogetter
+    - reassign

+ 0 - 0
core/mcpservers/README.md → mcp-servers/README.md


+ 9 - 7
core/mcpservers/aiproxy-openapi/openapi.go → mcp-servers/aiproxy-openapi/openapi.go

@@ -6,7 +6,7 @@ import (
 	"sync"
 
 	"github.com/labring/aiproxy/core/docs"
-	"github.com/labring/aiproxy/core/mcpservers"
+	mcpservers "github.com/labring/aiproxy/mcp-servers"
 	"github.com/labring/aiproxy/openapi-mcp/convert"
 	"github.com/mark3labs/mcp-go/server"
 )
@@ -63,10 +63,12 @@ func NewServer(config map[string]string, reusingConfig map[string]string) (*serv
 
 // need import in mcpregister/init.go
 func init() {
-	mcpservers.Register(mcpservers.EmbedMcp{
-		ID:              "aiproxy-openapi",
-		Name:            "AI Proxy OpenAPI",
-		NewServer:       NewServer,
-		ConfigTemplates: configTemplates,
-	})
+	mcpservers.Register(
+		mcpservers.NewEmbedMcp(
+			"aiproxy-openapi",
+			"AI Proxy OpenAPI",
+			NewServer,
+			mcpservers.WithConfigTemplates(configTemplates),
+		),
+	)
 }

+ 35 - 56
core/mcpservers/embedmcp.go → mcp-servers/embedmcp.go

@@ -4,7 +4,6 @@ import (
 	"errors"
 	"fmt"
 
-	"github.com/labring/aiproxy/core/model"
 	"github.com/mark3labs/mcp-go/server"
 )
 
@@ -96,44 +95,6 @@ func CheckConfigTemplatesValidate(ct ConfigTemplates) error {
 	return nil
 }
 
-func GetEmbedConfig(ct ConfigTemplates, initConfig map[string]string) (*model.MCPEmbeddingConfig, error) {
-	reusingConfig := make(map[string]model.MCPEmbeddingReusingConfig)
-	embedConfig := &model.MCPEmbeddingConfig{
-		Init: initConfig,
-	}
-	for key, value := range ct {
-		switch value.Required {
-		case ConfigRequiredTypeInitOnly:
-			if v, ok := initConfig[key]; !ok || v == "" {
-				return nil, fmt.Errorf("config %s is required", key)
-			}
-		case ConfigRequiredTypeReusingOnly:
-			if _, ok := initConfig[key]; ok {
-				return nil, fmt.Errorf("config %s is provided, but it is not allowed", key)
-			}
-			reusingConfig[key] = model.MCPEmbeddingReusingConfig{
-				Name:        value.Name,
-				Description: value.Description,
-				Required:    true,
-			}
-		case ConfigRequiredTypeInitOrReusingOnly:
-			if v, ok := initConfig[key]; ok {
-				if v == "" {
-					return nil, fmt.Errorf("config %s is required", key)
-				}
-				continue
-			}
-			reusingConfig[key] = model.MCPEmbeddingReusingConfig{
-				Name:        value.Name,
-				Description: value.Description,
-				Required:    true,
-			}
-		}
-	}
-	embedConfig.Reusing = reusingConfig
-	return embedConfig, nil
-}
-
 type NewServerFunc func(config map[string]string, reusingConfig map[string]string) (*server.MCPServer, error)
 
 type EmbedMcp struct {
@@ -142,26 +103,44 @@ type EmbedMcp struct {
 	Readme          string
 	Tags            []string
 	ConfigTemplates ConfigTemplates
-	NewServer       NewServerFunc
+	newServer       NewServerFunc
 }
 
-func ToPublicMCP(e EmbedMcp, initConfig map[string]string, enabled bool) (*model.PublicMCP, error) {
-	embedConfig, err := GetEmbedConfig(e.ConfigTemplates, initConfig)
-	if err != nil {
-		return nil, err
+type EmbedMcpConfig func(*EmbedMcp)
+
+func WithReadme(readme string) EmbedMcpConfig {
+	return func(e *EmbedMcp) {
+		e.Readme = readme
+	}
+}
+
+func WithTags(tags []string) EmbedMcpConfig {
+	return func(e *EmbedMcp) {
+		e.Tags = tags
+	}
+}
+
+func WithConfigTemplates(configTemplates ConfigTemplates) EmbedMcpConfig {
+	return func(e *EmbedMcp) {
+		e.ConfigTemplates = configTemplates
+	}
+}
+
+func NewEmbedMcp(id, name string, newServer NewServerFunc, opts ...EmbedMcpConfig) EmbedMcp {
+	e := EmbedMcp{
+		ID:        id,
+		Name:      name,
+		newServer: newServer,
 	}
-	pmcp := &model.PublicMCP{
-		ID:          e.ID,
-		Type:        model.PublicMCPTypeEmbed,
-		Name:        e.Name,
-		Readme:      e.Readme,
-		Tags:        e.Tags,
-		EmbedConfig: embedConfig,
+	for _, opt := range opts {
+		opt(&e)
 	}
-	if enabled {
-		pmcp.Status = model.PublicMCPStatusEnabled
-	} else {
-		pmcp.Status = model.PublicMCPStatusDisabled
+	return e
+}
+
+func (e *EmbedMcp) NewServer(config map[string]string, reusingConfig map[string]string) (*server.MCPServer, error) {
+	if err := ValidateConfigTemplatesConfig(e.ConfigTemplates, config, reusingConfig); err != nil {
+		return nil, fmt.Errorf("mcp %s config is invalid: %w", e.ID, err)
 	}
-	return pmcp, nil
+	return e.newServer(config, reusingConfig)
 }

+ 31 - 0
mcp-servers/go.mod

@@ -0,0 +1,31 @@
+module github.com/labring/aiproxy/mcp-servers
+
+go 1.24
+
+require (
+	github.com/labring/aiproxy/core v0.0.0-20250527101240-aac8e89068ad
+	github.com/labring/aiproxy/openapi-mcp v0.0.0-20250527101240-aac8e89068ad
+	github.com/mark3labs/mcp-go v0.30.0
+)
+
+require (
+	github.com/KyleBanks/depth v1.2.1 // indirect
+	github.com/getkin/kin-openapi v0.132.0 // indirect
+	github.com/go-openapi/jsonpointer v0.21.1 // indirect
+	github.com/go-openapi/jsonreference v0.21.0 // indirect
+	github.com/go-openapi/spec v0.21.0 // indirect
+	github.com/go-openapi/swag v0.23.1 // indirect
+	github.com/google/uuid v1.6.0 // indirect
+	github.com/josharian/intern v1.0.0 // indirect
+	github.com/mailru/easyjson v0.9.0 // indirect
+	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
+	github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect
+	github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
+	github.com/perimeterx/marshmallow v1.1.5 // indirect
+	github.com/spf13/cast v1.8.0 // indirect
+	github.com/swaggo/swag v1.16.4 // indirect
+	github.com/ugorji/go/codec v1.2.13 // indirect
+	github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
+	golang.org/x/tools v0.33.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+)

+ 69 - 0
mcp-servers/go.sum

@@ -0,0 +1,69 @@
+github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
+github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
+github.com/getkin/kin-openapi v0.132.0 h1:3ISeLMsQzcb5v26yeJrBcdTCEQTag36ZjaGk7MIRUwk=
+github.com/getkin/kin-openapi v0.132.0/go.mod h1:3OlG51PCYNsPByuiMB0t4fjnNlIDnaEDsjiKUV8nL58=
+github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic=
+github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk=
+github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
+github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
+github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
+github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
+github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU=
+github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0=
+github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
+github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/labring/aiproxy/core v0.0.0-20250527101240-aac8e89068ad h1:zdqBofaAILn4iovH9r4joTz1jQodcuNQ7oDNCzatEhU=
+github.com/labring/aiproxy/core v0.0.0-20250527101240-aac8e89068ad/go.mod h1:U9lCGsJdn7KQ8m1mndtDeQiVjIE50drwGz+qZvAT7Ro=
+github.com/labring/aiproxy/openapi-mcp v0.0.0-20250527101240-aac8e89068ad h1:Ai2SsuuKiggPCeg1HcbFMo0aSyd2wKb6rD/GHXsed6Y=
+github.com/labring/aiproxy/openapi-mcp v0.0.0-20250527101240-aac8e89068ad/go.mod h1:ZEVpQ9Ax+0mA8MJwAafzoNn+RWgdiCFkmxDQsDbccvI=
+github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
+github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
+github.com/mark3labs/mcp-go v0.30.0 h1:Taz7fiefkxY/l8jz1nA90V+WdM2eoMtlvwfWforVYbo=
+github.com/mark3labs/mcp-go v0.30.0/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
+github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY=
+github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw=
+github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c=
+github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
+github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
+github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
+github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
+github.com/spf13/cast v1.8.0 h1:gEN9K4b8Xws4EX0+a0reLmhq8moKn7ntRlQYgjPeCDk=
+github.com/spf13/cast v1.8.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/swaggo/swag v1.16.4 h1:clWJtd9LStiG3VeijiCfOVODP6VpHtKdQy9ELFG3s1A=
+github.com/swaggo/swag v1.16.4/go.mod h1:VBsHJRsDvfYvqoiMKnsdwhNV9LEMHgEDZcyVYX0sxPg=
+github.com/ugorji/go/codec v1.2.13 h1:6nvAfJXxwEVFG0UdQwvobVN44a+xQAFiQajSG1Z6bU8=
+github.com/ugorji/go/codec v1.2.13/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
+github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
+golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
+golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
+golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
+golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
+golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
+golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

+ 6 - 0
mcp-servers/mcpregister/init.go

@@ -0,0 +1,6 @@
+package mcpregister
+
+import (
+	// register embed mcp
+	_ "github.com/labring/aiproxy/mcp-servers/aiproxy-openapi"
+)

+ 1 - 1
core/mcpservers/register.go → mcp-servers/register.go

@@ -20,7 +20,7 @@ func Register(mcp EmbedMcp) {
 	if mcp.Name == "" {
 		panic("mcp name is required")
 	}
-	if mcp.NewServer == nil {
+	if mcp.newServer == nil {
 		panic(fmt.Sprintf("mcp %s new server is required", mcp.ID))
 	}
 	if mcp.ConfigTemplates != nil {

+ 3 - 3
openapi-mcp/go.mod

@@ -1,10 +1,10 @@
 module github.com/labring/aiproxy/openapi-mcp
 
-go 1.23.8
+go 1.24
 
 require (
 	github.com/getkin/kin-openapi v0.132.0
-	github.com/mark3labs/mcp-go v0.29.0
+	github.com/mark3labs/mcp-go v0.30.0
 )
 
 require (
@@ -21,7 +21,7 @@ require (
 	github.com/perimeterx/marshmallow v1.1.5 // indirect
 	github.com/rogpeppe/go-internal v1.14.1 // indirect
 	github.com/spf13/cast v1.8.0 // indirect
-	github.com/ugorji/go/codec v1.2.12 // indirect
+	github.com/ugorji/go/codec v1.2.13 // indirect
 	github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )

+ 4 - 4
openapi-mcp/go.sum

@@ -22,8 +22,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
 github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
-github.com/mark3labs/mcp-go v0.29.0 h1:sH1NBcumKskhxqYzhXfGc201D7P76TVXiT0fGVhabeI=
-github.com/mark3labs/mcp-go v0.29.0/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
+github.com/mark3labs/mcp-go v0.30.0 h1:Taz7fiefkxY/l8jz1nA90V+WdM2eoMtlvwfWforVYbo=
+github.com/mark3labs/mcp-go v0.30.0/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
 github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY=
@@ -40,8 +40,8 @@ github.com/spf13/cast v1.8.0 h1:gEN9K4b8Xws4EX0+a0reLmhq8moKn7ntRlQYgjPeCDk=
 github.com/spf13/cast v1.8.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
 github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
-github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
+github.com/ugorji/go/codec v1.2.13 h1:6nvAfJXxwEVFG0UdQwvobVN44a+xQAFiQajSG1Z6bU8=
+github.com/ugorji/go/codec v1.2.13/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
 github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

+ 79 - 0
scripts/golangci-lint-fix.sh

@@ -0,0 +1,79 @@
+#!/bin/bash
+
+set -e
+
+if [ ! -f "go.work" ]; then
+    echo "go.work file not found in current directory"
+    exit 1
+fi
+
+echo "Found go.work file, parsing directories..."
+
+directories=()
+in_use_block=false
+
+while IFS= read -r line; do
+    line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
+
+    if [[ -z "$line" || "$line" =~ ^// ]]; then
+        continue
+    fi
+
+    if [[ "$line" =~ ^use[[:space:]]*\( ]]; then
+        in_use_block=true
+        continue
+    fi
+
+    if [[ "$in_use_block" == true && "$line" =~ ^\) ]]; then
+        in_use_block=false
+        continue
+    fi
+
+    if [[ "$line" =~ ^use[[:space:]]+ ]]; then
+        dir=$(echo "$line" | sed 's/^use[[:space:]]*//;s/"//g')
+        directories+=("$dir")
+        continue
+    fi
+
+    if [[ "$in_use_block" == true ]]; then
+        dir=$(echo "$line" | sed 's/"//g')
+        directories+=("$dir")
+    fi
+done <go.work
+
+if [ ${#directories[@]} -eq 0 ]; then
+    echo "No directories found in go.work file"
+    exit 0
+fi
+
+echo "Found ${#directories[@]} directories to run golangci-lint --fix:"
+for dir in "${directories[@]}"; do
+    echo "  - $dir"
+done
+
+echo
+
+for dir in "${directories[@]}"; do
+    echo "Processing directory: $dir"
+
+    if [ ! -d "$dir" ]; then
+        echo "Directory '$dir' does not exist"
+        exit 1
+    fi
+
+    if [ ! -f "$dir/go.mod" ]; then
+        echo "No go.mod found in '$dir', skipping..."
+        exit 1
+    fi
+
+    if (cd "$dir" && golangci-lint run --fix --out-format colored-line-number --max-issues-per-linter 0 --max-same-issues 0 --config ./.golangci.yml); then
+        echo "Successfully fixed lint issues in '$dir'"
+    else
+        echo "Failed to fix lint issues in '$dir'"
+        exit 1
+    fi
+
+    echo
+done
+
+go work sync

+ 79 - 0
scripts/update-go-mod.sh

@@ -0,0 +1,79 @@
+#!/bin/bash
+
+set -e
+
+if [ ! -f "go.work" ]; then
+    echo "go.work file not found in current directory"
+    exit 1
+fi
+
+echo "Found go.work file, parsing directories..."
+
+directories=()
+in_use_block=false
+
+while IFS= read -r line; do
+    line=$(echo "$line" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
+
+    if [[ -z "$line" || "$line" =~ ^// ]]; then
+        continue
+    fi
+
+    if [[ "$line" =~ ^use[[:space:]]*\( ]]; then
+        in_use_block=true
+        continue
+    fi
+
+    if [[ "$in_use_block" == true && "$line" =~ ^\) ]]; then
+        in_use_block=false
+        continue
+    fi
+
+    if [[ "$line" =~ ^use[[:space:]]+ ]]; then
+        dir=$(echo "$line" | sed 's/^use[[:space:]]*//;s/"//g')
+        directories+=("$dir")
+        continue
+    fi
+
+    if [[ "$in_use_block" == true ]]; then
+        dir=$(echo "$line" | sed 's/"//g')
+        directories+=("$dir")
+    fi
+done <go.work
+
+if [ ${#directories[@]} -eq 0 ]; then
+    echo "No directories found in go.work file"
+    exit 0
+fi
+
+echo "Found ${#directories[@]} directories to update:"
+for dir in "${directories[@]}"; do
+    echo "  - $dir"
+done
+
+echo
+
+for dir in "${directories[@]}"; do
+    echo "Processing directory: $dir"
+
+    if [ ! -d "$dir" ]; then
+        echo "Directory '$dir' does not exist"
+        exit 1
+    fi
+
+    if [ ! -f "$dir/go.mod" ]; then
+        echo "No go.mod found in '$dir', skipping..."
+        exit 1
+    fi
+
+    if (cd "$dir" && go get -u); then
+        echo "Successfully updated dependencies in '$dir'"
+    else
+        echo "Failed to update dependencies in '$dir'"
+        exit 1
+    fi
+
+    echo
+done
+
+go work sync