Help us shape the future of Go! Take the 2026 Go Developer Survey

mcpsrv

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package mcpsrv exposes the library over the Model Context Protocol. M2.

A translation layer, not a home for logic: each tool definition validates its arguments, calls one function in internal/library, and marshals the result. It must never import internal/store.

M2 is cheap because M1 already did the work, and it is the part no existing citation-map tool has — an assistant that can answer "what connects these two papers in my library" against a graph the user owns.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New(lib *library.Library, version string) *mcp.Server

New returns an MCP server exposing lib. version is the fil version, reported to the client.

func ServeStdio

func ServeStdio(ctx context.Context, lib *library.Library, version string) error

ServeStdio serves lib over stdin and stdout until the client disconnects or ctx is cancelled. Nothing else may write to stdout while it runs.

Types

type Candidate

type Candidate struct {
	Work
	TitleMatch bool `json:"title_match,omitempty" jsonschema:"the title matches the one given, allowing for case, punctuation and a typo"`
}

Candidate is one work a title could mean.

type DuplicateGroup

type DuplicateGroup struct {
	Title string `json:"title"`
	Works []Work `json:"works"`
}

DuplicateGroup is fetched works that share a title.

type NoTextPaper added in v0.3.0

type NoTextPaper struct {
	Paper  Work   `json:"paper"`
	Status string `json:"status" jsonschema:"no-text (a scan), gibberish, unreadable or timed-out"`
	Reason string `json:"reason,omitempty"`
}

NoTextPaper is a paper whose PDF gave no searchable text.

type Page

type Page struct {
	Total   int    `json:"total" jsonschema:"how many there are in the library"`
	Fetched int    `json:"fetched" jsonschema:"how many of them have been fetched; the rest are stubs"`
	Omitted int    `json:"omitted" jsonschema:"how many were left out of works; raise limit to see more"`
	Works   []Work `json:"works"`
}

Page is a capped list: the works returned, and how many were left out. An assistant handed five thousand works spends its context on them and loses the thread, so no tool returns an unbounded list (§6, rule 1).

type Passage added in v0.3.0

type Passage struct {
	Paper   Work   `json:"paper"`
	Page    int    `json:"page" jsonschema:"the page of the PDF it is on, from 1"`
	Text    string `json:"text" jsonschema:"the matching stretch of the passage; matched words are between [[ and ]]"`
	InRefs  bool   `json:"in_reference_list,omitempty" jsonschema:"the passage is from the paper's reference list"`
	PDFPath string `json:"pdf_path" jsonschema:"the PDF on the user's disk"`
}

Passage is one passage that matched.

type Sentence added in v0.3.0

type Sentence struct {
	Cited    Work   `json:"cited"`
	Page     int    `json:"page"`
	Sentence string `json:"sentence"`
	Section  string `json:"section,omitempty"`
}

Sentence is a place the paper cites one of its references.

type Step

type Step struct {
	Work
	Next string `json:"next,omitempty" jsonschema:"cites: this paper cites the next one; cited_by: the next one cites this paper"`
}

Step is one paper on a chain, and how it relates to the next.

type Work

type Work struct {
	FilID    string `json:"fil_id" jsonschema:"the library's own ID for this paper, which never changes; pass it to any other tool"`
	ID       string `json:"id,omitempty" jsonschema:"OpenAlex ID; also accepted by any other tool"`
	OAStatus string `json:"oa_status" jsonschema:"diamond, gold, green, hybrid or bronze are free to read; closed is not; unknown until fetched"`

	// Stub marks a work known only by its ID: something in the library cites
	// it, but its metadata has not been fetched. It must never be presented as
	// if the library knew what it is (§6, rule 3).
	Stub bool `` /* 133-byte string literal not displayed */

	Title string `json:"title,omitempty"`

	// Authors is the byline, so that an answer can credit a paper from the
	// library rather than from the model's memory. Capped like every list.
	Authors     []string `json:"authors,omitempty" jsonschema:"the first authors, in byline order; absent when not recorded"`
	MoreAuthors int      `json:"more_authors,omitempty" jsonschema:"how many further authors the byline has (et al.)"`

	Year         int    `json:"year,omitempty"`
	Type         string `json:"type,omitempty"`
	Venue        string `json:"venue,omitempty"`
	DOI          string `json:"doi,omitempty"`
	OAURL        string `json:"oa_url,omitempty" jsonschema:"a free-to-read copy, when OpenAlex knows one"`
	CitedByCount int    `` /* 133-byte string literal not displayed */
	Seed         bool   `json:"seed,omitempty" jsonschema:"the user added this paper themselves"`
	Unresolved   bool   `json:"unresolved,omitempty" jsonschema:"OpenAlex has no record of this ID; it will never be fetched"`
}

Work is a paper as an assistant sees it. Two things are never omitted, whatever else is missing (ARCHITECTURE.md §6): an ID, so that every answer can be followed up with another call, and the open-access status, so that an assistant does not claim it can read a paper it cannot. The fil ID is always there (D17); the OpenAlex ID is there for every work OpenAlex knows.

Jump to

Keyboard shortcuts

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