a73x

b4909168

feat(mcp): advertise channel handling protocol via init instructions

a73x   2026-04-29 09:06


diff --git a/internal/mcp/mcp.go b/internal/mcp/mcp.go
index 6ed9ce8..be6e49d 100644
--- a/internal/mcp/mcp.go
+++ b/internal/mcp/mcp.go
@@ -8,6 +8,18 @@ import (
	"sync"
)

// channelInstructions is advertised in the initialize response so Claude
// Code adds it to the session prompt. Tells Claude how to handle filewatch
// channel messages.
const channelInstructions = `Channel messages arrive when a developer writes @claude in a code comment. ` +
	`params.content is the marker text starting with "@claude". ` +
	`params.meta has file (path), line (1-indexed line number, as a string), ` +
	`and replyTo (e.g. "fw-a1b2c3d4") — the UUID already stamped into the comment as @claude[<replyTo>]. ` +
	`To handle a message: read the file at meta.file around line meta.line, ` +
	`do what the developer asked (answer in-session for questions, edit code for tasks), ` +
	`then use Edit to remove the entire @claude[<replyTo>] marker line so the file returns to a clean state. ` +
	`There is no reply tool — line removal is the ack.`

// ChannelMeta is the meta block of a notifications/claude/channel notification.
// All fields are strings: Claude Code's schema is Record<string, string> and
// silently drops non-string values.
@@ -92,6 +104,7 @@ func (s *Server) Run(ctx context.Context) error {
					"name":    "filewatch-mcp",
					"version": "0.1.0",
				},
				"instructions": channelInstructions,
			})
		default:
			s.writeError(id, -32601, "method not found")
diff --git a/internal/mcp/mcp_test.go b/internal/mcp/mcp_test.go
index bf7e027..a4e32e7 100644
--- a/internal/mcp/mcp_test.go
+++ b/internal/mcp/mcp_test.go
@@ -71,4 +71,11 @@ func TestInitializeAdvertisesChannelCapability(t *testing.T) {
	if _, has := exp["claude/channel"]; !has {
		t.Errorf("missing experimental.claude/channel capability: %#v", caps)
	}
	instructions, _ := result["instructions"].(string)
	if instructions == "" {
		t.Error("missing instructions field")
	}
	if !strings.Contains(instructions, "remove") {
		t.Errorf("instructions don't mention marker removal: %q", instructions)
	}
}