@corva/ui 3.54.0-20 → 3.54.0-22
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/mcp-server/server.mjs +170 -69
- package/package.json +1 -1
package/mcp-server/server.mjs
CHANGED
|
@@ -11,9 +11,10 @@ import { randomUUID } from 'crypto';
|
|
|
11
11
|
import { Resource } from '@opentelemetry/resources';
|
|
12
12
|
import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
|
|
13
13
|
import { readFile } from 'fs/promises';
|
|
14
|
-
import { join as join$1, dirname } from 'path';
|
|
14
|
+
import { join as join$1, dirname, resolve } from 'path';
|
|
15
15
|
import { fileURLToPath } from 'url';
|
|
16
16
|
import { z } from 'zod';
|
|
17
|
+
import { readFileSync } from 'fs';
|
|
17
18
|
|
|
18
19
|
const LOG_SYMBOLS = {
|
|
19
20
|
success: '✓',
|
|
@@ -227,7 +228,7 @@ const validateDsn = (dsn) => {
|
|
|
227
228
|
|
|
228
229
|
const MCP_SERVER_VERSION = '1.1.0';
|
|
229
230
|
|
|
230
|
-
var version = "3.54.0-
|
|
231
|
+
var version = "3.54.0-22";
|
|
231
232
|
|
|
232
233
|
const CORVA_UI_VERSION = version;
|
|
233
234
|
|
|
@@ -268,16 +269,24 @@ const createMetricsClient = (meter) => {
|
|
|
268
269
|
recordToolEmptyResult: toolName => {
|
|
269
270
|
emptyResultCounter.add(1, { 'gen_ai.tool.name': toolName });
|
|
270
271
|
},
|
|
271
|
-
recordSession: (clientName, clientVersion) => {
|
|
272
|
+
recordSession: (clientName, clientVersion, projectIdentity) => {
|
|
272
273
|
sessionCounter.add(1, {
|
|
273
274
|
'mcp.client.name': clientName || UNKNOWN_CLIENT_ATTR,
|
|
274
275
|
'mcp.client.version': clientVersion || UNKNOWN_CLIENT_ATTR,
|
|
276
|
+
...(projectIdentity?.appKey ? { 'corva.app.key': projectIdentity.appKey } : {}),
|
|
277
|
+
...(projectIdentity?.packageName
|
|
278
|
+
? { 'corva.package.name': projectIdentity.packageName }
|
|
279
|
+
: {}),
|
|
275
280
|
});
|
|
276
281
|
},
|
|
277
|
-
recordSessionEnd: (durationMs, toolCount, clientName, clientVersion) => {
|
|
282
|
+
recordSessionEnd: (durationMs, toolCount, clientName, clientVersion, projectIdentity) => {
|
|
278
283
|
const attrs = {
|
|
279
284
|
'mcp.client.name': clientName || UNKNOWN_CLIENT_ATTR,
|
|
280
285
|
'mcp.client.version': clientVersion || UNKNOWN_CLIENT_ATTR,
|
|
286
|
+
...(projectIdentity?.appKey ? { 'corva.app.key': projectIdentity.appKey } : {}),
|
|
287
|
+
...(projectIdentity?.packageName
|
|
288
|
+
? { 'corva.package.name': projectIdentity.packageName }
|
|
289
|
+
: {}),
|
|
281
290
|
};
|
|
282
291
|
sessionDuration.record(durationMs, attrs);
|
|
283
292
|
sessionToolCount.record(toolCount, attrs);
|
|
@@ -375,6 +384,12 @@ const recordInitSpan = (tracer, attrs) => {
|
|
|
375
384
|
if (attrs.networkTransport) {
|
|
376
385
|
span.setAttribute('network.transport', attrs.networkTransport);
|
|
377
386
|
}
|
|
387
|
+
if (attrs.appKey) {
|
|
388
|
+
span.setAttribute('corva.app.key', attrs.appKey);
|
|
389
|
+
}
|
|
390
|
+
if (attrs.packageName) {
|
|
391
|
+
span.setAttribute('corva.package.name', attrs.packageName);
|
|
392
|
+
}
|
|
378
393
|
}
|
|
379
394
|
finally {
|
|
380
395
|
span.end();
|
|
@@ -94326,7 +94341,9 @@ const findSimilarComponents = (name, allComponents) => {
|
|
|
94326
94341
|
const componentDocsToolName = 'get_component_docs';
|
|
94327
94342
|
const componentDocsToolTitle = 'Get Component Docs';
|
|
94328
94343
|
const componentDocsToolDescription = `Get detailed documentation for a specific @corva/ui component.
|
|
94329
|
-
Returns props, examples, description, and links
|
|
94344
|
+
Returns props, examples, description, and links.
|
|
94345
|
+
|
|
94346
|
+
Usage: get_component_docs({ name: "Button" })`;
|
|
94330
94347
|
const componentDocsToolSchema = {
|
|
94331
94348
|
name: z.string().describe("Component name (e.g., 'Button', 'Tooltip', 'DatePicker')"),
|
|
94332
94349
|
category: z
|
|
@@ -94384,7 +94401,9 @@ const handleGetComponentDocs = (args) => {
|
|
|
94384
94401
|
|
|
94385
94402
|
**Category:** ${component.category}
|
|
94386
94403
|
**Import:** \`import { ${component.name} } from '${component.importPath}';\`
|
|
94387
|
-
${component.isExperimental
|
|
94404
|
+
${component.isExperimental
|
|
94405
|
+
? '**Experimental** - Recently added component, fully functional and safe to use.\n'
|
|
94406
|
+
: ''}${component.isDeprecated ? '❌ **Deprecated**\n' : ''}
|
|
94388
94407
|
|
|
94389
94408
|
${component.description}
|
|
94390
94409
|
|
|
@@ -94404,7 +94423,9 @@ ${examplesSection}
|
|
|
94404
94423
|
const hookDocsToolName = 'get_hook_docs';
|
|
94405
94424
|
const hookDocsToolTitle = 'Get Hook Docs';
|
|
94406
94425
|
const hookDocsToolDescription = `Get documentation for a @corva/ui hook.
|
|
94407
|
-
Returns parameters, return type, and usage examples
|
|
94426
|
+
Returns parameters, return type, and usage examples.
|
|
94427
|
+
|
|
94428
|
+
Usage: get_hook_docs({ name: "useSubscriptions" })`;
|
|
94408
94429
|
const hookDocsToolSchema = {
|
|
94409
94430
|
name: z.string().describe("Hook name (e.g., 'useSubscriptions', 'useOutsideClick')"),
|
|
94410
94431
|
};
|
|
@@ -94440,7 +94461,9 @@ Returns color palette (dark/light), CSS variables, SCSS variables,
|
|
|
94440
94461
|
SCSS functions/mixins, spacing, typography, transitions, z-index tokens, and usage examples.
|
|
94441
94462
|
|
|
94442
94463
|
Available sections: palette, css-variables, scss-variables, scss-functions,
|
|
94443
|
-
scss-mixins, spacing, typography, transition, z-index, usage, all
|
|
94464
|
+
scss-mixins, spacing, typography, transition, z-index, usage, all.
|
|
94465
|
+
|
|
94466
|
+
Usage: get_theme_docs({ section: "palette" })`;
|
|
94444
94467
|
const SECTIONS = [
|
|
94445
94468
|
'palette',
|
|
94446
94469
|
'css-variables',
|
|
@@ -94479,54 +94502,41 @@ const buildPaletteSection = (includeLight = false) => {
|
|
|
94479
94502
|
}
|
|
94480
94503
|
return text;
|
|
94481
94504
|
};
|
|
94482
|
-
const buildCssVariablesSection = () => h2('CSS Variables') +
|
|
94483
|
-
|
|
94484
|
-
|
|
94485
|
-
|
|
94486
|
-
const
|
|
94487
|
-
|
|
94488
|
-
"Import via `@import '@corva/ui/styles/common'`.\n\n" +
|
|
94489
|
-
formatScssVariables(theme.scssVariables);
|
|
94490
|
-
const buildScssFunctionsSection = () => h2('SCSS Functions') +
|
|
94491
|
-
'Available after importing `@corva/ui/styles/common`.\n\n' +
|
|
94492
|
-
formatScssFunctions(theme.scssFunctions);
|
|
94493
|
-
const buildScssMixinsSection = () => h2('SCSS Mixins') +
|
|
94494
|
-
'Available after importing `@corva/ui/styles/common`.\n\n' +
|
|
94495
|
-
formatScssMixins(theme.scssMixins);
|
|
94505
|
+
const buildCssVariablesSection = () => `${h2('CSS Variables')}All CSS custom properties available via theme data attributes ` +
|
|
94506
|
+
`(\`[data-corva-theme-dark]\` / \`[data-corva-theme-light]\`).\n\n${formatCssVariables(theme.cssVariables)}`;
|
|
94507
|
+
const buildScssVariablesSection = () => `${h2('SCSS Variables')}SCSS variables that map to CSS custom properties. ` +
|
|
94508
|
+
`Import via \`@import '@corva/ui/styles/common'\`.\n\n${formatScssVariables(theme.scssVariables)}`;
|
|
94509
|
+
const buildScssFunctionsSection = () => `${h2('SCSS Functions')}Available after importing \`@corva/ui/styles/common\`.\n\n${formatScssFunctions(theme.scssFunctions)}`;
|
|
94510
|
+
const buildScssMixinsSection = () => `${h2('SCSS Mixins')}Available after importing \`@corva/ui/styles/common\`.\n\n${formatScssMixins(theme.scssMixins)}`;
|
|
94496
94511
|
const buildSpacingSection = () => h2('Spacing') + formatSpacing(theme.spacing);
|
|
94497
94512
|
const buildTypographySection = () => h2('Typography') + formatTypography(theme.typography);
|
|
94498
94513
|
const buildZIndexSection = () => h2('Z-Index') + formatZIndex(theme.zIndex);
|
|
94499
94514
|
const buildTransitionSection = () => h2('Transitions') + formatTransition(theme.transition);
|
|
94500
94515
|
const buildUsageSection = () => {
|
|
94501
94516
|
const sections = [
|
|
94502
|
-
h2('Usage Guide')
|
|
94503
|
-
|
|
94504
|
-
|
|
94505
|
-
|
|
94506
|
-
|
|
94507
|
-
|
|
94508
|
-
|
|
94509
|
-
|
|
94510
|
-
|
|
94511
|
-
|
|
94512
|
-
|
|
94513
|
-
|
|
94514
|
-
|
|
94515
|
-
|
|
94516
|
-
|
|
94517
|
-
|
|
94518
|
-
|
|
94519
|
-
|
|
94520
|
-
|
|
94521
|
-
|
|
94522
|
-
|
|
94523
|
-
|
|
94524
|
-
|
|
94525
|
-
'### 5. SCSS Mixins\n' +
|
|
94526
|
-
codeBlock('.scrollable-container {\n' +
|
|
94527
|
-
' --corvaui-background: var(--palette-background-b-4);\n' +
|
|
94528
|
-
' @include verticalFadePseudoElements(2);\n' +
|
|
94529
|
-
'}', 'scss'),
|
|
94517
|
+
`${h2('Usage Guide')}### 1. JSS (Material-UI makeStyles)\n${codeBlock("import { theme } from '@corva/ui/config';\n\n" +
|
|
94518
|
+
"const primaryColor = theme.palette.primary.main; // '#03BCD4'\n" +
|
|
94519
|
+
'const bgColor = theme.palette.background.b4;', 'tsx')}`,
|
|
94520
|
+
`### 2. CSS Variables\n${codeBlock('.my-element {\n' +
|
|
94521
|
+
' color: var(--palette-primary-main);\n' +
|
|
94522
|
+
' background: var(--palette-background-b-4);\n' +
|
|
94523
|
+
'}', 'css')}`,
|
|
94524
|
+
`### 3. SCSS Variables\n${codeBlock("@import '@corva/ui/styles/common';\n\n" +
|
|
94525
|
+
'.my-element {\n' +
|
|
94526
|
+
' color: $palette_primary_main;\n' +
|
|
94527
|
+
' background: $palette_b4;\n' +
|
|
94528
|
+
'}', 'scss')}`,
|
|
94529
|
+
`### 4. SCSS Functions\n${codeBlock('// Alpha transparency\n' +
|
|
94530
|
+
'background: colorAlpha($palette_primary_main, 0.5);\n\n' +
|
|
94531
|
+
'// Spacing (base unit: 8px)\n' +
|
|
94532
|
+
'padding: spacing(2); // 16px\n' +
|
|
94533
|
+
'margin: spacing(1, 2); // 8px 16px\n\n' +
|
|
94534
|
+
'// Transitions\n' +
|
|
94535
|
+
'transition: transition(opacity, transform);', 'scss')}`,
|
|
94536
|
+
`### 5. SCSS Mixins\n${codeBlock('.scrollable-container {\n' +
|
|
94537
|
+
' --corvaui-background: var(--palette-background-b-4);\n' +
|
|
94538
|
+
' @include verticalFadePseudoElements(2);\n' +
|
|
94539
|
+
'}', 'scss')}`,
|
|
94530
94540
|
];
|
|
94531
94541
|
return sections.join('\n\n');
|
|
94532
94542
|
};
|
|
@@ -94542,9 +94552,7 @@ const buildAllSection = () => {
|
|
|
94542
94552
|
const availableSections = SECTIONS.filter(s => s !== 'all' && s !== 'variables')
|
|
94543
94553
|
.map(s => `\`${s}\``)
|
|
94544
94554
|
.join(', ');
|
|
94545
|
-
const tokenSummary = h2('Token Summary') +
|
|
94546
|
-
counts.map(c => `- ${c}`).join('\n') +
|
|
94547
|
-
`\n\nUse \`get_theme_docs\` with a specific section for full details: ${availableSections}`;
|
|
94555
|
+
const tokenSummary = `${h2('Token Summary') + counts.map(c => `- ${c}`).join('\n')}\n\nUse \`get_theme_docs\` with a specific section for full details: ${availableSections}`;
|
|
94548
94556
|
return join(h1('@corva/ui Theme'), buildPaletteSection(false), tokenSummary, buildSpacingSection(), buildTypographySection(), buildTransitionSection(), buildZIndexSection(), buildUsageSection());
|
|
94549
94557
|
};
|
|
94550
94558
|
const handleGetThemeDocs = (args) => {
|
|
@@ -94594,7 +94602,9 @@ const handleGetThemeDocs = (args) => {
|
|
|
94594
94602
|
const listToolName = 'list_corva_ui';
|
|
94595
94603
|
const listToolTitle = 'List @corva/ui';
|
|
94596
94604
|
const listToolDescription = `List all available items in @corva/ui by category.
|
|
94597
|
-
Useful to see what's available before searching
|
|
94605
|
+
Useful to see what's available before searching.
|
|
94606
|
+
|
|
94607
|
+
Usage: list_corva_ui({ type: "components-v2" })`;
|
|
94598
94608
|
const listToolSchema = {
|
|
94599
94609
|
type: z
|
|
94600
94610
|
.enum([
|
|
@@ -94720,15 +94730,15 @@ const handleList = (args) => {
|
|
|
94720
94730
|
const constantsDocsToolName = 'get_constants_docs';
|
|
94721
94731
|
const constantsDocsToolTitle = 'Get Constants Docs';
|
|
94722
94732
|
const constantsDocsToolDescription = `Get documentation for @corva/ui constants.
|
|
94723
|
-
Returns constant values, namespaces, and usage info
|
|
94733
|
+
Returns constant values, namespaces, and usage info.
|
|
94734
|
+
|
|
94735
|
+
Usage: get_constants_docs({ name: "ASSET_TYPES" })`;
|
|
94724
94736
|
const constantsDocsToolSchema = {
|
|
94725
|
-
|
|
94726
|
-
.string()
|
|
94727
|
-
.describe("Namespace (e.g., 'drillstring', 'alerts') or constant name (e.g., 'ASSET_TYPES')"),
|
|
94737
|
+
name: z.string().describe("Namespace or constant name (e.g., 'drillstring', 'ASSET_TYPES')"),
|
|
94728
94738
|
};
|
|
94729
94739
|
const handleGetConstantsDocs = (args) => {
|
|
94730
|
-
const {
|
|
94731
|
-
const namespaceLower =
|
|
94740
|
+
const { name } = args;
|
|
94741
|
+
const namespaceLower = name.toLowerCase();
|
|
94732
94742
|
// Find matching constants by namespace or name
|
|
94733
94743
|
const matches = constants.filter(c => c.namespace?.toLowerCase() === namespaceLower ||
|
|
94734
94744
|
c.name.toLowerCase() === namespaceLower ||
|
|
@@ -94747,7 +94757,7 @@ const handleGetConstantsDocs = (args) => {
|
|
|
94747
94757
|
'Metrics config may live in utility modules. Try search_corva_ui with type "util" and query "metrics".';
|
|
94748
94758
|
}
|
|
94749
94759
|
return {
|
|
94750
|
-
response: createToolResponse(`No constants found for "${
|
|
94760
|
+
response: createToolResponse(`No constants found for "${name}". ${suggestion}`),
|
|
94751
94761
|
found: false,
|
|
94752
94762
|
matchCount: 0,
|
|
94753
94763
|
};
|
|
@@ -94780,8 +94790,8 @@ ${c.value !== '[namespace]' ? `**Value:** \`${JSON.stringify(c.value, null, 2)}\
|
|
|
94780
94790
|
.map(c => `- **${c.name}**: ${c.description}\n Import: \`${c.importPath}\``)
|
|
94781
94791
|
.join('\n\n');
|
|
94782
94792
|
const title = exactNamespaceMatches.length > 0
|
|
94783
|
-
? `Constants in "${
|
|
94784
|
-
: `Constants matching "${
|
|
94793
|
+
? `Constants in "${name}" namespace`
|
|
94794
|
+
: `Constants matching "${name}"`;
|
|
94785
94795
|
return {
|
|
94786
94796
|
response: createToolResponse(`# ${title}\n\n${displayMatches.length} constant(s) found:\n\n${formatted}`),
|
|
94787
94797
|
found: true,
|
|
@@ -94792,7 +94802,9 @@ ${c.value !== '[namespace]' ? `**Value:** \`${JSON.stringify(c.value, null, 2)}\
|
|
|
94792
94802
|
const clientDocsToolName = 'get_client_docs';
|
|
94793
94803
|
const clientDocsToolTitle = 'Get Client Docs';
|
|
94794
94804
|
const clientDocsToolDescription = `Get documentation for @corva/ui API clients.
|
|
94795
|
-
Returns methods, parameters, and API endpoints from Swagger documentation
|
|
94805
|
+
Returns methods, parameters, and API endpoints from Swagger documentation.
|
|
94806
|
+
|
|
94807
|
+
Usage: get_client_docs({ name: "corvaAPI" })`;
|
|
94796
94808
|
const clientDocsToolSchema = {
|
|
94797
94809
|
name: z.string().describe("Client name (e.g., 'corvaAPI', 'socketClient', 'corvaDataAPI')"),
|
|
94798
94810
|
tag: z
|
|
@@ -94847,7 +94859,7 @@ const formatBytes = (bytes) => {
|
|
|
94847
94859
|
return `${mb.toFixed(1)} MB`;
|
|
94848
94860
|
};
|
|
94849
94861
|
const formatConfigSource = (source) => source === 'local' ? 'Local file' : 'Remote endpoint';
|
|
94850
|
-
const handleGetDiagnostics = (stats, telemetry) => {
|
|
94862
|
+
const handleGetDiagnostics = (stats, telemetry, identity) => {
|
|
94851
94863
|
const { heapUsed, heapTotal, rss } = process.memoryUsage();
|
|
94852
94864
|
const uptimeMs = Date.now() - stats.startTime;
|
|
94853
94865
|
let text = h1('MCP Server Diagnostics');
|
|
@@ -94880,11 +94892,82 @@ const handleGetDiagnostics = (stats, telemetry) => {
|
|
|
94880
94892
|
else {
|
|
94881
94893
|
text += `${bold('Status')}: Disabled\n`;
|
|
94882
94894
|
}
|
|
94895
|
+
text += h2('Project Identity');
|
|
94896
|
+
text += `${bold('App key')}: ${identity?.appKey ?? 'N/A'}\n`;
|
|
94897
|
+
text += `${bold('Package name')}: ${identity?.packageName ?? 'N/A'}\n`;
|
|
94883
94898
|
return {
|
|
94884
94899
|
response: createToolResponse(text),
|
|
94885
94900
|
};
|
|
94886
94901
|
};
|
|
94887
94902
|
|
|
94903
|
+
const readJsonField = (filePath, ...keys) => {
|
|
94904
|
+
try {
|
|
94905
|
+
let value = JSON.parse(readFileSync(filePath, 'utf-8'));
|
|
94906
|
+
for (const key of keys) {
|
|
94907
|
+
if (value && typeof value === 'object') {
|
|
94908
|
+
value = value[key];
|
|
94909
|
+
}
|
|
94910
|
+
else {
|
|
94911
|
+
return null;
|
|
94912
|
+
}
|
|
94913
|
+
}
|
|
94914
|
+
return typeof value === 'string' && value ? value : null;
|
|
94915
|
+
}
|
|
94916
|
+
catch {
|
|
94917
|
+
return null;
|
|
94918
|
+
}
|
|
94919
|
+
};
|
|
94920
|
+
const findUpJsonField = (startDir, fileName, ...keys) => {
|
|
94921
|
+
let dir = resolve(startDir);
|
|
94922
|
+
for (;;) {
|
|
94923
|
+
const value = readJsonField(join$1(dir, fileName), ...keys);
|
|
94924
|
+
if (value) {
|
|
94925
|
+
return value;
|
|
94926
|
+
}
|
|
94927
|
+
const parent = dirname(dir);
|
|
94928
|
+
if (parent === dir) {
|
|
94929
|
+
return null;
|
|
94930
|
+
}
|
|
94931
|
+
dir = parent;
|
|
94932
|
+
}
|
|
94933
|
+
};
|
|
94934
|
+
const getProjectIdentityAttrs = (identity) => {
|
|
94935
|
+
const attrs = {};
|
|
94936
|
+
if (identity?.appKey) {
|
|
94937
|
+
attrs['corva.app.key'] = identity.appKey;
|
|
94938
|
+
}
|
|
94939
|
+
if (identity?.packageName) {
|
|
94940
|
+
attrs['corva.package.name'] = identity.packageName;
|
|
94941
|
+
}
|
|
94942
|
+
return attrs;
|
|
94943
|
+
};
|
|
94944
|
+
const resolveProjectIdentity = async (server, logger) => {
|
|
94945
|
+
const empty = { appKey: null, packageName: null };
|
|
94946
|
+
try {
|
|
94947
|
+
const capabilities = server.getClientCapabilities();
|
|
94948
|
+
if (!capabilities?.roots) {
|
|
94949
|
+
return empty;
|
|
94950
|
+
}
|
|
94951
|
+
const { roots } = await server.listRoots();
|
|
94952
|
+
if (!roots.length) {
|
|
94953
|
+
return empty;
|
|
94954
|
+
}
|
|
94955
|
+
const rootPath = fileURLToPath(roots[0].uri);
|
|
94956
|
+
const appKey = findUpJsonField(rootPath, 'manifest.json', 'application', 'key');
|
|
94957
|
+
const packageName = findUpJsonField(rootPath, 'package.json', 'name');
|
|
94958
|
+
if (appKey) {
|
|
94959
|
+
logger.info(`Consuming app: ${appKey}`);
|
|
94960
|
+
}
|
|
94961
|
+
if (packageName) {
|
|
94962
|
+
logger.info(`Consuming package: ${packageName}`);
|
|
94963
|
+
}
|
|
94964
|
+
return { appKey, packageName };
|
|
94965
|
+
}
|
|
94966
|
+
catch {
|
|
94967
|
+
return empty;
|
|
94968
|
+
}
|
|
94969
|
+
};
|
|
94970
|
+
|
|
94888
94971
|
class CorvaUiMcpServer {
|
|
94889
94972
|
server;
|
|
94890
94973
|
mcpLogger;
|
|
@@ -94897,6 +94980,8 @@ class CorvaUiMcpServer {
|
|
|
94897
94980
|
telemetryInitPromise = null;
|
|
94898
94981
|
shutdownRequested = false;
|
|
94899
94982
|
pendingInitData = null;
|
|
94983
|
+
projectIdentity = null;
|
|
94984
|
+
identityPromise = null;
|
|
94900
94985
|
constructor() {
|
|
94901
94986
|
const baseLogger = createLogger({ prefix: '[CorvaUI MCP]' });
|
|
94902
94987
|
this.mcpLogger = createMcpNotificationLogger(baseLogger, () => this.isConnected ? this.server : null);
|
|
@@ -94929,7 +95014,16 @@ class CorvaUiMcpServer {
|
|
|
94929
95014
|
if (clientInfo?.name) {
|
|
94930
95015
|
this.mcpLogger.info(`Client connected: ${clientInfo.name}${clientInfo.version ? ` v${clientInfo.version}` : ''}`);
|
|
94931
95016
|
}
|
|
94932
|
-
this.
|
|
95017
|
+
this.identityPromise = resolveProjectIdentity(this.server.server, this.mcpLogger)
|
|
95018
|
+
.then(identity => {
|
|
95019
|
+
this.projectIdentity = identity;
|
|
95020
|
+
})
|
|
95021
|
+
.catch(error => {
|
|
95022
|
+
this.mcpLogger.error('Failed to resolve project identity', error);
|
|
95023
|
+
})
|
|
95024
|
+
.finally(() => {
|
|
95025
|
+
this.flushPendingInitData();
|
|
95026
|
+
});
|
|
94933
95027
|
};
|
|
94934
95028
|
}
|
|
94935
95029
|
flushPendingInitData() {
|
|
@@ -94982,6 +95076,7 @@ class CorvaUiMcpServer {
|
|
|
94982
95076
|
extraAttrs: {
|
|
94983
95077
|
...serializedResult.extraAttrs,
|
|
94984
95078
|
...getSpanAttributes?.(result),
|
|
95079
|
+
...getProjectIdentityAttrs(this.projectIdentity),
|
|
94985
95080
|
},
|
|
94986
95081
|
});
|
|
94987
95082
|
this.telemetry.metrics.recordToolInvocation(toolName, ms);
|
|
@@ -95013,7 +95108,10 @@ class CorvaUiMcpServer {
|
|
|
95013
95108
|
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
95014
95109
|
networkTransport: MCP_NETWORK_TRANSPORT,
|
|
95015
95110
|
parentContext,
|
|
95016
|
-
extraAttrs:
|
|
95111
|
+
extraAttrs: {
|
|
95112
|
+
...serializedError.extraAttrs,
|
|
95113
|
+
...getProjectIdentityAttrs(this.projectIdentity),
|
|
95114
|
+
},
|
|
95017
95115
|
});
|
|
95018
95116
|
this.telemetry.metrics.recordToolInvocation(toolName, ms);
|
|
95019
95117
|
this.telemetry.metrics.recordToolError(toolName, serializedError.errorType);
|
|
@@ -95153,7 +95251,7 @@ class CorvaUiMcpServer {
|
|
|
95153
95251
|
}, (extra) => {
|
|
95154
95252
|
const parentContext = extractContextFromMeta(extra?._meta);
|
|
95155
95253
|
try {
|
|
95156
|
-
return this.executeToolWithObservability(diagnosticsToolName, {}, () => handleGetDiagnostics(this.getStats(), this.getTelemetryStatus()), () => 'ok', { parentContext });
|
|
95254
|
+
return this.executeToolWithObservability(diagnosticsToolName, {}, () => handleGetDiagnostics(this.getStats(), this.getTelemetryStatus(), this.projectIdentity), () => 'ok', { parentContext });
|
|
95157
95255
|
}
|
|
95158
95256
|
catch (error) {
|
|
95159
95257
|
return createErrorResponse(`Error: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -95188,10 +95286,13 @@ class CorvaUiMcpServer {
|
|
|
95188
95286
|
if (this.telemetryInitPromise) {
|
|
95189
95287
|
await withTimeout(this.telemetryInitPromise, TELEMETRY_INIT_TIMEOUT_MS);
|
|
95190
95288
|
}
|
|
95289
|
+
if (this.identityPromise) {
|
|
95290
|
+
await withTimeout(this.identityPromise, TELEMETRY_INIT_TIMEOUT_MS);
|
|
95291
|
+
}
|
|
95191
95292
|
if (this.telemetry.isEnabled()) {
|
|
95192
95293
|
const sessionDurationMs = Date.now() - this.startTime;
|
|
95193
95294
|
const clientInfo = this.server.server.getClientVersion();
|
|
95194
|
-
this.telemetry.metrics.recordSessionEnd(sessionDurationMs, this.requestCount, clientInfo?.name, clientInfo?.version);
|
|
95295
|
+
this.telemetry.metrics.recordSessionEnd(sessionDurationMs, this.requestCount, clientInfo?.name, clientInfo?.version, this.projectIdentity);
|
|
95195
95296
|
}
|
|
95196
95297
|
if (this.transport) {
|
|
95197
95298
|
await this.server.close();
|