Documentation
¶
Overview ¶
Package mcp implements the MCP server mode: a thin, stateless adapter that exposes the same core sensors as MCP tools (PRD section 10). It reimplements no audit logic — every tool call translates to the same engine the CLI uses — and relies on prompt caching to neutralize the stateless overhead.
Skeleton: this declares the [Server] contract. No transport (stdio/HTTP) or tool dispatch is implemented yet.
Index ¶
- func NewServer() *mcpsdk.Server
- func Serve(ctx context.Context) error
- type BaselineAcceptRequest
- type BaselineAcceptResponse
- type BaselineDelta
- type BaselineListRequest
- type BaselineListResponse
- type BaselinePruneRequest
- type BaselinePruneResponse
- type BaselineRegisterAuthzHelperRequest
- type BaselineRegisterAuthzHelperResponse
- type BaselineUnregisterAuthzHelperRequest
- type BaselineUnregisterAuthzHelperResponse
- type CheckCVEsRequest
- type CheckCVEsResponse
- type ConfirmSurfaceRequest
- type ConfirmSurfaceResponse
- type CoverageRequest
- type CoverageResponse
- type DBSection
- type FileInput
- type FrontierPending
- type GoneItem
- type ResolvedClean
- type ScanAllRequest
- type ScanAllResponse
- type ScanAllSummary
- type ScanDBRequest
- type ScanDBResponse
- type ScanEndpointRequest
- type ScanEndpointResponse
- type ScanRequest
- type ScanResponse
- type SurfaceIDORRequest
- type SurfaceResponse
- type Tool
- type VulnerableDependency
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewServer ¶
NewServer builds the codefit MCP server with its tools registered. Each tool is a THIN adapter: it hands the SDK's typed request to the core handler that already exists and is tested, and returns the core's result as structured output. No audit logic lives here — the MCP layer only connects the protocol to the engine (PRD §15). The server is stateless: every tool call is independent and carries everything it needs.
Types ¶
type BaselineAcceptRequest ¶
type BaselineAcceptRequest struct {
Root string `json:"root"`
Fingerprints []string `json:"fingerprints"`
Reason string `json:"reason"`
}
BaselineAcceptRequest marks baseline items as acknowledged by a human (a false positive or accepted debt). reason is mandatory. SAFETY: the agent must call this ONLY when the human decided so — codefit records by:"human" but cannot verify it; the skill enforces the discipline.
type BaselineAcceptResponse ¶
type BaselineAcceptResponse struct {
Accepted []string `json:"accepted"`
Note string `json:"note"`
}
BaselineAcceptResponse reports which fingerprints were acknowledged.
func HandleBaselineAccept ¶
func HandleBaselineAccept(req BaselineAcceptRequest) (BaselineAcceptResponse, error)
HandleBaselineAccept records a human's decision to accept items. It only touches the baseline file.
type BaselineDelta ¶
type BaselineDelta struct {
New int `json:"new"`
Changed int `json:"changed"`
Known int `json:"known"`
Acknowledged int `json:"acknowledged"`
Gone int `json:"gone"`
AffirmationsShown int `json:"affirmations_shown"`
GoneCandidates []GoneItem `json:"gone_candidates,omitempty"`
Note string `json:"note"`
}
BaselineDelta is scan-all's account of how the current scan compares to the committed baseline. The agent acts on new + changed (and unaccepted affirmations); known surface is silenced but counted.
type BaselineListRequest ¶
type BaselineListRequest struct {
Root string `json:"root"`
Language string `json:"language,omitempty"`
Filter string `json:"filter,omitempty"`
}
BaselineListRequest reads the current baseline so the agent can reference items in accept/prune WITHOUT reading the raw .codefit-baseline file. Filter is "" (all), "known" (not yet accepted), or "acknowledged". Language is accepted for tool uniformity but unused — listing reads the file, it does not scan code.
type BaselineListResponse ¶
type BaselineListResponse struct {
Items []baseline.Entry `json:"items"`
Count int `json:"count"`
AuthzHelpers []baseline.AuthzHelper `json:"authz_helpers,omitempty"`
Note string `json:"note"`
}
BaselineListResponse is the projected baseline: per item just fp+file+category+ state (+reason/date if acknowledged), small enough not to truncate. AuthzHelpers lists the project's registered custom authz helpers (read-only visibility) so the agent can see — and propose unregistering — them without reading the file.
func HandleBaselineList ¶
func HandleBaselineList(req BaselineListRequest) (BaselineListResponse, error)
HandleBaselineList returns the baseline entries. A missing baseline is NOT an error: it returns an empty list with a note pointing to scan-all. Read-only.
type BaselinePruneRequest ¶
type BaselinePruneRequest struct {
Root string `json:"root"`
Language string `json:"language"`
Fingerprints []string `json:"fingerprints,omitempty"`
}
BaselinePruneRequest removes baseline items that no longer exist in the code (gone). With Fingerprints set it prunes only those (if confirmed gone); empty prunes all confirmed-gone items.
type BaselinePruneResponse ¶
BaselinePruneResponse reports which fingerprints were pruned.
func HandleBaselinePrune ¶
func HandleBaselinePrune(req BaselinePruneRequest) (BaselinePruneResponse, error)
HandleBaselinePrune re-scans to confirm which baseline items are gone, then removes them. Stateless: it recomputes the current surface; it never edits code.
type BaselineRegisterAuthzHelperRequest ¶ added in v0.1.2
type BaselineRegisterAuthzHelperRequest struct {
Root string `json:"root"`
Language string `json:"language"`
HelperName string `json:"helper_name"`
Reason string `json:"reason"`
}
BaselineRegisterAuthzHelperRequest registers a project-specific authz helper so codefit recognizes it on later scans (known_authz_detected reflects it). reason is mandatory. SAFETY: registering silences the AUTHZ gap on EVERY item that calls the helper — far more reach than accepting one item. The agent must call this ONLY when the human approved it; codefit records by:"human" but cannot verify it (the skill enforces the discipline). It does NOT clear the IDOR/ownership gap (ADR 0013, ADR 0006 amended).
type BaselineRegisterAuthzHelperResponse ¶ added in v0.1.2
type BaselineRegisterAuthzHelperResponse struct {
Registered bool `json:"registered"`
Note string `json:"note"`
}
BaselineRegisterAuthzHelperResponse reports the outcome.
func HandleBaselineRegisterAuthzHelper ¶ added in v0.1.2
func HandleBaselineRegisterAuthzHelper(req BaselineRegisterAuthzHelperRequest) (BaselineRegisterAuthzHelperResponse, error)
HandleBaselineRegisterAuthzHelper records a human-approved custom authz helper in the baseline. It only touches the baseline file.
type BaselineUnregisterAuthzHelperRequest ¶ added in v0.1.2
type BaselineUnregisterAuthzHelperRequest struct {
Root string `json:"root"`
Language string `json:"language"`
HelperName string `json:"helper_name"`
}
BaselineUnregisterAuthzHelperRequest reverses a registration (the developer's decision is always reversible). The next scan stops recognizing the helper.
type BaselineUnregisterAuthzHelperResponse ¶ added in v0.1.2
type BaselineUnregisterAuthzHelperResponse struct {
Unregistered bool `json:"unregistered"`
Note string `json:"note"`
}
BaselineUnregisterAuthzHelperResponse reports the outcome.
func HandleBaselineUnregisterAuthzHelper ¶ added in v0.1.2
func HandleBaselineUnregisterAuthzHelper(req BaselineUnregisterAuthzHelperRequest) (BaselineUnregisterAuthzHelperResponse, error)
HandleBaselineUnregisterAuthzHelper removes a registered helper. It only touches the baseline file.
type CheckCVEsRequest ¶ added in v0.1.4
type CheckCVEsRequest struct {
Root string `json:"root"`
}
CheckCVEsRequest is the input to codefit-check-cves: a project root. The dependency manifests are auto-detected under it.
type CheckCVEsResponse ¶ added in v0.1.4
type CheckCVEsResponse struct {
Vulnerable []VulnerableDependency `json:"vulnerable"`
DependenciesScanned int `json:"dependencies_scanned"`
Notes []string `json:"notes"`
}
CheckCVEsResponse reports the vulnerable dependencies, how many were scanned, and any honest notes (a manifest present without its lockfile, or none found).
func HandleCheckCVEs ¶ added in v0.1.4
func HandleCheckCVEs(req CheckCVEsRequest) (CheckCVEsResponse, error)
HandleCheckCVEs reads the project's dependency manifests (exact versions from lockfiles / go.mod only), queries OSV.dev for known vulnerabilities, and returns the vulnerable dependencies. A thin adapter: it parses manifests, queries the client, and reshapes the result — no detection logic here. When no version resolves (no lockfile), it returns the honest note WITHOUT querying OSV.
type ConfirmSurfaceRequest ¶
type ConfirmSurfaceRequest struct {
Confirmations []surface.Confirmation `json:"confirmations"`
}
ConfirmSurfaceRequest carries the agent's verdicts back to codefit.
type ConfirmSurfaceResponse ¶
type ConfirmSurfaceResponse struct {
Findings []findings.Finding `json:"findings"`
Dismissed []surface.Confirmation `json:"dismissed"`
Uncertain []surface.Confirmation `json:"uncertain"`
Invalid []surface.Confirmation `json:"invalid"`
}
ConfirmSurfaceResponse is the integration result: probabilistic findings plus the traceability buckets. Stateless — built purely from the verdicts sent.
func HandleConfirmSurface ¶
func HandleConfirmSurface(req ConfirmSurfaceRequest) ConfirmSurfaceResponse
HandleConfirmSurface integrates the agent's verdicts: codefit-confirm-surface. It recomputes each surface id to validate the verdict before integrating, and keeps no session.
type CoverageRequest ¶
type CoverageRequest struct {
Language string `json:"language"`
}
CoverageRequest is the input to codefit-coverage.
type CoverageResponse ¶
CoverageResponse carries the coverage manifest: what is audited deterministically vs reasoned over surface vs not covered.
func HandleCoverage ¶
func HandleCoverage(req CoverageRequest) (CoverageResponse, error)
HandleCoverage returns the coverage manifest for the language. Thin adapter: the manifest is the provider's single source of truth.
type DBSection ¶ added in v0.2.0
type DBSection struct {
Measured bool `json:"measured"`
Note string `json:"note,omitempty"`
Findings []findings.Finding `json:"findings,omitempty"`
Surface []findings.SurfaceItem `json:"surface,omitempty"`
Score int `json:"score"`
}
DBSection is the database dimension's result inside scan-all. Measured=false with a Note is the honest "not audited" state (disabled / no parser / schema read or parse failure) — a db failure is SOFT here, reported but never fatal to the security result (ADR 0020). Findings are affirmations (e.g. DB-050); Surface are questions; both are already filtered by the baseline.
type FileInput ¶
FileInput is one source file a surface tool reasons over (path + content), so the tool stays stateless — the caller passes the bytes, codefit reads nothing.
type FrontierPending ¶
type FrontierPending struct {
Count int `json:"count"`
Note string `json:"note,omitempty"`
Endpoints []report.FrontierEndpoint `json:"endpoints,omitempty"`
}
FrontierPending declares the endpoints codefit did NOT resolve locally: the data left the handler body, so codefit concluded nothing and the agent must follow it in the code. They are named (not detailed) with a Note explaining why they are not detailed and how to fetch any of them. This is not hiding — it is prioritising while declaring the rest.
type GoneItem ¶
type GoneItem struct {
Fingerprint string `json:"fingerprint"`
Category string `json:"category"`
File string `json:"file"`
Snippet string `json:"snippet,omitempty"`
}
GoneItem names a baseline item no longer present in the code — a prune candidate.
type ResolvedClean ¶
type ResolvedClean struct {
Count int `json:"count"`
Note string `json:"note,omitempty"`
Endpoints []report.ResolvedCleanEndpoint `json:"endpoints,omitempty"`
}
ResolvedClean declares the endpoints codefit resolved locally and found clean (controls present, no gap). They are NAMED with a verification fact, not detailed. This is an affirmation — codefit looked and it is clean — not a generic "not detailed" bucket; that is why it is separate from FrontierPending.
type ScanAllRequest ¶
ScanAllRequest is the input to codefit-scan-all: a project root and language. codefit walks the project, runs the deterministic sensor and the surface queries, and returns the complete per-endpoint picture.
type ScanAllResponse ¶
type ScanAllResponse struct {
Summary ScanAllSummary `json:"summary"`
// Score is the per-dimension breakdown plus the weighted global (ADR 0021). It
// is ALWAYS present: by_dimension carries every weighted dimension, with the
// unaudited ones (review/complexity/tests, and db when it did not run) as null —
// an honest statement that the dimension exists but was not measured. The score
// reflects deterministic AFFIRMATIONS only, not mapped surface.
Score scoring.ScoreSummary `json:"score"`
Baseline BaselineDelta `json:"baseline"`
Actionable []report.EndpointReport `json:"actionable"`
ResolvedClean ResolvedClean `json:"resolved_clean"`
FrontierPending FrontierPending `json:"frontier_pending"`
// DB is the parallel database-structure section — the db dimension's findings
// and surface, baseline-filtered. It is NON-endpoint (a table has no route), so
// it is its own section, not one of the three endpoint buckets. Nil when the
// project has no database.schema_paths configured, so a project without a
// database yields a response byte-identical to before db was wired (ADR 0020).
DB *DBSection `json:"db,omitempty"`
}
ScanAllResponse is the agent-first synthesis as an ACTIONABLE summary, not the raw item dump. It has three buckets, one per resolution level, all decided by facts codefit already computes (ADR 0008):
- Actionable — resolved locally AND has a gap: full detail, the agent acts.
- ResolvedClean — resolved locally, NO gap: named + a verification fact; codefit checked and the controls are present.
- FrontierPending — not resolved locally (the data left the handler body): named; the agent follows it in the code.
ResolvedClean and FrontierPending are kept DISTINCT on purpose: one affirms codefit verified the controls, the other states codefit could not conclude — epistemological opposites the agent must distinguish (flattening them would be the old frontier-wording error). Full detail of any named endpoint is always one codefit-scan-endpoint call away. Note on the baseline layer: when a baseline exists, the three buckets are FILTERED to what is not yet tracked (new/changed surface, and unaccepted deterministic affirmations). So on an unchanged re-scan all three buckets can be empty even though Summary.CertainConcerns (computed before filtering) is > 0 — the difference is exactly the "known" surface the baseline is silencing.
func HandleScanAll ¶
func HandleScanAll(req ScanAllRequest) (ScanAllResponse, error)
HandleScanAll runs the full audit over the project and returns the actionable summary plus the named frontier-pending list. It reuses the real security sensor (the deterministic rules plus the three surface queries already run together there), groups the result by endpoint, and partitions by the local-resolution fact — it adds no detection, only the aggregation and the split.
type ScanAllSummary ¶
type ScanAllSummary struct {
Endpoints int `json:"endpoints"`
DeterministicFindings int `json:"deterministic_findings"`
SurfaceItems int `json:"surface_items"`
CertainConcerns int `json:"certain_concerns"`
}
ScanAllSummary is the at-a-glance count, not a judgment.
type ScanDBRequest ¶ added in v0.2.0
ScanDBRequest is the input to codefit-scan-db: a project root and language.
type ScanDBResponse ¶ added in v0.2.0
type ScanDBResponse struct {
Measured bool `json:"measured"`
Note string `json:"note,omitempty"`
Findings []findings.Finding `json:"findings"`
Surface []findings.SurfaceItem `json:"surface"`
Score int `json:"score"`
}
ScanDBResponse is the standalone DB-structure result. Measured distinguishes "audited" from "not audited": when false, Note says why (no schema_paths, no schema parser, or the sensor is disabled) and Findings/Surface are empty — it is NOT a "clean" result. Score is a plain dimension score (0-100), like codefit-scan-security; this tool does not compute by_dimension.
func HandleScanDB ¶ added in v0.2.0
func HandleScanDB(req ScanDBRequest) (ScanDBResponse, error)
HandleScanDB runs the DB sensor over the project and returns its structural findings + surface. A thin adapter: it resolves the provider, loads the config, and delegates to the DB sensor (which reads the schema, runs the core rules, and stamps identity). Standalone — it touches nothing in scan-all.
type ScanEndpointRequest ¶
type ScanEndpointRequest struct {
Root string `json:"root"`
Language string `json:"language"`
File string `json:"file"`
}
ScanEndpointRequest is the input to codefit-scan-endpoint: a project root, language, and the file (relative to root, as it appears in scan-all's File fields) to re-analyse on demand.
type ScanEndpointResponse ¶
type ScanEndpointResponse struct {
File string `json:"file"`
Found bool `json:"found"`
Endpoints []report.EndpointReport `json:"endpoints,omitempty"`
Note string `json:"note,omitempty"`
}
ScanEndpointResponse carries the full per-endpoint detail for one file: every handler in it with all its concerns (signals, reason_to_review, certainty, fact fields) — the same concern contract as scan-all. Found is false when the file has no auditable concerns (not a route handler, or nothing to enumerate).
func HandleScanEndpoint ¶
func HandleScanEndpoint(req ScanEndpointRequest) (ScanEndpointResponse, error)
HandleScanEndpoint re-analyses a single file on demand and returns its endpoints with full detail. STATELESS: it re-runs the static analysis over the project and filters to the requested file — it retrieves nothing stored. codefit does not keep the surface items waiting to be asked for; it recomputes the request. Static analysis is cheap, and re-running the same pipeline guarantees the detail here is identical to what scan-all would have shown for that endpoint (ADR 0008).
type ScanRequest ¶
ScanRequest is the input to codefit-scan-security: a project root and language.
type ScanResponse ¶
type ScanResponse struct {
Findings []findings.Finding `json:"findings"`
Surface []findings.SurfaceItem `json:"surface"`
Score int `json:"score"`
Blocked bool `json:"blocked"`
}
ScanResponse is the deterministic + surface result over the project (the §11 contract): flat findings and surface, the dimension score, and whether the project is blocked (an unconsented critical security finding).
func HandleScanSecurity ¶
func HandleScanSecurity(req ScanRequest) (ScanResponse, error)
HandleScanSecurity runs the security sensor over the project and returns the flat findings + surface. A thin adapter: it resolves the provider, runs the sensor (the deterministic rules + the surface queries, already wired there), and returns its result — no detection logic lives here.
type SurfaceIDORRequest ¶
type SurfaceIDORRequest struct {
Files []FileInput `json:"files"`
}
SurfaceIDORRequest is the input to codefit-surface-idor.
type SurfaceResponse ¶
type SurfaceResponse struct {
Surface []findings.SurfaceItem `json:"surface"`
}
SurfaceResponse is the §11 surface contract: the items the agent must reason.
func HandleSurfaceAuthz ¶
func HandleSurfaceAuthz(req SurfaceIDORRequest) (SurfaceResponse, error)
HandleSurfaceAuthz enumerates the broken-authorization surface across the given files. It orders the items so the actionable ones — where no known authz helper was detected — come FIRST, the rest after (where a check exists, the agent verifies sufficiency). It does NOT reduce the list: the complete enumeration is preserved, only reordered, so findings surface instead of being buried in volume. Ordering by a fact is not a severity judgment — codefit does not say "no check is worse", it just surfaces the fact for the agent.
func HandleSurfaceIDOR ¶
func HandleSurfaceIDOR(req SurfaceIDORRequest) (SurfaceResponse, error)
HandleSurfaceIDOR enumerates the IDOR surface across the given files and returns it in the canonical JSON contract. Files that are not handled by a provider (or carry no IDOR surface) contribute nothing.
func HandleSurfaceNPlus1 ¶ added in v0.2.2
func HandleSurfaceNPlus1(req SurfaceIDORRequest) (SurfaceResponse, error)
HandleSurfaceNPlus1 enumerates the N+1 (DB-201) surface and orders by STRUCTURAL CERTAINTY, reusing the queryable facts — it does NOT filter (ADR 0005): a loop over three literal elements is enumerated exactly like a loop over an unbounded query result.
1st local + sequential await — the worst, most certain shape
2nd local + Promise.all-wrapped (concurrent) — still N queries
3rd frontier (a service/repository call — codefit cannot see the query;
kept last, honest, never dropped)
func HandleSurfaceOverfetch ¶
func HandleSurfaceOverfetch(req SurfaceIDORRequest) (SurfaceResponse, error)
HandleSurfaceOverfetch enumerates the over-fetching surface and orders by STRUCTURAL CERTAINTY, reusing the queryable facts — it does NOT filter:
1st local find, no select (structurally confirmed over-fetch — actionable) 2nd local find, with select (limited) 3rd frontier (service — codefit cannot see the find; kept last, honest)
The complete enumeration is preserved; only the order changes, lowering the uncertain (frontier) without dropping them — the unchecked-first principle on the local/frontier axis (ADR 0005). Ordering by a fact is not severity: codefit ranks by what it can assert with most certainty, the agent judges.
type Tool ¶
type Tool string
Tool is the name of an MCP tool codefit exposes. All tools use the codefit- prefix; the codefit-surface-* family enumerates surface for the agent to reason about rather than detecting (PRD section 11).
const ( ToolScanSecurity Tool = "codefit-scan-security" ToolScanDB Tool = "codefit-scan-db" ToolCheckCVEs Tool = "codefit-check-cves" ToolCheckPractices Tool = "codefit-check-practices" ToolScanTests Tool = "codefit-scan-tests" ToolSurfaceIDOR Tool = "codefit-surface-idor" ToolSurfaceAuthz Tool = "codefit-surface-authz" ToolSurfaceOverfetch Tool = "codefit-surface-overfetch" ToolSurfaceNPlus1 Tool = "codefit-surface-nplus1" ToolConfirmSurface Tool = "codefit-confirm-surface" ToolReviewCode Tool = "codefit-review-code" ToolScanAll Tool = "codefit-scan-all" ToolScanEndpoint Tool = "codefit-scan-endpoint" ToolBaselineList Tool = "codefit-baseline-list" ToolBaselineAccept Tool = "codefit-baseline-accept" ToolBaselinePrune Tool = "codefit-baseline-prune" ToolBaselineRegisterAuthzHelper Tool = "codefit-baseline-register-authz-helper" ToolBaselineUnregisterAuthzHelper Tool = "codefit-baseline-unregister-authz-helper" ToolCoverage Tool = "codefit-coverage" )
type VulnerableDependency ¶ added in v0.1.4
type VulnerableDependency struct {
Name string `json:"name"`
Version string `json:"version"`
Ecosystem string `json:"ecosystem"`
Vulnerabilities []cve.Vulnerability `json:"vulnerabilities"`
}
VulnerableDependency is one dependency that OSV.dev reports as vulnerable, with every vulnerability affecting its exact installed version.