Architecture¶
How a document gets from the editor to a diagnostic, and a hover to passmcp's guidance.
The packages¶
| Package | Owns |
|---|---|
cmd/passmcp-lsp |
Flags, server mode, check mode, completions |
internal/jsonrpc |
Content-Length framing, message envelopes, bounded reads |
internal/lsp |
The session: lifecycle, open documents, publishing, hover |
internal/check |
Recognising an artefact and every diagnostic about it |
internal/schema |
The JSON Schema subset server.json needs, fail-closed |
internal/jsondoc |
A JSON and JSON-with-comments parser that keeps byte ranges, and UTF-16 positions |
internal/guidance |
Asking the installed passmcp for a check's guidance |
The dependency direction is one way: lsp uses check, guidance and
jsonrpc; check uses schema and jsondoc; nothing below lsp knows
the protocol exists, which is why check mode needs no server.
A change to a document¶
- The read loop takes one framed message from stdin
(
jsonrpc.Reader), decodes the envelope and dispatches it. didOpenstores the text;didChangeapplies each change, whole or by range; either callsupdate.updaterunscheck.Analyze(path, text). Recognition is by file name first and content second; an unrecognised document ends here with no diagnostics.- The document is parsed strictly, and, for a client configuration, again
with comments and trailing commas allowed. A parse failure is one
syntaxdiagnostic. - The artefact's analyzer walks the tree. Every node knows its byte range, so each diagnostic carries one.
publishturns byte ranges into line and UTF-16 character positions and sendstextDocument/publishDiagnostics.
The read loop is the only goroutine that touches documents.
A hover¶
IDAtfinds the string under the cursor and checks where it is: a policy'smust_pass,must_not_failor exemptioncheck, or an attestation verdict'sid.- The lookup runs in its own goroutine, with the id and range copied out of the document, because it waits on a program.
guidance.Passmcpwrites a one-finding report, encodes the id into it, and runspassmcp explain --output jsonwith the report on stdin andPASSMCP_CONFIGpointing at an empty file. The entry for the id is the guidance; the answer is cached for the life of the process.- The hover is Markdown: what the check means, the steps, the verdict's documentation link when the attestation gave one.
Where each rule comes from¶
| Artefact | Source of truth | How this repository follows it |
|---|---|---|
server.json |
The MCP Registry's published schema | Embedded byte for byte; make schema-check compares it with the URL |
| Client configuration | passmcp's internal/clientconf and internal/discover at 0.0.1 |
The same layouts and fields, reimplemented; see the file's comments |
| Tool definitions | MCP specification 2025-11-25, schema.ts and server/tools |
Each rule's MUST or SHOULD sets its severity |
| Policies | passmcp 0.0.2's policy reader, documented in its manual | make crosscheck applies every fixture with the released passmcp |
| Attestations | passmcp-reporting 0.0.2 | Its verifiers are called; nothing is reimplemented |
| Guidance | passmcp's catalogue | Asked of the installed passmcp at hover time |