@overcrow/mcp 0.1.3 → 0.1.5

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.
Files changed (79) hide show
  1. package/README.md +12 -7
  2. package/dist/bootstrap/pin.js +19 -1
  3. package/dist/bootstrap/pin.json +47 -43
  4. package/dist/cli.js +14 -4
  5. package/dist/content/docs/en/cli.md +34 -32
  6. package/dist/content/docs/en/dev-channel.md +5 -5
  7. package/dist/content/docs/en/elements.md +5 -5
  8. package/dist/content/docs/en/forms.md +32 -30
  9. package/dist/content/docs/en/guide.md +16 -16
  10. package/dist/content/docs/en/index.md +12 -12
  11. package/dist/content/docs/en/limits.md +5 -4
  12. package/dist/content/docs/en/logic.md +30 -28
  13. package/dist/content/docs/en/manifest.md +35 -33
  14. package/dist/content/docs/en/mcp.md +13 -13
  15. package/dist/content/docs/en/package.md +7 -7
  16. package/dist/content/docs/en/publish-keys.md +6 -5
  17. package/dist/content/docs/en/publishing.md +9 -8
  18. package/dist/content/docs/en/reference.md +5 -5
  19. package/dist/content/docs/en/result-shapes.md +3 -3
  20. package/dist/content/docs/en/sdk.md +11 -11
  21. package/dist/content/docs/en/security.md +30 -30
  22. package/dist/content/docs/en/service-reference.md +2 -2
  23. package/dist/content/docs/en/services.md +33 -32
  24. package/dist/content/docs/en/style-properties.md +2 -2
  25. package/dist/content/docs/en/style.md +19 -18
  26. package/dist/content/docs/en/testing.md +36 -35
  27. package/dist/content/docs/en/view.md +13 -12
  28. package/dist/content/docs/en/widget-statistics.md +18 -17
  29. package/dist/content/docs/en/widgets.md +1 -1
  30. package/dist/content/docs/fr/cli.md +35 -30
  31. package/dist/content/docs/fr/dev-channel.md +8 -8
  32. package/dist/content/docs/fr/elements.md +5 -5
  33. package/dist/content/docs/fr/forms.md +35 -34
  34. package/dist/content/docs/fr/guide.md +13 -12
  35. package/dist/content/docs/fr/index.md +15 -15
  36. package/dist/content/docs/fr/limits.md +5 -5
  37. package/dist/content/docs/fr/logic.md +42 -37
  38. package/dist/content/docs/fr/manifest.md +40 -39
  39. package/dist/content/docs/fr/mcp.md +21 -19
  40. package/dist/content/docs/fr/package.md +8 -7
  41. package/dist/content/docs/fr/publish-keys.md +6 -5
  42. package/dist/content/docs/fr/publishing.md +8 -8
  43. package/dist/content/docs/fr/reference.md +6 -6
  44. package/dist/content/docs/fr/result-shapes.md +4 -3
  45. package/dist/content/docs/fr/sdk.md +12 -11
  46. package/dist/content/docs/fr/security.md +41 -39
  47. package/dist/content/docs/fr/service-reference.md +2 -2
  48. package/dist/content/docs/fr/services.md +34 -33
  49. package/dist/content/docs/fr/style-properties.md +2 -2
  50. package/dist/content/docs/fr/style.md +25 -22
  51. package/dist/content/docs/fr/testing.md +43 -43
  52. package/dist/content/docs/fr/view.md +17 -16
  53. package/dist/content/docs/fr/widget-statistics.md +20 -20
  54. package/dist/content/docs/fr/widgets.md +1 -1
  55. package/dist/content/examples/clock/README.md +3 -3
  56. package/dist/content/examples/fps/README.md +3 -3
  57. package/dist/content/examples/media/README.md +2 -2
  58. package/dist/content/examples/notes/README.md +1 -1
  59. package/dist/content/examples/performance/README.md +2 -2
  60. package/dist/content/examples/playervox-journal/README.md +5 -5
  61. package/dist/content/examples/playervox-rating/README.md +3 -3
  62. package/dist/content/examples/playervox-reviews/README.md +3 -3
  63. package/dist/content/examples/playervox-score/README.md +3 -3
  64. package/dist/content/examples/session/README.md +3 -3
  65. package/dist/content/examples/stopwatch/README.md +3 -3
  66. package/dist/content/examples/twitch-chat/README.md +4 -4
  67. package/dist/content/examples/warframe-market/README.md +2 -2
  68. package/dist/content/reference/errors.json +16 -16
  69. package/dist/prompts.js +2 -2
  70. package/dist/resources.js +1 -1
  71. package/dist/text.js +10 -2
  72. package/dist/texts.js +1 -1
  73. package/dist/tools/build.js +16 -10
  74. package/dist/tools/common.js +19 -12
  75. package/dist/tools/submission.js +7 -4
  76. package/dist/typescript.js +38 -0
  77. package/dist/version.js +1 -1
  78. package/npm-shrinkwrap.json +2 -2
  79. package/package.json +1 -1
@@ -8,7 +8,7 @@ import { ConfinementError } from "../confine.js";
8
8
  import { NpmError } from "../npm.js";
9
9
  import { RunError } from "../run.js";
10
10
  import { SetupError } from "../session.js";
11
- import { bound, DATA_NOTICE } from "../text.js";
11
+ import { bound, clean, DATA_NOTICE, dataText, stripInvisible } from "../text.js";
12
12
  /** Most characters a text result carries; Claude Code moves larger results to a file. */
13
13
  export const MAX_RESULT_CHARS = 40_000;
14
14
  /**
@@ -17,10 +17,8 @@ export const MAX_RESULT_CHARS = 40_000;
17
17
  * Results that carry project content are marked as data.
18
18
  */
19
19
  export function ok(structured, summary, options = {}) {
20
- const redact = (text) => (options.redactor ? options.redactor.text(text) : text);
21
- const structuredContent = options.redactor
22
- ? redactDeep(structured, options.redactor)
23
- : structured;
20
+ const redact = (text) => stripInvisible(options.redactor ? options.redactor.text(text) : text);
21
+ const structuredContent = redactDeep(structured, redact);
24
22
  const json = JSON.stringify(structuredContent);
25
23
  const body = options.data
26
24
  ? `${DATA_NOTICE}\n<data>\n${json.replaceAll("</data>", "<\\/data>")}\n</data>`
@@ -33,21 +31,29 @@ export function ok(structured, summary, options = {}) {
33
31
  structuredContent,
34
32
  };
35
33
  }
36
- /** Replaces the user's paths in every string of a JSON value. */
37
- function redactDeep(value, redactor) {
34
+ /**
35
+ * Applies `redact` to every string of a JSON value: the user's paths
36
+ * replaced, invisible characters removed.
37
+ */
38
+ function redactDeep(value, redact) {
38
39
  if (typeof value === "string")
39
- return redactor.text(value);
40
+ return redact(value);
40
41
  if (Array.isArray(value))
41
- return value.map((item) => redactDeep(item, redactor));
42
+ return value.map((item) => redactDeep(item, redact));
42
43
  if (typeof value === "object" && value !== null) {
43
- return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, redactDeep(item, redactor)]));
44
+ return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, redactDeep(item, redact)]));
44
45
  }
45
46
  return value;
46
47
  }
47
48
  /** A failure the model can correct: what went wrong and what to do. */
48
49
  export function fail(message, redactor) {
49
50
  return {
50
- content: [{ type: "text", text: bound(redactor ? redactor.text(message) : message, 4000) }],
51
+ content: [
52
+ {
53
+ type: "text",
54
+ text: bound(stripInvisible(redactor ? redactor.text(message) : message), 4000),
55
+ },
56
+ ],
51
57
  isError: true,
52
58
  };
53
59
  }
@@ -65,7 +71,8 @@ export function failure(error, redactor) {
65
71
  .filter((line) => line.trim() !== "")
66
72
  .slice(0, 8)
67
73
  .join("\n");
68
- return fail(`${error.message}${detail ? `\n${DATA_NOTICE}\n${detail}` : ""}`, redactor);
74
+ // The CLI's output may quote the project: fenced as data, like tool results.
75
+ return fail(`${error.message}${detail ? `\n${dataText(clean(detail))}` : ""}`, redactor);
69
76
  }
70
77
  throw error;
71
78
  }
@@ -7,6 +7,7 @@ import { join } from "node:path";
7
7
  import { z } from "zod";
8
8
  import { auditWidget } from "../audit/index.js";
9
9
  import { readWidget } from "../audit/project.js";
10
+ import { mayTypeCheck, TYPECHECK_SKIPPED } from "../typescript.js";
10
11
  import { Cli } from "../cli.js";
11
12
  import { limit } from "../content.js";
12
13
  import { sourcesFingerprint } from "../fingerprint.js";
@@ -94,15 +95,17 @@ export function registerSubmissionTool(env) {
94
95
  let review = [];
95
96
  if (tools) {
96
97
  const cli = new Cli(tools);
97
- const check = await cli.check(target, ctx.mcpReq.signal);
98
+ const typecheck = await mayTypeCheck(session.options.pin.npm.typescript, target);
99
+ const check = await cli.check(target, ctx.mcpReq.signal, typecheck);
98
100
  const errors = check.diagnostics.filter((d) => d.severity === "error").length;
99
101
  const warnings = check.diagnostics.length - errors;
102
+ const result = errors + warnings === 0
103
+ ? "Clean."
104
+ : `${errors} error(s), ${warnings} warning(s): the creator space refuses warnings too.`;
100
105
  checklist.push({
101
106
  item: "check: no error, no warning",
102
107
  status: errors + warnings === 0 ? "pass" : "fail",
103
- detail: errors + warnings === 0
104
- ? "Clean."
105
- : `${errors} error(s), ${warnings} warning(s): the creator space refuses warnings too.`,
108
+ detail: typecheck ? result : `${result} ${TYPECHECK_SKIPPED}`,
106
109
  });
107
110
  const report = await cli.admit(target, ctx.mcpReq.signal);
108
111
  const diagnostics = Array.isArray(report.diagnostics)
@@ -0,0 +1,38 @@
1
+ // check, package and test type-check with the project's own TypeScript: the
2
+ // CLI runs node_modules/typescript/lib/tsc.js with Node.js. A project may
3
+ // come from someone else, so the server lets that run only when those files
4
+ // are the pinned TypeScript's: tsc.js loads _tsc.js, which only loads Node's
5
+ // own modules, and the pin holds the SHA-256 of both (pin.ts). Otherwise the
6
+ // commands run with --no-typecheck and say so.
7
+ import { createHash } from "node:crypto";
8
+ import { lstat, readFile } from "node:fs/promises";
9
+ import { join } from "node:path";
10
+ import { TYPESCRIPT_FILES } from "./bootstrap/pin.js";
11
+ const MAX_FILE_BYTES = 64 * 1024 * 1024;
12
+ /** Said when a command ran without type checking. */
13
+ export const TYPECHECK_SKIPPED = "Types were not checked: node_modules/typescript is not the TypeScript install_sdk installs. To check them, run install_sdk (delete node_modules first if it came with the project).";
14
+ /** Whether `directory` holds the pinned TypeScript, as plain files (no link on the way). */
15
+ export async function mayTypeCheck(pin, directory) {
16
+ const folders = ["node_modules", "node_modules/typescript", "node_modules/typescript/lib"];
17
+ try {
18
+ for (const folder of folders) {
19
+ if (!(await lstat(join(directory, folder))).isDirectory())
20
+ return false;
21
+ }
22
+ for (const file of TYPESCRIPT_FILES) {
23
+ const path = join(directory, "node_modules", "typescript", file);
24
+ const info = await lstat(path);
25
+ if (!info.isFile() || info.size > MAX_FILE_BYTES)
26
+ return false;
27
+ const digest = createHash("sha256")
28
+ .update(await readFile(path))
29
+ .digest("hex");
30
+ if (digest !== pin.files[file])
31
+ return false;
32
+ }
33
+ return true;
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ }
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // The package version; scripts/build.mjs refuses a build where it differs
2
2
  // from package.json.
3
- export const VERSION = "0.1.3";
3
+ export const VERSION = "0.1.5";
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@overcrow/mcp",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@overcrow/mcp",
9
- "version": "0.1.3",
9
+ "version": "0.1.5",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@modelcontextprotocol/server": "2.3.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@overcrow/mcp",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "MCP server that lets an AI assistant create, check, test, audit and package PlayerVox OverCrow widgets.",
5
5
  "license": "MIT",
6
6
  "type": "module",