server
server — audit issues
Audited 2026-06-20. Repo: software/server. Criteria: completeness · tests · separation of concerns · verb-named functions · file size (<1000 lines) · organization.
Health summary
The server is small (≈850 lines across 7 files), cleanly layered (transport in main.cpp, protocol in Dispatch.cpp, domain handlers in Tools.cpp, message marshalling in Doc.h), builds clean with -Wall -Wextra, and ./test.sh passes all 9 checks. The pserver::Session rename (commit 4c3762c) is fully applied in source — no Document-wrapper collision remains and no stale prisma/prism identifiers leak outside legitimate .prisma/.prism extension handling. The main weaknesses are completeness gaps where mutating tools (connect/disconnect/rename/set_metadata) report success without validating their targets, thin test coverage (most of the 16 tools and the parse-error / missing-name paths are never exercised), and documentation drift (README tools table omits 5 tools and still names the MCP server prisma). No file exceeds 800 lines.
Issues
[MEDIUM] completeness — connect/disconnect report success without validating endpoints
- Where:
src/Tools.cpp:290-301(handlers);kinogaki-core/include/kinogaki/Document.h:51-52(void connect/void disconnect) - Problem:
connectparsessource/targetonly for syntactic validity, then callss.connect(*src, *tgt)(avoid) and unconditionally returnsokText("connected …"). There is no check that either element/slot exists, so an agent connecting to a typo'd or nonexistent path gets a success message and a dangling connection.disconnectlikewise always reports success even when no connection intotargetexisted. The agent has no way to tell a real wiring from a no-op. - Fix: Validate that the source and target elements exist (and ideally that the slot paths resolve) before calling
connect; fordisconnect, checks.connections()for an existing edge intotargetand report "no connection into …" when absent. Return a failedToolResultotherwise.
[MEDIUM] completeness — rename_element reports success on a rejected/no-op rename
- Where:
src/Tools.cpp:248-257 - Problem:
Document::renamereturnsfromunchanged when it rejects the move (e.g. moving an element under its own descendant) or no-ops (Document.h:48). The handler already guards!has(from), existing-to, andparentExists, but a self-descendant move slips past all three and is reported as"renamed to <from>"— a silent failure the agent reads as success. - Fix: Compare the returned
finalpath against*to; if they differ (and it wasn't an intentional uniquify), surface that the rename was rejected/adjusted rather than reporting plain success.
[MEDIUM] tests — protocol surface and most tools are untested
- Where:
test.sh:13-39 - Problem: The smoke test covers
initialize,tools/list,define_element,set_property,get_element,save, one failingget_element, and one unknown method. It never exercises: the JSON-RPC parse-error path (Dispatch.cpp:20-28, malformed JSON →-32700), the missing-method case (-32600,Dispatch.cpp:46),tools/callwith noname(Dispatch.cpp:74-76), or 11 of the 16 tools (remove_element,rename_element,remove_property,set_metadata,connect,disconnect,load,search,compose,import,export). No auth/session model exists to test (stdio, single doc), but the request-validation and error-code surface is largely unverified. - Fix: Add cases feeding a non-JSON line (assert
-32700), a request with nomethod(assert-32600), atools/callmissingname(assertisError), and at least round-trip coverage for the structural mutators (define→connect→get_elementshows the wiring;rename_element;remove_elementsubtree count) and one foreign-formatimport/export.
[LOW] completeness — no initialize-ordering enforcement
- Where:
src/Dispatch.cpp:49-86 - Problem: The dispatcher will service
tools/listandtools/callbefore anyinitializehandshake, andinitializecan be sent more than once, with no state tracking. This is lenient rather than wrong for an stdio MCP server, but it means protocol-sequence violations are silently accepted. - Fix: Optionally track an "initialized" flag and reject pre-initialize
tools/*with a JSON-RPC error; at minimum note the intentional leniency in a comment.
[LOW] organization — README tools table omits 5 tools and example names the server prisma
- Where:
README.md:19-33(table),README.md:39(.mcp.jsonexample) - Problem: The catalog in
buildToolCatalogadvertises 16 tools (Tools.cpp:167-201), but the README table documents only 11 —load,search,compose,import,exportare missing. The.mcp.jsonsnippet still registers the server under the key"prisma"(a pre-rename name), inconsistent with thekinogaki-serverbinary andserverInfo.name. - Fix: Add the 5 missing tools to the table and rename the example server key to
kinogaki(orprism). Also consider a one-line "no auth / single document / stdio" note for the protocol model.
[LOW] organization — stale binaries in the (gitignored) build dir
- Where:
build/prism-server,build/prisma-mcp,build/prisma-server - Problem:
build/is correctly gitignored and untracked, but it holds three obsolete binaries from earlier rename eras (prisma-mcp,prisma-server,prism-server) alongside the currentkinogaki-server. Not committed, so harmless to the repo, but confusing local cruft that can mask which binary is current. - Fix:
rm build/prism-server build/prisma-mcp build/prisma-server(orrm -rf buildand rebuild). No repo change needed.
[LOW] separation — clean
- Where:
src/main.cpp(transport/stdio loop),src/Dispatch.cpp(JSON-RPC protocol),src/Tools.cpp(domain handlers),src/Doc.h(Reader/Builder message marshalling),src/Log.h(sink-swappable log) - Problem: None. Transport, JSON-RPC protocol, domain tool dispatch, the "eat-our-own-food" Document message layer, and logging are each in their own unit, with
dispatch(Session&, line)a deliberately reusable seam. No god files. (One stale comment:Dispatch.h:3andLog.h:4still reference an "editor calls it per HTTP request" / "Phase 3" integration that has no code here — cosmetic.)
[LOW] naming — clean
- Where: all
src/ - Problem: None. Functions read as verbs:
dispatch,callTool,buildToolCatalog,readFile/writeFile,parsePath,parentExists,childrenOf,coerce,valueText,endsWith,lowerExt,codecFor,addTool,logln.Reader/Builder/Session/ToolResult/Logare types (exempt). No noun-named or ambiguous function names.
[LOW] filesize — clean
- Where: all
src/ - Problem: None. Largest file is
src/Tools.cppat 380 lines; no file exceeds 800 (let alone 1000). Line counts:Tools.cpp380,Dispatch.cpp91,Doc.h74,main.cpp70,Log.h39,Tools.h31,Dispatch.h14.