mcp-server-sfmc 0.1.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 ADDED
@@ -0,0 +1,234 @@
1
+ # mcp-server-sfmc
2
+
3
+ MCP server providing Salesforce Marketing Cloud language intelligence — AMPscript, SSJS, and GTL — as Model Context Protocol tools, resources, and prompts for AI-assisted development and code review.
4
+
5
+ Built on [sfmc-language-lsp](https://github.com/JoernBerkefeld/sfmc-language-lsp), the same engine that powers the [SFMC Language Service VS Code extension](https://marketplace.visualstudio.com/items?itemName=joernberkefeld.sfmc-language).
6
+
7
+ ## What it gives your AI assistant
8
+
9
+ | Feature | Details |
10
+ |---|---|
11
+ | **Validation** | Syntax errors, unknown functions, arity mismatches, unsupported SSJS syntax |
12
+ | **Lookup** | Full function signatures, parameters, return types, and examples from the SFMC catalog |
13
+ | **PR review** | Diff-aware review tool that surfaces issues in the exact lines that changed |
14
+ | **Fix suggestions** | Concrete, compilable replacement code for each detected issue |
15
+ | **Completions** | AMPscript function/keyword completions, SSJS Platform API catalog |
16
+ | **Prompts** | Guided prompts for writing AMPscript, SSJS, reviewing code, and converting between the two |
17
+ | **Resources** | Full function catalogs, keyword list, unsupported ES6+ syntax list |
18
+
19
+ ## Quick start
20
+
21
+ ### VS Code (1.99+) + GitHub Copilot
22
+
23
+ Add a `.vscode/mcp.json` file to your project (or copy it from this repo):
24
+
25
+ ```json
26
+ {
27
+ "servers": {
28
+ "sfmc": {
29
+ "type": "stdio",
30
+ "command": "npx",
31
+ "args": ["-y", "mcp-server-sfmc@latest"]
32
+ }
33
+ }
34
+ }
35
+ ```
36
+
37
+ Open the file in VS Code — a **Start** button appears at the top. Click it to launch the server. Open GitHub Copilot Chat in **Agent mode** and the SFMC tools appear automatically.
38
+
39
+ ### Cursor
40
+
41
+ Add to your Cursor settings (`~/.cursor/mcp.json` or project-level `.cursor/mcp.json`):
42
+
43
+ ```json
44
+ {
45
+ "mcpServers": {
46
+ "sfmc": {
47
+ "command": "npx",
48
+ "args": ["-y", "mcp-server-sfmc@latest"]
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
54
+ Restart Cursor. The tools are available in Agent mode.
55
+
56
+ ### Claude Desktop
57
+
58
+ Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
59
+
60
+ ```json
61
+ {
62
+ "mcpServers": {
63
+ "sfmc": {
64
+ "command": "npx",
65
+ "args": ["-y", "mcp-server-sfmc@latest"]
66
+ }
67
+ }
68
+ }
69
+ ```
70
+
71
+ Restart Claude Desktop.
72
+
73
+ ### Windsurf
74
+
75
+ Add to your Windsurf MCP settings (`~/.codeium/windsurf/mcp_config.json`):
76
+
77
+ ```json
78
+ {
79
+ "mcpServers": {
80
+ "sfmc": {
81
+ "command": "npx",
82
+ "args": ["-y", "mcp-server-sfmc@latest"]
83
+ }
84
+ }
85
+ }
86
+ ```
87
+
88
+ ### Local install (faster startup than npx)
89
+
90
+ ```bash
91
+ npm install -g mcp-server-sfmc
92
+ ```
93
+
94
+ Then replace `"command": "npx", "args": ["-y", "mcp-server-sfmc@latest"]` with:
95
+
96
+ ```json
97
+ "command": "mcp-server-sfmc",
98
+ "args": []
99
+ ```
100
+
101
+ ## Tools
102
+
103
+ | Tool | Description |
104
+ |---|---|
105
+ | `validate_ampscript` | Validate AMPscript code — unknown functions, arity, delimiter balance, comment syntax |
106
+ | `validate_ssjs` | Validate SSJS — ES6+ usage, missing Platform.Load, wrong API calls |
107
+ | `validate_sfmc_html` | Validate HTML with embedded AMPscript, SSJS, and GTL blocks |
108
+ | `lookup_ampscript_function` | Full signature, parameters, and example for any AMPscript function |
109
+ | `lookup_ssjs_function` | Full signature and description for any SSJS Platform function or method |
110
+ | `review_change` | Review a unified diff — validates only added lines, maps back to diff line numbers |
111
+ | `suggest_fix` | Generate fix suggestions for each diagnostic in a code snippet |
112
+ | `get_ampscript_completions` | List valid completions at a given cursor position in AMPscript |
113
+ | `get_ssjs_completions` | List SSJS Platform API completions, optionally filtered by prefix |
114
+ | `format_sfmc_code` | Apply basic formatting conventions (keyword casing, quote normalisation) |
115
+
116
+ ## Resources
117
+
118
+ | URI | Description |
119
+ |---|---|
120
+ | `sfmc://ampscript/functions` | Full AMPscript function catalog with signatures |
121
+ | `sfmc://ssjs/functions` | Full SSJS function catalog |
122
+ | `sfmc://ampscript/keywords` | All AMPscript keywords |
123
+ | `sfmc://ssjs/unsupported-syntax` | ES6+ features not supported in SFMC SSJS |
124
+
125
+ ## Prompts
126
+
127
+ Access via `/mcp.sfmc.writeAmpscript` etc. in VS Code, or via the prompts API:
128
+
129
+ | Prompt | Description |
130
+ |---|---|
131
+ | `writeAmpscript` | Generate AMPscript code for a described task |
132
+ | `writeSsjs` | Generate SSJS code for a described task |
133
+ | `reviewSfmcCode` | Review AMPscript or SSJS code for bugs and best-practice violations |
134
+ | `convertAmpscriptToSsjs` | Convert AMPscript code to equivalent SSJS |
135
+
136
+ ## AI code review in pull requests
137
+
138
+ ### GitHub Copilot (cloud agent)
139
+
140
+ The `.github/agents/sfmc-reviewer.agent.md` custom agent in this repository configures a GitHub Copilot cloud agent that uses `mcp-server-sfmc` for SFMC-aware PR reviews.
141
+
142
+ To enable it in your own repository:
143
+ 1. Copy `.github/agents/sfmc-reviewer.agent.md` to your repo.
144
+ 2. In your GitHub repo settings → **Copilot → Cloud agent → MCP configuration**, add:
145
+
146
+ ```json
147
+ {
148
+ "mcpServers": {
149
+ "sfmc": {
150
+ "type": "stdio",
151
+ "command": "npx",
152
+ "args": ["-y", "mcp-server-sfmc@latest"],
153
+ "tools": ["*"]
154
+ }
155
+ }
156
+ }
157
+ ```
158
+
159
+ 3. Assign the `sfmc-reviewer` agent to a pull request by mentioning it in a comment or via the **@sfmc-reviewer** agent in GitHub Copilot Chat.
160
+
161
+ ### GitHub Copilot (dedicated PR review)
162
+
163
+ Copy `.github/copilot-instructions.md` from this repo to your project. GitHub Copilot's dedicated PR review feature reads this file and applies the SFMC language rules when summarising your PRs.
164
+
165
+ ### GitLab Duo
166
+
167
+ 1. Copy the content of `ci-templates/gitlab-duo-review-instructions.md` to `.gitlab/duo-instructions.md` in your repository.
168
+ 2. GitLab Duo Code Review will apply these instructions on every merge request.
169
+
170
+ > GitLab Duo's dedicated MR review does not support MCP directly. Use the CI lint job below for automated static analysis, and the Duo instructions for AI-assisted review comments.
171
+
172
+ ### CI linting (deterministic checks)
173
+
174
+ For deterministic, blocking CI validation, use the **eslint-plugin-sfmc** templates provided in `ci-templates/`:
175
+
176
+ | Platform | File |
177
+ |---|---|
178
+ | GitHub Actions | [`github-actions.yml`](.github/workflows/sfmc-lint.yml) |
179
+ | GitLab CI | [`ci-templates/gitlab-ci.yml`](ci-templates/gitlab-ci.yml) |
180
+ | Jenkins | [`ci-templates/Jenkinsfile`](ci-templates/Jenkinsfile) |
181
+ | Azure DevOps | [`ci-templates/azure-pipelines.yml`](ci-templates/azure-pipelines.yml) |
182
+ | Bitbucket Pipelines | [`ci-templates/bitbucket-pipelines.yml`](ci-templates/bitbucket-pipelines.yml) |
183
+
184
+ These templates run `eslint-plugin-sfmc` on changed files and post lint results as PR/MR comments.
185
+
186
+ ### ESLint + @eslint/mcp
187
+
188
+ For AI assistants that don't support MCP but do support tool-calling, you can combine `eslint-plugin-sfmc` with the official `@eslint/mcp` server. Add it alongside `mcp-server-sfmc`:
189
+
190
+ ```json
191
+ {
192
+ "servers": {
193
+ "sfmc": {
194
+ "command": "npx",
195
+ "args": ["-y", "mcp-server-sfmc@latest"]
196
+ },
197
+ "eslint": {
198
+ "command": "npx",
199
+ "args": ["-y", "@eslint/mcp@latest"]
200
+ }
201
+ }
202
+ }
203
+ ```
204
+
205
+ Create an `eslint.config.mjs` in your project root:
206
+
207
+ ```js
208
+ import sfmc from 'eslint-plugin-sfmc';
209
+ export default [...sfmc.configs.recommended];
210
+ ```
211
+
212
+ The `@eslint/mcp` server exposes an `eslint_lint` tool that your AI can call to run the full ESLint rule set (including all AMPscript and SSJS rules from `eslint-plugin-sfmc`) on any file.
213
+
214
+ ## Architecture
215
+
216
+ ```
217
+ mcp-server-sfmc
218
+ └── sfmc-language-lsp (language intelligence core)
219
+ ├── ampscript-data (AMPscript function catalog)
220
+ └── ssjs-data (SSJS function catalog)
221
+
222
+ vscode-sfmc-language (VS Code extension)
223
+ └── sfmc-language-lsp (same core, bundled via esbuild)
224
+ ```
225
+
226
+ Both the VS Code extension and the MCP server share exactly the same validation, completion, hover, and lookup logic through `sfmc-language-lsp`. This means the AI assistant sees the same errors and suggestions that the editor shows.
227
+
228
+ ## Contributing
229
+
230
+ See [CONTRIBUTING.md](https://github.com/JoernBerkefeld/mcp-server-sfmc/blob/main/CONTRIBUTING.md).
231
+
232
+ ## License
233
+
234
+ MIT — see [LICENSE](./LICENSE).
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * mcp-server-sfmc
4
+ *
5
+ * MCP server exposing SFMC language intelligence (AMPscript, SSJS, GTL) as
6
+ * Model Context Protocol tools, resources, and prompts. Intended for use
7
+ * with AI assistants (GitHub Copilot, GitLab Duo, Cursor, Claude, Windsurf)
8
+ * to enable accurate SFMC code generation and review.
9
+ */
10
+ export {};
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG"}
package/dist/index.js ADDED
@@ -0,0 +1,556 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * mcp-server-sfmc
4
+ *
5
+ * MCP server exposing SFMC language intelligence (AMPscript, SSJS, GTL) as
6
+ * Model Context Protocol tools, resources, and prompts. Intended for use
7
+ * with AI assistants (GitHub Copilot, GitLab Duo, Cursor, Claude, Windsurf)
8
+ * to enable accurate SFMC code generation and review.
9
+ */
10
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
11
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
12
+ import { z } from 'zod';
13
+ import { sfmcLanguageService, validateAmpscript, validateSsjs, validateGtlBlocks, } from 'sfmc-language-lsp';
14
+ // ---------------------------------------------------------------------------
15
+ // Server instance
16
+ // ---------------------------------------------------------------------------
17
+ const server = new McpServer({
18
+ name: 'mcp-server-sfmc',
19
+ version: '0.1.0',
20
+ });
21
+ // ---------------------------------------------------------------------------
22
+ // Shared helpers
23
+ // ---------------------------------------------------------------------------
24
+ const defaultSettings = { maxNumberOfProblems: 100 };
25
+ function detectLanguage(code, hint) {
26
+ if (hint === 'ssjs')
27
+ return 'ssjs';
28
+ if (hint === 'ampscript')
29
+ return 'ampscript';
30
+ // HTML: check for dominant content
31
+ if (hint === 'html') {
32
+ const hasSsjs = /<script[^>]+runat=['"]?server/i.test(code);
33
+ const hasAmpscript = /%%\[|%%=/.test(code);
34
+ if (hasSsjs && !hasAmpscript)
35
+ return 'ssjs';
36
+ return 'ampscript';
37
+ }
38
+ // Auto-detect
39
+ if (/%%\[|%%=|<script[^>]+language=['"]?ampscript/i.test(code))
40
+ return 'ampscript';
41
+ if (/<script[^>]+runat=['"]?server/i.test(code) || /Platform\.(Load|Function|Variable)/i.test(code))
42
+ return 'ssjs';
43
+ return 'ampscript';
44
+ }
45
+ function formatDiagnostics(diagnostics) {
46
+ if (diagnostics.length === 0)
47
+ return 'No issues found.';
48
+ return diagnostics
49
+ .map((d) => {
50
+ const sev = d.severity === 1 ? 'ERROR' : d.severity === 2 ? 'WARNING' : 'INFO';
51
+ const loc = `line ${d.range.start.line + 1}, col ${d.range.start.character + 1}`;
52
+ return `[${sev}] ${loc}: ${d.message}`;
53
+ })
54
+ .join('\n');
55
+ }
56
+ // ---------------------------------------------------------------------------
57
+ // Tool: validate_ampscript
58
+ // ---------------------------------------------------------------------------
59
+ server.tool('validate_ampscript', 'Validate AMPscript code for syntax errors, unknown functions, arity mismatches, and style issues. ' +
60
+ 'Returns a list of diagnostics with line numbers and severity.', {
61
+ code: z.string().describe('The AMPscript code to validate. May include HTML context.'),
62
+ maxProblems: z.number().int().min(1).max(500).optional()
63
+ .describe('Maximum number of problems to return (default 100).'),
64
+ }, ({ code, maxProblems }) => {
65
+ const settings = { maxNumberOfProblems: maxProblems ?? 100 };
66
+ const diagnostics = validateAmpscript(code, settings);
67
+ return {
68
+ content: [{ type: 'text', text: formatDiagnostics(diagnostics) }],
69
+ };
70
+ });
71
+ // ---------------------------------------------------------------------------
72
+ // Tool: validate_ssjs
73
+ // ---------------------------------------------------------------------------
74
+ server.tool('validate_ssjs', 'Validate SSJS (Server-Side JavaScript) code for unsupported ES6+ syntax, missing Platform.Load, ' +
75
+ 'and incorrect usage patterns. Returns diagnostics with line numbers.', {
76
+ code: z.string().describe('The SSJS code to validate. May include <script runat="server"> tags.'),
77
+ maxProblems: z.number().int().min(1).max(500).optional()
78
+ .describe('Maximum number of problems to return (default 100).'),
79
+ }, ({ code, maxProblems }) => {
80
+ const settings = { maxNumberOfProblems: maxProblems ?? 100 };
81
+ const diagnostics = validateSsjs(code, settings);
82
+ return {
83
+ content: [{ type: 'text', text: formatDiagnostics(diagnostics) }],
84
+ };
85
+ });
86
+ // ---------------------------------------------------------------------------
87
+ // Tool: validate_sfmc_html
88
+ // ---------------------------------------------------------------------------
89
+ server.tool('validate_sfmc_html', 'Validate an HTML file that contains embedded AMPscript and/or SSJS blocks. ' +
90
+ 'Checks both languages and GTL template syntax.', {
91
+ code: z.string().describe('HTML source that may contain %%[ ]%%, %%= =%%, <script runat="server">, or {{ }} blocks.'),
92
+ maxProblems: z.number().int().min(1).max(500).optional()
93
+ .describe('Maximum number of problems to return (default 100).'),
94
+ }, ({ code, maxProblems }) => {
95
+ const limit = maxProblems ?? 100;
96
+ const settings = { maxNumberOfProblems: limit };
97
+ const ampDiags = validateAmpscript(code, settings);
98
+ const ssjsDiags = validateSsjs(code, settings);
99
+ const gtlDiags = [];
100
+ validateGtlBlocks(code, gtlDiags, limit);
101
+ const all = [...ampDiags, ...ssjsDiags, ...gtlDiags].sort((a, b) => a.range.start.line - b.range.start.line);
102
+ return {
103
+ content: [{ type: 'text', text: formatDiagnostics(all) }],
104
+ };
105
+ });
106
+ // ---------------------------------------------------------------------------
107
+ // Tool: lookup_ampscript_function
108
+ // ---------------------------------------------------------------------------
109
+ server.tool('lookup_ampscript_function', 'Look up the signature, parameters, description, and examples for an AMPscript function by name. ' +
110
+ 'Case-insensitive. Returns null if the function is not found.', {
111
+ name: z.string().describe('The AMPscript function name, e.g. "Lookup", "DateAdd", "IIf".'),
112
+ }, ({ name }) => {
113
+ const fn = sfmcLanguageService.lookupAmpscriptFunction(name);
114
+ if (!fn) {
115
+ return { content: [{ type: 'text', text: `AMPscript function "${name}" not found.` }] };
116
+ }
117
+ const params = fn.params
118
+ .map((p) => {
119
+ const req = p.optional ? '(optional)' : '(required)';
120
+ return ` - ${p.name}: ${p.type ?? 'any'} ${req}${p.description ? ' — ' + p.description : ''}`;
121
+ })
122
+ .join('\n');
123
+ const examples = fn.example ? '\n\nExample:\n' + fn.example : '';
124
+ const text = `## ${fn.name}\n\n` +
125
+ `**Category:** ${fn.category ?? 'Unknown'}\n\n` +
126
+ `**Description:** ${fn.description ?? ''}\n\n` +
127
+ `**Parameters:**\n${params || ' (none)'}` +
128
+ examples;
129
+ return { content: [{ type: 'text', text }] };
130
+ });
131
+ // ---------------------------------------------------------------------------
132
+ // Tool: lookup_ssjs_function
133
+ // ---------------------------------------------------------------------------
134
+ server.tool('lookup_ssjs_function', 'Look up the signature, parameters, and description for an SSJS function or method. ' +
135
+ 'Searches Platform functions, WSProxy methods, HTTP methods, and global functions. Case-insensitive.', {
136
+ name: z.string().describe('The function or method name, e.g. "Lookup", "retrieve", "Get". May include namespace like "Platform.Function.Lookup".'),
137
+ }, ({ name }) => {
138
+ // Strip namespace prefix for lookup
139
+ const bare = name.replace(/^(Platform\.(Function|Variable|Response|Request|ClientBrowser|Recipient|DateTime)\.|WSProxy\.|HTTP\.|Script\.Util\.|Function\.|Variable\.|Response\.|Request\.)/i, '');
140
+ const fn = sfmcLanguageService.lookupSsjsFunction(bare);
141
+ if (!fn) {
142
+ return { content: [{ type: 'text', text: `SSJS function/method "${name}" not found.` }] };
143
+ }
144
+ const params = (fn.params ?? [])
145
+ .map((p) => {
146
+ const isOptional = p.optional || p.required === false;
147
+ const req = isOptional ? '(optional)' : '(required)';
148
+ return ` - ${p.name}: ${p.type ?? 'any'} ${req}${p.description ? ' — ' + p.description : ''}`;
149
+ })
150
+ .join('\n');
151
+ const text = `## ${fn.name}\n\n` +
152
+ `**Description:** ${fn.description ?? ''}\n\n` +
153
+ `**Parameters:**\n${params || ' (none)'}\n\n` +
154
+ `**Returns:** ${fn.returnType ?? 'void'}`;
155
+ return { content: [{ type: 'text', text }] };
156
+ });
157
+ // ---------------------------------------------------------------------------
158
+ // Tool: review_change
159
+ // ---------------------------------------------------------------------------
160
+ server.tool('review_change', 'Review a code diff for SFMC (AMPscript, SSJS, or HTML) quality issues. ' +
161
+ 'Extracts added/changed lines from the diff and validates them. ' +
162
+ 'Returns structured feedback with line-level diagnostics and style suggestions.', {
163
+ diff: z.string().describe('A unified diff (git diff format) containing the changed code.'),
164
+ language: z.enum(['ampscript', 'ssjs', 'html', 'auto']).optional()
165
+ .describe('Language of the changed file. Defaults to "auto" for automatic detection.'),
166
+ maxProblems: z.number().int().min(1).max(200).optional()
167
+ .describe('Maximum number of problems to report (default 50).'),
168
+ }, ({ diff, language = 'auto', maxProblems = 50 }) => {
169
+ // Extract added lines from the unified diff
170
+ const addedLines = [];
171
+ let lineNum = 0;
172
+ const lineMap = []; // maps index in addedLines to original diff line number
173
+ for (const line of diff.split('\n')) {
174
+ lineNum++;
175
+ if (line.startsWith('+') && !line.startsWith('+++')) {
176
+ addedLines.push(line.slice(1));
177
+ lineMap.push(lineNum);
178
+ }
179
+ }
180
+ if (addedLines.length === 0) {
181
+ return { content: [{ type: 'text', text: 'No added lines found in the diff.' }] };
182
+ }
183
+ const addedCode = addedLines.join('\n');
184
+ const detectedLang = language === 'auto'
185
+ ? detectLanguage(addedCode)
186
+ : language === 'html'
187
+ ? detectLanguage(addedCode, 'html')
188
+ : language;
189
+ const settings = { maxNumberOfProblems: maxProblems };
190
+ const doc = { text: addedCode, languageId: detectedLang, uri: 'diff' };
191
+ const diagnostics = sfmcLanguageService.validate(doc, settings);
192
+ if (diagnostics.length === 0) {
193
+ return { content: [{ type: 'text', text: `No issues found in the ${detectedLang.toUpperCase()} changes.` }] };
194
+ }
195
+ const output = [`## SFMC Code Review — ${detectedLang.toUpperCase()} changes\n`];
196
+ for (const d of diagnostics) {
197
+ const sev = d.severity === 1 ? '🔴 ERROR' : d.severity === 2 ? '🟡 WARNING' : '🔵 INFO';
198
+ const origLine = lineMap[d.range.start.line] ?? d.range.start.line + 1;
199
+ output.push(`${sev} (diff line ${origLine}): ${d.message}`);
200
+ }
201
+ return { content: [{ type: 'text', text: output.join('\n') }] };
202
+ });
203
+ // ---------------------------------------------------------------------------
204
+ // Tool: suggest_fix
205
+ // ---------------------------------------------------------------------------
206
+ server.tool('suggest_fix', 'Generate a corrected version of SFMC code based on validation diagnostics. ' +
207
+ 'Returns the original code with inline fix suggestions or a corrected replacement.', {
208
+ code: z.string().describe('The SFMC code snippet to fix.'),
209
+ language: z.enum(['ampscript', 'ssjs', 'html', 'auto']).optional()
210
+ .describe('Language of the code. Defaults to "auto".'),
211
+ issueDescription: z.string().optional()
212
+ .describe('Optional human description of the specific issue to fix.'),
213
+ }, ({ code, language = 'auto', issueDescription }) => {
214
+ const detectedLang = language === 'auto' ? detectLanguage(code) : detectLanguage(code, language);
215
+ const settings = { maxNumberOfProblems: 50 };
216
+ const doc = { text: code, languageId: detectedLang, uri: 'fix-target' };
217
+ const diagnostics = sfmcLanguageService.validate(doc, settings);
218
+ const lines = code.split('\n');
219
+ const suggestions = [];
220
+ for (const d of diagnostics) {
221
+ const lineText = lines[d.range.start.line] ?? '';
222
+ suggestions.push(`Line ${d.range.start.line + 1}: ${d.message}\n` +
223
+ ` Code: ${lineText.trim()}\n` +
224
+ ` Fix: ${getFixSuggestion(d.message, lineText, detectedLang)}`);
225
+ }
226
+ if (suggestions.length === 0) {
227
+ const extra = issueDescription ? ` Issue reported: "${issueDescription}"` : '';
228
+ return { content: [{ type: 'text', text: `No validation issues detected.${extra}` }] };
229
+ }
230
+ const header = issueDescription
231
+ ? `## Fix Suggestions for: ${issueDescription}\n`
232
+ : `## Fix Suggestions\n`;
233
+ return { content: [{ type: 'text', text: header + suggestions.join('\n\n') }] };
234
+ });
235
+ /** Generate a human-readable fix hint for common diagnostics. */
236
+ function getFixSuggestion(message, line, lang) {
237
+ const m = message.toLowerCase();
238
+ if (m.includes("'let'") || m.includes("'const'"))
239
+ return 'Replace `let`/`const` with `var`.';
240
+ if (m.includes('arrow function'))
241
+ return 'Replace `() =>` with `function() {}`.';
242
+ if (m.includes('template literal'))
243
+ return 'Replace `` `${x}` `` with `"" + x + ""`.';
244
+ if (m.includes('platform.load'))
245
+ return 'Add `Platform.Load("core", "1.1.5");` before using Core library objects.';
246
+ if (m.includes('unclosed'))
247
+ return 'Add the matching closing delimiter.';
248
+ if (m.includes('// '))
249
+ return 'AMPscript does not support `//` comments. Use `/* comment */` instead.';
250
+ if (m.includes('html comment'))
251
+ return 'Remove the `<!-- -->` wrapper; use `/* comment */` inside AMPscript.';
252
+ if (m.includes('unknown function')) {
253
+ const fnMatch = message.match(/"([^"]+)"/);
254
+ if (fnMatch)
255
+ return `Check spelling — did you mean a known AMPscript function? ("${fnMatch[1]}")`;
256
+ }
257
+ if (m.includes('expects'))
258
+ return 'Check the number and types of arguments against the function signature.';
259
+ if (lang === 'ssjs' && line.includes('Platform.Load'))
260
+ return 'Use the correct version string, e.g. "1.1.5".';
261
+ return 'Review the relevant SFMC documentation for the correct syntax.';
262
+ }
263
+ // ---------------------------------------------------------------------------
264
+ // Tool: get_ampscript_completions
265
+ // ---------------------------------------------------------------------------
266
+ server.tool('get_ampscript_completions', 'Return a list of AMPscript function names, keywords, and variable names available at a given position in the code.', {
267
+ code: z.string().describe('The full AMPscript document text.'),
268
+ line: z.number().int().min(0).describe('Zero-based line number of the cursor position.'),
269
+ character: z.number().int().min(0).describe('Zero-based character offset within the line.'),
270
+ }, ({ code, line, character }) => {
271
+ const doc = { text: code, languageId: 'ampscript', uri: 'completions' };
272
+ const items = sfmcLanguageService.getCompletions(doc, { line, character });
273
+ const formatted = items
274
+ .slice(0, 50)
275
+ .map((item) => {
276
+ const label = typeof item.label === 'string' ? item.label : item.label.label;
277
+ return `- ${label}${item.detail ? ` — ${item.detail}` : ''}`;
278
+ })
279
+ .join('\n');
280
+ const total = items.length;
281
+ return {
282
+ content: [{
283
+ type: 'text',
284
+ text: total === 0
285
+ ? 'No completions at this position (cursor is outside an AMPscript block).'
286
+ : `${total} completions available (showing up to 50):\n\n${formatted}`,
287
+ }],
288
+ };
289
+ });
290
+ // ---------------------------------------------------------------------------
291
+ // Tool: get_ssjs_completions
292
+ // ---------------------------------------------------------------------------
293
+ server.tool('get_ssjs_completions', 'Return a list of SSJS Platform functions, WSProxy methods, and other SFMC-specific identifiers available for completion.', {
294
+ filter: z.string().optional()
295
+ .describe('Optional prefix filter, e.g. "Platform.Function" or "WSProxy".'),
296
+ }, ({ filter }) => {
297
+ const items = sfmcLanguageService.getSsjsCompletionCatalog();
298
+ const filtered = filter
299
+ ? items.filter((item) => {
300
+ const label = typeof item.label === 'string' ? item.label : item.label.label;
301
+ return label.toLowerCase().startsWith(filter.toLowerCase());
302
+ })
303
+ : items;
304
+ const formatted = filtered
305
+ .slice(0, 80)
306
+ .map((item) => {
307
+ const label = typeof item.label === 'string' ? item.label : item.label.label;
308
+ return `- ${label}${item.detail ? ` — ${item.detail}` : ''}`;
309
+ })
310
+ .join('\n');
311
+ return {
312
+ content: [{
313
+ type: 'text',
314
+ text: filtered.length === 0
315
+ ? `No SSJS completions matching "${filter}".`
316
+ : `${filtered.length} SSJS completions${filter ? ` matching "${filter}"` : ''} (showing up to 80):\n\n${formatted}`,
317
+ }],
318
+ };
319
+ });
320
+ // ---------------------------------------------------------------------------
321
+ // Tool: format_sfmc_code (basic, no prettier integration needed)
322
+ // ---------------------------------------------------------------------------
323
+ server.tool('format_sfmc_code', 'Apply basic formatting conventions to AMPscript or SSJS code. ' +
324
+ 'Normalises keyword casing, whitespace around operators, and indentation hints.', {
325
+ code: z.string().describe('The SFMC code to format.'),
326
+ language: z.enum(['ampscript', 'ssjs']).describe('The language of the code.'),
327
+ }, ({ code, language }) => {
328
+ let formatted = code;
329
+ if (language === 'ampscript') {
330
+ // Normalise AMPscript block keywords to uppercase
331
+ formatted = formatted
332
+ .replace(/\b(if|elseif|else|endif|for|to|downto|step|next|set|var|do|output)\b/gi, (m) => m.toUpperCase())
333
+ .replace(/\bAND\b/gi, 'AND')
334
+ .replace(/\bOR\b/gi, 'OR')
335
+ .replace(/\bNOT\b/gi, 'NOT');
336
+ }
337
+ else {
338
+ // SSJS: normalise Platform.Load to use double quotes
339
+ formatted = formatted.replace(/Platform\.Load\s*\(\s*'([^']*)'\s*,\s*'([^']*)'\s*\)/g, 'Platform.Load("$1", "$2")');
340
+ }
341
+ return { content: [{ type: 'text', text: formatted }] };
342
+ });
343
+ // ---------------------------------------------------------------------------
344
+ // Resource: ampscript-function-catalog
345
+ // ---------------------------------------------------------------------------
346
+ server.resource('ampscript-function-catalog', 'sfmc://ampscript/functions', async () => {
347
+ const functions = sfmcLanguageService.getAllAmpscriptFunctions();
348
+ const lines = functions.map((fn) => {
349
+ const paramList = fn.params.map((p) => p.optional ? `[${p.name}: ${p.type ?? 'any'}]` : `${p.name}: ${p.type ?? 'any'}`).join(', ');
350
+ return `${fn.name}(${paramList}) — ${fn.description ?? ''}`;
351
+ });
352
+ return {
353
+ contents: [{
354
+ uri: 'sfmc://ampscript/functions',
355
+ mimeType: 'text/plain',
356
+ text: `# AMPscript Function Catalog (${functions.length} functions)\n\n` + lines.join('\n'),
357
+ }],
358
+ };
359
+ });
360
+ // ---------------------------------------------------------------------------
361
+ // Resource: ssjs-function-catalog
362
+ // ---------------------------------------------------------------------------
363
+ server.resource('ssjs-function-catalog', 'sfmc://ssjs/functions', async () => {
364
+ const functions = sfmcLanguageService.getAllSsjsFunctions();
365
+ const lines = functions.map((fn) => {
366
+ const paramList = (fn.params ?? []).map((p) => (p.optional || p.required === false) ? `[${p.name}: ${p.type ?? 'any'}]` : `${p.name}: ${p.type ?? 'any'}`).join(', ');
367
+ return `${fn.name}(${paramList}) — ${fn.description ?? ''}`;
368
+ });
369
+ return {
370
+ contents: [{
371
+ uri: 'sfmc://ssjs/functions',
372
+ mimeType: 'text/plain',
373
+ text: `# SSJS Function Catalog (${functions.length} functions)\n\n` + lines.join('\n'),
374
+ }],
375
+ };
376
+ });
377
+ // ---------------------------------------------------------------------------
378
+ // Resource: ampscript-keywords
379
+ // ---------------------------------------------------------------------------
380
+ server.resource('ampscript-keywords', 'sfmc://ampscript/keywords', async () => {
381
+ const keywords = sfmcLanguageService.getAmpscriptKeywords();
382
+ return {
383
+ contents: [{
384
+ uri: 'sfmc://ampscript/keywords',
385
+ mimeType: 'text/plain',
386
+ text: `# AMPscript Keywords\n\n${keywords.join(', ')}`,
387
+ }],
388
+ };
389
+ });
390
+ // ---------------------------------------------------------------------------
391
+ // Resource: ssjs-unsupported-syntax
392
+ // ---------------------------------------------------------------------------
393
+ server.resource('ssjs-unsupported-syntax', 'sfmc://ssjs/unsupported-syntax', async () => {
394
+ const items = sfmcLanguageService.getUnsupportedSsjsSyntax();
395
+ const lines = items.map((item) => `- **${item.pattern}**: ${item.message}`);
396
+ return {
397
+ contents: [{
398
+ uri: 'sfmc://ssjs/unsupported-syntax',
399
+ mimeType: 'text/markdown',
400
+ text: `# SSJS Unsupported Syntax\n\nThese ES6+ features are not supported in Salesforce Marketing Cloud SSJS:\n\n${lines.join('\n')}`,
401
+ }],
402
+ };
403
+ });
404
+ // ---------------------------------------------------------------------------
405
+ // Prompt: writeAmpscript
406
+ // ---------------------------------------------------------------------------
407
+ server.prompt('writeAmpscript', 'Generate AMPscript code for a specific task. Ensures correct syntax, proper use of delimiters, ' +
408
+ 'and references to real SFMC functions.', {
409
+ task: z.string().describe('Description of what the AMPscript code should do.'),
410
+ context: z.string().optional().describe('Optional context about the email, landing page, or SFMC configuration.'),
411
+ }, ({ task, context }) => ({
412
+ messages: [{
413
+ role: 'user',
414
+ content: {
415
+ type: 'text',
416
+ text: [
417
+ 'You are an expert Salesforce Marketing Cloud developer.',
418
+ 'Generate AMPscript code for the following task.',
419
+ '',
420
+ '## Rules',
421
+ '- Use `%%[ ]%%` for block-level code and `%%= =%%` for inline output.',
422
+ '- Keywords (SET, VAR, IF, ENDIF, FOR, NEXT, OUTPUT) must be uppercase.',
423
+ '- Variables start with `@`. Example: `SET @myVar = "value"`',
424
+ '- Use `/* */` for comments — never `//` or `<!-- -->`.',
425
+ '- All function names are case-insensitive but conventionally PascalCase.',
426
+ '- Do NOT use ES6+ syntax (this is not JavaScript).',
427
+ '- Validate your output against the AMPscript function catalog.',
428
+ '',
429
+ `## Task`,
430
+ task,
431
+ context ? `\n## Context\n${context}` : '',
432
+ ].filter(Boolean).join('\n'),
433
+ },
434
+ }],
435
+ }));
436
+ // ---------------------------------------------------------------------------
437
+ // Prompt: writeSsjs
438
+ // ---------------------------------------------------------------------------
439
+ server.prompt('writeSsjs', 'Generate SSJS (Server-Side JavaScript) code for a specific task. Ensures ES5-compatible syntax and ' +
440
+ 'correct use of SFMC Platform APIs.', {
441
+ task: z.string().describe('Description of what the SSJS code should do.'),
442
+ context: z.string().optional().describe('Optional context about the SFMC environment or assets involved.'),
443
+ }, ({ task, context }) => ({
444
+ messages: [{
445
+ role: 'user',
446
+ content: {
447
+ type: 'text',
448
+ text: [
449
+ 'You are an expert Salesforce Marketing Cloud developer.',
450
+ 'Generate SSJS code for the following task.',
451
+ '',
452
+ '## Rules',
453
+ '- SSJS runs in an ES5 engine. Use `var`, not `let`/`const`.',
454
+ '- No arrow functions, template literals, destructuring, or `class`.',
455
+ '- Wrap code in `<script runat="server">` ... `</script>`.',
456
+ '- Use `Platform.Load("core", "1.1.5");` before accessing Core library objects.',
457
+ '- Use `Platform.Function.*` for SFMC-specific functions (e.g. `Platform.Function.Lookup`).',
458
+ '- For SOAP API calls, use WSProxy: `var prox = new WSProxy();`',
459
+ '- Use `Platform.Response.Write()` to output content.',
460
+ '',
461
+ `## Task`,
462
+ task,
463
+ context ? `\n## Context\n${context}` : '',
464
+ ].filter(Boolean).join('\n'),
465
+ },
466
+ }],
467
+ }));
468
+ // ---------------------------------------------------------------------------
469
+ // Prompt: reviewSfmcCode
470
+ // ---------------------------------------------------------------------------
471
+ server.prompt('reviewSfmcCode', 'Review SFMC code for correctness, best practices, and potential issues. Provides actionable feedback.', {
472
+ code: z.string().describe('The SFMC code to review.'),
473
+ language: z.enum(['ampscript', 'ssjs', 'html', 'auto']).optional(),
474
+ focus: z.string().optional().describe('Optional focus area, e.g. "security", "performance", "data extension usage".'),
475
+ }, ({ code, language = 'auto', focus }) => {
476
+ const detectedLang = language === 'auto' ? detectLanguage(code) : detectLanguage(code, language);
477
+ return {
478
+ messages: [{
479
+ role: 'user',
480
+ content: {
481
+ type: 'text',
482
+ text: [
483
+ `You are an expert Salesforce Marketing Cloud developer reviewing ${detectedLang.toUpperCase()} code.`,
484
+ 'Identify bugs, anti-patterns, performance issues, and security concerns.',
485
+ focus ? `Focus especially on: ${focus}` : '',
486
+ '',
487
+ '## Code to Review',
488
+ '```' + (detectedLang === 'ssjs' ? 'javascript' : detectedLang),
489
+ code,
490
+ '```',
491
+ '',
492
+ '## Review checklist',
493
+ detectedLang === 'ampscript' ? [
494
+ '- Delimiter balance (%%[ ]%%, %%= =%%)',
495
+ '- IF/ENDIF, FOR/NEXT block balance',
496
+ '- Correct function names and argument counts',
497
+ '- Correct comment syntax (/* */ only)',
498
+ '- Proper variable declaration with @',
499
+ ].join('\n') : [
500
+ '- No ES6+ syntax (var, not let/const; no arrow functions)',
501
+ '- Platform.Load before Core library objects',
502
+ '- Correct Platform.Function calls',
503
+ '- WSProxy error handling',
504
+ '- No sensitive data in logs or responses',
505
+ ].join('\n'),
506
+ ].filter(Boolean).join('\n'),
507
+ },
508
+ }],
509
+ };
510
+ });
511
+ // ---------------------------------------------------------------------------
512
+ // Prompt: convertAmpscriptToSsjs
513
+ // ---------------------------------------------------------------------------
514
+ server.prompt('convertAmpscriptToSsjs', 'Convert AMPscript code to equivalent SSJS, preserving business logic while adapting to SSJS APIs.', {
515
+ ampscript: z.string().describe('The AMPscript code to convert.'),
516
+ }, ({ ampscript }) => ({
517
+ messages: [{
518
+ role: 'user',
519
+ content: {
520
+ type: 'text',
521
+ text: [
522
+ 'Convert the following AMPscript code to equivalent SSJS.',
523
+ '',
524
+ '## Conversion rules',
525
+ '- AMPscript `Lookup()` → `Platform.Function.Lookup()` in SSJS',
526
+ '- AMPscript `LookupRows()` → `Platform.Function.LookupRows()` in SSJS',
527
+ '- AMPscript `@variable` → `var variable` in SSJS',
528
+ '- AMPscript `SET @x = value` → `var x = value;` in SSJS',
529
+ '- AMPscript `IF @x == "y" THEN` → `if (x === "y") {` in SSJS',
530
+ '- AMPscript `OUTPUT(CONCAT(...))` → `Platform.Response.Write(...)` in SSJS',
531
+ '- AMPscript `FOR @i = 1 TO 10 DO` → `for (var i = 1; i <= 10; i++) {` in SSJS',
532
+ '- Use `var`, not `let`/`const`. No arrow functions or template literals.',
533
+ '- Wrap in `<script runat="server">...</script>`.',
534
+ '- Add `Platform.Load("core", "1.1.5");` if using DataExtension, Rows, etc.',
535
+ '',
536
+ '## AMPscript to convert',
537
+ '```ampscript',
538
+ ampscript,
539
+ '```',
540
+ ].join('\n'),
541
+ },
542
+ }],
543
+ }));
544
+ // ---------------------------------------------------------------------------
545
+ // Start
546
+ // ---------------------------------------------------------------------------
547
+ async function main() {
548
+ const transport = new StdioServerTransport();
549
+ await server.connect(transport);
550
+ process.stderr.write('mcp-server-sfmc running on stdio\n');
551
+ }
552
+ main().catch((error) => {
553
+ process.stderr.write(`Fatal: ${String(error)}\n`);
554
+ process.exit(1);
555
+ });
556
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "mcp-server-sfmc",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for Salesforce Marketing Cloud — exposes SFMC language intelligence (AMPscript, SSJS, GTL) as Model Context Protocol tools, resources, and prompts for AI-assisted development and code review.",
5
+ "author": "Jörn Berkefeld",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/JoernBerkefeld/mcp-server-sfmc.git"
10
+ },
11
+ "bugs": {
12
+ "url": "https://github.com/JoernBerkefeld/mcp-server-sfmc/issues"
13
+ },
14
+ "homepage": "https://github.com/JoernBerkefeld/mcp-server-sfmc#readme",
15
+ "keywords": [
16
+ "mcp",
17
+ "model-context-protocol",
18
+ "ampscript",
19
+ "ssjs",
20
+ "sfmc",
21
+ "salesforce",
22
+ "marketing-cloud",
23
+ "ai",
24
+ "copilot",
25
+ "code-review"
26
+ ],
27
+ "type": "module",
28
+ "bin": {
29
+ "mcp-server-sfmc": "./dist/index.js"
30
+ },
31
+ "main": "./dist/index.js",
32
+ "exports": {
33
+ ".": "./dist/index.js"
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "README.md",
38
+ "LICENSE"
39
+ ],
40
+ "scripts": {
41
+ "build": "tsc -p tsconfig.json",
42
+ "dev": "tsc -p tsconfig.json --watch",
43
+ "start": "node dist/index.js",
44
+ "test": "node --test tests/*.test.mjs",
45
+ "clean": "node -e \"require('fs').rmSync('dist', { recursive: true, force: true })\""
46
+ },
47
+ "dependencies": {
48
+ "@modelcontextprotocol/sdk": "^1.29.0",
49
+ "sfmc-language-lsp": "file:../sfmc-language-lsp"
50
+ },
51
+ "engines": {
52
+ "node": ">=18.0.0"
53
+ }
54
+ }