@robinmordasiewicz/f5xc-api-mcp 3.0.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/CHANGELOG.md +74 -0
- package/README.md +234 -0
- package/dist/auth/credential-manager.d.ts +116 -0
- package/dist/auth/credential-manager.d.ts.map +1 -0
- package/dist/auth/credential-manager.js +208 -0
- package/dist/auth/credential-manager.js.map +1 -0
- package/dist/auth/http-client.d.ts +81 -0
- package/dist/auth/http-client.d.ts.map +1 -0
- package/dist/auth/http-client.js +197 -0
- package/dist/auth/http-client.js.map +1 -0
- package/dist/auth/index.d.ts +8 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +6 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/generator/index.d.ts +7 -0
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/index.js +7 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/generator/naming/acronyms.d.ts +81 -0
- package/dist/generator/naming/acronyms.d.ts.map +1 -0
- package/dist/generator/naming/acronyms.js +253 -0
- package/dist/generator/naming/acronyms.js.map +1 -0
- package/dist/generator/naming/index.d.ts +6 -0
- package/dist/generator/naming/index.d.ts.map +1 -0
- package/dist/generator/naming/index.js +6 -0
- package/dist/generator/naming/index.js.map +1 -0
- package/dist/generator/naming/volterra-mapping.d.ts +102 -0
- package/dist/generator/naming/volterra-mapping.d.ts.map +1 -0
- package/dist/generator/naming/volterra-mapping.js +259 -0
- package/dist/generator/naming/volterra-mapping.js.map +1 -0
- package/dist/generator/openapi-parser.d.ts +339 -0
- package/dist/generator/openapi-parser.d.ts.map +1 -0
- package/dist/generator/openapi-parser.js +463 -0
- package/dist/generator/openapi-parser.js.map +1 -0
- package/dist/generator/tool-generator.d.ts +74 -0
- package/dist/generator/tool-generator.d.ts.map +1 -0
- package/dist/generator/tool-generator.js +387 -0
- package/dist/generator/tool-generator.js.map +1 -0
- package/dist/generator/transformers/index.d.ts +7 -0
- package/dist/generator/transformers/index.d.ts.map +1 -0
- package/dist/generator/transformers/index.js +7 -0
- package/dist/generator/transformers/index.js.map +1 -0
- package/dist/generator/transformers/normalize-examples.d.ts +48 -0
- package/dist/generator/transformers/normalize-examples.d.ts.map +1 -0
- package/dist/generator/transformers/normalize-examples.js +66 -0
- package/dist/generator/transformers/normalize-examples.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +70 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/index.d.ts +6 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +5 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/workflows.d.ts +59 -0
- package/dist/prompts/workflows.d.ts.map +1 -0
- package/dist/prompts/workflows.js +585 -0
- package/dist/prompts/workflows.js.map +1 -0
- package/dist/resources/handlers.d.ts +72 -0
- package/dist/resources/handlers.d.ts.map +1 -0
- package/dist/resources/handlers.js +279 -0
- package/dist/resources/handlers.js.map +1 -0
- package/dist/resources/index.d.ts +8 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +6 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/templates.d.ts +86 -0
- package/dist/resources/templates.d.ts.map +1 -0
- package/dist/resources/templates.js +248 -0
- package/dist/resources/templates.js.map +1 -0
- package/dist/server.d.ts +78 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +426 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/discovery/consolidate.d.ts +97 -0
- package/dist/tools/discovery/consolidate.d.ts.map +1 -0
- package/dist/tools/discovery/consolidate.js +200 -0
- package/dist/tools/discovery/consolidate.js.map +1 -0
- package/dist/tools/discovery/describe.d.ts +132 -0
- package/dist/tools/discovery/describe.d.ts.map +1 -0
- package/dist/tools/discovery/describe.js +206 -0
- package/dist/tools/discovery/describe.js.map +1 -0
- package/dist/tools/discovery/execute.d.ts +98 -0
- package/dist/tools/discovery/execute.d.ts.map +1 -0
- package/dist/tools/discovery/execute.js +251 -0
- package/dist/tools/discovery/execute.js.map +1 -0
- package/dist/tools/discovery/index-loader.d.ts +28 -0
- package/dist/tools/discovery/index-loader.d.ts.map +1 -0
- package/dist/tools/discovery/index-loader.js +69 -0
- package/dist/tools/discovery/index-loader.js.map +1 -0
- package/dist/tools/discovery/index.d.ts +185 -0
- package/dist/tools/discovery/index.d.ts.map +1 -0
- package/dist/tools/discovery/index.js +177 -0
- package/dist/tools/discovery/index.js.map +1 -0
- package/dist/tools/discovery/search.d.ts +41 -0
- package/dist/tools/discovery/search.d.ts.map +1 -0
- package/dist/tools/discovery/search.js +155 -0
- package/dist/tools/discovery/search.js.map +1 -0
- package/dist/tools/discovery/types.d.ts +70 -0
- package/dist/tools/discovery/types.d.ts.map +1 -0
- package/dist/tools/discovery/types.js +9 -0
- package/dist/tools/discovery/types.js.map +1 -0
- package/dist/tools/generated/ai_intelligence/index.d.ts +8 -0
- package/dist/tools/generated/ai_intelligence/index.d.ts.map +1 -0
- package/dist/tools/generated/ai_intelligence/index.js +282 -0
- package/dist/tools/generated/ai_intelligence/index.js.map +1 -0
- package/dist/tools/generated/api_security/index.d.ts +8 -0
- package/dist/tools/generated/api_security/index.d.ts.map +1 -0
- package/dist/tools/generated/api_security/index.js +1852 -0
- package/dist/tools/generated/api_security/index.js.map +1 -0
- package/dist/tools/generated/applications/index.d.ts +8 -0
- package/dist/tools/generated/applications/index.d.ts.map +1 -0
- package/dist/tools/generated/applications/index.js +1589 -0
- package/dist/tools/generated/applications/index.js.map +1 -0
- package/dist/tools/generated/bigip/index.d.ts +8 -0
- package/dist/tools/generated/bigip/index.d.ts.map +1 -0
- package/dist/tools/generated/bigip/index.js +1173 -0
- package/dist/tools/generated/bigip/index.js.map +1 -0
- package/dist/tools/generated/billing/index.d.ts +8 -0
- package/dist/tools/generated/billing/index.d.ts.map +1 -0
- package/dist/tools/generated/billing/index.js +759 -0
- package/dist/tools/generated/billing/index.js.map +1 -0
- package/dist/tools/generated/cdn/index.d.ts +8 -0
- package/dist/tools/generated/cdn/index.d.ts.map +1 -0
- package/dist/tools/generated/cdn/index.js +841 -0
- package/dist/tools/generated/cdn/index.js.map +1 -0
- package/dist/tools/generated/config/index.d.ts +8 -0
- package/dist/tools/generated/config/index.d.ts.map +1 -0
- package/dist/tools/generated/config/index.js +316 -0
- package/dist/tools/generated/config/index.js.map +1 -0
- package/dist/tools/generated/identity/index.d.ts +8 -0
- package/dist/tools/generated/identity/index.d.ts.map +1 -0
- package/dist/tools/generated/identity/index.js +5371 -0
- package/dist/tools/generated/identity/index.js.map +1 -0
- package/dist/tools/generated/infrastructure/index.d.ts +8 -0
- package/dist/tools/generated/infrastructure/index.d.ts.map +1 -0
- package/dist/tools/generated/infrastructure/index.js +5342 -0
- package/dist/tools/generated/infrastructure/index.js.map +1 -0
- package/dist/tools/generated/infrastructure_protection/index.d.ts +8 -0
- package/dist/tools/generated/infrastructure_protection/index.d.ts.map +1 -0
- package/dist/tools/generated/infrastructure_protection/index.js +2919 -0
- package/dist/tools/generated/infrastructure_protection/index.js.map +1 -0
- package/dist/tools/generated/integrations/index.d.ts +8 -0
- package/dist/tools/generated/integrations/index.d.ts.map +1 -0
- package/dist/tools/generated/integrations/index.js +1995 -0
- package/dist/tools/generated/integrations/index.js.map +1 -0
- package/dist/tools/generated/load_balancer/index.d.ts +8 -0
- package/dist/tools/generated/load_balancer/index.d.ts.map +1 -0
- package/dist/tools/generated/load_balancer/index.js +2269 -0
- package/dist/tools/generated/load_balancer/index.js.map +1 -0
- package/dist/tools/generated/networking/index.d.ts +8 -0
- package/dist/tools/generated/networking/index.d.ts.map +1 -0
- package/dist/tools/generated/networking/index.js +11289 -0
- package/dist/tools/generated/networking/index.js.map +1 -0
- package/dist/tools/generated/nginx/index.d.ts +8 -0
- package/dist/tools/generated/nginx/index.d.ts.map +1 -0
- package/dist/tools/generated/nginx/index.js +680 -0
- package/dist/tools/generated/nginx/index.js.map +1 -0
- package/dist/tools/generated/observability/index.d.ts +8 -0
- package/dist/tools/generated/observability/index.d.ts.map +1 -0
- package/dist/tools/generated/observability/index.js +6140 -0
- package/dist/tools/generated/observability/index.js.map +1 -0
- package/dist/tools/generated/operations/index.d.ts +8 -0
- package/dist/tools/generated/operations/index.d.ts.map +1 -0
- package/dist/tools/generated/operations/index.js +1759 -0
- package/dist/tools/generated/operations/index.js.map +1 -0
- package/dist/tools/generated/security/index.d.ts +8 -0
- package/dist/tools/generated/security/index.d.ts.map +1 -0
- package/dist/tools/generated/security/index.js +9111 -0
- package/dist/tools/generated/security/index.js.map +1 -0
- package/dist/tools/generated/service_mesh/index.d.ts +8 -0
- package/dist/tools/generated/service_mesh/index.d.ts.map +1 -0
- package/dist/tools/generated/service_mesh/index.js +1628 -0
- package/dist/tools/generated/service_mesh/index.js.map +1 -0
- package/dist/tools/generated/shape_security/index.d.ts +8 -0
- package/dist/tools/generated/shape_security/index.d.ts.map +1 -0
- package/dist/tools/generated/shape_security/index.js +4121 -0
- package/dist/tools/generated/shape_security/index.js.map +1 -0
- package/dist/tools/generated/subscriptions/index.d.ts +8 -0
- package/dist/tools/generated/subscriptions/index.d.ts.map +1 -0
- package/dist/tools/generated/subscriptions/index.js +778 -0
- package/dist/tools/generated/subscriptions/index.js.map +1 -0
- package/dist/tools/generated/tenant_management/index.d.ts +8 -0
- package/dist/tools/generated/tenant_management/index.d.ts.map +1 -0
- package/dist/tools/generated/tenant_management/index.js +2292 -0
- package/dist/tools/generated/tenant_management/index.js.map +1 -0
- package/dist/tools/generated/vpn/index.d.ts +8 -0
- package/dist/tools/generated/vpn/index.d.ts.map +1 -0
- package/dist/tools/generated/vpn/index.js +1183 -0
- package/dist/tools/generated/vpn/index.js.map +1 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +6 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +27 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +83 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/utils/error-handling.d.ts +109 -0
- package/dist/utils/error-handling.d.ts.map +1 -0
- package/dist/utils/error-handling.js +239 -0
- package/dist/utils/error-handling.js.map +1 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logging.d.ts +75 -0
- package/dist/utils/logging.d.ts.map +1 -0
- package/dist/utils/logging.js +131 -0
- package/dist/utils/logging.js.map +1 -0
- package/manifest.json +143 -0
- package/package.json +95 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* F5 Distributed Cloud API MCP Server
|
|
3
|
+
*
|
|
4
|
+
* This module initializes and configures the MCP server with STDIO transport.
|
|
5
|
+
* Supports dual-mode operation: documentation mode (unauthenticated) and
|
|
6
|
+
* execution mode (authenticated with F5XC credentials).
|
|
7
|
+
*/
|
|
8
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
9
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import { CredentialManager, AuthMode } from "./auth/credential-manager.js";
|
|
12
|
+
import { createHttpClient } from "./auth/http-client.js";
|
|
13
|
+
import { logger } from "./utils/logging.js";
|
|
14
|
+
import { VERSION } from "./index.js";
|
|
15
|
+
import { WORKFLOW_PROMPTS, processPromptTemplate } from "./prompts/index.js";
|
|
16
|
+
import { RESOURCE_TYPES, createResourceHandler } from "./resources/index.js";
|
|
17
|
+
import { DISCOVERY_TOOLS, searchTools, describeTool, executeTool, getIndexMetadata, getAvailableDomains, searchConsolidatedResources, resolveConsolidatedTool, getConsolidatedResource, getConsolidationStats, } from "./tools/discovery/index.js";
|
|
18
|
+
/**
|
|
19
|
+
* F5XC API MCP Server
|
|
20
|
+
*
|
|
21
|
+
* Provides tools, resources, and prompts for interacting with F5 Distributed Cloud APIs.
|
|
22
|
+
* Works in two modes:
|
|
23
|
+
* - Documentation mode: Returns API documentation, schemas, f5xcctl equivalents, Terraform examples
|
|
24
|
+
* - Execution mode: Directly executes API calls when authenticated
|
|
25
|
+
*/
|
|
26
|
+
export class F5XCApiServer {
|
|
27
|
+
server;
|
|
28
|
+
credentialManager;
|
|
29
|
+
httpClient = null;
|
|
30
|
+
resourceHandler;
|
|
31
|
+
transport = null;
|
|
32
|
+
constructor(config) {
|
|
33
|
+
this.credentialManager = config.credentialManager;
|
|
34
|
+
// Create HTTP client if authenticated
|
|
35
|
+
if (this.credentialManager.getAuthMode() !== AuthMode.NONE) {
|
|
36
|
+
this.httpClient = createHttpClient(this.credentialManager);
|
|
37
|
+
}
|
|
38
|
+
// Create resource handler
|
|
39
|
+
this.resourceHandler = createResourceHandler(this.credentialManager, this.httpClient);
|
|
40
|
+
this.server = new McpServer({
|
|
41
|
+
name: config.name,
|
|
42
|
+
version: config.version,
|
|
43
|
+
});
|
|
44
|
+
this.registerCapabilities();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Register all MCP capabilities (tools, resources, prompts)
|
|
48
|
+
*/
|
|
49
|
+
registerCapabilities() {
|
|
50
|
+
this.registerTools();
|
|
51
|
+
this.registerResources();
|
|
52
|
+
this.registerPrompts();
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Register MCP tools for F5XC API operations
|
|
56
|
+
*
|
|
57
|
+
* Uses the dynamic discovery pattern for token efficiency:
|
|
58
|
+
* - 3 meta-tools instead of 1,400+ individual tools
|
|
59
|
+
* - Reduces upfront token consumption from ~535K to ~500 tokens
|
|
60
|
+
* - Full tool schemas loaded on-demand via describe_tool
|
|
61
|
+
*/
|
|
62
|
+
registerTools() {
|
|
63
|
+
const authMode = this.credentialManager.getAuthMode();
|
|
64
|
+
// Server info tool - provides server metadata and tool statistics
|
|
65
|
+
this.server.tool(DISCOVERY_TOOLS.serverInfo.name, DISCOVERY_TOOLS.serverInfo.description, {}, async () => {
|
|
66
|
+
const isAuthenticated = authMode !== AuthMode.NONE;
|
|
67
|
+
const tenantUrl = this.credentialManager.getApiUrl();
|
|
68
|
+
const indexMetadata = getIndexMetadata();
|
|
69
|
+
const domains = getAvailableDomains();
|
|
70
|
+
return {
|
|
71
|
+
content: [
|
|
72
|
+
{
|
|
73
|
+
type: "text",
|
|
74
|
+
text: JSON.stringify({
|
|
75
|
+
server: "f5xc-api-mcp",
|
|
76
|
+
version: VERSION,
|
|
77
|
+
mode: isAuthenticated ? "execution" : "documentation",
|
|
78
|
+
authenticated: isAuthenticated,
|
|
79
|
+
authMethod: authMode,
|
|
80
|
+
tenantUrl: isAuthenticated ? tenantUrl : null,
|
|
81
|
+
capabilities: {
|
|
82
|
+
documentation: true,
|
|
83
|
+
f5xcctl_equivalents: true,
|
|
84
|
+
terraform_examples: true,
|
|
85
|
+
api_execution: isAuthenticated,
|
|
86
|
+
},
|
|
87
|
+
toolIndex: {
|
|
88
|
+
totalTools: indexMetadata.totalTools,
|
|
89
|
+
domains: indexMetadata.domains,
|
|
90
|
+
availableDomains: domains,
|
|
91
|
+
},
|
|
92
|
+
consolidation: getConsolidationStats(),
|
|
93
|
+
discoveryTools: [
|
|
94
|
+
"f5xc-api-search-tools",
|
|
95
|
+
"f5xc-api-describe-tool",
|
|
96
|
+
"f5xc-api-execute-tool",
|
|
97
|
+
"f5xc-api-search-resources",
|
|
98
|
+
"f5xc-api-execute-resource",
|
|
99
|
+
],
|
|
100
|
+
message: isAuthenticated
|
|
101
|
+
? "Authenticated - API execution enabled. Use f5xc-api-search-tools to find available API tools."
|
|
102
|
+
: "Documentation mode. Set F5XC_API_URL and F5XC_API_TOKEN to enable API execution.",
|
|
103
|
+
}, null, 2),
|
|
104
|
+
},
|
|
105
|
+
],
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
// Search tools - find tools matching natural language queries
|
|
109
|
+
this.server.tool(DISCOVERY_TOOLS.search.name, DISCOVERY_TOOLS.search.description, {
|
|
110
|
+
query: z.string().describe("Natural language search query"),
|
|
111
|
+
limit: z.number().optional().describe("Maximum results (default: 10)"),
|
|
112
|
+
domains: z.array(z.string()).optional().describe("Filter by domains"),
|
|
113
|
+
operations: z.array(z.string()).optional().describe("Filter by operations"),
|
|
114
|
+
}, async (args) => {
|
|
115
|
+
const results = searchTools(args.query, {
|
|
116
|
+
limit: Math.min(args.limit ?? 10, 50),
|
|
117
|
+
domains: args.domains,
|
|
118
|
+
operations: args.operations,
|
|
119
|
+
});
|
|
120
|
+
return {
|
|
121
|
+
content: [
|
|
122
|
+
{
|
|
123
|
+
type: "text",
|
|
124
|
+
text: JSON.stringify({
|
|
125
|
+
query: args.query,
|
|
126
|
+
resultCount: results.length,
|
|
127
|
+
results: results.map((r) => ({
|
|
128
|
+
name: r.tool.name,
|
|
129
|
+
domain: r.tool.domain,
|
|
130
|
+
resource: r.tool.resource,
|
|
131
|
+
operation: r.tool.operation,
|
|
132
|
+
summary: r.tool.summary,
|
|
133
|
+
score: Math.round(r.score * 100) / 100,
|
|
134
|
+
})),
|
|
135
|
+
hint: "Use f5xc-api-describe-tool to get full schema for a specific tool.",
|
|
136
|
+
}, null, 2),
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
};
|
|
140
|
+
});
|
|
141
|
+
// Describe tool - get full schema for a specific tool
|
|
142
|
+
this.server.tool(DISCOVERY_TOOLS.describe.name, DISCOVERY_TOOLS.describe.description, {
|
|
143
|
+
toolName: z.string().describe("Exact tool name to describe"),
|
|
144
|
+
}, async (args) => {
|
|
145
|
+
const description = describeTool(args.toolName);
|
|
146
|
+
if (!description) {
|
|
147
|
+
return {
|
|
148
|
+
content: [
|
|
149
|
+
{
|
|
150
|
+
type: "text",
|
|
151
|
+
text: JSON.stringify({
|
|
152
|
+
error: `Tool "${args.toolName}" not found`,
|
|
153
|
+
hint: "Use f5xc-api-search-tools to find available tools.",
|
|
154
|
+
}, null, 2),
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
content: [
|
|
161
|
+
{
|
|
162
|
+
type: "text",
|
|
163
|
+
text: JSON.stringify({
|
|
164
|
+
tool: description,
|
|
165
|
+
hint: "Use f5xc-api-execute-tool to execute this tool.",
|
|
166
|
+
}, null, 2),
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
};
|
|
170
|
+
});
|
|
171
|
+
// Execute tool - execute a specific tool with parameters
|
|
172
|
+
this.server.tool(DISCOVERY_TOOLS.execute.name, DISCOVERY_TOOLS.execute.description, {
|
|
173
|
+
toolName: z.string().describe("Tool name to execute"),
|
|
174
|
+
pathParams: z.record(z.string(), z.string()).optional().describe("Path parameters"),
|
|
175
|
+
queryParams: z.record(z.string(), z.string()).optional().describe("Query parameters"),
|
|
176
|
+
body: z.record(z.string(), z.unknown()).optional().describe("Request body"),
|
|
177
|
+
}, async (args) => {
|
|
178
|
+
const result = await executeTool({
|
|
179
|
+
toolName: args.toolName,
|
|
180
|
+
pathParams: args.pathParams,
|
|
181
|
+
queryParams: args.queryParams,
|
|
182
|
+
body: args.body,
|
|
183
|
+
}, this.credentialManager);
|
|
184
|
+
return {
|
|
185
|
+
content: [
|
|
186
|
+
{
|
|
187
|
+
type: "text",
|
|
188
|
+
text: JSON.stringify(result, null, 2),
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
};
|
|
192
|
+
});
|
|
193
|
+
// Search resources - consolidated resource search
|
|
194
|
+
this.server.tool(DISCOVERY_TOOLS.searchResources.name, DISCOVERY_TOOLS.searchResources.description, {
|
|
195
|
+
query: z.string().describe("Natural language search query"),
|
|
196
|
+
limit: z.number().optional().describe("Maximum results (default: 10)"),
|
|
197
|
+
domains: z.array(z.string()).optional().describe("Filter by domains"),
|
|
198
|
+
}, async (args) => {
|
|
199
|
+
const results = searchConsolidatedResources(args.query, {
|
|
200
|
+
limit: Math.min(args.limit ?? 10, 50),
|
|
201
|
+
domains: args.domains,
|
|
202
|
+
});
|
|
203
|
+
return {
|
|
204
|
+
content: [
|
|
205
|
+
{
|
|
206
|
+
type: "text",
|
|
207
|
+
text: JSON.stringify({
|
|
208
|
+
query: args.query,
|
|
209
|
+
resultCount: results.length,
|
|
210
|
+
results: results.map((r) => ({
|
|
211
|
+
name: r.resource.name,
|
|
212
|
+
domain: r.resource.domain,
|
|
213
|
+
resource: r.resource.resource,
|
|
214
|
+
operations: r.resource.operations,
|
|
215
|
+
summary: r.resource.summary,
|
|
216
|
+
isFullCrud: r.resource.isFullCrud,
|
|
217
|
+
score: Math.round(r.score * 100) / 100,
|
|
218
|
+
})),
|
|
219
|
+
hint: "Use f5xc-api-execute-resource with resourceName and operation to execute.",
|
|
220
|
+
}, null, 2),
|
|
221
|
+
},
|
|
222
|
+
],
|
|
223
|
+
};
|
|
224
|
+
});
|
|
225
|
+
// Execute resource - execute a CRUD operation on a consolidated resource
|
|
226
|
+
this.server.tool(DISCOVERY_TOOLS.executeResource.name, DISCOVERY_TOOLS.executeResource.description, {
|
|
227
|
+
resourceName: z.string().describe("Consolidated resource name"),
|
|
228
|
+
operation: z.enum(["create", "get", "list", "update", "delete"]).describe("CRUD operation"),
|
|
229
|
+
pathParams: z.record(z.string(), z.string()).optional().describe("Path parameters"),
|
|
230
|
+
queryParams: z.record(z.string(), z.string()).optional().describe("Query parameters"),
|
|
231
|
+
body: z.record(z.string(), z.unknown()).optional().describe("Request body"),
|
|
232
|
+
}, async (args) => {
|
|
233
|
+
// Resolve to underlying tool
|
|
234
|
+
const toolName = resolveConsolidatedTool(args.resourceName, args.operation);
|
|
235
|
+
if (!toolName) {
|
|
236
|
+
const resource = getConsolidatedResource(args.resourceName);
|
|
237
|
+
if (!resource) {
|
|
238
|
+
return {
|
|
239
|
+
content: [
|
|
240
|
+
{
|
|
241
|
+
type: "text",
|
|
242
|
+
text: JSON.stringify({
|
|
243
|
+
error: `Resource "${args.resourceName}" not found`,
|
|
244
|
+
hint: "Use f5xc-api-search-resources to find available resources.",
|
|
245
|
+
}, null, 2),
|
|
246
|
+
},
|
|
247
|
+
],
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
content: [
|
|
252
|
+
{
|
|
253
|
+
type: "text",
|
|
254
|
+
text: JSON.stringify({
|
|
255
|
+
error: `Operation "${args.operation}" not available for "${args.resourceName}"`,
|
|
256
|
+
availableOperations: resource.operations,
|
|
257
|
+
}, null, 2),
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
// Execute the resolved tool
|
|
263
|
+
const result = await executeTool({
|
|
264
|
+
toolName,
|
|
265
|
+
pathParams: args.pathParams,
|
|
266
|
+
queryParams: args.queryParams,
|
|
267
|
+
body: args.body,
|
|
268
|
+
}, this.credentialManager);
|
|
269
|
+
return {
|
|
270
|
+
content: [
|
|
271
|
+
{
|
|
272
|
+
type: "text",
|
|
273
|
+
text: JSON.stringify({
|
|
274
|
+
resolvedTool: toolName,
|
|
275
|
+
...result,
|
|
276
|
+
}, null, 2),
|
|
277
|
+
},
|
|
278
|
+
],
|
|
279
|
+
};
|
|
280
|
+
});
|
|
281
|
+
const indexMetadata = getIndexMetadata();
|
|
282
|
+
const consolidationStats = getConsolidationStats();
|
|
283
|
+
logger.info("Tool registration completed (dynamic discovery mode)", {
|
|
284
|
+
authMode,
|
|
285
|
+
authenticated: authMode !== AuthMode.NONE,
|
|
286
|
+
registeredTools: 6,
|
|
287
|
+
indexedTools: indexMetadata.totalTools,
|
|
288
|
+
consolidatedResources: consolidationStats.consolidatedCount,
|
|
289
|
+
consolidationReduction: consolidationStats.reductionPercent,
|
|
290
|
+
domains: Object.keys(indexMetadata.domains),
|
|
291
|
+
tokenSavings: "95%+ (535K → ~500 tokens upfront)",
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Register MCP resources for F5XC configuration objects
|
|
296
|
+
*/
|
|
297
|
+
registerResources() {
|
|
298
|
+
const tenant = this.credentialManager.getTenant() ?? "{tenant}";
|
|
299
|
+
// Register resource templates for each resource type
|
|
300
|
+
for (const rt of Object.values(RESOURCE_TYPES)) {
|
|
301
|
+
const uriTemplate = rt.namespaceScoped
|
|
302
|
+
? `f5xc://${tenant}/{namespace}/${rt.type}/{name}`
|
|
303
|
+
: `f5xc://${tenant}/system/${rt.type}/{name}`;
|
|
304
|
+
this.server.resource(uriTemplate, rt.description, async (uri) => {
|
|
305
|
+
try {
|
|
306
|
+
const result = await this.resourceHandler.readResource(uri.href);
|
|
307
|
+
return {
|
|
308
|
+
contents: [
|
|
309
|
+
{
|
|
310
|
+
uri: result.uri,
|
|
311
|
+
mimeType: result.mimeType,
|
|
312
|
+
text: result.content,
|
|
313
|
+
},
|
|
314
|
+
],
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
logger.error(`Failed to read resource: ${uri.href}`, {
|
|
319
|
+
error: error instanceof Error ? error.message : String(error),
|
|
320
|
+
});
|
|
321
|
+
throw error;
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
logger.info("Resource registration completed", {
|
|
326
|
+
resourceTypes: Object.keys(RESOURCE_TYPES).length,
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Register MCP prompts for common workflows
|
|
331
|
+
*/
|
|
332
|
+
registerPrompts() {
|
|
333
|
+
// Register all workflow prompts
|
|
334
|
+
for (const workflow of WORKFLOW_PROMPTS) {
|
|
335
|
+
// Build Zod schema for arguments
|
|
336
|
+
const argSchema = {};
|
|
337
|
+
for (const arg of workflow.arguments) {
|
|
338
|
+
argSchema[arg.name] = arg.required
|
|
339
|
+
? z.string().describe(arg.description)
|
|
340
|
+
: z.string().optional().describe(arg.description);
|
|
341
|
+
}
|
|
342
|
+
this.server.prompt(workflow.name, workflow.description, argSchema, async (args) => {
|
|
343
|
+
// Process template with provided arguments
|
|
344
|
+
const processedArgs = {};
|
|
345
|
+
for (const [key, value] of Object.entries(args)) {
|
|
346
|
+
if (typeof value === "string") {
|
|
347
|
+
processedArgs[key] = value;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
// Apply default values for optional args
|
|
351
|
+
for (const arg of workflow.arguments) {
|
|
352
|
+
if (!processedArgs[arg.name] && !arg.required) {
|
|
353
|
+
// Set sensible defaults
|
|
354
|
+
if (arg.name === "backend_port")
|
|
355
|
+
processedArgs[arg.name] = "80";
|
|
356
|
+
if (arg.name === "enable_waf")
|
|
357
|
+
processedArgs[arg.name] = "false";
|
|
358
|
+
if (arg.name === "mode")
|
|
359
|
+
processedArgs[arg.name] = "blocking";
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
const processedTemplate = processPromptTemplate(workflow.template, processedArgs);
|
|
363
|
+
return {
|
|
364
|
+
messages: [
|
|
365
|
+
{
|
|
366
|
+
role: "user",
|
|
367
|
+
content: {
|
|
368
|
+
type: "text",
|
|
369
|
+
text: processedTemplate,
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
],
|
|
373
|
+
};
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
logger.info("Prompt registration completed", {
|
|
377
|
+
workflows: WORKFLOW_PROMPTS.length,
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Start the MCP server with STDIO transport
|
|
382
|
+
*/
|
|
383
|
+
async start() {
|
|
384
|
+
this.transport = new StdioServerTransport();
|
|
385
|
+
logger.info("Starting F5XC API MCP Server", {
|
|
386
|
+
version: VERSION,
|
|
387
|
+
authMode: this.credentialManager.getAuthMode(),
|
|
388
|
+
});
|
|
389
|
+
await this.server.connect(this.transport);
|
|
390
|
+
logger.info("F5XC API MCP Server started successfully");
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Stop the MCP server
|
|
394
|
+
*/
|
|
395
|
+
async stop() {
|
|
396
|
+
if (this.transport) {
|
|
397
|
+
await this.server.close();
|
|
398
|
+
this.transport = null;
|
|
399
|
+
logger.info("F5XC API MCP Server stopped");
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Get the underlying MCP server instance
|
|
404
|
+
*/
|
|
405
|
+
getMcpServer() {
|
|
406
|
+
return this.server;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Get the credential manager
|
|
410
|
+
*/
|
|
411
|
+
getCredentialManager() {
|
|
412
|
+
return this.credentialManager;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Create and configure the F5XC API MCP Server
|
|
417
|
+
*/
|
|
418
|
+
export function createServer() {
|
|
419
|
+
const credentialManager = new CredentialManager();
|
|
420
|
+
return new F5XCApiServer({
|
|
421
|
+
name: "f5xc-api-mcp",
|
|
422
|
+
version: VERSION,
|
|
423
|
+
credentialManager,
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAC3E,OAAO,EAAc,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAmB,MAAM,sBAAsB,CAAC;AAC9F,OAAO,EACL,eAAe,EACf,WAAW,EACX,YAAY,EACZ,WAAW,EACX,gBAAgB,EAChB,mBAAmB,EACnB,2BAA2B,EAC3B,uBAAuB,EACvB,uBAAuB,EACvB,qBAAqB,GAEtB,MAAM,4BAA4B,CAAC;AAcpC;;;;;;;GAOG;AACH,MAAM,OAAO,aAAa;IAChB,MAAM,CAAY;IAClB,iBAAiB,CAAoB;IACrC,UAAU,GAAsB,IAAI,CAAC;IACrC,eAAe,CAAkB;IACjC,SAAS,GAAgC,IAAI,CAAC;IAEtD,YAAY,MAAoB;QAC9B,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAC,iBAAiB,CAAC;QAElD,sCAAsC;QACtC,IAAI,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC,IAAI,EAAE,CAAC;YAC3D,IAAI,CAAC,UAAU,GAAG,gBAAgB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC7D,CAAC;QAED,0BAA0B;QAC1B,IAAI,CAAC,eAAe,GAAG,qBAAqB,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAEtF,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,CAAC;YAC1B,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,OAAO,EAAE,MAAM,CAAC,OAAO;SACxB,CAAC,CAAC;QAEH,IAAI,CAAC,oBAAoB,EAAE,CAAC;IAC9B,CAAC;IAED;;OAEG;IACK,oBAAoB;QAC1B,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACzB,IAAI,CAAC,eAAe,EAAE,CAAC;IACzB,CAAC;IAED;;;;;;;OAOG;IACK,aAAa;QACnB,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,CAAC;QAEtD,kEAAkE;QAClE,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,eAAe,CAAC,UAAU,CAAC,IAAI,EAC/B,eAAe,CAAC,UAAU,CAAC,WAAW,EACtC,EAAE,EACF,KAAK,IAAI,EAAE;YACT,MAAM,eAAe,GAAG,QAAQ,KAAK,QAAQ,CAAC,IAAI,CAAC;YACnD,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC;YACrD,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,mBAAmB,EAAE,CAAC;YAEtC,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;4BACE,MAAM,EAAE,cAAc;4BACtB,OAAO,EAAE,OAAO;4BAChB,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,eAAe;4BACrD,aAAa,EAAE,eAAe;4BAC9B,UAAU,EAAE,QAAQ;4BACpB,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;4BAC7C,YAAY,EAAE;gCACZ,aAAa,EAAE,IAAI;gCACnB,mBAAmB,EAAE,IAAI;gCACzB,kBAAkB,EAAE,IAAI;gCACxB,aAAa,EAAE,eAAe;6BAC/B;4BACD,SAAS,EAAE;gCACT,UAAU,EAAE,aAAa,CAAC,UAAU;gCACpC,OAAO,EAAE,aAAa,CAAC,OAAO;gCAC9B,gBAAgB,EAAE,OAAO;6BAC1B;4BACD,aAAa,EAAE,qBAAqB,EAAE;4BACtC,cAAc,EAAE;gCACd,uBAAuB;gCACvB,wBAAwB;gCACxB,uBAAuB;gCACvB,2BAA2B;gCAC3B,2BAA2B;6BAC5B;4BACD,OAAO,EAAE,eAAe;gCACtB,CAAC,CAAC,+FAA+F;gCACjG,CAAC,CAAC,kFAAkF;yBACvF,EACD,IAAI,EACJ,CAAC,CACF;qBACF;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,8DAA8D;QAC9D,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,eAAe,CAAC,MAAM,CAAC,IAAI,EAC3B,eAAe,CAAC,MAAM,CAAC,WAAW,EAClC;YACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;YAC3D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;YACtE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;YACrE,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;SAC5E,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;YACb,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE;gBACtC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,EAAE,CAAC;gBACrC,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,UAAU,EAAE,IAAI,CAAC,UAAU;aAC5B,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;4BACE,KAAK,EAAE,IAAI,CAAC,KAAK;4BACjB,WAAW,EAAE,OAAO,CAAC,MAAM;4BAC3B,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gCAC3B,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;gCACjB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;gCACrB,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ;gCACzB,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS;gCAC3B,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,OAAO;gCACvB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG;6BACvC,CAAC,CAAC;4BACH,IAAI,EAAE,oEAAoE;yBAC3E,EACD,IAAI,EACJ,CAAC,CACF;qBACF;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,sDAAsD;QACtD,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,eAAe,CAAC,QAAQ,CAAC,IAAI,EAC7B,eAAe,CAAC,QAAQ,CAAC,WAAW,EACpC;YACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6BAA6B,CAAC;SAC7D,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;YACb,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAEhD,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;gCACE,KAAK,EAAE,SAAS,IAAI,CAAC,QAAQ,aAAa;gCAC1C,IAAI,EAAE,oDAAoD;6BAC3D,EACD,IAAI,EACJ,CAAC,CACF;yBACF;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;4BACE,IAAI,EAAE,WAAW;4BACjB,IAAI,EAAE,iDAAiD;yBACxD,EACD,IAAI,EACJ,CAAC,CACF;qBACF;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,yDAAyD;QACzD,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,eAAe,CAAC,OAAO,CAAC,IAAI,EAC5B,eAAe,CAAC,OAAO,CAAC,WAAW,EACnC;YACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;YACrD,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;YACnF,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YACrF,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;SAC5E,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;YACb,MAAM,MAAM,GAAG,MAAM,WAAW,CAC9B;gBACE,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB,EACD,IAAI,CAAC,iBAAiB,CACvB,CAAC;YAEF,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;qBACtC;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,kDAAkD;QAClD,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,eAAe,CAAC,eAAe,CAAC,IAAI,EACpC,eAAe,CAAC,eAAe,CAAC,WAAW,EAC3C;YACE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;YAC3D,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;YACtE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;SACtE,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;YACb,MAAM,OAAO,GAAG,2BAA2B,CAAC,IAAI,CAAC,KAAK,EAAE;gBACtD,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,EAAE,CAAC;gBACrC,OAAO,EAAE,IAAI,CAAC,OAAO;aACtB,CAAC,CAAC;YAEH,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;4BACE,KAAK,EAAE,IAAI,CAAC,KAAK;4BACjB,WAAW,EAAE,OAAO,CAAC,MAAM;4BAC3B,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gCAC3B,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI;gCACrB,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC,MAAM;gCACzB,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ;gCAC7B,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU;gCACjC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO;gCAC3B,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU;gCACjC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG;6BACvC,CAAC,CAAC;4BACH,IAAI,EAAE,2EAA2E;yBAClF,EACD,IAAI,EACJ,CAAC,CACF;qBACF;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,yEAAyE;QACzE,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,eAAe,CAAC,eAAe,CAAC,IAAI,EACpC,eAAe,CAAC,eAAe,CAAC,WAAW,EAC3C;YACE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4BAA4B,CAAC;YAC/D,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC;YAC3F,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;YACnF,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kBAAkB,CAAC;YACrF,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;SAC5E,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;YACb,6BAA6B;YAC7B,MAAM,QAAQ,GAAG,uBAAuB,CACtC,IAAI,CAAC,YAAY,EACjB,IAAI,CAAC,SAA0B,CAChC,CAAC;YAEF,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,QAAQ,GAAG,uBAAuB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;gBAC5D,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,OAAO;wBACL,OAAO,EAAE;4BACP;gCACE,IAAI,EAAE,MAAM;gCACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;oCACE,KAAK,EAAE,aAAa,IAAI,CAAC,YAAY,aAAa;oCAClD,IAAI,EAAE,4DAA4D;iCACnE,EACD,IAAI,EACJ,CAAC,CACF;6BACF;yBACF;qBACF,CAAC;gBACJ,CAAC;gBACD,OAAO;oBACL,OAAO,EAAE;wBACP;4BACE,IAAI,EAAE,MAAM;4BACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;gCACE,KAAK,EAAE,cAAc,IAAI,CAAC,SAAS,wBAAwB,IAAI,CAAC,YAAY,GAAG;gCAC/E,mBAAmB,EAAE,QAAQ,CAAC,UAAU;6BACzC,EACD,IAAI,EACJ,CAAC,CACF;yBACF;qBACF;iBACF,CAAC;YACJ,CAAC;YAED,4BAA4B;YAC5B,MAAM,MAAM,GAAG,MAAM,WAAW,CAC9B;gBACE,QAAQ;gBACR,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB,EACD,IAAI,CAAC,iBAAiB,CACvB,CAAC;YAEF,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAClB;4BACE,YAAY,EAAE,QAAQ;4BACtB,GAAG,MAAM;yBACV,EACD,IAAI,EACJ,CAAC,CACF;qBACF;iBACF;aACF,CAAC;QACJ,CAAC,CACF,CAAC;QAEF,MAAM,aAAa,GAAG,gBAAgB,EAAE,CAAC;QACzC,MAAM,kBAAkB,GAAG,qBAAqB,EAAE,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,sDAAsD,EAAE;YAClE,QAAQ;YACR,aAAa,EAAE,QAAQ,KAAK,QAAQ,CAAC,IAAI;YACzC,eAAe,EAAE,CAAC;YAClB,YAAY,EAAE,aAAa,CAAC,UAAU;YACtC,qBAAqB,EAAE,kBAAkB,CAAC,iBAAiB;YAC3D,sBAAsB,EAAE,kBAAkB,CAAC,gBAAgB;YAC3D,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;YAC3C,YAAY,EAAE,mCAAmC;SAClD,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,iBAAiB;QACvB,MAAM,MAAM,GAAG,IAAI,CAAC,iBAAiB,CAAC,SAAS,EAAE,IAAI,UAAU,CAAC;QAEhE,qDAAqD;QACrD,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,EAAE,CAAC;YAC/C,MAAM,WAAW,GAAG,EAAE,CAAC,eAAe;gBACpC,CAAC,CAAC,UAAU,MAAM,gBAAgB,EAAE,CAAC,IAAI,SAAS;gBAClD,CAAC,CAAC,UAAU,MAAM,WAAW,EAAE,CAAC,IAAI,SAAS,CAAC;YAEhD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC,WAAW,EAAE,KAAK,EAAE,GAAQ,EAAE,EAAE;gBACnE,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;oBACjE,OAAO;wBACL,QAAQ,EAAE;4BACR;gCACE,GAAG,EAAE,MAAM,CAAC,GAAG;gCACf,QAAQ,EAAE,MAAM,CAAC,QAAQ;gCACzB,IAAI,EAAE,MAAM,CAAC,OAAO;6BACrB;yBACF;qBACF,CAAC;gBACJ,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,CAAC,KAAK,CAAC,4BAA4B,GAAG,CAAC,IAAI,EAAE,EAAE;wBACnD,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;qBAC9D,CAAC,CAAC;oBACH,MAAM,KAAK,CAAC;gBACd,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE;YAC7C,aAAa,EAAE,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,MAAM;SAClD,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,eAAe;QACrB,gCAAgC;QAChC,KAAK,MAAM,QAAQ,IAAI,gBAAgB,EAAE,CAAC;YACxC,iCAAiC;YACjC,MAAM,SAAS,GAAiC,EAAE,CAAC;YACnD,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;gBACrC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,QAAQ;oBAChC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC;oBACtC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;YACtD,CAAC;YAED,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,WAAW,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;gBAChF,2CAA2C;gBAC3C,MAAM,aAAa,GAA2B,EAAE,CAAC;gBACjD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAA+B,CAAC,EAAE,CAAC;oBAC3E,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;wBAC9B,aAAa,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;oBAC7B,CAAC;gBACH,CAAC;gBAED,yCAAyC;gBACzC,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;oBACrC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;wBAC9C,wBAAwB;wBACxB,IAAI,GAAG,CAAC,IAAI,KAAK,cAAc;4BAAE,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;wBAChE,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY;4BAAE,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC;wBACjE,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;4BAAE,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC;oBAChE,CAAC;gBACH,CAAC;gBAED,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;gBAElF,OAAO;oBACL,QAAQ,EAAE;wBACR;4BACE,IAAI,EAAE,MAAe;4BACrB,OAAO,EAAE;gCACP,IAAI,EAAE,MAAe;gCACrB,IAAI,EAAE,iBAAiB;6BACxB;yBACF;qBACF;iBACF,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,+BAA+B,EAAE;YAC3C,SAAS,EAAE,gBAAgB,CAAC,MAAM;SACnC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAE5C,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE;YAC1C,OAAO,EAAE,OAAO;YAChB,QAAQ,EAAE,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE;SAC/C,CAAC,CAAC;QAEH,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAE1C,MAAM,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC;IAC1D,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI;QACR,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YACnB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAC1B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED;;OAEG;IACH,oBAAoB;QAClB,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,iBAAiB,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAElD,OAAO,IAAI,aAAa,CAAC;QACvB,IAAI,EAAE,cAAc;QACpB,OAAO,EAAE,OAAO;QAChB,iBAAiB;KAClB,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource Consolidation Module
|
|
3
|
+
*
|
|
4
|
+
* Provides a resource-centric view of tools by grouping CRUD operations.
|
|
5
|
+
* This reduces cognitive load for LLMs by presenting one tool per resource
|
|
6
|
+
* instead of 5 separate CRUD tools.
|
|
7
|
+
*
|
|
8
|
+
* Example:
|
|
9
|
+
* Before: f5xc-api-waap-http-loadbalancer-{create,get,list,update,delete}
|
|
10
|
+
* After: f5xc-api-waap-http-loadbalancer (with operation parameter)
|
|
11
|
+
*/
|
|
12
|
+
import type { ToolIndexEntry } from "./types.js";
|
|
13
|
+
/**
|
|
14
|
+
* CRUD operation types supported by consolidated resources
|
|
15
|
+
*/
|
|
16
|
+
export type CrudOperation = "create" | "get" | "list" | "update" | "delete";
|
|
17
|
+
/**
|
|
18
|
+
* Consolidated resource entry representing a group of CRUD tools
|
|
19
|
+
*/
|
|
20
|
+
export interface ConsolidatedResource {
|
|
21
|
+
/** Resource identifier (e.g., "f5xc-api-waap-http-loadbalancer") */
|
|
22
|
+
name: string;
|
|
23
|
+
/** Domain category */
|
|
24
|
+
domain: string;
|
|
25
|
+
/** Resource type */
|
|
26
|
+
resource: string;
|
|
27
|
+
/** Available CRUD operations */
|
|
28
|
+
operations: CrudOperation[];
|
|
29
|
+
/** Combined summary */
|
|
30
|
+
summary: string;
|
|
31
|
+
/** Original tool names mapped by operation */
|
|
32
|
+
toolMap: Record<CrudOperation, string>;
|
|
33
|
+
/** Whether this is a full CRUD resource (has all 5 operations) */
|
|
34
|
+
isFullCrud: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Consolidated index with resource-centric view
|
|
38
|
+
*/
|
|
39
|
+
export interface ConsolidatedIndex {
|
|
40
|
+
/** Total consolidated resources */
|
|
41
|
+
totalResources: number;
|
|
42
|
+
/** Full CRUD resources (all 5 operations) */
|
|
43
|
+
fullCrudResources: number;
|
|
44
|
+
/** Partial resources (fewer operations) */
|
|
45
|
+
partialResources: number;
|
|
46
|
+
/** Standalone tools (non-CRUD) */
|
|
47
|
+
standaloneTools: number;
|
|
48
|
+
/** All consolidated resources */
|
|
49
|
+
resources: ConsolidatedResource[];
|
|
50
|
+
/** Standalone tools that don't fit CRUD pattern */
|
|
51
|
+
standalone: ToolIndexEntry[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Build consolidated index from tool index
|
|
55
|
+
*/
|
|
56
|
+
export declare function getConsolidatedIndex(): ConsolidatedIndex;
|
|
57
|
+
/**
|
|
58
|
+
* Clear consolidated index cache
|
|
59
|
+
*/
|
|
60
|
+
export declare function clearConsolidatedCache(): void;
|
|
61
|
+
/**
|
|
62
|
+
* Get consolidated resource by name
|
|
63
|
+
*/
|
|
64
|
+
export declare function getConsolidatedResource(name: string): ConsolidatedResource | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Get consolidated resources by domain
|
|
67
|
+
*/
|
|
68
|
+
export declare function getConsolidatedByDomain(domain: string): ConsolidatedResource[];
|
|
69
|
+
/**
|
|
70
|
+
* Search consolidated resources
|
|
71
|
+
*/
|
|
72
|
+
export interface ConsolidatedSearchResult {
|
|
73
|
+
resource: ConsolidatedResource;
|
|
74
|
+
score: number;
|
|
75
|
+
matchedTerms: string[];
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Search consolidated resources with natural language query
|
|
79
|
+
*/
|
|
80
|
+
export declare function searchConsolidatedResources(query: string, options?: {
|
|
81
|
+
limit?: number;
|
|
82
|
+
domains?: string[];
|
|
83
|
+
}): ConsolidatedSearchResult[];
|
|
84
|
+
/**
|
|
85
|
+
* Resolve a consolidated resource + operation to the underlying tool name
|
|
86
|
+
*/
|
|
87
|
+
export declare function resolveConsolidatedTool(resourceName: string, operation: CrudOperation): string | null;
|
|
88
|
+
/**
|
|
89
|
+
* Get consolidation statistics
|
|
90
|
+
*/
|
|
91
|
+
export declare function getConsolidationStats(): {
|
|
92
|
+
originalToolCount: number;
|
|
93
|
+
consolidatedCount: number;
|
|
94
|
+
reduction: number;
|
|
95
|
+
reductionPercent: string;
|
|
96
|
+
};
|
|
97
|
+
//# sourceMappingURL=consolidate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consolidate.d.ts","sourceRoot":"","sources":["../../../src/tools/discovery/consolidate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAGjD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE5E;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,oBAAoB;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,gCAAgC;IAChC,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B,uBAAuB;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IACvC,kEAAkE;IAClE,UAAU,EAAE,OAAO,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,cAAc,EAAE,MAAM,CAAC;IACvB,6CAA6C;IAC7C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,2CAA2C;IAC3C,gBAAgB,EAAE,MAAM,CAAC;IACzB,kCAAkC;IAClC,eAAe,EAAE,MAAM,CAAC;IACxB,iCAAiC;IACjC,SAAS,EAAE,oBAAoB,EAAE,CAAC;IAClC,mDAAmD;IACnD,UAAU,EAAE,cAAc,EAAE,CAAC;CAC9B;AAwBD;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,iBAAiB,CAsExD;AAED;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAE7C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAGtF;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,oBAAoB,EAAE,CAG9E;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,oBAAoB,CAAC;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CACzC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,GACnD,wBAAwB,EAAE,CAgE5B;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,aAAa,GACvB,MAAM,GAAG,IAAI,CAQf;AAED;;GAEG;AACH,wBAAgB,qBAAqB,IAAI;IACvC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;CAC1B,CAeA"}
|