@frase/mcp-server 0.3.7 → 0.3.8

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.
@@ -0,0 +1,42 @@
1
+ import type { ToolExecutor } from "../types.js";
2
+ /**
3
+ * Detects "the tool ran successfully but shipped garbage" — the class of bug
4
+ * where an object is coerced into markdown as `[object Object]`, or a leaked
5
+ * `undefined`/`NaN` lands in rendered prose. (Real example: People Also Ask
6
+ * entries rendered as `[object Object]` to every user, found only via a
7
+ * customer report.)
8
+ *
9
+ * In tests/CI a dirty render throws (pre-merge gate). In real traffic it never
10
+ * throws — it emits a structured warning and returns the result unchanged.
11
+ */
12
+ export interface RenderIssue {
13
+ /** The offending token, e.g. "[object Object]", "undefined", "empty-table". */
14
+ pattern: string;
15
+ /** A short slice of surrounding text, for the warning/error message. */
16
+ snippet: string;
17
+ }
18
+ export interface AssertCleanRenderOpts {
19
+ /**
20
+ * Set for `success: false` results — only the `[object …]` check runs, since
21
+ * error messages may legitimately mention "undefined"/"NaN".
22
+ */
23
+ errorResult?: boolean;
24
+ }
25
+ export declare class CleanRenderError extends Error {
26
+ readonly toolName: string;
27
+ readonly issues: RenderIssue[];
28
+ constructor(toolName: string, issues: RenderIssue[]);
29
+ }
30
+ /**
31
+ * Returns the render defects found in `markdown` (empty array = clean). Pure;
32
+ * conservative by design — tuned to catch the real bug class with near-zero
33
+ * false positives on legitimate empty-state output.
34
+ */
35
+ export declare function assertCleanRender(markdown: string, opts?: AssertCleanRenderOpts): RenderIssue[];
36
+ /**
37
+ * Wraps a tool executor so its rendered markdown is validated on every call.
38
+ * Applied at the `TOOL_EXECUTORS` chokepoint, so it covers every tool on both
39
+ * the stdio and in-app HTTP surfaces. Never alters the result.
40
+ */
41
+ export declare function withCleanRender(toolName: string, executor: ToolExecutor): ToolExecutor;
42
+ //# sourceMappingURL=clean-render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean-render.d.ts","sourceRoot":"","sources":["../../src/lib/clean-render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD;;;;;;;;;GASG;AAEH,MAAM,WAAW,WAAW;IAC1B,+EAA+E;IAC/E,OAAO,EAAE,MAAM,CAAC;IAChB,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAgBD,qBAAa,gBAAiB,SAAQ,KAAK;aAEvB,QAAQ,EAAE,MAAM;aAChB,MAAM,EAAE,WAAW,EAAE;gBADrB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,WAAW,EAAE;CAQxC;AAyBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,qBAA0B,GAC/B,WAAW,EAAE,CA0Df;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,YAAY,GACrB,YAAY,CAmBd"}
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Throw on a dirty render instead of warning. Tests, CI, and the scheduled
3
+ * synthetic smoke opt in; real stdio (customer machine) and in-app HTTP traffic
4
+ * never throw — a bad render must not break a live tool call. Evaluated per
5
+ * call so the environment can be toggled (e.g. in tests).
6
+ */
7
+ function isRenderStrict() {
8
+ return (!!process.env.VITEST ||
9
+ process.env.NODE_ENV === "test" ||
10
+ process.env.FRASE_RENDER_STRICT === "1");
11
+ }
12
+ export class CleanRenderError extends Error {
13
+ toolName;
14
+ issues;
15
+ constructor(toolName, issues) {
16
+ super(`Tool "${toolName}" produced a dirty render: ` +
17
+ issues.map((i) => `${i.pattern} (…${i.snippet}…)`).join("; "));
18
+ this.toolName = toolName;
19
+ this.issues = issues;
20
+ this.name = "CleanRenderError";
21
+ }
22
+ }
23
+ /**
24
+ * Blank out spans where these tokens are legitimate so they don't trip the
25
+ * scanner: fenced code blocks, inline code, and italic placeholders (the
26
+ * `_No results found._` empty-state convention, which `hidden: true` branches
27
+ * also use). Replaced with a space to preserve word boundaries around them.
28
+ */
29
+ function stripSafeSpans(md) {
30
+ return md
31
+ .replace(/```[\s\S]*?```/g, " ")
32
+ .replace(/`[^`]*`/g, " ")
33
+ // NOTE: greedy `_…_` blanking can also blank a snake_case span in prose
34
+ // (e.g. `field_undefined_value`), which could mask a token sitting between
35
+ // two snake_case words. That's a false-negative only (we'd miss a defect),
36
+ // never a false-positive — acceptable for this conservative validator.
37
+ .replace(/_[^_]+_/g, " ");
38
+ }
39
+ function snippetAround(text, index, len) {
40
+ const start = Math.max(0, index - 30);
41
+ const end = Math.min(text.length, index + len + 30);
42
+ return text.slice(start, end).replace(/\s+/g, " ").trim();
43
+ }
44
+ /**
45
+ * Returns the render defects found in `markdown` (empty array = clean). Pure;
46
+ * conservative by design — tuned to catch the real bug class with near-zero
47
+ * false positives on legitimate empty-state output.
48
+ */
49
+ export function assertCleanRender(markdown, opts = {}) {
50
+ const issues = [];
51
+ if (!markdown)
52
+ return issues;
53
+ // A coerced object is always a bug — even inside code or error messages.
54
+ const objMatch = markdown.match(/\[object \w+\]/);
55
+ if (objMatch) {
56
+ issues.push({
57
+ pattern: objMatch[0],
58
+ snippet: snippetAround(markdown, objMatch.index ?? 0, objMatch[0].length),
59
+ });
60
+ }
61
+ // Error results legitimately mention "undefined"/"NaN"; stop after the
62
+ // object check above.
63
+ if (opts.errorResult)
64
+ return issues;
65
+ const stripped = stripSafeSpans(markdown);
66
+ // Leaked `undefined`/`NaN` — but ONLY in a formatted-value position, never in
67
+ // free prose. Many tools pass verbatim user/LLM text through (article bodies,
68
+ // brief sections, descriptions) that legitimately contains the words
69
+ // "undefined"/"NaN"; scanning prose would false-positive and, in strict mode,
70
+ // throw on a valid tool call. So we anchor to where the formatter emits a
71
+ // value: a table cell, a bold "key:" value, a colon-terminated heading/label,
72
+ // or a bare list item. Case-sensitive — JS coercion yields exactly these.
73
+ // `null` is deliberately not checked (pervasive in legit JSON/prose).
74
+ const SCAFFOLD_TOKEN_RES = [
75
+ /\|\s*(undefined|NaN)\s*(?=\|)/g, // | undefined | (table cell)
76
+ /:\*\*\s*(undefined|NaN)\b/g, // **Key:** undefined
77
+ /:[^\S\n]*(undefined|NaN)[^\S\n]*$/gm, // ## Heading: undefined / Label: undefined
78
+ /^[^\S\n]*[-*][^\S\n]+(undefined|NaN)[^\S\n]*$/gm, // - undefined (bare list value)
79
+ ];
80
+ for (const re of SCAFFOLD_TOKEN_RES) {
81
+ let m;
82
+ while ((m = re.exec(stripped)) !== null) {
83
+ issues.push({
84
+ pattern: m[1],
85
+ snippet: snippetAround(stripped, m.index, m[0].length),
86
+ });
87
+ }
88
+ }
89
+ // A markdown table separator row with no data row after it. `formatTable()`
90
+ // guards this, but a hand-rolled table can still emit an empty grid.
91
+ const lines = stripped.split("\n");
92
+ const separatorRe = /^\s*\|(?:\s*:?-+:?\s*\|)+\s*$/;
93
+ for (let i = 0; i < lines.length; i++) {
94
+ if (separatorRe.test(lines[i])) {
95
+ const next = lines[i + 1];
96
+ const nextIsRow = next !== undefined && /^\s*\|/.test(next);
97
+ if (!nextIsRow) {
98
+ issues.push({ pattern: "empty-table", snippet: lines[i].trim() });
99
+ }
100
+ }
101
+ }
102
+ return issues;
103
+ }
104
+ /**
105
+ * Wraps a tool executor so its rendered markdown is validated on every call.
106
+ * Applied at the `TOOL_EXECUTORS` chokepoint, so it covers every tool on both
107
+ * the stdio and in-app HTTP surfaces. Never alters the result.
108
+ */
109
+ export function withCleanRender(toolName, executor) {
110
+ return async (input, context) => {
111
+ const result = await executor(input, context);
112
+ const issues = assertCleanRender(result.markdown ?? "", {
113
+ errorResult: !result.success,
114
+ });
115
+ if (issues.length > 0) {
116
+ if (isRenderStrict()) {
117
+ throw new CleanRenderError(toolName, issues);
118
+ }
119
+ // Structured warning → Sentry Logs via consoleLoggingIntegration on the
120
+ // in-app surface; visible in stderr on the stdio surface.
121
+ console.warn("mcp_dirty_render", JSON.stringify({ tool: toolName, issues }));
122
+ }
123
+ return result;
124
+ };
125
+ }
126
+ //# sourceMappingURL=clean-render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clean-render.js","sourceRoot":"","sources":["../../src/lib/clean-render.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,13 @@ import type { McpToolDefinition, ToolContext, ToolResult } from "../types.js";
11
11
  */
12
12
  export declare const ALL_TOOLS: McpToolDefinition[];
13
13
  /**
14
- * Tool executor mapping
14
+ * Tool executor mapping.
15
+ *
16
+ * Every executor is wrapped with `withCleanRender` so a malformed render (an
17
+ * object coerced to `[object Object]`, a leaked `undefined`/`NaN`) is caught in
18
+ * tests and recorded in prod instead of silently shipping to users. This is the
19
+ * single chokepoint both MCP surfaces dispatch through — the stdio server and
20
+ * the in-app HTTP endpoint — so wrapping here instruments every tool on both.
15
21
  */
16
22
  export declare const TOOL_EXECUTORS: Record<string, (input: unknown, context: ToolContext) => Promise<ToolResult>>;
17
23
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAsC9E;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,iBAAiB,EAwExC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CACjC,MAAM,EACN,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAyE9D,CAAC;AAEF;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAEzE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,GACX,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,SAAS,CAE7E;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAwC9E;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,iBAAiB,EAwExC,CAAC;AAkFF;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CACjC,MAAM,EACN,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAM9D,CAAC;AAEF;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAEzE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,GACX,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC,GAAG,SAAS,CAE7E;AAED;;GAEG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAErC"}
@@ -33,6 +33,7 @@ import { cmsPostTools, cmsPostExecutors } from "./cms-posts.js";
33
33
  import { commentTools, commentExecutors } from "./comments.js";
34
34
  // Dynamic tool discovery (MCP gateway pattern)
35
35
  import { discoverToolsTool, executeDiscoverTools } from "./discover.js";
36
+ import { withCleanRender } from "../lib/clean-render.js";
36
37
  // ============================================
37
38
  // Tool Registry
38
39
  // ============================================
@@ -90,9 +91,9 @@ export const ALL_TOOLS = [
90
91
  discoverToolsTool,
91
92
  ];
92
93
  /**
93
- * Tool executor mapping
94
+ * Raw executor mapping, before instrumentation.
94
95
  */
95
- export const TOOL_EXECUTORS = {
96
+ const RAW_TOOL_EXECUTORS = {
96
97
  // Sites (Phase 1)
97
98
  ...siteExecutors,
98
99
  // Briefs (Phase 2)
@@ -142,6 +143,19 @@ export const TOOL_EXECUTORS = {
142
143
  // Dynamic Tool Discovery (Gateway Pattern)
143
144
  discover_tools: executeDiscoverTools,
144
145
  };
146
+ /**
147
+ * Tool executor mapping.
148
+ *
149
+ * Every executor is wrapped with `withCleanRender` so a malformed render (an
150
+ * object coerced to `[object Object]`, a leaked `undefined`/`NaN`) is caught in
151
+ * tests and recorded in prod instead of silently shipping to users. This is the
152
+ * single chokepoint both MCP surfaces dispatch through — the stdio server and
153
+ * the in-app HTTP endpoint — so wrapping here instruments every tool on both.
154
+ */
155
+ export const TOOL_EXECUTORS = Object.fromEntries(Object.entries(RAW_TOOL_EXECUTORS).map(([name, exec]) => [
156
+ name,
157
+ withCleanRender(name, exec),
158
+ ]));
145
159
  /**
146
160
  * Get tool definition by name
147
161
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@frase/mcp-server",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "description": "Frase MCP Server — The complete content platform for AI agents. Research, write, optimize, and host SEO & GEO-optimized content with built-in AI search visibility monitoring. Includes Frase CMS for auto-optimized web hosting, 95 tools, 9 agent skills, and 7 workflows. The only MCP server that creates, optimizes, publishes, AND monitors content across Google and AI search engines (ChatGPT, Perplexity, Claude, Gemini, AI Overviews). Works with Claude Desktop, Claude Code, Cursor, Windsurf, VS Code Copilot, Lovable, Replit, and any MCP-compatible tool.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -54,7 +54,7 @@
54
54
  "devDependencies": {
55
55
  "@anthropic-ai/mcpb": "^2.1.2",
56
56
  "@types/node": "^22.10.2",
57
- "esbuild": "^0.21.5",
57
+ "esbuild": "^0.28.1",
58
58
  "tsx": "^4.19.2",
59
59
  "typescript": "^5.7.2",
60
60
  "vitest": "^4.1.2"
@@ -63,7 +63,8 @@
63
63
  "hono": "^4.12.18",
64
64
  "@hono/node-server": "^1.19.13",
65
65
  "fast-uri": "^3.1.2",
66
- "tmp": "^0.2.7"
66
+ "tmp": "^0.2.7",
67
+ "esbuild": "^0.28.1"
67
68
  },
68
69
  "engines": {
69
70
  "node": ">=20.0.0"
package/server.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "io.frase/mcp-server",
4
4
  "title": "Frase SEO",
5
5
  "description": "SEO, GEO & AI Visibility — research, write, optimize, publish & monitor content. 95 tools.",
6
- "version": "0.3.7",
6
+ "version": "0.3.8",
7
7
  "websiteUrl": "https://frase.io/agents",
8
8
  "repository": {
9
9
  "url": "https://github.com/frase-io/mcp-server.git",
@@ -13,7 +13,7 @@
13
13
  {
14
14
  "registryType": "npm",
15
15
  "identifier": "@frase/mcp-server",
16
- "version": "0.3.7",
16
+ "version": "0.3.8",
17
17
  "transport": {
18
18
  "type": "stdio"
19
19
  },