Documentation
¶
Overview ¶
Package tools registers the eight MCP tools hearsay exposes. Each tool bakes the peer's --name into its description at registration time so auto-routing works ("Ivan reported X" → Ivan's server). The ambiguity contract on get_current_session is also spelled out in the description so a consuming Claude doesn't need an external CLAUDE.md block to behave correctly on multi-live-session peers.
Index ¶
- func Register(s *mcp.Server, ctx Context)
- type AskPeerClaudeInput
- type AskPeerClaudeOutput
- type Context
- type EffectiveBudgetOutput
- type EndPeerConversationInput
- type EndPeerConversationOutput
- type GetCurrentSessionInput
- type GetCurrentSessionOutput
- type GetPeerInfoInput
- type GetPeerInfoOutput
- type GetSessionSummaryInput
- type GetSessionSummaryOutput
- type ListPeerConversationsInput
- type ListPeerConversationsOutput
- type ListSessionsInput
- type ListSessionsOutput
- type PeerConversationSummary
- type ReadSessionInput
- type ReadSessionOutput
- type ReadSubagentInput
- type ReadSubagentOutput
- type ReadToolResultInput
- type ReadToolResultOutput
- type SearchMatch
- type SearchSessionInput
- type SearchSessionOutput
- type SendPeerMessageInput
- type SendPeerMessageOutput
- type StartPeerConversationInput
- type StartPeerConversationOutput
- type SubagentEntry
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type AskPeerClaudeInput ¶
type AskPeerClaudeInput struct {
Prompt string `json:"prompt" jsonschema:"the question or instruction to send to the peer's Claude"`
Project string `json:"project,omitempty" jsonschema:"working directory the agent's tools see (default: hearsay's cwd)"`
MaxTokens int `json:"max_tokens,omitempty"`
MaxToolCalls int `json:"max_tool_calls,omitempty"`
TimeoutSeconds int `json:"timeout_seconds,omitempty"`
}
AskPeerClaudeInput is the wire shape the calling Claude sees. All budget fields are optional and cascade through call → server defaults.
type AskPeerClaudeOutput ¶
type AskPeerClaudeOutput struct {
Body string `json:"body,omitempty"`
TurnCount int `json:"turnCount,omitempty"`
ToolCallCount int `json:"toolCallCount,omitempty"`
StopReason string `json:"stopReason,omitempty"`
ElapsedMs int64 `json:"elapsedMs,omitempty"`
ErrorSummary string `json:"errorSummary,omitempty"`
}
AskPeerClaudeOutput carries the model's response body alongside the per-call metadata.
The body lives in StructuredContent (this struct) AND in Content as a fallback. Why both: PR #14 made StructuredContent empty on the theory that consumers would fall back to Content — but Claude Code-class clients render StructuredContent when present (even `{}`), silently dropping Content. Putting the body into the structured channel makes the response visible regardless of which channel the consumer prefers.
type Context ¶
type Context struct {
PeerName string
PeerVersion string
DataDir string
LiveWindow time.Duration
Log func(tool, status string, dur time.Duration)
// Agent is non-nil only when --enable-agent was passed; nil
// keeps Phase-1 behavior (the 8 read-only tools, no ask_peer_claude).
Agent agent.Agent
}
Context bundles the settings every tool handler needs. It's built once in main.go and passed into Register.
type EffectiveBudgetOutput ¶
type EffectiveBudgetOutput struct {
MaxTokens int `json:"maxTokens"`
MaxToolCalls int `json:"maxToolCalls"`
TimeoutSeconds int64 `json:"timeoutSeconds"`
}
EffectiveBudgetOutput echoes the resolved budget back so callers know what they're inheriting before deciding to override per turn.
type EndPeerConversationInput ¶
type EndPeerConversationInput struct {
ConvID string `json:"convId"`
}
type GetCurrentSessionInput ¶
type GetCurrentSessionInput struct {
Project string `json:"project,omitempty" jsonschema:"optional project filter (same semantics as list_sessions.project)"`
}
type GetCurrentSessionOutput ¶
type GetCurrentSessionOutput struct {
Ambiguous bool `json:"ambiguous"`
Session *transcript.SessionSummary `json:"session"`
Candidates []transcript.SessionSummary `json:"candidates,omitempty"`
}
GetCurrentSessionOutput honors the ambiguity contract from the plan:
- exactly one live session: {ambiguous: false, session: <it>}
- no live session: {ambiguous: false, session: null}
- multiple live sessions: {ambiguous: true, candidates: [...]}
The calling Claude is instructed (via the tool description) to ASK the user when ambiguous=true rather than silently pick one.
type GetPeerInfoInput ¶
type GetPeerInfoInput struct{}
type GetPeerInfoOutput ¶
type GetSessionSummaryInput ¶
type GetSessionSummaryInput struct {
SessionID string `json:"sessionId"`
}
type GetSessionSummaryOutput ¶
type GetSessionSummaryOutput struct {
SessionID string `json:"sessionId"`
FirstUserMessage string `json:"firstUserMessage,omitempty"`
ToolCallCount int `json:"toolCallCount"`
UniqueToolNames []string `json:"uniqueToolNames"`
Subagents []SubagentEntry `json:"subagents"`
LastAssistantText string `json:"lastAssistantText,omitempty"`
}
type ListPeerConversationsInput ¶
type ListPeerConversationsInput struct{}
type ListPeerConversationsOutput ¶
type ListPeerConversationsOutput struct {
Conversations []PeerConversationSummary `json:"conversations"`
}
type ListSessionsInput ¶
type ListSessionsInput struct {
Project string `json:"project,omitempty" jsonschema:"short project name (substring match on the decoded cwd) or full path"`
Since string `json:"since,omitempty" jsonschema:"ISO8601 — only return sessions with lastActivityAt >= since"`
Limit int `json:"limit,omitempty" jsonschema:"max results (default 20)"`
}
ListSessionsInput is the tool argument type. Struct tags drive both the JSON schema presented to MCP clients and the jsonschema-inferred docs.
type ListSessionsOutput ¶
type ListSessionsOutput struct {
Sessions []transcript.SessionSummary `json:"sessions"`
}
type PeerConversationSummary ¶
type ReadSessionInput ¶
type ReadSessionInput struct {
SessionID string `json:"sessionId" jsonschema:"session UUID from list_sessions or get_current_session"`
FromTurn int `json:"fromTurn,omitempty" jsonschema:"inclusive start turn (default 0)"`
ToTurn int `json:"toTurn,omitempty" jsonschema:"exclusive end turn (0 means end)"`
Format string `json:"format,omitempty" jsonschema:"'full' (default) returns markdown + JSON metadata; 'json' returns metadata only"`
}
type ReadSessionOutput ¶
type ReadSessionOutput struct {
// Body holds the rendered markdown for format="full" (the default);
// it is omitted for format="json". See the AskPeerClaudeOutput
// docstring for why the body lives in StructuredContent rather than
// only in Content — Claude Code-class clients render the structured
// channel and silently drop the Content channel when both exist.
Body string `json:"body,omitempty"`
SessionID string `json:"sessionId"`
TotalTurns int `json:"totalTurns"`
RenderedTurns int `json:"renderedTurns"`
NextCursor *int `json:"nextCursor,omitempty"`
PartialLastLine bool `json:"partialLastLine"`
}
type ReadSubagentInput ¶
type ReadSubagentOutput ¶
type ReadSubagentOutput struct {
SessionID string `json:"sessionId"`
AgentID string `json:"agentId"`
AgentType string `json:"agentType,omitempty"`
Description string `json:"description,omitempty"`
TotalTurns int `json:"totalTurns"`
RenderedTurns int `json:"renderedTurns"`
NextCursor *int `json:"nextCursor,omitempty"`
PartialLastLine bool `json:"partialLastLine"`
}
type ReadToolResultInput ¶
type ReadToolResultOutput ¶
type ReadToolResultOutput struct{}
ReadToolResultOutput is intentionally empty in PR 0.
Phase 1 returned the body in a TextContent block AND a populated StructuredContent block ({source, truncated, bytes}). Some MCP consumers surfaced only the structured channel back to the calling model, which experienced as "metadata-only" reads against large sidecars. To make the body the unconditional source of truth, the metadata is now inlined as a leading line in the body text:
[source=sidecar, bytes=12345, truncated=false] <actual content...>
The other Phase-1 tools keep markdown + StructuredContent metadata — this is a targeted exception, not a deprecation of the convention.
type SearchMatch ¶
type SearchSessionInput ¶
type SearchSessionOutput ¶
type SearchSessionOutput struct {
Query string `json:"query"`
TotalMatches int `json:"totalMatches"`
Matches []SearchMatch `json:"matches"`
}
type SendPeerMessageInput ¶
type SendPeerMessageInput struct {
ConvID string `json:"convId" jsonschema:"the conversation handle returned by start_peer_conversation"`
Prompt string `json:"prompt" jsonschema:"the next user message in the conversation"`
MaxTokens int `json:"max_tokens,omitempty"`
MaxToolCalls int `json:"max_tool_calls,omitempty"`
TimeoutSeconds int `json:"timeout_seconds,omitempty"`
}
type SendPeerMessageOutput ¶
type SendPeerMessageOutput = AskPeerClaudeOutput
SendPeerMessageOutput mirrors AskPeerClaudeOutput: per-turn body + metadata in StructuredContent, body duplicated into Content as a fallback. See the AskPeerClaudeOutput doc for the rationale.
type StartPeerConversationInput ¶
type StartPeerConversationInput struct {
SystemPrompt string `json:"system_prompt,omitempty" jsonschema:"optional system prompt seeded on the conversation"`
Project string `json:"project,omitempty" jsonschema:"working directory for the agent's tools (default: hearsay's cwd)"`
MaxTokens int `json:"max_tokens,omitempty"`
MaxToolCalls int `json:"max_tool_calls,omitempty"`
TimeoutSeconds int `json:"timeout_seconds,omitempty"`
}
type StartPeerConversationOutput ¶
type StartPeerConversationOutput struct {
ConvID string `json:"convId"`
StartedAt time.Time `json:"startedAt"`
EffectiveBudget EffectiveBudgetOutput `json:"effectiveBudget"`
}