mcp

package
v0.3.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 31, 2026 License: Apache-2.0 Imports: 29 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// EnvToken grants read and mutate.
	EnvToken = "CANARY_MCP_TOKEN" //nolint:gosec // env var NAME, not a credential value
	// EnvReadToken grants read only.
	EnvReadToken = "CANARY_MCP_READ_TOKEN" //nolint:gosec // env var NAME, not a credential value
)

Environment variables that configure MCP authentication. Their VALUES are never logged, echoed in an error, or written to a response body: an error message that names the expected token is the same leak as printing it.

View Source
const DefaultDBPath = ".canary/canary.db"

DefaultDBPath is the index every Canary command defaults to, relative to the server root.

Variables

This section is empty.

Functions

func New

func New(version string) *cobra.Command

New returns the MCP subcommand for Canary.

version is the binary's version (ldflags), reported to clients as the server implementation version. It used to be the string "1.0.0", which meant every build in the field identified itself identically.

func NewServer added in v0.3.3

func NewServer(version string, deps Deps) *mcp.Server

NewServer builds the MCP server with every registered tool bound to deps.

func RenderDocs added in v0.3.3

func RenderDocs() string

RenderDocs returns docs/MCP_TOOLS.md, generated from Registry.

The file on disk is asserted to equal this string, so the documentation cannot describe a tool set the server does not have.

Types

type BugCreateParams

type BugCreateParams struct {
	Title       string `json:"title" jsonschema:"description:Bug title,required"`
	Aspect      string `` /* 144-byte string literal not displayed */
	Severity    string `json:"severity,omitempty" jsonschema:"description:Severity level (S1 S2 S3 S4)"`
	Priority    string `json:"priority,omitempty" jsonschema:"description:Priority level (P0 P1 P2 P3)"`
	File        string `json:"file,omitempty" jsonschema:"description:File the bug lives in relative to the server root, optionally with :line"`
	Owner       string `json:"owner,omitempty" jsonschema:"description:Bug owner/assignee"`
	Description string `json:"description,omitempty" jsonschema:"description:Detailed description, recorded on the token"`
}

BugCreateParams defines parameters for the bug create tool

type BugCreateResult

type BugCreateResult struct {
	// Token is the CANARY comment to paste into the source file. The row is
	// rebuilt from source on the next `canary index`, so the comment is what
	// makes the bug survive a re-index.
	Token    string `json:"token"`
	BugID    string `json:"bugId"`
	Title    string `json:"title"`
	Aspect   string `json:"aspect"`
	Severity string `json:"severity"`
	Priority string `json:"priority"`
	FilePath string `json:"filePath"`
	Line     int    `json:"line"`
}

BugCreateResult defines the output for the bug create tool

type BugListParams

type BugListParams struct {
	Status   string `json:"status,omitempty" jsonschema:"description:Filter by status (OPEN INVESTIGATING FIXED WONTFIX)"`
	Severity string `json:"severity,omitempty" jsonschema:"description:Filter by severity (CRITICAL HIGH MEDIUM LOW)"`
	Limit    int    `json:"limit,omitempty" jsonschema:"description:Maximum results (default 20, max 100)"`
}

BugListParams defines parameters for the bug list tool

type BugListResult

type BugListResult struct {
	Bugs  []*storage.Token `json:"bugs"`
	Count int              `json:"count"`
	Total int              `json:"total"`
}

BugListResult defines the output for the bug list tool

type CreateParams

type CreateParams struct {
	ReqID   string `json:"reqId" jsonschema:"description:Requirement ID (e.g. CBIN-CLI-105),required"`
	Feature string `json:"feature" jsonschema:"description:Feature name,required"`
	Aspect  string `json:"aspect,omitempty" jsonschema:"description:Aspect (API CLI Engine etc.)"`
	Status  string `json:"status,omitempty" jsonschema:"description:Status (STUB IMPL TESTED BENCHED)"`
	Owner   string `json:"owner,omitempty" jsonschema:"description:Owner/assignee"`
}

CreateParams defines parameters for the create tool

type CreateResult

type CreateResult struct {
	Token   string `json:"token"`
	ReqID   string `json:"reqId"`
	Feature string `json:"feature"`
	Aspect  string `json:"aspect"`
	Status  string `json:"status"`
}

CreateResult defines the output for the create tool

type Deps added in v0.3.3

type Deps struct {
	// Root is the tree this server answers for. It is resolved to an
	// absolute path at startup; an empty value means the working directory.
	Root string
	// DBPath is the token index. Empty means DefaultDBPath under Root.
	DBPath string
}

Deps are the resolved inputs every tool handler runs against: the tree the server was started on and the index inside it.

They exist so a tool answers questions about the server's root rather than about whatever directory the process happens to be in. A path a caller supplies is resolved against Root and confined to it (see confine), which is what keeps `scan` from being pointed at an unrelated tree.

type DepsParams

type DepsParams struct {
	ReqID     string `json:"reqId" jsonschema:"description:requirement ID,required"`
	Direction string `json:"direction,omitempty" jsonschema:"description:forward (what it depends on, default) or reverse (what depends on it)"`
}

DepsParams selects a requirement and traversal direction.

type DepsResult

type DepsResult struct {
	ReqID        string   `json:"reqId"`
	Direction    string   `json:"direction"`
	Dependencies []string `json:"dependencies"`
	Count        int      `json:"count"`
}

DepsResult carries dependency IDs only -- deliberately no token payloads.

type FilesParams

type FilesParams struct {
	ReqID string `json:"reqId" jsonschema:"description:Requirement ID to find files for,required"`
}

FilesParams defines parameters for the files tool

type FilesResult

type FilesResult struct {
	ReqID     string   `json:"reqId"`
	Files     []string `json:"files"`
	FileCount int      `json:"fileCount"`
}

FilesResult defines the output for the files tool

type GrepParams

type GrepParams struct {
	Pattern string `json:"pattern" jsonschema:"description:Pattern to search for in token fields,required"`
	Field   string `json:"field,omitempty" jsonschema:"description:Field to search (req feature aspect owner or all)"`
	Limit   int    `json:"limit,omitempty" jsonschema:"description:Maximum results (default 20, max 100)"`
}

GrepParams defines parameters for the grep tool

type GrepResult

type GrepResult struct {
	Pattern string           `json:"pattern"`
	Field   string           `json:"field"`
	Tokens  []*storage.Token `json:"tokens"`
	Count   int              `json:"count"`
	Total   int              `json:"total"`
	// TotalIsLowerBound is true when the underlying overfetch hit its ceiling
	// (maxToolLimit+1 rows came back for an "all"-field search), meaning
	// Total is a floor, not an exact count.
	TotalIsLowerBound bool `json:"total_is_lower_bound,omitempty"`
}

GrepResult defines the output for the grep tool

type ImplementParams

type ImplementParams struct {
	ReqID string `json:"reqId" jsonschema:"description:Requirement ID to implement,required"`
}

ImplementParams defines parameters for the implement tool

type ImplementResult

type ImplementResult struct {
	Message      string `json:"message"`
	ReqID        string `json:"reqId"`
	Guidance     string `json:"guidance,omitempty"`
	SpecPath     string `json:"specPath,omitempty"`
	PlanPath     string `json:"planPath,omitempty"`
	HasSpec      bool   `json:"hasSpec"`
	HasPlan      bool   `json:"hasPlan"`
	TokenCount   int    `json:"tokenCount"`
	CurrentPhase string `json:"currentPhase,omitempty"`
}

ImplementResult defines the output for the implement tool

type ListParams

type ListParams struct {
	Status string `json:"status,omitempty" jsonschema:"description:Filter by status (STUB IMPL TESTED BENCHED)"`
	Aspect string `json:"aspect,omitempty" jsonschema:"description:Filter by aspect (API CLI Engine etc.)"`
	Owner  string `json:"owner,omitempty" jsonschema:"description:Filter by owner"`
	Limit  int    `json:"limit,omitempty" jsonschema:"description:Maximum number of results"`
}

ListParams defines parameters for the list tool

type ListResult

type ListResult struct {
	Tokens []*storage.Token `json:"tokens"`
	Count  int              `json:"count"`
	Total  int              `json:"total"`
	// TotalIsLowerBound is true when the underlying overfetch hit its ceiling
	// (maxToolLimit+1 rows came back), meaning Total is a floor, not an exact
	// count -- there may be more matches than reported.
	TotalIsLowerBound bool `json:"total_is_lower_bound,omitempty"`
}

ListResult defines the output for the list tool

type NextParams

type NextParams struct {
	Status string `json:"status,omitempty" jsonschema:"description:Filter by status (STUB or IMPL)"`
	Aspect string `json:"aspect,omitempty" jsonschema:"description:Filter by aspect"`
}

NextParams defines parameters for the next tool

type NextResult

type NextResult struct {
	Token    *storage.Token `json:"token,omitempty"`
	ReqID    string         `json:"reqId,omitempty"`
	Feature  string         `json:"feature,omitempty"`
	Aspect   string         `json:"aspect,omitempty"`
	Status   string         `json:"status,omitempty"`
	Priority int            `json:"priority,omitempty"`
	Message  string         `json:"message,omitempty"`
	// Source names where the answer came from: "database" (a fresh token
	// index) or "filesystem" (the index was missing or stale, so the tree was
	// scanned). An agent that gets no work back can tell an empty tree from
	// an unbuilt index.
	Source string `json:"source,omitempty"`
	// Blocked counts candidates passed over because a dependency was not
	// complete -- what separates "nothing left to do" from "everything left
	// is waiting on something".
	Blocked int `json:"blocked,omitempty"`
}

NextResult defines the output for the next tool

type PrioritizeParams

type PrioritizeParams struct {
	ReqID    string `json:"reqId" jsonschema:"description:Requirement ID to prioritize,required"`
	Priority int    `json:"priority" jsonschema:"description:Priority level (lower is higher priority),required"`
}

PrioritizeParams defines parameters for the prioritize tool

type PrioritizeResult

type PrioritizeResult struct {
	Message  string `json:"message"`
	ReqID    string `json:"reqId"`
	Priority int    `json:"priority"`
	Updated  int    `json:"updated"`
}

PrioritizeResult defines the output for the prioritize tool

type ScanParams

type ScanParams struct {
	Root        string `json:"root,omitempty" jsonschema:"description:Root directory to scan"`
	ProjectOnly bool   `json:"projectOnly,omitempty" jsonschema:"description:Filter by project requirement ID pattern"`
}

ScanParams defines parameters for the scan tool

type ScanResult

type ScanResult struct {
	Message string `json:"message"`
	Root    string `json:"root"`
	Tokens  int    `json:"total_tokens"`
	// Requirements is the unique requirement count, which the message has
	// always reported but the structured result did not.
	Requirements int `json:"unique_requirements"`
}

ScanResult defines the output for the scan tool

type Scopes added in v0.3.3

type Scopes struct {
	Read   bool
	Mutate bool
}

Scopes is what a request is allowed to do.

type SearchParams

type SearchParams struct {
	Keywords string `json:"keywords" jsonschema:"description:Search keywords,required"`
	Limit    int    `json:"limit,omitempty" jsonschema:"description:Maximum results (default 20, max 100)"`
}

SearchParams defines parameters for the search tool

type SearchResult

type SearchResult struct {
	Keywords string           `json:"keywords"`
	Tokens   []*storage.Token `json:"tokens"`
	Count    int              `json:"count"`
	Total    int              `json:"total"`
	// TotalIsLowerBound is true when the underlying overfetch hit its ceiling
	// (maxToolLimit+1 rows came back), meaning Total is a floor, not an exact
	// count -- there may be more matches than reported.
	TotalIsLowerBound bool `json:"total_is_lower_bound,omitempty"`
}

SearchResult defines the output for the search tool

type ShowParams

type ShowParams struct {
	ReqID string `json:"reqId" jsonschema:"description:Requirement ID (e.g. CBIN-123),required"`
	Limit int    `json:"limit,omitempty" jsonschema:"description:Maximum results (default 20, max 100)"`
}

ShowParams defines parameters for the show tool

type ShowResult

type ShowResult struct {
	ReqID  string           `json:"reqId"`
	Tokens []*storage.Token `json:"tokens"`
	Count  int              `json:"count"`
	Total  int              `json:"total"`
}

ShowResult defines the output for the show tool

type StatusParams

type StatusParams struct {
	ReqID string `json:"reqId" jsonschema:"description:Requirement ID (e.g. CBIN-123),required"`
}

StatusParams defines parameters for the status tool

type StatusResult

type StatusResult struct {
	ReqID string      `json:"reqId"`
	Stats StatusStats `json:"stats"`
	// DeclaredCompletionPct is the percentage of tokens declaring
	// STATUS=TESTED or STATUS=BENCHED -- declared status, not verified
	// evidence. Renamed from "CompletionPct" (R-15) so the field name itself
	// cannot be misread as a verified completion percentage.
	DeclaredCompletionPct int              `json:"declared_completion_pct"`
	Tokens                []*storage.Token `json:"tokens"`
	Total                 int              `json:"total"`
}

StatusResult defines the output for the status tool

type StatusStats

type StatusStats struct {
	Total   int `json:"total"`
	Stub    int `json:"stub"`
	Impl    int `json:"impl"`
	Tested  int `json:"tested"`
	Benched int `json:"benched"`
	// DeclaredComplete counts tokens declaring STATUS=TESTED or
	// STATUS=BENCHED -- a claim, not proof. Renamed from "Completed" (R-15):
	// the old name and the summary text below implied verified completion.
	DeclaredComplete int `json:"declared_complete"`
}

StatusStats holds progress statistics.

These counts reflect DECLARED token STATUS only, not verified evidence: a token counted in DeclaredComplete may have no passing test or bench record at all. Do not read Completed/DeclaredComplete as "done" -- use evidence.Complete for that question.

type ToolSpec added in v0.3.3

type ToolSpec struct {
	Name        string
	Description string
	// Mutates reports whether the tool writes. A read-scoped bearer token is
	// refused on these; everything else is readable with either token.
	Mutates  bool
	Register func(s *mcp.Server, deps Deps)
}

ToolSpec is one MCP tool: its identity, whether calling it changes stored state, and how it is registered.

Registry is the only place tools are declared. The server, the authorization scope check and docs/MCP_TOOLS.md are all derived from it, so a tool cannot be exposed without also being documented and scoped -- the failure mode of the previous design, where nineteen imperative AddTool calls sat beside a hand-maintained forty-line banner that had drifted from them.

func Registry added in v0.3.3

func Registry() []ToolSpec

Registry returns every tool this server exposes, in presentation order.

Every entry here has a postcondition a caller can check. The five placeholder tools that used to be registered -- specify, plan, index, bug-create and gap-mark -- returned a success message and changed nothing; an agent could not tell them from tools that worked. They are unregistered, and bug-create is back as a real tool that persists a row.

type ViewParams

type ViewParams struct {
	ReqID string `json:"reqId" jsonschema:"description:requirement ID e.g. CBIN-105 or PLAT-4521,required"`
	Limit int    `json:"limit,omitempty" jsonschema:"description:max entries per list section (default 10)"`
}

ViewParams identifies the requirement to aggregate.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL