{"name":"com.moltlinestudio/recall","slug":"moltlinestudio-recall","title":"Moltline Recall","description":"A portable knowledge-graph memory you pass in and get back. No database. 4 of 6 free.","url":"https://mcp.market/server/moltlinestudio-recall","rating":null,"grade":"A","score":87,"certified":false,"status":"active","category":"data","tags":["data"],"presence":{"score":23,"stars":0,"forks":0,"downloads_week":null,"last_push_at":"2026-09-19T15:00:29.000Z","license":"MIT"},"uptime":{"percent":100,"checks":3,"ok":3,"last_checked_at":"2026-09-20T03:21:09.308Z","last_ok_at":"2026-09-20T03:21:09.308Z","latency_ms":130},"claimed":false,"transport":"remote","callable_via_gateway":true,"default_price_micros":0,"repository":"https://github.com/GarphenGate/moltline-mcp","website":"https://moltlinestudio.com/servers.html#recall","version":"1.2.0","remotes":[{"type":"streamable-http","url":"https://mcp.moltlinestudio.com/recall"}],"packages":[],"tools":[{"name":"graph_at_time","description":"See the memory as it stood on a given day, optionally faded by age. PREMIUM (license).\n\nRelations carrying since and until are filtered to those in force on the\ndate; with a half-life, confidence decays exponentially with age so a\ntwo-year-old belief does not weigh the same as last week's. Typical input\n{\"graph\": {...}, \"as_of\": \"2026-06-01\", \"half_life_days\": 180} returns\n{\"as_of\": \"2026-06-01\", \"graph\": {...}, \"dropped\": {\"not_yet\": 1,\n\"expired\": 2}, \"decayed\": 4}.\n\nUse when the answer depends on when you ask. Not for what changed between\ntwo points - that is graph_diff, which does not need dates at all. Errors: on invalid, missing, or malformed input this tool never raises a protocol error — it returns {\"error\": \"<what is wrong and how to fix it>\"} (for example {\"error\": \"as_of must be a date like 2026-06-01\"}). Every call is read-only and idempotent, so after correcting the input it is always safe to retry.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"graph":{"additionalProperties":true,"type":"object","description":"The graph document."},"as_of":{"type":"string","description":"The date to view the memory as of, ISO 8601, e.g. \"2026-06-01\"."},"half_life_days":{"default":0,"minimum":0,"type":"integer","description":"Days over which a relation's confidence halves. 0, the\ndefault, disables decay and leaves confidence untouched."}},"required":["graph","as_of"],"additionalProperties":false}},{"name":"graph_compact","description":"Shrink a memory to the part that still earns its place. PREMIUM (license).\n\nRanks entities by how connected they are and how much is recorded about\nthem, keeps anything you name outright, and drops the rest along with the\nrelations that pointed at them. Typical input {\"graph\": {...},\n\"max_entities\": 50, \"keep\": [\"Acme Corp\"]} returns {\"graph\": {...},\n\"kept\": 50, \"dropped_entities\": [\"Old Note\", ...], \"dropped_relations\": 12,\n\"ranking\": \"degree, then observation count, then name\"}.\n\nUse when a graph has outgrown the context you can spend on it. Not for\nremoving wrong facts - graph_lint finds those, and deleting them is a\ndecision you should make deliberately rather than by ranking. Errors: on invalid, missing, or malformed input this tool never raises a protocol error — it returns {\"error\": \"<what is wrong and how to fix it>\"}. Every call is read-only and idempotent, so after correcting the input it is always safe to retry.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"graph":{"additionalProperties":true,"type":"object","description":"The graph document to compact."},"max_entities":{"default":50,"minimum":1,"type":"integer","description":"How many entities to keep. Default 50."},"keep":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"default":null,"description":"Entity names to keep regardless of rank, e.g. [\"Acme Corp\"].\nMatched case-insensitively."}},"required":["graph"],"additionalProperties":false}},{"name":"graph_diff","description":"Say exactly what changed between two versions of a memory. FREE.\n\nThe audit trail a database gives you for free, without the database.\nTypical input {\"before\": {...}, \"after\": {...}} returns\n{\"entities_added\": [\"Beta Ltd\"], \"entities_removed\": [],\n\"observations_added\": {\"Acme Corp\": [\"renewed in March\"]},\n\"relations_added\": [...], \"changed\": true}.\n\nUse after an upsert to record what a session learned, or between two\nagents to see what one knows that the other does not. Not for merging the\ntwo - feed the differences back through graph_upsert for that. Errors: on invalid, missing, or malformed input this tool never raises a protocol error — it returns {\"error\": \"<what is wrong and how to fix it>\"}. Every call is read-only and idempotent, so after correcting the input it is always safe to retry.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"before":{"additionalProperties":true,"type":"object","description":"The earlier graph document."},"after":{"additionalProperties":true,"type":"object","description":"The later graph document."}},"required":["before","after"],"additionalProperties":false}},{"name":"graph_lint","description":"Find the breaks a memory graph accumulates as it grows. FREE.\n\nRelations pointing at entities that do not exist, entities nothing points\nat, near-duplicate names, and observations that contradict each other on\nthe same entity. Typical input {\"graph\": {...}} returns {\"ok\": false,\n\"dangling_relations\": [{\"from\": \"Acme Corp\", \"to\": \"Beta Ltd\", \"missing\":\n[\"Beta Ltd\"]}], \"orphan_entities\": [\"Old Note\"], \"near_duplicates\":\n[[\"Acme Corp\", \"Acme  Corp.\"]], \"contradictions\": []}.\n\nUse before trusting a graph you did not build, or on a schedule as memory\ngrows. Not for comparing two graphs (graph_diff) and not for shrinking one\n(graph_compact). Errors: on invalid, missing, or malformed input this tool never raises a protocol error — it returns {\"error\": \"<what is wrong and how to fix it>\"}. Every call is read-only and idempotent, so after correcting the input it is always safe to retry.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"graph":{"additionalProperties":true,"type":"object","description":"The graph document to check."}},"required":["graph"],"additionalProperties":false}},{"name":"graph_search","description":"Find what the graph knows about something, plus its neighbourhood. FREE.\n\nScores entities by how many query words appear in the name, type and\nobservations, then pulls in whatever is within the requested number of\nhops - because the useful answer to \"what do we know about Acme\" is\nusually Acme plus who it is connected to. Typical input {\"graph\": {...},\n\"query\": \"acme renewal\", \"hops\": 1} returns {\"matches\": [{\"name\": \"Acme\nCorp\", \"score\": 3, \"why\": [\"name\", \"observation\"]}], \"neighbourhood\":\n{\"entities\": [...], \"relations\": [...]}, \"hops\": 1}.\n\nUse to read memory back before answering. Not for writing (graph_upsert)\nand not for narrowing by date, which graph_at_time does. Errors: on invalid, missing, or malformed input this tool never raises a protocol error — it returns {\"error\": \"<what is wrong and how to fix it>\"} (for example {\"error\": \"query must contain at least one word or number\"}). Every call is read-only and idempotent, so after correcting the input it is always safe to retry.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"graph":{"additionalProperties":true,"type":"object","description":"The graph document to search."},"query":{"type":"string","description":"Words to look for, e.g. \"acme renewal\". Matching is on whole\nlowercase words, so it is exact and repeatable rather than fuzzy."},"hops":{"default":1,"maximum":3,"minimum":0,"type":"integer","description":"How far to expand from each match along relations. 0 returns\nmatches only; 3 is the maximum. Default 1."},"limit":{"default":20,"maximum":200,"minimum":1,"type":"integer","description":"Maximum entities to return. Default 20, maximum 200."}},"required":["graph","query"],"additionalProperties":false}},{"name":"graph_upsert","description":"Fold new facts into a memory graph and get the whole graph back. FREE.\n\nIdempotent by construction: re-adding the same entity, observation or\nrelation changes nothing, so an agent that replays its own history does not\nend up with a graph full of duplicates. Typical input {\"graph\": {\"entities\":\n[], \"relations\": []}, \"entities\": [{\"name\": \"Acme Corp\", \"type\":\n\"company\", \"observations\": [\"renewed in March\"]}]} returns {\"graph\": {...},\n\"added\": {\"entities\": 1, \"observations\": 1, \"relations\": 0}, \"merged\": 0}.\n\nUse as the single write path for memory. Not for reading it back\nselectively - that is graph_search - and not for finding out what a write\nchanged, which graph_diff answers precisely. Errors: on invalid, missing, or malformed input this tool never raises a protocol error — it returns {\"error\": \"<what is wrong and how to fix it>\"} (for example {\"error\": \"graph exceeds <value> entities; split it\"}). Every call is read-only and idempotent, so after correcting the input it is always safe to retry.","write_action":false,"price_micros":0,"input_schema":{"type":"object","properties":{"graph":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"The existing graph document, or omitted to start a new one.\nShape: {\"entities\": [...], \"relations\": [...]}."},"entities":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"default":null,"description":"Entities to add or extend, each {\"name\": ..., \"type\": ...,\n\"observations\": [...]}. Observations are appended and deduplicated;\nan existing entity keeps its type unless a new one is supplied."},"relations":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"default":null,"description":"Relations to add, each {\"from\": ..., \"to\": ..., \"type\":\n..., and optionally \"since\", \"until\", \"confidence\"}. Dates are\nISO 8601 (YYYY-MM-DD); confidence is 0 to 1."}},"additionalProperties":false}}],"scan":{"score":87,"grade":"A","scanned_at":"2026-09-20T00:23:52.791Z","report":{"scannerVersion":"0.1.9","scannedAt":"2026-09-20T00:23:52.789Z","components":{"code":{"score":-1,"max":25,"notes":["remote-only server, no package to scan"]},"reliability":{"score":20,"max":20,"notes":["remote reachable in 345ms"]},"poisoning":{"score":15,"max":15,"notes":["6 tool descriptions checked"]},"auth":{"score":10,"max":15,"notes":["open endpoint, read-only tools"]},"maintenance":{"score":15,"max":15,"notes":["last push 0 days ago"]},"identity":{"score":5,"max":10,"notes":["namespace and repository owner differ","website matches verified namespace"]}},"findings":[],"inputs":{"probes":[{"url":"https://mcp.moltlinestudio.com/recall","reachable":true,"authRequired":false,"latencyMs":345,"serverInfo":{"name":"moltline-recall","version":"1.1.0"}}],"packages":[],"repo":{"found":true,"owner":"GarphenGate","repo":"moltline-mcp","archived":false,"pushedAt":"2026-09-19T15:00:29Z","stars":0,"forks":0,"openIssues":0,"ownerType":"User","ownerAvatarUrl":"https://avatars.githubusercontent.com/u/316633241?v=4","ownerCreatedAt":"2026-08-13T15:17:26Z","license":"MIT"},"icon":{"url":"https://moltlinestudio.com/icon-192.png","source":"registry","width":192,"height":192},"presence":{"stars":0,"forks":0,"downloadsWeek":null,"license":"MIT","lastPushAt":"2026-09-19T15:00:29.000Z","score":23}}}},"grade_history":[],"reviews":[]}