Expand description
JSON ↔ engine-type conversions shared by TopoDB’s JSON-speaking front ends
(currently topodb-mcp; topodb-cli is next).
Every function here is pure (no I/O, no Db access) and returns Result<_, String> — callers are responsible for mapping the String into their own
error type (topodb-mcp’s server.rs maps it to an rmcp::ErrorData:
invalid_params for bad input, internal_error otherwise). Nothing here
ever panics: an unrepresentable value is always an Err, never an
unwrap/expect.
Constants§
- ENTITY_
LABEL - Label/prop name constants for the two built-in write shapes
(
create_memory/create-memory,create_entity/create-entity). Single source of truth shared by every front end (topodb-mcp’s defaultIndexSpecand write tools,topodb-cli’screate-entity/create-memorysubcommands) so writes land on exactly the(label, prop)pairs the default spec indexes — search and lookup work out of the box regardless of which front end wrote the data. - ENTITY_
NAME_ PROP - MEMORY_
CONTENT_ PROP - MEMORY_
LABEL - UNSUPPORTED
- Error string for both directions of an unrepresentable
PropValue:BytesandDateTimehave no JSON counterpart over MCP v0, and any JSON shape that isn’t a string/number/bool (array, object, null) has noPropValuecounterpart either.
Functions§
- default_
spec - The ONE canonical default
IndexSpecfor TopoDB’s built-in write shapes, shared by every front end (topodb-mcpwhen--specis omitted;topodb-cliwhen it creates a brand-new db file). Declares equality on(Entity, name)and text on(Memory, content), using the sharedENTITY_LABEL/ENTITY_NAME_PROP/MEMORY_LABEL/MEMORY_CONTENT_PROPconstants. - edge_
to_ json - An
EdgeRecord→ JSON:id/from/toas ULID strings,typeforty(JSON-friendlier than the Rust keyword-adjacent field name),scopeperscope_to_json,propsperprops_to_json, and the temporal boundsvalid_from/valid_to(valid_toisnullwhile the edge is open). - json_
to_ f32_ vec - A JSON array of finite numbers →
Vec<f32>, for raw embeddings (topodb::Op::SetEmbedding) and vector-search queries.Errifvisn’t a JSON array, or any element isn’t a finite number. (The host computes embeddings; TopoDB stores/searches the raw floats.) - json_
to_ prop_ changes - A JSON object of property changes for
topodb::Op::SetNodeProps. Anullvalue REMOVES the key (None); any other JSON scalar SETS it (Some(PropValue), viajson_to_prop_value).Errifvisn’t a JSON object, or a non-null value isn’t a representable scalar. Thenull-removes convention is what lets a caller delete a prop over the wire — plainjson_to_propshas no way to express removal. - json_
to_ prop_ value serde_json::Value→PropValue. Strings/bools map directly. A JSON integer maps toIntwhen it fitsi64, and is an error when it doesn’t ((i64::MAX, u64::MAX]— silently downgrading it to a lossyFloatwould corrupt the value); only a genuine non-integer number maps toFloat. This is the inverse ofprop_value_to_json’sInt/Floathandling. Every other JSON shape (array, object, null — and, structurally, anything that would have needed to round-trip throughBytes/DateTime) isUNSUPPORTED.- json_
to_ props - A JSON object →
Props, propagating the first unrepresentable value asErr.Errifvisn’t a JSON object at all. - merge_
required_ prop - Builds the
Propsmap for a write tool that has one required, caller-named field (create_memory’scontent,create_entity’sname) plus an optional JSONpropsobject of additional metadata.key/valueare the required field, already converted to aPropValue;extrais the tool call’s optionalpropsparam, converted viajson_to_props. - node_
to_ json - A
NodeRecord→ JSON:id/labelas strings (ULID viaDisplayforid),scopeperscope_to_json, andpropsperprops_to_json. Deliberately omits theembeddingfield — no MCP v0 tool surfaces vector data (that’s a later concern via dedicated embedding tools). - prop_
value_ to_ json PropValue→serde_json::Value.Str/Int/Boolmap directly;Floatmaps to a JSON number (Erronly for a non-finite float, which JSON has no representation for).Bytes/DateTimeareUNSUPPORTED.- props_
to_ json Props(aBTreeMap<String, PropValue>) → a JSON object, propagating the first unrepresentable value asErr.- resolve_
batch - resolve_
scope - Resolves a tool’s optional
scopestring param to aScope:None→default(the server’s configured default scope);Some("shared")(case-insensitive) →Scope::Shared;Some(<ulid>)→Scope::Id; any other string → a clearErr. Mirrorstopodb-mcp’sconfig::parse_scope“shared” / ULID contract, generalized to theOption(tool-call) case. - scope_
label - Human/JSON-facing rendering of a
Scope:"shared"or the ULID string. Reused by every front end’sinfo/db_info-style output and scope round-tripping. (Distinct fromscope_to_json, which wraps the same rendering in aserde_json::Valuefor a JSON response body; this returns a bareStringfor contexts — like a struct field — that want the label without aValuewrapper.) - scope_
to_ json - A
Scope→ its JSON rendering:"shared"or the scope’s ULID string. Mirrors theshared/ULID label convention used across TopoDB’s JSON-facing front ends (e.g.topodb-mcp’sdb_infotool). - scope_
to_ scope_ set - A resolved
Scope→ the singletonScopeSeta read call needs:Sharedadmits only the shared scope,Id(id)admits only that one scope id. - scopes_
to_ scope_ set - Several resolved
Scopes → theScopeSeta multi-scope read runs against.Scope::Sharedsets the set’sinclude_sharedflag; eachScope::Idbecomes a member id. This is the only constructor that can produce a genuinely multi-memberScopeSet—scope_to_scope_setalways collapses to a singleton, which is why “this project plus shared” was previously unexpressible from any client. - subgraph_
to_ json - A
Subgraph→{"nodes": [...], "edges": [...]}, each element pernode_to_json/edge_to_json.