mcpserver

package
v0.0.1-alpha Latest Latest
Warning

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

Go to latest
Published: May 28, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package mcpserver exposes ProjectLens's retrieval capabilities via the Model Context Protocol (MCP) over Streamable HTTP. It registers 10 tools (see toolRegistry) that an agent can call to search symbols, query code semantically, inspect symbol context, summarize packages, look up database table schemas, check index freshness, show change history, analyse co-change coupling, and save/search captured knowledge.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NotReadyHandler

func NotReadyHandler(slug string, cause error) http.Handler

NotReadyHandler returns an http.Handler that responds with 503 and a JSON body explaining how to bring the project online. Used when a configured project's runtime cannot be opened (e.g., storage schema missing).

Types

type ChangeHistoryPayload

type ChangeHistoryPayload struct {
	Target     string         `json:"target"`
	TargetKind string         `json:"target_kind,omitempty"`
	NotFound   bool           `json:"not_found,omitempty"`
	Evidence   *EvidenceSpan  `json:"evidence,omitempty"`
	Records    []ChangeRecord `json:"records"`
}

ChangeHistoryPayload is the structured response for get_change_history. TargetKind is "file" or "symbol" (empty when nothing matched). Evidence is populated when the target resolved to a symbol. NotFound is true when neither a file nor a symbol matched the query.

type ChangeRecord

type ChangeRecord struct {
	Hash       string `json:"hash"`
	ShortHash  string `json:"short_hash"`
	Author     string `json:"author"`
	Date       string `json:"date"` // ISO date YYYY-MM-DD
	ChangeType string `json:"change_type,omitempty"`
	Subject    string `json:"subject,omitempty"`
}

ChangeRecord is one structured change-history entry. Subject is the first line of the commit message when available; otherwise empty.

type CouplingEntry

type CouplingEntry struct {
	FilePath        string  `json:"file_path"`
	Strength        float64 `json:"strength"`
	Provenance      string  `json:"provenance,omitempty"`
	ConfidenceClass string  `json:"confidence_class,omitempty"`
}

CouplingEntry is one structurally exposed co-change relationship. Provenance + ConfidenceClass identify the trust class of the underlying co_changes edge (typically history/inferred).

type CouplingPayload

type CouplingPayload struct {
	Target      string          `json:"target"`
	NotFound    bool            `json:"not_found,omitempty"`
	MinStrength float64         `json:"min_strength"`
	Coupled     []CouplingEntry `json:"coupled"`
	Trust       *Trust          `json:"trust,omitempty"`
}

CouplingPayload is the structured response for get_coupling. NotFound is set when the named file isn't indexed; Coupled is then nil. Trust summarizes the worst class across the Coupled entries.

type Degradation

type Degradation struct {
	Degraded bool   `json:"degraded"`
	Reason   string `json:"reason,omitempty"`
	Fallback string `json:"fallback,omitempty"`
}

Degradation signals that a result is partial because a backend was unavailable. Agents should treat results as best-effort when Degraded == true; when false, Reason and Fallback are omitted and the result is fully trusted.

type EvidenceSpan

type EvidenceSpan struct {
	FilePath  string `json:"file_path"`
	LineStart int    `json:"line_start"`
	LineEnd   int    `json:"line_end"`
}

EvidenceSpan points at the bytes a structured result is derived from so an agent can cheaply re-read and verify before acting on them.

type FindSymbolPayload

type FindSymbolPayload struct {
	Query string      `json:"query"`
	Kind  string      `json:"kind,omitempty"`
	Hits  []SymbolHit `json:"hits"`
	Total int         `json:"total"`
}

FindSymbolPayload is the structured response for find_symbol.

type KnowledgeHit

type KnowledgeHit struct {
	ID         int64    `json:"id"`
	Category   string   `json:"category"`
	Title      string   `json:"title"`
	Body       string   `json:"body"`
	Tags       []string `json:"tags,omitempty"`
	Score      float64  `json:"score,omitempty"`
	MatchedVia string   `json:"matched_via"` // "vector" | "anchor" | "both"
}

KnowledgeHit is one structured row used by search_knowledge.

type PackageSummaryPayload

type PackageSummaryPayload struct {
	PackageName     string   `json:"package_name"`
	Summary         string   `json:"summary,omitempty"`
	ModelVersion    string   `json:"model_version,omitempty"`
	GeneratedAt     string   `json:"generated_at,omitempty"`
	AgeMinutes      float64  `json:"age_minutes,omitempty"`
	Stale           bool     `json:"stale"`
	ExportedSymbols []string `json:"exported_symbols,omitempty"`
}

PackageSummaryPayload is the structured response for get_package_summary. GeneratedAt + AgeMinutes + Stale are derived from the summaries row at response time. Stale is set when the summary is older than 7 days; agents can use it to decide whether to ask for a re-summarize before quoting.

type ProviderHealth

type ProviderHealth = indexstate.ProviderHealth

ProviderHealth reports the state of one configured provider.

type SaveKnowledgePayload

type SaveKnowledgePayload struct {
	ID                int64    `json:"id"`
	Embedded          bool     `json:"embedded"`
	Deduped           bool     `json:"deduped,omitempty"`
	AnchorsResolved   int      `json:"anchors_resolved"`
	AnchorsUnresolved []string `json:"anchors_unresolved,omitempty"`
}

SaveKnowledgePayload is the structured response for save_knowledge.

Deduped is true when the handler short-circuited on a recent duplicate (same source+title+body within the dedup window) — the returned ID points at the pre-existing entry. Anchors from the dup-hit call are still resolved and merged into the existing entry's edges (idempotent via the edges unique constraint), so a retry with corrected anchors can still attach.

AnchorsUnresolved entries are formatted as "type:ref (reason)" — the reason is the resolver's diagnostic ("not found", "ambiguous: N matches — use SCIP id") so the agent can pick a canonical ref instead of retrying with the same short name.

type SearchGoContextPayload

type SearchGoContextPayload struct {
	Query       string      `json:"query"`
	QueryType   string      `json:"query_type"`
	Hits        []SymbolHit `json:"hits"`
	Total       int         `json:"total"`
	Degradation Degradation `json:"degradation"`
}

SearchGoContextPayload is the structured response for search_go_context. Degradation is non-zero when a backend was unavailable — agents should treat Hits as best-effort then.

type SearchKnowledgePayload

type SearchKnowledgePayload struct {
	Query   string         `json:"query,omitempty"`
	Total   int            `json:"total"`
	Entries []KnowledgeHit `json:"entries"`
}

SearchKnowledgePayload is the structured response for search_knowledge.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server wraps the dependencies needed by the MCP tool handlers.

func New

func New(db *storage.DB, router *retrieval.Router, port int, repoPath string) *Server

New creates a new MCP server with the given dependencies.

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler returns an http.Handler that serves this Server's MCP tools over Streamable HTTP at the caller-supplied mount point. Each invocation creates a fresh MCPServer + session manager so multiple projects can be mounted independently in one process.

func (*Server) MCPServer

func (s *Server) MCPServer() *server.MCPServer

MCPServer returns the internal mcp-go MCPServer for testing purposes. It creates a new server with all tools registered but does not start HTTP.

func (*Server) Start

func (s *Server) Start(ctx context.Context) error

Start creates the MCP server, registers all tools, and starts serving over Streamable HTTP. It blocks until ctx is cancelled, then shuts down gracefully.

func (*Server) WithProjectIdentity

func (s *Server) WithProjectIdentity(slug, schema string) *Server

WithProjectIdentity attaches project_slug + storage_schema for log scope inside loggingHooks. Returns the same *Server for chaining.

func (*Server) WithSummarizer

func (s *Server) WithSummarizer(p SummarizerProber) *Server

WithSummarizer attaches a SummarizerProber. Returns the same Server for chaining at wire-up time. Safe to call before Start.

type StageFreshness

type StageFreshness = indexstate.StageFreshness

StageFreshness mirrors the per-stage shape used in index_status.

type SummarizerProber

type SummarizerProber = indexstate.SummarizerProber

SummarizerProber matches the summarizer probe contract used by indexstate.

type SymbolContextPayload

type SymbolContextPayload struct {
	Query        string      `json:"query,omitempty"`
	NotFound     bool        `json:"not_found,omitempty"`
	Target       SymbolHit   `json:"target"`
	ScipSymbol   string      `json:"scip_symbol,omitempty"`
	Callers      []SymbolHit `json:"callers,omitempty"`
	Callees      []SymbolHit `json:"callees,omitempty"`
	Implementors []SymbolHit `json:"implementors,omitempty"`
	Trust        *Trust      `json:"trust,omitempty"`
}

SymbolContextPayload is the structured response for get_symbol_context. Target carries the matched symbol (Evidence.FilePath:LineStart-LineEnd is where it lives). Callers, Callees, and Implementors are slices of SymbolHit so each carries its own evidence span. NotFound is set when the lookup matched no symbol — Target and the slices are then zero.

type SymbolHit

type SymbolHit struct {
	Kind        string       `json:"kind"`
	Name        string       `json:"name"`
	Signature   string       `json:"signature,omitempty"`
	PackageName string       `json:"package_name,omitempty"`
	Score       float64      `json:"score"`
	DocComment  string       `json:"doc_comment,omitempty"`
	Evidence    EvidenceSpan `json:"evidence"`
	// Provenance + ConfidenceClass are set on graph-derived hits
	// (callers/callees/implementors) and identify the trust class of the
	// edge that produced the hit. Empty on the Target hit and on
	// lexical/semantic results.
	Provenance      string `json:"provenance,omitempty"`
	ConfidenceClass string `json:"confidence_class,omitempty"`
}

SymbolHit is one structured result row used by find_symbol and any other tool that returns ranked symbols. The Evidence span points an agent at the bytes that produced this hit so it can re-read before acting.

type TableColumn

type TableColumn struct {
	Name         string `json:"name"`
	Type         string `json:"type,omitempty"`
	IsNullable   bool   `json:"is_nullable"`
	IsPrimaryKey bool   `json:"is_primary_key"`
	Default      string `json:"default,omitempty"`
	ForeignKey   string `json:"foreign_key,omitempty"`
}

TableColumn is one column from a datastore_tables.columns JSON blob.

type TableContextPayload

type TableContextPayload struct {
	TableName string         `json:"table_name"`
	NotFound  bool           `json:"not_found,omitempty"`
	Engine    string         `json:"engine,omitempty"`
	Columns   []TableColumn  `json:"columns,omitempty"`
	ReadBy    []TableEdgeHit `json:"read_by,omitempty"`
	WrittenBy []TableEdgeHit `json:"written_by,omitempty"`
	Trust     *Trust         `json:"trust,omitempty"`
}

TableContextPayload is the structured response for get_table_context. NotFound is set when the table lookup didn't match anything; in that case Columns/ReadBy/WrittenBy are nil and TableName echoes the query. Trust summarizes the worst class across ReadBy + WrittenBy edges.

type TableEdgeHit

type TableEdgeHit struct {
	Kind            string       `json:"kind"`
	Name            string       `json:"name"`
	Evidence        EvidenceSpan `json:"evidence"`
	Provenance      string       `json:"provenance,omitempty"`
	ConfidenceClass string       `json:"confidence_class,omitempty"`
}

TableEdgeHit is a code reference to a table — used in TableContextPayload to expose reads_table / writes_table edges with evidence spans. Provenance + ConfidenceClass identify the trust class of the edge.

type Trust

type Trust struct {
	WorstClass string `json:"worst_class"`
}

Trust summarizes the worst confidence class encountered across the edges that fed a response. Agents can read this single field instead of scanning every hit. Ordering: ambiguous > inferred > extracted (worst first).

Jump to

Keyboard shortcuts

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