Documentation
¶
Overview ¶
Package mcp is lore's MCP (Model Context Protocol) driving adapter: it exposes lore's grounded retrieval and Q&A use cases as MCP tools so any MCP client (Claude Desktop, editors, agent frameworks) can call a private corpus and get back cited answers. Like internal/cli it is a driving adapter — it wires the same internal/app use cases to a protocol surface (the official Go MCP SDK as transport) and holds no business logic. It is read-only: no add/sync/rm/init tools are registered.
Because it is lore's first long-running process, the storage and provider handles in Deps are opened once by the composition root and reused for the server's lifetime; tool calls hit that warm state and never re-open the DB.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AskInput ¶
type AskInput struct {
Collections []string `` /* 130-byte string literal not displayed */
Question string `json:"question" jsonschema:"the question to answer using only these collections"`
K int `json:"k,omitempty" jsonschema:"number of chunks to ground on (default 8)"`
Budget int `json:"budget,omitempty" jsonschema:"cap the grounding to roughly this many tokens, trimming within k (0 = no cap)"`
Rerank bool `` /* 162-byte string literal not displayed */
Hybrid bool `json:"hybrid,omitempty" jsonschema:"fuse BM25 keyword search with vector search (recovers exact-term and identifier matches)"`
MMR bool `json:"mmr,omitempty" jsonschema:"diversify grounding with Maximal Marginal Relevance (single-collection; not with rerank)"`
Recency bool `json:"recency,omitempty" jsonschema:"prefer recently-updated documents via a time decay (not with rerank/mmr)"`
Where []string `` /* 136-byte string literal not displayed */
SourceGlob string `json:"source_glob,omitempty" jsonschema:"restrict grounding to documents whose source matches this glob, e.g. '*.pdf'"`
Strict bool `json:"strict,omitempty" jsonschema:"when true, return an error instead of an ungrounded answer if no chunks match"`
IncludeSources *bool `json:"include_sources,omitempty" jsonschema:"include each cited chunk's full text in the citations (default true)"`
}
AskInput is the `ask` tool's arguments.
type AskOutput ¶
type AskOutput struct {
Answer string `json:"answer" jsonschema:"the synthesized answer; inline [n] markers reference the citations"`
Citations []Citation `json:"citations" jsonschema:"the chunks the answer cites, in [n] order"`
Grounded bool `json:"grounded" jsonschema:"false means nothing matched and the answer rests on model knowledge alone"`
}
AskOutput is the `ask` tool's structured result.
type Chunk ¶
type Chunk struct {
ChunkID string `json:"chunk_id" jsonschema:"the chunk's ID"`
Seq int `json:"seq" jsonschema:"the chunk's position within its document"`
HeadingPath string `json:"heading_path,omitempty" jsonschema:"the document section the chunk came from (structure-aware chunkers only)"`
Text string `json:"text" jsonschema:"the chunk's stored text"`
}
Chunk is one stored chunk returned by get_chunks (the cat --chunk shape).
type Citation ¶
type Citation struct {
Ordinal int `json:"ordinal" jsonschema:"the [n] marker this citation has in the answer text"`
Source string `json:"source" jsonschema:"source URI of the cited document"`
Seq int `json:"seq" jsonschema:"the chunk's position within its document"`
ChunkID string `json:"chunk_id" jsonschema:"the cited chunk's ID; pass to get_chunks to fetch it"`
Collection string `json:"collection,omitempty" jsonschema:"origin collection (set only for multi-collection answers)"`
Text string `json:"text,omitempty" jsonschema:"the cited chunk's text (present when include_sources is true)"`
}
Citation is one cited chunk in an answer.
type CollectionInfo ¶
type CollectionInfo struct {
Name string `json:"name" jsonschema:"the collection name"`
Model string `json:"model" jsonschema:"the embedding model the collection is pinned to"`
Dimensions int `json:"dimensions" jsonschema:"the embedding dimensionality"`
Documents int `json:"documents" jsonschema:"number of documents ingested"`
Chunker string `json:"chunker" jsonschema:"the pinned chunker spec"`
}
CollectionInfo is one collection's summary in list_collections.
type CollectionStatusInput ¶
type CollectionStatusInput struct {
Collection string `json:"collection" jsonschema:"the collection to inspect"`
}
CollectionStatusInput is the `collection_status` tool's arguments.
type CollectionStatusOutput ¶
type CollectionStatusOutput struct {
Name string `json:"name" jsonschema:"the collection name"`
Model string `json:"model" jsonschema:"the embedding model the collection is pinned to"`
Dimensions int `json:"dimensions" jsonschema:"the embedding dimensionality"`
Documents int `json:"documents" jsonschema:"number of documents ingested"`
Chunks int `json:"chunks" jsonschema:"number of indexed chunks"`
Chunker string `json:"chunker" jsonschema:"the pinned chunker spec"`
// LastIngestAt is the most recent document ingestion time (RFC3339); it
// advances on any re-ingest, unlike a collection's birth timestamp. Empty
// for a collection with no documents.
LastIngestAt string `json:"last_ingest_at,omitempty" jsonschema:"timestamp of the most recently ingested document; advances on any re-ingest"`
// CorpusDigest is the corpus content identity (hex sha256 over the document
// set); it changes on any add, removal, or edit and is the stable handle for
// a provenance snapshot.
CorpusDigest string `json:"corpus_digest" jsonschema:"content digest of the document set; changes on any add, removal, or edit"`
}
CollectionStatusOutput is one collection's detailed status, including its chunk count (the field list_collections omits to stay cheap).
type Config ¶
type Config struct {
// Collections restricts which collections the tools expose, as exact names or
// globs (path.Match against the collection name). Empty exposes all local
// collections.
Collections []string
// Version is reported to clients in the MCP initialize handshake.
Version string
}
Config tunes the server: the collection scope and the version reported to clients.
type Deps ¶
type Deps struct {
Catalog *app.Catalog
Query *app.Querier
Ask *app.Asker
// Retriever composes retrieval (hybrid/rerank/mmr/recency/where/cap) for the
// ask/query tools — the same use case the CLI and eval use.
Retriever *app.Retriever
// Rerank is nil when no rerank provider is configured; the ask/query tools
// return a tool error if rerank is requested in that case (mirroring the CLI).
Rerank *app.Reranker
// Tokens backs the ask tool's budget trimming.
Tokens app.TokenCounter
// Index backs collection_status's chunk count (read-only; Entries).
Index app.VectorIndex
}
Deps are the lore use cases the MCP tools invoke, wired by the composition root (via the cli mcp command). They are warm, already-opened handles reused across every tool call.
type GetChunksInput ¶
type GetChunksInput struct {
Collection string `json:"collection" jsonschema:"the lore collection the chunks belong to"`
ChunkIDs []string `json:"chunk_ids" jsonschema:"the chunk IDs to fetch; unknown IDs are omitted from the result"`
}
GetChunksInput is the `get_chunks` tool's arguments.
type GetChunksOutput ¶
type GetChunksOutput struct {
Chunks []Chunk `json:"chunks" jsonschema:"the found chunks, in request order; absent IDs are omitted"`
}
GetChunksOutput is the `get_chunks` tool's structured result.
type Hit ¶
type Hit struct {
Text string `json:"text" jsonschema:"the chunk's text"`
Source string `json:"source" jsonschema:"source URI of the chunk's document"`
Score float64 `json:"score" jsonschema:"vector similarity score (higher is more similar)"`
ChunkID string `json:"chunk_id" jsonschema:"the chunk's ID; pass to get_chunks to fetch it again"`
Seq int `json:"seq" jsonschema:"the chunk's position within its document"`
Collection string `json:"collection,omitempty" jsonschema:"origin collection (set only for multi-collection queries)"`
RerankScore *float64 `json:"rerank_score,omitempty" jsonschema:"cross-encoder relevance score (present only when rerank was used)"`
}
Hit is one retrieved chunk in the query result (the standard lore hit object plus its origin collection).
type ListCollectionsInput ¶
type ListCollectionsInput struct{}
ListCollectionsInput is empty — list_collections takes no arguments.
type ListCollectionsOutput ¶
type ListCollectionsOutput struct {
Collections []CollectionInfo `json:"collections" jsonschema:"the collections this server exposes"`
}
ListCollectionsOutput is the `list_collections` tool's structured result.
type QueryInput ¶
type QueryInput struct {
Collections []string `json:"collections" jsonschema:"the lore collection name(s) to search; at least one, all sharing one embedding space"`
Query string `json:"query" jsonschema:"the search text"`
K int `json:"k,omitempty" jsonschema:"number of chunks to return (default 8)"`
SourceGlob string `json:"source_glob,omitempty" jsonschema:"restrict to documents whose source matches this glob, e.g. '*.pdf'"`
Rerank bool `` /* 162-byte string literal not displayed */
Hybrid bool `json:"hybrid,omitempty" jsonschema:"fuse BM25 keyword search with vector search (recovers exact-term and identifier matches)"`
MMR bool `json:"mmr,omitempty" jsonschema:"diversify results with Maximal Marginal Relevance (single-collection; not with rerank)"`
Recency bool `json:"recency,omitempty" jsonschema:"prefer recently-updated documents via a time decay (not with rerank/mmr)"`
Where []string `` /* 126-byte string literal not displayed */
}
QueryInput is the `query` tool's arguments.
type QueryOutput ¶
type QueryOutput struct {
Hits []Hit `json:"hits" jsonschema:"the matching chunks, best first"`
}
QueryOutput is the `query` tool's structured result.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is lore's configured MCP server: the SDK server with lore's tools registered, plus the scope it enforces. Build it with New, then serve over stdio (ServeStdio) or Streamable HTTP (ServeHTTP).
func New ¶
New builds the server, validating the collection scope and registering every read-only tool. A nil logger discards logs (never writes to stdout).
func (*Server) ServeHTTP ¶
ServeHTTP serves the MCP protocol over the SDK's Streamable HTTP transport, bound to addr. A bare ":port" (empty host) is bound to 127.0.0.1 — local by default. When token is non-empty every request must carry "Authorization: Bearer <token>". Binding to a non-loopback host without a token is refused (a usage error), so a network-exposed server is never unauthenticated. The server stays up across tool failures and shuts down gracefully on ctx cancel.
func (*Server) ServeStdio ¶
ServeStdio serves the MCP protocol over stdin/stdout until the client disconnects or ctx is cancelled. stdout carries JSON-RPC only — logs go to the injected logger (stderr), never stdout, so the protocol stream stays clean.
A startup failure (Connect) is returned. Once serving, the client closing the pipe (EOF) or ctx being cancelled (SIGINT) is normal stdio termination and returns nil; only a genuine mid-session transport error is surfaced.