@robosystems/core 0.5.8 → 0.6.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.
@@ -406,51 +406,51 @@ export function ConsoleContent({ config }) {
406
406
  }
407
407
  };
408
408
  const showMcpSetup = async () => {
409
- addSystemMessage('Creating MCP API key...', true);
409
+ addSystemMessage('Creating graph-scoped connector key...', true);
410
+ const apiUrl = process.env.NEXT_PUBLIC_ROBOSYSTEMS_API_URL ||
411
+ 'https://api.robosystems.ai';
412
+ const { mcp } = config;
413
+ const contextId = graphId || mcp.contextIdFallback;
410
414
  try {
411
- const { createUserApiKey } = await import('@robosystems/client/sdk');
412
- const response = await createUserApiKey({
413
- body: {
414
- name: `MCP - Console Generated - ${new Date().toLocaleDateString()}`,
415
- },
416
- });
417
- if (!response.data) {
418
- throw new Error('Failed to create API key');
419
- }
420
- const apiKey = response.data.key;
421
- const apiUrl = process.env.NEXT_PUBLIC_ROBOSYSTEMS_API_URL ||
422
- 'https://api.robosystems.ai';
423
- const { mcp } = config;
415
+ const { createMcpConnectorUrl } = await import('../../lib/mcp-connector');
416
+ // The graph id lives in the URL path and never becomes a tool argument,
417
+ // so one connector is anchored to exactly one graph. Multi-graph users
418
+ // add one connector per graph, which is why the name carries the id.
419
+ // The key is graph-scoped: valid only for this graph, revocable in
420
+ // Settings → API Keys, and rejected on every account-level surface.
421
+ const connector = await createMcpConnectorUrl(contextId, { apiUrl });
422
+ const connectorName = `${mcp.serverName}-${contextId}`;
424
423
  const exampleLines = mcp.exampleQuestions
425
424
  .map((q) => ` • "${q}"`)
426
425
  .join('\n');
427
426
  addSystemMessage(`MCP Setup Instructions:\n` +
428
427
  `═══════════════════════════════════════════════════════════════\n\n` +
429
- `API Key Created Successfully!\n\n` +
430
- `Add this configuration to claude_desktop_config.json:\n\n` +
431
- ` {\n` +
432
- ` "mcpServers": {\n` +
433
- ` "${mcp.serverName}": {\n` +
434
- ` "command": "npx",\n` +
435
- ` "args": ["-y", "${mcp.packageName}@latest"],\n` +
436
- ` "env": {\n` +
437
- ` "ROBOSYSTEMS_API_URL": "${apiUrl}",\n` +
438
- ` "ROBOSYSTEMS_API_KEY": "${apiKey}",\n` +
439
- ` "ROBOSYSTEMS_GRAPH_ID": "${graphId || mcp.contextIdFallback}"\n` +
440
- ` }\n` +
441
- ` }\n` +
442
- ` }\n` +
443
- ` }\n\n` +
444
- `Restart Claude Desktop or Claude Code to apply.\n\n` +
428
+ `Graph-scoped API key created — it works only for ${contextId}\n` +
429
+ `and can be revoked anytime in Settings → API Keys.\n\n` +
430
+ `Claude (claude.ai / Desktop)\n` +
431
+ ` Settings → Connectors → Add custom connector, then paste this\n` +
432
+ ` URL (the key rides inside it — no header field needed):\n` +
433
+ ` ${connector.url}\n\n` +
434
+ `Claude Code\n` +
435
+ ` claude mcp add --transport http ${connectorName} \\\n` +
436
+ ` ${connector.endpoint} \\\n` +
437
+ ` --header "X-API-Key: ${connector.apiKey}"\n\n` +
438
+ `Cursor / VS Code (mcp.json)\n` +
439
+ ` "${connectorName}": {\n` +
440
+ ` "url": "${connector.endpoint}",\n` +
441
+ ` "headers": { "X-API-Key": "${connector.apiKey}" }\n` +
442
+ ` }\n\n` +
445
443
  `Once connected, ask Claude questions like:\n` +
446
444
  `${exampleLines}\n\n` +
447
- `Keep this API key secure! It has full access to your account.`, true);
445
+ `Clients without HTTP transport support can use the stdio bridge\n` +
446
+ `in proxy mode: https://github.com/RoboFinSystems/robosystems-mcp-client\n\n` +
447
+ `The connector URL contains the key — treat it like a password.`, true);
448
448
  }
449
449
  catch (error) {
450
- addErrorMessage(`Failed to create API key: ${error.message || 'Unknown error'}\n\n` +
451
- `You can manually create an API key in Settings and use it with:\n` +
452
- ` ROBOSYSTEMS_API_URL: https://api.robosystems.ai\n` +
453
- ` ROBOSYSTEMS_GRAPH_ID: ${graphId || config.mcp.contextIdFallback}`);
450
+ addErrorMessage(`Failed to create connector key: ${error.message || 'Unknown error'}\n\n` +
451
+ `You can create an API key in Settings and connect with:\n` +
452
+ ` URL: ${apiUrl}/v1/graphs/${contextId}/mcp\n` +
453
+ ` Header: X-API-Key: <your key>`);
454
454
  }
455
455
  };
456
456
  const handleCommand = async (command) => {
@@ -35,7 +35,9 @@ export declare const EXAMPLE_SETS: Record<GraphExampleKind, GraphExampleSet>;
35
35
  * @param preferredKind Tiebreak used only when a graph carries more than one
36
36
  * entity extension (e.g. both roboledger and roboinvestor). Pass the app's
37
37
  * own lens (a RoboLedger app passes 'roboledger') so a dual-extension graph
38
- * shows the examples that fit the app the user is in.
38
+ * shows the examples that fit the app the user is in. With no lens — the
39
+ * brand-neutral RoboSystems console — a graph carrying the roboledger schema
40
+ * gets ledger examples, never portfolio ones.
39
41
  */
40
42
  export declare function getGraphExampleKind(graph: GraphInfo | undefined, preferredKind?: GraphExampleKind): GraphExampleKind;
41
43
  /** App-specific branding merged with the graph-derived example set. */
@@ -50,7 +52,8 @@ export interface ConsoleBranding {
50
52
  closingMessage: string;
51
53
  mcp: {
52
54
  serverName: string;
53
- packageName: string;
55
+ /** @deprecated Unused since the remote MCP transport landed. */
56
+ packageName?: string;
54
57
  contextIdFallback: string;
55
58
  };
56
59
  /** Defaults to "Example Cypher Queries:". */
@@ -333,7 +333,9 @@ export const EXAMPLE_SETS = {
333
333
  * @param preferredKind Tiebreak used only when a graph carries more than one
334
334
  * entity extension (e.g. both roboledger and roboinvestor). Pass the app's
335
335
  * own lens (a RoboLedger app passes 'roboledger') so a dual-extension graph
336
- * shows the examples that fit the app the user is in.
336
+ * shows the examples that fit the app the user is in. With no lens — the
337
+ * brand-neutral RoboSystems console — a graph carrying the roboledger schema
338
+ * gets ledger examples, never portfolio ones.
337
339
  */
338
340
  export function getGraphExampleKind(graph, preferredKind) {
339
341
  var _a;
@@ -347,7 +349,7 @@ export function getGraphExampleKind(graph, preferredKind) {
347
349
  if (hasInvestor && hasLedger) {
348
350
  return preferredKind === 'roboledger' || preferredKind === 'roboinvestor'
349
351
  ? preferredKind
350
- : 'roboinvestor';
352
+ : 'roboledger';
351
353
  }
352
354
  if (hasInvestor)
353
355
  return 'roboinvestor';
@@ -27,10 +27,15 @@ export interface ConsoleHeaderConfig {
27
27
  gradientTo: string;
28
28
  }
29
29
  export interface ConsoleMcpConfig {
30
- /** MCP server name in the JSON config, e.g. "robosystems" */
30
+ /** Connector name prefix, e.g. "robosystems". The graph id is appended, so
31
+ * each of a user's graphs gets a distinctly named connector. */
31
32
  serverName: string;
32
- /** npm package name, e.g. "@robosystems/mcp" */
33
- packageName: string;
33
+ /**
34
+ * @deprecated Unused since the remote MCP transport landed — `/mcp` now emits
35
+ * a URL + `X-API-Key` header instead of an npx stdio config. Kept optional so
36
+ * consuming apps can drop it on their own schedule.
37
+ */
38
+ packageName?: string;
34
39
  /** Example questions shown after MCP setup */
35
40
  exampleQuestions: string[];
36
41
  /** Fallback text for graph ID placeholder, e.g. "your_graph_id" */
package/index.d.ts CHANGED
@@ -4,7 +4,7 @@ export { clearUserCookies, clearUserLocalStorage, clearUserSessionStorage, listU
4
4
  export { AppSwitcher, AuthGuard, AuthProvider, SignInForm, SignUpForm, useAuth, } from './auth-components';
5
5
  export { useApiError, useMediaQuery, useToast, useUser, useUserLimits, type ToastMessage, } from './hooks';
6
6
  export { createGraphContext, createGraphProvider, createUseGraphContext, EntityProvider, GraphContext, GraphProvider, OrgProvider, ServiceOfferingsProvider, SidebarProvider, useEntity, useGraphContext, useOrg, useServiceOfferings, useSidebarContext, type EntityContextValue, type EntityProviderProps, type GraphContextValue, type GraphProviderProps, type GraphState, type OrgContextState, type OrgContextValue, type OrgProviderProps, type ServiceOfferings, } from './contexts';
7
- export { clientGraphCookie, clientSidebarCookie, entityCookie, graphCookie, sidebarCookie, type EntityCookie, type GraphCookie, type SidebarCookie, } from './lib';
7
+ export { clientGraphCookie, clientSidebarCookie, createMcpConnectorUrl, entityCookie, graphCookie, sidebarCookie, type EntityCookie, type GraphCookie, type McpConnectorUrl, type SidebarCookie, } from './lib';
8
8
  export { generateEntityUri, isUUID, UUID_REGEX } from './utils';
9
9
  export { clearGraphSelection, getGraphSelection, persistGraphSelection, } from './actions/graph-actions';
10
10
  export { clearEntitySelection, getEntitySelection, persistEntitySelection, } from './actions/entity-actions';
package/index.js CHANGED
@@ -20,7 +20,7 @@ OrgProvider,
20
20
  // Service offerings context
21
21
  ServiceOfferingsProvider, SidebarProvider, useEntity, useGraphContext, useOrg, useServiceOfferings, useSidebarContext, } from './contexts';
22
22
  // Export lib utilities
23
- export { clientGraphCookie, clientSidebarCookie, entityCookie, graphCookie, sidebarCookie, } from './lib';
23
+ export { clientGraphCookie, clientSidebarCookie, createMcpConnectorUrl, entityCookie, graphCookie, sidebarCookie, } from './lib';
24
24
  // Export utils
25
25
  export { generateEntityUri, isUUID, UUID_REGEX } from './utils';
26
26
  // Export server actions
package/lib/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { clientSidebarCookie, sidebarCookie, type SidebarCookie, } from './sidebar-cookie';
2
2
  export { clientGraphCookie, graphCookie, type GraphCookie, } from './graph-cookie';
3
3
  export { entityCookie, type EntityCookie } from './entity-cookie';
4
+ export { createMcpConnectorUrl, type McpConnectorUrl } from './mcp-connector';
package/lib/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export { clientSidebarCookie, sidebarCookie, } from './sidebar-cookie';
2
2
  export { clientGraphCookie, graphCookie, } from './graph-cookie';
3
3
  export { entityCookie } from './entity-cookie';
4
+ export { createMcpConnectorUrl } from './mcp-connector';
@@ -0,0 +1,29 @@
1
+ export interface McpConnectorUrl {
2
+ /** Pasteable connector URL with the graph-scoped key embedded as `?token=` */
3
+ url: string;
4
+ /** Bare MCP endpoint URL (no credential) — for header-capable clients */
5
+ endpoint: string;
6
+ /** The plaintext graph-scoped API key (returned once at mint) */
7
+ apiKey: string;
8
+ /** Name the key was created under (visible in Settings → API Keys) */
9
+ keyName: string;
10
+ graphId: string;
11
+ }
12
+ /**
13
+ * Mint a graph-scoped API key and assemble the MCP connector URL for it.
14
+ *
15
+ * The URL is for clients that cannot send custom headers (claude.ai /
16
+ * Claude Desktop custom connectors): the scoped key travels as a `token`
17
+ * query parameter, which the server honors only on the MCP endpoint and
18
+ * only for keys scoped to that URL's graph — account-wide keys are
19
+ * rejected there. The key works for exactly this graph (and its
20
+ * subgraphs), is rejected on every account-level surface, and can be
21
+ * revoked from Settings → API Keys like any other key.
22
+ *
23
+ * Header-capable clients (Claude Code, Cursor, VS Code) should use the
24
+ * bare `endpoint` with the key in an `X-API-Key` header instead.
25
+ */
26
+ export declare function createMcpConnectorUrl(graphId: string, options?: {
27
+ apiUrl?: string;
28
+ name?: string;
29
+ }): Promise<McpConnectorUrl>;
@@ -0,0 +1,35 @@
1
+ const DEFAULT_API_URL = 'https://api.robosystems.ai';
2
+ /**
3
+ * Mint a graph-scoped API key and assemble the MCP connector URL for it.
4
+ *
5
+ * The URL is for clients that cannot send custom headers (claude.ai /
6
+ * Claude Desktop custom connectors): the scoped key travels as a `token`
7
+ * query parameter, which the server honors only on the MCP endpoint and
8
+ * only for keys scoped to that URL's graph — account-wide keys are
9
+ * rejected there. The key works for exactly this graph (and its
10
+ * subgraphs), is rejected on every account-level surface, and can be
11
+ * revoked from Settings → API Keys like any other key.
12
+ *
13
+ * Header-capable clients (Claude Code, Cursor, VS Code) should use the
14
+ * bare `endpoint` with the key in an `X-API-Key` header instead.
15
+ */
16
+ export async function createMcpConnectorUrl(graphId, options = {}) {
17
+ var _a, _b;
18
+ const { createUserApiKey } = await import('@robosystems/client/sdk');
19
+ const apiUrl = ((_a = options.apiUrl) !== null && _a !== void 0 ? _a : DEFAULT_API_URL).replace(/\/$/, '');
20
+ const keyName = (_b = options.name) !== null && _b !== void 0 ? _b : `MCP Connector - ${graphId} - ${new Date().toLocaleDateString()}`;
21
+ const response = await createUserApiKey({
22
+ body: { name: keyName, graph_id: graphId },
23
+ });
24
+ if (!response.data) {
25
+ throw new Error('Failed to create connector API key');
26
+ }
27
+ const endpoint = `${apiUrl}/v1/graphs/${graphId}/mcp`;
28
+ return {
29
+ url: `${endpoint}?token=${response.data.key}`,
30
+ endpoint,
31
+ apiKey: response.data.key,
32
+ keyName,
33
+ graphId,
34
+ };
35
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robosystems/core",
3
- "version": "0.5.8",
3
+ "version": "0.6.0",
4
4
  "description": "Shared RoboSystems frontend core library (auth, contexts, task monitoring, UI components) for the RoboSystems Next.js apps",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -27,7 +27,7 @@
27
27
  "tailwind-merge": "^3"
28
28
  },
29
29
  "peerDependencies": {
30
- "@robosystems/client": ">=0.6.2 <2",
30
+ "@robosystems/client": ">=1.2 <2",
31
31
  "flowbite-react": "^0.12.5",
32
32
  "next": ">=15 <17",
33
33
  "react": ">=18 <20",