mcp-server-sfmc 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -29,9 +29,14 @@ You **do not** have to install the VS Code extension. Pick one way to run the se
29
29
  | **`npx` (no install)** | Default in the examples below. Runs the latest published version from npm on demand; first run may download the package. **Requires Node.js and npm** (which provides `npx`). |
30
30
  | **`npm install -g mcp-server-sfmc`** | Same CLI as `npx`, but the package stays on disk so **startup is faster** and you can set `"command": "mcp-server-sfmc"` with empty `args` in your MCP config. |
31
31
  | **`npm install mcp-server-sfmc` in a project** | Keeps a **pinned version** in that folder’s `node_modules` — point your MCP config at `npx mcp-server-sfmc` with `cwd` set to the project, or run `./node_modules/.bin/mcp-server-sfmc` directly. |
32
+ | **`sfmc-review-diff` (bundled CLI)** | For **CI**: spawns this MCP server, calls `review_change` on a unified diff (stdin or file), exits non-zero on `ERROR` by default. Install the package in the job, then e.g. `git diff base...HEAD \| npx sfmc-review-diff`. |
32
33
 
33
34
  None of these replace the VS Code extension for **editing** (syntax, LSP, snippets); they only expose the **MCP server** to tools that speak the Model Context Protocol.
34
35
 
36
+ ## CI templates and `sfmc-review-diff`
37
+
38
+ Ready-to-copy workflows (GitHub Actions, GitLab CI, Jenkins, Azure Pipelines, Bitbucket Pipelines) live under **[`ci-templates/`](./ci-templates/)**. They run **`eslint-plugin-sfmc`** on changed files and **`sfmc-review-diff`** on the PR/MR unified diff. See **[`ci-templates/README.md`](./ci-templates/README.md)** for what each file does and how the two checks differ.
39
+
35
40
  ## What it gives your AI assistant
36
41
 
37
42
  | Feature | Details |
@@ -45,7 +50,7 @@ None of these replace the VS Code extension for **editing** (syntax, LSP, snippe
45
50
  | **Resources** | Full function catalogs, keyword list, unsupported ES6+ syntax list |
46
51
  | **MCE help search** | Bundled excerpts from mirrored Salesforce Help (MCE vs Next scoped) |
47
52
 
48
- ## Quick start
53
+ ## Connecting AI clients
49
54
 
50
55
  ### VS Code (1.99+) + GitHub Copilot — manual `mcp.json`
51
56
 
@@ -0,0 +1,71 @@
1
+ // Jenkins pipeline — SFMC Code Quality
2
+ // Runs eslint-plugin-sfmc on changed AMPscript and SSJS files in a pull request.
3
+ //
4
+ // Prerequisites:
5
+ // - Node.js 20+ installed on the agent (or use the 'nodejs' tool in Jenkins config)
6
+ // - "GitHub Pull Request Builder" or "Bitbucket Branch Source" plugin for PR detection
7
+
8
+ pipeline {
9
+ agent any
10
+
11
+ tools {
12
+ nodejs 'node-20' // matches the name in Manage Jenkins > Global Tool Configuration
13
+ }
14
+
15
+ triggers {
16
+ // GitHub Pull Request Builder plugin trigger (adjust as needed for your SCM)
17
+ githubPush()
18
+ }
19
+
20
+ stages {
21
+ stage('Lint SFMC') {
22
+ when {
23
+ changeRequest() // only run on PRs/MRs
24
+ }
25
+ steps {
26
+ script {
27
+ // Install linter
28
+ sh 'npm install --no-save eslint eslint-plugin-sfmc'
29
+
30
+ // Write minimal config
31
+ writeFile file: 'eslint.config.mjs', text: '''
32
+ import sfmc from 'eslint-plugin-sfmc';
33
+ export default [...sfmc.configs.recommended];
34
+ '''
35
+
36
+ // Determine changed files (adjust base-branch detection as needed)
37
+ def changedFiles = sh(
38
+ script: "git diff --name-only origin/${env.CHANGE_TARGET}...HEAD | grep -E '\\.(amp|ampscript|ssjs|html)$' || true",
39
+ returnStdout: true
40
+ ).trim()
41
+
42
+ if (changedFiles) {
43
+ echo "Linting SFMC files:\n${changedFiles}"
44
+ sh "npx eslint --format stylish ${changedFiles}"
45
+ } else {
46
+ echo "No SFMC files changed — skipping lint."
47
+ }
48
+ }
49
+ }
50
+ post {
51
+ failure {
52
+ // Optionally post a comment using the GitHub plugin
53
+ echo 'SFMC lint failed. See build log for details.'
54
+ }
55
+ }
56
+ }
57
+
58
+ stage('MCP diff review') {
59
+ when {
60
+ changeRequest()
61
+ }
62
+ steps {
63
+ script {
64
+ sh 'npm install --no-save mcp-server-sfmc@latest'
65
+ sh 'git fetch origin +refs/heads/$CHANGE_TARGET:refs/remotes/origin/$CHANGE_TARGET --depth=500 || true'
66
+ sh 'git diff origin/$CHANGE_TARGET...HEAD | npx sfmc-review-diff'
67
+ }
68
+ }
69
+ }
70
+ }
71
+ }
@@ -0,0 +1,36 @@
1
+ # CI templates for SFMC projects
2
+
3
+ Copy these files into your own repository and adjust branch names, Node version, or path filters as needed.
4
+
5
+ ## Two complementary checks
6
+
7
+ | Mechanism | What it does |
8
+ |-----------|----------------|
9
+ | **ESLint** (`eslint-plugin-sfmc`) | Lints **changed files** matching `*.amp`, `*.ssjs`, `*.html` (and embedded rules for HTML). File-level rules (unknown functions, arity, ES6 in SSJS, etc.). |
10
+ | **`sfmc-review-diff`** (this package, CLI) | Pipes a **unified `git diff`** into the MCP tool `review_change`, which validates **only added lines** using the same language catalog as the MCP server. Fails the job on `ERROR` diagnostics by default (`--fail-on` can include warnings or infos). |
11
+
12
+ You can keep **both** jobs in CI, or drop one if you only want file-based linting or only diff-based review.
13
+
14
+ **Git history:** shallow clones often lack the merge base. Prefer `fetch-depth: 0` (GitHub Actions), `GIT_DEPTH: "0"` (GitLab merge request pipelines), or enough depth that your diff command’s base ref/SHA exists.
15
+
16
+ ## Files in this folder
17
+
18
+ | File | Platform | ESLint | `sfmc-review-diff` |
19
+ |------|----------|--------|----------------------|
20
+ | [github-action.yml](./github-action.yml) | GitHub Actions | yes | yes |
21
+ | [gitlab-ci.yml](./gitlab-ci.yml) | GitLab CI | yes | yes |
22
+ | [Jenkinsfile](./Jenkinsfile) | Jenkins | yes | yes |
23
+ | [azure-pipelines.yml](./azure-pipelines.yml) | Azure Pipelines | yes | yes |
24
+ | [bitbucket-pipelines.yml](./bitbucket-pipelines.yml) | Bitbucket Pipelines | yes | yes |
25
+ | [eslint.config.mjs](./eslint.config.mjs) | (reference) | shared flat config | — |
26
+
27
+ ## AI review instructions (not CI)
28
+
29
+ These files guide **GitLab Duo** / **GitHub Copilot** style review text; they do **not** run `sfmc-review-diff`:
30
+
31
+ - [gitlab-duo-review-instructions.md](./gitlab-duo-review-instructions.md) — place content in `.gitlab/duo/mr-review-instructions.yaml` per GitLab docs (YAML format), not as a raw paste of this file.
32
+ - [github-copilot-review-instructions.md](./github-copilot-review-instructions.md) — Copilot / agent instructions; MCP blocks belong in client config, not in Actions YAML.
33
+
34
+ ## Installing the CLI in CI
35
+
36
+ Templates use `npm install --no-save mcp-server-sfmc@latest` so the `sfmc-review-diff` binary is available. Pin a semver range in your project if you need reproducible builds.
@@ -0,0 +1,64 @@
1
+ # Azure DevOps Pipelines — SFMC Code Quality
2
+ # Runs eslint-plugin-sfmc on changed AMPscript and SSJS files in pull requests.
3
+ #
4
+ # Add to your repository as azure-pipelines.yml and enable in Azure DevOps Pipelines.
5
+
6
+ trigger: none # only run on PRs, not pushes
7
+
8
+ pr:
9
+ branches:
10
+ include:
11
+ - main
12
+ - master
13
+ - develop
14
+ paths:
15
+ include:
16
+ - "**/*.amp"
17
+ - "**/*.ampscript"
18
+ - "**/*.ssjs"
19
+ - "**/*.html"
20
+
21
+ pool:
22
+ vmImage: "ubuntu-latest"
23
+
24
+ steps:
25
+ - task: NodeTool@0
26
+ inputs:
27
+ versionSpec: "20.x"
28
+ displayName: "Install Node.js 20"
29
+
30
+ - script: npm install --no-save eslint eslint-plugin-sfmc
31
+ displayName: "Install eslint-plugin-sfmc"
32
+
33
+ - script: |
34
+ cat > eslint.config.mjs << 'EOF'
35
+ import sfmc from 'eslint-plugin-sfmc';
36
+ export default [...sfmc.configs.recommended];
37
+ EOF
38
+ displayName: "Create ESLint config"
39
+
40
+ - script: |
41
+ git fetch origin $(System.PullRequest.TargetBranch) --depth=1
42
+ CHANGED=$(git diff --name-only origin/$(System.PullRequest.TargetBranch)...HEAD \
43
+ | grep -E '\.(amp|ampscript|ssjs|html)$' || true)
44
+
45
+ if [ -z "$CHANGED" ]; then
46
+ echo "No SFMC files changed — skipping lint."
47
+ exit 0
48
+ fi
49
+
50
+ echo "Linting SFMC files:"
51
+ echo "$CHANGED"
52
+ npx eslint --format stylish $CHANGED
53
+ displayName: "Run SFMC lint"
54
+ failOnStderr: false
55
+
56
+ - script: npm install --no-save mcp-server-sfmc@latest
57
+ displayName: "Install mcp-server-sfmc (sfmc-review-diff)"
58
+
59
+ - script: |
60
+ set -e
61
+ git fetch origin "$(System.PullRequest.TargetBranch)" --unshallow 2>/dev/null || git fetch origin "$(System.PullRequest.TargetBranch)" --depth=500
62
+ git diff "origin/$(System.PullRequest.TargetBranch)...HEAD" | npx sfmc-review-diff
63
+ displayName: "MCP diff review (sfmc-review-diff)"
64
+ failOnStderr: false
@@ -0,0 +1,57 @@
1
+ # Bitbucket Pipelines — SFMC Code Quality
2
+ # Runs eslint-plugin-sfmc on changed AMPscript and SSJS files in pull requests.
3
+ #
4
+ # Add to your repository as bitbucket-pipelines.yml (or merge into your existing one).
5
+
6
+ image: node:20-alpine
7
+
8
+ definitions:
9
+ steps:
10
+ - step: &sfmc-lint
11
+ name: Lint AMPscript & SSJS
12
+ script:
13
+ - npm install --no-save eslint eslint-plugin-sfmc
14
+ - |
15
+ cat > eslint.config.mjs << 'EOF'
16
+ import sfmc from 'eslint-plugin-sfmc';
17
+ export default [...sfmc.configs.recommended];
18
+ EOF
19
+ - |
20
+ # Bitbucket provides BITBUCKET_PR_DESTINATION_BRANCH for PR builds
21
+ if [ -n "$BITBUCKET_PR_DESTINATION_BRANCH" ]; then
22
+ git fetch origin "$BITBUCKET_PR_DESTINATION_BRANCH" --depth=1
23
+ CHANGED=$(git diff --name-only "origin/$BITBUCKET_PR_DESTINATION_BRANCH"...HEAD \
24
+ | grep -E '\.(amp|ampscript|ssjs|html)$' || true)
25
+ else
26
+ # Fallback: lint all SFMC files
27
+ CHANGED=$(find . -type f \( -name '*.amp' -o -name '*.ampscript' -o -name '*.ssjs' \) | head -50)
28
+ fi
29
+
30
+ if [ -z "$CHANGED" ]; then
31
+ echo "No SFMC files to lint."
32
+ exit 0
33
+ fi
34
+
35
+ echo "Linting:"
36
+ echo "$CHANGED"
37
+ npx eslint --format stylish $CHANGED
38
+
39
+ - step: &sfmc-review-diff
40
+ name: MCP diff review (sfmc-review-diff)
41
+ script:
42
+ - npm install --no-save mcp-server-sfmc@latest
43
+ - |
44
+ if [ -n "$BITBUCKET_PR_DESTINATION_BRANCH" ]; then
45
+ git fetch origin "$BITBUCKET_PR_DESTINATION_BRANCH" --depth=500
46
+ git diff "origin/$BITBUCKET_PR_DESTINATION_BRANCH"...HEAD | npx sfmc-review-diff
47
+ else
48
+ echo "Not a PR build — skipping sfmc-review-diff."
49
+ exit 0
50
+ fi
51
+
52
+ pipelines:
53
+ pull-requests:
54
+ "**":
55
+ - parallel:
56
+ - step: *sfmc-lint
57
+ - step: *sfmc-review-diff
@@ -0,0 +1,25 @@
1
+ /**
2
+ * eslint.config.mjs — SFMC project ESLint configuration
3
+ *
4
+ * Copy this file to your project root to enable eslint-plugin-sfmc rules
5
+ * for AMPscript (.amp, .ampscript) and SSJS (.ssjs) files.
6
+ *
7
+ * Usage:
8
+ * npm install --save-dev eslint eslint-plugin-sfmc
9
+ * npx eslint .
10
+ */
11
+
12
+ import sfmc from 'eslint-plugin-sfmc';
13
+
14
+ export default [
15
+ // eslint-plugin-sfmc recommended rules for .amp, .ampscript, .ssjs, and .html files
16
+ ...sfmc.configs.recommended,
17
+
18
+ // Optional: customise rules for your project
19
+ {
20
+ rules: {
21
+ // Increase the maximum number of problems reported per file
22
+ // 'sfmc/max-problems': ['warn', { max: 200 }],
23
+ },
24
+ },
25
+ ];
@@ -0,0 +1,109 @@
1
+ # place this file in .github/workflows
2
+ name: SFMC Code Quality
3
+
4
+ on:
5
+ pull_request:
6
+ paths:
7
+ - "**/*.amp"
8
+ - "**/*.ampscript"
9
+ - "**/*.ssjs"
10
+ - "**/*.html"
11
+
12
+ jobs:
13
+ lint-sfmc:
14
+ name: Lint AMPscript & SSJS
15
+ runs-on: ubuntu-latest
16
+ permissions:
17
+ contents: read
18
+ pull-requests: write
19
+
20
+ steps:
21
+ - name: Checkout
22
+ uses: actions/checkout@v4
23
+
24
+ - name: Set up Node.js
25
+ uses: actions/setup-node@v4
26
+ with:
27
+ node-version: "20"
28
+
29
+ - name: Install eslint-plugin-sfmc
30
+ run: npm install --no-save eslint eslint-plugin-sfmc
31
+
32
+ - name: Create ESLint config
33
+ run: |
34
+ cat > eslint.config.mjs << 'EOF'
35
+ import sfmc from 'eslint-plugin-sfmc';
36
+ export default [
37
+ ...sfmc.configs.recommended,
38
+ ];
39
+ EOF
40
+
41
+ - name: Run ESLint on changed files
42
+ id: lint
43
+ run: |
44
+ # Get changed files
45
+ git fetch origin ${{ github.base_ref }} --depth=1
46
+ CHANGED=$(git diff --name-only origin/${{ github.base_ref }}...HEAD \
47
+ | grep -E '\.(amp|ampscript|ssjs|html)$' || true)
48
+
49
+ if [ -z "$CHANGED" ]; then
50
+ echo "No SFMC files changed."
51
+ echo "result=pass" >> "$GITHUB_OUTPUT"
52
+ exit 0
53
+ fi
54
+
55
+ echo "Linting files:"
56
+ echo "$CHANGED"
57
+
58
+ # Run eslint and capture output
59
+ OUTPUT=$(npx eslint --format stylish $CHANGED 2>&1 || true)
60
+ echo "$OUTPUT"
61
+
62
+ if echo "$OUTPUT" | grep -q "error"; then
63
+ echo "result=fail" >> "$GITHUB_OUTPUT"
64
+ echo "lint_output<<EOF" >> "$GITHUB_OUTPUT"
65
+ echo "$OUTPUT" >> "$GITHUB_OUTPUT"
66
+ echo "EOF" >> "$GITHUB_OUTPUT"
67
+ else
68
+ echo "result=pass" >> "$GITHUB_OUTPUT"
69
+ fi
70
+
71
+ - name: Comment on PR
72
+ if: steps.lint.outputs.result == 'fail'
73
+ uses: actions/github-script@v7
74
+ with:
75
+ script: |
76
+ const output = `${{ steps.lint.outputs.lint_output }}`;
77
+ await github.rest.issues.createComment({
78
+ issue_number: context.issue.number,
79
+ owner: context.repo.owner,
80
+ repo: context.repo.repo,
81
+ body: `## SFMC Lint Results\n\n\`\`\`\n${output}\n\`\`\`\n\n> Run by [SFMC Code Quality workflow](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})`
82
+ });
83
+
84
+ - name: Fail if errors found
85
+ if: steps.lint.outputs.result == 'fail'
86
+ run: exit 1
87
+
88
+ review-diff-sfmc:
89
+ name: MCP diff review (sfmc-review-diff)
90
+ runs-on: ubuntu-latest
91
+ permissions:
92
+ contents: read
93
+ steps:
94
+ - name: Checkout
95
+ uses: actions/checkout@v4
96
+ with:
97
+ fetch-depth: 0
98
+
99
+ - name: Set up Node.js
100
+ uses: actions/setup-node@v4
101
+ with:
102
+ node-version: "20"
103
+
104
+ - name: Install mcp-server-sfmc
105
+ run: npm install --no-save mcp-server-sfmc@latest
106
+
107
+ - name: review_change on PR unified diff
108
+ run: |
109
+ git diff "${{ github.event.pull_request.base.sha }}...${{ github.event.pull_request.head.sha }}" | npx sfmc-review-diff
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: sfmc-reviewer
3
+ description: >
4
+ SFMC code quality specialist. Reviews AMPscript, SSJS, and HTML containing
5
+ SFMC-specific syntax. Validates language correctness, catches common mistakes,
6
+ and suggests idiomatic fixes — all grounded in the SFMC language catalog via
7
+ the mcp-server-sfmc MCP tools.
8
+ tools:
9
+ - read_file
10
+ - create_file
11
+ - replace_string_in_file
12
+ - sfmc/validate_ampscript
13
+ - sfmc/validate_ssjs
14
+ - sfmc/validate_sfmc_html
15
+ - sfmc/lookup_ampscript_function
16
+ - sfmc/lookup_ssjs_function
17
+ - sfmc/review_change
18
+ - sfmc/suggest_fix
19
+ - sfmc/get_ampscript_completions
20
+ - sfmc/get_ssjs_completions
21
+ mcp-servers:
22
+ sfmc:
23
+ type: stdio
24
+ command: npx
25
+ args:
26
+ - "-y"
27
+ - "mcp-server-sfmc@latest"
28
+ ---
29
+
30
+ # instructions for human
31
+ Place this content in `.github/agents/sfmc-reviewer.agent.md` in your repository.
32
+ GitLab Duo Code Review will use these instructions when reviewing merge requests.
33
+
34
+ # instructions for AI
35
+ You are an expert Salesforce Marketing Cloud (SFMC) developer and code reviewer.
36
+
37
+ ## Your responsibilities
38
+
39
+ - Review AMPscript, SSJS, and SFMC HTML code for correctness and best practices.
40
+ - Use `validate_ampscript`, `validate_ssjs`, or `validate_sfmc_html` to find real errors — never guess.
41
+ - Use `lookup_ampscript_function` and `lookup_ssjs_function` to verify function signatures and parameter counts before commenting on them.
42
+ - Use `suggest_fix` to generate concrete, compilable corrections for every issue you raise.
43
+ - Use `review_change` when reviewing diffs rather than full files.
44
+
45
+ ## Language rules to enforce
46
+
47
+ ### AMPscript
48
+ - Delimiters: `%%[ ]%%` for blocks, `%%= =%%` for inline output.
49
+ - Keywords (SET, VAR, IF, ELSEIF, ELSE, ENDIF, FOR, NEXT, OUTPUT) must be uppercase.
50
+ - Variables start with `@`. Example: `SET @myVar = "value"`.
51
+ - Comments: `/* block comment */` only — never `//` or `<!-- -->`.
52
+ - No ES6+ syntax (this is NOT JavaScript).
53
+ - All function names are case-insensitive (PascalCase by convention).
54
+
55
+ ### SSJS
56
+ - ES5 engine only: use `var`, never `let`/`const`.
57
+ - No arrow functions, template literals, destructuring, Promises, or `class`.
58
+ - Wrap code in `<script runat="server">` ... `</script>`.
59
+ - Call `Platform.Load("core", "1.1.5");` before using Core library objects (DataExtension, Rows, etc.).
60
+ - Use `Platform.Function.*` for SFMC-specific APIs.
61
+ - Use `new WSProxy()` for SOAP API calls.
62
+ - Handle WSProxy errors by checking `response.Status`.
63
+
64
+ ## Review format
65
+
66
+ For each issue found:
67
+ 1. State the line number and the exact problem.
68
+ 2. Quote the problematic code.
69
+ 3. Provide the corrected code.
70
+ 4. Explain why the original is wrong (one sentence).
71
+
72
+ End with a brief summary: total issues by severity, and whether the code is safe to merge.
@@ -0,0 +1,49 @@
1
+ # GitLab CI — SFMC Code Quality
2
+ #
3
+ # Runs eslint-plugin-sfmc on every merge request that touches AMPscript or SSJS files.
4
+ # Add this to your .gitlab-ci.yml or include it via:
5
+ #
6
+ # include:
7
+ # - remote: 'https://raw.githubusercontent.com/JoernBerkefeld/mcp-server-sfmc/main/ci-templates/gitlab-ci.yml'
8
+
9
+ stages:
10
+ - lint
11
+
12
+ sfmc-lint:
13
+ stage: lint
14
+ image: node:20-alpine
15
+ rules:
16
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
17
+ changes:
18
+ - "**/*.amp"
19
+ - "**/*.ampscript"
20
+ - "**/*.ssjs"
21
+ - "**/*.html"
22
+ script:
23
+ - npm install --no-save eslint eslint-plugin-sfmc
24
+ - |
25
+ cat > eslint.config.mjs << 'EOF'
26
+ import sfmc from 'eslint-plugin-sfmc';
27
+ export default [...sfmc.configs.recommended];
28
+ EOF
29
+ - |
30
+ CHANGED=$(git diff --name-only origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME...HEAD \
31
+ | grep -E '\.(amp|ampscript|ssjs|html)$' || true)
32
+ if [ -z "$CHANGED" ]; then
33
+ echo "No SFMC files changed — skipping lint."
34
+ exit 0
35
+ fi
36
+ npx eslint --format stylish $CHANGED
37
+ allow_failure: false
38
+
39
+ sfmc-review-diff:
40
+ stage: lint
41
+ image: node:20-alpine
42
+ variables:
43
+ GIT_DEPTH: "0"
44
+ rules:
45
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
46
+ script:
47
+ - npm install --no-save mcp-server-sfmc@latest
48
+ - git diff "$CI_MERGE_REQUEST_DIFF_BASE_SHA...HEAD" | npx sfmc-review-diff
49
+ allow_failure: false
@@ -0,0 +1,36 @@
1
+ # GitLab Duo — SFMC Code Review Instructions
2
+
3
+ Place this content in `.gitlab/duo-instructions.md` in your repository.
4
+ GitLab Duo Code Review will use these instructions when reviewing merge requests.
5
+
6
+ ---
7
+
8
+ This repository contains Salesforce Marketing Cloud (SFMC) code.
9
+ Apply the following rules when reviewing merge requests that contain AMPscript, SSJS, or HTML files.
10
+
11
+ ## AMPscript rules
12
+
13
+ - Block delimiters must balance: every `%%[` requires a matching `]%%`, every `%%=` requires `=%%`.
14
+ - Control flow must balance: every `IF` requires `ENDIF`, every `FOR` requires `NEXT`.
15
+ - Keywords must be uppercase: `SET`, `VAR`, `IF`, `ELSEIF`, `ELSE`, `ENDIF`, `FOR`, `TO`, `NEXT`, `OUTPUT`.
16
+ - Variables must start with `@`. Example: `SET @name = "value"`.
17
+ - Comments must use `/* */`. Flag `//` and `<!-- -->` inside AMPscript blocks as errors.
18
+ - Flag any function name that does not match the AMPscript function catalog.
19
+ - Flag arity mismatches (too few or too many arguments for known functions).
20
+
21
+ ## SSJS rules
22
+
23
+ - SSJS runs on an ES5 engine. Flag `let`, `const`, arrow functions, template literals, and `class`.
24
+ - Flag missing `Platform.Load("core", "1.1.5")` when Core library objects (DataExtension, Rows, etc.) are used.
25
+ - Verify WSProxy error handling: flag any `WSProxy` call without a `Status` check on the response.
26
+ - Flag `console.log` — use `Platform.Response.Write()` or `Write()` instead.
27
+
28
+ ## Review format
29
+
30
+ For each issue:
31
+ 1. Provide the line number.
32
+ 2. Quote the exact problematic code.
33
+ 3. Explain why it is wrong.
34
+ 4. Provide the corrected version.
35
+
36
+ End with a one-line verdict: APPROVE, REQUEST CHANGES, or COMMENT.
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * sfmc-review-diff — CI helper: spawn mcp-server-sfmc and call review_change on a unified diff.
4
+ */
5
+ export type FailOnLevel = 'error' | 'warning' | 'info';
6
+ export interface SeverityCounts {
7
+ errors: number;
8
+ warnings: number;
9
+ infos: number;
10
+ }
11
+ /**
12
+ * Counts diagnostic lines emitted by the review_change tool (see src/index.ts).
13
+ * @param output
14
+ */
15
+ export declare function countReviewSeverities(output: string): SeverityCounts;
16
+ /**
17
+ * Whether the CLI should exit with code 1 given counts and --fail-on policy.
18
+ * @param counts
19
+ * @param failOn
20
+ */
21
+ export declare function shouldFail(counts: SeverityCounts, failOn: FailOnLevel): boolean;
22
+ //# sourceMappingURL=reviewDiff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reviewDiff.d.ts","sourceRoot":"","sources":["../../src/cli/reviewDiff.ts"],"names":[],"mappings":";AACA;;GAEG;AAUH,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc,CAUpE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAK/E"}