Conversation
…toml Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
|
@copilot for registerToolsFromBackend don't change the implementation. instead change the documentation |
There was a problem hiding this comment.
Pull request overview
This PR aligns runtime behavior and documentation/examples around tool exposure and Docker/TOML configuration by enforcing the per-server tools allow-list at registration time and clarifying that TOML configs do not perform ${VAR} expansion.
Changes:
- Enforce
ServerConfig.Toolsas a runtime allow-list when registering backend tools (empty/nil continues to mean “allow all”). - Add test coverage for the tools filter behavior (allow-listed, no filter, and no matches).
- Fix/clarify example TOML configs to avoid broken
${PWD}mounts and misleading${VAR_NAME}notes.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| internal/server/unified.go | Filters backend tool registrations using serverCfg.Tools allow-list. |
| internal/server/register_tools_from_backend_test.go | Adds new tests + a mock backend for tools-filter enforcement. |
| config.example.toml | Replaces ${PWD} mount with absolute-path placeholder; clarifies ${VAR} expansion limitations in TOML. |
Comments suppressed due to low confidence (2)
internal/server/register_tools_from_backend_test.go:884
- Same as above: without a dummy
Headersentry,NewHTTPConnectionwill attempt streamable/SSE transports before plain JSON-RPC. Adding a header here keeps this test deterministic and avoids potential transport-handshake timeouts against the minimal mock server.
cfg := &config.Config{
Servers: map[string]*config.ServerConfig{
"nofilter-backend": {
Type: "http",
URL: backend.URL,
Tools: nil, // no filter — all tools should be exposed
},
},
}
internal/server/register_tools_from_backend_test.go:918
- Same issue here: consider adding a dummy
Headersmap entry to force the plain JSON-RPC transport path in tests (avoids streamable/SSE attempts against thishttptestserver).
cfg := &config.Config{
Servers: map[string]*config.ServerConfig{
"nomatch-backend": {
Type: "http",
URL: backend.URL,
Tools: []string{"nonexistent_tool"},
},
},
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
internal/server/unified.go
Outdated
| filteredTools := make([]struct { | ||
| Name string `json:"name"` | ||
| Description string `json:"description"` | ||
| InputSchema map[string]interface{} `json:"inputSchema"` | ||
| }, 0, len(listResult.Tools)) |
| cfg := &config.Config{ | ||
| Servers: map[string]*config.ServerConfig{ | ||
| "filter-backend": { | ||
| Type: "http", | ||
| URL: backend.URL, | ||
| Tools: []string{"read_file"}, // only allow read_file | ||
| }, | ||
| }, | ||
| } |
| return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||
| var req map[string]interface{} | ||
| if err := json.NewDecoder(r.Body).Decode(&req); err != nil { | ||
| w.WriteHeader(http.StatusBadRequest) | ||
| return | ||
| } | ||
| method, _ := req["method"].(string) | ||
| switch method { | ||
| case "initialize": | ||
| json.NewEncoder(w).Encode(map[string]interface{}{ | ||
| "jsonrpc": "2.0", | ||
| "id": req["id"], | ||
| "result": map[string]interface{}{ | ||
| "protocolVersion": "2024-11-05", | ||
| "capabilities": map[string]interface{}{}, | ||
| "serverInfo": map[string]interface{}{"name": "test", "version": "1.0.0"}, | ||
| }, | ||
| }) | ||
| case "tools/list": | ||
| json.NewEncoder(w).Encode(map[string]interface{}{ | ||
| "jsonrpc": "2.0", | ||
| "id": req["id"], | ||
| "result": map[string]interface{}{ | ||
| "tools": []map[string]interface{}{ | ||
| {"name": "read_file", "description": "Read a file", "inputSchema": map[string]interface{}{"type": "object"}}, | ||
| {"name": "write_file", "description": "Write a file", "inputSchema": map[string]interface{}{"type": "object"}}, | ||
| }, | ||
| }, | ||
| }) | ||
| } | ||
| })) |
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Done. Reverted the implementation change and updated Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
Three discrepancies between docs/examples and actual runtime behaviour, found by the nightly reconciliation check.
config.example.tomlExample 4: broken${PWD}volume mountTOML configs have no variable expansion —
${PWD}was passed verbatim to Docker, silently producing a broken volume mount. Replaced with an absolute path placeholder and added an explanatoryNOTEcomment.Misleading
${VAR_NAME}note in Docker Best PracticesThe notes section implied
${VAR}syntax works in TOML. Clarified it applies to JSON stdin format only; TOML configs require literal absolute paths.toolsfield behaviour clarified in documentationdocs/CONFIGURATION.mdpreviously stated thetoolsfield controlled which tools were exposed, implying non-listed tools would be filtered out. In practice,registerToolsFromBackenddoes not read this field — all backend tools are always registered. The documentation now explicitly states the field is stored but not currently enforced at runtime.💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.