Skip to content

feat: AI assist commands, HTTP MCP server, extensions management#1014

Merged
rsenden merged 58 commits into
dev/v3.xfrom
feat/v3.x/agent-skills
May 24, 2026
Merged

feat: AI assist commands, HTTP MCP server, extensions management#1014
rsenden merged 58 commits into
dev/v3.xfrom
feat/v3.x/agent-skills

Conversation

@rsenden
Copy link
Copy Markdown
Contributor

@rsenden rsenden commented May 22, 2026

feat: `fcli ai-assist mcp start-stdio`: New command replacing `fcli util mcp-server start` for starting the fcli MCP server over stdio

feat: `fcli ai-assist mcp start-http`: New command to start an HTTP MCP server exposing imported action functions, with per-request auth headers for SSC and FoD

feat: `fcli ai-assist mcp create-http-config`: New command to generate sample HTTP MCP server config files for SSC or FoD

feat: `fcli ai-assist extensions setup`: New command to install/update Fortify extensions (skills, agents, ...) for AI coding assistants (Claude Code, GitHub Copilot, OpenAI Codex, Gemini CLI) with auto-detection, target deduplication, and digest verification

feat: `fcli ai-assist extensions uninstall`: New command to remove installed Fortify extensions, with optional `--dir` for directory-specific removal

feat: `fcli ai-assist extensions list-installed`: New command to list currently installed Fortify extensions per coding assistant and content type

feat: `fcli ai-assist extensions list-versions`: New command to list available extension versions from tool definitions

feat: `fcli ai-assist extensions list-assistants`: New command to list supported AI coding assistants with detection and installation status

feat: `fcli util mcp-server start`: Deprecated in favor of `fcli ai-assist mcp start-stdio`; delegates all arguments to the new command

fix: `fcli sc-sast sensor list`: Include full sensor details independent of filtering options; previously `--pool`, `--appversion`, and `--latest-only` returned only compatible client versions instead of full sensor records

fix: `fcli tool definitions update`: Ignore spurious intermediate directories in custom `tool-definitions.zip`

rsenden added 30 commits May 6, 2026 16:42
@rsenden rsenden marked this pull request as ready for review May 22, 2026 12:54
@rsenden
Copy link
Copy Markdown
Contributor Author

rsenden commented May 23, 2026

@copilot Please review the code that is being updated in this PR compared to dev/v3.x and provide any improvement suggestions, also taking copilot instructions file (and related files) into account.

Copy link
Copy Markdown
Contributor

Copilot AI commented May 23, 2026

@copilot Please review the code that is being updated in this PR compared to dev/v3.x and provide any improvement suggestions, also taking copilot instructions file (and related files)...

Here's a comprehensive code review of the PR changes compared to dev/v3.x, organized by severity:


🔴 Critical / High Severity

1. Path Traversal in AiAssistExtensionsSourceHandler read methods

File: AiAssistExtensionsSourceHandler.java:212-246

The readFileBytes(), exists(), listFiles(), and listDirs() methods accept a relativePath parameter and resolve it via extractedDir.resolve(relativePath) without validating containment. While zip extraction (line 141) has a proper traversal check, the subsequent file access operations don't. A malicious content-manifest.yaml could reference paths like ../../../etc/passwd:

public byte[] readFileBytes(String relativePath) {
    var filePath = extractedDir.resolve(relativePath);
    // No containment check here — unlike the zip extraction code on line 141
    if (!Files.isRegularFile(filePath)) { return null; }
    return Files.readAllBytes(filePath);
}

Fix: Add a helper that validates resolved.normalize().startsWith(extractedDir.normalize()) and use it in all resolve operations.

2. Path Traversal in AiAssistExtensionsInstaller file operations

File: AiAssistExtensionsInstaller.java:155, 370, 393, 733

Multiple locations use dir.resolve(file) or resolvedDir.resolve(targetRelPath) where the relative path is derived from manifest data without traversal validation. A malicious manifest could write files outside the target directory:

var targetAbsPath = resolvedDir.resolve(targetRelPath).toString(); // line 370

Fix: Introduce a shared safeResolve(Path baseDir, String relativePath) helper that validates the resolved path stays within the base directory.

3. Unclosed Stream<Path> resource leak

File: AiAssistExtensionsSourceHandler.java:226-246

Both listFiles() and listDirs() return Files.walk()/Files.list() streams to callers. These streams hold open directory handles and must be closed. However, the callers in AiAssistExtensionsInstaller (lines 540-549, 559-563, 580-583) use .forEach() directly on the returned stream without try-with-resources, leaking file descriptors:

sourceHandler.listDirs(sourceDir).forEach(dir -> {  // Leaked
    sourceHandler.listFiles(dir.toString()).forEach(f -> { ... }); // Also leaked
});

Fix: Either change listFiles()/listDirs() to return List<Path> (collecting internally), or ensure all callers wrap in try-with-resources.


🟡 Medium Severity

4. Unbounded request body size (DoS vector)

File: JdkHttpServerMcpStatelessTransport.java:164-165

When maxRequestBodyBytes defaults to -1, the server calls readAllBytes() with no limit, allowing an attacker to exhaust JVM memory:

if ( maxRequestBodyBytes <= 0 ) {
    return exchange.getRequestBody().readAllBytes(); // No limit — DoS vector
}

Fix: Use a sensible default limit (e.g., 10 MB) instead of unlimited when the config value is ≤ 0.

5. HttpMcpFoDUserCredentials password char[] never cleared

File: MCPServerHttpSessionDescriptorResolver.java:382-386

The password is stored in a char[] (good practice) but is never zeroed after use — it remains in memory for the lifetime of the object:

private final char[] password; // Never cleared after token creation

This is a minor concern since the IsolationScopeEntry caches credentials for the TTL duration anyway, but worth noting for defense-in-depth.

6. enableEphemeralEncryption() race condition

File: FcliExecutionContext.java:132-141

The double-check on encryptionHelper != EncryptionHelper.DEFAULT is not properly synchronized — the check on line 133 races with the assignment inside the synchronized block. A second thread could observe the field as DEFAULT, enter the block, and overwrite a previously-set ephemeral helper:

public boolean enableEphemeralEncryption() {
    if ( encryptionHelper!=EncryptionHelper.DEFAULT ) { return true; } // Unsynchronized read
    synchronized(this) {
        // Missing re-check after acquiring lock
        var rnd = new byte[32];
        ...
    }
}

Fix: Add the re-check inside the synchronized block (standard DCL pattern).


🟢 Low Severity / Style

7. matchesGlob() regex is incomplete

File: AiAssistExtensionsInstaller.java:697-699

The glob-to-regex conversion only escapes . and replaces *. Characters like ?, [, ], +, ^, $, {, }, (, ) are not handled:

private static boolean matchesGlob(String filename, String glob) {
    var regex = glob.replace(".", "\\.").replace("*", ".*");
    return filename.matches(regex);
}

If glob ever contains regex-special characters other than . or *, this will fail or match incorrectly. Consider using java.nio.file.PathMatcher (as already used in AiAssistExtensionsConditionEvaluator) for consistency.

8. HttpMcpSscUrlConfig.getDisabledComponents() allocates new HashSet per call

File: MCPServerHttpSessionDescriptorResolver.java:422-424

@Override
public Set<SSCComponentDisable> getDisabledComponents() {
    return new HashSet<>(); // New allocation per call
}

Consider returning Set.of() or a shared empty set.

9. Inner credential classes could use records

File: MCPServerHttpSessionDescriptorResolver.java:357-401

HttpMcpFoDClientCredentials and HttpMcpFoDUserCredentials are plain data carriers. Per the project's Java 17 target and style guide, they could be records (except that the char[] for password prevents meaningful equals/hashCode). As-is, they're fine, but the client credentials one could be a record since it only has String fields.

10. Installer class is 991 lines

File: AiAssistExtensionsInstaller.java

The class exceeds the ~20 lines/method guideline in aggregate. The logic divides cleanly into: plan building, plan execution, manifest I/O, state persistence, and content discovery. Consider splitting into smaller helper classes (e.g., AiAssistExtensionsSetupPlanBuilder, AiAssistExtensionsManifestHelper) for maintainability.


✅ Things Done Well

  • Zip-slip protection in fromZipFile() (line 141) is correctly implemented
  • Per-request isolation via FcliIsolationScope + LogMaskContext is well-designed
  • Auth credential hashing for the isolation scope cache key uses SHA-256 with null-byte separators (prevents concatenation collisions)
  • Proper try-with-resources on JdkHttpServerMcpStatelessTransport and FcliExecutionContextHolder.ContextFrame
  • Signature verification on distribution descriptor and zip files
  • Thread safety on FcliIsolationScope (ConcurrentHashMap) and IsolationScopeEntry (synchronized validation)
  • Idempotent setup with diff-based install/update/remove plan

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new ai-assist module that adds MCP server commands (stdio + HTTP) and AI-assistant “extensions” management, while also refactoring execution-context/isolation handling to support per-request and per-identity state (sessions, variables, job caches). It also includes fixes and test updates across SSC/FoD/SC-SAST and supporting infrastructure.

Changes:

  • Add fcli ai-assist command tree (MCP server start/config generation + extensions setup/uninstall/listing) and wire it into the root CLI.
  • Refactor execution context, isolation scope, action global state, and async job infrastructure to support proper isolation across CLI invocations and server requests.
  • Fix sc-sast sensor list to always return full sensor records and include compatible client version enrichment.

Reviewed changes

Copilot reviewed 173 out of 173 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
gradle.properties Adds module ref for ai-assist
fcli-other/fcli-functional-test/src/ftest/resources/runtime/actions/server-import-http-ssc-functions.yaml Adds SSC HTTP MCP test action
fcli-other/fcli-functional-test/src/ftest/resources/runtime/actions/server-import-http-fod-functions.yaml Adds FoD HTTP MCP test action
fcli-other/fcli-functional-test/src/ftest/resources/runtime/actions/run-fcli-shared-state-parent.yaml Adds parent action for state-sharing test
fcli-other/fcli-functional-test/src/ftest/resources/runtime/actions/run-fcli-shared-state-child.yaml Adds child action for state-sharing test
fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/ssc/SSCAlertDefinitionSpec.groovy Updates SSC command name in test
fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/fod/FoDMCPServerHttpSpec.groovy Adds FoD HTTP MCP functional test
fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/core/MCPServerImportSpec.groovy Extends MCP import tests (globals)
fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/core/ActionFunctionsSpec.groovy Adds run.fcli state reuse test
fcli-other/fcli-functional-test/src/ftest/groovy/com/fortify/cli/ftest/_common/MCPHttpServerTestHelper.groovy Adds HTTP MCP client/server test helper
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/rpc_server/helper/RPCWaitHelper.java Switches job listener import to common
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/rpc_server/helper/RPCServer.java Pushes execution context per RPC call
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/rpc_server/helper/RPCPushJobEventListener.java Switches job listener import to common
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/rpc_server/helper/RPCMethodHandlerRegistry.java Refactors registry to use isolation scope
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/rpc_server/helper/RPCMethodHandlerJobRemove.java Uses scoped caching listener via context
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/rpc_server/helper/RPCMethodHandlerJobList.java Switches AsyncJobManager import to common
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/rpc_server/helper/RPCMethodHandlerJobGetStatus.java Uses scoped caching listener via context
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/rpc_server/helper/RPCMethodHandlerJobGetPage.java Resolves caching listener from isolation scope
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/rpc_server/helper/RPCMethodHandlerJobCancel.java Switches AsyncJobManager import to common
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/rpc_server/helper/RPCMethodHandlerFnCall.java Uses new AsyncJobManager task descriptor API
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/rpc_server/helper/RPCMethodHandlerFcliExecute.java Uses new AsyncJobManager task descriptor API
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/rpc_server/helper/RPCJobEventListenerFactory.java Uses scoped caching listener via context
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/rpc_server/cli/cmd/RPCServerStartCommand.java Marks RPC start as context manager command
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/mcp_server/cli/cmd/MCPServerStartDeprecatedCommand.java Adds deprecated MCP start wrapper
fcli-core/fcli-util/src/main/java/com/fortify/cli/util/mcp_server/cli/cmd/MCPServerCommands.java Routes util mcp-server start to deprecated wrapper
fcli-core/fcli-tool/src/main/java/com/fortify/cli/tool/sc_client/cli/cmd/ToolSCClientInstallCommand.java Removes ToolDependency usage for JRE
fcli-core/fcli-tool/src/main/java/com/fortify/cli/tool/_common/helper/ToolDependency.java Removes ToolDependency enum
fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/access_control/helper/SSCTokenConverter.java Makes regex pattern final
fcli-core/fcli-ssc/src/main/java/com/fortify/cli/ssc/_common/rest/cli/mixin/SSCAndScanCentralUnirestInstanceSupplierMixin.java Implements session descriptor type hook
fcli-core/fcli-sc-sast/src/main/resources/com/fortify/cli/sc_sast/i18n/SCSastMessages.properties Updates sensor list help text
fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/sensor/helper/SCSastSensorCompatibleVersionHelper.java Adds sensor streaming + enrichment helper
fcli-core/fcli-sc-sast/src/main/java/com/fortify/cli/sc_sast/sensor/cli/cmd/SCSastSensorListCommand.java Returns full sensors for filtered modes
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/helper/FoDReleaseDescriptor.java Switches attribute type to value descriptor
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/cli/cmd/FoDReleaseUpdateCommand.java Uses new attribute definition helper
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/release/cli/cmd/FoDReleaseCreateCommand.java Uses new attribute definition helper
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/microservice/helper/FoDMicroserviceHelper.java Uses new attribute definition helper
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/microservice/helper/FoDMicroserviceDescriptor.java Switches attribute type to value descriptor
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/microservice/cli/cmd/FoDMicroserviceUpdateCommand.java Refactors microservice attribute update flow
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/microservice/cli/cmd/FoDMicroserviceCreateCommand.java Uses new attribute definition helper
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/issue/cli/cmd/FoDIssueUpdateCommand.java Refactors issue attributes/status resolution
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/attribute/helper/FoDAttributeValueDescriptor.java Adds value-only attribute descriptor
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/attribute/helper/FoDAttributeDefinitionDescriptor.java Renames definition descriptor; removes value field
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/attribute/cli/mixin/FoDAttributeResolverMixin.java Switches to new definition helper/descriptor
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/attribute/cli/cmd/FoDAttributeUpdateCommand.java Switches to definition helper for updates
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/attribute/cli/cmd/FoDAttributeDeleteCommand.java Switches to definition helper for deletes
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/attribute/cli/cmd/FoDAttributeCreateCommand.java Switches to definition helper for create
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/app/helper/FoDAppDescriptor.java Switches attribute type to value descriptor
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/app/helper/FoDAppCreateRequest.java Uses definition helper for auto-attributes
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/app/cli/cmd/FoDAppUpdateCommand.java Uses definition helper for update attrs
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/_common/session/helper/FoDSessionDescriptor.java Adds copy-with-token helper method
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/_common/session/cli/mixin/FoDUnirestInstanceSupplierMixin.java Implements session descriptor type hook
fcli-core/fcli-fod/src/main/java/com/fortify/cli/fod/_common/scan/helper/FoDScanDescriptor.java Switches attribute type to value descriptor
fcli-core/fcli-common/src/test/java/com/fortify/cli/common/session/cli/mixin/AbstractSessionDescriptorSupplierMixinTest.java Adds transient session descriptor tests
fcli-core/fcli-common/src/test/java/com/fortify/cli/common/concurrent/job/AsyncJobManagerIsolationScopeTest.java Adds isolation-scope job tracking test
fcli-core/fcli-common/src/test/java/com/fortify/cli/common/concurrent/FcliConcurrencyTest.java Updates access to global action state
fcli-core/fcli-common/src/test/java/com/fortify/cli/common/cli/util/FcliExecutionContextTest.java Adds execution context behavior tests
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/variable/FcliVariableHelper.java Supports scoped vars path via isolation scope
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/util/FileUtils.java Renames stream open helpers
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/session/helper/AbstractSessionHelper.java Exposes log mask registration for transient sessions
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/session/cli/mixin/AbstractSessionDescriptorSupplierMixin.java Prefers transient session descriptors
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/log/LogMaskSource.java Adds HTTP auth header mask source
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/concurrent/job/task/AsyncTaskFcliCommand.java Moves task into common job package
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/concurrent/job/task/AsyncTaskActionFunction.java Moves task into common job package
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/concurrent/job/IJobEventListener.java Moves interface into common job package
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/concurrent/job/IAsyncTask.java Moves interface into common job package
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/concurrent/job/exec/FcliRunnerHelper.java Moves helper; adjusts executor usage
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/concurrent/job/exec/FcliExecutionResult.java Moves result into common job package
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/concurrent/job/CompositeJobEventListener.java Moves listener into common job package
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/concurrent/job/CollectingJobEventListener.java Moves listener into common job package
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/concurrent/job/cli/mixin/AsyncJobManagerMixin.java Moves mixin into common job package
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/concurrent/job/CachingJobEventListener.java Moves listener into common job package
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/cli/util/StdioHelper.java Adds ANSI capture + progress suppression safeguards
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/cli/util/IFcliExecutionContextManager.java Adds marker interface for context-managing commands
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/cli/util/FcliModules.java Adds AGENT module enum
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/cli/util/FcliIsolationScope.java Introduces isolation-scope state container
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/cli/util/FcliExecutionContextHolder.java Makes context pushing explicit; adds frames
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/cli/util/FcliCommandExecutorFactory.java Removes implicit context creation option
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/cli/util/FcliActionState.java Adds shared global.* action state container
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/runner/ActionRunnerVars.java Uses actionState global values
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/runner/ActionFunctionExecutor.java Uses supplier-based context frames
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/helper/ActionLoaderHelper.java Updates FileUtils method names
fcli-core/fcli-common/src/main/java/com/fortify/cli/common/action/cli/cmd/RunBuildTimeFcliAction.java Pushes execution context for build-time run
fcli-core/fcli-aviator/src/main/java/com/fortify/cli/aviator/_common/session/user/cli/mixin/AviatorUserSessionDescriptorSupplier.java Implements session descriptor type hook
fcli-core/fcli-aviator/src/main/java/com/fortify/cli/aviator/_common/config/admin/cli/mixin/AviatorAdminConfigDescriptorSupplier.java Implements session descriptor type hook
fcli-core/fcli-app/src/main/java/com/fortify/cli/app/runner/util/FortifyCLIDynamicInitializer.java Updates log mask registration API
fcli-core/fcli-app/src/main/java/com/fortify/cli/app/FortifyCLI.java Moves ANSI detection out of main
fcli-core/fcli-app/src/main/java/com/fortify/cli/app/_main/cli/cmd/FCLIRootCommands.java Registers new ai-assist command group
fcli-core/fcli-app/build.gradle.kts Adds ai-assist dependency + reflect generator main
fcli-core/fcli-ai-assist/src/test/java/com/fortify/cli/agent/mcp/unit/MCPToolFcliRunnerRecordsTest.java Moves MCP tests to ai-assist packages
fcli-core/fcli-ai-assist/src/test/java/com/fortify/cli/agent/mcp/unit/MCPToolArgHandlersTest.java Moves MCP tests to ai-assist packages
fcli-core/fcli-ai-assist/src/test/java/com/fortify/cli/agent/mcp/unit/MCPServerHttpConfigLoaderTest.java Adds HTTP MCP config loader tests
fcli-core/fcli-ai-assist/src/test/java/com/fortify/cli/agent/mcp/unit/MCPJobManagerTest.java Adds isolation-scope MCP job tests
fcli-core/fcli-ai-assist/src/test/java/com/fortify/cli/agent/mcp/helper/runner/MCPToolResultTest.java Adds pagination jobToken test
fcli-core/fcli-ai-assist/src/test/java/com/fortify/cli/agent/mcp/helper/runner/MCPToolFcliRunnerFunctionStreamingTest.java Tests paging arg exclusion for streaming
fcli-core/fcli-ai-assist/src/main/resources/com/fortify/cli/ai_assist/mcp/config/mcp-http-config-ssc.yaml Adds SSC sample HTTP MCP config template
fcli-core/fcli-ai-assist/src/main/resources/com/fortify/cli/ai_assist/mcp/config/mcp-http-config-fod.yaml Adds FoD sample HTTP MCP config template
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/runner/MCPToolResult.java Adds jobToken support in paged results
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/runner/MCPToolFcliRunnerRecordsPaged.java Moves runner to ai-assist package
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/runner/MCPToolFcliRunnerRecords.java Moves runner to ai-assist package
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/runner/MCPToolFcliRunnerPlainText.java Moves runner to ai-assist package
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/runner/MCPToolFcliRunnerHelper.java Uses common FcliRunnerHelper
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/runner/MCPToolFcliRunnerFunctionStreaming.java Filters paging args; uses async tasks
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/runner/MCPToolFcliRunnerFunction.java Moves runner to ai-assist package
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/runner/MCPToolFcliRunnerAction.java Moves runner + arg handlers to ai-assist
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/runner/MCPToolFcliPagedHelper.java Includes jobToken in paged responses
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/runner/MCPToolAsyncJobManager.java Scopes caches/job tokens to isolation scope
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/runner/MCPResourceFcliRunnerFunction.java Moves resource runner to ai-assist
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/runner/IMCPToolRunner.java Moves tool runner interface to ai-assist
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/runner/AbstractMCPToolFcliRunner.java Moves base runner to ai-assist
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/MCPReflectConfigGenerator.java Moves reflect generator to ai-assist
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/MCPJobManager.java Isolation-scope job registry + worker context
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/http/ParsedAuthorization.java Adds parsed auth header + log masking
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/http/MCPServerHttpConfigLoader.java Adds HTTP MCP config YAML loader
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/arg/MCPToolArgHandlers.java Moves arg handling into ai-assist
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/arg/MCPToolArgHandlerQuery.java Moves query arg handler into ai-assist
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/arg/MCPToolArgHandlerPaging.java Moves paging arg handler into ai-assist
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/arg/MCPToolArgHandlerFcliParam.java Moves param arg handler into ai-assist
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/arg/MCPToolArgHandlerFcliOption.java Moves option arg handler into ai-assist
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/arg/MCPToolArgHandlerActionOption.java Moves action option arg handler into ai-assist
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/arg/IMCPToolArgHandler.java Moves arg handler interface into ai-assist
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/helper/arg/AbstractMCPToolArgHandlerFcli.java Moves base arg handler into ai-assist
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/cli/cmd/AiAssistMCPCreateHttpConfigCommand.java Adds HTTP MCP config template generator
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/cli/cmd/AiAssistMCPCommands.java Adds MCP subcommand container
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/helper/AiAssistExtensionsVersionOutputDescriptor.java Adds list-versions output DTO
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/helper/AiAssistExtensionsTargetDirManifest.java Adds per-target manifest format
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/helper/AiAssistExtensionsTargetDescriptor.java Adds target descriptor model
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/helper/AiAssistExtensionsPathResolver.java Adds assistant target path resolution
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/helper/AiAssistExtensionsOutputDescriptor.java Adds install/uninstall output DTO
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/helper/AiAssistExtensionsInstallPlanContext.java Adds dedup context for installs
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/helper/AiAssistExtensionsInstallationsDescriptor.java Adds persisted installations registry
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/helper/AiAssistExtensionsDistributionDescriptor.java Adds distribution descriptor model
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/helper/AiAssistExtensionsContentTypeDescriptor.java Adds content-manifest content type model
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/helper/AiAssistExtensionsContentManifestDescriptor.java Adds content-manifest descriptor model
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/helper/AiAssistExtensionsAssistantOutputDescriptor.java Adds assistant listing output DTO
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/helper/AiAssistExtensionsAssistantDescriptor.java Adds assistant descriptor model
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/cli/cmd/AiAssistExtensionsUninstallCommand.java Adds uninstall command wrapper
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/cli/cmd/AiAssistExtensionsSetupCommand.java Adds setup/install command wrapper
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/cli/cmd/AiAssistExtensionsListVersionsCommand.java Adds list-versions command
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/cli/cmd/AiAssistExtensionsListInstalledCommand.java Adds list-installed command
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/cli/cmd/AiAssistExtensionsListAssistantsCommand.java Adds list-assistants command
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/extensions/cli/cmd/AiAssistExtensionsCommands.java Adds extensions subcommand container
fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/_main/cli/cmd/AiAssistCommands.java Adds top-level ai-assist container
fcli-core/fcli-ai-assist/build.gradle.kts Adds new ai-assist module build
.github/instructions/utilities.instructions.md Updates documented utilities/infrastructure
.github/instructions/style.instructions.md Updates style/self-update guidance
.github/instructions/java.instructions.md Updates Java patterns guidance
.github/copilot-instructions.md Updates workflow + self-learning guidance
Comments suppressed due to low confidence (1)

fcli-core/fcli-ai-assist/src/main/java/com/fortify/cli/ai_assist/mcp/cli/cmd/AiAssistMCPCreateHttpConfigCommand.java:73

  • The template read failure handler catches IOException but drops the underlying cause. Consider passing the caught exception as the cause to FcliSimpleException so users can diagnose resource/IO issues.
        } catch (IOException e) {
            throw new FcliSimpleException("Error reading HTTP MCP template resource: %s", templateResource);
        }

Comment on lines +63 to +64
case ssc -> "/com/fortify/cli/agent/mcp/config/mcp-http-config-ssc.yaml";
case fod -> "/com/fortify/cli/agent/mcp/config/mcp-http-config-fod.yaml";
Comment on lines +52 to +56
force ? new StandardOpenOption[] {StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING}
: new StandardOpenOption[] {StandardOpenOption.CREATE_NEW});
} catch (IOException e) {
throw new FcliSimpleException("Error writing HTTP MCP config file: %s", outputPath);
}
Comment on lines +59 to +62
@Option(names = {"-y", "--confirm"},
descriptionKey = "fcli.ai-assist.extensions.confirm")
private boolean confirm;

Comment on lines +43 to +46
@Option(names = {"-y", "--confirm"},
descriptionKey = "fcli.ai-assist.extensions.confirm")
private boolean confirm;

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 174 out of 174 changed files in this pull request and generated 5 comments.

Comment on lines +37 to +41
public Integer call() {
var cmd = "fcli ai-assist mcp start-stdio";
if ( delegatedArgs != null && !delegatedArgs.isEmpty() ) {
cmd += " " + String.join(" ", delegatedArgs);
}
Comment on lines 79 to +86
public static synchronized void install() {
if ( installed ) return;
// Detect ANSI capability before replacing streams: the delegating/masking
// wrappers installed below can interfere with terminal-based ANSI probing.
ansi = Ansi.AUTO.enabled() ? Ansi.ON : Ansi.AUTO;
rawOut = System.out;
rawErr = System.err;
installThread = Thread.currentThread();
Comment on lines +106 to +112
/**
* Look up a transient session descriptor by type, searching from top to bottom
* through the current thread's execution-context stack.
*/
public static ISessionDescriptor getTransientSessionDescriptor(String type) {
return current().getIsolationScope().getTransientSessionDescriptor(type);
}
Comment on lines +51 to +56
Files.writeString(outputPath, loadTemplate(), StandardCharsets.UTF_8,
force ? new StandardOpenOption[] {StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING}
: new StandardOpenOption[] {StandardOpenOption.CREATE_NEW});
} catch (IOException e) {
throw new FcliSimpleException("Error writing HTTP MCP config file: %s", outputPath);
}
Comment on lines +46 to +56
try {
var rawNode = YAML_MAPPER.readTree(normalizedPath.toFile());
var resolvedNode = resolveTemplateExpressions(rawNode);
var result = YAML_MAPPER.treeToValue(resolvedNode, MCPServerHttpConfig.class);
result.validate(normalizedPath);
return result;
} catch (FcliSimpleException e) {
throw e;
} catch (IOException e) {
throw new FcliSimpleException("Unable to read HTTP MCP config file: " + normalizedPath);
}
@rsenden rsenden merged commit 1c6916a into dev/v3.x May 24, 2026
44 checks passed
@rsenden rsenden deleted the feat/v3.x/agent-skills branch May 24, 2026 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants