@plurnk/plurnk-mcp 1.16.5 → 1.18.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.
- package/.env.defaults +36 -40
- package/README.md +35 -20
- package/SPEC.md +91 -58
- package/dist/McpExecutor.d.ts +6 -51
- package/dist/McpExecutor.d.ts.map +1 -1
- package/dist/McpExecutor.js +36 -29
- package/dist/McpExecutor.js.map +1 -1
- package/dist/McpResources.d.ts +1 -0
- package/dist/McpResources.d.ts.map +1 -1
- package/dist/McpResources.js +47 -39
- package/dist/McpResources.js.map +1 -1
- package/dist/Module.d.ts +9 -10
- package/dist/Module.d.ts.map +1 -1
- package/dist/Module.js +70 -61
- package/dist/Module.js.map +1 -1
- package/dist/ResourceContent.d.ts +9 -0
- package/dist/ResourceContent.d.ts.map +1 -0
- package/dist/ResourceContent.js +15 -0
- package/dist/ResourceContent.js.map +1 -0
- package/dist/ToolPresentation.d.ts +1 -2
- package/dist/ToolPresentation.d.ts.map +1 -1
- package/dist/ToolPresentation.js +2 -174
- package/dist/ToolPresentation.js.map +1 -1
- package/dist/capabilityMatrix.js +9 -9
- package/dist/capabilityMatrix.js.map +1 -1
- package/dist/client.d.ts +5 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +41 -6
- package/dist/client.js.map +1 -1
- package/docs/mcp.md +57 -0
- package/package.json +5 -5
package/.env.defaults
CHANGED
|
@@ -1,46 +1,42 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @plurnk/plurnk-mcp — Worker MCP attachments.
|
|
2
|
+
# Alias blocks make servers available; ENABLED selects initial attachments.
|
|
3
|
+
# A Worker can add/enable/disable/remove attachments through its Functionality controls.
|
|
2
4
|
|
|
3
|
-
#
|
|
4
|
-
# the request timeout below and remain cancellable through their Plurnk run.
|
|
5
|
+
# Connection and protocol-discovery deadline, positive ms.
|
|
5
6
|
PLURNK_MCP_CONNECT_TIMEOUT=30000
|
|
7
|
+
# Individual operation deadline, positive ms; caller cancellation still applies.
|
|
6
8
|
PLURNK_MCP_REQUEST_TIMEOUT=86400000
|
|
7
|
-
|
|
8
|
-
# Configured servers are available to clients. Only this exact JSON-array
|
|
9
|
-
# subset connects and becomes model-visible by default; workspaces may override it.
|
|
9
|
+
# Initially enabled aliases, JSON array; [] = none.
|
|
10
10
|
PLURNK_MCP_ENABLED=[]
|
|
11
|
-
|
|
12
|
-
# Turn 0 surveys enabled tool FAMILIES (one row per server, summary = its
|
|
13
|
-
# one-liner). Servers named here also expand their complete tool tree into
|
|
14
|
-
# the turn-0 survey:
|
|
11
|
+
# Expand these servers' tool lists in turn 0; otherwise show one row per server.
|
|
15
12
|
# PLURNK_MCP_EXPANDED=[]
|
|
16
13
|
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
|
|
23
|
-
#
|
|
24
|
-
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
|
|
31
|
-
#
|
|
32
|
-
#
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
# Then list it above to make it model-visible, e.g. PLURNK_MCP_ENABLED=["brave"].
|
|
14
|
+
# --- HTTP target ---
|
|
15
|
+
# URL, optional bearer reference, optional headers (string-valued JSON object).
|
|
16
|
+
# PLURNK_MCP_forge=https://example.test/mcp
|
|
17
|
+
# PLURNK_MCP_forge_BEARER=${FORGE_TOKEN}
|
|
18
|
+
# PLURNK_MCP_forge_HEADERS={"X-Tenant":"${FORGE_TENANT}"}
|
|
19
|
+
|
|
20
|
+
# --- stdio target ---
|
|
21
|
+
# One exact executable (not a shell command); ARGS is a literal JSON array.
|
|
22
|
+
# CWD is optional; ENV overlays the subprocess environment, resolving ${NAME} references.
|
|
23
|
+
# PLURNK_MCP_browser=node
|
|
24
|
+
# PLURNK_MCP_browser_ARGS=["/absolute/path/to/browser-server.mjs"]
|
|
25
|
+
# PLURNK_MCP_browser_CWD=/absolute/working/directory
|
|
26
|
+
# PLURNK_MCP_browser_ENV={"TOKEN":"${BROWSER_TOKEN}"}
|
|
27
|
+
|
|
28
|
+
# --- Tool admission and orientation ---
|
|
29
|
+
# Optional tool allowlist; omitted = all server tools. READ marks tools as read-only for admission.
|
|
30
|
+
# PLURNK_MCP_forge_TOOLS=["issue_read","issue_search"]
|
|
31
|
+
# PLURNK_MCP_forge_READ=["issue_read","issue_search"]
|
|
32
|
+
# Summary fallbacks when server metadata is inadequate; per-server or per-tool.
|
|
33
|
+
# PLURNK_MCP_forge_SUMMARY=```forge (issue_read) <!-- Read forge issues -->```
|
|
34
|
+
# PLURNK_MCP_forge_issue_read_SUMMARY=Read one issue.
|
|
35
|
+
|
|
36
|
+
# --- Optional Brave Search ---
|
|
37
|
+
# PLURNK_MCP_brave=npx
|
|
38
|
+
# PLURNK_MCP_brave_ARGS=["-y","@brave/brave-search-mcp-server@2.1.0"]
|
|
39
|
+
# PLURNK_MCP_brave_ENV={"BRAVE_API_KEY":"${BRAVE_API_KEY}"}
|
|
40
|
+
# PLURNK_MCP_brave_TOOLS=["brave_web_search","brave_news_search"]
|
|
41
|
+
# PLURNK_MCP_brave_READ=["brave_web_search","brave_news_search"]
|
|
42
|
+
# PLURNK_MCP_ENABLED=["brave"]
|
package/README.md
CHANGED
|
@@ -13,11 +13,11 @@ serves its standard surface at its own negotiated revision. Plurnk does not
|
|
|
13
13
|
downgrade its own extension wire, but it does not reject an older supported
|
|
14
14
|
revision.
|
|
15
15
|
|
|
16
|
-
## Manage
|
|
16
|
+
## Manage workspace servers
|
|
17
17
|
|
|
18
|
-
Service environment variables provide available servers for every
|
|
18
|
+
Service environment variables provide available servers for every workspace;
|
|
19
19
|
`PLURNK_MCP_ENABLED` selects the exact cold-enabled subset. Users can add,
|
|
20
|
-
enable, disable, or remove
|
|
20
|
+
enable, disable, or remove a workspace's servers without restarting the daemon. An
|
|
21
21
|
existing AG-UI connection sends the ordinary management-action form under
|
|
22
22
|
`forwardedProps.plurnk.action`:
|
|
23
23
|
|
|
@@ -27,7 +27,7 @@ existing AG-UI connection sends the ordinary management-action form under
|
|
|
27
27
|
"plurnk": {
|
|
28
28
|
"workspace": "example",
|
|
29
29
|
"action": {
|
|
30
|
-
"kind": "
|
|
30
|
+
"kind": "workspace.mcp.add",
|
|
31
31
|
"alias": "project",
|
|
32
32
|
"definition": {
|
|
33
33
|
"name": "project",
|
|
@@ -45,22 +45,29 @@ existing AG-UI connection sends the ordinary management-action form under
|
|
|
45
45
|
```
|
|
46
46
|
|
|
47
47
|
The standard `plurnk.action.result` event reports success or exact RFC 9457
|
|
48
|
-
Problem Details. The definition is durable and
|
|
48
|
+
Problem Details. The definition is durable and workspace-shared; symbolic
|
|
49
49
|
environment references remain unexpanded at rest.
|
|
50
50
|
|
|
51
|
-
MCP is one family of
|
|
51
|
+
MCP is one family of workspace Functionality; the common lifecycle actions are
|
|
52
52
|
published by the coordinator and the two continuations by this module:
|
|
53
53
|
|
|
54
54
|
| Action | Parameters |
|
|
55
55
|
|---|---|
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
62
|
-
|
|
63
|
-
The model manages the same family through
|
|
56
|
+
| `workspace.mcp.list` | — |
|
|
57
|
+
| `workspace.mcp.discover` | optional `query`, `source` (URL or command line), `configuration` (a client's `PLURNK_MCP_*` overlay) |
|
|
58
|
+
| `workspace.mcp.add` | optional `alias` (must equal the definition's `name`), `definition: McpServerDefinition` |
|
|
59
|
+
| `workspace.mcp.enable` / `disable` / `remove` | `alias` |
|
|
60
|
+
| `workspace.mcp.oauth.complete` | `alias`, complete `callbackUrl` |
|
|
61
|
+
| `workspace.mcp.complete` | `server`, completion `ref` and `argument`; optional `context` |
|
|
62
|
+
|
|
63
|
+
The model manages the same family through ```` ```mcp (list|discover|add|enable|disable|remove) ````.
|
|
64
|
+
|
|
65
|
+
Tool discovery uses ordinary `FIND (worker:///_plurnk/tools/*.md)` and READ.
|
|
66
|
+
Each server's document lists enabled tool calls with required-field previews
|
|
67
|
+
and links to full input schemas under `tools/<server>/<encoded-tool>.md`.
|
|
68
|
+
The manager uses the same layout under `plurnk/mcp.md` and `plurnk/mcp/`;
|
|
69
|
+
schema documents preserve descriptions and constraints without adding them to
|
|
70
|
+
the initial survey ({§tools-resource-discovery}).
|
|
64
71
|
|
|
65
72
|
The owning [specification](./SPEC.md) defines the complete action and server
|
|
66
73
|
definition contracts.
|
|
@@ -80,9 +87,11 @@ PLURNK_MCP_GITEA_ARGS=["plurnk_pk"]
|
|
|
80
87
|
|
|
81
88
|
The client carries its raw declarations while listing and enabling. Listing is
|
|
82
89
|
inert. `/mcp enable gitea` (or `plurnk mcp enable gitea` in a bound conversation)
|
|
83
|
-
composes service, durable
|
|
90
|
+
composes service, durable workspace, client, and optional command-file fields
|
|
84
91
|
in that order, prepares the connection, then persists the complete unexpanded
|
|
85
|
-
|
|
92
|
+
workspace definition. Arrays and maps replace rather than append or merge.
|
|
93
|
+
Reapplying an identical definition is idempotent. A different definition for
|
|
94
|
+
the same workspace alias requires explicit removal before replacement.
|
|
86
95
|
|
|
87
96
|
## Demo fixtures
|
|
88
97
|
|
|
@@ -156,18 +165,24 @@ Portable timeouts and complete examples live in [`.env.defaults`](./.env.default
|
|
|
156
165
|
|
|
157
166
|
| MCP surface | Plurnk surface |
|
|
158
167
|
|---|---|
|
|
159
|
-
| Server tools | `worker
|
|
160
|
-
| Enabled tool | Exact `worker
|
|
168
|
+
| Server tools | `worker:///_plurnk/tools/<server>.md` family summary |
|
|
169
|
+
| Enabled tool | Exact `worker:///_plurnk/tools/<server>/<encoded-tool>.md` document and ```` ```server (tool) ```` |
|
|
161
170
|
| Resource catalog | `server:///` or `server:///resources` |
|
|
162
171
|
| Resource | `server:///resources/<encoded-uri>` through ordinary `FIND` and `READ` |
|
|
163
172
|
| Prompt catalog | `server:///prompts` |
|
|
164
173
|
| Prompt retrieval | `server:///prompts/<encoded-name>?argument=value` through ordinary `READ` |
|
|
165
|
-
| Completion | Client-owned `
|
|
174
|
+
| Completion | Client-owned `workspace.mcp.complete` action |
|
|
175
|
+
| Tool image/audio or embedded resource | A named resource beneath the invocation's `resources/`; eight hexadecimal characters when unnamed |
|
|
176
|
+
| Exact tool-result evidence | The invocation's `#json` channel, retrieved on demand |
|
|
166
177
|
|
|
167
178
|
Tool results, resource bodies, prompt messages, and failures become ordinary
|
|
168
179
|
Plurnk entries and channels. Disabled tools appear in neither teaching nor
|
|
169
180
|
admission. There is no MCP-specific model discovery grammar.
|
|
170
181
|
|
|
182
|
+
Results link to media rather than dumping base64. An ordinary `READ` delivers
|
|
183
|
+
supported images natively; other content and unsupported models retain the
|
|
184
|
+
text/byte view. Listing the resource alone does not attach it.
|
|
185
|
+
|
|
171
186
|
Current pagination, cache hints, unified subscriptions, progress,
|
|
172
187
|
cancellation, multi-round-trip input, elicitation, and negotiated Tasks remain
|
|
173
188
|
inside the owning operation. Client input uses the standard AG-UI interrupt and
|
|
@@ -180,7 +195,7 @@ HTTP definitions support bearer references, client credentials, and
|
|
|
180
195
|
interactive OAuth. Stdio never receives OAuth. Interactive add or enable returns
|
|
181
196
|
`{ "status": 202, "authorization": { "url": "..." } }` without publishing a
|
|
182
197
|
partial server. After the user completes that URL, the client submits its
|
|
183
|
-
complete callback URL through `
|
|
198
|
+
complete callback URL through `workspace.mcp.oauth.complete`. PKCE, issuer and
|
|
184
199
|
resource validation, refresh, scope escalation, and credentials remain inside
|
|
185
200
|
the host connection.
|
|
186
201
|
|
package/SPEC.md
CHANGED
|
@@ -45,7 +45,7 @@ matrix rows cite.
|
|
|
45
45
|
| Resources | Negotiated server capability: `resources/list`, `resources/templates/list`, `resources/read` | Publish catalogs, templates, and materialized contents through the server's resource authority |
|
|
46
46
|
| Prompts | Negotiated server capability: `prompts/list`, `prompts/get` | Publish prompt definitions and retrieve prompt messages through the same server authority |
|
|
47
47
|
| Completion | Negotiated server capability: `completion/complete` | Make prompt and resource-template completion available to the host interaction that owns the argument |
|
|
48
|
-
| Pagination | Opaque cursors on list methods | Drain every page with a finite non-convergence guard; never publish a partial catalog as complete |
|
|
48
|
+
| Pagination | Opaque cursors on list methods | Drain every page with a finite non-convergence guard; never publish a partial catalog as complete ({§mcp-catalog-convergence}) |
|
|
49
49
|
| Caching | `server/discover`, list methods, and `resources/read` carry `ttlMs` and `cacheScope` | Honor freshness and notification invalidation; partition private entries by authorization context |
|
|
50
50
|
| Subscriptions | `subscriptions/listen` plus acknowledged filters and correlated notifications | Keep one current filter for list changes, resource URIs read into cache, and active Task IDs; overlap filter replacement, re-listen after loss, and never use the removed resource subscription methods |
|
|
51
51
|
| Progress | Request-scoped `notifications/progress` | Project progress onto the owning Plurnk operation without creating an independent protocol lifecycle |
|
|
@@ -54,6 +54,16 @@ matrix rows cite.
|
|
|
54
54
|
| Elicitation | Active client capability carried through MRTR | Advertise supported form/URL modes and route the request through Plurnk's client-owned interaction lifecycle |
|
|
55
55
|
| Authorization | OAuth profile for HTTP transports | Require validated protected-resource and authorization-server metadata; never infer endpoints; use PKCE, issuer validation, resource indicators, refresh, and bounded scope escalation; never apply OAuth to stdio |
|
|
56
56
|
|
|
57
|
+
§mcp-catalog-convergence **A catalog is complete or it is an error.** The pinned SDK's aggregating
|
|
58
|
+
list walk (`listTools`, `listResources`, `listResourceTemplates`, `listPrompts`) stops silently when
|
|
59
|
+
a server returns a cursor it already returned, drops `nextCursor`, and caches the partial aggregate
|
|
60
|
+
as if it were whole; only its page cap (`listMaxPages`) throws. The host's client watches the pages
|
|
61
|
+
the SDK requests and refuses the page that repeats a cursor with `CatalogNonConvergenceError`
|
|
62
|
+
(method and cursor named), so the listing fails and nothing partial is published or cached.
|
|
63
|
+
Pagination, caching, and the cap remain the SDK's; a converging server's pages aggregate exactly as
|
|
64
|
+
before. This is a host guard over an upstream behavior, not a second paginator; the upstream
|
|
65
|
+
report is #601's to file.
|
|
66
|
+
|
|
57
67
|
## §mcp-tasks Tasks extension
|
|
58
68
|
|
|
59
69
|
Tasks is the optional `io.modelcontextprotocol/tasks` extension, never core
|
|
@@ -85,7 +95,7 @@ nothing task-shaped is written to SQLite and no MCP sidecar lifecycle exists.
|
|
|
85
95
|
|---|---|
|
|
86
96
|
| Client disconnect | The daemon-owned operation and its task keep running; the client reattaches to the operation, not the task. |
|
|
87
97
|
| Daemon restart | The connection and every in-flight task handle die with it; the tool call fails like any interrupted operation, the loop re-runs, and the tool call creates a fresh task. |
|
|
88
|
-
|
|
|
98
|
+
| Workspace reactivation | The attachment reconstructs from its durable definition; in-flight tasks on the replaced connection are abandoned, not resumed. |
|
|
89
99
|
| Expiry | The owning operation deadline bounds polling; a non-converging task fails at the standard round bound and is cancelled. |
|
|
90
100
|
| Cancellation | Owner abort cancels the task before settling; the handle is then terminal. |
|
|
91
101
|
| Already terminal | Terminal results and errors are consumed by the drive loop; a completed or failed task is never re-polled or re-resumed. |
|
|
@@ -164,17 +174,17 @@ originating distinction in its canonical Problem/result path.
|
|
|
164
174
|
|
|
165
175
|
## §mcp-configuration Configuration
|
|
166
176
|
|
|
167
|
-
Service configuration and
|
|
168
|
-
enabled subset per
|
|
177
|
+
Service configuration and workspace state produce one available set and one
|
|
178
|
+
enabled subset per workspace. Every `PLURNK_MCP_<server>` declares an available
|
|
169
179
|
service-owned definition. `PLURNK_MCP_ENABLED` names the exact subset enabled
|
|
170
|
-
when a
|
|
180
|
+
when a workspace has no override. Workspace state may positively override a
|
|
171
181
|
service definition's enabledness or own an added definition and its enabledness.
|
|
172
182
|
Disabled definitions remain client-visible but contribute no connection,
|
|
173
183
|
Registry, documentation, or resource authority.
|
|
174
184
|
|
|
175
185
|
§mcp-activation-isolation **Cold endpoint failure is capability-local.** Invalid
|
|
176
186
|
service configuration or durable state fails admission, but an enabled server
|
|
177
|
-
that cannot connect or complete discovery during
|
|
187
|
+
that cannot connect or complete discovery during workspace activation remains
|
|
178
188
|
enabled and client-visible as `unavailable`. It publishes no runtime, tools,
|
|
179
189
|
resources, or documentation and cannot prevent other capabilities or the daemon
|
|
180
190
|
from starting or serving dormant workers. Enabling that already-enabled alias is an explicit reconnect
|
|
@@ -195,7 +205,7 @@ unavailable candidate without changing durable state.
|
|
|
195
205
|
| `PLURNK_MCP_<server>_SUMMARY` | Authored one-line server orientation ({§mcp-summary-derivation}) |
|
|
196
206
|
| `PLURNK_MCP_<server>_<tool>_SUMMARY` | Authored one-line tool orientation; tool names fold the same way and may contain underscores |
|
|
197
207
|
| `PLURNK_MCP_ENABLED` | JSON array of exact configured server aliases enabled by default; absent or `[]` enables none |
|
|
198
|
-
| `PLURNK_MCP_EXPANDED` | JSON array subset of enabled servers whose every tool is surveyed at turn 0 — one FIND row per
|
|
208
|
+
| `PLURNK_MCP_EXPANDED` | JSON array subset of enabled servers whose every tool is surveyed at turn 0 — one FIND row per executable block of the family document, with aside and signature ({§tools-resource-materialization}); never a document delivered unasked; absent or `[]` expands none |
|
|
199
209
|
| `PLURNK_MCP_CONNECT_TIMEOUT` | Positive integer milliseconds |
|
|
200
210
|
| `PLURNK_MCP_REQUEST_TIMEOUT` | Positive integer milliseconds |
|
|
201
211
|
|
|
@@ -218,7 +228,7 @@ resolves: its `_<server>_<tool>_SUMMARY` companion, `annotations.title`, the
|
|
|
218
228
|
first sentence of its `description` (capped), then the tool name. The family
|
|
219
229
|
doc's Summary section and the survey row carry the server one-liner; the tool
|
|
220
230
|
doc's Summary section IS the invocation form
|
|
221
|
-
|
|
231
|
+
```` ```server (tool) <!-- one-liner --> ````, so the discovery row teaches the
|
|
222
232
|
call ({§tools-resource-materialization}). Summary companions expand `${NAME}`
|
|
223
233
|
references like every other companion.
|
|
224
234
|
|
|
@@ -253,22 +263,22 @@ stdio executable) and its options (`args`, `cwd`, `env`, `headers`,
|
|
|
253
263
|
transport-inapplicable options before any connection work.
|
|
254
264
|
|
|
255
265
|
§mcp-configuration-cascade MCP server configuration has one field-wise
|
|
256
|
-
precedence order: service environment, then the
|
|
266
|
+
precedence order: service environment, then the workspace's durable definition.
|
|
257
267
|
Arrays and maps replace their lower value instead of appending or merging.
|
|
258
268
|
Client configuration is not a live layer: the contracts-owned
|
|
259
269
|
`{§mcp-configuration-overlay}` enters only as the `configuration` of a
|
|
260
270
|
`discover` query, is parsed by the same owner and path as service environment
|
|
261
271
|
declarations, and yields inert candidates with client-configuration provenance
|
|
262
272
|
({§mcp-discovery}); adding one persists a complete, normalized, unexpanded
|
|
263
|
-
|
|
273
|
+
workspace definition. Thus later enablement needs neither the originating client
|
|
264
274
|
nor its configuration file, and symbolic credentials remain resolvable only by
|
|
265
275
|
the service at connection preparation.
|
|
266
276
|
|
|
267
277
|
### §mcp-module The MCP family beneath the coordinator
|
|
268
278
|
|
|
269
|
-
§mcp-management-actions MCP is one family of
|
|
270
|
-
({§functionality-coordinator}): the coordinator publishes `
|
|
271
|
-
discover | add | enable | disable | remove` and the model's `
|
|
279
|
+
§mcp-management-actions MCP is one family of workspace Functionality
|
|
280
|
+
({§functionality-coordinator}): the coordinator publishes `workspace.mcp.list |
|
|
281
|
+
discover | add | enable | disable | remove` and the model's `mcp` executable fence
|
|
272
282
|
family with the common semantics, durable state, and publication; this module
|
|
273
283
|
registers the family adapter and owns protocol truth beneath it. `available`
|
|
274
284
|
is the service environment with its `PLURNK_MCP_ENABLED` defaults; `admit`
|
|
@@ -281,13 +291,13 @@ exact Problem, or `authorization-required` with its URL), and a two-phase
|
|
|
281
291
|
snapshot: `commit` closes connections the new set no longer uses and records
|
|
282
292
|
pending authorizations; `abort` closes only what the attempt opened.
|
|
283
293
|
|
|
284
|
-
Two protocol continuations remain MCP-registered
|
|
294
|
+
Two protocol continuations remain MCP-registered workspace actions beneath the
|
|
285
295
|
common grammar:
|
|
286
296
|
|
|
287
297
|
| Action | Parameters | Result / effect |
|
|
288
298
|
|---|---|---|
|
|
289
|
-
| `
|
|
290
|
-
| `
|
|
299
|
+
| `workspace.mcp.oauth.complete` | `alias`, `callbackUrl` | State- and issuer-validates one pending interactive callback through the SDK, completes connection preparation, and re-enables the alias through the coordinator ({§oauth-continuation}); the result is the common mutation result. |
|
|
300
|
+
| `workspace.mcp.complete` | `server`, `ref`, `argument`; optional `context` | Requests negotiated prompt/resource-template argument completion for a client-owned interaction. |
|
|
291
301
|
|
|
292
302
|
§mcp-discovery Discovery is inert. `configuration` (a client's own
|
|
293
303
|
`PLURNK_MCP_*` overlay) becomes candidates without connecting; `source` — an
|
|
@@ -314,8 +324,8 @@ in daemon diagnostics. No MCP resource Problem admits an unbounded SDK message.
|
|
|
314
324
|
|
|
315
325
|
§oauth-continuation Interactive preparation publishes the alias as enabled and
|
|
316
326
|
`authorization-required` with its URL; it publishes no runtime. The adapter
|
|
317
|
-
retains one pending candidate per `(
|
|
318
|
-
connection and one
|
|
327
|
+
retains one pending candidate per `(workspace, alias)` holding the challenged
|
|
328
|
+
connection and one workspace residency lease; a new challenge for the alias
|
|
319
329
|
supersedes and releases the previous one ({§oauth-lifetime}).
|
|
320
330
|
`oauth.complete` accepts the complete callback URL so state, `code`, and
|
|
321
331
|
`iss` remain one parsing unit; it finishes the pending connection's
|
|
@@ -332,25 +342,25 @@ error text.
|
|
|
332
342
|
Interactive OAuth state is deliberately ephemeral and process-memory: client
|
|
333
343
|
registration data, access and refresh tokens, the PKCE verifier, and pending
|
|
334
344
|
state live only in the owning connection or pending candidate. Nothing
|
|
335
|
-
OAuth-secret is written to SQLite; the durable
|
|
345
|
+
OAuth-secret is written to SQLite; the durable workspace state holds only the
|
|
336
346
|
unexpanded definition ({§mcp-configuration}). There is no callback HTTP
|
|
337
347
|
listener, authority-root resource, or daemon-side browser side channel: the
|
|
338
|
-
client returns the complete callback URL through `
|
|
348
|
+
client returns the complete callback URL through `workspace.mcp.oauth.complete`
|
|
339
349
|
so `state`, `code`, and `iss` remain one parsing unit. Reauthorization after a
|
|
340
350
|
daemon restart is the intended journey, documented here rather than presented
|
|
341
351
|
as an accidental failure.
|
|
342
352
|
|
|
343
353
|
| Journey point | Behaviour |
|
|
344
354
|
|---|---|
|
|
345
|
-
| Pending authorization | One pending candidate per `(
|
|
355
|
+
| Pending authorization | One pending candidate per `(workspace, alias)`; a new add or customized enable cancels and replaces it. A callback from a superseded attempt fails state validation instead of cross-completing. |
|
|
346
356
|
| Client disconnect | Does not touch the pending candidate; it can still be completed, or replaced by a fresh request. |
|
|
347
357
|
| Daemon restart during pending | The candidate is lost: nothing was durable, no attachment publishes, and `oauth.complete` answers `404 oauth-not-pending`. Start authorization again. |
|
|
348
358
|
| Daemon restart after authorization | The durable definition rehydrates but tokens are gone; the attachment publishes `authorization-required` and enable returns a fresh `{ status: 202, authorization: { url } }`. The operator reauthorizes. |
|
|
349
359
|
| Token expiry | An expired access token surfaces as one unauthorized response; the SDK re-acquires via `refresh_token` when one was issued, otherwise re-enters interactive authorization. |
|
|
350
360
|
| Refresh | Happens only against the issuer bound during the original authorization; the refreshed token replaces the in-memory token. |
|
|
351
|
-
|
|
|
361
|
+
| Workspace disable/remove | Closes the attachment and clears its pending candidate; no durable secret deletion is needed because nothing secret is durable. |
|
|
352
362
|
| Server replacement | Completion compares the pending candidate's expected definition with the current one; drift of the same server fails `409 oauth-target-conflict` instead of replaying a stale snapshot. |
|
|
353
|
-
| Cross-authorization protection | Candidates are keyed by `(
|
|
363
|
+
| Cross-authorization protection | Candidates are keyed by `(workspace, alias)`; callback state, PKCE, and issuer are validated by the SDK against the attempt that created them, so no other workspace, alias, or attempt can complete this authorization. |
|
|
354
364
|
|
|
355
365
|
## §oauth-client-credentials Client-credentials grant adoption
|
|
356
366
|
|
|
@@ -402,32 +412,32 @@ decision on durable identity material is ratified.
|
|
|
402
412
|
|
|
403
413
|
## §mcp-setup Atomic lifecycle
|
|
404
414
|
|
|
405
|
-
When a cold
|
|
406
|
-
|
|
415
|
+
When a cold workspace is demanded, activation resolves service defaults and durable positive
|
|
416
|
+
workspace state, opens and discovers only enabled connections,
|
|
407
417
|
lists the negotiated catalogs, applies enabled/effect policy, builds each exact
|
|
408
418
|
tool Registry and resource facet, and submits one complete owner snapshot to
|
|
409
|
-
{§module-
|
|
419
|
+
{§module-workspace-capabilities}. A configured tool absent from the server, a
|
|
410
420
|
duplicate remote name, an enabled name not representable as a Plurnk target,
|
|
411
|
-
or a `read` name outside the enabled set fails that
|
|
421
|
+
or a `read` name outside the enabled set fails that workspace activation. No
|
|
412
422
|
partial namespace is published and every acquired candidate closes.
|
|
413
423
|
|
|
414
424
|
- §mcp-catalog-refresh-in-place **A catalog change refreshes in place.** When a server announces a changed catalog, the alias is dirty and its executor is rebuilt on the next preparation — on the connection the alias already holds, never by spawning a second server: with an unchanged definition and a live connection, preparation re-lists the catalog over that connection, so neither an aborted attempt nor a commit has anything of the alias to close, and a failed re-listing leaves the current catalog in service. (#429's root: the SDK's negotiated connect probes a stdio server on a disposable sibling process before the real connect, so every stdio connect starts the server twice and the sibling exits on its own schedule — a test that reads "any exit" as "the committed server was closed" flakes under load. The committed server is the last one started; the refresh-in-place rule keeps it so.) Covered: `Module.test.ts` — one process ever, no close marker across the refresh.
|
|
415
425
|
|
|
416
|
-
MCP participates in core Functionality residency ({§module-
|
|
417
|
-
Every tool call and Task retains the
|
|
426
|
+
MCP participates in core Functionality residency ({§module-workspace-residency}).
|
|
427
|
+
Every tool call and Task retains the workspace from executor entry through its
|
|
418
428
|
terminal result; an interactive OAuth candidate retains it until completion,
|
|
419
429
|
replacement, cancellation, or module shutdown. Catalog refresh timers are
|
|
420
430
|
infrastructure, not residency owners: cooling serializes behind a refresh
|
|
421
431
|
already running and cancels any timer not yet begun. At a lease-free quiescent
|
|
422
|
-
boundary, deactivation removes the
|
|
432
|
+
boundary, deactivation removes the workspace snapshot and closes all of its
|
|
423
433
|
connections. Core separately withdraws the executor/scheme publication while
|
|
424
434
|
preserving durable MCP state and generated reference entries for transparent
|
|
425
435
|
reactivation.
|
|
426
436
|
|
|
427
437
|
Add and enable prepare the candidate while the old snapshot remains
|
|
428
|
-
authoritative, then commit only at {§module-
|
|
438
|
+
authoritative, then commit only at {§module-workspace-quiescence}. Disable and
|
|
429
439
|
remove commit the complete reduced snapshot at the same boundary. The
|
|
430
|
-
old connection rejects replacement while it owns an active protocol request,
|
|
440
|
+
old connection rejects replacement with `409 server-busy` while it owns an active protocol request,
|
|
431
441
|
MRTR exchange, or Task. Cache/list-change watches are infrastructure and close
|
|
432
442
|
with the old connection after the new snapshot commits. A failed candidate or
|
|
433
443
|
commit leaves the durable definition, connection, Registry, docs, and resource
|
|
@@ -446,17 +456,17 @@ cancellation.
|
|
|
446
456
|
|
|
447
457
|
One `ServerConnection` owns negotiation, SDK caches, authorization partition,
|
|
448
458
|
subscriptions, active request controllers, MRTR rounds, and Tasks for one
|
|
449
|
-
|
|
459
|
+
workspace attachment. The host does not reproduce SDK protocol machinery.
|
|
450
460
|
|
|
451
461
|
| Protocol event | Plurnk composition |
|
|
452
462
|
|---|---|
|
|
453
|
-
| `tools/call` progress | Writes ordinary transient progress on the owning
|
|
454
|
-
| Operation cancellation | The owning
|
|
463
|
+
| `tools/call` progress | Writes ordinary transient progress on the owning execution stream; it creates no log sibling or polling vocabulary. |
|
|
464
|
+
| Operation cancellation | The owning execution's abort signal closes the HTTP request stream or sends the stdio cancellation notification. |
|
|
455
465
|
| `input_required` | Batches all embedded requests from one result into one atomic client interaction. Opaque `requestState` remains private to the connection and only the originating request is reissued after a complete response. |
|
|
456
466
|
| Elicitation form / URL | Validates the response against the requested form or URL action contract. Client cancellation becomes the standard `cancel` action; unsupported families or modes fail before any interaction or retry. |
|
|
457
|
-
| Task handle | Keeps the original
|
|
467
|
+
| Task handle | Keeps the original execution stream active, follows `tasks/get` and selected Task notifications, and settles that same stream with the terminal result or error. |
|
|
458
468
|
| Task input | Routes through the operation's client interaction, then sends `tasks/update`; it never asks the model to manufacture protocol state. |
|
|
459
|
-
| Task cancellation | The owning
|
|
469
|
+
| Task cancellation | The owning execution's cancellation invokes `tasks/cancel` before settling the ordinary stream cancellation. |
|
|
460
470
|
| List/resource invalidation | List changes invalidate SDK catalogs and atomically refresh the attachment snapshot. Updates to selected resource URIs invalidate their SDK cache entries; private entries remain authorization-partitioned. |
|
|
461
471
|
| Prompt get / completion | Serves ordinary resource-authority reads and host interactions from negotiated prompt/template definitions; no prompt becomes an executable tool. |
|
|
462
472
|
|
|
@@ -479,18 +489,34 @@ effect occurred.
|
|
|
479
489
|
|
|
480
490
|
## §mcp-result-content Passive result content
|
|
481
491
|
|
|
482
|
-
The
|
|
483
|
-
|
|
484
|
-
— `application/json` when the text is a JSON document,
|
|
492
|
+
The default output channel carries the tool's result, not its transport envelope:
|
|
493
|
+
text parts are written as text with their own newlines
|
|
494
|
+
— whitespace-formatted `application/json` when the text is a complete JSON document,
|
|
495
|
+
else unchanged `text/plain` ({§json-document-presentation});
|
|
485
496
|
several text parts join with newlines; an empty content with
|
|
486
497
|
`structuredContent` writes it pretty-printed — so the page rule and a scoped
|
|
487
|
-
READ mean what they say and nothing reaches the model double-escaped.
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
498
|
+
READ mean what they say and nothing reaches the model double-escaped. The
|
|
499
|
+
complete result, including metadata and annotations, remains available in
|
|
500
|
+
`#json` as protocol evidence. The default body preserves content order:
|
|
501
|
+
|
|
502
|
+
| Content | Model-facing projection |
|
|
503
|
+
| --- | --- |
|
|
504
|
+
| Text | Its text. |
|
|
505
|
+
| Inline image/audio | Link to an invocation-owned typed byte resource, published through {§executor-entry-sink}. |
|
|
506
|
+
| Embedded text/blob resource | Link to a typed resource snapshot; use the supplied URI's filename when present. |
|
|
507
|
+
| Resource link | Link to the existing MCP resource address; acquisition occurs on READ, not on listing. |
|
|
508
|
+
|
|
509
|
+
Unnamed resources receive eight-character hexadecimal identifiers, not ordinal
|
|
510
|
+
labels. No binary base64 is copied into the default result body. Listing a
|
|
511
|
+
resource creates no native model attachment; READ uses {§packet-attachment-parts},
|
|
512
|
+
including scoped byte reads, supported modalities, and single-request delivery.
|
|
513
|
+
Resource publication is passive; completion of the originating execution retains
|
|
514
|
+
its ordinary wake semantics. A single `resources/read` content item becomes the
|
|
515
|
+
resource's typed body; multiple items become named children under its `resources/`
|
|
516
|
+
folder and a directory of links. Each response retains its complete `#json` evidence;
|
|
517
|
+
reconstructing the same collection preserves child paths ({§resource-publication-names}).
|
|
518
|
+
Generated catalogs and prompt documents use two-space
|
|
519
|
+
JSON indentation; individual text resources preserve their source layout. A
|
|
494
520
|
standalone `blob` content block is not a modern `tools/call` content member
|
|
495
521
|
(blobs ride inside embedded blob resources) and is rejected as
|
|
496
522
|
protocol-invalid. Size limits and MIME trust remain ordinary channel and
|
|
@@ -516,25 +542,32 @@ even then the capability would be per-client-advertised, never daemon-wide.
|
|
|
516
542
|
|
|
517
543
|
| MCP surface | Plurnk surface |
|
|
518
544
|
|---|---|
|
|
519
|
-
| Server | One registered executor family, `worker
|
|
520
|
-
| Enabled tool | One annotated call in the compact family document plus one exact `worker
|
|
545
|
+
| Server | One registered executor family, `worker:///_plurnk/tools/<server>.md`, and matching resource scheme |
|
|
546
|
+
| Enabled tool | One annotated call in the compact family document plus one exact `worker:///_plurnk/tools/<server>/<encoded-tool>.md` input-contract document |
|
|
521
547
|
| Tool survey | Ordinary FIND summary metadata from the standard executable-tool resource tree |
|
|
522
548
|
| Resource catalog | `<server>:///` and `<server>:///resources` |
|
|
523
549
|
| Resources | `<server>:///resources` and encoded resource-URI descendants |
|
|
524
550
|
| Prompts | `<server>:///prompts` and encoded prompt-name descendants |
|
|
525
551
|
|
|
552
|
+
Qualified `<server>://<worker>/…` resources, prompts, and catalogs follow
|
|
553
|
+
{§runtime-resource-binding}: the qualifier selects the stored projection, not
|
|
554
|
+
a private attachment. Acquisition uses the workspace attachment; the requesting
|
|
555
|
+
operation retains its policy and client interactions.
|
|
556
|
+
Returned Plurnk resource links retain that qualifier; MCP protocol URIs remain
|
|
557
|
+
unchanged on the wire.
|
|
558
|
+
|
|
526
559
|
§mcp-tool-presentation One canonical enabled-tool snapshot owns every
|
|
527
560
|
model-facing and executable consequence. Each enabled remote tool becomes one
|
|
528
561
|
exact target in {§executor-tool-registry}. Its standard
|
|
529
|
-
{§executor-tool-document} carries
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
562
|
+
{§executor-tool-document} carries a compact summary, requiredness derived from
|
|
563
|
+
the input schema, and the original schema itself. The common renderer owns
|
|
564
|
+
{§executor-input-schema-preview}, not an MCP-specific schema interpreter.
|
|
565
|
+
The compact family document contains annotated, copyable tool invocations with
|
|
566
|
+
shallow required-field previews and alias-scoped schema links. Each linked child
|
|
567
|
+
preserves the complete remote description and raw input schema, without
|
|
568
|
+
reconstructing property tables or expanding nested constraints into the preview.
|
|
569
|
+
A missing remote description falls back to the tool name rather than an invented
|
|
570
|
+
capability claim. Output schemas
|
|
538
571
|
do not enter model teaching; the returned value remains ordinary evidence. Disabled names
|
|
539
572
|
appear in neither discovery nor admission, and there is no MCP-specific FIND,
|
|
540
573
|
READ, authority-root, or other model discovery mechanism for tools.
|
package/dist/McpExecutor.d.ts
CHANGED
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import { BaseExecutor } from "@plurnk/plurnk-execs";
|
|
2
2
|
import type { ChannelDecl, Effect, ExecArgs, ExecResult, RuntimeAvailability, RuntimeDecl, RuntimeSummaryDecl, RuntimeToolRegistry } from "@plurnk/plurnk-execs";
|
|
3
3
|
import ServerConnection, { type ServerCatalog } from "./client.ts";
|
|
4
|
+
import type { ContentBlock } from "@modelcontextprotocol/client";
|
|
4
5
|
import type { ToolPolicy } from "./config.ts";
|
|
5
6
|
export declare const serverSummary: (name: string, catalog: ServerCatalog | undefined, override: string | undefined) => string;
|
|
6
7
|
export declare const runtimeServerSummary: (name: string, catalog: ServerCatalog | undefined, override: string | undefined) => RuntimeSummaryDecl;
|
|
7
8
|
export type ToolResultShape = {
|
|
8
|
-
readonly content?:
|
|
9
|
-
readonly type: string;
|
|
10
|
-
readonly text?: string;
|
|
11
|
-
readonly [field: string]: unknown;
|
|
12
|
-
}>;
|
|
9
|
+
readonly content?: readonly ContentBlock[];
|
|
13
10
|
readonly structuredContent?: unknown;
|
|
14
11
|
readonly isError?: boolean;
|
|
15
12
|
};
|
|
16
|
-
export declare const toolResultBody: (result: ToolResultShape) => {
|
|
13
|
+
export declare const toolResultBody: (result: ToolResultShape, runtime: string, entry?: ExecArgs["entry"]) => Promise<{
|
|
17
14
|
content: string;
|
|
18
15
|
mimetype: string;
|
|
19
|
-
}
|
|
16
|
+
}>;
|
|
20
17
|
export declare const runtimeDecl: (name: string, summary: RuntimeSummaryDecl, expandTools: boolean) => RuntimeDecl;
|
|
21
18
|
export default class McpExecutor extends BaseExecutor {
|
|
22
19
|
#private;
|
|
@@ -24,55 +21,13 @@ export default class McpExecutor extends BaseExecutor {
|
|
|
24
21
|
runtime: string;
|
|
25
22
|
glyph: string;
|
|
26
23
|
}, connection: ServerConnection, retainWorkspace: () => () => void, policy?: Partial<ToolPolicy>, toolSummaries?: ReadonlyMap<string, string>);
|
|
27
|
-
get manifest(): {
|
|
28
|
-
name: string;
|
|
29
|
-
authority?: import("@plurnk/plurnk-schemes").SchemeAuthority;
|
|
30
|
-
channels: Record<string, string>;
|
|
31
|
-
defaultChannel: string;
|
|
32
|
-
writableBy: ReadonlyArray<import("@plurnk/plurnk-schemes").WriterTier>;
|
|
33
|
-
volatile: boolean;
|
|
34
|
-
modelVisible: boolean;
|
|
35
|
-
folderScopes?: boolean;
|
|
36
|
-
textEditScopes?: boolean;
|
|
37
|
-
metadataModifier?: boolean;
|
|
38
|
-
lineAnchors?: boolean;
|
|
39
|
-
foldedByDefault?: boolean;
|
|
40
|
-
traits?: ReadonlyArray<string>;
|
|
41
|
-
documentation?: string;
|
|
42
|
-
glyph?: string;
|
|
43
|
-
storedScheme?: string;
|
|
44
|
-
category: "data";
|
|
45
|
-
entryOwner: import("@plurnk/plurnk-schemes").SchemeEntryOwner;
|
|
46
|
-
inherit: import("@plurnk/plurnk-schemes").SchemeEntryInheritance;
|
|
47
|
-
example: string;
|
|
48
|
-
} | {
|
|
49
|
-
name: string;
|
|
50
|
-
authority?: import("@plurnk/plurnk-schemes").SchemeAuthority;
|
|
51
|
-
channels: Record<string, string>;
|
|
52
|
-
defaultChannel: string;
|
|
53
|
-
writableBy: ReadonlyArray<import("@plurnk/plurnk-schemes").WriterTier>;
|
|
54
|
-
volatile: boolean;
|
|
55
|
-
modelVisible: boolean;
|
|
56
|
-
folderScopes?: boolean;
|
|
57
|
-
textEditScopes?: boolean;
|
|
58
|
-
metadataModifier?: boolean;
|
|
59
|
-
lineAnchors?: boolean;
|
|
60
|
-
foldedByDefault?: boolean;
|
|
61
|
-
traits?: ReadonlyArray<string>;
|
|
62
|
-
documentation?: string;
|
|
63
|
-
glyph?: string;
|
|
64
|
-
storedScheme?: string;
|
|
65
|
-
category: "logging" | "control";
|
|
66
|
-
entryOwner?: never;
|
|
67
|
-
inherit?: never;
|
|
68
|
-
example: string;
|
|
69
|
-
};
|
|
70
24
|
get channels(): Readonly<Record<string, ChannelDecl>>;
|
|
71
25
|
effect(target: string | null): Effect;
|
|
26
|
+
get publishedChannel(): string;
|
|
72
27
|
toolRegistry(): RuntimeToolRegistry;
|
|
73
28
|
get catalog(): ServerCatalog;
|
|
74
29
|
probe(signal?: AbortSignal): Promise<RuntimeAvailability>;
|
|
75
30
|
requireAvailable(signal?: AbortSignal): Promise<RuntimeAvailability>;
|
|
76
|
-
run({ runtime, body, target, signal, write, setState, emit, interact, }: ExecArgs): Promise<ExecResult>;
|
|
31
|
+
run({ runtime, body, target, signal, write, setState, emit, interact, entry, }: ExecArgs): Promise<ExecResult>;
|
|
77
32
|
}
|
|
78
33
|
//# sourceMappingURL=McpExecutor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"McpExecutor.d.ts","sourceRoot":"","sources":["../src/McpExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,YAAY,
|
|
1
|
+
{"version":3,"file":"McpExecutor.d.ts","sourceRoot":"","sources":["../src/McpExecutor.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,YAAY,EAKf,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EACR,WAAW,EACX,MAAM,EACN,QAAQ,EACR,UAAU,EAEV,mBAAmB,EACnB,WAAW,EACX,kBAAkB,EAClB,mBAAmB,EACtB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,gBAAgB,EAAE,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,KAAK,EAAE,YAAY,EAAkB,MAAM,8BAA8B,CAAC;AAGjF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAiC9C,eAAO,MAAM,aAAa,SAChB,MAAM,WACH,aAAa,GAAG,SAAS,YACxB,MAAM,GAAG,SAAS,KAC7B,MAOF,CAAC;AAIF,eAAO,MAAM,oBAAoB,SACvB,MAAM,WACH,aAAa,GAAG,SAAS,YACxB,MAAM,GAAG,SAAS,KAC7B,kBAIF,CAAC;AAMF,MAAM,MAAM,eAAe,GAAG;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAC3C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,OAAO,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,eAAO,MAAM,cAAc,WAAkB,eAAe,WAAW,MAAM,UAAU,QAAQ,CAAC,OAAO,CAAC,KAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAyBvJ,CAAC;AAEF,eAAO,MAAM,WAAW,SAAU,MAAM,WAAW,kBAAkB,eAAe,OAAO,KAAG,WAc5F,CAAC;AAuBH,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,YAAY;;IASjD,YACI,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAC5C,UAAU,EAAE,gBAAgB,EAC5B,eAAe,EAAE,MAAM,MAAM,IAAI,EACjC,MAAM,GAAE,OAAO,CAAC,UAAU,CAAM,EAChC,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAQ9C;IAED,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAOpD;IAEQ,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAK7C;IAED,IAAa,gBAAgB,IAAI,MAAM,CAEtC;IAgCD,YAAY,IAAI,mBAAmB,CAKlC;IAED,IAAI,OAAO,IAAI,aAAa,CAK3B;IAEc,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAgBvE;IAEK,gBAAgB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAqBzE;IAEK,GAAG,CAAC,EACN,OAAO,EACP,IAAI,EACJ,MAAM,EACN,MAAM,EACN,KAAK,EACL,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,KAAK,GACR,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,CA2HhC;CACJ"}
|