This is an automated email from the ASF dual-hosted git repository.

alexstocks pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go-pixiu.git


The following commit(s) were added to refs/heads/develop by this push:
     new edaa3f62 Feat(MCP): Add MCP Server Filter for Model Context Protocol 
support (#702)
edaa3f62 is described below

commit edaa3f620b1089976b40f4de9640f994d9076317
Author: Zerui Yang <[email protected]>
AuthorDate: Sat Aug 16 23:30:03 2025 +0800

    Feat(MCP): Add MCP Server Filter for Model Context Protocol support (#702)
    
    * feat: Add MCP executor filter with configuration and request handling
    
    * feat: Implement MCP server filter with configuration, request handling, 
and tool registry
    
    * feat: Enhance MCP server filter with new context management and tool 
registry features
    
    * feat: Enhance MCP server filter with new context management and tool 
registry features
    
    * feat: Simplify MCP server configuration and response handling with 
optimized structures and error management
    
    * fix: fix some problems from copilot
    
    * chore: update dependencies in go.mod for MCP integration and improvements
    
    * style: add missing newlines in context and filter files
    
    * chore: update dependencies for MCP integration
    
    * chore: update dependencies for MCP integration
    
    * refactor: update MCP context to use explicit contexthttp package and 
improve method naming
    
    * refactor: delete useless method and fix mistakes about function name
---
 go.mod                               |  14 +-
 go.sum                               |  35 ++-
 pkg/common/constant/key.go           |   2 +
 pkg/filter/mcp/mcpserver/config.go   | 217 +++++++++++++
 pkg/filter/mcp/mcpserver/context.go  | 111 +++++++
 pkg/filter/mcp/mcpserver/filter.go   | 237 +++++++++++++++
 pkg/filter/mcp/mcpserver/handlers.go | 571 +++++++++++++++++++++++++++++++++++
 pkg/filter/mcp/mcpserver/plugin.go   |  50 +++
 pkg/filter/mcp/mcpserver/registry.go | 359 ++++++++++++++++++++++
 pkg/filter/mcp/mcpserver/response.go | 151 +++++++++
 pkg/pluginregistry/registry.go       |   1 +
 11 files changed, 1739 insertions(+), 9 deletions(-)

diff --git a/go.mod b/go.mod
index 2cde68b6..29b28814 100644
--- a/go.mod
+++ b/go.mod
@@ -32,13 +32,15 @@ require (
        github.com/golang/protobuf v1.5.4
        github.com/jhump/protoreflect v1.17.0
        github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible
+       github.com/lestrrat-go/jwx/v2 v2.1.6
+       github.com/mark3labs/mcp-go v0.32.0
        github.com/mitchellh/mapstructure v1.5.0
        github.com/nacos-group/nacos-sdk-go v1.1.3
        github.com/pkg/errors v0.9.1
        github.com/prometheus/client_golang v1.14.0
        github.com/prometheus/common v0.37.0
        github.com/smartystreets/goconvey v1.7.2
-       github.com/spf13/cast v1.5.0
+       github.com/spf13/cast v1.7.1
        github.com/spf13/cobra v1.5.0
        github.com/spf13/viper v1.7.1
        github.com/stretchr/testify v1.10.0
@@ -94,6 +96,7 @@ require (
        github.com/coreos/go-semver v0.3.0 // indirect
        github.com/coreos/go-systemd/v22 v22.3.2 // indirect
        github.com/davecgh/go-spew v1.1.1 // indirect
+       github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
        github.com/dlclark/regexp2 v1.7.0 // indirect
        github.com/dustin/go-humanize v1.0.1 // indirect
        github.com/eapache/go-resiliency v1.7.0 // indirect
@@ -115,7 +118,7 @@ require (
        github.com/go-playground/universal-translator v0.18.1 // indirect
        github.com/go-playground/validator/v10 v10.20.0 // indirect
        github.com/go-resty/resty/v2 v2.7.0 // indirect
-       github.com/goccy/go-json v0.10.2 // indirect
+       github.com/goccy/go-json v0.10.3 // indirect
        github.com/gogo/protobuf v1.3.2 // indirect
        github.com/golang/snappy v0.0.4 // indirect
        github.com/google/uuid v1.6.0 // indirect
@@ -148,6 +151,11 @@ require (
        github.com/klauspost/cpuid/v2 v2.2.7 // indirect
        github.com/knadh/koanf v1.5.0 // indirect
        github.com/leodido/go-urn v1.4.0 // indirect
+       github.com/lestrrat-go/blackmagic v1.0.3 // indirect
+       github.com/lestrrat-go/httpcc v1.0.1 // indirect
+       github.com/lestrrat-go/httprc v1.0.6 // indirect
+       github.com/lestrrat-go/iter v1.0.2 // indirect
+       github.com/lestrrat-go/option v1.0.1 // indirect
        github.com/lestrrat-go/strftime v1.1.1 // indirect
        github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // 
indirect
        github.com/magiconair/properties v1.8.5 // indirect
@@ -178,6 +186,7 @@ require (
        github.com/prometheus/procfs v0.8.0 // indirect
        github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // 
indirect
        github.com/robfig/cron/v3 v3.0.1 // indirect
+       github.com/segmentio/asm v1.2.0 // indirect
        github.com/shirou/gopsutil/v3 v3.22.2 // indirect
        github.com/sirupsen/logrus v1.8.1 // indirect
        github.com/smartystreets/assertions v1.2.0 // indirect
@@ -193,6 +202,7 @@ require (
        github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
        github.com/ugorji/go/codec v1.2.12 // indirect
        github.com/wasmerio/wasmer-go v1.0.3 // indirect
+       github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
        github.com/yusufpapurcu/wmi v1.2.2 // indirect
        go.etcd.io/etcd/client/pkg/v3 v3.5.7 // indirect
        go.opentelemetry.io/contrib/propagators/b3 v1.10.0 // indirect
diff --git a/go.sum b/go.sum
index b83be784..6a703ba0 100644
--- a/go.sum
+++ b/go.sum
@@ -556,6 +556,8 @@ github.com/creasty/defaults v1.5.2/go.mod 
h1:FPZ+Y0WNrbqOVw+c6av63eyHUAl6pMHZwqL
 github.com/davecgh/go-spew v1.1.0/go.mod 
h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 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/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 
h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod 
h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible 
h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
 github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod 
h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod 
h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
@@ -632,8 +634,8 @@ github.com/franela/goblin 
v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVB
 github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod 
h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
 github.com/frankban/quicktest v1.10.0/go.mod 
h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y=
 github.com/frankban/quicktest v1.11.3/go.mod 
h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
-github.com/frankban/quicktest v1.14.3 
h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
-github.com/frankban/quicktest v1.14.3/go.mod 
h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
+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/fsnotify/fsnotify v1.4.7/go.mod 
h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.4.9/go.mod 
h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/fsnotify/fsnotify v1.6.0 
h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
@@ -704,8 +706,8 @@ github.com/go-stack/stack v1.8.0/go.mod 
h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
 github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod 
h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
 github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod 
h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
 github.com/go-test/deep v1.0.2/go.mod 
h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
-github.com/goccy/go-json v0.10.2 
h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
-github.com/goccy/go-json v0.10.2/go.mod 
h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/goccy/go-json v0.10.3 
h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
+github.com/goccy/go-json v0.10.3/go.mod 
h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
 github.com/godbus/dbus/v5 v5.0.3/go.mod 
h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/godbus/dbus/v5 v5.0.4/go.mod 
h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/gogo/googleapis v1.1.0/go.mod 
h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
@@ -1035,10 +1037,22 @@ github.com/kr/text v0.2.0/go.mod 
h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/leodido/go-urn v1.2.2/go.mod 
h1:kUaIbLZWttglzwNuG0pgsh5vuV6u2YcGBYz1hIPjtOQ=
 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/lestrrat-go/blackmagic v1.0.3 
h1:94HXkVLxkZO9vJI/w2u1T0DAoprShFd13xtnSINtDWs=
+github.com/lestrrat-go/blackmagic v1.0.3/go.mod 
h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw=
 github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc 
h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
 github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod 
h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
 github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible 
h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
 github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod 
h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
+github.com/lestrrat-go/httpcc v1.0.1 
h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
+github.com/lestrrat-go/httpcc v1.0.1/go.mod 
h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
+github.com/lestrrat-go/httprc v1.0.6 
h1:qgmgIRhpvBqexMJjA/PmwSvhNk679oqD1RbovdCGW8k=
+github.com/lestrrat-go/httprc v1.0.6/go.mod 
h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
+github.com/lestrrat-go/iter v1.0.2 
h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
+github.com/lestrrat-go/iter v1.0.2/go.mod 
h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
+github.com/lestrrat-go/jwx/v2 v2.1.6 
h1:hxM1gfDILk/l5ylers6BX/Eq1m/pnxe9NBwW6lVfecA=
+github.com/lestrrat-go/jwx/v2 v2.1.6/go.mod 
h1:Y722kU5r/8mV7fYDifjug0r8FK8mZdw0K0GpJw/l8pU=
+github.com/lestrrat-go/option v1.0.1 
h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
+github.com/lestrrat-go/option v1.0.1/go.mod 
h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
 github.com/lestrrat-go/strftime v1.1.1 
h1:zgf8QCsgj27GlKBy3SU9/8MMgegZ8UCzlCyHYrUF0QU=
 github.com/lestrrat-go/strftime v1.1.1/go.mod 
h1:YDrzHJAODYQ+xxvrn5SG01uFIQAeDTzpxNVppCz7Nmw=
 github.com/lestrrat/go-envload v0.0.0-20180220120943-6ed08b54a570/go.mod 
h1:BLt8L9ld7wVsvEWQbuLrUZnCMnUmLZ+CGDzKtclrTlE=
@@ -1058,6 +1072,8 @@ github.com/mailru/easyjson 
v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
 github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod 
h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 github.com/mailru/easyjson v0.7.6 
h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
 github.com/mailru/easyjson v0.7.6/go.mod 
h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mark3labs/mcp-go v0.32.0 
h1:fgwmbfL2gbd67obg57OfV2Dnrhs1HtSdlY/i5fn7MU8=
+github.com/mark3labs/mcp-go v0.32.0/go.mod 
h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
 github.com/mattn/go-colorable v0.0.9/go.mod 
h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
 github.com/mattn/go-colorable v0.1.4/go.mod 
h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
 github.com/mattn/go-colorable v0.1.6/go.mod 
h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
@@ -1258,8 +1274,9 @@ github.com/rogpeppe/fastuuid 
v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So
 github.com/rogpeppe/fastuuid v1.2.0/go.mod 
h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 github.com/rogpeppe/go-internal v1.3.0/go.mod 
h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 github.com/rogpeppe/go-internal v1.6.1/go.mod 
h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
-github.com/rogpeppe/go-internal v1.8.0 
h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
 github.com/rogpeppe/go-internal v1.8.0/go.mod 
h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
+github.com/rogpeppe/go-internal v1.9.0 
h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
+github.com/rogpeppe/go-internal v1.9.0/go.mod 
h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 github.com/russross/blackfriday/v2 v2.0.1/go.mod 
h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/russross/blackfriday/v2 v2.1.0/go.mod 
h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/rwtodd/Go.Sed v0.0.0-20210816025313-55464686f9ef/go.mod 
h1:8AEUvGVi2uQ5b24BIhcr0GCcpd/RNAFWaN2CJFrWIIQ=
@@ -1268,6 +1285,8 @@ github.com/ryanuber/columnize v2.1.0+incompatible/go.mod 
h1:sm1tb6uqfes/u+d4ooFo
 github.com/ryanuber/go-glob v1.0.0/go.mod 
h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
 github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod 
h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod 
h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
+github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
+github.com/segmentio/asm v1.2.0/go.mod 
h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
 github.com/shirou/gopsutil v3.20.11+incompatible/go.mod 
h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
 github.com/shirou/gopsutil/v3 v3.21.6/go.mod 
h1:JfVbDpIBLVzT8oKbvMg9P3wEIMDDpVn+LwHTKj0ST88=
 github.com/shirou/gopsutil/v3 v3.22.2 
h1:wCrArWFkHYIdDxx/FSfF5RB4dpJYW6t7rcp3+zL8uks=
@@ -1299,8 +1318,8 @@ github.com/spf13/afero v1.9.2/go.mod 
h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcD
 github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
 github.com/spf13/afero v1.10.0/go.mod 
h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
 github.com/spf13/cast v1.3.0/go.mod 
h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
-github.com/spf13/cast v1.5.0/go.mod 
h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
+github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
+github.com/spf13/cast v1.7.1/go.mod 
h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/spf13/cobra v0.0.3/go.mod 
h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
 github.com/spf13/cobra v1.1.1/go.mod 
h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
 github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
@@ -1382,6 +1401,8 @@ github.com/xdg-go/scram v1.0.2/go.mod 
h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+
 github.com/xdg-go/stringprep v1.0.2/go.mod 
h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 
h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod 
h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
+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.1.25/go.mod 
h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.27/go.mod 
h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.32/go.mod 
h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
diff --git a/pkg/common/constant/key.go b/pkg/common/constant/key.go
index bc60701f..fd542610 100644
--- a/pkg/common/constant/key.go
+++ b/pkg/common/constant/key.go
@@ -57,6 +57,8 @@ const (
 
        LLMProxyFilter     = "dgp.filter.llm.proxy"
        LLMTokenizerFilter = "dgp.filter.llm.tokenizer"
+
+       MCPServerFilter = "dgp.filter.mcp.mcpserver"
 )
 
 const (
diff --git a/pkg/filter/mcp/mcpserver/config.go 
b/pkg/filter/mcp/mcpserver/config.go
new file mode 100644
index 00000000..28c97b4e
--- /dev/null
+++ b/pkg/filter/mcp/mcpserver/config.go
@@ -0,0 +1,217 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mcpserver
+
+import (
+       "regexp"
+)
+
+type (
+       // Config MCP Server Filter configuration
+       Config struct {
+               ServerInfo        ServerInfo               `yaml:"server_info" 
json:"server_info"`
+               Endpoint          string                   `yaml:"endpoint" 
json:"endpoint" default:"/mcp"`
+               Tools             []ToolConfig             
`yaml:"tools,omitempty" json:"tools,omitempty"`
+               Resources         []ResourceConfig         
`yaml:"resources,omitempty" json:"resources,omitempty"`
+               ResourceTemplates []ResourceTemplateConfig 
`yaml:"resource_templates,omitempty" json:"resource_templates,omitempty"`
+               Prompts           []PromptConfig           
`yaml:"prompts,omitempty" json:"prompts,omitempty"`
+       }
+
+       // ServerInfo server information
+       ServerInfo struct {
+               Name         string `yaml:"name" json:"name" default:"Pixiu MCP 
Server"`
+               Version      string `yaml:"version" json:"version" 
default:"1.0.0"`
+               Description  string `yaml:"description,omitempty" 
json:"description,omitempty" default:"MCP Server powered by Apache 
Dubbo-go-pixiu"`
+               Instructions string `yaml:"instructions,omitempty" 
json:"instructions,omitempty" default:"Use the provided tools to interact with 
backend services."`
+       }
+
+       // ToolConfig tool configuration
+       ToolConfig struct {
+               Name        string        `yaml:"name" json:"name"`
+               Description string        `yaml:"description" 
json:"description"`
+               Cluster     string        `yaml:"cluster" json:"cluster"`
+               Request     RequestConfig `yaml:"request" json:"request"`
+               Args        []ArgConfig   `yaml:"args,omitempty" 
json:"args,omitempty"`
+       }
+
+       // RequestConfig request configuration
+       RequestConfig struct {
+               Method  string            `yaml:"method" json:"method" 
default:"GET"`
+               Path    string            `yaml:"path" json:"path"`
+               Headers map[string]string `yaml:"headers,omitempty" 
json:"headers,omitempty"`
+               Timeout string            `yaml:"timeout,omitempty" 
json:"timeout,omitempty" default:"30s"`
+       }
+
+       // ArgConfig parameter configuration (simplified)
+       ArgConfig struct {
+               Name        string   `yaml:"name" json:"name"`
+               Type        string   `yaml:"type" json:"type" default:"string"`
+               In          string   `yaml:"in" json:"in"`
+               Description string   `yaml:"description,omitempty" 
json:"description,omitempty"`
+               Required    bool     `yaml:"required,omitempty" 
json:"required,omitempty"`
+               Default     any      `yaml:"default,omitempty" 
json:"default,omitempty"`
+               Enum        []string `yaml:"enum,omitempty" 
json:"enum,omitempty"`
+       }
+
+       // ResourceConfig resource configuration
+       ResourceConfig struct {
+               Name        string         `yaml:"name" json:"name"`
+               URI         string         `yaml:"uri" json:"uri"`
+               Description string         `yaml:"description,omitempty" 
json:"description,omitempty"`
+               MIMEType    string         `yaml:"mime_type,omitempty" 
json:"mime_type,omitempty"`
+               Source      ResourceSource `yaml:"source" json:"source"`
+       }
+
+       // ResourceSource resource source configuration (simplified)
+       ResourceSource struct {
+               Type     string `yaml:"type" json:"type"`
+               Path     string `yaml:"path,omitempty" json:"path,omitempty"`   
      // for file type
+               URL      string `yaml:"url,omitempty" json:"url,omitempty"`     
      // for url type
+               Content  string `yaml:"content,omitempty" 
json:"content,omitempty"`   // for inline type
+               Template string `yaml:"template,omitempty" 
json:"template,omitempty"` // for template type
+       }
+
+       // ResourceTemplateConfig resource template configuration
+       ResourceTemplateConfig struct {
+               Name        string                       `yaml:"name" 
json:"name"`
+               URITemplate string                       `yaml:"uri_template" 
json:"uri_template"`
+               Title       string                       
`yaml:"title,omitempty" json:"title,omitempty"`
+               Description string                       
`yaml:"description,omitempty" json:"description,omitempty"`
+               MIMEType    string                       
`yaml:"mime_type,omitempty" json:"mime_type,omitempty"`
+               Parameters  []ResourceTemplateParameter  
`yaml:"parameters,omitempty" json:"parameters,omitempty"`
+               Annotations *ResourceTemplateAnnotations 
`yaml:"annotations,omitempty" json:"annotations,omitempty"`
+       }
+
+       // ResourceTemplateParameter resource template parameter
+       ResourceTemplateParameter struct {
+               Name        string   `yaml:"name" json:"name"`
+               Type        string   `yaml:"type" json:"type" default:"string"`
+               Description string   `yaml:"description,omitempty" 
json:"description,omitempty"`
+               Required    bool     `yaml:"required,omitempty" 
json:"required,omitempty" default:"false"`
+               Enum        []string `yaml:"enum,omitempty" 
json:"enum,omitempty"`
+               Default     any      `yaml:"default,omitempty" 
json:"default,omitempty"`
+       }
+
+       // ResourceTemplateAnnotations resource template annotations
+       ResourceTemplateAnnotations struct {
+               Audience     []string `yaml:"audience,omitempty" 
json:"audience,omitempty"`
+               Priority     *float64 `yaml:"priority,omitempty" 
json:"priority,omitempty"`
+               LastModified string   `yaml:"last_modified,omitempty" 
json:"last_modified,omitempty"`
+       }
+
+       // ComputedParameter computed parameter (for internal processing, 
simplified)
+       ComputedParameter struct {
+               Name        string
+               Type        string
+               In          string
+               Description string
+               Required    bool
+               Enum        []string
+               Default     any
+       }
+)
+
+// GetAllParameters gets all parameters of the tool
+func (tc *ToolConfig) GetAllParameters() ([]ComputedParameter, error) {
+       var allParams []ComputedParameter
+
+       // 1. Automatically extract path parameters
+       pathParams := GetPathParameterNames(tc.Request.Path)
+       for _, paramName := range pathParams {
+               // Find corresponding arg configuration
+               var argConfig *ArgConfig
+               for _, arg := range tc.Args {
+                       if arg.Name == paramName && arg.In == "path" {
+                               argConfig = &arg
+                               break
+                       }
+               }
+
+               // Create computed parameter
+               computed := ComputedParameter{
+                       Name:     paramName,
+                       Type:     "string", // Default type
+                       In:       "path",
+                       Required: true, // Path parameters are always required
+               }
+
+               // Apply arg configuration
+               if argConfig != nil {
+                       computed.Type = argConfig.Type
+                       computed.Description = argConfig.Description
+                       // Simplified: removed Pattern and Format fields
+               }
+
+               allParams = append(allParams, computed)
+       }
+
+       // 2. Add non-path parameters
+       for _, arg := range tc.Args {
+               if arg.In != "path" {
+                       computed := ComputedParameter{
+                               Name:        arg.Name,
+                               Type:        arg.Type,
+                               In:          arg.In,
+                               Description: arg.Description,
+                               Required:    arg.Required,
+                               Enum:        arg.Enum,
+                               Default:     arg.Default,
+                               // Simplified: removed complex validation fields
+                       }
+                       allParams = append(allParams, computed)
+               }
+       }
+
+       return allParams, nil
+}
+
+// GetPathParameterNames gets all parameter names in the path template
+func GetPathParameterNames(pathTemplate string) []string {
+       re := regexp.MustCompile(`\{([^}]+)}`)
+       matches := re.FindAllStringSubmatch(pathTemplate, -1)
+
+       // Initialize as empty slice instead of nil
+       names := []string{}
+       for _, match := range matches {
+               names = append(names, match[1])
+       }
+
+       return names
+}
+
+// PromptConfig prompt configuration
+type PromptConfig struct {
+       Name        string                 `yaml:"name" json:"name"`
+       Title       string                 `yaml:"title,omitempty" 
json:"title,omitempty"`
+       Description string                 `yaml:"description,omitempty" 
json:"description,omitempty"`
+       Arguments   []PromptArgumentConfig `yaml:"arguments,omitempty" 
json:"arguments,omitempty"`
+       Messages    []PromptMessageConfig  `yaml:"messages" json:"messages"`
+}
+
+// PromptArgumentConfig prompt argument configuration
+type PromptArgumentConfig struct {
+       Name        string `yaml:"name" json:"name"`
+       Description string `yaml:"description,omitempty" 
json:"description,omitempty"`
+       Required    bool   `yaml:"required,omitempty" json:"required,omitempty"`
+}
+
+// PromptMessageConfig prompt message configuration
+type PromptMessageConfig struct {
+       Role    string `yaml:"role" json:"role"` // "user" or "assistant"
+       Content string `yaml:"content" json:"content"`
+}
diff --git a/pkg/filter/mcp/mcpserver/context.go 
b/pkg/filter/mcp/mcpserver/context.go
new file mode 100644
index 00000000..1404bec2
--- /dev/null
+++ b/pkg/filter/mcp/mcpserver/context.go
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mcpserver
+
+import (
+       "github.com/mark3labs/mcp-go/mcp"
+)
+
+import (
+       "github.com/apache/dubbo-go-pixiu/pkg/common/constant"
+       contexthttp "github.com/apache/dubbo-go-pixiu/pkg/context/http"
+)
+
+const MCPDataKey = "mcp_data"
+
+// MCPData stores MCP-related data
+type MCPData struct {
+       // Method stores MCP method name
+       Method string
+       // RequestID stores JSON-RPC request ID
+       RequestID any
+}
+
+// MCPContext MCP context wrapper that composes HttpContext and provides 
MCP-specific operations
+type MCPContext struct {
+       *contexthttp.HttpContext
+       mcpData *MCPData
+}
+
+// NewMCPContext creates a new MCP context
+func NewMCPContext(httpCtx *contexthttp.HttpContext) *MCPContext {
+       return &MCPContext{
+               HttpContext: httpCtx,
+               mcpData:     &MCPData{},
+       }
+}
+
+// IsMCPRequest checks if it's an MCP request (by method name)
+func (ctx *MCPContext) IsMCPRequest() bool {
+       return ctx.mcpData.Method != ""
+}
+
+// SetMCPMethod sets MCP method name
+func (ctx *MCPContext) SetMCPMethod(method string) {
+       ctx.mcpData.Method = method
+}
+
+// McpMethod gets MCP method name
+func (ctx *MCPContext) McpMethod() string {
+       return ctx.mcpData.Method
+}
+
+// SetMCPRequestID sets JSON-RPC request ID
+func (ctx *MCPContext) SetMCPRequestID(id any) {
+       ctx.mcpData.RequestID = id
+}
+
+// McpRequestID gets JSON-RPC request ID
+func (ctx *MCPContext) McpRequestID() any {
+       return ctx.mcpData.RequestID
+}
+
+// IsMCPToolCall checks if it's a tool call request (by method name)
+func (ctx *MCPContext) IsMCPToolCall() bool {
+       return ctx.mcpData.Method == string(mcp.MethodToolsCall)
+}
+
+// StoreMCPDataInParams stores MCP data in HttpContext.Params for passing 
through the filter chain
+func (ctx *MCPContext) StoreMCPDataInParams() {
+       if ctx.HttpContext.Params == nil {
+               ctx.HttpContext.Params = make(map[string]any)
+       }
+       ctx.HttpContext.Params[MCPDataKey] = ctx.mcpData
+}
+
+// LoadMCPDataFromParams loads MCP data from HttpContext.Params
+func (ctx *MCPContext) LoadMCPDataFromParams() {
+       if ctx.HttpContext.Params == nil {
+               return
+       }
+       if data, ok := ctx.HttpContext.Params[MCPDataKey].(*MCPData); ok {
+               ctx.mcpData = data
+       }
+}
+
+// NewMCPContextFromHttpContext creates MCPContext from existing HttpContext 
and tries to load stored MCP data
+func NewMCPContextFromHttpContext(httpCtx *contexthttp.HttpContext) 
*MCPContext {
+       mcpCtx := NewMCPContext(httpCtx)
+       mcpCtx.LoadMCPDataFromParams()
+       return mcpCtx
+}
+
+// ClearContentLengthHeader removes the Content-Length header to prevent 
conflicts with chunked transfer encoding.
+func (ctx *MCPContext) ClearContentLengthHeader() {
+       ctx.Writer.Header().Del(constant.HeaderKeyContentLength)
+}
diff --git a/pkg/filter/mcp/mcpserver/filter.go 
b/pkg/filter/mcp/mcpserver/filter.go
new file mode 100644
index 00000000..5392af2e
--- /dev/null
+++ b/pkg/filter/mcp/mcpserver/filter.go
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mcpserver
+
+import (
+       "encoding/json"
+       "fmt"
+       "io"
+       "net/http"
+)
+
+import (
+       "github.com/mark3labs/mcp-go/mcp"
+)
+
+import (
+       "github.com/apache/dubbo-go-pixiu/pkg/common/extension/filter"
+       contexthttp "github.com/apache/dubbo-go-pixiu/pkg/context/http"
+       "github.com/apache/dubbo-go-pixiu/pkg/logger"
+)
+
+// FilterFactory and MCPServerFilter types
+type (
+       // FilterFactory is a factory to create MCP server filters.
+       FilterFactory struct {
+               cfg      *Config
+               registry *ToolRegistry
+       }
+
+       // MCPServerFilter is a filter that handles MCP protocol.
+       MCPServerFilter struct {
+               cfg             *Config
+               registry        *ToolRegistry
+               errorHandler    *ErrorHandler
+               responseBuilder *ResponseBuilder
+       }
+)
+
+// Apply prepares the MCP server and tool registry.
+func (f *FilterFactory) Apply() error {
+       // Initialize tool registry
+       f.registry = NewToolRegistry()
+
+       // Register statically configured tools
+       for _, tool := range f.cfg.Tools {
+               if err := f.registry.RegisterTool(tool); err != nil {
+                       return fmt.Errorf("failed to register tool %s: %v", 
tool.Name, err)
+               }
+               logger.Debugf("[dubbo-go-pixiu] mcp server registered tool '%s' 
-> cluster:%s", tool.Name, tool.Cluster)
+       }
+
+       // Register statically configured resources
+       for _, resource := range f.cfg.Resources {
+               if err := f.registry.RegisterResource(resource); err != nil {
+                       return fmt.Errorf("failed to register resource %s: %v", 
resource.Name, err)
+               }
+               logger.Debugf("[dubbo-go-pixiu] mcp server registered resource 
'%s' -> uri:%s", resource.Name, resource.URI)
+       }
+
+       // Register statically configured resource templates
+       for _, template := range f.cfg.ResourceTemplates {
+               if err := f.registry.RegisterResourceTemplate(template); err != 
nil {
+                       return fmt.Errorf("failed to register resource template 
%s: %v", template.Name, err)
+               }
+               logger.Debugf("[dubbo-go-pixiu] mcp server registered template 
'%s' -> pattern:%s", template.Name, template.URITemplate)
+       }
+
+       // Register statically configured prompts
+       for _, prompt := range f.cfg.Prompts {
+               if err := f.registry.RegisterPrompt(prompt); err != nil {
+                       return fmt.Errorf("failed to register prompt %s: %v", 
prompt.Name, err)
+               }
+               logger.Debugf("[dubbo-go-pixiu] mcp server registered prompt 
'%s'", prompt.Name)
+       }
+
+       return nil
+}
+
+// Config returns the configuration struct
+func (f *FilterFactory) Config() any {
+       return f.cfg
+}
+
+// PrepareFilterChain prepares the filter chain
+func (f *FilterFactory) PrepareFilterChain(ctx *contexthttp.HttpContext, chain 
filter.FilterChain) error {
+       mcpFilter := &MCPServerFilter{
+               cfg:             f.cfg,
+               registry:        f.registry,
+               errorHandler:    NewErrorHandler(),
+               responseBuilder: NewResponseBuilder(),
+       }
+       chain.AppendDecodeFilters(mcpFilter)
+       chain.AppendEncodeFilters(mcpFilter) // Add to Encode chain
+       return nil
+}
+
+// Decode processes incoming HTTP requests for MCP protocol.
+func (f *MCPServerFilter) Decode(ctx *contexthttp.HttpContext) 
filter.FilterStatus {
+       // Check if it's an MCP request
+       if !f.isMCPRequest(ctx) {
+               return filter.Continue
+       }
+
+       // Create MCP context wrapper
+       mcpCtx := NewMCPContext(ctx)
+
+       // Read request body
+       body, err := io.ReadAll(ctx.Request.Body)
+       if err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to read 
request body: %v", err)
+               return f.errorHandler.SendInternalError(mcpCtx, nil, "failed to 
read request body")
+       }
+
+       // Parse JSON-RPC request
+       var jsonrpcReq mcp.JSONRPCRequest
+       if err := json.Unmarshal(body, &jsonrpcReq); err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to parse 
JSON-RPC request: %v", err)
+               return f.errorHandler.SendInternalError(mcpCtx, nil, "invalid 
JSON-RPC request")
+       }
+
+       logger.Infof("[dubbo-go-pixiu] mcp server received request: %s (id: 
%v)", jsonrpcReq.Method, jsonrpcReq.ID)
+
+       // Store information in MCP context
+       mcpCtx.SetMCPMethod(jsonrpcReq.Method)
+       mcpCtx.SetMCPRequestID(jsonrpcReq.ID)
+
+       // Handle terminal methods (methods that don't need forwarding to 
backend)
+       if f.isTerminalMethod(jsonrpcReq.Method) {
+               return f.handleTerminalMethod(mcpCtx, jsonrpcReq)
+       } else if jsonrpcReq.Method == string(mcp.MethodToolsCall) {
+               // Tool call will be processed in Encode stage (IsMCPToolCall() 
checks method)
+               return f.handleToolCall(mcpCtx, jsonrpcReq)
+       } else {
+               // Unknown method
+               logger.Warnf("[dubbo-go-pixiu] mcp server unsupported method: 
%s", jsonrpcReq.Method)
+               return f.errorHandler.SendMethodNotFound(mcpCtx, jsonrpcReq.ID)
+       }
+}
+
+// isTerminalMethod checks if it's a terminal method (methods that don't need 
forwarding to backend)
+func (f *MCPServerFilter) isTerminalMethod(method string) bool {
+       switch method {
+       case string(mcp.MethodInitialize), string(mcp.MethodToolsList), 
string(mcp.MethodResourcesList), string(mcp.MethodResourcesRead),
+               "resources/templates/list", string(mcp.MethodPromptsList), 
string(mcp.MethodPromptsGet),
+               "notifications/initialized", string(mcp.MethodPing):
+               return true
+       default:
+               return false
+       }
+}
+
+// handleTerminalMethod handles terminal methods
+func (f *MCPServerFilter) handleTerminalMethod(ctx *MCPContext, req 
mcp.JSONRPCRequest) filter.FilterStatus {
+       switch req.Method {
+       case string(mcp.MethodInitialize):
+               return f.handleInitialize(ctx, req)
+       case string(mcp.MethodToolsList):
+               return f.handleToolsList(ctx, req)
+       case string(mcp.MethodResourcesList):
+               return f.handleResourcesList(ctx, req)
+       case string(mcp.MethodResourcesRead):
+               return f.handleResourceRead(ctx, req)
+       case "resources/templates/list":
+               return f.handleResourceTemplatesList(ctx, req)
+       case string(mcp.MethodPromptsList):
+               return f.handlePromptsList(ctx, req)
+       case string(mcp.MethodPromptsGet):
+               return f.handlePromptsGet(ctx, req)
+       case "notifications/initialized":
+               return f.handleNotificationsInitialized(ctx, req)
+       case string(mcp.MethodPing):
+               return f.handlePing(ctx, req)
+       default:
+               logger.Warnf("[dubbo-go-pixiu] mcp server unsupported method: 
%s", req.Method)
+               return f.errorHandler.SendMethodNotFound(ctx, req.ID)
+       }
+}
+
+// Encode processes outgoing HTTP responses.
+func (f *MCPServerFilter) Encode(ctx *contexthttp.HttpContext) 
filter.FilterStatus {
+       // Create MCP context wrapper and load stored MCP data
+       mcpCtx := NewMCPContextFromHttpContext(ctx)
+
+       // Check if it's a tool call response
+       if mcpCtx.IsMCPToolCall() {
+               logger.Debugf("[dubbo-go-pixiu] mcp server processing tool call 
response: %s", ctx.Request.URL.Path)
+               return f.handleToolCallResponse(mcpCtx)
+       }
+
+       // For regular MCP requests, no special processing needed
+       if mcpCtx.IsMCPRequest() {
+               logger.Debugf("[dubbo-go-pixiu] mcp server regular MCP request, 
no special processing needed")
+       }
+
+       return filter.Continue
+}
+
+// isMCPRequest checks if it's an MCP request
+func (f *MCPServerFilter) isMCPRequest(ctx *contexthttp.HttpContext) bool {
+       return ctx.Request.URL.Path == f.cfg.Endpoint
+}
+
+// sendJSONResponse sends a JSON response
+func (f *MCPServerFilter) sendJSONResponse(ctx *MCPContext, response any) 
filter.FilterStatus {
+       responseBody, err := json.Marshal(response)
+       if err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to marshal 
response: %v", err)
+               ctx.SendLocalReply(http.StatusInternalServerError, 
[]byte("internal server error"))
+               return filter.Stop
+       }
+
+       // Get method and request ID for logging
+       method := ctx.McpMethod()
+       requestID := ctx.McpRequestID()
+
+       logger.Infof("[dubbo-go-pixiu] mcp server response sent: %s (id: %v)", 
method, requestID)
+
+       // Critical: Clear Content-Length header to prevent mismatch errors
+       ctx.ClearContentLengthHeader()
+       ctx.SendLocalReply(http.StatusOK, responseBody)
+       return filter.Stop
+}
diff --git a/pkg/filter/mcp/mcpserver/handlers.go 
b/pkg/filter/mcp/mcpserver/handlers.go
new file mode 100644
index 00000000..f468b394
--- /dev/null
+++ b/pkg/filter/mcp/mcpserver/handlers.go
@@ -0,0 +1,571 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mcpserver
+
+import (
+       "encoding/json"
+       "fmt"
+       "io"
+       "net/http"
+       "strings"
+)
+
+import (
+       "github.com/mark3labs/mcp-go/mcp"
+)
+
+import (
+       "github.com/apache/dubbo-go-pixiu/pkg/client"
+       "github.com/apache/dubbo-go-pixiu/pkg/common/constant"
+       "github.com/apache/dubbo-go-pixiu/pkg/common/extension/filter"
+       "github.com/apache/dubbo-go-pixiu/pkg/logger"
+       "github.com/apache/dubbo-go-pixiu/pkg/model"
+)
+
+const (
+       inPath  = "path"
+       inQuery = "query"
+       inBody  = "body"
+
+       typeString  = "string"
+       typeInteger = "integer"
+       typeNumber  = "number"
+       typeBoolean = "boolean"
+)
+
+// handleInitialize handles the initialize method
+func (f *MCPServerFilter) handleInitialize(ctx *MCPContext, req 
mcp.JSONRPCRequest) filter.FilterStatus {
+       // Build server capabilities using mcp-go structures
+       capabilities := mcp.ServerCapabilities{
+               Tools: &struct {
+                       ListChanged bool `json:"listChanged,omitempty"`
+               }{
+                       // TODO: Dynamic update capabilities - enable after 
Nacos integration
+                       // Currently set to false, future Nacos integration 
will support:
+                       // 1. Dynamic discovery and registration of new backend 
services
+                       // 2. Automatic generation of corresponding MCP tools
+                       // 3. Send notifications/tools/list_changed 
notifications
+                       ListChanged: false,
+               },
+               Resources: &struct {
+                       Subscribe   bool `json:"subscribe,omitempty"`
+                       ListChanged bool `json:"listChanged,omitempty"`
+               }{
+                       Subscribe:   false,
+                       ListChanged: false,
+               },
+               Prompts: &struct {
+                       ListChanged bool `json:"listChanged,omitempty"`
+               }{
+                       ListChanged: false,
+               },
+       }
+
+       // Build server info using mcp-go structures
+       serverInfo := mcp.Implementation{
+               Name:    f.cfg.ServerInfo.Name,
+               Version: f.cfg.ServerInfo.Version,
+       }
+
+       // Create initialization result using mcp-go API
+       instructions := f.cfg.ServerInfo.Instructions
+       if instructions == "" {
+               instructions = "This MCP server provides API access through 
tools, documentation through resources, and AI assistance through prompts."
+       }
+       result := mcp.NewInitializeResult(mcp.LATEST_PROTOCOL_VERSION, 
capabilities, serverInfo, instructions)
+
+       // Create JSON-RPC response
+       response := f.responseBuilder.Success(req.ID, result)
+       return f.sendJSONResponse(ctx, response)
+}
+
+// handleToolsList handles the tools/list method using mcp-go APIs
+func (f *MCPServerFilter) handleToolsList(ctx *MCPContext, req 
mcp.JSONRPCRequest) filter.FilterStatus {
+       tools := make([]mcp.Tool, 0, len(f.cfg.Tools))
+
+       // Build tools using mcp-go API for standard compliance
+       for _, toolCfg := range f.cfg.Tools {
+               // Start with basic tool options
+               toolOptions := []mcp.ToolOption{
+                       mcp.WithDescription(toolCfg.Description),
+               }
+
+               // Add parameter definitions using mcp-go APIs
+               for _, arg := range toolCfg.Args {
+                       opts := f.buildToolParameterOptions(&arg)
+                       switch arg.Type {
+                       case typeString:
+                               toolOptions = append(toolOptions, 
mcp.WithString(arg.Name, opts...))
+                       case typeInteger, typeNumber:
+                               toolOptions = append(toolOptions, 
mcp.WithNumber(arg.Name, opts...))
+                       case typeBoolean:
+                               toolOptions = append(toolOptions, 
mcp.WithBoolean(arg.Name, opts...))
+                       }
+               }
+
+               // Create tool using mcp-go API
+               tool := mcp.NewTool(toolCfg.Name, toolOptions...)
+               tools = append(tools, tool)
+       }
+
+       // Build standard MCP tools list response using mcp-go structures
+       result := mcp.NewListToolsResult(tools, "") // empty cursor for no 
pagination
+
+       response := f.responseBuilder.Success(req.ID, result)
+       return f.sendJSONResponse(ctx, response)
+}
+
+// buildToolParameterOptions builds the mcp.PropertyOption slice for a given 
tool argument
+func (f *MCPServerFilter) buildToolParameterOptions(arg *ArgConfig) 
[]mcp.PropertyOption {
+       opts := []mcp.PropertyOption{mcp.Description(arg.Description)}
+
+       if arg.Required {
+               opts = append(opts, mcp.Required())
+       }
+
+       if arg.Default != nil {
+               switch arg.Type {
+               case typeString:
+                       if defaultStr, ok := arg.Default.(string); ok {
+                               opts = append(opts, 
mcp.DefaultString(defaultStr))
+                       }
+               case typeInteger, typeNumber:
+                       switch defaultVal := arg.Default.(type) {
+                       case float64:
+                               opts = append(opts, 
mcp.DefaultNumber(defaultVal))
+                       case int:
+                               opts = append(opts, 
mcp.DefaultNumber(float64(defaultVal)))
+                       case int64:
+                               opts = append(opts, 
mcp.DefaultNumber(float64(defaultVal)))
+                       }
+               case typeBoolean:
+                       if defaultBool, ok := arg.Default.(bool); ok {
+                               opts = append(opts, 
mcp.DefaultBool(defaultBool))
+                       }
+               }
+       }
+
+       if len(arg.Enum) > 0 && arg.Type == typeString {
+               opts = append(opts, mcp.Enum(arg.Enum...))
+       }
+
+       return opts
+}
+
+// handleResourcesList handles the resources/list method
+func (f *MCPServerFilter) handleResourcesList(ctx *MCPContext, req 
mcp.JSONRPCRequest) filter.FilterStatus {
+       // Get all resources
+       mcpResources, err := f.registry.ToMCPResources()
+       if err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to get MCP 
resources: %v", err)
+               return f.errorHandler.SendInternalError(ctx, req.ID, "failed to 
get resources")
+       }
+
+       // Build resources list response using mcp-go structures
+       result := mcp.NewListResourcesResult(mcpResources, "") // empty cursor 
for no pagination
+
+       response := f.responseBuilder.Success(req.ID, result)
+       return f.sendJSONResponse(ctx, response)
+}
+
+// handlePing handles the ping method
+func (f *MCPServerFilter) handlePing(ctx *MCPContext, req mcp.JSONRPCRequest) 
filter.FilterStatus {
+       logger.Debugf("[dubbo-go-pixiu] mcp server handling ping request")
+
+       // Simple ping response
+       result := map[string]any{}
+
+       response := f.responseBuilder.Success(req.ID, result)
+       return f.sendJSONResponse(ctx, response)
+}
+
+// handleNotificationsInitialized handles notifications/initialized 
notification
+func (f *MCPServerFilter) handleNotificationsInitialized(ctx *MCPContext, req 
mcp.JSONRPCRequest) filter.FilterStatus {
+       logger.Debugf("[dubbo-go-pixiu] mcp server received initialized 
notification from client")
+
+       // Store client initialization state
+       // This notification indicates that the client has completed 
initialization
+       // and is ready to receive requests
+
+       // For notifications, we don't send a response, just return Stop
+       return filter.Stop
+}
+
+// handleResourceRead handles the resources/read method
+func (f *MCPServerFilter) handleResourceRead(ctx *MCPContext, req 
mcp.JSONRPCRequest) filter.FilterStatus {
+       logger.Debugf("[dubbo-go-pixiu] mcp server handling resources/read")
+
+       // Parse request parameters
+       paramsBytes, err := json.Marshal(req.Params)
+       if err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to marshal 
params: %v", err)
+               return f.errorHandler.SendInvalidParams(ctx, req.ID, "invalid 
parameters")
+       }
+
+       var params struct {
+               URI string `json:"uri"`
+       }
+       if err := json.Unmarshal(paramsBytes, &params); err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to parse 
resource read params: %v", err)
+               return f.errorHandler.SendInvalidParams(ctx, req.ID, "invalid 
parameters")
+       }
+
+       // Find resource (by URI)
+       resource, exists := f.registry.GetResourceByURI(params.URI)
+       if !exists {
+               logger.Warnf("[dubbo-go-pixiu] mcp server resource not found: 
%s", params.URI)
+               return f.errorHandler.SendInternalError(ctx, req.ID, 
fmt.Sprintf("resource not found: %s", params.URI))
+       }
+
+       // Build resource content response
+       // TODO: Implement actual resource content loading from source
+       content := fmt.Sprintf("Resource content for %s (source: %s)", 
resource.URI, resource.Source.Type)
+
+       result := map[string]any{
+               "contents": []map[string]any{
+                       {
+                               "uri":      resource.URI,
+                               "mimeType": resource.MIMEType,
+                               "text":     content,
+                       },
+               },
+       }
+
+       response := f.responseBuilder.Success(req.ID, result)
+       return f.sendJSONResponse(ctx, response)
+}
+
+// handleResourceTemplatesList handles the resources/templates/list method
+func (f *MCPServerFilter) handleResourceTemplatesList(ctx *MCPContext, req 
mcp.JSONRPCRequest) filter.FilterStatus {
+       // Get all resource templates (parameterized resource patterns)
+       mcpResourceTemplates, err := f.registry.ToMCPResourceTemplates()
+       if err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to get MCP 
resource templates: %v", err)
+               return f.errorHandler.SendInternalError(ctx, req.ID, "failed to 
get resource templates")
+       }
+
+       // Build resource templates list response
+       result := map[string]any{
+               "resourceTemplates": mcpResourceTemplates,
+       }
+
+       response := f.responseBuilder.Success(req.ID, result)
+       return f.sendJSONResponse(ctx, response)
+}
+
+// handlePromptsList handles the prompts/list method
+func (f *MCPServerFilter) handlePromptsList(ctx *MCPContext, req 
mcp.JSONRPCRequest) filter.FilterStatus {
+       logger.Debugf("[dubbo-go-pixiu] mcp server handling prompts/list 
request")
+
+       // Get all prompts
+       mcpPrompts, err := f.registry.ToMCPPrompts()
+       if err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to get 
prompts: %v", err)
+               return f.errorHandler.SendInternalError(ctx, req.ID, "failed to 
get prompts")
+       }
+
+       // Build prompts list response
+       result := map[string]any{
+               "prompts": mcpPrompts,
+       }
+
+       response := f.responseBuilder.Success(req.ID, result)
+       return f.sendJSONResponse(ctx, response)
+}
+
+// handlePromptsGet handles the prompts/get method
+func (f *MCPServerFilter) handlePromptsGet(ctx *MCPContext, req 
mcp.JSONRPCRequest) filter.FilterStatus {
+       logger.Debugf("[dubbo-go-pixiu] mcp server handling prompts/get 
request")
+
+       // Parse request parameters
+       paramsBytes, err := json.Marshal(req.Params)
+       if err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to marshal 
params: %v", err)
+               return f.errorHandler.SendInvalidParams(ctx, req.ID, "invalid 
parameters")
+       }
+
+       var params struct {
+               Name      string         `json:"name"`
+               Arguments map[string]any `json:"arguments,omitempty"`
+       }
+       if err := json.Unmarshal(paramsBytes, &params); err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to parse 
prompts/get params: %v", err)
+               return f.errorHandler.SendInvalidParams(ctx, req.ID, "invalid 
parameters")
+       }
+
+       // Find prompt configuration
+       promptConfig, exists := f.registry.GetPrompt(params.Name)
+       if !exists {
+               logger.Warnf("[dubbo-go-pixiu] mcp server prompt not found: 
%s", params.Name)
+               return f.errorHandler.SendInternalError(ctx, req.ID, 
fmt.Sprintf("prompt not found: %s", params.Name))
+       }
+
+       // Build prompt messages with parameter replacement
+       messages, err := f.buildPromptMessages(promptConfig, params.Arguments)
+       if err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to build 
prompt messages: %v", err)
+               return f.errorHandler.SendInternalError(ctx, req.ID, "failed to 
build prompt messages")
+       }
+
+       // Build prompts/get response
+       result := map[string]any{
+               "description": promptConfig.Description,
+               "messages":    messages,
+       }
+
+       response := f.responseBuilder.Success(req.ID, result)
+       return f.sendJSONResponse(ctx, response)
+}
+
+// buildPromptMessages builds prompt messages with parameter replacement 
support
+func (f *MCPServerFilter) buildPromptMessages(promptConfig PromptConfig, 
arguments map[string]any) ([]map[string]any, error) {
+       messages := make([]map[string]any, 0, len(promptConfig.Messages))
+
+       for _, msg := range promptConfig.Messages {
+               // Replace parameter placeholders in content
+               content := f.replacePromptArguments(msg.Content, arguments)
+
+               message := map[string]any{
+                       "role":    msg.Role,
+                       "content": content,
+               }
+               messages = append(messages, message)
+       }
+
+       return messages, nil
+}
+
+// replacePromptArguments replaces parameter placeholders in prompt content
+func (f *MCPServerFilter) replacePromptArguments(content string, arguments 
map[string]any) string {
+       if arguments == nil {
+               return content
+       }
+
+       result := content
+       for key, value := range arguments {
+               placeholder := fmt.Sprintf("{{%s}}", key)
+               replacement := fmt.Sprintf("%v", value)
+               result = strings.ReplaceAll(result, placeholder, replacement)
+       }
+
+       return result
+}
+
+// handleToolCall handles tool call requests by forwarding to backend
+func (f *MCPServerFilter) handleToolCall(ctx *MCPContext, req 
mcp.JSONRPCRequest) filter.FilterStatus {
+       // Parse tool call parameters
+       paramsBytes, err := json.Marshal(req.Params)
+       if err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to marshal 
tool call params: %v", err)
+               return f.errorHandler.SendInternalError(ctx, req.ID, "invalid 
tool call parameters")
+       }
+
+       var params struct {
+               Name      string         `json:"name"`
+               Arguments map[string]any `json:"arguments,omitempty"`
+       }
+       if err := json.Unmarshal(paramsBytes, &params); err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to parse tool 
call params: %v", err)
+               return f.errorHandler.SendInvalidParams(ctx, req.ID, "invalid 
tool call parameters")
+       }
+
+       // Find tool configuration
+       toolConfig, exists := f.registry.GetTool(params.Name)
+       if !exists {
+               logger.Warnf("[dubbo-go-pixiu] mcp server tool not found: %s", 
params.Name)
+               return f.errorHandler.SendToolCallError(ctx, req.ID, 
fmt.Sprintf("tool not found: %s", params.Name))
+       }
+
+       // Build backend request
+       err = f.buildBackendRequest(ctx, toolConfig, params.Arguments)
+       if err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to build 
backend request: %v", err)
+               return f.errorHandler.SendToolCallError(ctx, req.ID, "failed to 
build backend request")
+       }
+
+       // Set cluster information for routing
+       if ctx.Params == nil {
+               ctx.Params = make(map[string]any)
+       }
+
+       logger.Infof("[dubbo-go-pixiu] mcp server forwarding tool call: %s -> 
%s %s (cluster: %s)",
+               params.Name, toolConfig.Request.Method, ctx.Request.URL.Path, 
toolConfig.Cluster)
+
+       // Store MCP data for Encode stage processing
+       ctx.StoreMCPDataInParams()
+
+       ctx.Route = &model.RouteAction{
+               Cluster: toolConfig.Cluster,
+       }
+
+       // Continue to next filter for backend forwarding
+       return filter.Continue
+}
+
+// buildBackendRequest builds the complete backend request including path, 
body, and headers
+func (f *MCPServerFilter) buildBackendRequest(ctx *MCPContext, toolConfig 
ToolConfig, arguments map[string]any) error {
+       // Set HTTP method
+       ctx.Request.Method = toolConfig.Request.Method
+
+       // Build request path and body based on argument locations
+       path := toolConfig.Request.Path
+       bodyParams := make(map[string]any)
+       queryParams := make(map[string]string)
+
+       // Process arguments based on their location (path, query, body)
+       if arguments != nil {
+               for argName, argValue := range arguments {
+                       // Find argument configuration
+                       var argConfig *ArgConfig
+                       for _, arg := range toolConfig.Args {
+                               if arg.Name == argName {
+                                       argConfig = &arg
+                                       break
+                               }
+                       }
+
+                       if argConfig == nil {
+                               continue // Skip unknown arguments
+                       }
+
+                       switch argConfig.In {
+                       case inPath:
+                               // Replace path parameters
+                               placeholder := fmt.Sprintf("{%s}", argName)
+                               replacement := fmt.Sprintf("%v", argValue)
+                               path = strings.ReplaceAll(path, placeholder, 
replacement)
+
+                       case inQuery:
+                               // Add to query parameters
+                               queryParams[argName] = fmt.Sprintf("%v", 
argValue)
+
+                       case inBody:
+                               // Add to request body
+                               bodyParams[argName] = argValue
+                       }
+               }
+       }
+
+       // Set the request path
+       ctx.Request.URL.Path = path
+
+       // Add query parameters
+       if len(queryParams) > 0 {
+               query := ctx.Request.URL.Query()
+               for key, value := range queryParams {
+                       query.Set(key, value)
+               }
+               ctx.Request.URL.RawQuery = query.Encode()
+       }
+
+       // Build request body for POST/PUT requests
+       if len(bodyParams) > 0 && (toolConfig.Request.Method == constant.Post 
|| toolConfig.Request.Method == constant.Put) {
+               bodyJSON, err := json.Marshal(bodyParams)
+               if err != nil {
+                       return fmt.Errorf("failed to marshal request body: %v", 
err)
+               }
+
+               // Set request body
+               ctx.Request.Body = 
io.NopCloser(strings.NewReader(string(bodyJSON)))
+
+               // Set Content-Type header
+               ctx.Request.Header.Set(constant.HeaderKeyContextType, 
constant.HeaderValueApplicationJson)
+
+               logger.Debugf("[dubbo-go-pixiu] mcp server built request body: 
%s", string(bodyJSON))
+       }
+
+       return nil
+}
+
+// handleToolCallResponse handles tool call responses, wrapping backend 
responses in MCP format
+func (f *MCPServerFilter) handleToolCallResponse(ctx *MCPContext) 
filter.FilterStatus {
+       logger.Debugf("[dubbo-go-pixiu] mcp server handling tool call response")
+
+       // Extract request information
+       requestID := ctx.McpRequestID()
+       if requestID == nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server missing request ID 
for tool call response")
+               return filter.Continue
+       }
+
+       // Extract backend response
+       responseBody, statusCode, err := f.extractBackendResponse(ctx)
+       if err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to extract 
backend response: %v", err)
+               return f.errorHandler.SendToolCallError(ctx, requestID, "failed 
to process backend response")
+       }
+
+       // Process the response
+       return f.processToolCallResponse(ctx, requestID, responseBody, 
statusCode)
+}
+
+// extractBackendResponse extracts response data from the context
+func (f *MCPServerFilter) extractBackendResponse(ctx *MCPContext) ([]byte, 
int, error) {
+       if ctx.TargetResp == nil {
+               return nil, 0, fmt.Errorf("no target response available")
+       }
+
+       unaryResp, ok := ctx.TargetResp.(*client.UnaryResponse)
+       if !ok {
+               return nil, 0, fmt.Errorf("unexpected response type")
+       }
+
+       responseBody := unaryResp.Data
+       statusCode := ctx.GetStatusCode()
+
+       if len(responseBody) == 0 {
+               return nil, statusCode, fmt.Errorf("empty response body")
+       }
+
+       logger.Debugf("[dubbo-go-pixiu] mcp server backend response: status=%d, 
size=%d bytes", statusCode, len(responseBody))
+       return responseBody, statusCode, nil
+}
+
+// processToolCallResponse processes the tool call response and sends the 
result
+func (f *MCPServerFilter) processToolCallResponse(ctx *MCPContext, requestID 
any, responseBody []byte, statusCode int) filter.FilterStatus {
+       // Check for backend errors
+       if statusCode >= 400 {
+               logger.Errorf("[dubbo-go-pixiu] mcp server backend returned 
error status: %d", statusCode)
+               return f.errorHandler.SendToolCallError(ctx, requestID, 
fmt.Sprintf("backend error: %d", statusCode))
+       }
+
+       // Build successful response using ToolCallSuccess method
+       content := strings.TrimSpace(string(responseBody))
+       mcpResponse := f.responseBuilder.ToolCallSuccess(requestID, content)
+       return f.sendMCPResponse(ctx, mcpResponse)
+}
+
+// sendMCPResponse sends an MCP response and updates the target response
+func (f *MCPServerFilter) sendMCPResponse(ctx *MCPContext, response 
mcp.JSONRPCResponse) filter.FilterStatus {
+       mcpResponseBody, err := json.Marshal(response)
+       if err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to marshal 
MCP response: %v", err)
+               return filter.Continue
+       }
+
+       // Override TargetResp to ensure MCP format response is sent
+       ctx.TargetResp = &client.UnaryResponse{Data: mcpResponseBody}
+       ctx.StatusCode(http.StatusOK)
+       ctx.AddHeader(constant.HeaderKeyContextType, 
constant.HeaderValueApplicationJson)
+
+       // Critical: Clear Content-Length header to prevent mismatch errors
+       ctx.ClearContentLengthHeader()
+
+       logger.Debugf("[dubbo-go-pixiu] mcp server successfully wrapped backend 
response in MCP format")
+       return filter.Continue
+}
diff --git a/pkg/filter/mcp/mcpserver/plugin.go 
b/pkg/filter/mcp/mcpserver/plugin.go
new file mode 100644
index 00000000..bfef12bc
--- /dev/null
+++ b/pkg/filter/mcp/mcpserver/plugin.go
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mcpserver
+
+import (
+       "github.com/apache/dubbo-go-pixiu/pkg/common/constant"
+       "github.com/apache/dubbo-go-pixiu/pkg/common/extension/filter"
+)
+
+const (
+       // Kind is the type identifier for MCP Server Filter
+       Kind = constant.MCPServerFilter
+)
+
+func init() {
+       filter.RegisterHttpFilter(&Plugin{})
+}
+
+// Plugin implements filter.HttpFilterPlugin interface
+type Plugin struct{}
+
+// Kind returns the plugin type
+func (p *Plugin) Kind() string {
+       return Kind
+}
+
+// CreateFilterFactory creates FilterFactory
+func (p *Plugin) CreateFilterFactory() (filter.HttpFilterFactory, error) {
+       return &FilterFactory{cfg: &Config{}}, nil
+}
+
+// Config returns the configuration struct
+func (p *Plugin) Config() any {
+       return &Config{}
+}
diff --git a/pkg/filter/mcp/mcpserver/registry.go 
b/pkg/filter/mcp/mcpserver/registry.go
new file mode 100644
index 00000000..6d3e0b79
--- /dev/null
+++ b/pkg/filter/mcp/mcpserver/registry.go
@@ -0,0 +1,359 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mcpserver
+
+import (
+       "fmt"
+       "sync"
+)
+
+import (
+       "github.com/mark3labs/mcp-go/mcp"
+)
+
+import (
+       "github.com/apache/dubbo-go-pixiu/pkg/logger"
+)
+
+// ToolRegistry tool registry, thread-safe (optimized with single indexing)
+type ToolRegistry struct {
+       mu                sync.RWMutex
+       tools             map[string]ToolConfig
+       resources         map[string]ResourceConfig         // indexed by URI
+       resourceTemplates map[string]ResourceTemplateConfig // indexed by name
+       prompts           map[string]PromptConfig
+
+       // TODO: Dynamic update support - add when integrating with Nacos
+       // changeListeners   []ChangeListener              // change listeners
+       // nacosClient      nacos.ConfigClient            // Nacos config client
+       // serviceDiscovery nacos.NamingClient            // Nacos service 
discovery client
+}
+
+// NewToolRegistry creates a new tool registry
+func NewToolRegistry() *ToolRegistry {
+       return &ToolRegistry{
+               tools:             make(map[string]ToolConfig),
+               resources:         make(map[string]ResourceConfig),
+               resourceTemplates: make(map[string]ResourceTemplateConfig),
+               prompts:           make(map[string]PromptConfig),
+       }
+}
+
+// RegisterTool registers a tool
+func (r *ToolRegistry) RegisterTool(tool ToolConfig) error {
+       r.mu.Lock()
+       defer r.mu.Unlock()
+
+       if _, exists := r.tools[tool.Name]; exists {
+               return fmt.Errorf("tool %s already exists", tool.Name)
+       }
+
+       r.tools[tool.Name] = tool
+
+       // TODO: Dynamic update notification - enable when integrating with 
Nacos
+       // r.notifyToolsListChanged()
+
+       return nil
+}
+
+// RegisterResource registers a resource (indexed by URI as per MCP 
specification)
+func (r *ToolRegistry) RegisterResource(resource ResourceConfig) error {
+       r.mu.Lock()
+       defer r.mu.Unlock()
+
+       if _, exists := r.resources[resource.URI]; exists {
+               return fmt.Errorf("resource with URI %s already exists", 
resource.URI)
+       }
+
+       // Register resource by URI as per MCP specification
+       r.resources[resource.URI] = resource
+       return nil
+}
+
+// GetTool gets tool configuration
+func (r *ToolRegistry) GetTool(name string) (ToolConfig, bool) {
+       r.mu.RLock()
+       defer r.mu.RUnlock()
+
+       tool, exists := r.tools[name]
+       return tool, exists
+}
+
+// GetResourceByURI gets resource configuration (by URI, O(1) lookup)
+func (r *ToolRegistry) GetResourceByURI(uri string) (ResourceConfig, bool) {
+       r.mu.RLock()
+       defer r.mu.RUnlock()
+
+       // Direct O(1) lookup by URI
+       resource, exists := r.resources[uri]
+       return resource, exists
+}
+
+// RegisterResourceTemplate registers a resource template
+func (r *ToolRegistry) RegisterResourceTemplate(template 
ResourceTemplateConfig) error {
+       r.mu.Lock()
+       defer r.mu.Unlock()
+
+       if _, exists := r.resourceTemplates[template.Name]; exists {
+               return fmt.Errorf("resource template %s already exists", 
template.Name)
+       }
+
+       r.resourceTemplates[template.Name] = template
+       return nil
+}
+
+// GetResourceTemplate gets resource template configuration
+func (r *ToolRegistry) GetResourceTemplate(name string) 
(ResourceTemplateConfig, bool) {
+       r.mu.RLock()
+       defer r.mu.RUnlock()
+
+       template, exists := r.resourceTemplates[name]
+       return template, exists
+}
+
+// ListResourceTemplates lists all resource templates
+func (r *ToolRegistry) ListResourceTemplates() []ResourceTemplateConfig {
+       r.mu.RLock()
+       defer r.mu.RUnlock()
+
+       templates := make([]ResourceTemplateConfig, 0, len(r.resourceTemplates))
+       for _, template := range r.resourceTemplates {
+               templates = append(templates, template)
+       }
+       return templates
+}
+
+// ListTools lists all tools
+func (r *ToolRegistry) ListTools() []ToolConfig {
+       r.mu.RLock()
+       defer r.mu.RUnlock()
+
+       tools := make([]ToolConfig, 0, len(r.tools))
+       for _, tool := range r.tools {
+               tools = append(tools, tool)
+       }
+       return tools
+}
+
+// ListResources lists all resources
+func (r *ToolRegistry) ListResources() []ResourceConfig {
+       r.mu.RLock()
+       defer r.mu.RUnlock()
+
+       resources := make([]ResourceConfig, 0, len(r.resources))
+       for _, resource := range r.resources {
+               resources = append(resources, resource)
+       }
+       return resources
+}
+
+// ToMCPTools converts tool configurations to tool list
+func (r *ToolRegistry) ToMCPTools() ([]map[string]any, error) {
+       tools := r.ListTools()
+       mcpTools := make([]map[string]any, 0, len(tools))
+
+       for _, tool := range tools {
+               // Build tool according to MCP protocol specification
+               mcpTool := map[string]any{
+                       "name":        tool.Name,
+                       "description": tool.Description,
+                       "inputSchema": r.convertToInputSchema(tool),
+               }
+               mcpTools = append(mcpTools, mcpTool)
+       }
+
+       return mcpTools, nil
+}
+
+// convertToInputSchema converts tool parameters to MCP inputSchema format
+func (r *ToolRegistry) convertToInputSchema(tool ToolConfig) map[string]any {
+       allParams, err := tool.GetAllParameters()
+       if err != nil {
+               logger.Errorf("failed to get parameters for tool %s: %v", 
tool.Name, err)
+               return map[string]any{
+                       "type":       "object",
+                       "properties": map[string]any{},
+               }
+       }
+
+       properties := make(map[string]any)
+       required := make([]string, 0)
+
+       for _, param := range allParams {
+               propSchema := map[string]any{
+                       "type":        param.Type,
+                       "description": param.Description,
+               }
+
+               if len(param.Enum) > 0 {
+                       propSchema["enum"] = param.Enum
+               }
+
+               if param.Default != nil {
+                       propSchema["default"] = param.Default
+               }
+
+               properties[param.Name] = propSchema
+
+               if param.Required {
+                       required = append(required, param.Name)
+               }
+       }
+
+       schema := map[string]any{
+               "type":       "object",
+               "properties": properties,
+       }
+
+       if len(required) > 0 {
+               schema["required"] = required
+       }
+
+       return schema
+}
+
+// ToMCPResources converts resource configurations to MCP resource list using 
mcp-go structures
+func (r *ToolRegistry) ToMCPResources() ([]mcp.Resource, error) {
+       resources := r.ListResources()
+       mcpResources := make([]mcp.Resource, 0, len(resources))
+
+       for _, resource := range resources {
+               // Use mcp-go Resource structure
+               mcpResource := mcp.Resource{
+                       URI:         resource.URI,
+                       Name:        resource.Name,
+                       Description: resource.Description,
+                       MIMEType:    resource.MIMEType,
+               }
+               mcpResources = append(mcpResources, mcpResource)
+       }
+
+       return mcpResources, nil
+}
+
+// ToMCPResourceTemplates converts resource template configurations to MCP 
resource template list
+func (r *ToolRegistry) ToMCPResourceTemplates() ([]map[string]any, error) {
+       templates := r.ListResourceTemplates()
+       mcpTemplates := make([]map[string]any, 0, len(templates))
+
+       for _, template := range templates {
+               mcpTemplate := map[string]any{
+                       "uriTemplate": template.URITemplate,
+                       "name":        template.Name,
+                       "description": template.Description,
+                       "mimeType":    template.MIMEType,
+               }
+
+               // Add optional fields
+               if template.Title != "" {
+                       mcpTemplate["title"] = template.Title
+               }
+
+               // Add annotations
+               if template.Annotations != nil {
+                       annotations := make(map[string]any)
+                       if len(template.Annotations.Audience) > 0 {
+                               annotations["audience"] = 
template.Annotations.Audience
+                       }
+                       if template.Annotations.Priority != nil {
+                               annotations["priority"] = 
*template.Annotations.Priority
+                       }
+                       if template.Annotations.LastModified != "" {
+                               annotations["lastModified"] = 
template.Annotations.LastModified
+                       }
+                       if len(annotations) > 0 {
+                               mcpTemplate["annotations"] = annotations
+                       }
+               }
+
+               mcpTemplates = append(mcpTemplates, mcpTemplate)
+       }
+
+       return mcpTemplates, nil
+}
+
+// RegisterPrompt registers a prompt
+func (r *ToolRegistry) RegisterPrompt(prompt PromptConfig) error {
+       r.mu.Lock()
+       defer r.mu.Unlock()
+
+       if _, exists := r.prompts[prompt.Name]; exists {
+               return fmt.Errorf("prompt %s already exists", prompt.Name)
+       }
+
+       r.prompts[prompt.Name] = prompt
+       return nil
+}
+
+// GetPrompt gets a prompt
+func (r *ToolRegistry) GetPrompt(name string) (PromptConfig, bool) {
+       r.mu.RLock()
+       defer r.mu.RUnlock()
+
+       prompt, exists := r.prompts[name]
+       return prompt, exists
+}
+
+// ListPrompts lists all prompts
+func (r *ToolRegistry) ListPrompts() []PromptConfig {
+       r.mu.RLock()
+       defer r.mu.RUnlock()
+
+       prompts := make([]PromptConfig, 0, len(r.prompts))
+       for _, prompt := range r.prompts {
+               prompts = append(prompts, prompt)
+       }
+
+       return prompts
+}
+
+// ToMCPPrompts converts prompt configurations to MCP prompt list
+func (r *ToolRegistry) ToMCPPrompts() ([]map[string]any, error) {
+       prompts := r.ListPrompts()
+       mcpPrompts := make([]map[string]any, 0, len(prompts))
+
+       for _, prompt := range prompts {
+               mcpPrompt := map[string]any{
+                       "name":        prompt.Name,
+                       "description": prompt.Description,
+               }
+
+               if prompt.Title != "" {
+                       mcpPrompt["title"] = prompt.Title
+               }
+
+               if len(prompt.Arguments) > 0 {
+                       args := make([]map[string]any, 0, len(prompt.Arguments))
+                       for _, arg := range prompt.Arguments {
+                               argMap := map[string]any{
+                                       "name":        arg.Name,
+                                       "description": arg.Description,
+                                       "required":    arg.Required,
+                               }
+                               args = append(args, argMap)
+                       }
+                       mcpPrompt["arguments"] = args
+               }
+
+               mcpPrompts = append(mcpPrompts, mcpPrompt)
+       }
+
+       return mcpPrompts, nil
+}
+
+// TODO: Dynamic update functionality - implement when integrating with Nacos
diff --git a/pkg/filter/mcp/mcpserver/response.go 
b/pkg/filter/mcp/mcpserver/response.go
new file mode 100644
index 00000000..429976b0
--- /dev/null
+++ b/pkg/filter/mcp/mcpserver/response.go
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package mcpserver
+
+import (
+       "encoding/json"
+       "fmt"
+       "net/http"
+       "sync"
+)
+
+import (
+       "github.com/mark3labs/mcp-go/mcp"
+)
+
+import (
+       "github.com/apache/dubbo-go-pixiu/pkg/common/extension/filter"
+       "github.com/apache/dubbo-go-pixiu/pkg/logger"
+)
+
+// ResponseBuilder provides methods to create standardized MCP responses
+type ResponseBuilder struct{}
+
+var (
+       responseBuilderInstance *ResponseBuilder
+       responseBuilderOnce     sync.Once
+)
+
+// NewResponseBuilder returns the singleton ResponseBuilder instance
+func NewResponseBuilder() *ResponseBuilder {
+       responseBuilderOnce.Do(func() {
+               responseBuilderInstance = &ResponseBuilder{}
+       })
+       return responseBuilderInstance
+}
+
+// Success creates a successful JSON-RPC response
+func (rb *ResponseBuilder) Success(id any, result any) mcp.JSONRPCResponse {
+       return mcp.JSONRPCResponse{
+               JSONRPC: mcp.JSONRPC_VERSION,
+               ID:      mcp.NewRequestId(id),
+               Result:  result,
+       }
+}
+
+// Error creates an error JSON-RPC response
+func (rb *ResponseBuilder) Error(id any, code int, message string) 
mcp.JSONRPCError {
+       return mcp.NewJSONRPCError(mcp.NewRequestId(id), code, message, nil)
+}
+
+// ToolCallSuccess creates a successful tool call response
+func (rb *ResponseBuilder) ToolCallSuccess(id any, content string) 
mcp.JSONRPCResponse {
+       // Use mcp-go API to create text content
+       textContent := mcp.NewTextContent(content)
+
+       // Build MCP tool call result using mcp-go structures
+       result := mcp.CallToolResult{
+               Content: []mcp.Content{textContent},
+               IsError: false,
+       }
+
+       return rb.Success(id, result)
+}
+
+// ToolCallError creates an error tool call response
+func (rb *ResponseBuilder) ToolCallError(id any, message string) 
mcp.JSONRPCResponse {
+       errorText := fmt.Sprintf("Error: %s", message)
+       textContent := mcp.NewTextContent(errorText)
+
+       // Build MCP tool call error result using mcp-go structures
+       result := mcp.CallToolResult{
+               Content: []mcp.Content{textContent},
+               IsError: true,
+       }
+
+       return rb.Success(id, result)
+}
+
+// ErrorHandler provides centralized error handling for MCP responses
+type ErrorHandler struct {
+       responseBuilder *ResponseBuilder
+}
+
+var (
+       errorHandlerInstance *ErrorHandler
+       errorHandlerOnce     sync.Once
+)
+
+// NewErrorHandler returns the singleton ErrorHandler instance
+func NewErrorHandler() *ErrorHandler {
+       errorHandlerOnce.Do(func() {
+               errorHandlerInstance = &ErrorHandler{
+                       responseBuilder: NewResponseBuilder(),
+               }
+       })
+       return errorHandlerInstance
+}
+
+// SendInternalError sends an internal server error response
+func (eh *ErrorHandler) SendInternalError(ctx *MCPContext, id any, message 
string) filter.FilterStatus {
+       response := eh.responseBuilder.Error(id, mcp.INTERNAL_ERROR, message)
+       return eh.sendResponse(ctx, response)
+}
+
+// SendMethodNotFound sends a method not found error response
+func (eh *ErrorHandler) SendMethodNotFound(ctx *MCPContext, id any) 
filter.FilterStatus {
+       response := eh.responseBuilder.Error(id, mcp.METHOD_NOT_FOUND, "Method 
not found")
+       return eh.sendResponse(ctx, response)
+}
+
+// SendInvalidParams sends an invalid parameters error response
+func (eh *ErrorHandler) SendInvalidParams(ctx *MCPContext, id any, message 
string) filter.FilterStatus {
+       response := eh.responseBuilder.Error(id, mcp.INVALID_PARAMS, 
fmt.Sprintf("Invalid params: %s", message))
+       return eh.sendResponse(ctx, response)
+}
+
+// SendToolCallError sends a tool call error response
+func (eh *ErrorHandler) SendToolCallError(ctx *MCPContext, id any, message 
string) filter.FilterStatus {
+       response := eh.responseBuilder.ToolCallError(id, message)
+       return eh.sendResponse(ctx, response)
+}
+
+// sendResponse sends any response and handles Content-Length cleanup
+func (eh *ErrorHandler) sendResponse(ctx *MCPContext, response any) 
filter.FilterStatus {
+       responseBody, err := json.Marshal(response)
+       if err != nil {
+               logger.Errorf("[dubbo-go-pixiu] mcp server failed to marshal 
response: %v", err)
+               ctx.SendLocalReply(http.StatusInternalServerError, 
[]byte("internal server error"))
+               return filter.Stop
+       }
+
+       // Critical: Clear Content-Length header to prevent mismatch errors
+       ctx.ClearContentLengthHeader()
+       ctx.SendLocalReply(http.StatusOK, responseBody)
+       return filter.Stop
+}
diff --git a/pkg/pluginregistry/registry.go b/pkg/pluginregistry/registry.go
index fd32183a..775c1b97 100644
--- a/pkg/pluginregistry/registry.go
+++ b/pkg/pluginregistry/registry.go
@@ -46,6 +46,7 @@ import (
        _ 
"github.com/apache/dubbo-go-pixiu/pkg/filter/http/remote/resolver/dubboresolver"
        _ "github.com/apache/dubbo-go-pixiu/pkg/filter/llm/proxy"
        _ "github.com/apache/dubbo-go-pixiu/pkg/filter/llm/tokenizer"
+       _ "github.com/apache/dubbo-go-pixiu/pkg/filter/mcp/mcpserver"
        _ "github.com/apache/dubbo-go-pixiu/pkg/filter/metric"
        _ "github.com/apache/dubbo-go-pixiu/pkg/filter/network/dubboproxy"
        _ 
"github.com/apache/dubbo-go-pixiu/pkg/filter/network/dubboproxy/filter/http"

Reply via email to