@enfyra/mcp-server 0.1.64 → 0.1.66
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 +1 -0
- package/dist/lib/extension-search-tools.d.ts +8 -0
- package/dist/lib/extension-search-tools.js +12 -5
- package/dist/lib/extension-search-tools.js.map +1 -1
- package/dist/lib/mcp-instructions.js +3 -1
- package/dist/lib/mcp-instructions.js.map +1 -1
- package/dist/lib/model-eval.d.ts +4 -0
- package/dist/lib/model-eval.js +291 -0
- package/dist/lib/model-eval.js.map +1 -0
- package/dist/lib/pagination.d.ts +16 -0
- package/dist/lib/pagination.js +41 -0
- package/dist/lib/pagination.js.map +1 -0
- package/dist/lib/platform-operation-tools.d.ts +1 -0
- package/dist/lib/required-knowledge.d.ts +2 -2
- package/dist/lib/required-knowledge.js +8 -4
- package/dist/lib/required-knowledge.js.map +1 -1
- package/dist/lib/response-format.d.ts +3 -1
- package/dist/lib/response-format.js +47 -17
- package/dist/lib/response-format.js.map +1 -1
- package/dist/lib/runtime-zone-tools.d.ts +37 -0
- package/dist/lib/runtime-zone-tools.js +70 -16
- package/dist/lib/runtime-zone-tools.js.map +1 -1
- package/dist/lib/session-safety.js +3 -26
- package/dist/lib/session-safety.js.map +1 -1
- package/dist/lib/source-artifacts.d.ts +7 -0
- package/dist/lib/source-artifacts.js +38 -2
- package/dist/lib/source-artifacts.js.map +1 -1
- package/dist/lib/tool-catalog.d.ts +7 -0
- package/dist/lib/tool-catalog.js +141 -0
- package/dist/lib/tool-catalog.js.map +1 -0
- package/dist/lib/tool-contracts.d.ts +6 -0
- package/dist/lib/tool-contracts.js +99 -0
- package/dist/lib/tool-contracts.js.map +1 -0
- package/dist/lib/tool-output-contracts.d.ts +7 -0
- package/dist/lib/tool-output-contracts.js +152 -0
- package/dist/lib/tool-output-contracts.js.map +1 -0
- package/dist/lib/tool-routing.d.ts +2 -1
- package/dist/lib/tool-routing.js +27 -7
- package/dist/lib/tool-routing.js.map +1 -1
- package/dist/lib/toolset-filter.d.ts +7 -6
- package/dist/lib/toolset-filter.js +80 -22
- package/dist/lib/toolset-filter.js.map +1 -1
- package/dist/lib/types.d.ts +75 -0
- package/dist/lib/workflow-tool-packs.d.ts +2 -0
- package/dist/lib/workflow-tool-packs.js +55 -0
- package/dist/lib/workflow-tool-packs.js.map +1 -0
- package/dist/mcp-server-entry.js +48 -7
- package/dist/mcp-server-entry.js.map +1 -1
- package/package.json +5 -2
package/dist/lib/types.d.ts
CHANGED
|
@@ -15,6 +15,81 @@ export interface ToolResult {
|
|
|
15
15
|
_meta?: Record<string, unknown>;
|
|
16
16
|
}
|
|
17
17
|
export type UnknownRecord = Record<string, unknown>;
|
|
18
|
+
export interface McpToolAnnotations {
|
|
19
|
+
title: string;
|
|
20
|
+
readOnlyHint: boolean;
|
|
21
|
+
destructiveHint: boolean;
|
|
22
|
+
idempotentHint: boolean;
|
|
23
|
+
openWorldHint: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface McpToolContract {
|
|
26
|
+
name: string;
|
|
27
|
+
annotations: McpToolAnnotations;
|
|
28
|
+
catalogExecutable: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface RegisteredToolDefinition {
|
|
31
|
+
name: string;
|
|
32
|
+
description: string;
|
|
33
|
+
inputSchema: Record<string, unknown>;
|
|
34
|
+
annotations?: McpToolAnnotations;
|
|
35
|
+
handler: (...args: any[]) => any;
|
|
36
|
+
visible: boolean;
|
|
37
|
+
registration?: {
|
|
38
|
+
enabled: boolean;
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export interface ToolsetRegistrationState {
|
|
42
|
+
toolset: string;
|
|
43
|
+
profile: string;
|
|
44
|
+
dynamic: boolean;
|
|
45
|
+
hiddenTools: string[];
|
|
46
|
+
getTool(name: string): RegisteredToolDefinition | undefined;
|
|
47
|
+
listTools(): RegisteredToolDefinition[];
|
|
48
|
+
listVisibleToolNames(): string[];
|
|
49
|
+
setActiveTools(toolNames: Iterable<string>): {
|
|
50
|
+
changed: boolean;
|
|
51
|
+
visibleToolNames: string[];
|
|
52
|
+
hiddenToolCount: number;
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export type ToolAvailabilityStatus = 'allowed' | 'denied' | 'unknown';
|
|
56
|
+
export interface ToolAvailability {
|
|
57
|
+
status: ToolAvailabilityStatus;
|
|
58
|
+
reason: string;
|
|
59
|
+
}
|
|
60
|
+
export interface ModelEvalTraceEvent {
|
|
61
|
+
tool: string;
|
|
62
|
+
arguments?: Record<string, unknown>;
|
|
63
|
+
result?: unknown;
|
|
64
|
+
isError?: boolean;
|
|
65
|
+
}
|
|
66
|
+
export interface ModelEvalRun {
|
|
67
|
+
scenarioId: string;
|
|
68
|
+
model: string;
|
|
69
|
+
events: ModelEvalTraceEvent[];
|
|
70
|
+
}
|
|
71
|
+
export interface ModelEvalScenario {
|
|
72
|
+
id: string;
|
|
73
|
+
prompt: string;
|
|
74
|
+
surface: string;
|
|
75
|
+
requiredToolGroups: string[][];
|
|
76
|
+
verificationTools: string[];
|
|
77
|
+
maxToolCalls: number;
|
|
78
|
+
mutationExpected: boolean;
|
|
79
|
+
destructiveExpected?: boolean;
|
|
80
|
+
}
|
|
81
|
+
export interface ModelEvalCheck {
|
|
82
|
+
key: string;
|
|
83
|
+
passed: boolean;
|
|
84
|
+
detail: string;
|
|
85
|
+
}
|
|
86
|
+
export interface ModelEvalScore {
|
|
87
|
+
scenarioId: string;
|
|
88
|
+
model: string;
|
|
89
|
+
score: number;
|
|
90
|
+
recommended: boolean;
|
|
91
|
+
checks: ModelEvalCheck[];
|
|
92
|
+
}
|
|
18
93
|
export interface MetadataContext {
|
|
19
94
|
dbType: "postgres" | "mysql" | "mongodb" | "mariadb" | "sqlite" | null;
|
|
20
95
|
enfyraVersion: string | null;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { jsonContent } from './response-format.js';
|
|
3
|
+
import { WORKFLOW_SURFACES, workflowToolNames } from './tool-routing.js';
|
|
4
|
+
const MAX_ACTIVE_WORKFLOWS = 2;
|
|
5
|
+
export function registerWorkflowToolPack(server, state) {
|
|
6
|
+
const activeSurfaces = new Set();
|
|
7
|
+
return server.tool('select_enfyra_workflow', [
|
|
8
|
+
'Select a workflow surface and expose its exact direct MCP tools for this stdio session.',
|
|
9
|
+
'Use replace for normal tasks, add only when one task genuinely spans two surfaces, and reset to return to the compact routing surface.',
|
|
10
|
+
'This changes tool visibility only; it does not grant permissions or bypass Enfyra PAT/RBAC.',
|
|
11
|
+
].join(' '), {
|
|
12
|
+
surface: z.enum(WORKFLOW_SURFACES).optional().describe('Required for replace/add. Omit only with mode=reset.'),
|
|
13
|
+
mode: z.enum(['replace', 'add', 'reset']).optional().default('replace'),
|
|
14
|
+
}, async ({ surface, mode }) => {
|
|
15
|
+
if (mode !== 'reset' && !surface)
|
|
16
|
+
throw new Error('surface is required when mode is replace or add.');
|
|
17
|
+
if (mode === 'reset') {
|
|
18
|
+
activeSurfaces.clear();
|
|
19
|
+
}
|
|
20
|
+
else if (mode === 'replace') {
|
|
21
|
+
activeSurfaces.clear();
|
|
22
|
+
activeSurfaces.add(surface);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
activeSurfaces.add(surface);
|
|
26
|
+
if (activeSurfaces.size > MAX_ACTIVE_WORKFLOWS) {
|
|
27
|
+
activeSurfaces.delete(surface);
|
|
28
|
+
throw new Error(`At most ${MAX_ACTIVE_WORKFLOWS} workflow surfaces may be active. Use mode=replace or reset first.`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const packTools = [...activeSurfaces].flatMap(workflowToolNames);
|
|
32
|
+
const result = state.setActiveTools(packTools);
|
|
33
|
+
return jsonContent({
|
|
34
|
+
action: 'enfyra_workflow_selected',
|
|
35
|
+
mode,
|
|
36
|
+
dynamic: state.dynamic,
|
|
37
|
+
activeSurfaces: [...activeSurfaces],
|
|
38
|
+
visibleToolCount: result.visibleToolNames.length,
|
|
39
|
+
visibleTools: result.visibleToolNames,
|
|
40
|
+
hiddenToolCount: result.hiddenToolCount,
|
|
41
|
+
changed: result.changed,
|
|
42
|
+
guidance: state.dynamic
|
|
43
|
+
? [
|
|
44
|
+
'Refresh tools/list after this response if the host has not already processed notifications/tools/list_changed.',
|
|
45
|
+
'Call the newly visible workflow tools directly so their exact schemas, annotations, and safety gates remain active.',
|
|
46
|
+
'Use search_enfyra_tools only for hidden read-only long-tail helpers.',
|
|
47
|
+
]
|
|
48
|
+
: [
|
|
49
|
+
'Dynamic packs are disabled for this static profile/toolset; the configured profile remains visible.',
|
|
50
|
+
'Use ENFYRA_MCP_DYNAMIC_TOOLS=on with guided/all on hosts that support tools/list_changed.',
|
|
51
|
+
],
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=workflow-tool-packs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow-tool-packs.js","sourceRoot":"","sources":["../../src/lib/workflow-tool-packs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAwB,MAAM,mBAAmB,CAAC;AAG/F,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAE/B,MAAM,UAAU,wBAAwB,CAAC,MAAW,EAAE,KAA+B;IACnF,MAAM,cAAc,GAAG,IAAI,GAAG,EAAmB,CAAC;IAElD,OAAO,MAAM,CAAC,IAAI,CAChB,wBAAwB,EACxB;QACE,yFAAyF;QACzF,wIAAwI;QACxI,6FAA6F;KAC9F,CAAC,IAAI,CAAC,GAAG,CAAC,EACX;QACE,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sDAAsD,CAAC;QAC9G,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC;KACxE,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAoE,EAAE,EAAE;QAC5F,IAAI,IAAI,KAAK,OAAO,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACtG,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,cAAc,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC;aAAM,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YAC9B,cAAc,CAAC,KAAK,EAAE,CAAC;YACvB,cAAc,CAAC,GAAG,CAAC,OAAQ,CAAC,CAAC;QAC/B,CAAC;aAAM,CAAC;YACN,cAAc,CAAC,GAAG,CAAC,OAAQ,CAAC,CAAC;YAC7B,IAAI,cAAc,CAAC,IAAI,GAAG,oBAAoB,EAAE,CAAC;gBAC/C,cAAc,CAAC,MAAM,CAAC,OAAQ,CAAC,CAAC;gBAChC,MAAM,IAAI,KAAK,CAAC,WAAW,oBAAoB,oEAAoE,CAAC,CAAC;YACvH,CAAC;QACH,CAAC;QAED,MAAM,SAAS,GAAG,CAAC,GAAG,cAAc,CAAC,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QAC/C,OAAO,WAAW,CAAC;YACjB,MAAM,EAAE,0BAA0B;YAClC,IAAI;YACJ,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,cAAc,EAAE,CAAC,GAAG,cAAc,CAAC;YACnC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,CAAC,MAAM;YAChD,YAAY,EAAE,MAAM,CAAC,gBAAgB;YACrC,eAAe,EAAE,MAAM,CAAC,eAAe;YACvC,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,QAAQ,EAAE,KAAK,CAAC,OAAO;gBACrB,CAAC,CAAC;oBACE,gHAAgH;oBAChH,qHAAqH;oBACrH,sEAAsE;iBACvE;gBACH,CAAC,CAAC;oBACE,qGAAqG;oBACrG,2FAA2F;iBAC5F;SACN,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
|
package/dist/mcp-server-entry.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { config } from 'dotenv';
|
|
5
5
|
config();
|
|
6
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
6
|
+
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
7
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
8
8
|
import { z } from 'zod';
|
|
9
9
|
import { createHash } from 'node:crypto';
|
|
@@ -72,13 +72,18 @@ import { installColumnarToolFormatter, jsonContent } from './lib/response-format
|
|
|
72
72
|
import { startMcpUsageTelemetry } from './lib/mcp-usage-telemetry.js';
|
|
73
73
|
import { startRuntimeCacheSocket } from './lib/runtime-cache-socket.js';
|
|
74
74
|
import { executeSequentialBatch } from './lib/sequential-batch.js';
|
|
75
|
-
import { compactSourceFields, writeSourceArtifact } from './lib/source-artifacts.js';
|
|
76
|
-
import { installToolsetFilter, normalizeMcpProfile, normalizeMcpToolset, summarizeToolsetForInstructions } from './lib/toolset-filter.js';
|
|
75
|
+
import { compactSourceFields, readSourceArtifactResource, writeSourceArtifact } from './lib/source-artifacts.js';
|
|
76
|
+
import { installToolsetFilter, normalizeDynamicToolPacks, normalizeMcpProfile, normalizeMcpToolset, summarizeToolsetForInstructions } from './lib/toolset-filter.js';
|
|
77
|
+
import { installToolAnnotations } from './lib/tool-contracts.js';
|
|
78
|
+
import { installToolOutputContracts } from './lib/tool-output-contracts.js';
|
|
79
|
+
import { registerToolCatalogTools } from './lib/tool-catalog.js';
|
|
80
|
+
import { registerWorkflowToolPack } from './lib/workflow-tool-packs.js';
|
|
77
81
|
import { findRoutePermission, mergeMethodNames, normalizeMethodNames, resolveRoleByNameOrId, routeAvailableMethodNames, routePublicMethodNames, summarizeRouteAccess, summarizeRoutePermission, validateMethodsForRoute, } from './lib/route-permission-tools.js';
|
|
78
82
|
// Initialize auth module
|
|
79
83
|
initAuth(ENFYRA_API_URL, ENFYRA_API_TOKEN);
|
|
80
84
|
const MCP_TOOLSET = normalizeMcpToolset(process.env.ENFYRA_MCP_TOOLSET);
|
|
81
85
|
const MCP_PROFILE = normalizeMcpProfile(process.env.ENFYRA_MCP_PROFILE);
|
|
86
|
+
const MCP_DYNAMIC_TOOLS = normalizeDynamicToolPacks(process.env.ENFYRA_MCP_DYNAMIC_TOOLS, MCP_TOOLSET, MCP_PROFILE);
|
|
82
87
|
const CAPABILITY_AREAS = [
|
|
83
88
|
{
|
|
84
89
|
area: 'Schema and metadata',
|
|
@@ -418,6 +423,30 @@ function summarizePermissionProfile(user) {
|
|
|
418
423
|
})),
|
|
419
424
|
};
|
|
420
425
|
}
|
|
426
|
+
async function resolveCatalogToolAvailability(toolNames) {
|
|
427
|
+
const fields = DEFAULT_ME_PERMISSION_FIELDS.join(',');
|
|
428
|
+
const result = await fetchAPI(ENFYRA_API_URL, `/me?fields=${encodeURIComponent(fields)}`);
|
|
429
|
+
const user = firstDataRecord(result);
|
|
430
|
+
if (user?.isRootAdmin) {
|
|
431
|
+
return Object.fromEntries(toolNames.map((name) => [name, {
|
|
432
|
+
status: 'allowed',
|
|
433
|
+
reason: 'The configured PAT belongs to a root administrator.',
|
|
434
|
+
}]));
|
|
435
|
+
}
|
|
436
|
+
const requirements = summarizePermissionProfile(user).mcpRequirements;
|
|
437
|
+
return Object.fromEntries(toolNames.map((name) => {
|
|
438
|
+
const requirement = requirements.find((item) => item.tools.includes(name));
|
|
439
|
+
if (!requirement) {
|
|
440
|
+
return [name, {
|
|
441
|
+
status: 'unknown',
|
|
442
|
+
reason: 'No static admin-route capability mapping exists for this tool; Enfyra PAT/RBAC remains authoritative at execution time.',
|
|
443
|
+
}];
|
|
444
|
+
}
|
|
445
|
+
return [name, requirement.allowed
|
|
446
|
+
? { status: 'allowed', reason: `Current PAT grants ${requirement.methods.map((item) => item.method).join(', ')} ${requirement.route}.` }
|
|
447
|
+
: { status: 'denied', reason: `Current PAT lacks one or more required methods on ${requirement.route}.` }];
|
|
448
|
+
}));
|
|
449
|
+
}
|
|
421
450
|
function parseJsonArg(value, fallback = undefined) {
|
|
422
451
|
if (value === undefined || value === null || value === '')
|
|
423
452
|
return fallback;
|
|
@@ -810,12 +839,19 @@ const server = new McpServer({
|
|
|
810
839
|
version: '1.0.0',
|
|
811
840
|
}, {
|
|
812
841
|
instructions: buildMcpServerInstructions(ENFYRA_API_URL, {
|
|
813
|
-
toolsetSummary: summarizeToolsetForInstructions(MCP_TOOLSET, MCP_PROFILE),
|
|
842
|
+
toolsetSummary: summarizeToolsetForInstructions(MCP_TOOLSET, MCP_PROFILE, MCP_DYNAMIC_TOOLS),
|
|
814
843
|
}),
|
|
815
844
|
});
|
|
845
|
+
installToolOutputContracts(server);
|
|
816
846
|
installColumnarToolFormatter(server);
|
|
817
|
-
installToolsetFilter(server, MCP_TOOLSET, MCP_PROFILE);
|
|
847
|
+
const toolsetState = installToolsetFilter(server, MCP_TOOLSET, MCP_PROFILE, { dynamic: MCP_DYNAMIC_TOOLS });
|
|
848
|
+
installToolAnnotations(server);
|
|
818
849
|
startMcpUsageTelemetry(ENFYRA_API_URL, `${MCP_TOOLSET}:${MCP_PROFILE}`);
|
|
850
|
+
server.registerResource('enfyra-source-artifact', new ResourceTemplate('enfyra-source://artifact/{artifactId}', { list: undefined }), {
|
|
851
|
+
title: 'Enfyra source artifact',
|
|
852
|
+
description: 'Process-scoped source or diff artifact created by an Enfyra MCP inspect or preview tool.',
|
|
853
|
+
mimeType: 'text/plain',
|
|
854
|
+
}, async (uri) => ({ contents: [readSourceArtifactResource(uri.href)] }));
|
|
819
855
|
// ============================================================================
|
|
820
856
|
// METADATA TOOLS
|
|
821
857
|
// ============================================================================
|
|
@@ -1632,10 +1668,11 @@ server.tool('update_records', 'Update one or more records in one MCP call. Pass
|
|
|
1632
1668
|
});
|
|
1633
1669
|
server.tool('get_script_source', [
|
|
1634
1670
|
'Fetch the full editable source for one script-backed metadata record without preview truncation.',
|
|
1635
|
-
'Use
|
|
1671
|
+
'Use search_runtime_zone first and pass the returned nextInspect.input to inspect the concrete record. The inspection already returns exact source artifacts.',
|
|
1672
|
+
'Call get_script_source only when a fresh artifact is needed for that located record. Never guess or probe record ids.',
|
|
1636
1673
|
].join(' '), {
|
|
1637
1674
|
tableName: z.enum(SCRIPT_BACKED_TABLES).describe('Script-backed table to read'),
|
|
1638
|
-
id: z.string().describe('
|
|
1675
|
+
id: z.string().describe('Concrete record id returned by search_runtime_zone, inspect output, or a successful create/update operation. Never guess an id.'),
|
|
1639
1676
|
}, async ({ tableName, id }) => {
|
|
1640
1677
|
const { primaryKey, record, sourceField, sourceCode } = await fetchScriptRecord(tableName, id);
|
|
1641
1678
|
const sourceArtifact = writeSourceArtifact({ tableName, id, fieldName: sourceField, source: sourceCode });
|
|
@@ -3149,6 +3186,10 @@ server.tool('install_package', [
|
|
|
3149
3186
|
result,
|
|
3150
3187
|
});
|
|
3151
3188
|
});
|
|
3189
|
+
registerToolCatalogTools(server, toolsetState, {
|
|
3190
|
+
resolveAvailability: resolveCatalogToolAvailability,
|
|
3191
|
+
});
|
|
3192
|
+
registerWorkflowToolPack(server, toolsetState);
|
|
3152
3193
|
// ============================================================================
|
|
3153
3194
|
// MAIN
|
|
3154
3195
|
// ============================================================================
|