Skip to content

Commit c40bf82

Browse files
committed
feat: enhance tool filtering with explicit allow/block modes and update configuration
1 parent a05c663 commit c40bf82

File tree

6 files changed

+63
-57
lines changed

6 files changed

+63
-57
lines changed

README.md

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ The server is configured using a JSON file. Below is an example configuration:
6565
],
6666
"env": {
6767
"GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>"
68+
},
69+
"options": {
70+
"toolFilter": {
71+
"mode": "block",
72+
"list": [
73+
"create_or_update_file"
74+
]
75+
}
6876
}
6977
},
7078
"fetch": {
@@ -77,11 +85,7 @@ The server is configured using a JSON file. Below is an example configuration:
7785
"logEnabled": false,
7886
"authTokens": [
7987
"SpecificTokens"
80-
],
81-
"toolFilter": {
82-
"mode": "block", // Must be explicitly set to "allow" or "block"
83-
"list": ["tool_name_to_block_or_allow"]
84-
}
88+
]
8589
}
8690
},
8791
"amap": {
@@ -96,14 +100,14 @@ Common options for `mcpProxy` and `mcpServers`.
96100
97101
- `panicIfInvalid`: If true, the server will panic if the client is invalid.
98102
- `logEnabled`: If true, the server will log the client's requests.
99-
- `authTokens`: A list of authentication tokens for the client. The `Authorization` header will be checked against this list.
100-
- `toolFilter`: Optional tool filtering configuration.
101-
- `mode`: Specifies the filtering mode. Must be explicitly set to "allow" or "block" if `list` is provided. If `list` is present but `mode` is missing or invalid, the filter will be ignored for this server.
103+
- `authTokens`: A list of authentication tokens for the client. The `Authorization` header will be checked against this list.
104+
- `toolFilter`: Optional tool filtering configuration. **This configuration is only effective in `mcpServers`.**
105+
- `mode`: Specifies the filtering mode. Must be explicitly set to `allow` or `block` if `list` is provided. If `list` is present but `mode` is missing or invalid, the filter will be ignored for this server.
102106
- `list`: A list of tool names to filter (either allow or block based on the `mode`).
103-
104107
> **Tip:** If you don't know the exact tool names, run the proxy once without any `toolFilter` configured. The console will log messages like `<server_name> Adding tool <tool_name>` for each successfully registered tool. You can use these logged names in your `toolFilter` list.
105108
106-
> In the new configuration, the `authTokens` of `mcpProxy` is not a global authentication token, but rather the default authentication token for `mcpProxy`. When `authTokens` is set in `mcpServers`, the value of `authTokens` in `mcpServers` will be used instead of the value in `mcpProxy`. In other words, the `authTokens` of `mcpProxy` serves as a default value and is only applied when `authTokens` is not set in `mcpServers`.
109+
> In the new configuration, the `authTokens` of `mcpProxy` is not a global authentication token, but rather the default authentication token for `mcpProxy`. When `authTokens` is set in `mcpServers`, the value of `authTokens` in `mcpServers` will be used instead of the value in `mcpProxy`. In other words, the `authTokens` of `mcpProxy` serves as a default value and is only applied when `authTokens` is not set in `mcpServers`.
110+
107111
> Other fields are the same.
108112
109113
### **`mcpProxy`**
@@ -134,7 +138,7 @@ For sse mcp servers, the `url` field is required. When the current `url` exists,
134138
For http streaming mcp servers, the `url` field is required. and `transportType` need to manually set to `streamable-http`.
135139
- `url`: The URL of the MCP client.
136140
- `headers`: The headers to send with the request to the MCP client.
137-
- `timeout`: The timeout for the request to the MCP client.
141+
- `timeout`: The timeout for the request to the MCP client.
138142
139143
140144
## Usage

client.go

Lines changed: 27 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -134,28 +134,35 @@ PingLoop:
134134

135135
func (c *Client) addToolsToServer(ctx context.Context, mcpServer *server.MCPServer) error {
136136
toolsRequest := mcp.ListToolsRequest{}
137-
filterSet := make(map[string]struct{})
138-
var filterMode string // Store the validated filter mode
139-
applyFilter := false // Whether to apply filter rules
137+
filterFunc := func(toolName string) bool {
138+
return true
139+
}
140140

141141
if c.options != nil && c.options.ToolFilter != nil && len(c.options.ToolFilter.List) > 0 {
142-
// List is provided, now validate the mode explicitly
143-
mode := strings.ToLower(c.options.ToolFilter.Mode)
144-
if mode == "allow" || mode == "block" {
145-
// Mode is valid, prepare to apply filter
146-
applyFilter = true
147-
filterMode = mode // Store the valid mode
148-
for _, toolName := range c.options.ToolFilter.List {
149-
filterSet[toolName] = struct{}{}
142+
filterSet := make(map[string]struct{})
143+
mode := ToolFilterMode(strings.ToLower(string(c.options.ToolFilter.Mode)))
144+
for _, toolName := range c.options.ToolFilter.List {
145+
filterSet[toolName] = struct{}{}
146+
}
147+
switch mode {
148+
case ToolFilterModeAllow:
149+
filterFunc = func(toolName string) bool {
150+
_, inList := filterSet[toolName]
151+
if !inList {
152+
log.Printf("<%s> Ignoring tool %s as it is not in allow list", c.name, toolName)
153+
}
154+
return inList
150155
}
151-
} else {
152-
// Mode is missing or invalid, ignore the filter configuration
153-
if c.options.ToolFilter.Mode == "" {
154-
log.Printf("<%s> WARNING: toolFilter list provided but mode is missing. Ignoring toolFilter configuration for this server. Mode must be 'allow' or 'block'.", c.name)
155-
} else {
156-
log.Printf("<%s> WARNING: Invalid toolFilter mode '%s' provided. Ignoring toolFilter configuration for this server. Mode must be 'allow' or 'block'.", c.name, c.options.ToolFilter.Mode)
156+
case ToolFilterModeBlock:
157+
filterFunc = func(toolName string) bool {
158+
_, inList := filterSet[toolName]
159+
if inList {
160+
log.Printf("<%s> Ignoring tool %s as it is in block list", c.name, toolName)
161+
}
162+
return !inList
157163
}
158-
// applyFilter remains false
164+
default:
165+
log.Printf("<%s> Unknown tool filter mode: %s, skipping tool filter", c.name, mode)
159166
}
160167
}
161168

@@ -169,37 +176,17 @@ func (c *Client) addToolsToServer(ctx context.Context, mcpServer *server.MCPServ
169176
}
170177
log.Printf("<%s> Successfully listed %d tools", c.name, len(tools.Tools))
171178
for _, tool := range tools.Tools {
172-
shouldAdd := true // Default to adding the tool
173-
174-
if applyFilter { // Only apply filter rules if applyFilter is true
175-
_, inList := filterSet[tool.Name]
176-
if filterMode == "allow" {
177-
if !inList {
178-
shouldAdd = false
179-
}
180-
} else { // filterMode == "block" (already validated)
181-
if inList {
182-
shouldAdd = false
183-
}
184-
}
185-
}
186-
187-
if shouldAdd {
179+
if filterFunc(tool.Name) {
188180
log.Printf("<%s> Adding tool %s", c.name, tool.Name)
189181
mcpServer.AddTool(tool, c.client.CallTool)
190-
} else if applyFilter { // Log skip reason only if filtering was applied and caused the skip
191-
if filterMode == "allow" {
192-
log.Printf("<%s> Skipping tool %s (not in allowlist)", c.name, tool.Name)
193-
} else { // filterMode == "block"
194-
log.Printf("<%s> Skipping blocked tool %s", c.name, tool.Name)
195-
}
196182
}
197183
}
198184
if tools.NextCursor == "" {
199185
break
200186
}
201187
toolsRequest.Params.Cursor = tools.NextCursor
202188
}
189+
203190
return nil
204191
}
205192

config.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,23 @@ func parseMCPClientConfigV1(conf *MCPClientConfigV1) (any, error) {
8282

8383
// ---- V2 ----
8484

85+
type ToolFilterMode string
86+
87+
const (
88+
ToolFilterModeAllow ToolFilterMode = "allow"
89+
ToolFilterModeBlock ToolFilterMode = "block"
90+
)
91+
8592
type ToolFilterConfig struct {
86-
Mode string `json:"mode,omitempty"` // 过滤模式 ("allow" or "block")
87-
List []string `json:"list,omitempty"` // 用于过滤的工具列表
93+
Mode ToolFilterMode `json:"mode,omitempty"`
94+
List []string `json:"list,omitempty"`
8895
}
8996

9097
type OptionsV2 struct {
9198
PanicIfInvalid optional.Field[bool] `json:"panicIfInvalid,omitempty"`
9299
LogEnabled optional.Field[bool] `json:"logEnabled,omitempty"`
93100
AuthTokens []string `json:"authTokens,omitempty"`
94-
ToolFilter *ToolFilterConfig `json:"toolFilter,omitempty"` // 工具过滤配置
101+
ToolFilter *ToolFilterConfig `json:"toolFilter,omitempty"`
95102
}
96103

97104
type MCPProxyConfigV2 struct {

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,14 @@
2121
],
2222
"env": {
2323
"GITHUB_PERSONAL_ACCESS_TOKEN": "<YOUR_TOKEN>"
24+
},
25+
"options": {
26+
"toolFilter": {
27+
"mode": "block",
28+
"list": [
29+
"create_or_update_file"
30+
]
31+
}
2432
}
2533
},
2634
"fetch": {

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ toolchain go1.23.7
77
require (
88
github.com/TBXark/confstore v0.0.3
99
github.com/TBXark/optional-go v0.0.1
10-
github.com/mark3labs/mcp-go v0.23.1
10+
github.com/mark3labs/mcp-go v0.24.1
1111
golang.org/x/sync v0.13.0
1212
)
1313

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
1414
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
1515
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
1616
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
17-
github.com/mark3labs/mcp-go v0.23.1 h1:RzTzZ5kJ+HxwnutKA4rll8N/pKV6Wh5dhCmiJUu5S9I=
18-
github.com/mark3labs/mcp-go v0.23.1/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
17+
github.com/mark3labs/mcp-go v0.24.1 h1:YV+5X/+W4oBdERLWgiA1uR7AIvenlKJaa5V4hqufI7E=
18+
github.com/mark3labs/mcp-go v0.24.1/go.mod h1:rXqOudj/djTORU/ThxYx8fqEVj/5pvTuuebQ2RC7uk4=
1919
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
2020
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2121
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=

0 commit comments

Comments
 (0)