You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Mirrors the in-repo docs/mcp.md update from JavaScriptSolidServer#497
and #498. Adds sections for the three new tools shipped in JSS 0.0.201
plus the Footguns section covering relative-vs-absolute WebID
resolution in write_acl agents.
Copy file name to clipboardExpand all lines: docs/features/mcp.md
+109-3Lines changed: 109 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -104,6 +104,83 @@ Both `SKILL.md` (Anthropic markdown format) and `SKILL.jsonld` (typed JSON-LD de
104
104
105
105
Pod-resident docs (`/docs/`, `/public/apps/<name>/docs/`) are reachable via the regular CRUD tools — no separate surface.
106
106
107
+
### ACL editing
108
+
109
+
The most common owner operation is delegating an agent access to a resource. The MCP server exposes ACL editing as first-class tools so bots don't need to hand-roll JSON-LD.
110
+
111
+
| Tool | Effect | WAC check |
112
+
|---|---|---|
113
+
|`read_acl`| Return the ACL for a resource as a structured list (agents, agentClasses, modes, isDefault) | Control on resource |
114
+
|`write_acl`| Persist a structured ACL to the resource's `.acl` file | Control on resource |
The structured form abstracts JSON-LD shape (`acl:agent` vs `acl:agentClass`, mode URI prefixes, `acl:default` propagation). New WAC vocabulary additions extend the structure without breaking existing bots.
135
+
136
+
**Safety**: `write_acl` refuses ACLs that would lock the caller out (no Control for the calling identity). This is the most common write_acl failure mode — typically caused by relative WebID paths in `agents` resolving against the .acl URL to a different absolute URI than the caller's actual WebID.
137
+
138
+
### Subscribe — live change notifications
139
+
140
+
`subscribe` is a streaming tool. The response switches to SSE (`text/event-stream`) and emits MCP notifications as resources change. WAC-filtered per event so subscribers only see resources they have Read access to.
141
+
142
+
| Tool | Effect |
143
+
|---|---|
144
+
|`subscribe`| Stream `resource_changed` events for a container subtree or specific path |
For chat-style bots, replace polling with `subscribe` and react to events as they land. Path scope: trailing slash watches a subtree, exact path watches a single resource, default watches the whole pod (filtered by Read access).
160
+
161
+
### Federation — bot-to-bot
162
+
163
+
`call_remote_pod` lets a bot on this pod invoke MCP tools on another pod. WAC-gated on both ends; depth-capped at 3 hops.
164
+
165
+
| Tool | Effect | Gating |
166
+
|---|---|---|
167
+
|`call_remote_pod`| Forward an MCP `tools/call` to another pod | Caller needs `acl:Write` on `<their-pod>/private/federation/` on this pod |
To delegate outbound federation to a specific agent, grant them `acl:Write` on your `/private/federation/` container. Owners control which agents can initiate calls; remote pods control what they expose.
179
+
180
+
In single-user mode, the pod owner has implicit gate access via `/private/` inheritance. In multi-user mode, each pod's owner gates their own federation.
181
+
182
+
Foreign WebIDs (identities hosted on other pods) cannot initiate federation from this pod — there's no local path for the gate to live at. Multi-pod federation chains compose by hopping between pods, each gated locally.
183
+
107
184
### Introspection
108
185
109
186
| Tool | Returns |
@@ -138,13 +215,42 @@ The owner opens `/public/apps/charlie/`, logs in via [xlogin](https://npm.im/xlo
138
215
139
216
The bot's *behavior* lives in `SKILL.md`. Edit the file → next session picks up the change. No re-deploy, no API call sequence — the bot's brain is a pod resource.
140
217
218
+
## Footguns
219
+
220
+
A short list of real gotchas, learned from live-fire use:
221
+
222
+
### Use absolute WebIDs in `write_acl` agents
223
+
224
+
The `agents` array is interpreted as a list of URIs. Relative paths (e.g. `../profile/card.jsonld#me`) resolve against the **.acl file's URL**, not the pod root — and the .acl URL changes depending on which resource the ACL applies to. Two pitfalls:
225
+
226
+
```json
227
+
// Pod owner WebID: http://example.com/profile/card.jsonld#me
228
+
// Writing this ACL to /public/forum/.acl:
229
+
"agents": ["../profile/card.jsonld#me"] // wrong — resolves to /public/profile/card.jsonld#me
230
+
"agents": ["./profile/card.jsonld#me"] // wrong — resolves to /public/forum/profile/card.jsonld#me
231
+
"agents": ["/profile/card.jsonld#me"] // right — absolute path
232
+
"agents": ["http://example.com/profile/card.jsonld#me"] // right — absolute URL, portable
233
+
```
234
+
235
+
**Always use absolute WebID URLs unless you know exactly what relative-URL resolution will give you.**
236
+
237
+
### `write_acl` will refuse if you'd lock yourself out
238
+
239
+
If the proposed ACL doesn't grant `Control` to the caller (typically a relative-URL mistake), `write_acl` refuses with an explanatory error. This is a safety, not a permission check — it's stopping you from breaking your own access.
240
+
241
+
If you really want to transfer ownership: do it in two steps. First `write_acl` granting Control to the new owner *in addition to* yourself. Then the new owner calls `write_acl` removing you.
242
+
243
+
### Subscribe needs an SSE-capable client
244
+
245
+
`subscribe` keeps an HTTP+SSE connection open indefinitely. Some proxies and load balancers will time out idle streams. Use a client that handles SSE reconnect (most browsers do; raw `curl` does not).
246
+
141
247
## What's not yet included
142
248
143
-
The first cut ships CRUD, skills, docs, and introspection. Deferred (tracked on [JSS#490](https://github.com/JavaScriptSolidServer/JavaScriptSolidServer/issues/490)):
249
+
The current cut ships CRUD, structured ACL editing, subscribe, federation, skills, docs, and introspection. Deferred (tracked on [JSS#490](https://github.com/JavaScriptSolidServer/JavaScriptSolidServer/issues/490)):
144
250
145
251
-**`update_resource` (PATCH)** — SPARQL Update / N3 patches. Read-modify-write through the CRUD tools is the workaround.
146
-
-**`subscribe`** — wrap JSS's WebSocket notifications as MCP events over SSE. Today, agents can poll via `read_resource`.
147
-
-**`call_remote_pod`** — federation primitive for bot-to-bot. Today, an agent can talk to two pods by registering both as MCP servers in its client.
252
+
-**Discovery layer** — no DNS SRV / Solid Type Index entry for "this pod offers MCP". Owners share URLs explicitly today.
253
+
-**Pod-resident federation credentials** — every `call_remote_pod` carries its own auth. A vault for storing remote-pod credentials is a separate security surface worth its own design pass.
148
254
-**Hosted Charlie** (`/agent/` endpoint) — JSS-internal LLM proxy with token metering. Tracked on [JSS#205](https://github.com/JavaScriptSolidServer/JavaScriptSolidServer/issues/205).
0 commit comments