Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
4c6475f
use claude
basilkot Jan 16, 2026
4f71c52
create first code
basilkot Jan 19, 2026
a26cfcd
small fixes
basilkot Jan 26, 2026
fe94824
add cancel order operation
basilkot Jan 27, 2026
3aadc12
getCustomers method
basilkot Jan 27, 2026
dc19ea9
implement getProducts method
basilkot Jan 27, 2026
32cf41e
implement getProductVariants method
basilkot Jan 27, 2026
13ec41f
getFulfillments method
basilkot Jan 27, 2026
a88e3cd
implement getInventory method
basilkot Jan 27, 2026
2807001
updateOrder operation
basilkot Jan 30, 2026
f620521
change order statuses
basilkot Jan 31, 2026
feb5427
prepare to npm
basilkot Feb 9, 2026
5bf2e98
create dockerfile which works over http
basilkot Feb 11, 2026
6fbadbc
add ci
basilkot Feb 12, 2026
55faef1
add ci
basilkot Feb 12, 2026
c6e5262
rename artifact
basilkot Feb 12, 2026
0e23bb5
rename image in ci
basilkot Feb 12, 2026
00ec4d6
change exposed port in docker
basilkot Feb 13, 2026
cc8369e
add support for overriding apiKey from environment variable
basilkot Feb 16, 2026
e0acc46
refactor adapter configuration to support overriding options from env…
basilkot Feb 16, 2026
d8767f7
change exposed port from 3000 to 80 in Dockerfile
basilkot Feb 16, 2026
38f0ef6
remove cof user from docker file
basilkot Feb 16, 2026
c6ff049
add SSE headers and keep-alive mechanism to improve connection stability
basilkot Feb 16, 2026
bb0419e
feat: upgrade @modelcontextprotocol/sdk to v1.26.0 and add Streamable…
basilkot Feb 16, 2026
db351c6
refactor: streamline server initialization and handler setup in MCPSe…
basilkot Feb 16, 2026
2458850
fix: update adapter workspace assignment and add debug mode handling
basilkot Feb 16, 2026
5d45d19
fix: enable type coercion in AJV validation configuration
basilkot Feb 16, 2026
b0305c1
fix: mask sensitive values in API request logging
basilkot Feb 17, 2026
c9f75ce
test changes
basilkot Feb 17, 2026
ad14093
update correct api key
basilkot Feb 17, 2026
1d897f8
add log info
basilkot Feb 17, 2026
82f0717
revert changes in server folder
basilkot Feb 19, 2026
eac8365
fix customer search
basilkot Feb 23, 2026
fca985a
fetch catalogId on start
basilkot Feb 23, 2026
2c20d63
small changes
basilkot Feb 23, 2026
9001012
Add catalogId handling to product service and enhance API client logging
basilkot Feb 23, 2026
c194639
get shipments (fulfillments)
basilkot Feb 24, 2026
b99846e
use workspace as storeId in requests
basilkot Feb 24, 2026
d4fee74
Update test prompts with accurate product SKUs and customer references
basilkot Feb 24, 2026
3ddd608
Create order by request through mcp server
basilkot Feb 24, 2026
0137335
Enhance product pricing handling in transformers and models, adding t…
basilkot Feb 25, 2026
f3a9d84
Refactor product variant handling to align with VirtoCommerce API, re…
basilkot Feb 25, 2026
a12fe83
Fix customer schema validation and enhance SKU resolution for order c…
basilkot Feb 25, 2026
acd74ee
Update test prompts for order creation and cancellation, refining cus…
basilkot Feb 26, 2026
a42bc79
create return generated code
basilkot Feb 26, 2026
1a311fc
prepare npm publishing
basilkot Feb 26, 2026
6958ecb
revert virtocommerce/cof-mcp package
basilkot Feb 26, 2026
fc7ae35
remove agent plans
basilkot Feb 26, 2026
395a29b
fix: update log directory resolution to use fileURLToPath for compati…
basilkot Feb 26, 2026
f1fb4e6
fix: use pathToFileURL for dynamic adapter imports on Windows
basilkot Feb 27, 2026
747b238
Merge branch 'commerce-operations-foundation:develop' into develop
basilkot Mar 23, 2026
56f9f05
fix: resolve symlink handling for entry point detection on POSIX systems
basilkot May 13, 2026
76f03a3
Merge branch 'virto' into fix/entrypoint-symlink
basilkot May 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{
"permissions": {
"allow": [
"WebFetch(domain:raw.githubusercontent.com)",
"Bash(npx tsc:*)",
"Bash(npm run build:*)",
"Bash(npm test)",
"Bash(tree:*)",
"Bash(npx jest:*)",
"Bash(dir /s \"e:\\\\Develops\\\\VirtoWay\\\\projects\\\\tasks\\\\4464\\\\mcp-reference-server\\\\virtocommerce-adapter\")",
"Bash(dir /B /S \"e:\\\\Develops\\\\VirtoWay\\\\projects\\\\tasks\\\\4464\\\\mcp-reference-server\\\\virtocommerce-adapter\")",
"Bash(node --experimental-vm-modules node_modules/jest/bin/jest.js:*)",
"Bash(test:*)",
"Bash(npm ls:*)",
"Bash(docker build:*)",
"Bash(docker run:*)",
"Bash(powershell -Command \"Write-Output ''{\"\"jsonrpc\"\":\"\"2.0\"\",\"\"method\"\":\"\"tools/list\"\",\"\"id\"\":1}'' | docker run --rm -i -e ADAPTER_CONFIG=''{}'' cof-mcp-virto\")",
"Bash(powershell -Command \"Write-Output ''{\"\"jsonrpc\"\":\"\"2.0\"\",\"\"method\"\":\"\"tools/list\"\",\"\"id\"\":1}'' | docker run --rm -i -e ADAPTER_CONFIG=''{\"\"apiUrl\"\":\"\"https://host.docker.internal:5001\"\",\"\"apiKey\"\":\"\"76bf85d9-196e-4d4a-a6d7-6765102361c9\"\"}'' -e LOG_LEVEL=debug cof-mcp-virto\")",
"Bash(powershell -Command \"Write-Output ''{\"\"jsonrpc\"\":\"\"2.0\"\",\"\"method\"\":\"\"tools/list\"\",\"\"id\"\":1}'' | docker run --rm -i --env-file ''e:\\\\Develops\\\\VirtoWay\\\\projects\\\\tasks\\\\4464\\\\mcp-reference-server\\\\.env.docker'' cof-mcp-virto\")",
"Bash(npm view:*)",
"Bash(powershell -Command:*)",
"Bash(timeout:*)",
"Bash(curl:*)",
"Bash(docker stop:*)",
"Bash(docker rm:*)",
"Bash(node -e:*)",
"Bash(docker compose up:*)",
"mcp__plugin_serena_serena__find_symbol",
"Bash(npm info:*)",
"Bash(wc:*)",
"mcp__plugin_serena_serena__list_dir",
"mcp__plugin_serena_serena__activate_project",
"mcp__plugin_serena_serena__check_onboarding_performed",
"mcp__plugin_serena_serena__get_symbols_overview",
"mcp__plugin_serena_serena__read_file",
"mcp__plugin_serena_serena__search_for_pattern",
"mcp__plugin_serena_serena__replace_content",
"mcp__plugin_serena_serena__replace_symbol_body",
"Bash(dir:*)",
"Bash(cmd /c:*)",
"Bash(powershell.exe \"Get-ChildItem ''E:\\\\Develops\\\\VirtoWay\\\\projects\\\\tasks\\\\4464\\\\vc-module-order\\\\src'' -Recurse | Select-Object FullName\")",
"Bash(powershell.exe \"Get-ChildItem ''E:\\\\Develops\\\\VirtoWay\\\\projects\\\\tasks\\\\4464\\\\vc-module-order\\\\src'' -Recurse -Filter ''*.cs'' | Where-Object { $_.Name -match ''Order|Controller|Cancel'' } | Select-Object FullName\")",
"Bash(powershell.exe -Command \"Get-ChildItem ''E:\\\\Develops\\\\VirtoWay\\\\projects\\\\tasks\\\\4464\\\\vc-module-order\\\\src'' -Recurse -Filter ''*.cs'' | Select-Object -ExpandProperty FullName\")",
"Bash(powershell.exe -Command \"Get-ChildItem ''E:\\\\Develops\\\\VirtoWay\\\\projects\\\\tasks\\\\4464\\\\vc-module-order\\\\src'' -Recurse -Filter ''*.cs'' | Select-Object -ExpandProperty FullName | Out-String\")",
"Bash(powershell.exe -Command \"Get-ChildItem ''E:\\\\Develops\\\\VirtoWay\\\\projects\\\\tasks\\\\4464\\\\vc-module-order\\\\src'' -Recurse -Filter ''*.cs'' | Select-Object -First 50 -ExpandProperty FullName\")",
"Bash(powershell.exe -Command:*)",
"mcp__plugin_serena_serena__insert_after_symbol",
"mcp__plugin_context7_context7__resolve-library-id",
"mcp__plugin_context7_context7__query-docs",
"Bash(grep:*)",
"Bash(find:*)",
"Bash(head:*)",
"Bash(cd \"e:/Develops/VirtoWay/projects/tasks/4464/mcp-reference-server/server\" && npm run test:unit 2>&1)",
"Bash(sed:*)",
"Bash(npm:*)",
"WebSearch",
"WebFetch(domain:www.npmjs.com)",
"WebFetch(domain:github.com)",
"Bash(mkdir:*)"
]
}
}
150 changes: 150 additions & 0 deletions .github/workflows/mcp-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# v1.0.1
name: MCP Server CI

on:
workflow_dispatch:

jobs:
ci:
runs-on: ubuntu-latest
env:
FORCE_COLOR: true
CLOUD_INSTANCE_BASE_URL: ${{secrets.CLOUD_INSTANCE_BASE_URL}}
CLIENT_ID: ${{secrets.CLIENT_ID}}
CLIENT_SECRET: ${{secrets.CLIENT_SECRET}}
GITHUB_TOKEN: ${{ secrets.REPO_TOKEN }}
BLOB_SAS: ${{ secrets.BLOB_TOKEN }}
VERSION: ''
BUILD_STATE: 'failed'
RELEASE_STATUS: 'false'
DOCKER_REPOSITORY: 'ghcr.io'
DOCKER_IMAGE: 'vc-mcp-onx'
DOCKER_TAG: ''
outputs:
jira-keys: ${{ steps.jira_keys.outputs.jira-keys }}
version: ${{ env.VERSION }}
tag: ${{ env.DOCKER_TAG }}

steps:

- name: Set up Node 22
uses: actions/setup-node@v4
with:
node-version: '22'

- name: Set RELEASE_STATUS
if: ${{ github.ref == 'refs/heads/master' }}
run: echo "RELEASE_STATUS=true" >> $GITHUB_ENV

- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Get version from package.json
id: version
run: |
BASE_VERSION=$(jq -r .version server/package.json)
SHORT_SHA=$(git rev-parse --short HEAD)
echo "base=$BASE_VERSION" >> $GITHUB_OUTPUT
echo "sha=$SHORT_SHA" >> $GITHUB_OUTPUT

- name: Set VERSION
run: |
if [ '${{ github.ref }}' = 'refs/heads/master' ]; then
echo "VERSION=${{ steps.version.outputs.base }}" >> $GITHUB_ENV
else
echo "VERSION=${{ steps.version.outputs.base }}-alpha.${{ github.run_number }}" >> $GITHUB_ENV
fi

- name: Update package.json Version
run: |
npm version ${{ env.VERSION }} --no-git-tag-version --prefix server
npm version ${{ env.VERSION }} --no-git-tag-version --prefix virtocommerce-adapter

- name: Set DOCKER_TAG
run: echo "DOCKER_TAG=${{ env.VERSION }}" >> $GITHUB_ENV

- name: Install and build server
run: cd server && npm ci && npm run build

- name: Install and build adapter
run: cd virtocommerce-adapter && npm ci && npm run build

- name: BUILD_STATE::successful
if: success()
run: echo "BUILD_STATE=successful" >> $GITHUB_ENV

- name: Add files to zip
run: |
mkdir ./artifacts
zip -r ./artifacts/vc-mcp-onx-${{ env.VERSION }}.zip \
server/dist/ server/package.json \
virtocommerce-adapter/dist/ virtocommerce-adapter/package.json \
Dockerfile docker-compose.yml

- name: Publish to Blob
id: blobRelease
uses: VirtoCommerce/vc-github-actions/publish-blob-release@master
with:
blobSAS: ${{ secrets.BLOB_TOKEN }}
blobUrl: ${{ vars.BLOB_URL }}

- name: Set URLs
id: urls
run: |
echo "DOCKER_URL=${{ env.DOCKER_REPOSITORY }}/${GITHUB_REPOSITORY_OWNER,,}/${{ env.DOCKER_IMAGE }}:" >> $GITHUB_OUTPUT
echo "BLOB_URL=${{ steps.blobRelease.outputs.packageUrl }}" >> $GITHUB_OUTPUT

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.DOCKER_REPOSITORY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
push: true
context: .
file: ./Dockerfile
tags: |
${{ steps.urls.outputs.DOCKER_URL }}${{ env.DOCKER_TAG }}
${{ steps.urls.outputs.DOCKER_URL }}${{ github.ref == 'refs/heads/master' && 'latest' || 'dev-latest' }}

- name: Parse Jira Keys from All Commits
uses: VirtoCommerce/vc-github-actions/get-jira-keys@master
if: always()
id: jira_keys
with:
release: ${{ env.RELEASE_STATUS }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Push Build Info to Jira
if: ${{ env.CLOUD_INSTANCE_BASE_URL != 0 && env.CLIENT_ID != 0 && env.CLIENT_SECRET != 0 && steps.jira_keys.outputs.jira-keys != '' && always() }}
id: push_build_info_to_jira
uses: VirtoCommerce/jira-upload-build-info@master
with:
cloud-instance-base-url: '${{ secrets.CLOUD_INSTANCE_BASE_URL }}'
client-id: '${{ secrets.CLIENT_ID }}'
client-secret: '${{ secrets.CLIENT_SECRET }}'
pipeline-id: '${{ github.repository }} ${{ github.workflow }}'
build-number: ${{ github.run_number }}
build-display-name: 'Workflow: ${{ github.workflow }} (#${{ github.run_number }})'
build-state: '${{ env.BUILD_STATE }}'
build-url: '${{github.event.repository.url}}/actions/runs/${{github.run_id}}'
update-sequence-number: '${{ github.run_id }}'
last-updated: '${{github.event.head_commit.timestamp}}'
issue-keys: '${{ steps.jira_keys.outputs.jira-keys }}'
commit-id: '${{ github.sha }}'
repo-url: '${{ github.event.repository.url }}'
build-ref-url: '${{ github.event.repository.url }}/actions/runs/${{ github.run_id }}'

- name: Confirm Jira Build Output
if: success()
run: |
echo "Jira Upload Build Info response: ${{ steps.push_build_info_to_jira.outputs.response }}"
1 change: 1 addition & 0 deletions .serena/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/cache
124 changes: 124 additions & 0 deletions .serena/project.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# the name by which the project can be referenced within Serena
project_name: "mcp-reference-server"


# list of languages for which language servers are started; choose from:
# al bash clojure cpp csharp
# csharp_omnisharp dart elixir elm erlang
# fortran fsharp go groovy haskell
# java julia kotlin lua markdown
# matlab nix pascal perl php
# php_phpactor powershell python python_jedi r
# rego ruby ruby_solargraph rust scala
# swift terraform toml typescript typescript_vts
# vue yaml zig
# (This list may be outdated. For the current list, see values of Language enum here:
# https://github.com/oraios/serena/blob/main/src/solidlsp/ls_config.py
# For some languages, there are alternative language servers, e.g. csharp_omnisharp, ruby_solargraph.)
# Note:
# - For C, use cpp
# - For JavaScript, use typescript
# - For Free Pascal/Lazarus, use pascal
# Special requirements:
# Some languages require additional setup/installations.
# See here for details: https://oraios.github.io/serena/01-about/020_programming-languages.html#language-servers
# When using multiple languages, the first language server that supports a given file will be used for that file.
# The first language is the default language and the respective language server will be used as a fallback.
# Note that when using the JetBrains backend, language servers are not used and this list is correspondingly ignored.
languages:
- typescript

# the encoding used by text files in the project
# For a list of possible encodings, see https://docs.python.org/3.11/library/codecs.html#standard-encodings
encoding: "utf-8"

# whether to use project's .gitignore files to ignore files
ignore_all_files_in_gitignore: true

# list of additional paths to ignore in this project.
# Same syntax as gitignore, so you can use * and **.
# Note: global ignored_paths from serena_config.yml are also applied additively.
ignored_paths: []

# whether the project is in read-only mode
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
# Added on 2025-04-18
read_only: false

# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details.
# Below is the complete list of tools for convenience.
# To make sure you have the latest list of tools, and to view their descriptions,
# execute `uv run scripts/print_tool_overview.py`.
#
# * `activate_project`: Activates a project by name.
# * `check_onboarding_performed`: Checks whether project onboarding was already performed.
# * `create_text_file`: Creates/overwrites a file in the project directory.
# * `delete_lines`: Deletes a range of lines within a file.
# * `delete_memory`: Deletes a memory from Serena's project-specific memory store.
# * `execute_shell_command`: Executes a shell command.
# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced.
# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type).
# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type).
# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
# * `initial_instructions`: Gets the initial instructions for the current project.
# Should only be used in settings where the system prompt cannot be set,
# e.g. in clients you have no control over, like Claude Desktop.
# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
# * `insert_at_line`: Inserts content at a given line in a file.
# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
# * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
# * `list_memories`: Lists memories in Serena's project-specific memory store.
# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context).
# * `read_file`: Reads a file within the project directory.
# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store.
# * `remove_project`: Removes a project from the Serena configuration.
# * `replace_lines`: Replaces a range of lines within a file with new content.
# * `replace_symbol_body`: Replaces the full definition of a symbol.
# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen.
# * `search_for_pattern`: Performs a search for a pattern in the project.
# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase.
# * `switch_modes`: Activates modes by providing a list of their names
# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information.
# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task.
# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed.
# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store.
excluded_tools: []

# list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default)
included_optional_tools: []

# fixed set of tools to use as the base tool set (if non-empty), replacing Serena's default set of tools.
# This cannot be combined with non-empty excluded_tools or included_optional_tools.
fixed_tools: []

# list of mode names to that are always to be included in the set of active modes
# The full set of modes to be activated is base_modes + default_modes.
# If the setting is undefined, the base_modes from the global configuration (serena_config.yml) apply.
# Otherwise, this setting overrides the global configuration.
# Set this to [] to disable base modes for this project.
# Set this to a list of mode names to always include the respective modes for this project.
base_modes:

# list of mode names that are to be activated by default.
# The full set of modes to be activated is base_modes + default_modes.
# If the setting is undefined, the default_modes from the global configuration (serena_config.yml) apply.
# Otherwise, this overrides the setting from the global configuration (serena_config.yml).
# This setting can, in turn, be overridden by CLI parameters (--mode).
default_modes:

# initial prompt for the project. It will always be given to the LLM upon activating the project
# (contrary to the memories, which are loaded on demand).
initial_prompt: ""

# override of the corresponding setting in serena_config.yml, see the documentation there.
# If null or missing, the value from the global config is used.
symbol_info_budget:

# The language backend to use for this project.
# If not set, the global setting from serena_config.yml is used.
# Valid values: LSP, JetBrains
# Note: the backend is fixed at startup. If a project with a different backend
# is activated post-init, an error will be returned.
language_backend:
32 changes: 26 additions & 6 deletions server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
* Entry point using MCP SDK components
*/

import { fileURLToPath } from 'url';
import { realpathSync } from 'fs';
import { pathToFileURL } from 'url';

import { ConfigManager } from './config/config-manager.js';
import { MCPServerSDK } from './server.js';
Expand Down Expand Up @@ -57,12 +58,31 @@ async function main() {
}
}

// Run if this is the main module
// ES modules use import.meta.url
const __filename = fileURLToPath(import.meta.url);
/**
* Detect whether this module is the process entry point.
*
* `process.argv[1]` holds the path Node was invoked with. When the package is
* installed via npm/npx, the `bin` entry is exposed as a symlink (for example
* `node_modules/.bin/cof-mcp -> ../@virtocommerce/cof-mcp/dist/index.js`), so a
* direct string comparison against `import.meta.url` fails on POSIX systems
* and `main()` is silently skipped — the process exits with code 0 and no
* output, which is what causes the server to "start and immediately disconnect"
* under Claude Desktop on macOS/Linux.
*
* Resolving symlinks with `fs.realpathSync` and comparing canonical file URLs
* makes the check correct on macOS, Linux, and Windows.
*/
function isMainModule(): boolean {
const invokedPath = process.argv[1];
if (!invokedPath) return false;
try {
return pathToFileURL(realpathSync(invokedPath)).href === import.meta.url;
} catch {
return false;
}
}

// Check if this file was run directly
if (process.argv[1] === __filename) {
if (isMainModule()) {
main();
}

Expand Down
Loading
Loading