@robinmordasiewicz/f5xc-api-mcp 1.0.82-2512312028
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 +415 -0
- package/dist/auth/credential-manager.d.ts +151 -0
- package/dist/auth/credential-manager.d.ts.map +1 -0
- package/dist/auth/credential-manager.js +330 -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/config/config-manager.d.ts +72 -0
- package/dist/config/config-manager.d.ts.map +1 -0
- package/dist/config/config-manager.js +247 -0
- package/dist/config/config-manager.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +7 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/schema.d.ts +74 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +75 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/types.d.ts +77 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +31 -0
- package/dist/config/types.js.map +1 -0
- package/dist/generator/dependency-extractor.d.ts +103 -0
- package/dist/generator/dependency-extractor.d.ts.map +1 -0
- package/dist/generator/dependency-extractor.js +473 -0
- package/dist/generator/dependency-extractor.js.map +1 -0
- package/dist/generator/dependency-graph.d.ts +67 -0
- package/dist/generator/dependency-graph.d.ts.map +1 -0
- package/dist/generator/dependency-graph.js +330 -0
- package/dist/generator/dependency-graph.js.map +1 -0
- package/dist/generator/dependency-types.d.ts +206 -0
- package/dist/generator/dependency-types.d.ts.map +1 -0
- package/dist/generator/dependency-types.js +37 -0
- package/dist/generator/dependency-types.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 +701 -0
- package/dist/generator/openapi-parser.d.ts.map +1 -0
- package/dist/generator/openapi-parser.js +704 -0
- package/dist/generator/openapi-parser.js.map +1 -0
- package/dist/generator/tool-generator.d.ts +118 -0
- package/dist/generator/tool-generator.d.ts.map +1 -0
- package/dist/generator/tool-generator.js +529 -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 +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +101 -0
- package/dist/index.js.map +1 -0
- package/dist/prompts/error-resolution.d.ts +70 -0
- package/dist/prompts/error-resolution.d.ts.map +1 -0
- package/dist/prompts/error-resolution.js +350 -0
- package/dist/prompts/error-resolution.js.map +1 -0
- package/dist/prompts/index.d.ts +8 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +7 -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 +441 -0
- package/dist/prompts/workflows.js.map +1 -0
- package/dist/resources/handlers.d.ts +70 -0
- package/dist/resources/handlers.d.ts.map +1 -0
- package/dist/resources/handlers.js +270 -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 +721 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/discovery/best-practices.d.ts +140 -0
- package/dist/tools/discovery/best-practices.d.ts.map +1 -0
- package/dist/tools/discovery/best-practices.js +499 -0
- package/dist/tools/discovery/best-practices.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/cost-estimator.d.ts +114 -0
- package/dist/tools/discovery/cost-estimator.d.ts.map +1 -0
- package/dist/tools/discovery/cost-estimator.js +273 -0
- package/dist/tools/discovery/cost-estimator.js.map +1 -0
- package/dist/tools/discovery/dependencies.d.ts +113 -0
- package/dist/tools/discovery/dependencies.d.ts.map +1 -0
- package/dist/tools/discovery/dependencies.js +258 -0
- package/dist/tools/discovery/dependencies.js.map +1 -0
- package/dist/tools/discovery/describe.d.ts +133 -0
- package/dist/tools/discovery/describe.d.ts.map +1 -0
- package/dist/tools/discovery/describe.js +208 -0
- package/dist/tools/discovery/describe.js.map +1 -0
- package/dist/tools/discovery/execute.d.ts +96 -0
- package/dist/tools/discovery/execute.d.ts.map +1 -0
- package/dist/tools/discovery/execute.js +220 -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 +72 -0
- package/dist/tools/discovery/index-loader.js.map +1 -0
- package/dist/tools/discovery/index.d.ts +363 -0
- package/dist/tools/discovery/index.d.ts.map +1 -0
- package/dist/tools/discovery/index.js +361 -0
- package/dist/tools/discovery/index.js.map +1 -0
- package/dist/tools/discovery/resolver.d.ts +119 -0
- package/dist/tools/discovery/resolver.d.ts.map +1 -0
- package/dist/tools/discovery/resolver.js +369 -0
- package/dist/tools/discovery/resolver.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 +176 -0
- package/dist/tools/discovery/search.js.map +1 -0
- package/dist/tools/discovery/types.d.ts +91 -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/discovery/validate.d.ts +63 -0
- package/dist/tools/discovery/validate.d.ts.map +1 -0
- package/dist/tools/discovery/validate.js +239 -0
- package/dist/tools/discovery/validate.js.map +1 -0
- package/dist/tools/generated/admin_console_and_ui/index.d.ts +8 -0
- package/dist/tools/generated/admin_console_and_ui/index.d.ts.map +1 -0
- package/dist/tools/generated/admin_console_and_ui/index.js +265 -0
- package/dist/tools/generated/admin_console_and_ui/index.js.map +1 -0
- package/dist/tools/generated/api/index.d.ts +8 -0
- package/dist/tools/generated/api/index.d.ts.map +1 -0
- package/dist/tools/generated/api/index.js +7016 -0
- package/dist/tools/generated/api/index.js.map +1 -0
- package/dist/tools/generated/authentication/index.d.ts +8 -0
- package/dist/tools/generated/authentication/index.d.ts.map +1 -0
- package/dist/tools/generated/authentication/index.js +907 -0
- package/dist/tools/generated/authentication/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 +3152 -0
- package/dist/tools/generated/bigip/index.js.map +1 -0
- package/dist/tools/generated/billing_and_usage/index.d.ts +8 -0
- package/dist/tools/generated/billing_and_usage/index.d.ts.map +1 -0
- package/dist/tools/generated/billing_and_usage/index.js +2452 -0
- package/dist/tools/generated/billing_and_usage/index.js.map +1 -0
- package/dist/tools/generated/blindfold/index.d.ts +8 -0
- package/dist/tools/generated/blindfold/index.d.ts.map +1 -0
- package/dist/tools/generated/blindfold/index.js +3790 -0
- package/dist/tools/generated/blindfold/index.js.map +1 -0
- package/dist/tools/generated/bot_and_threat_defense/index.d.ts +8 -0
- package/dist/tools/generated/bot_and_threat_defense/index.d.ts.map +1 -0
- package/dist/tools/generated/bot_and_threat_defense/index.js +2746 -0
- package/dist/tools/generated/bot_and_threat_defense/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 +2686 -0
- package/dist/tools/generated/cdn/index.js.map +1 -0
- package/dist/tools/generated/ce_management/index.d.ts +8 -0
- package/dist/tools/generated/ce_management/index.d.ts.map +1 -0
- package/dist/tools/generated/ce_management/index.js +3812 -0
- package/dist/tools/generated/ce_management/index.js.map +1 -0
- package/dist/tools/generated/certificates/index.d.ts +8 -0
- package/dist/tools/generated/certificates/index.d.ts.map +1 -0
- package/dist/tools/generated/certificates/index.js +2547 -0
- package/dist/tools/generated/certificates/index.js.map +1 -0
- package/dist/tools/generated/cloud_infrastructure/index.d.ts +8 -0
- package/dist/tools/generated/cloud_infrastructure/index.d.ts.map +1 -0
- package/dist/tools/generated/cloud_infrastructure/index.js +3959 -0
- package/dist/tools/generated/cloud_infrastructure/index.js.map +1 -0
- package/dist/tools/generated/container_services/index.d.ts +8 -0
- package/dist/tools/generated/container_services/index.d.ts.map +1 -0
- package/dist/tools/generated/container_services/index.js +2018 -0
- package/dist/tools/generated/container_services/index.js.map +1 -0
- package/dist/tools/generated/data_and_privacy_security/index.d.ts +8 -0
- package/dist/tools/generated/data_and_privacy_security/index.d.ts.map +1 -0
- package/dist/tools/generated/data_and_privacy_security/index.js +1662 -0
- package/dist/tools/generated/data_and_privacy_security/index.js.map +1 -0
- package/dist/tools/generated/data_intelligence/index.d.ts +8 -0
- package/dist/tools/generated/data_intelligence/index.d.ts.map +1 -0
- package/dist/tools/generated/data_intelligence/index.js +1600 -0
- package/dist/tools/generated/data_intelligence/index.js.map +1 -0
- package/dist/tools/generated/ddos/index.d.ts +8 -0
- package/dist/tools/generated/ddos/index.d.ts.map +1 -0
- package/dist/tools/generated/ddos/index.js +8091 -0
- package/dist/tools/generated/ddos/index.js.map +1 -0
- package/dist/tools/generated/dependency-graph.json +26358 -0
- package/dist/tools/generated/dns/index.d.ts +8 -0
- package/dist/tools/generated/dns/index.d.ts.map +1 -0
- package/dist/tools/generated/dns/index.js +6096 -0
- package/dist/tools/generated/dns/index.js.map +1 -0
- package/dist/tools/generated/generative_ai/index.d.ts +8 -0
- package/dist/tools/generated/generative_ai/index.d.ts.map +1 -0
- package/dist/tools/generated/generative_ai/index.js +1019 -0
- package/dist/tools/generated/generative_ai/index.js.map +1 -0
- package/dist/tools/generated/managed_kubernetes/index.d.ts +8 -0
- package/dist/tools/generated/managed_kubernetes/index.d.ts.map +1 -0
- package/dist/tools/generated/managed_kubernetes/index.js +3368 -0
- package/dist/tools/generated/managed_kubernetes/index.js.map +1 -0
- package/dist/tools/generated/marketplace/index.d.ts +8 -0
- package/dist/tools/generated/marketplace/index.d.ts.map +1 -0
- package/dist/tools/generated/marketplace/index.js +4329 -0
- package/dist/tools/generated/marketplace/index.js.map +1 -0
- package/dist/tools/generated/network/index.d.ts +8 -0
- package/dist/tools/generated/network/index.d.ts.map +1 -0
- package/dist/tools/generated/network/index.js +12424 -0
- package/dist/tools/generated/network/index.js.map +1 -0
- package/dist/tools/generated/network_security/index.d.ts +8 -0
- package/dist/tools/generated/network_security/index.d.ts.map +1 -0
- package/dist/tools/generated/network_security/index.js +9637 -0
- package/dist/tools/generated/network_security/index.js.map +1 -0
- package/dist/tools/generated/nginx_one/index.d.ts +8 -0
- package/dist/tools/generated/nginx_one/index.d.ts.map +1 -0
- package/dist/tools/generated/nginx_one/index.js +1692 -0
- package/dist/tools/generated/nginx_one/index.js.map +1 -0
- package/dist/tools/generated/object_storage/index.d.ts +8 -0
- package/dist/tools/generated/object_storage/index.d.ts.map +1 -0
- package/dist/tools/generated/object_storage/index.js +996 -0
- package/dist/tools/generated/object_storage/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 +5285 -0
- package/dist/tools/generated/observability/index.js.map +1 -0
- package/dist/tools/generated/rate_limiting/index.d.ts +8 -0
- package/dist/tools/generated/rate_limiting/index.d.ts.map +1 -0
- package/dist/tools/generated/rate_limiting/index.js +2108 -0
- package/dist/tools/generated/rate_limiting/index.js.map +1 -0
- package/dist/tools/generated/secops_and_incident_response/index.d.ts +8 -0
- package/dist/tools/generated/secops_and_incident_response/index.d.ts.map +1 -0
- package/dist/tools/generated/secops_and_incident_response/index.js +710 -0
- package/dist/tools/generated/secops_and_incident_response/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 +6062 -0
- package/dist/tools/generated/service_mesh/index.js.map +1 -0
- package/dist/tools/generated/shape/index.d.ts +8 -0
- package/dist/tools/generated/shape/index.d.ts.map +1 -0
- package/dist/tools/generated/shape/index.js +19381 -0
- package/dist/tools/generated/shape/index.js.map +1 -0
- package/dist/tools/generated/sites/index.d.ts +8 -0
- package/dist/tools/generated/sites/index.d.ts.map +1 -0
- package/dist/tools/generated/sites/index.js +13160 -0
- package/dist/tools/generated/sites/index.js.map +1 -0
- package/dist/tools/generated/statistics/index.d.ts +8 -0
- package/dist/tools/generated/statistics/index.d.ts.map +1 -0
- package/dist/tools/generated/statistics/index.js +8131 -0
- package/dist/tools/generated/statistics/index.js.map +1 -0
- package/dist/tools/generated/support/index.d.ts +8 -0
- package/dist/tools/generated/support/index.d.ts.map +1 -0
- package/dist/tools/generated/support/index.js +5608 -0
- package/dist/tools/generated/support/index.js.map +1 -0
- package/dist/tools/generated/telemetry_and_insights/index.d.ts +8 -0
- package/dist/tools/generated/telemetry_and_insights/index.d.ts.map +1 -0
- package/dist/tools/generated/telemetry_and_insights/index.js +2404 -0
- package/dist/tools/generated/telemetry_and_insights/index.js.map +1 -0
- package/dist/tools/generated/tenant_and_identity/index.d.ts +8 -0
- package/dist/tools/generated/tenant_and_identity/index.d.ts.map +1 -0
- package/dist/tools/generated/tenant_and_identity/index.js +18938 -0
- package/dist/tools/generated/tenant_and_identity/index.js.map +1 -0
- package/dist/tools/generated/threat_campaign/index.d.ts +8 -0
- package/dist/tools/generated/threat_campaign/index.d.ts.map +1 -0
- package/dist/tools/generated/threat_campaign/index.js +102 -0
- package/dist/tools/generated/threat_campaign/index.js.map +1 -0
- package/dist/tools/generated/users/index.d.ts +8 -0
- package/dist/tools/generated/users/index.d.ts.map +1 -0
- package/dist/tools/generated/users/index.js +1515 -0
- package/dist/tools/generated/users/index.js.map +1 -0
- package/dist/tools/generated/virtual/index.d.ts +8 -0
- package/dist/tools/generated/virtual/index.d.ts.map +1 -0
- package/dist/tools/generated/virtual/index.js +11263 -0
- package/dist/tools/generated/virtual/index.js.map +1 -0
- package/dist/tools/generated/vpm_and_node_management/index.d.ts +8 -0
- package/dist/tools/generated/vpm_and_node_management/index.d.ts.map +1 -0
- package/dist/tools/generated/vpm_and_node_management/index.js +88 -0
- package/dist/tools/generated/vpm_and_node_management/index.js.map +1 -0
- package/dist/tools/generated/waf/index.d.ts +8 -0
- package/dist/tools/generated/waf/index.d.ts.map +1 -0
- package/dist/tools/generated/waf/index.js +4586 -0
- package/dist/tools/generated/waf/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 +115 -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 +110 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,721 @@
|
|
|
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, ERROR_PROMPTS, processErrorTemplate, } 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, generateDependencyReport, getDependencyStats, validateToolParams, formatValidationResult, resolveDependencies, formatCreationPlan, estimateToolCost, estimateMultipleToolsCost, estimateWorkflowCost, formatCostEstimate, formatWorkflowCostEstimate, queryBestPractices, getAllDomainsSummary, formatBestPractices, } 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, and 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
|
+
terraform_examples: true,
|
|
84
|
+
api_execution: isAuthenticated,
|
|
85
|
+
},
|
|
86
|
+
toolIndex: {
|
|
87
|
+
totalTools: indexMetadata.totalTools,
|
|
88
|
+
domains: indexMetadata.domains,
|
|
89
|
+
availableDomains: domains,
|
|
90
|
+
},
|
|
91
|
+
consolidation: getConsolidationStats(),
|
|
92
|
+
discoveryTools: [
|
|
93
|
+
"f5xc-api-search-tools",
|
|
94
|
+
"f5xc-api-describe-tool",
|
|
95
|
+
"f5xc-api-execute-tool",
|
|
96
|
+
"f5xc-api-search-resources",
|
|
97
|
+
"f5xc-api-execute-resource",
|
|
98
|
+
"f5xc-api-dependencies",
|
|
99
|
+
"f5xc-api-dependency-stats",
|
|
100
|
+
"f5xc-api-validate-params",
|
|
101
|
+
"f5xc-api-resolve-dependencies",
|
|
102
|
+
"f5xc-api-estimate-cost",
|
|
103
|
+
"f5xc-api-best-practices",
|
|
104
|
+
],
|
|
105
|
+
message: isAuthenticated
|
|
106
|
+
? "Authenticated - API execution enabled. Use f5xc-api-search-tools to find available API tools."
|
|
107
|
+
: "Documentation mode. Set F5XC_API_URL and F5XC_API_TOKEN to enable API execution.",
|
|
108
|
+
}, null, 2),
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
};
|
|
112
|
+
});
|
|
113
|
+
// Search tools - find tools matching natural language queries
|
|
114
|
+
this.server.tool(DISCOVERY_TOOLS.search.name, DISCOVERY_TOOLS.search.description, {
|
|
115
|
+
query: z.string().describe("Natural language search query"),
|
|
116
|
+
limit: z.number().optional().describe("Maximum results (default: 10)"),
|
|
117
|
+
domains: z.array(z.string()).optional().describe("Filter by domains"),
|
|
118
|
+
operations: z.array(z.string()).optional().describe("Filter by operations"),
|
|
119
|
+
excludeDangerous: z.boolean().optional().describe("Exclude high-danger operations"),
|
|
120
|
+
excludeDeprecated: z.boolean().optional().describe("Exclude deprecated operations"),
|
|
121
|
+
includeDependencies: z
|
|
122
|
+
.boolean()
|
|
123
|
+
.optional()
|
|
124
|
+
.describe("Include prerequisite hints for create operations"),
|
|
125
|
+
}, async (args) => {
|
|
126
|
+
const results = searchTools(args.query, {
|
|
127
|
+
limit: Math.min(args.limit ?? 10, 50),
|
|
128
|
+
domains: args.domains,
|
|
129
|
+
operations: args.operations,
|
|
130
|
+
excludeDangerous: args.excludeDangerous,
|
|
131
|
+
excludeDeprecated: args.excludeDeprecated,
|
|
132
|
+
includeDependencies: args.includeDependencies,
|
|
133
|
+
});
|
|
134
|
+
return {
|
|
135
|
+
content: [
|
|
136
|
+
{
|
|
137
|
+
type: "text",
|
|
138
|
+
text: JSON.stringify({
|
|
139
|
+
query: args.query,
|
|
140
|
+
resultCount: results.length,
|
|
141
|
+
results: results.map((r) => ({
|
|
142
|
+
name: r.tool.name,
|
|
143
|
+
domain: r.tool.domain,
|
|
144
|
+
resource: r.tool.resource,
|
|
145
|
+
operation: r.tool.operation,
|
|
146
|
+
summary: r.tool.summary,
|
|
147
|
+
score: Math.round(r.score * 100) / 100,
|
|
148
|
+
// Phase A enhancement fields
|
|
149
|
+
dangerLevel: r.tool.dangerLevel,
|
|
150
|
+
isDeprecated: r.tool.isDeprecated,
|
|
151
|
+
// Phase B enhancement: prerequisites for create operations
|
|
152
|
+
...(r.prerequisites && { prerequisites: r.prerequisites }),
|
|
153
|
+
})),
|
|
154
|
+
hint: "Use f5xc-api-describe-tool to get full schema for a specific tool.",
|
|
155
|
+
}, null, 2),
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
// Describe tool - get full schema for a specific tool
|
|
161
|
+
this.server.tool(DISCOVERY_TOOLS.describe.name, DISCOVERY_TOOLS.describe.description, {
|
|
162
|
+
toolName: z.string().describe("Exact tool name to describe"),
|
|
163
|
+
}, async (args) => {
|
|
164
|
+
const description = describeTool(args.toolName);
|
|
165
|
+
if (!description) {
|
|
166
|
+
return {
|
|
167
|
+
content: [
|
|
168
|
+
{
|
|
169
|
+
type: "text",
|
|
170
|
+
text: JSON.stringify({
|
|
171
|
+
error: `Tool "${args.toolName}" not found`,
|
|
172
|
+
hint: "Use f5xc-api-search-tools to find available tools.",
|
|
173
|
+
}, null, 2),
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
content: [
|
|
180
|
+
{
|
|
181
|
+
type: "text",
|
|
182
|
+
text: JSON.stringify({
|
|
183
|
+
tool: description,
|
|
184
|
+
hint: "Use f5xc-api-execute-tool to execute this tool.",
|
|
185
|
+
}, null, 2),
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
};
|
|
189
|
+
});
|
|
190
|
+
// Execute tool - execute a specific tool with parameters
|
|
191
|
+
this.server.tool(DISCOVERY_TOOLS.execute.name, DISCOVERY_TOOLS.execute.description, {
|
|
192
|
+
toolName: z.string().describe("Tool name to execute"),
|
|
193
|
+
pathParams: z.record(z.string(), z.string()).optional().describe("Path parameters"),
|
|
194
|
+
queryParams: z.record(z.string(), z.string()).optional().describe("Query parameters"),
|
|
195
|
+
body: z.record(z.string(), z.unknown()).optional().describe("Request body"),
|
|
196
|
+
}, async (args) => {
|
|
197
|
+
const result = await executeTool({
|
|
198
|
+
toolName: args.toolName,
|
|
199
|
+
pathParams: args.pathParams,
|
|
200
|
+
queryParams: args.queryParams,
|
|
201
|
+
body: args.body,
|
|
202
|
+
}, this.credentialManager);
|
|
203
|
+
return {
|
|
204
|
+
content: [
|
|
205
|
+
{
|
|
206
|
+
type: "text",
|
|
207
|
+
text: JSON.stringify(result, null, 2),
|
|
208
|
+
},
|
|
209
|
+
],
|
|
210
|
+
};
|
|
211
|
+
});
|
|
212
|
+
// Search resources - consolidated resource search
|
|
213
|
+
this.server.tool(DISCOVERY_TOOLS.searchResources.name, DISCOVERY_TOOLS.searchResources.description, {
|
|
214
|
+
query: z.string().describe("Natural language search query"),
|
|
215
|
+
limit: z.number().optional().describe("Maximum results (default: 10)"),
|
|
216
|
+
domains: z.array(z.string()).optional().describe("Filter by domains"),
|
|
217
|
+
}, async (args) => {
|
|
218
|
+
const results = searchConsolidatedResources(args.query, {
|
|
219
|
+
limit: Math.min(args.limit ?? 10, 50),
|
|
220
|
+
domains: args.domains,
|
|
221
|
+
});
|
|
222
|
+
return {
|
|
223
|
+
content: [
|
|
224
|
+
{
|
|
225
|
+
type: "text",
|
|
226
|
+
text: JSON.stringify({
|
|
227
|
+
query: args.query,
|
|
228
|
+
resultCount: results.length,
|
|
229
|
+
results: results.map((r) => ({
|
|
230
|
+
name: r.resource.name,
|
|
231
|
+
domain: r.resource.domain,
|
|
232
|
+
resource: r.resource.resource,
|
|
233
|
+
operations: r.resource.operations,
|
|
234
|
+
summary: r.resource.summary,
|
|
235
|
+
isFullCrud: r.resource.isFullCrud,
|
|
236
|
+
score: Math.round(r.score * 100) / 100,
|
|
237
|
+
})),
|
|
238
|
+
hint: "Use f5xc-api-execute-resource with resourceName and operation to execute.",
|
|
239
|
+
}, null, 2),
|
|
240
|
+
},
|
|
241
|
+
],
|
|
242
|
+
};
|
|
243
|
+
});
|
|
244
|
+
// Execute resource - execute a CRUD operation on a consolidated resource
|
|
245
|
+
this.server.tool(DISCOVERY_TOOLS.executeResource.name, DISCOVERY_TOOLS.executeResource.description, {
|
|
246
|
+
resourceName: z.string().describe("Consolidated resource name"),
|
|
247
|
+
operation: z.enum(["create", "get", "list", "update", "delete"]).describe("CRUD operation"),
|
|
248
|
+
pathParams: z.record(z.string(), z.string()).optional().describe("Path parameters"),
|
|
249
|
+
queryParams: z.record(z.string(), z.string()).optional().describe("Query parameters"),
|
|
250
|
+
body: z.record(z.string(), z.unknown()).optional().describe("Request body"),
|
|
251
|
+
}, async (args) => {
|
|
252
|
+
// Resolve to underlying tool
|
|
253
|
+
const toolName = resolveConsolidatedTool(args.resourceName, args.operation);
|
|
254
|
+
if (!toolName) {
|
|
255
|
+
const resource = getConsolidatedResource(args.resourceName);
|
|
256
|
+
if (!resource) {
|
|
257
|
+
return {
|
|
258
|
+
content: [
|
|
259
|
+
{
|
|
260
|
+
type: "text",
|
|
261
|
+
text: JSON.stringify({
|
|
262
|
+
error: `Resource "${args.resourceName}" not found`,
|
|
263
|
+
hint: "Use f5xc-api-search-resources to find available resources.",
|
|
264
|
+
}, null, 2),
|
|
265
|
+
},
|
|
266
|
+
],
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
return {
|
|
270
|
+
content: [
|
|
271
|
+
{
|
|
272
|
+
type: "text",
|
|
273
|
+
text: JSON.stringify({
|
|
274
|
+
error: `Operation "${args.operation}" not available for "${args.resourceName}"`,
|
|
275
|
+
availableOperations: resource.operations,
|
|
276
|
+
}, null, 2),
|
|
277
|
+
},
|
|
278
|
+
],
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
// Execute the resolved tool
|
|
282
|
+
const result = await executeTool({
|
|
283
|
+
toolName,
|
|
284
|
+
pathParams: args.pathParams,
|
|
285
|
+
queryParams: args.queryParams,
|
|
286
|
+
body: args.body,
|
|
287
|
+
}, this.credentialManager);
|
|
288
|
+
return {
|
|
289
|
+
content: [
|
|
290
|
+
{
|
|
291
|
+
type: "text",
|
|
292
|
+
text: JSON.stringify({
|
|
293
|
+
resolvedTool: toolName,
|
|
294
|
+
...result,
|
|
295
|
+
}, null, 2),
|
|
296
|
+
},
|
|
297
|
+
],
|
|
298
|
+
};
|
|
299
|
+
});
|
|
300
|
+
// Dependencies tool - get resource dependency information
|
|
301
|
+
this.server.tool(DISCOVERY_TOOLS.dependencies.name, DISCOVERY_TOOLS.dependencies.description, {
|
|
302
|
+
resource: z.string().describe("Resource name (e.g., 'http-loadbalancer')"),
|
|
303
|
+
domain: z.string().describe("Domain containing the resource (e.g., 'virtual')"),
|
|
304
|
+
action: z
|
|
305
|
+
.enum(["prerequisites", "dependents", "oneOf", "subscriptions", "creationOrder", "full"])
|
|
306
|
+
.optional()
|
|
307
|
+
.describe("Type of dependency information to retrieve (default: 'full')"),
|
|
308
|
+
}, async (args) => {
|
|
309
|
+
const action = (args.action ?? "full");
|
|
310
|
+
const report = generateDependencyReport(args.domain, args.resource, action);
|
|
311
|
+
return {
|
|
312
|
+
content: [
|
|
313
|
+
{
|
|
314
|
+
type: "text",
|
|
315
|
+
text: JSON.stringify(report, null, 2),
|
|
316
|
+
},
|
|
317
|
+
],
|
|
318
|
+
};
|
|
319
|
+
});
|
|
320
|
+
// Dependency stats tool - get graph statistics
|
|
321
|
+
this.server.tool(DISCOVERY_TOOLS.dependencyStats.name, DISCOVERY_TOOLS.dependencyStats.description, {}, async () => {
|
|
322
|
+
const stats = getDependencyStats();
|
|
323
|
+
return {
|
|
324
|
+
content: [
|
|
325
|
+
{
|
|
326
|
+
type: "text",
|
|
327
|
+
text: JSON.stringify(stats, null, 2),
|
|
328
|
+
},
|
|
329
|
+
],
|
|
330
|
+
};
|
|
331
|
+
});
|
|
332
|
+
// Phase B: Parameter validation tool
|
|
333
|
+
this.server.tool(DISCOVERY_TOOLS.validateParams.name, DISCOVERY_TOOLS.validateParams.description, {
|
|
334
|
+
toolName: z.string().describe("Tool name to validate parameters for"),
|
|
335
|
+
pathParams: z
|
|
336
|
+
.record(z.string(), z.string())
|
|
337
|
+
.optional()
|
|
338
|
+
.describe("Path parameters to validate"),
|
|
339
|
+
queryParams: z
|
|
340
|
+
.record(z.string(), z.string())
|
|
341
|
+
.optional()
|
|
342
|
+
.describe("Query parameters to validate"),
|
|
343
|
+
body: z.record(z.string(), z.unknown()).optional().describe("Request body to validate"),
|
|
344
|
+
}, async (args) => {
|
|
345
|
+
const result = validateToolParams({
|
|
346
|
+
toolName: args.toolName,
|
|
347
|
+
pathParams: args.pathParams,
|
|
348
|
+
queryParams: args.queryParams,
|
|
349
|
+
body: args.body,
|
|
350
|
+
});
|
|
351
|
+
return {
|
|
352
|
+
content: [
|
|
353
|
+
{
|
|
354
|
+
type: "text",
|
|
355
|
+
text: JSON.stringify({
|
|
356
|
+
...result,
|
|
357
|
+
formatted: formatValidationResult(result),
|
|
358
|
+
}, null, 2),
|
|
359
|
+
},
|
|
360
|
+
],
|
|
361
|
+
};
|
|
362
|
+
});
|
|
363
|
+
// Phase C: Dependency resolver tool
|
|
364
|
+
this.server.tool(DISCOVERY_TOOLS.resolveDependencies.name, DISCOVERY_TOOLS.resolveDependencies.description, {
|
|
365
|
+
resource: z.string().describe("Target resource to create"),
|
|
366
|
+
domain: z.string().describe("Domain containing the resource"),
|
|
367
|
+
existingResources: z
|
|
368
|
+
.array(z.string())
|
|
369
|
+
.optional()
|
|
370
|
+
.describe("Resources that already exist (will be skipped)"),
|
|
371
|
+
includeOptional: z
|
|
372
|
+
.boolean()
|
|
373
|
+
.optional()
|
|
374
|
+
.default(false)
|
|
375
|
+
.describe("Include optional dependencies"),
|
|
376
|
+
maxDepth: z.number().optional().default(10).describe("Maximum dependency traversal depth"),
|
|
377
|
+
expandAlternatives: z
|
|
378
|
+
.boolean()
|
|
379
|
+
.optional()
|
|
380
|
+
.default(false)
|
|
381
|
+
.describe("Include alternative paths for oneOf choices"),
|
|
382
|
+
}, async (args) => {
|
|
383
|
+
const result = resolveDependencies({
|
|
384
|
+
resource: args.resource,
|
|
385
|
+
domain: args.domain,
|
|
386
|
+
existingResources: args.existingResources,
|
|
387
|
+
includeOptional: args.includeOptional,
|
|
388
|
+
maxDepth: args.maxDepth,
|
|
389
|
+
expandAlternatives: args.expandAlternatives,
|
|
390
|
+
});
|
|
391
|
+
if (!result.success || !result.plan) {
|
|
392
|
+
return {
|
|
393
|
+
content: [
|
|
394
|
+
{
|
|
395
|
+
type: "text",
|
|
396
|
+
text: JSON.stringify({ success: false, error: result.error }, null, 2),
|
|
397
|
+
},
|
|
398
|
+
],
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
return {
|
|
402
|
+
content: [
|
|
403
|
+
{
|
|
404
|
+
type: "text",
|
|
405
|
+
text: JSON.stringify({
|
|
406
|
+
success: true,
|
|
407
|
+
plan: result.plan,
|
|
408
|
+
formatted: formatCreationPlan(result.plan),
|
|
409
|
+
}, null, 2),
|
|
410
|
+
},
|
|
411
|
+
],
|
|
412
|
+
};
|
|
413
|
+
});
|
|
414
|
+
// Phase C: Cost estimation tool
|
|
415
|
+
this.server.tool(DISCOVERY_TOOLS.estimateCost.name, DISCOVERY_TOOLS.estimateCost.description, {
|
|
416
|
+
toolName: z.string().optional().describe("Single tool name to estimate"),
|
|
417
|
+
toolNames: z.array(z.string()).optional().describe("Multiple tool names to estimate"),
|
|
418
|
+
plan: z.record(z.string(), z.unknown()).optional().describe("CreationPlan to estimate"),
|
|
419
|
+
detailed: z.boolean().optional().default(true).describe("Include detailed breakdown"),
|
|
420
|
+
}, async (args) => {
|
|
421
|
+
// Single tool estimation
|
|
422
|
+
if (args.toolName) {
|
|
423
|
+
const estimate = estimateToolCost(args.toolName);
|
|
424
|
+
return {
|
|
425
|
+
content: [
|
|
426
|
+
{
|
|
427
|
+
type: "text",
|
|
428
|
+
text: JSON.stringify({
|
|
429
|
+
type: "single_tool",
|
|
430
|
+
estimate,
|
|
431
|
+
formatted: args.detailed ? formatCostEstimate(estimate) : undefined,
|
|
432
|
+
}, null, 2),
|
|
433
|
+
},
|
|
434
|
+
],
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
// Multiple tools estimation
|
|
438
|
+
if (args.toolNames && args.toolNames.length > 0) {
|
|
439
|
+
const estimates = estimateMultipleToolsCost(args.toolNames);
|
|
440
|
+
const totalTokens = estimates.reduce((sum, e) => sum + e.tokens.totalTokens, 0);
|
|
441
|
+
return {
|
|
442
|
+
content: [
|
|
443
|
+
{
|
|
444
|
+
type: "text",
|
|
445
|
+
text: JSON.stringify({
|
|
446
|
+
type: "multiple_tools",
|
|
447
|
+
toolCount: estimates.length,
|
|
448
|
+
totalTokens,
|
|
449
|
+
estimates,
|
|
450
|
+
formatted: args.detailed
|
|
451
|
+
? estimates.map((e) => formatCostEstimate(e)).join("\n\n---\n\n")
|
|
452
|
+
: undefined,
|
|
453
|
+
}, null, 2),
|
|
454
|
+
},
|
|
455
|
+
],
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
// Workflow/plan estimation
|
|
459
|
+
if (args.plan) {
|
|
460
|
+
const estimate = estimateWorkflowCost(args.plan);
|
|
461
|
+
return {
|
|
462
|
+
content: [
|
|
463
|
+
{
|
|
464
|
+
type: "text",
|
|
465
|
+
text: JSON.stringify({
|
|
466
|
+
type: "workflow",
|
|
467
|
+
estimate,
|
|
468
|
+
formatted: args.detailed ? formatWorkflowCostEstimate(estimate) : undefined,
|
|
469
|
+
}, null, 2),
|
|
470
|
+
},
|
|
471
|
+
],
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
// No valid input provided
|
|
475
|
+
return {
|
|
476
|
+
content: [
|
|
477
|
+
{
|
|
478
|
+
type: "text",
|
|
479
|
+
text: JSON.stringify({
|
|
480
|
+
error: "No valid input provided",
|
|
481
|
+
hint: "Provide either 'toolName', 'toolNames', or 'plan' parameter",
|
|
482
|
+
}, null, 2),
|
|
483
|
+
},
|
|
484
|
+
],
|
|
485
|
+
};
|
|
486
|
+
});
|
|
487
|
+
// Phase C: Best practices tool
|
|
488
|
+
this.server.tool(DISCOVERY_TOOLS.bestPractices.name, DISCOVERY_TOOLS.bestPractices.description, {
|
|
489
|
+
domain: z.string().optional().describe("Domain to get best practices for"),
|
|
490
|
+
aspect: z
|
|
491
|
+
.enum(["errors", "workflows", "danger", "security", "performance", "all"])
|
|
492
|
+
.optional()
|
|
493
|
+
.default("all")
|
|
494
|
+
.describe("Specific aspect to retrieve"),
|
|
495
|
+
detailed: z.boolean().optional().default(true).describe("Include detailed breakdowns"),
|
|
496
|
+
}, async (args) => {
|
|
497
|
+
// If no domain specified, return domain summary
|
|
498
|
+
if (!args.domain) {
|
|
499
|
+
const summary = getAllDomainsSummary();
|
|
500
|
+
return {
|
|
501
|
+
content: [
|
|
502
|
+
{
|
|
503
|
+
type: "text",
|
|
504
|
+
text: JSON.stringify({
|
|
505
|
+
type: "domain_summary",
|
|
506
|
+
hint: "Specify a domain to get detailed best practices",
|
|
507
|
+
domains: summary,
|
|
508
|
+
}, null, 2),
|
|
509
|
+
},
|
|
510
|
+
],
|
|
511
|
+
};
|
|
512
|
+
}
|
|
513
|
+
// Query best practices for specified domain
|
|
514
|
+
const result = queryBestPractices({
|
|
515
|
+
domain: args.domain,
|
|
516
|
+
aspect: args.aspect,
|
|
517
|
+
detailed: args.detailed,
|
|
518
|
+
});
|
|
519
|
+
if (!result.success) {
|
|
520
|
+
return {
|
|
521
|
+
content: [
|
|
522
|
+
{
|
|
523
|
+
type: "text",
|
|
524
|
+
text: JSON.stringify({ success: false, error: result.error }, null, 2),
|
|
525
|
+
},
|
|
526
|
+
],
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
return {
|
|
530
|
+
content: [
|
|
531
|
+
{
|
|
532
|
+
type: "text",
|
|
533
|
+
text: JSON.stringify({
|
|
534
|
+
success: true,
|
|
535
|
+
practices: result.practices,
|
|
536
|
+
formatted: args.detailed && result.practices
|
|
537
|
+
? formatBestPractices(result.practices)
|
|
538
|
+
: undefined,
|
|
539
|
+
}, null, 2),
|
|
540
|
+
},
|
|
541
|
+
],
|
|
542
|
+
};
|
|
543
|
+
});
|
|
544
|
+
const indexMetadata = getIndexMetadata();
|
|
545
|
+
const consolidationStats = getConsolidationStats();
|
|
546
|
+
logger.info("Tool registration completed (dynamic discovery mode)", {
|
|
547
|
+
authMode,
|
|
548
|
+
authenticated: authMode !== AuthMode.NONE,
|
|
549
|
+
registeredTools: 12,
|
|
550
|
+
indexedTools: indexMetadata.totalTools,
|
|
551
|
+
consolidatedResources: consolidationStats.consolidatedCount,
|
|
552
|
+
consolidationReduction: consolidationStats.reductionPercent,
|
|
553
|
+
domains: Object.keys(indexMetadata.domains),
|
|
554
|
+
tokenSavings: "95%+ (535K → ~500 tokens upfront)",
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Register MCP resources for F5XC configuration objects
|
|
559
|
+
*/
|
|
560
|
+
registerResources() {
|
|
561
|
+
const tenant = this.credentialManager.getTenant() ?? "{tenant}";
|
|
562
|
+
// Register resource templates for each resource type
|
|
563
|
+
for (const rt of Object.values(RESOURCE_TYPES)) {
|
|
564
|
+
const uriTemplate = rt.namespaceScoped
|
|
565
|
+
? `f5xc://${tenant}/{namespace}/${rt.type}/{name}`
|
|
566
|
+
: `f5xc://${tenant}/system/${rt.type}/{name}`;
|
|
567
|
+
this.server.resource(uriTemplate, rt.description, async (uri) => {
|
|
568
|
+
try {
|
|
569
|
+
const result = await this.resourceHandler.readResource(uri.href);
|
|
570
|
+
return {
|
|
571
|
+
contents: [
|
|
572
|
+
{
|
|
573
|
+
uri: result.uri,
|
|
574
|
+
mimeType: result.mimeType,
|
|
575
|
+
text: result.content,
|
|
576
|
+
},
|
|
577
|
+
],
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
catch (error) {
|
|
581
|
+
logger.error(`Failed to read resource: ${uri.href}`, {
|
|
582
|
+
error: error instanceof Error ? error.message : String(error),
|
|
583
|
+
});
|
|
584
|
+
throw error;
|
|
585
|
+
}
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
logger.info("Resource registration completed", {
|
|
589
|
+
resourceTypes: Object.keys(RESOURCE_TYPES).length,
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Register MCP prompts for common workflows
|
|
594
|
+
*/
|
|
595
|
+
registerPrompts() {
|
|
596
|
+
// Register all workflow prompts
|
|
597
|
+
for (const workflow of WORKFLOW_PROMPTS) {
|
|
598
|
+
// Build Zod schema for arguments
|
|
599
|
+
const argSchema = {};
|
|
600
|
+
for (const arg of workflow.arguments) {
|
|
601
|
+
argSchema[arg.name] = arg.required
|
|
602
|
+
? z.string().describe(arg.description)
|
|
603
|
+
: z.string().optional().describe(arg.description);
|
|
604
|
+
}
|
|
605
|
+
this.server.prompt(workflow.name, workflow.description, argSchema, async (args) => {
|
|
606
|
+
// Process template with provided arguments
|
|
607
|
+
const processedArgs = {};
|
|
608
|
+
for (const [key, value] of Object.entries(args)) {
|
|
609
|
+
if (typeof value === "string") {
|
|
610
|
+
processedArgs[key] = value;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
// Apply default values for optional args
|
|
614
|
+
for (const arg of workflow.arguments) {
|
|
615
|
+
if (!processedArgs[arg.name] && !arg.required) {
|
|
616
|
+
// Set sensible defaults
|
|
617
|
+
if (arg.name === "backend_port")
|
|
618
|
+
processedArgs[arg.name] = "80";
|
|
619
|
+
if (arg.name === "enable_waf")
|
|
620
|
+
processedArgs[arg.name] = "false";
|
|
621
|
+
if (arg.name === "mode")
|
|
622
|
+
processedArgs[arg.name] = "blocking";
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
const processedTemplate = processPromptTemplate(workflow.template, processedArgs);
|
|
626
|
+
return {
|
|
627
|
+
messages: [
|
|
628
|
+
{
|
|
629
|
+
role: "user",
|
|
630
|
+
content: {
|
|
631
|
+
type: "text",
|
|
632
|
+
text: processedTemplate,
|
|
633
|
+
},
|
|
634
|
+
},
|
|
635
|
+
],
|
|
636
|
+
};
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
// Phase B: Register error resolution prompts
|
|
640
|
+
for (const errorPrompt of ERROR_PROMPTS) {
|
|
641
|
+
// Build Zod schema for arguments
|
|
642
|
+
const argSchema = {};
|
|
643
|
+
for (const arg of errorPrompt.arguments) {
|
|
644
|
+
argSchema[arg.name] = arg.required
|
|
645
|
+
? z.string().describe(arg.description)
|
|
646
|
+
: z.string().optional().describe(arg.description);
|
|
647
|
+
}
|
|
648
|
+
this.server.prompt(errorPrompt.name, errorPrompt.description, argSchema, async (args) => {
|
|
649
|
+
// Process template with provided arguments
|
|
650
|
+
const processedArgs = {};
|
|
651
|
+
for (const [key, value] of Object.entries(args)) {
|
|
652
|
+
if (typeof value === "string") {
|
|
653
|
+
processedArgs[key] = value;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
const processedTemplate = processErrorTemplate(errorPrompt, processedArgs);
|
|
657
|
+
return {
|
|
658
|
+
messages: [
|
|
659
|
+
{
|
|
660
|
+
role: "user",
|
|
661
|
+
content: {
|
|
662
|
+
type: "text",
|
|
663
|
+
text: processedTemplate,
|
|
664
|
+
},
|
|
665
|
+
},
|
|
666
|
+
],
|
|
667
|
+
};
|
|
668
|
+
});
|
|
669
|
+
}
|
|
670
|
+
logger.info("Prompt registration completed", {
|
|
671
|
+
workflows: WORKFLOW_PROMPTS.length,
|
|
672
|
+
errorPrompts: ERROR_PROMPTS.length,
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Start the MCP server with STDIO transport
|
|
677
|
+
*/
|
|
678
|
+
async start() {
|
|
679
|
+
this.transport = new StdioServerTransport();
|
|
680
|
+
logger.info("Starting F5XC API MCP Server", {
|
|
681
|
+
version: VERSION,
|
|
682
|
+
authMode: this.credentialManager.getAuthMode(),
|
|
683
|
+
});
|
|
684
|
+
await this.server.connect(this.transport);
|
|
685
|
+
logger.info("F5XC API MCP Server started successfully");
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Stop the MCP server
|
|
689
|
+
*/
|
|
690
|
+
async stop() {
|
|
691
|
+
if (this.transport) {
|
|
692
|
+
await this.server.close();
|
|
693
|
+
this.transport = null;
|
|
694
|
+
logger.info("F5XC API MCP Server stopped");
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Get the underlying MCP server instance
|
|
699
|
+
*/
|
|
700
|
+
getMcpServer() {
|
|
701
|
+
return this.server;
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Get the credential manager
|
|
705
|
+
*/
|
|
706
|
+
getCredentialManager() {
|
|
707
|
+
return this.credentialManager;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Create and configure the F5XC API MCP Server
|
|
712
|
+
*/
|
|
713
|
+
export function createServer(configManager) {
|
|
714
|
+
const credentialManager = new CredentialManager(configManager);
|
|
715
|
+
return new F5XCApiServer({
|
|
716
|
+
name: "f5xc-api-mcp",
|
|
717
|
+
version: VERSION,
|
|
718
|
+
credentialManager,
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
//# sourceMappingURL=server.js.map
|