diff options
| author | Paul Buetow <paul@buetow.org> | 2026-02-11 22:43:50 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-02-11 22:43:50 +0200 |
| commit | 36d7c0b01e9e5a01f079784e4bf9f052c974c91e (patch) | |
| tree | ca6bc80c74b7b892516d1164fe1cdd005ab2cbaf /internal/mcp/server_test.go | |
| parent | d3810ca268f8db2867ae838d0655fb7a56e67252 (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.go | 29 |
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) { |
