@fragno-dev/mcp-fragment 0.0.0-stage → 0.0.3
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/LICENSE.md +16 -0
- package/README.md +312 -2
- package/bin/run.js +7 -0
- package/dist/browser/client/react.d.ts +253 -0
- package/dist/browser/client/react.d.ts.map +1 -0
- package/dist/browser/client/react.js +194 -0
- package/dist/browser/client/react.js.map +1 -0
- package/dist/browser/client/solid.d.ts +256 -0
- package/dist/browser/client/solid.d.ts.map +1 -0
- package/dist/browser/client/solid.js +129 -0
- package/dist/browser/client/solid.js.map +1 -0
- package/dist/browser/client/svelte.d.ts +256 -0
- package/dist/browser/client/svelte.d.ts.map +1 -0
- package/dist/browser/client/svelte.js +131 -0
- package/dist/browser/client/svelte.js.map +1 -0
- package/dist/browser/client/vanilla.d.ts +283 -0
- package/dist/browser/client/vanilla.d.ts.map +1 -0
- package/dist/browser/client/vanilla.js +159 -0
- package/dist/browser/client/vanilla.js.map +1 -0
- package/dist/browser/client/vue.d.ts +256 -0
- package/dist/browser/client/vue.d.ts.map +1 -0
- package/dist/browser/client/vue.js +127 -0
- package/dist/browser/client/vue.js.map +1 -0
- package/dist/browser/client-BCzNDSlW.d.ts +711 -0
- package/dist/browser/client-BCzNDSlW.d.ts.map +1 -0
- package/dist/browser/index.d.ts +813 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +1 -0
- package/dist/browser/src-B6dHZXqB.js +2303 -0
- package/dist/browser/src-B6dHZXqB.js.map +1 -0
- package/dist/cli/cli.d.ts +6 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +227 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/definition.js +330 -0
- package/dist/cli/definition.js.map +1 -0
- package/dist/cli/diagnostics.js +93 -0
- package/dist/cli/diagnostics.js.map +1 -0
- package/dist/cli/index.js +13 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/mcp-api.js +87 -0
- package/dist/cli/mcp-api.js.map +1 -0
- package/dist/cli/mcp-types.js +100 -0
- package/dist/cli/mcp-types.js.map +1 -0
- package/dist/cli/oauth-provider.js +113 -0
- package/dist/cli/oauth-provider.js.map +1 -0
- package/dist/cli/routes.js +743 -0
- package/dist/cli/routes.js.map +1 -0
- package/dist/cli/schema.js +13 -0
- package/dist/cli/schema.js.map +1 -0
- package/dist/cli/services.js +330 -0
- package/dist/cli/services.js.map +1 -0
- package/dist/node/definition.d.ts +260 -0
- package/dist/node/definition.d.ts.map +1 -0
- package/dist/node/definition.js +330 -0
- package/dist/node/definition.js.map +1 -0
- package/dist/node/diagnostics.js +93 -0
- package/dist/node/diagnostics.js.map +1 -0
- package/dist/node/index.d.ts +694 -0
- package/dist/node/index.d.ts.map +1 -0
- package/dist/node/index.js +26 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/mcp-api.d.ts +2 -0
- package/dist/node/mcp-api.js +87 -0
- package/dist/node/mcp-api.js.map +1 -0
- package/dist/node/mcp-types.d.ts +146 -0
- package/dist/node/mcp-types.d.ts.map +1 -0
- package/dist/node/mcp-types.js +100 -0
- package/dist/node/mcp-types.js.map +1 -0
- package/dist/node/oauth-provider.d.ts +24 -0
- package/dist/node/oauth-provider.d.ts.map +1 -0
- package/dist/node/oauth-provider.js +113 -0
- package/dist/node/oauth-provider.js.map +1 -0
- package/dist/node/routes.d.ts +466 -0
- package/dist/node/routes.d.ts.map +1 -0
- package/dist/node/routes.js +743 -0
- package/dist/node/routes.js.map +1 -0
- package/dist/node/schema.d.ts +9 -0
- package/dist/node/schema.d.ts.map +1 -0
- package/dist/node/schema.js +13 -0
- package/dist/node/schema.js.map +1 -0
- package/dist/node/services.d.ts +40 -0
- package/dist/node/services.d.ts.map +1 -0
- package/dist/node/services.js +330 -0
- package/dist/node/services.js.map +1 -0
- package/dist/node/testing/mcp-test-server.d.ts +42 -0
- package/dist/node/testing/mcp-test-server.d.ts.map +1 -0
- package/dist/node/testing/mcp-test-server.js +218 -0
- package/dist/node/testing/mcp-test-server.js.map +1 -0
- package/package.json +130 -3
package/LICENSE.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Copyright 2025 - present "ReJot Nederland B.V.", and individual contributors.
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
|
4
|
+
associated documentation files (the “Software”), to deal in the Software without restriction,
|
|
5
|
+
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
|
6
|
+
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
|
7
|
+
furnished to do so, subject to the following conditions:
|
|
8
|
+
|
|
9
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial
|
|
10
|
+
portions of the Software.
|
|
11
|
+
|
|
12
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
|
13
|
+
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
14
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
|
15
|
+
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
16
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,313 @@
|
|
|
1
|
-
#
|
|
1
|
+
# mcp-fragment
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A DB-backed Fragno fragment for calling MCP tools over Streamable HTTP.
|
|
4
|
+
|
|
5
|
+
This fragment is a client for one or more remote MCP servers. It stores server configuration and
|
|
6
|
+
auth state in the fragment database, then connects to MCP servers per operation to list tools or
|
|
7
|
+
call a tool. It supports MCP **tools** only; prompts, resources, roots, sampling, and elicitation
|
|
8
|
+
are out of scope for this package.
|
|
9
|
+
|
|
10
|
+
## Protocol support
|
|
11
|
+
|
|
12
|
+
The fragment supports MCP **2026-07-28** using the official TypeScript SDK v2 client. Each operation
|
|
13
|
+
discovers the server's protocol automatically; older servers fall back to the initialization-based
|
|
14
|
+
protocol (including **2025-11-25**). Both JSON and SSE responses over Streamable HTTP are supported.
|
|
15
|
+
It does not implement the separate legacy HTTP+SSE transport.
|
|
16
|
+
|
|
17
|
+
Tool listing follows all cursor pages before replacing the cached tool list. Tool metadata,
|
|
18
|
+
including output schemas and icons, is preserved. `McpTool` mirrors the protocol's tool definition,
|
|
19
|
+
including the required `inputSchema`. Structured tool results may be objects, arrays, primitives, or
|
|
20
|
+
`null`; protocol-only result envelopes are handled by the SDK.
|
|
21
|
+
|
|
22
|
+
Protocol support does not enable optional MCP features outside this package's tools-only scope, such
|
|
23
|
+
as elicitation, sampling, subscriptions, or the tasks extension.
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { createMcpFragment } from "@fragno-dev/mcp-fragment";
|
|
29
|
+
|
|
30
|
+
const oauthRedirectUri = "https://app.example.com/mcp/oauth/callback";
|
|
31
|
+
const fragment = createMcpFragment(
|
|
32
|
+
{
|
|
33
|
+
// Optional SSRF/tenant allow-list hook.
|
|
34
|
+
allowedEndpointUrls: (url) => url.protocol === "https:",
|
|
35
|
+
// OAuth start is denied unless the callback is explicitly allowed.
|
|
36
|
+
allowedOAuthRedirectUris: (url) => url.toString() === oauthRedirectUri,
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
databaseAdapter: yourDatabaseAdapter,
|
|
40
|
+
},
|
|
41
|
+
);
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Hooks
|
|
45
|
+
|
|
46
|
+
Hooks are durable: they run after the transaction that triggered them commits, and are retried on
|
|
47
|
+
failure.
|
|
48
|
+
|
|
49
|
+
- `onServerReadinessChanged` receives `{ serverId, ready }` when a write changes whether stored auth
|
|
50
|
+
can authorize operations: on creation, and afterwards whenever credentials, consent, or tokens
|
|
51
|
+
flip readiness, including tokens the server rejects during an operation. Expiry without a write
|
|
52
|
+
does not trigger it.
|
|
53
|
+
- `onServerConfigurationChanged` receives `{ serverId, current: { tools } }` when a refresh finds a
|
|
54
|
+
different tool list.
|
|
55
|
+
- `onServerConfigurationDeleted` receives `{ serverId }` when a server is deleted.
|
|
56
|
+
|
|
57
|
+
## CLI
|
|
58
|
+
|
|
59
|
+
The package ships a small local CLI for trying remote MCP servers from disk-backed SQLite storage.
|
|
60
|
+
It runs the MCP fragment locally, migrates the SQLite database on startup when needed, and stores
|
|
61
|
+
data under `~/.fragno/mcp-fragment` by default.
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Terminal 1: start the local fragment server.
|
|
65
|
+
fragno-mcp serve
|
|
66
|
+
|
|
67
|
+
# From this repository, run the same command through pnpm:
|
|
68
|
+
pnpm --filter @fragno-dev/mcp-fragment cli -- serve
|
|
69
|
+
|
|
70
|
+
# Terminal 2: register a remote Streamable HTTP MCP server.
|
|
71
|
+
fragno-mcp add my-tools https://mcp.example.com/mcp
|
|
72
|
+
|
|
73
|
+
# Start OAuth for that server. Keep `serve` running so it can handle the callback.
|
|
74
|
+
fragno-mcp oauth my-tools --scope tools
|
|
75
|
+
|
|
76
|
+
# Check auth state.
|
|
77
|
+
fragno-mcp status my-tools
|
|
78
|
+
|
|
79
|
+
# Retrieve the remote MCP tools.
|
|
80
|
+
fragno-mcp tools my-tools
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Defaults:
|
|
84
|
+
|
|
85
|
+
- local base URL: `http://127.0.0.1:3927`
|
|
86
|
+
- fragment mount route: `/api/mcp-fragment`
|
|
87
|
+
- SQLite data directory: `~/.fragno/mcp-fragment`
|
|
88
|
+
|
|
89
|
+
Useful options:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
fragno-mcp serve --port 4000 --data-dir ./mcp-data
|
|
93
|
+
fragno-mcp oauth my-tools --client-id ... --client-secret ... --no-open
|
|
94
|
+
fragno-mcp tools my-tools --json
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
For `add`, the CLI registers the server with `auth: { type: "none" }`; run `oauth` afterwards for
|
|
98
|
+
OAuth-backed servers. Keep `fragno-mcp serve` running while authorizing so the remote OAuth provider
|
|
99
|
+
can redirect back to `/api/mcp-fragment/oauth/callback`.
|
|
100
|
+
|
|
101
|
+
## Client helpers
|
|
102
|
+
|
|
103
|
+
```ts
|
|
104
|
+
import { createMcpFragmentClients } from "@fragno-dev/mcp-fragment";
|
|
105
|
+
|
|
106
|
+
const mcp = createMcpFragmentClients({ baseUrl: "/mcp" });
|
|
107
|
+
|
|
108
|
+
// Hooks
|
|
109
|
+
mcp.useServers;
|
|
110
|
+
mcp.useServer;
|
|
111
|
+
|
|
112
|
+
// Mutators
|
|
113
|
+
mcp.createServer;
|
|
114
|
+
mcp.refreshServer;
|
|
115
|
+
mcp.setToken;
|
|
116
|
+
mcp.startOAuth;
|
|
117
|
+
mcp.deleteAuth;
|
|
118
|
+
mcp.callTool;
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Routes
|
|
122
|
+
|
|
123
|
+
Server management:
|
|
124
|
+
|
|
125
|
+
- `POST /servers` - register an MCP server.
|
|
126
|
+
- `GET /servers` - list registered servers.
|
|
127
|
+
- `GET /servers/:slug` - get one registered server.
|
|
128
|
+
- `DELETE /servers/:slug` - delete a server and its auth/cache state.
|
|
129
|
+
|
|
130
|
+
Auth:
|
|
131
|
+
|
|
132
|
+
- `GET /servers/:slug/auth/status` - report auth mode and whether usable auth is stored.
|
|
133
|
+
- `POST /servers/:slug/auth/token` - store or replace a bearer token.
|
|
134
|
+
- `POST /servers/:slug/auth/start` - start OAuth authorization-code + PKCE with an explicit
|
|
135
|
+
`redirectUri` query parameter.
|
|
136
|
+
- `GET /oauth/callback` - complete OAuth authorization-code + PKCE.
|
|
137
|
+
- `DELETE /servers/:slug/auth` - delete auth state and switch the server to `none` auth.
|
|
138
|
+
|
|
139
|
+
Tools:
|
|
140
|
+
|
|
141
|
+
- `POST /servers/:slug/refresh` - connect to the MCP server, refresh cached tools, and return live
|
|
142
|
+
diagnostics.
|
|
143
|
+
- `POST /servers/:slug/tools/execute` - connect to the MCP server and call one tool.
|
|
144
|
+
|
|
145
|
+
## Registering servers
|
|
146
|
+
|
|
147
|
+
No auth:
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
await mcp.createServer.mutate({
|
|
151
|
+
slug: "local-tools",
|
|
152
|
+
endpointUrl: "https://mcp.example.com/mcp",
|
|
153
|
+
auth: { type: "none" },
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Bearer token auth:
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
await mcp.createServer.mutate({
|
|
161
|
+
slug: "private-tools",
|
|
162
|
+
endpointUrl: "https://mcp.example.com/mcp",
|
|
163
|
+
auth: { type: "bearer", token: "..." },
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Later replacement:
|
|
167
|
+
await mcp.setToken.mutate({ token: "new-token" }, { pathParams: { slug: "private-tools" } });
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
Client credentials auth:
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
await mcp.createServer.mutate({
|
|
174
|
+
slug: "machine-tools",
|
|
175
|
+
endpointUrl: "https://mcp.example.com/mcp",
|
|
176
|
+
auth: {
|
|
177
|
+
type: "client_credentials",
|
|
178
|
+
clientId: "...",
|
|
179
|
+
clientSecret: "...",
|
|
180
|
+
scopes: ["tools"],
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
The fragment acquires an access token before the first tool operation, stores it with its expiry,
|
|
186
|
+
and reuses it until it is close to expiring.
|
|
187
|
+
|
|
188
|
+
OAuth auth:
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
await mcp.createServer.mutate({
|
|
192
|
+
slug: "oauth-tools",
|
|
193
|
+
endpointUrl: "https://mcp.example.com/mcp",
|
|
194
|
+
auth: { type: "oauth" },
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## OAuth flow
|
|
199
|
+
|
|
200
|
+
The OAuth flow uses the official MCP TypeScript SDK auth APIs with a fragment-owned DB-backed
|
|
201
|
+
`OAuthClientProvider`.
|
|
202
|
+
|
|
203
|
+
### 1. Start authorization
|
|
204
|
+
|
|
205
|
+
Call `POST /servers/:slug/auth/start`:
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
const start = await mcp.startOAuth.mutate(
|
|
209
|
+
{
|
|
210
|
+
// Optional OAuth scope string.
|
|
211
|
+
scope: "tools",
|
|
212
|
+
// Optional static/pre-registered OAuth client. Persisted for the callback.
|
|
213
|
+
clientId: "...",
|
|
214
|
+
clientSecret: "...",
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
pathParams: { slug: "oauth-tools" },
|
|
218
|
+
query: { redirectUri: oauthRedirectUri },
|
|
219
|
+
},
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
window.location.href = start.authorizationUrl;
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
The route:
|
|
226
|
+
|
|
227
|
+
1. Loads the MCP server by slug.
|
|
228
|
+
2. Creates a DB-backed SDK `OAuthClientProvider` for that server.
|
|
229
|
+
3. Calls the SDK `auth(...)` helper.
|
|
230
|
+
4. Lets the SDK discover OAuth protected-resource metadata and authorization-server metadata.
|
|
231
|
+
5. Lets the SDK perform dynamic client registration when required.
|
|
232
|
+
6. Generates PKCE verifier/challenge and an authorization URL.
|
|
233
|
+
7. Stores the OAuth state, PKCE verifier, validated redirect URI, requested scope, discovery state,
|
|
234
|
+
and client information in the fragment DB/secret tables.
|
|
235
|
+
8. Returns `{ authorizationUrl, state }`.
|
|
236
|
+
|
|
237
|
+
### 2. User authorizes with the OAuth server
|
|
238
|
+
|
|
239
|
+
Redirect the browser to `authorizationUrl`. The OAuth server eventually redirects back to the
|
|
240
|
+
fragment callback URL with `code` and `state` query parameters.
|
|
241
|
+
|
|
242
|
+
### 3. Complete callback
|
|
243
|
+
|
|
244
|
+
The mounted fragment handles:
|
|
245
|
+
|
|
246
|
+
```http
|
|
247
|
+
GET /oauth/callback?code=...&state=...&iss=...
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The callback route:
|
|
251
|
+
|
|
252
|
+
1. Validates that `code` and `state` exist.
|
|
253
|
+
2. Loads the pending one-time OAuth state from the DB.
|
|
254
|
+
3. Rejects missing, expired, or already consumed states.
|
|
255
|
+
4. Recreates the DB-backed SDK `OAuthClientProvider` for the matching server.
|
|
256
|
+
5. Calls SDK `auth(...)` with the authorization code and callback `iss` parameter. The SDK rejects
|
|
257
|
+
an issuer mismatch before token exchange, and requires `iss` when the authorization server
|
|
258
|
+
advertises support for it. Custom callback forwarding must preserve `iss` alongside `code` and
|
|
259
|
+
`state`.
|
|
260
|
+
6. Lets the SDK exchange the code + PKCE verifier for tokens.
|
|
261
|
+
7. Stores access token, refresh token, token type, scope, and expiry in stored secret payloads.
|
|
262
|
+
8. Marks the OAuth state as consumed only after successful token exchange.
|
|
263
|
+
9. Returns `{ authenticated: true, mode: "oauth" }`.
|
|
264
|
+
|
|
265
|
+
### 4. Tool operations use stored OAuth tokens
|
|
266
|
+
|
|
267
|
+
After callback completion, `POST /servers/:slug/refresh` and `POST /servers/:slug/tools/execute`
|
|
268
|
+
read the stored OAuth token payload from the DB and send the access token as a bearer token when
|
|
269
|
+
connecting to the MCP server.
|
|
270
|
+
|
|
271
|
+
The fragment still connects per operation. MCP 2026-07-28 is sessionless. When connecting to an
|
|
272
|
+
older server, MCP session IDs are used only inside a single operation by the SDK transport and are
|
|
273
|
+
not stored or reused across requests. OAuth credentials retain the SDK's issuer binding, and OAuth
|
|
274
|
+
discovery state persists across requests.
|
|
275
|
+
|
|
276
|
+
## Calling tools
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
const refresh = await mcp.refreshServer.mutate({}, { pathParams: { slug: "oauth-tools" } });
|
|
280
|
+
const tools = refresh.tools;
|
|
281
|
+
|
|
282
|
+
const result = await mcp.callTool.mutate(
|
|
283
|
+
{
|
|
284
|
+
name: "echo",
|
|
285
|
+
arguments: { text: "hello" },
|
|
286
|
+
timeoutMs: 10_000,
|
|
287
|
+
},
|
|
288
|
+
{ pathParams: { slug: "oauth-tools" } },
|
|
289
|
+
);
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Security notes
|
|
293
|
+
|
|
294
|
+
- Always provide `allowedEndpointUrls` in production to prevent SSRF.
|
|
295
|
+
- Auth payloads and OAuth state are serialized as JSON in the fragment database, not encrypted by
|
|
296
|
+
this package. Integrators must provide encrypted-at-rest storage and appropriate access controls
|
|
297
|
+
to keep refresh tokens and other credentials confidential.
|
|
298
|
+
- OAuth state is one-time use and expires after 10 minutes.
|
|
299
|
+
- Deleting a server deletes stored auth, pending OAuth state, and cached tools.
|
|
300
|
+
- `DELETE /servers/:slug/auth` deletes auth state and switches that server back to `none` auth.
|
|
301
|
+
|
|
302
|
+
## Build
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
pnpm run types:check
|
|
306
|
+
pnpm run build
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Test
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
pnpm run test
|
|
313
|
+
```
|
package/bin/run.js
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { a as FragnoClientRequestError, c as InferOr, d as MaybeExtractPathParamsOrWiden, f as QueryParamsHint, i as ReadableAtom, l as ExtractPathParamsOrWiden, o as NonGetHTTPMethod, r as FetcherValue, s as FragnoPublicClientConfig, u as HasPathParams } from "../client-BCzNDSlW.js";
|
|
2
|
+
import { StandardSchemaV1 } from "@standard-schema/spec";
|
|
3
|
+
//#region ../fragno/dist/client/react.d.ts
|
|
4
|
+
//#region src/client/react.d.ts
|
|
5
|
+
type FragnoReactHook<_TMethod extends "GET", TPath extends string, TOutputSchema extends StandardSchemaV1, TErrorCode extends string, TQueryParameters extends string> = (args?: {
|
|
6
|
+
path?: MaybeExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>>;
|
|
7
|
+
query?: QueryParamsHint<TQueryParameters, string | ReadableAtom<string>>;
|
|
8
|
+
}) => FetcherValue<StandardSchemaV1.InferOutput<TOutputSchema>, FragnoClientRequestError<NonNullable<TErrorCode>>> & {
|
|
9
|
+
refetch: () => void;
|
|
10
|
+
};
|
|
11
|
+
type FragnoReactMutator<_TMethod extends NonGetHTTPMethod, TPath extends string, TInputSchema extends StandardSchemaV1 | undefined, TOutputSchema extends StandardSchemaV1 | undefined, TErrorCode extends string, TQueryParameters extends string> = () => {
|
|
12
|
+
mutate: ({ body, path, query }: {
|
|
13
|
+
body?: InferOr<TInputSchema, undefined>;
|
|
14
|
+
path?: HasPathParams<TPath> extends true ? ExtractPathParamsOrWiden<TPath, string | ReadableAtom<string>> : undefined;
|
|
15
|
+
query?: QueryParamsHint<TQueryParameters, string | ReadableAtom<string>>;
|
|
16
|
+
}) => Promise<InferOr<TOutputSchema, undefined>>;
|
|
17
|
+
loading?: boolean | undefined;
|
|
18
|
+
error?: FragnoClientRequestError<NonNullable<TErrorCode>[number]> | undefined;
|
|
19
|
+
data?: InferOr<TOutputSchema, undefined> | undefined;
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/client/react.d.ts
|
|
23
|
+
export declare function createMcpFragmentClient(config?: FragnoPublicClientConfig): {
|
|
24
|
+
useServers: FragnoReactHook<"GET", "/servers", import("zod").ZodObject<{
|
|
25
|
+
servers: import("zod").ZodArray<import("zod").ZodObject<{
|
|
26
|
+
slug: import("zod").ZodString;
|
|
27
|
+
name: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
28
|
+
endpointUrl: import("zod").ZodString;
|
|
29
|
+
authMode: import("zod").ZodString;
|
|
30
|
+
cache: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
|
|
31
|
+
protocolVersion: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
32
|
+
serverInfo: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodUnknown>>;
|
|
33
|
+
capabilities: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodUnknown>>;
|
|
34
|
+
tools: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodArray<import("zod").ZodObject<{
|
|
35
|
+
name: import("zod").ZodString;
|
|
36
|
+
title: import("zod").ZodOptional<import("zod").ZodString>;
|
|
37
|
+
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
38
|
+
inputSchema: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
|
|
39
|
+
outputSchema: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
40
|
+
annotations: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
41
|
+
_meta: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
42
|
+
}, import("zod/v4/core").$loose>>>>;
|
|
43
|
+
updatedAt: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodDate]>>;
|
|
44
|
+
}, import("zod/v4/core").$strip>>>;
|
|
45
|
+
}, import("zod/v4/core").$strip>>;
|
|
46
|
+
}, import("zod/v4/core").$strip>, string, string>;
|
|
47
|
+
useServer: FragnoReactHook<"GET", "/servers/:slug", import("zod").ZodObject<{
|
|
48
|
+
slug: import("zod").ZodString;
|
|
49
|
+
name: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
50
|
+
endpointUrl: import("zod").ZodString;
|
|
51
|
+
authMode: import("zod").ZodString;
|
|
52
|
+
cache: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
|
|
53
|
+
protocolVersion: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
54
|
+
serverInfo: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodUnknown>>;
|
|
55
|
+
capabilities: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodUnknown>>;
|
|
56
|
+
tools: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodArray<import("zod").ZodObject<{
|
|
57
|
+
name: import("zod").ZodString;
|
|
58
|
+
title: import("zod").ZodOptional<import("zod").ZodString>;
|
|
59
|
+
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
60
|
+
inputSchema: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
|
|
61
|
+
outputSchema: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
62
|
+
annotations: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
63
|
+
_meta: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
64
|
+
}, import("zod/v4/core").$loose>>>>;
|
|
65
|
+
updatedAt: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodDate]>>;
|
|
66
|
+
}, import("zod/v4/core").$strip>>>;
|
|
67
|
+
}, import("zod/v4/core").$strip>, "SERVER_NOT_FOUND", string>;
|
|
68
|
+
createServer: FragnoReactMutator<NonGetHTTPMethod, "/servers", import("@standard-schema/spec").StandardSchemaV1<unknown, unknown> | import("zod").ZodObject<{
|
|
69
|
+
slug: import("zod").ZodString;
|
|
70
|
+
name: import("zod").ZodOptional<import("zod").ZodString>;
|
|
71
|
+
endpointUrl: import("zod").ZodURL;
|
|
72
|
+
auth: import("zod").ZodDefault<import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
|
|
73
|
+
type: import("zod").ZodLiteral<"none">;
|
|
74
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
75
|
+
type: import("zod").ZodLiteral<"bearer">;
|
|
76
|
+
token: import("zod").ZodString;
|
|
77
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
78
|
+
type: import("zod").ZodLiteral<"client_credentials">;
|
|
79
|
+
clientId: import("zod").ZodString;
|
|
80
|
+
clientSecret: import("zod").ZodString;
|
|
81
|
+
scopes: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
|
|
82
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
83
|
+
type: import("zod").ZodLiteral<"oauth">;
|
|
84
|
+
clientId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
85
|
+
clientSecret: import("zod").ZodOptional<import("zod").ZodString>;
|
|
86
|
+
scopes: import("zod").ZodOptional<import("zod").ZodArray<import("zod").ZodString>>;
|
|
87
|
+
}, import("zod/v4/core").$strip>], "type">>;
|
|
88
|
+
}, import("zod/v4/core").$strip> | undefined, import("zod").ZodObject<{
|
|
89
|
+
slug: import("zod").ZodString;
|
|
90
|
+
name: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
91
|
+
endpointUrl: import("zod").ZodString;
|
|
92
|
+
authMode: import("zod").ZodString;
|
|
93
|
+
cache: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
|
|
94
|
+
protocolVersion: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
95
|
+
serverInfo: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodUnknown>>;
|
|
96
|
+
capabilities: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodUnknown>>;
|
|
97
|
+
tools: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodArray<import("zod").ZodObject<{
|
|
98
|
+
name: import("zod").ZodString;
|
|
99
|
+
title: import("zod").ZodOptional<import("zod").ZodString>;
|
|
100
|
+
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
101
|
+
inputSchema: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
|
|
102
|
+
outputSchema: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
103
|
+
annotations: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
104
|
+
_meta: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
105
|
+
}, import("zod/v4/core").$loose>>>>;
|
|
106
|
+
updatedAt: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodDate]>>;
|
|
107
|
+
}, import("zod/v4/core").$strip>>>;
|
|
108
|
+
}, import("zod/v4/core").$strip> | import("zod").ZodObject<{
|
|
109
|
+
servers: import("zod").ZodArray<import("zod").ZodObject<{
|
|
110
|
+
slug: import("zod").ZodString;
|
|
111
|
+
name: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
112
|
+
endpointUrl: import("zod").ZodString;
|
|
113
|
+
authMode: import("zod").ZodString;
|
|
114
|
+
cache: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodObject<{
|
|
115
|
+
protocolVersion: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
116
|
+
serverInfo: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodUnknown>>;
|
|
117
|
+
capabilities: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodUnknown>>;
|
|
118
|
+
tools: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodArray<import("zod").ZodObject<{
|
|
119
|
+
name: import("zod").ZodString;
|
|
120
|
+
title: import("zod").ZodOptional<import("zod").ZodString>;
|
|
121
|
+
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
122
|
+
inputSchema: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
|
|
123
|
+
outputSchema: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
124
|
+
annotations: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
125
|
+
_meta: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
126
|
+
}, import("zod/v4/core").$loose>>>>;
|
|
127
|
+
updatedAt: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodDate]>>;
|
|
128
|
+
}, import("zod/v4/core").$strip>>>;
|
|
129
|
+
}, import("zod/v4/core").$strip>>;
|
|
130
|
+
}, import("zod/v4/core").$strip> | undefined, string, string>;
|
|
131
|
+
refreshServer: FragnoReactMutator<NonGetHTTPMethod, "/servers/:slug/refresh", import("@standard-schema/spec").StandardSchemaV1<unknown, unknown> | undefined, import("zod").ZodObject<{
|
|
132
|
+
ok: import("zod").ZodBoolean;
|
|
133
|
+
tools: import("zod").ZodArray<import("zod").ZodObject<{
|
|
134
|
+
name: import("zod").ZodString;
|
|
135
|
+
title: import("zod").ZodOptional<import("zod").ZodString>;
|
|
136
|
+
description: import("zod").ZodOptional<import("zod").ZodString>;
|
|
137
|
+
inputSchema: import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>;
|
|
138
|
+
outputSchema: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
139
|
+
annotations: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
140
|
+
_meta: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
141
|
+
}, import("zod/v4/core").$loose>>;
|
|
142
|
+
stage: import("zod").ZodNullable<import("zod").ZodEnum<{
|
|
143
|
+
auth: "auth";
|
|
144
|
+
list_tools: "list_tools";
|
|
145
|
+
}>>;
|
|
146
|
+
checkedAt: import("zod").ZodString;
|
|
147
|
+
server: import("zod").ZodObject<{
|
|
148
|
+
name: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
|
|
149
|
+
endpointUrl: import("zod").ZodString;
|
|
150
|
+
authMode: import("zod").ZodString;
|
|
151
|
+
slug: import("zod").ZodString;
|
|
152
|
+
}, import("zod/v4/core").$strip>;
|
|
153
|
+
auth: import("zod").ZodObject<{
|
|
154
|
+
authenticated: import("zod").ZodBoolean;
|
|
155
|
+
mode: import("zod").ZodString;
|
|
156
|
+
tokenPresent: import("zod").ZodBoolean;
|
|
157
|
+
expiresAt: import("zod").ZodNullable<import("zod").ZodUnion<readonly [import("zod").ZodString, import("zod").ZodDate]>>;
|
|
158
|
+
expired: import("zod").ZodNullable<import("zod").ZodBoolean>;
|
|
159
|
+
scopes: import("zod").ZodObject<{
|
|
160
|
+
requested: import("zod").ZodNullable<import("zod").ZodArray<import("zod").ZodString>>;
|
|
161
|
+
granted: import("zod").ZodNullable<import("zod").ZodArray<import("zod").ZodString>>;
|
|
162
|
+
missing: import("zod").ZodNullable<import("zod").ZodArray<import("zod").ZodString>>;
|
|
163
|
+
raw: import("zod").ZodNullable<import("zod").ZodString>;
|
|
164
|
+
}, import("zod/v4/core").$strip>;
|
|
165
|
+
}, import("zod/v4/core").$strip>;
|
|
166
|
+
live: import("zod").ZodObject<{
|
|
167
|
+
reachable: import("zod").ZodBoolean;
|
|
168
|
+
listToolsOk: import("zod").ZodBoolean;
|
|
169
|
+
toolCount: import("zod").ZodNullable<import("zod").ZodNumber>;
|
|
170
|
+
protocolVersion: import("zod").ZodNullable<import("zod").ZodString>;
|
|
171
|
+
serverInfo: import("zod").ZodNullable<import("zod").ZodUnknown>;
|
|
172
|
+
capabilities: import("zod").ZodNullable<import("zod").ZodUnknown>;
|
|
173
|
+
}, import("zod/v4/core").$strip>;
|
|
174
|
+
cache: import("zod").ZodObject<{
|
|
175
|
+
presentBeforeCheck: import("zod").ZodBoolean;
|
|
176
|
+
previousToolCount: import("zod").ZodNullable<import("zod").ZodNumber>;
|
|
177
|
+
updatedToolCount: import("zod").ZodNullable<import("zod").ZodNumber>;
|
|
178
|
+
}, import("zod/v4/core").$strip>;
|
|
179
|
+
error: import("zod").ZodNullable<import("zod").ZodObject<{
|
|
180
|
+
code: import("zod").ZodString;
|
|
181
|
+
message: import("zod").ZodString;
|
|
182
|
+
}, import("zod/v4/core").$strip>>;
|
|
183
|
+
}, import("zod/v4/core").$strip> | undefined, "SERVER_NOT_FOUND", string>;
|
|
184
|
+
callTool: FragnoReactMutator<NonGetHTTPMethod, "/servers/:slug/tools/execute", import("zod").ZodObject<{
|
|
185
|
+
name: import("zod").ZodString;
|
|
186
|
+
arguments: import("zod").ZodOptional<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
187
|
+
timeoutMs: import("zod").ZodOptional<import("zod").ZodNumber>;
|
|
188
|
+
}, import("zod/v4/core").$strip> | undefined, import("zod").ZodObject<{
|
|
189
|
+
isError: import("zod").ZodBoolean;
|
|
190
|
+
content: import("zod").ZodArray<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>;
|
|
191
|
+
structuredContent: import("zod").ZodUnknown;
|
|
192
|
+
}, import("zod/v4/core").$strip> | undefined, "SERVER_NOT_FOUND" | "MCP_ERROR", string>;
|
|
193
|
+
setToken: FragnoReactMutator<NonGetHTTPMethod, "/servers/:slug/auth/token", import("zod").ZodObject<{
|
|
194
|
+
token: import("zod").ZodString;
|
|
195
|
+
}, import("zod/v4/core").$strip> | undefined, import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
|
|
196
|
+
mode: import("zod").ZodLiteral<"none">;
|
|
197
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
198
|
+
mode: import("zod").ZodLiteral<"bearer">;
|
|
199
|
+
credentials: import("zod").ZodEnum<{
|
|
200
|
+
present: "present";
|
|
201
|
+
missing: "missing";
|
|
202
|
+
}>;
|
|
203
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
204
|
+
mode: import("zod").ZodLiteral<"client_credentials">;
|
|
205
|
+
credentials: import("zod").ZodEnum<{
|
|
206
|
+
present: "present";
|
|
207
|
+
missing: "missing";
|
|
208
|
+
}>;
|
|
209
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
210
|
+
mode: import("zod").ZodLiteral<"oauth">;
|
|
211
|
+
state: import("zod").ZodEnum<{
|
|
212
|
+
"consent-required": "consent-required";
|
|
213
|
+
"consent-pending": "consent-pending";
|
|
214
|
+
authorized: "authorized";
|
|
215
|
+
expired: "expired";
|
|
216
|
+
}>;
|
|
217
|
+
}, import("zod/v4/core").$strip>], "mode"> | undefined, "SERVER_NOT_FOUND", string>;
|
|
218
|
+
startOAuth: FragnoReactMutator<NonGetHTTPMethod, "/servers/:slug/auth/start", import("zod").ZodObject<{
|
|
219
|
+
scope: import("zod").ZodOptional<import("zod").ZodString>;
|
|
220
|
+
clientId: import("zod").ZodOptional<import("zod").ZodString>;
|
|
221
|
+
clientSecret: import("zod").ZodOptional<import("zod").ZodString>;
|
|
222
|
+
discardTokens: import("zod").ZodDefault<import("zod").ZodBoolean>;
|
|
223
|
+
}, import("zod/v4/core").$strip> | undefined, import("zod").ZodObject<{
|
|
224
|
+
authorizationUrl: import("zod").ZodString;
|
|
225
|
+
state: import("zod").ZodString;
|
|
226
|
+
}, import("zod/v4/core").$strip> | undefined, "SERVER_NOT_FOUND" | "INVALID_OAUTH_REDIRECT_URI" | "OAUTH_REDIRECT_URI_NOT_ALLOWED" | "OAUTH_ERROR", string>;
|
|
227
|
+
deleteAuth: FragnoReactMutator<NonGetHTTPMethod, "/servers/:slug/auth", import("@standard-schema/spec").StandardSchemaV1<unknown, unknown> | undefined, import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
|
|
228
|
+
mode: import("zod").ZodLiteral<"none">;
|
|
229
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
230
|
+
mode: import("zod").ZodLiteral<"bearer">;
|
|
231
|
+
credentials: import("zod").ZodEnum<{
|
|
232
|
+
present: "present";
|
|
233
|
+
missing: "missing";
|
|
234
|
+
}>;
|
|
235
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
236
|
+
mode: import("zod").ZodLiteral<"client_credentials">;
|
|
237
|
+
credentials: import("zod").ZodEnum<{
|
|
238
|
+
present: "present";
|
|
239
|
+
missing: "missing";
|
|
240
|
+
}>;
|
|
241
|
+
}, import("zod/v4/core").$strip>, import("zod").ZodObject<{
|
|
242
|
+
mode: import("zod").ZodLiteral<"oauth">;
|
|
243
|
+
state: import("zod").ZodEnum<{
|
|
244
|
+
"consent-required": "consent-required";
|
|
245
|
+
"consent-pending": "consent-pending";
|
|
246
|
+
authorized: "authorized";
|
|
247
|
+
expired: "expired";
|
|
248
|
+
}>;
|
|
249
|
+
}, import("zod/v4/core").$strip>], "mode"> | undefined, "SERVER_NOT_FOUND", string>;
|
|
250
|
+
};
|
|
251
|
+
//#endregion
|
|
252
|
+
export {};
|
|
253
|
+
//# sourceMappingURL=react.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.d.ts","names":["_$_fragno_dev_core_react0.FragnoReactHook","_$_fragno_dev_core_api0.NonGetHTTPMethod","_$_fragno_dev_core_react0.FragnoReactMutator"],"sources":["../../../../fragno/dist/client/react.d.ts","../../../src/client/react.ts"],"mappings":";;;;KASK,gBAAgB,wBAAwB,sBAAsB,sBAAsB,kBAAkB,2BAA2B,oCAAoC;EACxK,OAAO,8BAA8B,gBAAgB;EACrD,QAAQ,gBAAgB,2BAA2B;MAC/C,aAAa,iBAAiB,YAAY,gBAAgB,yBAAyB,YAAY;EACnG;;KAEG,mBAAmB,iBAAiB,kBAAkB,sBAAsB,qBAAqB,8BAA8B,sBAAsB,8BAA8B,2BAA2B;EACjN,WAAW,MAAM,MAAM;IACrB,OAAO,QAAQ;IACf,OAAO,cAAc,sBAAsB,yBAAyB,gBAAgB;IACpF,QAAQ,gBAAgB,2BAA2B;QAC/C,QAAQ,QAAQ;EACtB;EACA,QAAQ,yBAAyB,YAAY;EAC7C,OAAO,QAAQ;;;;wBClBD,wBAAwB,SAAQ;cAAAA"}
|