@W-20926594 MCP Server Flag Configuration and SDK Refactoring#65
@W-20926594 MCP Server Flag Configuration and SDK Refactoring#65
Conversation
…/refactor-fix-lookup-config
| When `--config` is not provided, the MCP server searches for `dw.json` starting from the `--working-directory` path (or `SFCC_WORKING_DIRECTORY` env var). | ||
|
|
||
| > **Note:** Auto-discovery starts from the home directory, so it won't find project-level `dw.json` files. Use `--config` with an explicit path instead. | ||
| > **Important:** MCP clients like Cursor and Claude Desktop often spawn servers from the home directory (`~`) rather than the project directory. Always set `--working-directory` for reliable `dw.json` auto-discovery. |
There was a problem hiding this comment.
We should not be mentioning dw.json in most places. The config load is complex and dw.json is just one part of it. We should be more general: "reliable configuration loading and auto-discovery", etc
There was a problem hiding this comment.
This looks good. Overall a good refactoring. A added a few nits and observations where we might not be using some of your new methods. And if we're ready we can confirm that plugins work (should be able to a plugins install sfcc-solutions-share/b2c-plugin-macos-keychain to get my keychain plugin).
And I just want to emphasize that (outside of the --config flag that points to it) the dw.json convention is an implementation detail of the SDK. That is, it's just one step in the configuration loading and that config can come from multiple places (mobify, package.json now, plugin sources and likely future out of the box sources). So it's important that the MCP behaves the same as the CLI and doesn't accidentally change the config behavior. I think we're good here as I just noticed it mentioned in documentation.
| **Option E: dw.json with auto-discovery** | ||
|
|
||
| When `--config` is not provided, the MCP server searches upward from `~/` for a `dw.json` file. | ||
| When `--config` is not provided, the MCP server searches for `dw.json` starting from the `--working-directory` path (or `SFCC_WORKING_DIRECTORY` env var). |
There was a problem hiding this comment.
Can the --working-directory suffice? I'm not sure we need to do a search for dw.json at all here. If the file isn't in the working-directory we won't load it. But we may load some other configuration source that is sufficient for the task. The working-directory is the important part here.
There was a problem hiding this comment.
--working-directory should be suffice but --config is also useful if user has different config setup. I will --config to be consist with CLI and de-emphasize it in the doc so that user will not be confused. I'll have a separated PR for README.md update soon to reflect this. PR #78
| const options: LoadConfigOptions = { | ||
| instance: this.flags.instance, | ||
| configPath: this.flags.config, |
There was a problem hiding this comment.
Should this be using your new getBaseConfigOptions?
| cloudOrigin: this.flags['cloud-origin'] as string | undefined, // MobifySource uses this to load ~/.mobify--[hostname] if set | ||
| credentialsFile: this.flags['credentials-file'] as string | undefined, // Override path to MRT credentials file |
There was a problem hiding this comment.
Shouldn't these two be part of the extractMrtFlags?
| const pluginSources: PluginSources = { | ||
| before: this.pluginSourcesBefore, | ||
| after: this.pluginSourcesAfter, | ||
| }; |
There was a problem hiding this comment.
Do we have everything to make the mcp server command support our plugins? Reference the b2c-cli package to ensure we do (I believe it'll just work since it's just registering hooks with oclif but want to confirm)
There was a problem hiding this comment.
Also should this be getPluginSources which you added to base command?
There was a problem hiding this comment.
I think MCP should not support plugins to keep it simple since the plugin needs separated installation. I removed it to avoid confusion.
There was a problem hiding this comment.
We definitely DO want MCP to support plugins. Yes they do need to install it (via npx for instance) but it's crucial to support alternative config sources.
It's ok if that's a separate task to get it working.
There was a problem hiding this comment.
I see. I will add a task to support plugin.
Keep refactored loadConfiguration() using extractOAuthFlags helper instead of verbose inline flag extraction from main.
The tenant-id flag was defined in OAuthCommand.baseFlags but not extracted in extractOAuthFlags(), causing SLAS client commands to fail when tenant-id was provided via flags.
clavery
left a comment
There was a problem hiding this comment.
We DO want to support b2c-cli plugins. But it doesn't have to be this PRs job to validate that
Summary
This PR refactors the SDK's flag extraction logic into reusable helpers, enabling consistent configuration handling between CLI commands and the MCP server. Previously, flag-to-config mapping was duplicated across
OAuthCommand,InstanceCommand, andMrtCommand. Now, shared helpers (extractOAuthFlags,extractInstanceFlags,extractMrtFlags) provide a single source of truth that both CLI commands andMcpServerCommanduse.A new
startDiroption was added toLoadConfigOptionsto specify where config file search begins. This is essential for MCP servers since clients (Cursor, Claude Desktop) spawn servers from~rather than the project directory—withoutstartDir,dw.jsondiscovery would fail.Additionally, this PR improves auto-discovery behavior to gracefully handle invalid toolset/tool names by falling back to auto-discovery instead of registering zero tools.
Changes
MCP Server (
packages/b2c-dx-mcp)Registry Improvements (
src/registry.ts)--toolsetsand--tools(not just when no flags are provided)performAutoDiscovery()helper: Reusable function for workspace type detection with loggingstorefront-nextproject type mapping (['STOREFRONTNEXT', 'MRT', 'CARTRIDGES'])registerToolsets(): Removed redundant auto-discovery check, unified into single fallbackAuto-Discovery Behavior
--toolsetsor--toolsprovided--toolsetsinvalid (e.g., typos)--toolsinvalid--toolsetsor--toolsOther Changes
loadConfiguration()override toMcpServerCommandto extract B2C instance and MRT flagstest/registry.test.tsto reflect new auto-discovery behaviorSDK Flag Extraction Refactoring (
packages/b2c-tooling-sdk)Problem
The existing command classes (
OAuthCommand,InstanceCommand,MrtCommand) each contained inline flag-to-config mapping logic. This duplication meant:Solution: Extract Reusable Helpers
Refactored flag extraction into dedicated helper functions in
src/cli/config.ts:extractOAuthFlags()--client-id,--client-secret,--short-code,--auth-methods,--account-manager-host,--scopeextractInstanceFlags()--server,--webdav-server,--code-version,--username,--password+ OAuth flagsextractMrtFlags()--api-key,--project,--environment,--cloud-originChanges
extractOAuthFlags(),extractInstanceFlags(),extractMrtFlags()tosrc/cli/config.tsstartDiroption: AddedstartDirtoLoadConfigOptionsfor specifying the starting directory when searching for config files (e.g.,dw.json). Why needed for MCP: MCP clients (Cursor, Claude Desktop) typically spawn servers from~(home directory) rather than the project directory. WithoutstartDir, config file search starts from~and won't find the project'sdw.json. The--working-directoryflag orSFCC_WORKING_DIRECTORYenv var tells the config loader where to look.getBaseConfigOptions()andgetPluginSources()methods: Added toBaseCommandto centralize common config options. Subclasses spreadthis.getBaseConfigOptions()to automatically inherit base options likestartDir, preventing bugs when new options are added.OAuthCommand,InstanceCommand,MrtCommandto use helpers and spread base optionsMcpServerCommand.loadConfiguration()now uses the same helpers, ensuring consistent flag handlingtest/cli/config.test.tsBenefits
Configuration Priority
B2C Instance
--server,--username,--password, etc.)SFCC_SERVER,SFCC_USERNAME, etc.)MRT
--api-key,--project,--environment)SFCC_MRT_API_KEY,SFCC_MRT_PROJECT, etc.)~/.mobifyfileTest Plan
Toolset Selection Tests (Section 1)
Auto-Discovery Tests (Section 2)
B2C Instance Configuration Tests (Section 3)
--server,--username,--passwordflags work--client-id,--client-secretflags workSFCC_SERVER,SFCC_USERNAME,SFCC_PASSWORDenv vars work--working-directory(testsstartDiroption)MRT Configuration Tests (Section 4)
--project,--environment,--api-keyflags workSFCC_MRT_*env vars workpnpm test)pnpm run format)