summaryrefslogtreecommitdiff
path: root/internal/mcp/server_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-02-11 22:43:50 +0200
committerPaul Buetow <paul@buetow.org>2026-02-11 22:43:50 +0200
commit36d7c0b01e9e5a01f079784e4bf9f052c974c91e (patch)
treeca6bc80c74b7b892516d1164fe1cdd005ab2cbaf /internal/mcp/server_test.go
parentd3810ca268f8db2867ae838d0655fb7a56e67252 (diff)
feat: add MCP Tools support for prompt management
Implements tools/list and tools/call endpoints to expose prompt management operations (create, update, delete) as callable MCP tools. This enables Claude to use the meta-prompts (save_prompt, update_prompt) to actually create and modify prompts. Key changes: - Add Tool type definitions (Tool, ListToolsRequest, CallToolRequest, etc.) - Implement handleToolsList() returning 3 tools with JSON Schemas - Implement handleToolsCall() with tool wrappers for create/update/delete - Add 17 comprehensive unit tests (82.8% coverage maintained) - Update meta-prompts to reference tools instead of JSON-RPC methods - Enable listChanged notifications for immediate prompt availability - Refactor large functions into helpers to stay under 50-line limit Tools advertised alongside Prompts capability. All functions under 50 lines. Backward compatible - existing prompts/* JSON-RPC methods unchanged. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'internal/mcp/server_test.go')
-rw-r--r--internal/mcp/server_test.go29
1 files changed, 23 insertions, 6 deletions
diff --git a/internal/mcp/server_test.go b/internal/mcp/server_test.go
index 0944f35..4b43f51 100644
--- a/internal/mcp/server_test.go
+++ b/internal/mcp/server_test.go
@@ -73,23 +73,40 @@ func sendRequest(w io.Writer, req Request) error {
}
// readResponse reads a newline-delimited JSON-RPC response (MCP stdio protocol).
+// Skips notification messages (those without an ID) and returns the actual response.
func readResponse(r io.Reader) (*Response, error) {
data, err := io.ReadAll(r)
if err != nil {
return nil, err
}
- // Parse newline-delimited JSON; take the last non-empty line as the response
+ // Parse newline-delimited JSON; find the first line with an ID (skip notifications)
lines := strings.Split(strings.TrimSpace(string(data)), "\n")
if len(lines) == 0 {
return nil, fmt.Errorf("no response data")
}
- body := lines[len(lines)-1]
- var resp Response
- if err := json.Unmarshal([]byte(body), &resp); err != nil {
- return nil, fmt.Errorf("unmarshal response: %w, body: %s", err, body)
+
+ // Try to find a response (message with an ID)
+ for _, line := range lines {
+ if len(line) == 0 {
+ continue
+ }
+
+ // Quick check if this might be a response (has "id" field)
+ if !strings.Contains(line, `"id"`) {
+ continue // Skip notifications
+ }
+
+ var resp Response
+ if err := json.Unmarshal([]byte(line), &resp); err != nil {
+ continue // Not a valid response, try next line
+ }
+
+ // Valid response found
+ return &resp, nil
}
- return &resp, nil
+
+ return nil, fmt.Errorf("no response found in output (only notifications)")
}
func TestServer_Initialize(t *testing.T) {