@stigmer/react 0.0.79 → 0.0.80
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/agent/AgentDetailView.js +2 -2
- package/agent/AgentDetailView.js.map +1 -1
- package/agent/agentSetupReducer.d.ts +3 -3
- package/agent/agentSetupReducer.d.ts.map +1 -1
- package/agent/index.d.ts +1 -1
- package/agent/index.d.ts.map +1 -1
- package/agent/index.js +1 -1
- package/agent/index.js.map +1 -1
- package/agent/useAgentSetup.d.ts +4 -4
- package/agent/useAgentSetup.js +9 -9
- package/agent/useAgentSetup.js.map +1 -1
- package/environment/EnvVarForm.d.ts +9 -3
- package/environment/EnvVarForm.d.ts.map +1 -1
- package/environment/EnvVarForm.js +1 -1
- package/environment/EnvVarForm.js.map +1 -1
- package/environment/EnvironmentListPanel.d.ts +19 -4
- package/environment/EnvironmentListPanel.d.ts.map +1 -1
- package/environment/EnvironmentListPanel.js +7 -3
- package/environment/EnvironmentListPanel.js.map +1 -1
- package/environment/{diffEnvSpec.d.ts → diffEnv.d.ts} +9 -8
- package/environment/diffEnv.d.ts.map +1 -0
- package/environment/{diffEnvSpec.js → diffEnv.js} +10 -9
- package/environment/diffEnv.js.map +1 -0
- package/environment/index.d.ts +1 -1
- package/environment/index.d.ts.map +1 -1
- package/environment/index.js +1 -1
- package/environment/index.js.map +1 -1
- package/execution/SessionVariablesInput.d.ts +1 -1
- package/index.d.ts +3 -3
- package/index.d.ts.map +1 -1
- package/index.js +3 -3
- package/index.js.map +1 -1
- package/library/parse-resource-yaml.d.ts +1 -1
- package/library/parse-resource-yaml.d.ts.map +1 -1
- package/library/parse-resource-yaml.js +26 -16
- package/library/parse-resource-yaml.js.map +1 -1
- package/library/serialize-resource-yaml.js +17 -21
- package/library/serialize-resource-yaml.js.map +1 -1
- package/mcp-server/McpServerDetailView.d.ts +8 -1
- package/mcp-server/McpServerDetailView.d.ts.map +1 -1
- package/mcp-server/McpServerDetailView.js +27 -6
- package/mcp-server/McpServerDetailView.js.map +1 -1
- package/mcp-server/McpServerPicker.d.ts +8 -1
- package/mcp-server/McpServerPicker.d.ts.map +1 -1
- package/mcp-server/McpServerPicker.js +2 -2
- package/mcp-server/McpServerPicker.js.map +1 -1
- package/mcp-server/index.d.ts +2 -0
- package/mcp-server/index.d.ts.map +1 -1
- package/mcp-server/index.js +1 -0
- package/mcp-server/index.js.map +1 -1
- package/mcp-server/mcpServerSetupReducer.d.ts +4 -4
- package/mcp-server/useMcpServerCredentials.d.ts +32 -17
- package/mcp-server/useMcpServerCredentials.d.ts.map +1 -1
- package/mcp-server/useMcpServerCredentials.js +30 -19
- package/mcp-server/useMcpServerCredentials.js.map +1 -1
- package/mcp-server/useMcpServerSetup.d.ts +5 -5
- package/mcp-server/useMcpServerSetup.d.ts.map +1 -1
- package/mcp-server/useMcpServerSetup.js +33 -13
- package/mcp-server/useMcpServerSetup.js.map +1 -1
- package/mcp-server/useOAuthGrantStatus.d.ts +41 -0
- package/mcp-server/useOAuthGrantStatus.d.ts.map +1 -0
- package/mcp-server/useOAuthGrantStatus.js +91 -0
- package/mcp-server/useOAuthGrantStatus.js.map +1 -0
- package/package.json +4 -4
- package/src/agent/AgentDetailView.tsx +5 -5
- package/src/agent/agentSetupReducer.ts +3 -3
- package/src/agent/index.ts +1 -1
- package/src/agent/useAgentSetup.ts +11 -11
- package/src/environment/EnvVarForm.tsx +9 -3
- package/src/environment/EnvironmentListPanel.tsx +27 -9
- package/src/environment/{diffEnvSpec.ts → diffEnv.ts} +10 -9
- package/src/environment/index.ts +1 -1
- package/src/execution/SessionVariablesInput.tsx +1 -1
- package/src/index.ts +4 -2
- package/src/library/parse-resource-yaml.ts +27 -18
- package/src/library/serialize-resource-yaml.ts +20 -27
- package/src/mcp-server/McpServerDetailView.tsx +39 -7
- package/src/mcp-server/McpServerPicker.tsx +9 -1
- package/src/mcp-server/index.ts +3 -0
- package/src/mcp-server/mcpServerSetupReducer.ts +4 -4
- package/src/mcp-server/useMcpServerCredentials.ts +65 -32
- package/src/mcp-server/useMcpServerSetup.ts +38 -15
- package/src/mcp-server/useOAuthGrantStatus.ts +125 -0
- package/environment/diffEnvSpec.d.ts.map +0 -1
- package/environment/diffEnvSpec.js.map +0 -1
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
import { useCallback, useEffect, useMemo, useReducer, useRef } from "react";
|
|
4
4
|
import type { EnvVarInput, McpServerUsageInput, ResourceRef } from "@stigmer/sdk";
|
|
5
|
+
import { create } from "@bufbuild/protobuf";
|
|
5
6
|
import type { McpServer } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
|
|
7
|
+
import { GetOAuthGrantStatusInputSchema } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/io_pb";
|
|
6
8
|
import type { DiscoveredTool } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/status_pb";
|
|
7
9
|
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
8
10
|
import { useStigmer } from "../hooks";
|
|
9
11
|
import { usePersonalEnvironment } from "../environment/usePersonalEnvironment";
|
|
10
|
-
import {
|
|
12
|
+
import { diffEnv } from "../environment/diffEnv";
|
|
11
13
|
import { toError } from "../internal/toError";
|
|
12
14
|
import {
|
|
13
15
|
mcpServerSetupReducer,
|
|
@@ -57,8 +59,8 @@ export interface UseMcpServerSetupReturn {
|
|
|
57
59
|
/**
|
|
58
60
|
* Add an MCP server to the setup flow.
|
|
59
61
|
*
|
|
60
|
-
* Fetches the full server resource, checks `
|
|
61
|
-
* personal environment, and resolves the entry to either `ready`
|
|
62
|
+
* Fetches the full server resource, checks `env` declarations against
|
|
63
|
+
* the personal environment, and resolves the entry to either `ready`
|
|
62
64
|
* (no credentials needed or all present) or `needsSetup` (missing
|
|
63
65
|
* variables). Also extracts discovered tools and approval policies
|
|
64
66
|
* for the tool selector.
|
|
@@ -171,8 +173,8 @@ function computeDefaultEnabledTools(
|
|
|
171
173
|
* MCP servers selected in the {@link McpServerPicker}.
|
|
172
174
|
*
|
|
173
175
|
* When a user toggles an MCP server ON, this hook fetches the server's
|
|
174
|
-
* full resource, checks its `
|
|
175
|
-
* (via {@link
|
|
176
|
+
* full resource, checks its `env` declarations against the personal
|
|
177
|
+
* environment (via {@link diffEnv}), and determines whether credentials are
|
|
176
178
|
* needed. It also extracts discovered tools and approval policies for
|
|
177
179
|
* the tool selector UI.
|
|
178
180
|
*
|
|
@@ -198,7 +200,7 @@ function computeDefaultEnabledTools(
|
|
|
198
200
|
* @param org - Organization slug. Pass `null` to disable.
|
|
199
201
|
* @param poolKeys - Optional set of env-var keys already available
|
|
200
202
|
* from the session env pool (manual secrets, one-time env vars from
|
|
201
|
-
* other components). When provided, servers whose `
|
|
203
|
+
* other components). When provided, servers whose `env` keys
|
|
202
204
|
* are fully covered by `poolKeys` + personal env auto-resolve to
|
|
203
205
|
* `ready` without prompting. Reactive — when `poolKeys` changes,
|
|
204
206
|
* `needsSetup` entries are re-evaluated.
|
|
@@ -264,9 +266,9 @@ export function useMcpServerSetup(
|
|
|
264
266
|
const discoveredTools =
|
|
265
267
|
mcpServer.status?.discoveredCapabilities?.tools ?? [];
|
|
266
268
|
const toolApprovals = mcpServer.spec?.pinnedToolApprovals ?? [];
|
|
267
|
-
const
|
|
269
|
+
const envDeclarations = mcpServer.spec?.env;
|
|
268
270
|
|
|
269
|
-
if (!
|
|
271
|
+
if (!envDeclarations || Object.keys(envDeclarations).length === 0) {
|
|
270
272
|
dispatch({
|
|
271
273
|
type: "RESOLVE_READY",
|
|
272
274
|
key,
|
|
@@ -284,9 +286,29 @@ export function useMcpServerSetup(
|
|
|
284
286
|
const existingKeys = new Set(
|
|
285
287
|
Object.keys(personalEnv.environment?.spec?.data ?? {}),
|
|
286
288
|
);
|
|
287
|
-
const missingVariables = diffEnvSpec(envSpecData, existingKeys, poolKeys);
|
|
288
289
|
|
|
289
|
-
|
|
290
|
+
const auth = mcpServer.spec?.auth;
|
|
291
|
+
if (auth?.targetEnvVar && mcpServer.metadata?.id) {
|
|
292
|
+
try {
|
|
293
|
+
const grantStatus = await stigmer.mcpServer.getOAuthGrantStatus(
|
|
294
|
+
create(GetOAuthGrantStatusInputSchema, {
|
|
295
|
+
resourceId: mcpServer.metadata.id,
|
|
296
|
+
org,
|
|
297
|
+
}),
|
|
298
|
+
);
|
|
299
|
+
if (grantStatus.connected) {
|
|
300
|
+
existingKeys.add(auth.targetEnvVar);
|
|
301
|
+
}
|
|
302
|
+
} catch {
|
|
303
|
+
// Non-fatal: if grant status lookup fails, the OAuth var stays
|
|
304
|
+
// in missingVariables and the UI shows the sign-in button.
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const allMissing = diffEnv(envDeclarations, existingKeys, poolKeys);
|
|
309
|
+
const requiredMissing = allMissing.filter((v) => !v.optional);
|
|
310
|
+
|
|
311
|
+
if (requiredMissing.length === 0) {
|
|
290
312
|
dispatch({
|
|
291
313
|
type: "RESOLVE_READY",
|
|
292
314
|
key,
|
|
@@ -305,7 +327,7 @@ export function useMcpServerSetup(
|
|
|
305
327
|
type: "RESOLVE_NEEDS_SETUP",
|
|
306
328
|
key,
|
|
307
329
|
mcpServer,
|
|
308
|
-
missingVariables,
|
|
330
|
+
missingVariables: requiredMissing,
|
|
309
331
|
discoveredTools,
|
|
310
332
|
toolApprovals,
|
|
311
333
|
});
|
|
@@ -420,15 +442,16 @@ export function useMcpServerSetup(
|
|
|
420
442
|
for (const [key, entry] of Object.entries(entriesRef.current)) {
|
|
421
443
|
if (entry.status !== "needsSetup") continue;
|
|
422
444
|
|
|
423
|
-
const
|
|
424
|
-
if (!
|
|
445
|
+
const envDeclarations = entry.mcpServer.spec?.env;
|
|
446
|
+
if (!envDeclarations) continue;
|
|
425
447
|
|
|
426
|
-
const
|
|
448
|
+
const allMissing = diffEnv(envDeclarations, personalKeys, poolKeys);
|
|
449
|
+
const requiredMissing = allMissing.filter((v) => !v.optional);
|
|
427
450
|
const enabledTools = computeDefaultEnabledTools(
|
|
428
451
|
entry.mcpServer,
|
|
429
452
|
entry.discoveredTools,
|
|
430
453
|
);
|
|
431
|
-
dispatch({ type: "POOL_RESOLVE", key, missingVariables, enabledTools });
|
|
454
|
+
dispatch({ type: "POOL_RESOLVE", key, missingVariables: requiredMissing, enabledTools });
|
|
432
455
|
}
|
|
433
456
|
}, [poolKeys, personalEnv.environment]);
|
|
434
457
|
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useState } from "react";
|
|
4
|
+
import { create } from "@bufbuild/protobuf";
|
|
5
|
+
import { GetOAuthGrantStatusInputSchema } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/io_pb";
|
|
6
|
+
import { useStigmer } from "../hooks";
|
|
7
|
+
import { toError } from "../internal/toError";
|
|
8
|
+
|
|
9
|
+
/** Return value of {@link useOAuthGrantStatus}. */
|
|
10
|
+
export interface UseOAuthGrantStatusReturn {
|
|
11
|
+
/** Whether the user has an active OAuth grant for this resource + org. */
|
|
12
|
+
readonly connected: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* When the access token expires (Unix timestamp seconds).
|
|
15
|
+
* `BigInt(0)` when no grant exists or the token does not expire.
|
|
16
|
+
*/
|
|
17
|
+
readonly accessTokenExpiresAt: bigint;
|
|
18
|
+
/** The env var name managed by OAuth, or empty string when no grant exists. */
|
|
19
|
+
readonly targetEnvVar: string;
|
|
20
|
+
/** Auth method used (`"mcp_oauth"` or `"vendor_oauth"`), or empty string. */
|
|
21
|
+
readonly authMethod: string;
|
|
22
|
+
/** `true` while the grant status is being fetched. */
|
|
23
|
+
readonly isLoading: boolean;
|
|
24
|
+
/** Error from the last failed request, or `null` when healthy. */
|
|
25
|
+
readonly error: Error | null;
|
|
26
|
+
/** Discard cached data and re-fetch the grant status. */
|
|
27
|
+
readonly refetch: () => void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const BIGINT_ZERO = BigInt(0);
|
|
31
|
+
|
|
32
|
+
const IDLE: UseOAuthGrantStatusReturn = {
|
|
33
|
+
connected: false,
|
|
34
|
+
accessTokenExpiresAt: BIGINT_ZERO,
|
|
35
|
+
targetEnvVar: "",
|
|
36
|
+
authMethod: "",
|
|
37
|
+
isLoading: false,
|
|
38
|
+
error: null,
|
|
39
|
+
refetch: () => {},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Data hook that fetches the OAuth grant status for a single MCP server.
|
|
44
|
+
*
|
|
45
|
+
* Wraps `stigmer.mcpServer.getOAuthGrantStatus()` with loading, error,
|
|
46
|
+
* and idle state management. When `resourceId` or `org` changes, the
|
|
47
|
+
* previous in-flight request is discarded and a fresh fetch begins.
|
|
48
|
+
*
|
|
49
|
+
* Pass `null` for either parameter to skip fetching (stable no-op).
|
|
50
|
+
* This is useful when the MCP server resource has not loaded yet.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```tsx
|
|
54
|
+
* const grantStatus = useOAuthGrantStatus(mcpServer?.metadata?.id ?? null, org);
|
|
55
|
+
*
|
|
56
|
+
* if (grantStatus.isLoading) return <Spinner />;
|
|
57
|
+
* if (grantStatus.connected) return <span>Connected via OAuth</span>;
|
|
58
|
+
* return <button onClick={startOAuth}>Sign in</button>;
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export function useOAuthGrantStatus(
|
|
62
|
+
resourceId: string | null,
|
|
63
|
+
org: string | null,
|
|
64
|
+
): UseOAuthGrantStatusReturn {
|
|
65
|
+
const stigmer = useStigmer();
|
|
66
|
+
const [connected, setConnected] = useState(false);
|
|
67
|
+
const [accessTokenExpiresAt, setAccessTokenExpiresAt] = useState(BIGINT_ZERO);
|
|
68
|
+
const [targetEnvVar, setTargetEnvVar] = useState("");
|
|
69
|
+
const [authMethod, setAuthMethod] = useState("");
|
|
70
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
71
|
+
const [error, setError] = useState<Error | null>(null);
|
|
72
|
+
const [fetchKey, setFetchKey] = useState(0);
|
|
73
|
+
|
|
74
|
+
const refetch = useCallback(() => setFetchKey((k) => k + 1), []);
|
|
75
|
+
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (!resourceId || !org) {
|
|
78
|
+
setConnected(false);
|
|
79
|
+
setAccessTokenExpiresAt(BIGINT_ZERO);
|
|
80
|
+
setTargetEnvVar("");
|
|
81
|
+
setAuthMethod("");
|
|
82
|
+
setIsLoading(false);
|
|
83
|
+
setError(null);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const cancelled = { current: false };
|
|
88
|
+
setIsLoading(true);
|
|
89
|
+
setError(null);
|
|
90
|
+
|
|
91
|
+
stigmer.mcpServer
|
|
92
|
+
.getOAuthGrantStatus(create(GetOAuthGrantStatusInputSchema, { resourceId, org }))
|
|
93
|
+
.then(
|
|
94
|
+
(result) => {
|
|
95
|
+
if (cancelled.current) return;
|
|
96
|
+
setConnected(result.connected);
|
|
97
|
+
setAccessTokenExpiresAt(result.accessTokenExpiresAt);
|
|
98
|
+
setTargetEnvVar(result.targetEnvVar);
|
|
99
|
+
setAuthMethod(result.authMethod);
|
|
100
|
+
setIsLoading(false);
|
|
101
|
+
},
|
|
102
|
+
(err) => {
|
|
103
|
+
if (cancelled.current) return;
|
|
104
|
+
setError(toError(err));
|
|
105
|
+
setIsLoading(false);
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
return () => {
|
|
110
|
+
cancelled.current = true;
|
|
111
|
+
};
|
|
112
|
+
}, [resourceId, org, stigmer, fetchKey]);
|
|
113
|
+
|
|
114
|
+
if (!resourceId || !org) return { ...IDLE, refetch };
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
connected,
|
|
118
|
+
accessTokenExpiresAt,
|
|
119
|
+
targetEnvVar,
|
|
120
|
+
authMethod,
|
|
121
|
+
isLoading,
|
|
122
|
+
error,
|
|
123
|
+
refetch,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"diffEnvSpec.d.ts","sourceRoot":"","sources":["../../src/environment/diffEnvSpec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAEvD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,WAAW,CACzB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EACxE,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,EACzB,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACrB,kBAAkB,EAAE,CAetB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"diffEnvSpec.js","sourceRoot":"","sources":["../../src/environment/diffEnvSpec.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,WAAW,CACzB,WAAwE,EACxE,YAAyB,EACzB,QAAsB;IAEtB,MAAM,OAAO,GAAyB,EAAE,CAAC;IAEzC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;QACvD,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QACpC,IAAI,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAEjC,OAAO,CAAC,IAAI,CAAC;YACX,GAAG;YACH,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC;SAC7D,CAAC,CAAC;IACL,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|