@nesso-how/mcp 0.1.0-alpha.40 → 0.2.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -70,11 +70,6 @@ export declare const buildGraphInputSchema: z.ZodObject<{
|
|
|
70
70
|
text: z.ZodString;
|
|
71
71
|
elaboration: z.ZodOptional<z.ZodObject<{
|
|
72
72
|
definition: z.ZodString;
|
|
73
|
-
examples: z.ZodString;
|
|
74
|
-
notes: z.ZodString;
|
|
75
|
-
imageUrl: z.ZodOptional<z.ZodString>;
|
|
76
|
-
imageTitle: z.ZodOptional<z.ZodString>;
|
|
77
|
-
imageDescriptionUrl: z.ZodOptional<z.ZodString>;
|
|
78
73
|
}, z.core.$strip>>;
|
|
79
74
|
}, z.core.$strip>]>>;
|
|
80
75
|
relations: z.ZodArray<z.ZodObject<{
|
package/dist/lib/graph-tools.js
CHANGED
|
@@ -4,11 +4,6 @@ import * as z from 'zod/v4';
|
|
|
4
4
|
import { deserialize, serialize, VOCABULARY, RELATION_TYPE_VALUES, } from '@nesso-how/vocab-learning';
|
|
5
5
|
const elaborationSchema = z.object({
|
|
6
6
|
definition: z.string(),
|
|
7
|
-
examples: z.string(),
|
|
8
|
-
notes: z.string(),
|
|
9
|
-
imageUrl: z.string().optional(),
|
|
10
|
-
imageTitle: z.string().optional(),
|
|
11
|
-
imageDescriptionUrl: z.string().optional(),
|
|
12
7
|
});
|
|
13
8
|
export const relationTypeEnum = z.enum(RELATION_TYPE_VALUES);
|
|
14
9
|
const conceptInputSchema = z.union([
|
|
@@ -4,19 +4,19 @@
|
|
|
4
4
|
"slug": "faq",
|
|
5
5
|
"title": "FAQ",
|
|
6
6
|
"description": "Common conceptual questions about privacy, the web/desktop split, and the AI mentor.",
|
|
7
|
-
"markdown": "## Is my data private?\n\nGraph content (concepts, definitions,
|
|
7
|
+
"markdown": "## Is my data private?\n\nGraph content (concepts, definitions, relation structure) and review progress (FSRS stability, ratings, due dates) are stored locally, in IndexedDB on the web app or as plain JSON files on disk for the desktop app, and never leave your device. Mentor chat history lives only in memory for the current panel session, and AI endpoint API keys are stored locally and sent only to the endpoint you configured.\n\nThe only things that can leave your device:\n\n- **AI mentor prompts and chat history**, if you enable the mentor with a remote endpoint. A local Ollama endpoint sends nothing off your machine.\n- **Opt-in telemetry**, off by default.\n- **The desktop app's version check** against GitHub Releases, a plain request that carries no graph or usage data.\n\n## What changes between the web app and the desktop app?\n\n| Area | Web | Desktop |\n| --------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Graph storage | IndexedDB only | Plain JSON files on disk (authoritative); IndexedDB mirrors the active project |\n| Projects | Single implicit workspace, no switching | Multiple named project folders: create, open, switch, remove |\n| File import/export | File System Access API or browser download | Native save/open dialogs |\n| Native app menu | None | A real File/Edit/View/Window/Help menu bar |\n| Auto-update | Not applicable | Checks GitHub Releases on launch, can install and relaunch |\n| External file changes | Not applicable | A file watcher detects edits made outside the app (see [Troubleshooting](../troubleshooting/#this-graph-was-changed-on-disk-while-you-were-editing)) |\n\nEverything else, the canvas, the Inspector, Review, and the AI mentor, works the same on both.\n\n## Why does the AI mentor need an API key?\n\nIt doesn't, if you run a model locally. The default setup points at [Ollama](https://ollama.com/) on `http://localhost:11434/v1`, which needs no key. An API key is only required when you point the mentor at a hosted provider that authenticates requests (most OpenAI-compatible APIs); Nesso sends it as a bearer token to that endpoint only, never anywhere else. See [AI mentor](../guides/ai-mentor/#connecting-a-model).\n\n## Where do I report a bug or request a feature?\n\nOpen an issue on [GitHub](https://github.com/nesso-how/nesso/issues). The code is MIT-licensed and contributions are welcome."
|
|
8
8
|
},
|
|
9
9
|
{
|
|
10
10
|
"slug": "guides/ai-mentor",
|
|
11
11
|
"title": "AI mentor (Socrates)",
|
|
12
12
|
"description": "How the Socratic mentor works, connecting a model, persona, and graph-aware context.",
|
|
13
|
-
"markdown": "The Socratic mentor is **experimental** and **off by default**. Enable it under **Settings → AI** with the **Mentor** toggle. While off, **Socrates** is hidden from the status bar.\n\nWhen enabled, click **Socrates** in the **status bar** (bottom-left) to start a dialogue. The mentor reads your current graph and selection, and replies with **questions rather than explanations**. The goal is to surface what you understand and where the gaps are.\n\n:::note\nFor good results, use at least a 7–8B model. `qwen3:14b` is a strong default; `llama3.3:70b` for higher quality if your hardware allows. For hosted endpoints, model names change fast, so pick any capable instruction-following model from your preferred provider.\n:::\n\n## How it works\n\nEvery send rebuilds a system prompt from the live store: a snapshot of up to ~60 concept nodes, sorted weakest-first via **`nodeStrength()`** ([`context.ts`](https://github.com/nesso-how/nesso/blob/main/src/llm/context.ts)): **FSRS stability** dominates ordering, **Again/Hard** nudge weaker items up, overdue is only a slight tie-break. Each node line lists stability (`s=` days), days since last review, last FSRS rating, and `DUE` when the scheduler says so, plus typed edges (~2× the node allowance), current selection when any, and focal-neighbour context when a node is selected (`Focus:` / `Related:` lines). The conversation history stays in the mentor card and is reset when you switch graphs or click **New chat**.\n\nChat history is **not persisted**. It lives only for the current panel session.\n\n## Connecting a model\n\nConfigure any OpenAI-compatible `chat/completions` endpoint under **Settings → AI**: base URL, model, and an optional API key. Endpoint fields appear only while the mentor toggle is on.\n\nThe default targets a local [Ollama](https://ollama.com/) instance (`http://localhost:11434/v1`, model `gemma3:4b`). Install Ollama, pull a model, and the mentor works with nothing leaving your machine.
|
|
13
|
+
"markdown": "The Socratic mentor is **experimental** and **off by default**. Enable it under **Settings → AI** with the **Mentor** toggle. While off, **Socrates** is hidden from the status bar.\n\nWhen enabled, click **Socrates** in the **status bar** (bottom-left) to start a dialogue. The mentor reads your current graph and selection, and replies with **questions rather than explanations**. The goal is to surface what you understand and where the gaps are.\n\n:::note\nFor good results, use at least a 7–8B model. `qwen3:14b` is a strong default; `llama3.3:70b` for higher quality if your hardware allows. For hosted endpoints, model names change fast, so pick any capable instruction-following model from your preferred provider.\n:::\n\n## How it works\n\nEvery send rebuilds a system prompt from the live store: a snapshot of up to ~60 concept nodes, sorted weakest-first via **`nodeStrength()`** ([`context.ts`](https://github.com/nesso-how/nesso/blob/main/src/llm/context.ts)): **FSRS stability** dominates ordering, **Again/Hard** nudge weaker items up, overdue is only a slight tie-break. Each node line lists stability (`s=` days), days since last review, last FSRS rating, and `DUE` when the scheduler says so, plus typed edges (~2× the node allowance), current selection when any, and focal-neighbour context when a node is selected (`Focus:` / `Related:` lines). The conversation history stays in the mentor card and is reset when you switch graphs or click **New chat**.\n\nChat history is **not persisted**. It lives only for the current panel session.\n\n## Connecting a model\n\nConfigure any OpenAI-compatible `chat/completions` endpoint under **Settings → AI**: base URL, model, and an optional API key. Endpoint fields appear only while the mentor toggle is on.\n\nThe desktop app uses Tauri's native HTTP client for mentor requests. It supports any `https://` endpoint, including hosted providers such as OpenCode Zen at `https://opencode.ai/zen/v1` with model `big-pickle`. It also supports loopback HTTP endpoints at `localhost`, `127.0.0.1`, and `::1` for local Ollama. Arbitrary non-loopback `http://` endpoints are not permitted by the desktop capability.\n\nThe browser app keeps using the browser's normal `fetch`. Hosted endpoints must allow the app's origin, and browser requests to local Ollama still need the Ollama CORS setting described below. Nesso sends an optional API key as `Authorization: Bearer …` only to the configured endpoint and does not log it.\n\nThe default targets a local [Ollama](https://ollama.com/) instance (`http://localhost:11434/v1`, model `gemma3:4b`). Install Ollama, pull a model, and the mentor works with nothing leaving your machine. Set the API key expected by a hosted endpoint when one is required.\n\nUntil a reachable endpoint is configured, the chat input stays disabled and the mentor shows a short setup hint. If the mentor stops responding once a turn fails, see [Troubleshooting](../../troubleshooting/#mentor-not-responding).\n\n### Endpoint status\n\nWhile the AI tab is open in **Settings**, Nesso calls the `/models` endpoint of your configured base URL and shows the result inline:\n\n| Status | Meaning |\n| --------------------- | -------------------------------------------------------------------------------------------------- |\n| **Checking…** | Nesso is querying `/models` — shows a spinner until the first response arrives. |\n| **Available** | The model is present in the endpoint's model list. The mentor can start. |\n| **Not found locally** | The endpoint is reachable but the model is not installed. On localhost, a **Pull** button appears. |\n| **Pulling `NN`%** | A native Ollama pull is in progress for the current model (local endpoints only). |\n| **Unauthorized** | The endpoint returned HTTP `401` or `403` — wrong or missing API key. |\n| **API unreachable** | The endpoint did not respond (wrong URL, server down, or network failure). |\n\nThe status resets to idle when the dialog closes or the mentor toggle is turned off. Changing the base URL, model, or API key triggers a fresh check and cancels any in-flight pull.\n\n### Pulling a model from Ollama\n\nWhen the endpoint is a `localhost`-based Ollama instance and the model is **Not found locally**, click **Pull** to download it. Progress is streamed in real time, and the status switches to **Available** on success. If the pull fails mid-way, the status shows **API unreachable**.\n\nPulls are local-only: the pull button appears only for loopback URLs (`localhost`, `127.0.0.1`, `::1`) because it calls the Ollama-native `/api/pull` endpoint. For hosted providers, pull models through their own tools or dashboard.\n\nClosing the **Settings** dialog, disabling the **Mentor** toggle, or changing the model while a pull is running aborts it immediately.\n\n### Reaching local Ollama from the hosted app\n\nIf you use the hosted web app over HTTPS, requests to `http://localhost:11434` are allowed by the browser, but Ollama still rejects the cross-origin request unless you allow the app's origin. Start it with `OLLAMA_ORIGINS=https://app.nesso.how` or use the desktop build, whose native transport does not require this browser CORS setting.\n\n## The Socratic persona\n\nThe system prompt (`getMentorBase` in [`MentorPanel.tsx`](https://github.com/nesso-how/nesso/blob/main/src/components/mentor/MentorPanel.tsx)) shapes Socrates:\n\n- One short question per turn by default, explaining only enough to frame it.\n- Replies are soft-capped at ~200 words (hard cap via output tokens).\n- No graph edits proposed in dialogue. Socrates probes; the user edits.\n- No emojis, flattery, JSON, or pseudo-graph markup. Sparse `*asterisks*` on key terms.\n- Replies in the active UI language (English or Italian). Snapshot tokens stay **English-shaped** (`s=…d`, `…d since review`, etc.), with the same spelling in the legend for every locale.\n\nIf you want a more permissive coach, fork the persona. It is plain text in the component and easy to swap.\n\n## Opening message\n\nWhen the panel opens, the mentor sends itself a short synthetic **user** turn so its first message reflects what's selected:\n\n- **A concept node selected:** opens on that concept and one of its relations.\n- **An edge selected (no node):** opens on the typed relation between its endpoints.\n- **Nothing selected:** opens on a weak spot in the graph (low stability plus weak **last reviews** (Again/Hard or a long gap); **DUE** is extra scheduler context).\n\nClick **New chat** in the header to reset history and request a fresh opener.\n\n## Context size\n\nLarge graphs are summarised, not truncated abruptly. The weakest-reviewed nodes appear first (`nodeStrength`), so the verbatim slice emphasises instability and risky last ratings; tail nodes are omitted with a short count only. Edges have a ~2x allowance over node count. These limits live in [`MentorPanel.tsx`](https://github.com/nesso-how/nesso/blob/main/src/components/mentor/MentorPanel.tsx) as `MAX_SNAPSHOT_NODES` and `MAX_SNAPSHOT_EDGES`."
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
16
|
"slug": "guides/building-a-graph",
|
|
17
17
|
"title": "Building a graph",
|
|
18
|
-
"description": "How to add concepts, draw typed relations, and use the Inspector to enrich nodes with definitions
|
|
19
|
-
"markdown": "The canvas is the centre of Nesso. **Concepts** are nodes and **typed relations** are edges. The **Inspector** is the right-hand panel where you enrich whatever you've got selected.\n\n## Adding concepts\n\n- **Double-click** empty canvas to add a concept at the pointer.\n- **`N`** adds a concept at the viewport centre.\n- **Right-click** empty canvas and choose **Add concept here** to add one at the cursor.\n- New concepts open in edit mode with the text input focused. Start typing immediately. Press `Enter` to commit, `Esc` to cancel.\n- **Double-click** a concept to rename it inline.\n\nAn empty graph shows a centered **\"Your first concept\"** hint, but the double-click still works through it.\n\n## Drawing relations\n\nDrag from a node
|
|
18
|
+
"description": "How to add concepts, draw typed relations, and use the Inspector to enrich nodes with definitions.",
|
|
19
|
+
"markdown": "The canvas is the centre of Nesso. **Concepts** are nodes and **typed relations** are edges. The **Inspector** is the right-hand panel where you enrich whatever you've got selected.\n\n## Adding concepts\n\n- **Double-click** empty canvas to add a concept at the pointer.\n- **`N`** adds a concept at the viewport centre.\n- **Right-click** empty canvas and choose **Add concept here** to add one at the cursor.\n- New concepts open in edit mode with the text input focused. Start typing immediately. Press `Enter` to commit, `Esc` to cancel.\n- **Double-click** a concept to rename it inline.\n\nAn empty graph shows a centered **\"Your first concept\"** hint, but the double-click still works through it.\n\n## Drawing relations\n\nDrag from either visible connection dot on a node to another node. The node where you start is the source and the node where you release is the target, so the relation picker follows the direction of your gesture. The usual path is the right edge (`out`) to the other node's left edge (`in`). On release, a **relation picker** opens, grouped by category. Pick the relation type and the edge is created.\n\n- The connection line previews with the same quadratic geometry the final edge uses.\n- Edge type can be changed any time from the Inspector when an edge is selected.\n\nSee the [relation types reference](../../reference/relation-types/) for the full list, semantic meaning, and type properties. Each type has a category colour and an SVG glyph, both defined in `@nesso-how/vocab-learning`. Edge encoding density is under [Display options](#display-options-sidebar) below.\n\n## Selecting and editing\n\n- **Click** a node or edge to select it. The Inspector reflects the selection.\n- **Hold `⌘` / `Ctrl` and click** to toggle additional items into the selection.\n- **Drag on empty canvas** to marquee-select multiple items.\n- **`⌘A` / `Ctrl+A`** selects every concept and relation in the graph.\n- **Right-click** a concept, relation, or empty canvas for a context menu of the relevant actions (copy/cut/duplicate/delete a concept; flip / delete a relation; paste / add concept / center·fit on the canvas). To change a relation's type, select the edge and pick a new type in the Inspector.\n- **`Del`** or **`Backspace`** deletes the selection (one relation, one concept, or every concept in a marquee). Edges attached to a deleted concept go with it. Delete is also on the right-click menu and the Inspector's action toolbar.\n- **`⌘C` / `Ctrl+C`** copies the selection. Copying concepts also copies relations between them; copying a relation includes its two endpoints. **`⌘X` / `Ctrl+X`** cuts: it copies the selection and removes it in one step. **`⌘V` / `Ctrl+V`** pastes the clipboard with a small offset (right-click **Paste** drops it at the cursor instead). **`⌘D` / `Ctrl+D`** duplicates the selection in place without touching the clipboard. These also live on the right-click menu and the Inspector toolbar.\n- **Arrow keys** nudge a selected concept, and **Shift + arrows** move it in larger steps.\n- **`⌘Z` / `Ctrl+Z`** undoes structural edits; **`⌘⇧Z` / `Ctrl+Shift+Z`** redoes. History has 50 steps and resets when you switch or import a graph.\n\n## The Inspector\n\nThe Inspector docks on the **right**, full height between the top bar and the status bar. Its header has a **collapse** control that shrinks it to a slim **rail** (keeping the selection plus a vertical action toolbar) and a **close** control. A docked bottom **action toolbar** offers copy / cut / duplicate / delete for a concept, or flip / delete for a relation.\n\nWhen a concept is selected it shows, top to bottom:\n\n- **Memory** _(collapsible):_ the FSRS schedule, read-only: when due, stability (in days), last self-rating, review count (with lapses), and time since the last review.\n- **Definition**: see below.\n- **Relations** _(collapsible):_ outgoing and incoming edges, each connected concept shown with the relation glyph in a chip and the type on the right (incoming dimmed). Click a row to jump to that concept. Change a relation's type by selecting the edge.\n\nWhen an edge is selected, the Inspector shows the relation as a chip with its category colour and a dropdown of every relation type. Picking a new type updates the edge in place. The graph keeps its endpoints and identity.\n\n### Definition field\n\nA single free-text field that travels with the concept and feeds both the AI mentor and [Review](../../guides/review-mode/):\n\n- **Definition:** a one-sentence-ish explanation in your own words.\n\nIn Review, the definition appears when you **Reveal** a card so you can check your recall. The AI mentor uses the definition in its graph snapshot and focal-neighbour context when a concept is selected.\n\n## Display options (sidebar)\n\n**Sidebar → Display** controls how the **active graph** is rendered: heatmap overlay, edge encoding density, curve style, and auto flip. Choices are saved **with the graph** in IndexedDB (and included in JSON export). New graphs start from the app defaults until you change them.\n\nWhen **Display → Curve** is set to **Arc**, **Auto flip** (on by default) bends relations toward the side that avoids overlapping nodes, flipping when the target is above the source on the right, or below on the left, and updates live while you drag concepts. **Flip curve** in the Inspector is **Off | Auto | On** while auto flip is on: **Auto** follows layout, **Off** / **On** pin a manual bend on that edge. With auto flip off for that graph, the control is **Off | On** only."
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
22
|
"slug": "guides/embedding-graphs",
|
|
@@ -34,19 +34,19 @@
|
|
|
34
34
|
"slug": "guides/graph-management",
|
|
35
35
|
"title": "Graph management",
|
|
36
36
|
"description": "Working with multiple graphs, exporting and importing JSON, and desktop project folders.",
|
|
37
|
-
"markdown": "A **graph** is one map: its concepts, relations, and display settings. You can keep several graphs and switch between them, export or import any of them as JSON, and, on desktop, group graphs into project folders.\n\n## Multiple graphs\n\nThe **Sidebar** lists every graph in the current project. Click a graph to switch to it: the canvas, Inspector, and Review queue all follow.\n\n- **Rename**: double-click a graph's row in the list, type the new name, `Enter` to commit.\n- **Delete**: hover a row and click the trash icon. You're asked to confirm. Deleting also removes its file from the project folder on desktop. The last remaining graph can't be deleted, so the delete action is hidden when only one graph is left.\n- **New graph**: the **New** button above the list creates an empty graph and switches to it immediately.\n\nSwitching graphs flushes any pending autosave on the one you're leaving, so edits made just before a switch aren't lost.\n\n## Export and import (JSON)\n\nOpen the **⋯** menu in the top bar (tooltip: \"Export · Import · Shortcuts\") for:\n\n- **Export graph**: saves the active graph as a `.json` file named after the graph.\n- **Export graph (.png)**: renders the canvas at 1920×1200 and saves it as an image, with React Flow's selection handles excluded from the render.\n- **Import graph**: opens a file picker for a `.json` file and adds it as a new graph.\n\nExport behaves differently depending on platform:\n\n- **Desktop**: a native save dialog lets you pick the destination.\n- **Web**: if your browser supports the File System Access API, you get a save dialog and can overwrite the same file on repeat exports. Otherwise it falls back to a normal browser download.\n\nImporting a file that isn't a valid Nesso graph shows an error toast and imports nothing. A successful import creates a new graph (de-duplicating its name against your existing graphs) and switches to it.\n\nExported JSON carries graph **content** only: concepts, relations, and display settings. Personal review progress (FSRS data) is never included, so sharing or re-importing a file never carries someone else's recall history.\n\n## Desktop projects\n\nOn the desktop app, graphs live inside **project folders**: plain directories on disk holding one JSON file per graph plus a small manifest. The **Projects** section in the sidebar (desktop only) lists every folder you've opened and lets you switch between them.\n\n- **Add project**: the **+** button opens a native folder picker. Pick an existing project folder, or create a new one from the dialog's \"New Folder\" button (macOS). The selected folder becomes the active project.\n- **Switch project**: click any project in the list. The current graph is saved first, then the target folder's graphs load.\n- **Remove project**: hover a project and click the trash icon, then confirm. This only removes it from Nesso's list. Its files stay on disk untouched. You can't remove the last project in the list.\n- **Reveal in Finder**: hover a project and click the folder icon to reveal it in the system file manager.\n\nIf a project folder is moved, renamed, or deleted outside the app, it stays in the list marked as missing (greyed out, with a \"not found\" label) rather than disappearing. Switching away from a missing project happens automatically. Switching back works again once the folder reappears at the same path. Only the trash icon removes it from the list for good.\n\n:::caution\nNative folder pickers and the system menu bar are desktop-only Tauri APIs. None of this section applies to the web app, which has a single implicit workspace backed by IndexedDB. See [FAQ](../../faq/#what-changes-between-the-web-app-and-the-desktop-app) for the full web/desktop comparison.\n:::"
|
|
37
|
+
"markdown": "A **graph** is one map: its concepts, relations, and display settings. You can keep several graphs and switch between them, export or import any of them as JSON, and, on desktop, group graphs into project folders.\n\n## Multiple graphs\n\nThe **Sidebar** lists every graph in the current project. Click a graph to switch to it: the canvas, Inspector, and Review queue all follow.\n\n- **Rename**: double-click a graph's row in the list, type the new name, `Enter` to commit.\n- **Delete**: hover a row and click the trash icon. You're asked to confirm. Deleting also removes its file from the project folder on desktop. The last remaining graph can't be deleted, so the delete action is hidden when only one graph is left.\n- **New graph**: the **New** button above the list creates an empty graph and switches to it immediately.\n\nSwitching graphs flushes any pending autosave on the one you're leaving, so edits made just before a switch aren't lost.\n\n## Export and import (JSON)\n\nOpen the **⋯** menu in the top bar (tooltip: \"Export · Import · Shortcuts\") for:\n\n- **Export graph**: saves the active graph as a `.json` file named after the graph.\n- **Export graph (.png)**: renders the canvas at 1920×1200 and saves it as an image, with React Flow's selection handles excluded from the render.\n- **Import graph**: opens a file picker for a `.json` file and adds it as a new graph.\n\nExport behaves differently depending on platform:\n\n- **Desktop**: a native save dialog lets you pick the destination.\n- **Web**: if your browser supports the File System Access API, you get a save dialog and can overwrite the same file on repeat exports. Otherwise it falls back to a normal browser download.\n\nImporting a file that isn't a valid Nesso graph shows an error toast and imports nothing. A successful import creates a new graph (de-duplicating its name against your existing graphs) and switches to it.\n\nExported JSON carries graph **content** only: concepts, relations, and display settings. Personal review progress (FSRS data) is never included, so sharing or re-importing a file never carries someone else's recall history.\n\n## File compatibility\n\nNesso graph files carry separate envelope and vocabulary versions. When you\nimport a file or open a desktop project, released older beta formats are\nupgraded through sequential compatibility steps. A file created by a newer\nunsupported Nesso version is rejected so its data is not interpreted\nincorrectly.\n\nThe first supported baseline is the definition-only graph shape introduced\nbefore `0.2.0-beta.0`. Earlier alpha-only `examples`, `notes`, and image\nfields are not migrated. Review scheduling state is stored separately and is\nnot included in exported graph files.\n\n## Desktop projects\n\nOn the desktop app, graphs live inside **project folders**: plain directories on disk holding one JSON file per graph plus a small manifest. The **Projects** section in the sidebar (desktop only) lists every folder you've opened and lets you switch between them.\n\n- **Add project**: the **+** button opens a native folder picker. Pick an existing project folder, or create a new one from the dialog's \"New Folder\" button (macOS). The selected folder becomes the active project.\n- **Switch project**: click any project in the list. The current graph is saved first, then the target folder's graphs load.\n- **Remove project**: hover a project and click the trash icon, then confirm. This only removes it from Nesso's list. Its files stay on disk untouched. You can't remove the last project in the list.\n- **Reveal in Finder**: hover a project and click the folder icon to reveal it in the system file manager.\n\nIf a project folder is moved, renamed, or deleted outside the app, it stays in the list marked as missing (greyed out, with a \"not found\" label) rather than disappearing. Switching away from a missing project happens automatically. Switching back works again once the folder reappears at the same path. Only the trash icon removes it from the list for good.\n\nIf every file in a project folder uses a vocabulary or format version that this release of Nesso cannot read, the project is blocked: Nesso does not switch to it, does not create new files inside it, and does not overwrite any of the unsupported files. A banner explains what happened, and the previous project stays active. See [Troubleshooting](../../troubleshooting/#unsupported-project-files-desktop) for recovery steps.\n\n:::caution\nNative folder pickers and the system menu bar are desktop-only Tauri APIs. None of this section applies to the web app, which has a single implicit workspace backed by IndexedDB. See [FAQ](../../faq/#what-changes-between-the-web-app-and-the-desktop-app) for the full web/desktop comparison.\n:::"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
"slug": "guides/mcp",
|
|
41
41
|
"title": "MCP",
|
|
42
42
|
"description": "Connect Nesso to Claude, Cursor, or any MCP-compatible AI client.",
|
|
43
|
-
"markdown": "The `@nesso-how/mcp` package is a [Model Context Protocol](https://modelcontextprotocol.io/) server that gives AI clients access to Nesso documentation, the full relation-type vocabulary, and tools to **build** and **validate** graph documents. Once connected, models can answer questions about how Nesso works, produce importable graph JSON, and check files before writing them back to disk.\n\n## Setup\n\n### Claude Desktop\n\nOpen `claude_desktop_config.json`. On macOS it lives at `~/Library/Application Support/Claude/claude_desktop_config.json`; on Windows at `%APPDATA%\\Claude\\claude_desktop_config.json`.\n\nAdd a `nesso` entry under `mcpServers`:\n\n```json\n{\n \"mcpServers\": {\n \"nesso\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@nesso-how/mcp\"]\n }\n }\n}\n```\n\nSave the file and restart Claude Desktop. The Nesso tools will be available to the model automatically.\n\n### Cursor\n\nOpen **Settings -> MCP** and add a new server with command `npx` and args `[\"-y\", \"@nesso-how/mcp\"]`.\n\n### Other MCP clients\n\nAny client that speaks the stdio MCP transport works. Run `npx -y @nesso-how/mcp` as the server command. No other configuration is required.\n\n## What it can do\n\nOnce connected, you can ask your AI client things like:\n\n- \"What relation types does Nesso support?\" (uses `get_relation_types`)\n- \"Show me the Nesso getting started guide\" (uses `get_nesso_docs`)\n- \"Build a graph about photosynthesis with causes and enables relations\" (uses `build_graph`)\n- \"Validate this graph JSON before I save it\" (uses `validate_graph`)\n\nThe MCP server is **stateless** and does not read or write files. Your client uses its own filesystem tools to read `.json` graph files, passes the contents inline to `validate_graph` or `build_graph`, and writes the result back. Nesso picks up external edits through its normal workspace sync.\n\n### Agent workflow for graph files\n\nA typical end-to-end flow when the client has filesystem access:\n\n1. **Read** the target graph `.json` from the project folder (client filesystem tool).\n2. **Validate** with `validate_graph`. Fix any `errors` before saving. Review `warnings` (e.g. missing
|
|
43
|
+
"markdown": "The `@nesso-how/mcp` package is a [Model Context Protocol](https://modelcontextprotocol.io/) server that gives AI clients access to Nesso documentation, the full relation-type vocabulary, and tools to **build** and **validate** graph documents. Once connected, models can answer questions about how Nesso works, produce importable graph JSON, and check files before writing them back to disk.\n\n## Setup\n\n### Claude Desktop\n\nOpen `claude_desktop_config.json`. On macOS it lives at `~/Library/Application Support/Claude/claude_desktop_config.json`; on Windows at `%APPDATA%\\Claude\\claude_desktop_config.json`.\n\nAdd a `nesso` entry under `mcpServers`:\n\n```json\n{\n \"mcpServers\": {\n \"nesso\": {\n \"command\": \"npx\",\n \"args\": [\"-y\", \"@nesso-how/mcp\"]\n }\n }\n}\n```\n\nSave the file and restart Claude Desktop. The Nesso tools will be available to the model automatically.\n\n### Cursor\n\nOpen **Settings -> MCP** and add a new server with command `npx` and args `[\"-y\", \"@nesso-how/mcp\"]`.\n\n### Other MCP clients\n\nAny client that speaks the stdio MCP transport works. Run `npx -y @nesso-how/mcp` as the server command. No other configuration is required.\n\n## What it can do\n\nOnce connected, you can ask your AI client things like:\n\n- \"What relation types does Nesso support?\" (uses `get_relation_types`)\n- \"Show me the Nesso getting started guide\" (uses `get_nesso_docs`)\n- \"Build a graph about photosynthesis with causes and enables relations\" (uses `build_graph`)\n- \"Validate this graph JSON before I save it\" (uses `validate_graph`)\n\nThe MCP server is **stateless** and does not read or write files. Your client uses its own filesystem tools to read `.json` graph files, passes the contents inline to `validate_graph` or `build_graph`, and writes the result back. Nesso picks up external edits through its normal workspace sync.\n\n### Agent workflow for graph files\n\nA typical end-to-end flow when the client has filesystem access:\n\n1. **Read** the target graph `.json` from the project folder (client filesystem tool).\n2. **Validate** with `validate_graph`. Fix any `errors` before saving; missing or foreign `vocabulary` is a hard error that rejects the file. Review `warnings` (e.g. a missing relation `type`).\n3. **Build or extend** with `build_graph` when creating a new graph from structured concepts and relations: the tool assigns ids, vocabulary metadata, valid relation types, and layout positions.\n4. **Re-validate** the output with `validate_graph` if the client edited the JSON by hand.\n5. **Write** the JSON back to disk (client filesystem tool). Open or sync the graph in Nesso.\n\nExample prompt:\n\n> Read `graphs/biology.json` in this workspace, validate it with Nesso MCP, then use `build_graph` to add concepts \"Chloroplast\" and \"Glucose\" linked by `produces`, merge the result, re-validate, and write the file back.\n\nSee [MCP tools](../../reference/mcp-tools/) for the full tool reference."
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
"slug": "guides/review-mode",
|
|
47
47
|
"title": "Review mode",
|
|
48
48
|
"description": "Spaced-repetition review of your concepts with FSRS, how it queues cards and reschedules them from your self-ratings.",
|
|
49
|
-
"markdown": "Press `R` (or open the **Review** pill in the top bar) to start a focused study session. Review surfaces concepts that are due, prompts you to recall what you know, and reschedules them based on how you self-rate.\n\nNesso uses [FSRS](https://github.com/open-spaced-repetition/ts-fsrs), a modern open-source successor to the SM-2 / Anki algorithm.\n\n## What gets reviewed\n\nEach concept node carries its own FSRS state: `stability`, `difficulty`, `due`, `lastReview`, `lastRating`, and friends. A node is **due** when `due <= now`. New, unrated concepts default to `due = 0`, which means they show up immediately the first time you open Review.\n\nThe session queue is built fresh every time you open the overlay: all due nodes, sorted by urgency, in random order within the same due bucket.\n\n## Flow\n\nFor each due concept, Review:\n\n1. **Shows the concept title** and a short recall prompt. Try to remember its definition
|
|
49
|
+
"markdown": "Press `R` (or open the **Review** pill in the top bar) to start a focused study session. Review surfaces concepts that are due, prompts you to recall what you know, and reschedules them based on how you self-rate.\n\nNesso uses [FSRS](https://github.com/open-spaced-repetition/ts-fsrs), a modern open-source successor to the SM-2 / Anki algorithm.\n\n## What gets reviewed\n\nEach concept node carries its own FSRS state: `stability`, `difficulty`, `due`, `lastReview`, `lastRating`, and friends. A node is **due** when `due <= now`. New, unrated concepts default to `due = 0`, which means they show up immediately the first time you open Review.\n\nThe session queue is built fresh every time you open the overlay: all due nodes, sorted by urgency, in random order within the same due bucket.\n\n## Daily reminder\n\nWhen a concept you have already studied becomes due, Nesso can show a reminder after you open its graph. The reminder appears at most once per local calendar day for each graph. New concepts do not trigger it, although they still join the normal queue when you choose **Start review**.\n\nClosing the reminder suppresses it for that graph for the rest of the day. **Start review** opens the same unfiltered Review session as the top-bar pill.\n\n## Flow\n\nFor each due concept, Review:\n\n1. **Shows the concept title** and a short recall prompt. Try to remember its definition and typed relations before revealing.\n2. **Waits for you to think**, then click **Reveal** (or press `Space`).\n3. **Reveals** the concept's definition and typed relations.\n4. **You rate** how it felt: `Again`, `Hard`, `Good`, `Easy`. Each button shows the **predicted next interval** under it (e.g. `5 min`, `2 hours`, `4 days`, `2 months`, localized to your language).\n\nFSRS then updates `stability` and `difficulty`, schedules the next `due` date, and Review advances to the next card. Done with the queue, the overlay closes. You're caught up.\n\n## Tuning FSRS\n\nUnder **Settings → Learning → Review**:\n\n| Setting | What it does | Range |\n| -------------------- | --------------------------------------------------------------------------------------------------------------------- | ----------- |\n| **Review reminder** | Shows a daily reminder when concepts you have studied are due. This can be disabled independently of **Review mode**. | On/off |\n| **Target retention** | Probability of correctly recalling a concept at its next review. Higher means more frequent reviews. | 70% to 97% |\n| **Max interval** | Longest interval FSRS can schedule, in days. Caps how far into the future a card can be pushed. | 1 to 36,500 |\n\nThe defaults (90% retention, 100-year cap) match the FSRS reference defaults. Lower the retention if you're comfortable forgetting more in exchange for fewer reviews. Raise the max interval if you want long-term cards to keep stretching out.\n\nReview is on by default. The **Review mode** toggle at the top of **Settings → Learning** turns it off entirely: the **Review** pill and the `R` shortcut disappear, and the FSRS settings above hide while it is off. The **Review reminder** toggle remains available independently, but reminders only appear while **Review mode** is enabled.\n\n## Tips\n\n- Add a **definition** in the Inspector. It appears on reveal and gives you something concrete to check your recall against.\n- Pair concepts with **at least one typed edge** before reviewing them. Relations are part of what you reveal and what makes the graph worth remembering.\n- The session count in the top bar reflects the original queue size. Cards rated `Again` that come back later increase the count past 100%. That is expected."
|
|
50
50
|
},
|
|
51
51
|
{
|
|
52
52
|
"slug": "introduction",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"slug": "reference/mcp-tools",
|
|
59
59
|
"title": "MCP tools",
|
|
60
60
|
"description": "Reference for the four tools exposed by the @nesso-how/mcp server.",
|
|
61
|
-
"markdown": "The `@nesso-how/mcp` server exposes four tools. See [MCP](../../guides/mcp/) for setup and workflow.\n\n### `get_nesso_docs`\n\nFetches documentation pages from this site. Call it without a `slug` to get a table of contents, or with a slug (e.g. `\"guides/getting-started\"`) to get the full page content.\n\n### `get_relation_types`\n\nReturns the complete list of relation types grouped by category id (`taxonomic`, `structural`, and so on from `RELATION_CATEGORIES` in `@nesso-how/vocab-learning`), with glyph, symmetry, and type properties (transitive, inverse, strength, polarity, cardinality). Use this whenever you need valid type names for graph JSON or explanations for the learner.\n\n### `validate_graph`\n\n**Input:** `{ \"graph\": \"<json string>\" }`: a Nesso graph document (`concepts[]`, `relations[]`), not runtime React Flow `nodes`/`edges`.\n\n**Output:** `{ \"valid\": boolean, \"errors\": [{ \"path\", \"message\" }], \"warnings\": [{ \"path\", \"message\" }] }`\n\nRuns envelope and vocabulary validation
|
|
61
|
+
"markdown": "The `@nesso-how/mcp` server exposes four tools. See [MCP](../../guides/mcp/) for setup and workflow.\n\n### `get_nesso_docs`\n\nFetches documentation pages from this site. Call it without a `slug` to get a table of contents, or with a slug (e.g. `\"guides/getting-started\"`) to get the full page content.\n\n### `get_relation_types`\n\nReturns the complete list of relation types grouped by category id (`taxonomic`, `structural`, and so on from `RELATION_CATEGORIES` in `@nesso-how/vocab-learning`), with glyph, symmetry, and type properties (transitive, inverse, strength, polarity, cardinality). Use this whenever you need valid type names for graph JSON or explanations for the learner.\n\n### `validate_graph`\n\n**Input:** `{ \"graph\": \"<json string>\" }`: a Nesso graph document (`concepts[]`, `relations[]`), not runtime React Flow `nodes`/`edges`.\n\n**Output:** `{ \"valid\": boolean, \"errors\": [{ \"path\", \"message\" }], \"warnings\": [{ \"path\", \"message\" }] }`\n\nRuns the same envelope and vocabulary validation used by the app: it accepts the\ncurrent protected baseline, rejects newer unsupported envelope versions, and\nrejects unsupported alpha elaboration fields. Also performs structural checks:\nduplicate ids, dangling relation endpoints, and unknown relation types.\n\n`valid` is `true` only when `errors` is empty. The tool returns diagnostics\nonly; it does not produce rewritten or migrated JSON.\n\n### `build_graph`\n\n**Input:**\n\n```json\n{\n \"name\": \"Photosynthesis\",\n \"concepts\": [\n \"Sunlight\",\n {\n \"text\": \"Chloroplast\",\n \"elaboration\": { \"definition\": \"...\" }\n }\n ],\n \"relations\": [{ \"from\": \"Sunlight\", \"to\": \"Chloroplast\", \"relation\": \"enables\" }]\n}\n```\n\n- `concepts`: label strings or objects with optional `id`, `text`, and `elaboration`.\n- `relations`: `from` / `to` match concept `id` or label (must be unambiguous); `relation` must be a valid type id from `get_relation_types`.\n\n**Output:** Pretty-printed graph document JSON ready to write to disk (includes `vocabulary`, generated ids, and dagre layout positions). FSRS review fields and React Flow edge shape (`type: \"nesso\"`, handles) are applied by the app on import, not stored in the file."
|
|
62
62
|
},
|
|
63
63
|
{
|
|
64
64
|
"slug": "reference/relation-types",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"slug": "troubleshooting",
|
|
71
71
|
"title": "Troubleshooting",
|
|
72
72
|
"description": "What to do when a banner, the mentor, or an update check doesn't behave as expected.",
|
|
73
|
-
"markdown": "## \"This graph was changed on disk while you were editing\"\n\n**When it appears**: desktop only. The file watcher noticed the active graph's JSON file changed outside the app (an external editor, a sync tool, another Nesso window) while you had unsaved edits in memory.\n\nThe banner offers two actions:\n\n- **Keep my changes**: writes your in-memory version to disk, overwriting the external change.\n- **Reload from disk**: discards your in-memory edits and loads the file as it now is on disk. Undo/redo history is cleared in the process.\n\nThere's no automatic merge: pick whichever side of the conflict you want to keep.\n\n## Auto-update problems (desktop)\n\nThe desktop app checks GitHub Releases once on launch. If checking fails (offline, GitHub unreachable), it stays silent: no banner, no error, just no update for now.\n\nOnce an update is found, the banner can show:\n\n- **Version `X` is available**: click **Install & restart** to download and apply it.\n- **Installing…**: download/install in progress; the button is disabled and there is no way to cancel.\n- **Update failed. Try again?**: the download or install step failed (e.g. lost connectivity mid-download). Click **Retry**.\n- **Update installed. Restart Nesso to finish**: the update was applied to disk, but the app couldn't relaunch itself automatically. Quit and reopen Nesso manually.\n\nYou can dismiss the available/error states for the rest of the session with the banner's close button; the install-in-progress state has no dismiss, since the install can't be cancelled once started.\n\n## Mentor not responding\n\nIf a mentor message fails, the reply bubble shows one of two messages, depending on what went wrong:\n\n- **Can't reach the AI endpoint. Check Settings (`⌘,`) → AI. For local Ollama, run `ollama serve`.** A network-level failure: the endpoint is unreachable, the wrong port, or
|
|
73
|
+
"markdown": "## \"This graph was changed on disk while you were editing\"\n\n**When it appears**: desktop only. The file watcher noticed the active graph's JSON file changed outside the app (an external editor, a sync tool, another Nesso window) while you had unsaved edits in memory.\n\nThe banner offers two actions:\n\n- **Keep my changes**: writes your in-memory version to disk, overwriting the external change.\n- **Reload from disk**: discards your in-memory edits and loads the file as it now is on disk. Undo/redo history is cleared in the process.\n\nThere's no automatic merge: pick whichever side of the conflict you want to keep.\n\n## Auto-update problems (desktop)\n\nThe desktop app checks GitHub Releases once on launch. If checking fails (offline, GitHub unreachable), it stays silent: no banner, no error, just no update for now.\n\nOnce an update is found, the banner can show:\n\n- **Version `X` is available**: click **Install & restart** to download and apply it.\n- **Installing…**: download/install in progress; the button is disabled and there is no way to cancel.\n- **Update failed. Try again?**: the download or install step failed (e.g. lost connectivity mid-download). Click **Retry**.\n- **Update installed. Restart Nesso to finish**: the update was applied to disk, but the app couldn't relaunch itself automatically. Quit and reopen Nesso manually.\n\nYou can dismiss the available/error states for the rest of the session with the banner's close button; the install-in-progress state has no dismiss, since the install can't be cancelled once started.\n\n## Unsupported project files (desktop)\n\nIf you open a project folder whose graph files come from a newer Nesso version or use an unknown vocabulary, Nesso blocks the project and shows a yellow info banner:\n\n> This project contains N file(s) not supported by this version of Nesso. Please update the app or remove the files manually.\n\n**What happens**: the project folder stays intact on disk. Nesso does not create new graphs inside it, does not overwrite any of the unsupported files, and does not switch to that project; the current (previously loaded) project remains active.\n\n**How to recover**:\n\n- **Update Nesso** if a newer release supports those files.\n- **Remove the unsupported files manually** from the project folder (Finder / File Explorer), then switch back to the project. Nesso will treat it as an empty project and seed one starter graph.\n- **Open a different project** from the sidebar; the blocked project stays in your list, greyed out, until you resolve it.\n\n## Mentor not responding\n\nIf a mentor message fails, the reply bubble shows one of two messages, depending on what went wrong:\n\n- **Can't reach the AI endpoint. Check Settings (`⌘,`) → AI. For local Ollama, run `ollama serve`.** A network-level failure: the endpoint is unreachable, the wrong port, or, on the hosted web app, a CORS rejection from a local Ollama instance. Confirm the base URL in **Settings → AI**, that Ollama or your server is actually running, and, if you're on the hosted web app talking to local Ollama, that you started it with `OLLAMA_ORIGINS` set to the app's origin (see [AI mentor](../guides/ai-mentor/#reaching-local-ollama-from-the-hosted-app)).\n- **_Hmm._ My voice failed me. Try again, slowly.** The endpoint was reachable but returned an error or a response Nesso couldn't parse. Check the model name and that the endpoint speaks the OpenAI-compatible `chat/completions` format.\n\nDesktop mentor requests use the native HTTP client. The desktop capability allows HTTPS and loopback HTTP only. If a desktop endpoint uses non-loopback `http://`, switch it to `https://` or configure a local service on `localhost`, `127.0.0.1`, or `::1`. Browser requests continue to follow normal browser CORS rules.\n\nClosing the mentor panel, switching graphs, or clicking **New chat** aborts any in-flight request without showing an error.\n\n## \"No AI endpoint configured\"\n\nThis isn't a failure: it's the mentor's resting state until you've set up an endpoint. It appears whenever **Mentor** is enabled in **Settings → AI** but the base URL or model field is empty. The input stays disabled until both are filled in. See [AI mentor](../guides/ai-mentor/#connecting-a-model) for setup.\n\n## Model pull stalls or shows stale results\n\nModel pulling is available only for local Ollama endpoints. When you click **Pull** in **Settings → AI**, Nesso streams the download progress from Ollama's `/api/pull` endpoint.\n\nIf a pull appears stuck:\n\n- **Changing settings cancels the pull.** Switching the model, base URL, or API key, disabling the mentor toggle, or closing the **Settings** dialog all abort the in-flight pull so stale progress cannot interfere with a new model selection.\n- **Ollama must be reachable on the native port.** Nesso strips the `/v1` suffix from your base URL to reach Ollama's native `/api/pull` endpoint. If you configured a non-standard port, make sure Ollama's native API is running on that same port.\n- **Progress is purely cosmetic.** The pull runs to completion regardless of whether the progress bar is visible. If the pull completes while you are on a different settings tab, the status badge updates when you return to the AI tab.\n\nIf the status shows **Unauthorized**, check your API key. The endpoint rejected the request with HTTP `401` or `403`. For hosted providers, make sure the key is valid and has not expired. Local Ollama instances do not require an API key; leave the field empty."
|
|
74
74
|
}
|
|
75
75
|
]
|
|
76
76
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nesso-how/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0-beta.0",
|
|
4
4
|
"description": "MCP server exposing Nesso knowledge graph tools to LLM clients",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -23,12 +23,13 @@
|
|
|
23
23
|
"dagre": "^0.8.5",
|
|
24
24
|
"zod": "^4.4.3",
|
|
25
25
|
"@modelcontextprotocol/server": "^2.0.0-alpha.2",
|
|
26
|
-
"@nesso-how/vocab-learning": "0.
|
|
26
|
+
"@nesso-how/vocab-learning": "0.2.0-beta.0"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/dagre": "^0.7.53",
|
|
30
30
|
"@types/node": "^22.0.0",
|
|
31
|
-
"typescript": "~5.8.3"
|
|
31
|
+
"typescript": "~5.8.3",
|
|
32
|
+
"@nesso-how/schema": "0.2.0-beta.0"
|
|
32
33
|
},
|
|
33
34
|
"scripts": {
|
|
34
35
|
"bundle-docs": "node scripts/bundle-starlight-docs.mjs",
|