Browse topics
RobinPath Overview
Storage API
Key-value storage scoped to your custom applet.
The Storage API provides simple key-value storage scoped to your applet. Each applet has its own isolated namespace - you cannot read or write another applet’s storage.
Capability required: storage:kv
Frontend (iframe)
import { createResourceClient } from "@rightplace/sdk";
const rp = createResourceClient();
await rp.ready();
// Set a value
await rp.storage.set("api_endpoint", "https://api.example.com");
// Get a value
const endpoint = await rp.storage.get("api_endpoint");
// → "https://api.example.com"
// Get a non-existent key
const missing = await rp.storage.get("not_here");
// → null
// List keys by prefix
await rp.storage.set("cache:page1", "...");
await rp.storage.set("cache:page2", "...");
await rp.storage.set("setting:theme", "dark");
const cacheKeys = await rp.storage.list("cache:");
// → ["cache:page1", "cache:page2"]
// Delete a key
await rp.storage.delete("cache:page1");
Backend (Node.js)
The same API is available in backend methods via the rp host object:
import { createResourceServer } from "@rightplace/sdk/server";
const server = createResourceServer({
methods: {
saveSettings: async (params, { rp }) => {
await rp.storage.set("settings", JSON.stringify(params));
return { ok: true };
},
loadSettings: async (_params, { rp }) => {
const raw = await rp.storage.get("settings");
return raw ? JSON.parse(raw) : {};
},
},
});
server.start();
MCP
A different storage tier is exposed to agents: the project’s object storage (files/folders), not the applet’s private key-value store. Use these tools for blob-style data; they all scope by resourceId.
| Tool | Purpose | Permission |
|---|---|---|
rightplace_storage_list | List objects with an optional prefix | storage:read |
rightplace_storage_get_object | Read one object (text or base64) | storage:read |
rightplace_storage_put_object | Write/overwrite one object | storage:write |
rightplace_storage_delete_object | Delete one object | storage:write |
rightplace_storage_delete_prefix | Delete everything under a prefix | storage:write |
rightplace_storage_create_folder | Create an empty folder marker | storage:write |
rightplace_storage_rename | Rename an object or prefix | storage:write |
The per-applet KV store (rp.storage.get/set) is NOT in MCP - it’s sandboxed to the iframe.
RobinPath Bridge
From a script, use dynamic MCP names on the rightplace module:
# List
rightplace.storage_list {resourceId: "res_abc", prefix: "cache/"} into $objects
for $o in $objects
log $o.key $o.size
endfor
# Write text
rightplace.storage_put_object {
resourceId: "res_abc",
key: "cache/report.txt",
body: "generated at 2026-04-19"
}
# Read
rightplace.storage_get_object {resourceId: "res_abc", key: "cache/report.txt"} into $obj
log $obj.body
# Delete
rightplace.storage_delete_prefix {resourceId: "res_abc", prefix: "cache/"}
API Reference
rp.storage.get(key)
| Parameter | Type | Description |
|---|---|---|
key | string | The key to retrieve |
| Returns | Promise<string | null> | The value, or null if not found |
rp.storage.set(key, value)
| Parameter | Type | Description |
|---|---|---|
key | string | The key to store |
value | string | The value to store |
| Returns | Promise<void> |
rp.storage.delete(key)
| Parameter | Type | Description |
|---|---|---|
key | string | The key to delete |
| Returns | Promise<void> |
rp.storage.list(prefix?)
| Parameter | Type | Description |
|---|---|---|
prefix | string (optional) | Filter keys by prefix |
| Returns | Promise<string[]> | Array of matching key names |
Manifest Configuration
{
"capabilities": [
"storage:kv"
]
}
Notes
- Values are strings only. To store objects, use
JSON.stringify()/JSON.parse(). - Storage persists across app restarts and applet updates.
- Storage is deleted when the applet is uninstalled.
- There is no size limit per key, but keep values reasonable (under 1MB).