@decocms/mesh-sdk 1.1.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/README.md +368 -0
- package/package.json +51 -0
- package/src/context/index.ts +9 -0
- package/src/context/project-context.tsx +89 -0
- package/src/hooks/index.ts +73 -0
- package/src/hooks/use-collections.ts +357 -0
- package/src/hooks/use-connection.ts +82 -0
- package/src/hooks/use-mcp-client.ts +127 -0
- package/src/hooks/use-mcp-prompts.ts +126 -0
- package/src/hooks/use-mcp-resources.ts +128 -0
- package/src/hooks/use-mcp-tools.ts +184 -0
- package/src/hooks/use-virtual-mcp.ts +91 -0
- package/src/index.ts +128 -0
- package/src/lib/constants.ts +204 -0
- package/src/lib/mcp-oauth.ts +742 -0
- package/src/lib/query-keys.ts +178 -0
- package/src/lib/streamable-http-client-transport.ts +79 -0
- package/src/types/connection.ts +204 -0
- package/src/types/index.ts +27 -0
- package/src/types/virtual-mcp.ts +218 -0
- package/tsconfig.json +8 -0
package/README.md
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
# @decocms/mesh-sdk
|
|
2
|
+
|
|
3
|
+
SDK for building external apps that integrate with Mesh MCP servers. Provides React hooks and utilities for managing connections, authenticating with OAuth, and calling MCP tools.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @decocms/mesh-sdk @decocms/bindings
|
|
9
|
+
# or
|
|
10
|
+
bun add @decocms/mesh-sdk @decocms/bindings
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Peer Dependencies
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install react @tanstack/react-query
|
|
17
|
+
# Optional: for toast notifications
|
|
18
|
+
npm install sonner
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### 1. Create an API Key
|
|
24
|
+
|
|
25
|
+
In Mesh, call the `API_KEY_CREATE` tool to create an API key with the appropriate scopes for the connections you want to access. The API key will be used to authenticate your external app.
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
// Example: Create an API key via MCP
|
|
29
|
+
await client.callTool({
|
|
30
|
+
name: "API_KEY_CREATE",
|
|
31
|
+
arguments: {
|
|
32
|
+
name: "My External App",
|
|
33
|
+
scopes: ["connections:read", "connections:write"],
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### 2. Server-Side: Connect to Mesh
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
// server.ts (Node.js / Bun / your backend)
|
|
42
|
+
import { createMCPClient } from "@decocms/mesh-sdk";
|
|
43
|
+
|
|
44
|
+
// Create an MCP client - keep API key on server only!
|
|
45
|
+
const client = await createMCPClient({
|
|
46
|
+
meshUrl: "https://mesh.your-company.com", // Your Mesh server URL
|
|
47
|
+
connectionId: "self", // "self" for management API
|
|
48
|
+
orgId: "org_xxxxx", // Your organization ID
|
|
49
|
+
token: process.env.MESH_API_KEY, // API key from environment
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// List connections
|
|
53
|
+
const result = await client.callTool({
|
|
54
|
+
name: "COLLECTION_CONNECTIONS_LIST",
|
|
55
|
+
arguments: { limit: 100 },
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### 3. Client-Side: Set Up React App
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
// app.tsx (React client)
|
|
63
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
64
|
+
import { Toaster } from "sonner";
|
|
65
|
+
|
|
66
|
+
const queryClient = new QueryClient();
|
|
67
|
+
|
|
68
|
+
function App() {
|
|
69
|
+
return (
|
|
70
|
+
<QueryClientProvider client={queryClient}>
|
|
71
|
+
<YourApp />
|
|
72
|
+
<Toaster />
|
|
73
|
+
</QueryClientProvider>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Full Example: User Sandbox Integration
|
|
79
|
+
|
|
80
|
+
The most common use case for external apps is letting your end-users connect their own MCPs via the **User Sandbox plugin**. This creates isolated connections per user.
|
|
81
|
+
|
|
82
|
+
### Server-Side: Create a Connect Session
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
// server/api.ts (Hono / Express / your backend)
|
|
86
|
+
import { Hono } from "hono";
|
|
87
|
+
import { createMCPClient } from "@decocms/mesh-sdk";
|
|
88
|
+
|
|
89
|
+
const app = new Hono();
|
|
90
|
+
|
|
91
|
+
const MESH_URL = process.env.MESH_URL!;
|
|
92
|
+
const ORG_ID = process.env.MESH_ORG_ID!;
|
|
93
|
+
const API_KEY = process.env.MESH_API_KEY!;
|
|
94
|
+
|
|
95
|
+
let meshClient: Awaited<ReturnType<typeof createMCPClient>> | null = null;
|
|
96
|
+
|
|
97
|
+
async function getMeshClient() {
|
|
98
|
+
if (!meshClient) {
|
|
99
|
+
meshClient = await createMCPClient({
|
|
100
|
+
meshUrl: MESH_URL,
|
|
101
|
+
connectionId: "self",
|
|
102
|
+
orgId: ORG_ID,
|
|
103
|
+
token: API_KEY,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
return meshClient;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// POST /api/connect-session - Create a session for end-user to connect MCPs
|
|
110
|
+
app.post("/api/connect-session", async (c) => {
|
|
111
|
+
const { userId } = await c.req.json();
|
|
112
|
+
const client = await getMeshClient();
|
|
113
|
+
|
|
114
|
+
// Call User Sandbox plugin to create a connect session
|
|
115
|
+
const result = await client.callTool({
|
|
116
|
+
name: "USER_SANDBOX_CREATE_SESSION",
|
|
117
|
+
arguments: {
|
|
118
|
+
templateId: "your-template-id", // Created in Mesh dashboard
|
|
119
|
+
externalUserId: userId, // Your app's user ID
|
|
120
|
+
redirectUrl: "https://your-app.com/connect/complete",
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const payload = result as { structuredContent?: { sessionUrl: string } };
|
|
125
|
+
return c.json({ connectUrl: payload.structuredContent?.sessionUrl });
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
export default app;
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Client-Side: Redirect User to Connect
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
// client/connect-button.tsx (React)
|
|
135
|
+
|
|
136
|
+
function ConnectIntegrationsButton({ userId }: { userId: string }) {
|
|
137
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
138
|
+
|
|
139
|
+
const handleConnect = async () => {
|
|
140
|
+
setIsLoading(true);
|
|
141
|
+
|
|
142
|
+
// Get connect session URL from your server
|
|
143
|
+
const res = await fetch("/api/connect-session", {
|
|
144
|
+
method: "POST",
|
|
145
|
+
headers: { "Content-Type": "application/json" },
|
|
146
|
+
body: JSON.stringify({ userId }),
|
|
147
|
+
});
|
|
148
|
+
const { connectUrl } = await res.json();
|
|
149
|
+
|
|
150
|
+
// Redirect user to Mesh connect flow
|
|
151
|
+
window.location.href = connectUrl;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
return (
|
|
155
|
+
<button
|
|
156
|
+
onClick={handleConnect}
|
|
157
|
+
disabled={isLoading}
|
|
158
|
+
className="px-4 py-2 bg-blue-600 text-white rounded"
|
|
159
|
+
>
|
|
160
|
+
{isLoading ? "Loading..." : "Connect Your Apps"}
|
|
161
|
+
</button>
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Example: Direct MCP Tool Calls
|
|
167
|
+
|
|
168
|
+
For server-side automation or admin tasks, you can call any MCP tool directly:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
// server-side only
|
|
172
|
+
import { createMCPClient } from "@decocms/mesh-sdk";
|
|
173
|
+
|
|
174
|
+
const client = await createMCPClient({
|
|
175
|
+
meshUrl: "https://mesh.your-company.com",
|
|
176
|
+
connectionId: "self",
|
|
177
|
+
orgId: process.env.ORG_ID!,
|
|
178
|
+
token: process.env.MESH_API_KEY!,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
// List Virtual MCPs (agents)
|
|
182
|
+
const agents = await client.callTool({
|
|
183
|
+
name: "COLLECTION_VIRTUAL_MCP_LIST",
|
|
184
|
+
arguments: { limit: 100 },
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Create a connection
|
|
188
|
+
const newConn = await client.callTool({
|
|
189
|
+
name: "COLLECTION_CONNECTIONS_CREATE",
|
|
190
|
+
arguments: {
|
|
191
|
+
data: {
|
|
192
|
+
title: "My MCP Server",
|
|
193
|
+
url: "https://mcp.example.com/sse",
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// Call a tool on a specific connection
|
|
199
|
+
const specificClient = await createMCPClient({
|
|
200
|
+
meshUrl: "https://mesh.your-company.com",
|
|
201
|
+
connectionId: "conn_xxx", // Target connection ID
|
|
202
|
+
orgId: process.env.ORG_ID!,
|
|
203
|
+
token: process.env.MESH_API_KEY!,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const result = await specificClient.callTool({
|
|
207
|
+
name: "SOME_TOOL_ON_THAT_MCP",
|
|
208
|
+
arguments: { /* ... */ },
|
|
209
|
+
});
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## API Reference
|
|
213
|
+
|
|
214
|
+
### `createMCPClient(options)` - Server-Side
|
|
215
|
+
|
|
216
|
+
Creates and connects an MCP client to a Mesh server. **Use on server only** - don't expose your API key to the client.
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
// server-side only
|
|
220
|
+
const client = await createMCPClient({
|
|
221
|
+
meshUrl: "https://mesh.example.com", // Required for external apps
|
|
222
|
+
connectionId: "self", // "self" for management API, or connection ID
|
|
223
|
+
orgId: "org_xxx", // Organization ID
|
|
224
|
+
token: process.env.MESH_API_KEY, // API key from environment
|
|
225
|
+
});
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### `useMCPClient(options)` - Client-Side (Same-Origin Only)
|
|
229
|
+
|
|
230
|
+
React hook version of `createMCPClient`. Uses Suspense. **Only use when running on the same origin as Mesh** (e.g., inside the Mesh app itself).
|
|
231
|
+
|
|
232
|
+
```typescript
|
|
233
|
+
// client-side - only for same-origin apps
|
|
234
|
+
function MyComponent() {
|
|
235
|
+
const client = useMCPClient({
|
|
236
|
+
connectionId: "self",
|
|
237
|
+
orgId: "org_xxx",
|
|
238
|
+
// No token needed when using cookies on same origin
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
// client is ready to use
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### `authenticateMcp(options)` - Client-Side
|
|
246
|
+
|
|
247
|
+
Triggers OAuth authentication flow for an MCP connection. **This runs client-side** - it doesn't expose your API key.
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
// client-side - safe to use in browser
|
|
251
|
+
const result = await authenticateMcp({
|
|
252
|
+
meshUrl: "https://mesh.example.com", // Required for external apps
|
|
253
|
+
connectionId: "conn_xxx", // Connection to authenticate
|
|
254
|
+
callbackUrl: "https://your-app.com/oauth/callback", // Your OAuth callback URL
|
|
255
|
+
timeout: 120000, // Timeout in ms (default: 120000)
|
|
256
|
+
scope: ["read", "write"], // OAuth scopes (optional)
|
|
257
|
+
windowMode: "popup", // "popup" (default) or "tab"
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
if (result.error) {
|
|
261
|
+
console.error("Auth failed:", result.error);
|
|
262
|
+
} else {
|
|
263
|
+
console.log("Got token:", result.token);
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Window modes:**
|
|
268
|
+
- `"popup"` (default): Opens OAuth in a popup window. May be blocked on some mobile devices.
|
|
269
|
+
- `"tab"`: Opens OAuth in a new tab. Works on all devices. Uses localStorage for cross-tab communication.
|
|
270
|
+
|
|
271
|
+
### `isConnectionAuthenticated(options)` - Server or Client
|
|
272
|
+
|
|
273
|
+
Check if a connection is authenticated. Can be used on either server or client.
|
|
274
|
+
|
|
275
|
+
```typescript
|
|
276
|
+
const status = await isConnectionAuthenticated({
|
|
277
|
+
url: "https://mesh.example.com/mcp/conn_xxx",
|
|
278
|
+
token: "bearer_token", // Optional
|
|
279
|
+
meshUrl: "https://mesh.example.com", // For API calls
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
console.log(status.isAuthenticated); // boolean
|
|
283
|
+
console.log(status.supportsOAuth); // boolean
|
|
284
|
+
console.log(status.hasOAuthToken); // boolean
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Collection Hooks - Client-Side (Same-Origin Only)
|
|
288
|
+
|
|
289
|
+
When using with `ProjectContextProvider`, you get access to collection hooks. **Only use when running on the same origin as Mesh** (e.g., inside the Mesh app or plugins).
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
// client-side - only for same-origin apps (inside Mesh)
|
|
293
|
+
import {
|
|
294
|
+
ProjectContextProvider,
|
|
295
|
+
useConnections,
|
|
296
|
+
useConnection,
|
|
297
|
+
useConnectionActions,
|
|
298
|
+
} from "@decocms/mesh-sdk";
|
|
299
|
+
|
|
300
|
+
function App() {
|
|
301
|
+
return (
|
|
302
|
+
<ProjectContextProvider
|
|
303
|
+
org={{ id: "org_xxx", slug: "my-org", name: "My Org", logo: null }}
|
|
304
|
+
project={{ slug: "org-admin" }}
|
|
305
|
+
>
|
|
306
|
+
<ConnectionsManager />
|
|
307
|
+
</ProjectContextProvider>
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function ConnectionsManager() {
|
|
312
|
+
// List all connections
|
|
313
|
+
const connections = useConnections();
|
|
314
|
+
|
|
315
|
+
// Get single connection
|
|
316
|
+
const connection = useConnection("conn_xxx");
|
|
317
|
+
|
|
318
|
+
// CRUD actions
|
|
319
|
+
const { create, update, delete: remove } = useConnectionActions();
|
|
320
|
+
|
|
321
|
+
await create.mutateAsync({
|
|
322
|
+
title: "My MCP",
|
|
323
|
+
url: "https://mcp.example.com",
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## OAuth Callback Setup - Client-Side
|
|
329
|
+
|
|
330
|
+
If you're using `authenticateMcp()` directly (not via User Sandbox plugin), you need an OAuth callback route. This is a **client-side page** that receives the OAuth authorization code:
|
|
331
|
+
|
|
332
|
+
```tsx
|
|
333
|
+
// pages/oauth/callback.tsx (React client-side page)
|
|
334
|
+
export function OAuthCallback() {
|
|
335
|
+
const params = new URLSearchParams(window.location.search);
|
|
336
|
+
|
|
337
|
+
if (window.opener) {
|
|
338
|
+
window.opener.postMessage({
|
|
339
|
+
type: "mcp:oauth:callback",
|
|
340
|
+
success: !params.get("error"),
|
|
341
|
+
code: params.get("code"),
|
|
342
|
+
state: params.get("state"),
|
|
343
|
+
error: params.get("error"),
|
|
344
|
+
}, window.location.origin);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return <p>Authentication complete. You can close this window.</p>;
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
> **Note**: If you're using the User Sandbox plugin, OAuth is handled automatically in the connect flow - you don't need this callback page.
|
|
352
|
+
|
|
353
|
+
## Types
|
|
354
|
+
|
|
355
|
+
```typescript
|
|
356
|
+
import type {
|
|
357
|
+
ConnectionEntity,
|
|
358
|
+
ConnectionCreateData,
|
|
359
|
+
ConnectionUpdateData,
|
|
360
|
+
VirtualMCPEntity,
|
|
361
|
+
VirtualMCPCreateData,
|
|
362
|
+
VirtualMCPUpdateData,
|
|
363
|
+
} from "@decocms/mesh-sdk";
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## License
|
|
367
|
+
|
|
368
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@decocms/mesh-sdk",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "SDK for building external apps that integrate with Mesh MCP servers",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"check": "tsc --noEmit",
|
|
8
|
+
"test": "bun test"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./src/index.ts",
|
|
12
|
+
"./hooks": "./src/hooks/index.ts",
|
|
13
|
+
"./context": "./src/context/index.ts",
|
|
14
|
+
"./types": "./src/types/index.ts"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@decocms/bindings": "^1.1.1",
|
|
18
|
+
"@modelcontextprotocol/sdk": "1.25.2",
|
|
19
|
+
"zod": "^4.0.0"
|
|
20
|
+
},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"@tanstack/react-query": ">=5.0.0",
|
|
23
|
+
"react": ">=18.0.0",
|
|
24
|
+
"sonner": ">=2.0.0"
|
|
25
|
+
},
|
|
26
|
+
"peerDependenciesMeta": {
|
|
27
|
+
"sonner": {
|
|
28
|
+
"optional": true
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18.0.0"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"mesh",
|
|
36
|
+
"mcp",
|
|
37
|
+
"model-context-protocol",
|
|
38
|
+
"sdk",
|
|
39
|
+
"react",
|
|
40
|
+
"hooks"
|
|
41
|
+
],
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/decocms/admin.git",
|
|
45
|
+
"directory": "packages/mesh-sdk"
|
|
46
|
+
},
|
|
47
|
+
"license": "MIT",
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { createContext, useContext, type PropsWithChildren } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* a ProjectLocator is a github-like slug string that identifies a project in an organization.
|
|
5
|
+
*
|
|
6
|
+
* format: <org-slug>/<project-slug>
|
|
7
|
+
*/
|
|
8
|
+
export type ProjectLocator = `${string}/${string}`;
|
|
9
|
+
|
|
10
|
+
export type LocatorStructured = {
|
|
11
|
+
org: string;
|
|
12
|
+
project: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export const ORG_ADMIN_PROJECT_SLUG = "org-admin";
|
|
16
|
+
|
|
17
|
+
export const Locator = {
|
|
18
|
+
from({ org, project }: LocatorStructured): ProjectLocator {
|
|
19
|
+
if (org?.includes("/") || project.includes("/")) {
|
|
20
|
+
throw new Error("Org or project cannot contain slashes");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
return `${org}/${project}` as ProjectLocator;
|
|
24
|
+
},
|
|
25
|
+
parse(locator: ProjectLocator): LocatorStructured {
|
|
26
|
+
if (locator.startsWith("/")) {
|
|
27
|
+
locator = locator.slice(1) as ProjectLocator;
|
|
28
|
+
}
|
|
29
|
+
const [org, project] = locator.split("/");
|
|
30
|
+
if (!org || !project) {
|
|
31
|
+
throw new Error("Invalid locator");
|
|
32
|
+
}
|
|
33
|
+
return { org, project };
|
|
34
|
+
},
|
|
35
|
+
isOrgAdminProject(locator: ProjectLocator): boolean {
|
|
36
|
+
return locator.split("/")[1] === ORG_ADMIN_PROJECT_SLUG;
|
|
37
|
+
},
|
|
38
|
+
adminProject(org: string): ProjectLocator {
|
|
39
|
+
return `${org}/${ORG_ADMIN_PROJECT_SLUG}`;
|
|
40
|
+
},
|
|
41
|
+
} as const;
|
|
42
|
+
|
|
43
|
+
interface ProjectContextType {
|
|
44
|
+
org: {
|
|
45
|
+
id: string;
|
|
46
|
+
name: string;
|
|
47
|
+
slug: string;
|
|
48
|
+
logo: string | null;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
project: {
|
|
52
|
+
name?: string;
|
|
53
|
+
slug: string;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
locator: ProjectLocator;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const ProjectContext = createContext<ProjectContextType | undefined>(undefined);
|
|
60
|
+
|
|
61
|
+
export const useProjectContext = () => {
|
|
62
|
+
const context = useContext(ProjectContext);
|
|
63
|
+
if (!context) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
"useProjectContext must be used within a ProjectContextProvider",
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return context;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type ProjectContextProviderProps = {
|
|
73
|
+
org: { id: string; slug: string; name: string; logo: string | null };
|
|
74
|
+
project: { name?: string; slug: string };
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const ProjectContextProvider = ({
|
|
78
|
+
children,
|
|
79
|
+
org,
|
|
80
|
+
project,
|
|
81
|
+
}: PropsWithChildren<ProjectContextProviderProps>) => {
|
|
82
|
+
const locator = Locator.from({ org: org.slug, project: project.slug });
|
|
83
|
+
|
|
84
|
+
const value = { org, project, locator };
|
|
85
|
+
|
|
86
|
+
return (
|
|
87
|
+
<ProjectContext.Provider value={value}>{children}</ProjectContext.Provider>
|
|
88
|
+
);
|
|
89
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// Collection hooks
|
|
2
|
+
export {
|
|
3
|
+
useCollectionItem,
|
|
4
|
+
useCollectionList,
|
|
5
|
+
useCollectionActions,
|
|
6
|
+
type CollectionEntity,
|
|
7
|
+
type CollectionFilter,
|
|
8
|
+
type UseCollectionListOptions,
|
|
9
|
+
} from "./use-collections";
|
|
10
|
+
|
|
11
|
+
// Connection hooks
|
|
12
|
+
export {
|
|
13
|
+
useConnections,
|
|
14
|
+
useConnection,
|
|
15
|
+
useConnectionActions,
|
|
16
|
+
type ConnectionFilter,
|
|
17
|
+
type UseConnectionsOptions,
|
|
18
|
+
} from "./use-connection";
|
|
19
|
+
|
|
20
|
+
// MCP client hook and factory
|
|
21
|
+
export {
|
|
22
|
+
createMCPClient,
|
|
23
|
+
useMCPClient,
|
|
24
|
+
type CreateMcpClientOptions,
|
|
25
|
+
type UseMcpClientOptions,
|
|
26
|
+
} from "./use-mcp-client";
|
|
27
|
+
|
|
28
|
+
// MCP tools hooks
|
|
29
|
+
export {
|
|
30
|
+
useMCPToolsList,
|
|
31
|
+
useMCPToolsListQuery,
|
|
32
|
+
useMCPToolCall,
|
|
33
|
+
useMCPToolCallQuery,
|
|
34
|
+
useMCPToolCallMutation,
|
|
35
|
+
type UseMcpToolsListOptions,
|
|
36
|
+
type UseMcpToolsListQueryOptions,
|
|
37
|
+
type UseMcpToolCallOptions,
|
|
38
|
+
type UseMcpToolCallQueryOptions,
|
|
39
|
+
type UseMcpToolCallMutationOptions,
|
|
40
|
+
} from "./use-mcp-tools";
|
|
41
|
+
|
|
42
|
+
// MCP resources hooks and helpers
|
|
43
|
+
export {
|
|
44
|
+
listResources,
|
|
45
|
+
readResource,
|
|
46
|
+
useMCPResourcesList,
|
|
47
|
+
useMCPResourcesListQuery,
|
|
48
|
+
useMCPReadResource,
|
|
49
|
+
type UseMcpResourcesListOptions,
|
|
50
|
+
type UseMcpResourcesListQueryOptions,
|
|
51
|
+
type UseMcpReadResourceOptions,
|
|
52
|
+
} from "./use-mcp-resources";
|
|
53
|
+
|
|
54
|
+
// MCP prompts hooks and helpers
|
|
55
|
+
export {
|
|
56
|
+
listPrompts,
|
|
57
|
+
getPrompt,
|
|
58
|
+
useMCPPromptsList,
|
|
59
|
+
useMCPPromptsListQuery,
|
|
60
|
+
useMCPGetPrompt,
|
|
61
|
+
type UseMcpPromptsListOptions,
|
|
62
|
+
type UseMcpPromptsListQueryOptions,
|
|
63
|
+
type UseMcpGetPromptOptions,
|
|
64
|
+
} from "./use-mcp-prompts";
|
|
65
|
+
|
|
66
|
+
// Virtual MCP hooks
|
|
67
|
+
export {
|
|
68
|
+
useVirtualMCPs,
|
|
69
|
+
useVirtualMCP,
|
|
70
|
+
useVirtualMCPActions,
|
|
71
|
+
type VirtualMCPFilter,
|
|
72
|
+
type UseVirtualMCPsOptions,
|
|
73
|
+
} from "./use-virtual-mcp";
|