Skip to main content

Module descriptors

Module descriptors 

Source
Expand description

Task 19 (Commit A) — safe local MCP descriptor cache and dormant deferred-tool integration (spec §7.4).

Before exact selection, MCP capability knowledge comes ONLY from bounded local state: the user’s mcp.json server config plus this descriptor cache (mcp-descriptors.json), treated as pre-existing operator-managed local state. Loading NEVER spawns a process or touches the network, and descriptors are never invented from server config alone: a server without a fingerprint-matching cache entry contributes no capabilities. This task deliberately adds no cache-refresh path from live server responses — a server-wide legacy connection is not exact-tool authorized and must not become a cache-poisoning bridge.

Under progressive tool disclosure, cached descriptors become truthful DORMANT registry entries: live tools-map/catalog entries with a stable identity, schema, and digest whose implementation is deferred (DeferredMcpTool). Exact activation therefore never mutates the catalog generation; execution is separately authorization-gated and (lease lifecycle commit) acquires a session-scoped runtime lease before any process starts.

Structs§

CachedServerDescriptors
Cached descriptors for one configured server, keyed to the exact config fingerprint they were recorded under.
CachedToolDescriptor
One cached MCP tool descriptor: exactly the fields a live tools/list would provide, pinned locally so activation can validate the live listing against operator-known expectations.
DeferredMcpTool
A dormant, descriptor-backed MCP tool. Registered like any live tool (stable identity, schema, digest — so wire resolution, discovery, exact grants, and the execution gate all work unchanged), but its implementation is DEFERRED: executing it requires the session MCP lease capability, which starts only this tool’s server after the execution gate has already authorized the call. Without that capability it fails typed and spawns nothing.
DiscoveryFailure
One server’s failed boot-discovery record: the launch fingerprint it failed under, when it was last tried (unix seconds) and how many consecutive attempts under that fingerprint failed.
McpDescriptorCache
Versioned on-disk descriptor cache model.

Enums§

DescriptorCacheError
Typed descriptor-cache boundary failures. All fail closed: a rejected cache yields ZERO dormant capabilities, never a partial or guessed set.

Constants§

CACHE_FORMAT_VERSION
Supported cache format version. Anything else fails typed.
CACHE_MAX_BYTES
Hard byte bound on the cache file — larger files are rejected unread.
DESCRIPTOR_CACHE_FILE
File name of the descriptor cache, resolved through the profile-aware config path helper so profiles cannot collide on one cache file.
DISCOVERY_BACKOFF_BASE_SECS
First retry delay after a failed boot discovery.
DISCOVERY_BACKOFF_MAX_SECS
Retry delay cap after repeated failed boot discoveries.
DISCOVERY_FAILURES_MAX
Maximum retained discovery-failure entries (oldest attempts evicted).
SERVER_MAX_TOOLS
Maximum retained descriptors per server entry.
TOOL_DESCRIPTION_MAX_BYTES
Byte bound applied to cached descriptions on load.
TOOL_NAME_MAX_BYTES
Maximum bytes of a cached tool name (also: nonempty, no control chars).
TOOL_SCHEMA_MAX_BYTES
Maximum serialized bytes of one cached input schema.

Functions§

cache_writeback_enabled
SYNAPS_MCP_CACHE_WRITEBACK=0 disables record_server_listing.
default_cache_path
Profile-aware default cache path. Uses the same profile FALLBACK semantics as every other config read (resolve_read_path): the profile copy is used when it exists, otherwise the shared base file. A shared base cache can therefore be visible to multiple profiles; the per-server config fingerprint still gates trust in every entry.
dormant_tools_for_config
Build the dormant deferred tools for the current config from the cache. Deterministic order (sorted server names, cached tool order). Only servers present in the CURRENT config whose cache entry fingerprint matches the current config fingerprint contribute tools; everything else is skipped with a warning. Never spawns, never touches the network.
load_cache_from
Load and sanitize a descriptor cache from an explicit path. Boundary rules: exactly ONE handle is opened (O_NOFOLLOW|O_NONBLOCK on Unix, so a symlink or FIFO at the path is refused without following/blocking) and ALL checks run against that opened handle’s metadata — no metadata-then-reopen TOCTOU. The opened file must be regular and within CACHE_MAX_BYTES; the read itself is capped via Read::take and a post-read length check rejects concurrent growth past the bound. The content must be valid JSON of the supported version. Individual hostile descriptor entries (invalid name, non-object schema, oversized schema, duplicates) are dropped deterministically; descriptions are bounded. Never spawns, never touches the network.
load_default_cache
Load the descriptor cache from the profile-resolved default location.
record_discovery_failure
Negative-cache sibling of record_server_listing: record that boot discovery of server under fingerprint failed at now_unix. Same locked read-merge-write and sanitisation. Consecutive failures under the same fingerprint increment attempts (driving the backoff); a different fingerprint restarts at 1. Returns the stored record.
record_server_listing
Write-back after a successful, lease-authorized tools/list (daemon-mode phase 2, C4): merge tools into the cache at path under server, keyed by the launch fingerprint, so the NEXT boot’s setup_lazy_mcp registers the same dormant descriptors without spawning anything (stable prompt-cache prefix across daemon restarts).
server_config_fingerprint
Deterministic fingerprint of one server’s local launch configuration (command, args, env). Cached descriptors are only trusted while the current config still fingerprints identically; any drift invalidates them. Pure local computation — no process, no network.
store_cache_at
Atomically persist a descriptor cache with private-filesystem policy (spec §5.4): parent directory ensured 0700, temp file created create_new at mode 0600 (never create-then-chmod), then renamed over the target; symlinks at the target are refused typed. Used to seed/maintain operator-local state (and by tests); this task adds no production writer fed from live server responses.