@cyanheads/mcp-ts-core 0.13.1 → 0.13.3

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 (46) hide show
  1. package/AGENTS.md +7 -7
  2. package/CLAUDE.md +7 -7
  3. package/README.md +2 -2
  4. package/changelog/0.12.x/0.12.2.md +1 -1
  5. package/changelog/0.13.x/0.13.2.md +43 -0
  6. package/changelog/0.13.x/0.13.3.md +44 -0
  7. package/changelog/0.8.x/0.8.11.md +2 -2
  8. package/dist/mcp-server/resources/utils/resourceHandlerFactory.d.ts.map +1 -1
  9. package/dist/mcp-server/resources/utils/resourceHandlerFactory.js +17 -9
  10. package/dist/mcp-server/resources/utils/resourceHandlerFactory.js.map +1 -1
  11. package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts +22 -2
  12. package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts.map +1 -1
  13. package/dist/mcp-server/tools/utils/toolHandlerFactory.js +216 -20
  14. package/dist/mcp-server/tools/utils/toolHandlerFactory.js.map +1 -1
  15. package/dist/mcp-server/transports/http/serverCard.d.ts +23 -0
  16. package/dist/mcp-server/transports/http/serverCard.d.ts.map +1 -1
  17. package/dist/mcp-server/transports/http/serverCard.js +7 -0
  18. package/dist/mcp-server/transports/http/serverCard.js.map +1 -1
  19. package/dist/testing/index.d.ts +5 -0
  20. package/dist/testing/index.d.ts.map +1 -1
  21. package/dist/testing/index.js +7 -2
  22. package/dist/testing/index.js.map +1 -1
  23. package/dist/utils/internal/error-handler/errorHandler.d.ts +33 -0
  24. package/dist/utils/internal/error-handler/errorHandler.d.ts.map +1 -1
  25. package/dist/utils/internal/error-handler/errorHandler.js +45 -3
  26. package/dist/utils/internal/error-handler/errorHandler.js.map +1 -1
  27. package/framework-skills/add-tool/SKILL.md +3 -3
  28. package/framework-skills/api-errors/SKILL.md +14 -9
  29. package/framework-skills/api-testing/SKILL.md +3 -1
  30. package/framework-skills/git-wrapup/SKILL.md +11 -7
  31. package/framework-skills/orchestrations/SKILL.md +3 -3
  32. package/framework-skills/polish-docs-meta/SKILL.md +4 -3
  33. package/framework-skills/release-and-publish/SKILL.md +6 -6
  34. package/framework-skills/release-pr-review/SKILL.md +16 -23
  35. package/framework-skills/tool-defs-analysis/SKILL.md +4 -4
  36. package/package.json +6 -6
  37. package/scripts/build.ts +28 -6
  38. package/scripts/clean-mcpb.ts +8 -2
  39. package/scripts/clean.ts +40 -4
  40. package/scripts/devcheck.ts +46 -15
  41. package/scripts/lint-packaging.ts +79 -4
  42. package/templates/.github/workflows/codeql.yml +39 -0
  43. package/templates/AGENTS.md +3 -1
  44. package/templates/CLAUDE.md +3 -1
  45. package/templates/package.json +2 -2
  46. package/templates/src/index.ts +4 -3
package/scripts/build.ts CHANGED
@@ -14,7 +14,7 @@
14
14
  */
15
15
 
16
16
  import { execFile } from 'node:child_process';
17
- import { readFileSync } from 'node:fs';
17
+ import { existsSync, readFileSync } from 'node:fs';
18
18
  import { readdir, stat } from 'node:fs/promises';
19
19
  import { dirname, join } from 'node:path';
20
20
  import { fileURLToPath } from 'node:url';
@@ -22,6 +22,32 @@ import { fileURLToPath } from 'node:url';
22
22
  const ROOT_DIR = join(dirname(fileURLToPath(import.meta.url)), '..');
23
23
  const DIST_DIR = join(ROOT_DIR, 'dist');
24
24
 
25
+ /** Where `bunx @cyanheads/mcp-ts-core init` writes the build tsconfig. */
26
+ const SCAFFOLD_BUILD_PROJECT = 'tsconfig.build.json';
27
+
28
+ /**
29
+ * Build tsconfig locations, in precedence order. A project may keep its project
30
+ * tsconfigs in `config/` or at the root, and this script ships to both
31
+ * verbatim, so the default is probed rather than hardcoded.
32
+ */
33
+ const BUILD_PROJECT_CANDIDATES = ['config/tsconfig.build.json', SCAFFOLD_BUILD_PROJECT];
34
+
35
+ /**
36
+ * The tsconfig to build: an explicit `--project <path>` verbatim — a missing
37
+ * one still reaches the compiler and fails there — otherwise the first
38
+ * candidate location present. With neither present the scaffold's layout is
39
+ * named, so the compiler error points at the file the project should have.
40
+ */
41
+ function resolveProject(argv: string[]): string {
42
+ const flagIndex = argv.indexOf('--project');
43
+ const explicit = flagIndex === -1 ? undefined : argv[flagIndex + 1];
44
+ if (explicit !== undefined) return explicit;
45
+ return (
46
+ BUILD_PROJECT_CANDIDATES.find((candidate) => existsSync(join(ROOT_DIR, candidate))) ??
47
+ SCAFFOLD_BUILD_PROJECT
48
+ );
49
+ }
50
+
25
51
  async function exec(
26
52
  cmd: string[],
27
53
  label: string,
@@ -92,11 +118,7 @@ function formatBytes(bytes: number): string {
92
118
  async function main() {
93
119
  // Read package info
94
120
  const pkg = JSON.parse(readFileSync(join(ROOT_DIR, 'package.json'), 'utf-8'));
95
- const projectIdx = process.argv.indexOf('--project');
96
- const project =
97
- projectIdx !== -1
98
- ? (process.argv[projectIdx + 1] ?? 'config/tsconfig.build.json')
99
- : 'config/tsconfig.build.json';
121
+ const project = resolveProject(process.argv);
100
122
 
101
123
  console.log(`\x1b[1mBuilding ${pkg.name}@${pkg.version}\x1b[0m`);
102
124
  console.log(`\x1b[2m tsconfig: ${project}\x1b[0m`);
@@ -33,7 +33,10 @@ import { fileURLToPath } from 'node:url';
33
33
  /**
34
34
  * Agent-doc entries under `node_modules/` that must not ship in a bundle.
35
35
  * KEEP IN SYNC with `AGENT_DOC_ENTRY` in `scripts/lint-packaging.ts`
36
- * (post-bundle content check) — a unit test asserts the two are identical.
36
+ * (post-bundle content check) — edit both literals together. The assertion that
37
+ * they match lives in the mcp-ts-core repository's own test suite; `tests/` is
38
+ * not part of the published package, so nothing enforces the pair in a server
39
+ * these scripts were copied into.
37
40
  */
38
41
  export const AGENT_DOC_ENTRY =
39
42
  /^node_modules\/.*(?:\/framework-skills\/|\/skills\/|\/\.claude\/|\/\.agents\/|\/SKILL\.md$)/;
@@ -41,7 +44,10 @@ export const AGENT_DOC_ENTRY =
41
44
  /**
42
45
  * Platform-specific native binding packages, which must not ship in a bundle.
43
46
  * KEEP IN SYNC with `NATIVE_BINDING_ENTRY` in `scripts/lint-packaging.ts`
44
- * (post-bundle content check) — a unit test asserts the two are identical.
47
+ * (post-bundle content check) — edit both literals together. The assertion that
48
+ * they match lives in the mcp-ts-core repository's own test suite; `tests/` is
49
+ * not part of the published package, so nothing enforces the pair in a server
50
+ * these scripts were copied into.
45
51
  *
46
52
  * `mcpb pack` archives the whole project directory, so a native dependency
47
53
  * contributes the build host's platform slice and nothing else — for
package/scripts/clean.ts CHANGED
@@ -1,12 +1,16 @@
1
1
  /**
2
2
  * @fileoverview Utility script to clean build artifacts and temporary directories.
3
3
  * @module scripts/clean
4
- * By default, it removes the 'dist' and 'logs' directories.
5
- * Custom directories can be specified as command-line arguments.
4
+ * By default, it removes the 'dist' and 'logs' directories plus every
5
+ * TypeScript build-info file the project's tsconfigs write — in the root and
6
+ * in 'config/', where a tsconfig kept there resolves its relative
7
+ * `tsBuildInfoFile` against itself.
8
+ * Custom directories can be specified as command-line arguments, which
9
+ * replace the default set entirely.
6
10
  * Works on all platforms using Node.js path normalization.
7
11
  *
8
12
  * @example
9
- * // Default directories (dist, logs):
13
+ * // Default targets (dist, logs, build info):
10
14
  * // bun run scripts/clean.ts
11
15
  *
12
16
  * // Custom directories:
@@ -21,6 +25,38 @@ interface CleanResult {
21
25
  status: 'cleaned' | 'skipped' | 'error';
22
26
  }
23
27
 
28
+ /**
29
+ * A TypeScript build-info file: the plain `.tsbuildinfo`, a `<name>.tsbuildinfo`,
30
+ * and the lane-suffixed `.tsbuildinfo.<lane>` forms a multi-tsconfig project
31
+ * writes (`tsBuildInfoFile: ".tsbuildinfo.worker"`).
32
+ */
33
+ const BUILD_INFO_FILE = /\.tsbuildinfo(\.[^.]*)?$/;
34
+
35
+ /**
36
+ * Directories a tsconfig may write its build info into. A `tsBuildInfoFile` is
37
+ * resolved against the tsconfig that declares it, so a project keeping its
38
+ * tsconfigs in `config/` leaves build info there rather than at the root.
39
+ */
40
+ const BUILD_INFO_DIRS = ['.', 'config'];
41
+
42
+ /** Every build-info file under the scanned directories, as root-relative paths. */
43
+ async function findBuildInfoFiles(root: string): Promise<string[]> {
44
+ const found = await Promise.all(
45
+ BUILD_INFO_DIRS.map(async (dir) => {
46
+ let entries: string[];
47
+ try {
48
+ entries = await readdir(resolve(root, dir));
49
+ } catch {
50
+ return []; // directory absent — nothing to clean there
51
+ }
52
+ return entries
53
+ .filter((entry) => BUILD_INFO_FILE.test(entry))
54
+ .map((entry) => (dir === '.' ? entry : `${dir}/${entry}`));
55
+ }),
56
+ );
57
+ return found.flat();
58
+ }
59
+
24
60
  /**
25
61
  * Validates that a resolved path stays within the project root.
26
62
  * Rejects absolute paths, '..' traversal, and paths that escape cwd.
@@ -46,7 +82,7 @@ const clean = async (): Promise<void> => {
46
82
  try {
47
83
  const root = process.cwd();
48
84
  const args = process.argv.slice(2);
49
- const buildInfoFiles = (await readdir(root)).filter((f) => f.endsWith('.tsbuildinfo'));
85
+ const buildInfoFiles = await findBuildInfoFiles(root);
50
86
  const dirsToClean = [...new Set(args.length > 0 ? args : ['dist', 'logs', ...buildInfoFiles])];
51
87
 
52
88
  console.log(`Cleaning directories: ${dirsToClean.join(', ')}`);
@@ -624,6 +624,13 @@ function classifyAuditVulns(output: string): { direct: string[]; upstream: strin
624
624
  // Define file extensions for linting and formatting
625
625
  const LINT_EXTS = ['.ts', '.tsx', '.js', '.jsx'];
626
626
 
627
+ /**
628
+ * Worker tsconfig locations, in precedence order. A project keeps its project
629
+ * tsconfigs in `config/` or at the root — the `init` scaffold writes the root
630
+ * form — and this script ships to both verbatim.
631
+ */
632
+ const WORKER_PROJECT_CANDIDATES = ['config/tsconfig.worker.json', 'tsconfig.worker.json'];
633
+
627
634
  const ALL_CHECKS: Check[] = [
628
635
  // Fast checks first (local operations, no network)
629
636
  {
@@ -703,18 +710,23 @@ const ALL_CHECKS: Check[] = [
703
710
  flag: '--no-packaging',
704
711
  canFix: false,
705
712
  // Validates env var alignment between manifest.json (MCPB bundle) and
706
- // server.json (MCP Registry), plus plugin marketplace manifests (#240), and
707
- // the bundle-content guards on .mcpbignore (#343). Runs when any of those
708
- // inputs is present; skipped cleanly when none exist — consumers on an
709
- // HTTP-only deploy are unaffected.
713
+ // server.json (MCP Registry), plus plugin marketplace manifests (#240), the
714
+ // bundle-content guards on .mcpbignore (#343), and the README version badge
715
+ // (#418). Runs when any of those inputs is present; skipped cleanly when
716
+ // none exist — consumers on an HTTP-only deploy are unaffected. README.md is
717
+ // a trigger in its own right: the badge check must gate a project that
718
+ // carries no bundle or plugin metadata at all, which the other three inputs
719
+ // only covered incidentally.
710
720
  getCommand: () => {
711
- const hasManifest = existsSync(path.join(ROOT_DIR, 'manifest.json'));
712
- const hasPluginManifest =
713
- existsSync(path.join(ROOT_DIR, '.claude-plugin/plugin.json')) ||
714
- existsSync(path.join(ROOT_DIR, '.codex-plugin/plugin.json')) ||
715
- existsSync(path.join(ROOT_DIR, '.codex-plugin/mcp.json'));
716
- const hasMcpbIgnore = existsSync(path.join(ROOT_DIR, '.mcpbignore'));
717
- if (!hasManifest && !hasPluginManifest && !hasMcpbIgnore) return null;
721
+ const inputs = [
722
+ 'manifest.json',
723
+ '.claude-plugin/plugin.json',
724
+ '.codex-plugin/plugin.json',
725
+ '.codex-plugin/mcp.json',
726
+ '.mcpbignore',
727
+ 'README.md',
728
+ ];
729
+ if (!inputs.some((input) => existsSync(path.join(ROOT_DIR, input)))) return null;
718
730
  return ['bun', 'run', 'scripts/lint-packaging.ts'];
719
731
  },
720
732
  tip: (c) =>
@@ -864,14 +876,20 @@ const ALL_CHECKS: Check[] = [
864
876
  canFix: false,
865
877
  // The workerd type environment is its own program: Cloudflare's ambient
866
878
  // globals cannot share one with @types/node's (#397). It reads the built
867
- // declarations, so it only has something to check after a build.
879
+ // declarations, so it only has something to check after a build. The
880
+ // tsconfig is looked for in both supported layouts — `config/` and the
881
+ // project root, which is where the `init` scaffold writes its tsconfigs
882
+ // (#440) — and the step skips only when neither carries one.
868
883
  getCommand: (ctx) => {
869
- if (!existsSync(path.join(ctx.rootDir, 'config', 'tsconfig.worker.json'))) return null;
884
+ const project = WORKER_PROJECT_CANDIDATES.find((candidate) =>
885
+ existsSync(path.join(ctx.rootDir, candidate)),
886
+ );
887
+ if (!project) return null;
870
888
  if (!existsSync(path.join(ctx.rootDir, 'dist'))) return null;
871
889
  return [
872
890
  path.join(ctx.rootDir, 'node_modules', '.bin', 'tsc'),
873
891
  '--project',
874
- 'config/tsconfig.worker.json',
892
+ project,
875
893
  '--noEmit',
876
894
  ];
877
895
  },
@@ -1030,8 +1048,21 @@ const UI = {
1030
1048
  return `${c.bold(c.yellow(`🔶 Skipping ${check.name}...`))}${c.dim(` (${reason})`)}`;
1031
1049
  },
1032
1050
 
1051
+ /**
1052
+ * The running-log line for a finished step. A result `isSuccess` demoted to a
1053
+ * warning is reported as one here too, on `printSummary`'s own guard
1054
+ * (`exitCode === 0 && warning`), so the two surfaces cannot disagree about a
1055
+ * single outcome (#344). A `{ success: false, warning }` return keeps its
1056
+ * non-zero exit and so still renders as a failure.
1057
+ */
1033
1058
  formatCheckResult(result: CommandResult, _mode: UIMode): string {
1034
- const { checkName, exitCode, duration } = result;
1059
+ const { checkName, exitCode, duration, warning } = result;
1060
+ if (exitCode === 0 && warning) {
1061
+ return [
1062
+ `${c.bold(c.yellow('⚠️'))} ${c.yellow(checkName)} ${c.yellow(`finished with a warning in ${duration}ms.`)}`,
1063
+ c.yellow(warning.replace(/^/gm, ' | ')),
1064
+ ].join('\n');
1065
+ }
1035
1066
  if (exitCode === 0) {
1036
1067
  return `${c.bold(c.green('✅'))} ${c.yellow(checkName)} ${c.green(`finished successfully in ${duration}ms.`)}`;
1037
1068
  }
@@ -54,6 +54,11 @@
54
54
  * path variables (the host delivers anything else as the literal string),
55
55
  * and an optional string option has `"default": ""` so a blank answer
56
56
  * arrives as empty rather than as the unsubstituted placeholder.
57
+ * 12. README version badge parity: a shields.io `Version-<semver>-` badge in
58
+ * `README.md` must carry the `package.json` `version`. The badge is the
59
+ * package's headline version on GitHub and npmjs.com and ships in the
60
+ * tarball, so a half-finished bump is publicly visible. Skipped when the
61
+ * README, the badge, or the package version is absent (issue #418).
57
62
  *
58
63
  * Every check skips cleanly when its input is absent — consumers who deleted
59
64
  * `manifest.json` for an HTTP-only deploy, or who haven't built a bundle,
@@ -99,8 +104,10 @@ const USER_CONFIG_REF = /^\$\{user_config\.([\w-]+)\}$/;
99
104
  /**
100
105
  * Root dev directories the scaffold template excludes from the bundle, and
101
106
  * whose `.mcpbignore` patterns must be anchored with `/` to avoid also
102
- * stripping nested runtime paths like `node_modules/x/framework-skills/`. Keep in step
103
- * with the directory entries in `templates/_.mcpbignore`.
107
+ * stripping nested runtime paths like `node_modules/x/framework-skills/`. Keep
108
+ * in step with the directory entries in this project's `.mcpbignore` — seeded
109
+ * from the mcp-ts-core repository's `templates/_.mcpbignore`, whose `_` prefix
110
+ * `init` drops on copy.
104
111
  */
105
112
  export const KNOWN_DEV_DIRS = ['framework-skills/', '.agents/', '.claude/'];
106
113
 
@@ -121,7 +128,10 @@ export const CRITICAL_RUNTIME_PATHS = [
121
128
  * `framework-skills/` is this framework's tree; `skills/` covers any other
122
129
  * dependency that vendors agent skills.
123
130
  * KEEP IN SYNC with `AGENT_DOC_ENTRY` in `scripts/clean-mcpb.ts` (the strip
124
- * step this check verifies) — a unit test asserts the two are identical.
131
+ * step this check verifies) — edit both literals together. The assertion that
132
+ * they match lives in the mcp-ts-core repository's own test suite; `tests/` is
133
+ * not part of the published package, so nothing enforces the pair in a server
134
+ * these scripts were copied into.
125
135
  */
126
136
  export const AGENT_DOC_ENTRY =
127
137
  /^node_modules\/.*(?:\/framework-skills\/|\/skills\/|\/\.claude\/|\/\.agents\/|\/SKILL\.md$)/;
@@ -129,7 +139,10 @@ export const AGENT_DOC_ENTRY =
129
139
  /**
130
140
  * Platform-specific native binding packages that must not ship in a bundle.
131
141
  * KEEP IN SYNC with `NATIVE_BINDING_ENTRY` in `scripts/clean-mcpb.ts` (the
132
- * strip step this check verifies) — a unit test asserts the two are identical.
142
+ * strip step this check verifies) — edit both literals together. The assertion
143
+ * that they match lives in the mcp-ts-core repository's own test suite;
144
+ * `tests/` is not part of the published package, so nothing enforces the pair
145
+ * in a server these scripts were copied into.
133
146
  */
134
147
  export const NATIVE_BINDING_ENTRY = /^node_modules\/@duckdb\/node-bindings-[^/]+\//;
135
148
 
@@ -673,6 +686,62 @@ export function checkPluginManifests(
673
686
  return errors;
674
687
  }
675
688
 
689
+ /**
690
+ * The shields.io static version badge, anchored on the `Version-` label and the
691
+ * `-` that closes the version segment. A literal `-` inside a badge segment is
692
+ * escaped as `--`, so the segment is "runs of non-dash characters joined by
693
+ * escaped dashes" — which also keeps the scan linear, since the alternation
694
+ * cannot match the same character two ways. Anchoring on the label and the
695
+ * trailing `-` tolerates colour, extension, and query-string variation without
696
+ * enumerating them, and matches no other badge: a live `img.shields.io/npm/v/…`
697
+ * badge has no `badge/Version-` path.
698
+ */
699
+ const README_VERSION_BADGE = /img\.shields\.io\/badge\/Version-([^-]*(?:--[^-]*)*)-/;
700
+
701
+ /**
702
+ * A version the badge can be compared against once its `--` escapes are
703
+ * decoded: the semver core, then at most one `-` prerelease segment and one
704
+ * `+` build segment. The two are separate optionals rather than one repeated
705
+ * `(?:[-+]…)*`, because `-` is itself a member of the segment character class
706
+ * — a repeated group can split a run of dashes two ways and backtracks
707
+ * exponentially on a segment the check is about to reject (CodeQL `js/redos`,
708
+ * CWE-1333). `+` is outside the class, so each segment's end is determined and
709
+ * the scan stays linear.
710
+ */
711
+ const READABLE_VERSION = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/;
712
+
713
+ /**
714
+ * Check 12: README version badge parity. When `README.md` carries a shields.io
715
+ * `Version-<semver>-` badge, its version must equal `package.json` `version` —
716
+ * the badge is the package's headline version on GitHub and npmjs.com, and it
717
+ * ships in the tarball, so a half-finished bump is publicly visible.
718
+ *
719
+ * Skipped when the README, the badge, or the package version is absent: a
720
+ * server that replaced the static badge with a live `npm/v` one has nothing to
721
+ * check, and a version-less `package.json` is the same fail-safe the
722
+ * plugin-manifest parity check applies. A badge that exists but cannot be read
723
+ * is drift the check cannot rule out, so it fails rather than skips.
724
+ */
725
+ export function checkReadmeVersionBadge(readme: string, packageVersion?: string): string[] {
726
+ if (!packageVersion) return [];
727
+
728
+ const segment = README_VERSION_BADGE.exec(readme)?.[1];
729
+ if (segment === undefined) return [];
730
+
731
+ const badgeVersion = segment.replaceAll('--', '-');
732
+ if (!READABLE_VERSION.test(badgeVersion)) {
733
+ return [
734
+ `README.md version badge segment is "${segment}" — not a readable version, so it cannot be ` +
735
+ `checked against the package.json version "${packageVersion}"; write the badge as ` +
736
+ `"Version-${packageVersion.replaceAll('-', '--')}-"`,
737
+ ];
738
+ }
739
+ if (badgeVersion === packageVersion) return [];
740
+ return [
741
+ `README.md version badge is "${badgeVersion}" — must equal the package.json version "${packageVersion}"`,
742
+ ];
743
+ }
744
+
676
745
  /** Read `packaging.pluginManifests` from devcheck.config.json; default on. */
677
746
  function pluginManifestsEnabled(): boolean {
678
747
  const cfg = tryReadJson<{ packaging?: { pluginManifests?: boolean } }>(
@@ -805,6 +874,12 @@ async function main(): Promise<void> {
805
874
  }
806
875
  }
807
876
 
877
+ // ── README version badge (check 12) ──
878
+ const readmePath = resolve('README.md');
879
+ if (existsSync(readmePath)) {
880
+ errors.push(...checkReadmeVersionBadge(readFileSync(readmePath, 'utf-8'), pkg?.version));
881
+ }
882
+
808
883
  // ── Plugin marketplace manifests (check 10) ──
809
884
  if (unscopedName && pkg?.name) {
810
885
  if (pluginManifestsEnabled()) {
@@ -0,0 +1,39 @@
1
+ # CodeQL static analysis — the one workflow every server carries.
2
+ # Verification (typecheck, lint, tests) is local; this file exists because CodeQL
3
+ # is GitHub-owned end to end and a workflow file is visible in the repo where a
4
+ # repo-level "default setup" is not. Default setup must be OFF for this to run.
5
+ name: CodeQL
6
+
7
+ on:
8
+ push:
9
+ branches: [main]
10
+ pull_request:
11
+ branches: [main]
12
+ schedule:
13
+ - cron: '30 6 * * 1'
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ analyze:
20
+ name: Analyze
21
+ runs-on: ubuntu-latest
22
+ timeout-minutes: 15
23
+ permissions:
24
+ security-events: write
25
+ contents: read
26
+ actions: read
27
+
28
+ steps:
29
+ - name: Checkout repository
30
+ uses: actions/checkout@v7
31
+
32
+ - name: Initialize CodeQL
33
+ uses: github/codeql-action/init@v4
34
+ with:
35
+ languages: javascript-typescript, actions
36
+ build-mode: none
37
+
38
+ - name: Perform CodeQL Analysis
39
+ uses: github/codeql-action/analyze@v4
@@ -311,7 +311,7 @@ Available skills:
311
311
  | `code-simplifier` | Post-session cleanup against `git diff` — modernize syntax, consolidate duplication, align with the codebase |
312
312
  | `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
313
313
  | `git-wrapup` | Land working-tree changes as a commit stack — version bump, changelog, verify, commit by concern, release commit on top. No tag, no push to main; opens the release PR when the project declares release PR mode |
314
- | `release-pr-review` | Review pass on an open release PR — simplifier + correctness review, fixup commits autosquashed into the stack, PR body kept in sync. Release PR mode only |
314
+ | `release-pr-review` | Review pass on an open release PR — simplifier + correctness review, fixes as ordinary commits on top of the stack, PR body kept in sync. Release PR mode only |
315
315
  | `release-and-publish` | Fast-forward merge (release PR mode) + tag + push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |
316
316
  | `maintenance` | Investigate changelogs, adopt upstream changes, sync skills to agent dirs |
317
317
  | `orchestrations` | Chain task skills into a gated multi-phase pipeline — build-out, QA-fix, update-ship — when you can spawn sub-agents |
@@ -362,6 +362,8 @@ When you complete a skill's checklist, check the boxes and add a completion time
362
362
  | `bun run changelog:check` | Verify `CHANGELOG.md` is in sync (used by devcheck) |
363
363
  | `bun run bundle` | Build, pack, and clean a `.mcpb` for one-click Claude Desktop install |
364
364
 
365
+ **CI is one file.** `.github/workflows/codeql.yml` (scaffolded) is the only GitHub Actions workflow: CodeQL is GitHub-owned end to end, and the file runs only while the repo's CodeQL *default setup* is turned off. Verification — `devcheck`, tests, the release gates — runs locally; don't add a workflow that re-runs it.
366
+
365
367
  ---
366
368
 
367
369
  ## Bundling
@@ -311,7 +311,7 @@ Available skills:
311
311
  | `code-simplifier` | Post-session cleanup against `git diff` — modernize syntax, consolidate duplication, align with the codebase |
312
312
  | `polish-docs-meta` | Finalize docs, README, metadata, and agent protocol for shipping |
313
313
  | `git-wrapup` | Land working-tree changes as a commit stack — version bump, changelog, verify, commit by concern, release commit on top. No tag, no push to main; opens the release PR when the project declares release PR mode |
314
- | `release-pr-review` | Review pass on an open release PR — simplifier + correctness review, fixup commits autosquashed into the stack, PR body kept in sync. Release PR mode only |
314
+ | `release-pr-review` | Review pass on an open release PR — simplifier + correctness review, fixes as ordinary commits on top of the stack, PR body kept in sync. Release PR mode only |
315
315
  | `release-and-publish` | Fast-forward merge (release PR mode) + tag + push + npm + MCP Registry + GH Release + Docker. Picks up from `git-wrapup` |
316
316
  | `maintenance` | Investigate changelogs, adopt upstream changes, sync skills to agent dirs |
317
317
  | `orchestrations` | Chain task skills into a gated multi-phase pipeline — build-out, QA-fix, update-ship — when you can spawn sub-agents |
@@ -362,6 +362,8 @@ When you complete a skill's checklist, check the boxes and add a completion time
362
362
  | `bun run changelog:check` | Verify `CHANGELOG.md` is in sync (used by devcheck) |
363
363
  | `bun run bundle` | Build, pack, and clean a `.mcpb` for one-click Claude Desktop install |
364
364
 
365
+ **CI is one file.** `.github/workflows/codeql.yml` (scaffolded) is the only GitHub Actions workflow: CodeQL is GitHub-owned end to end, and the file runs only while the repo's CodeQL *default setup* is turned off. Verification — `devcheck`, tests, the release gates — runs locally; don't add a workflow that re-runs it.
366
+
365
367
  ---
366
368
 
367
369
  ## Bundling
@@ -72,8 +72,8 @@
72
72
  "@vitest/coverage-istanbul": "4.1.11",
73
73
  "depcheck": "^1.4.7",
74
74
  "fast-check": "^4.9.0",
75
- "ignore": "^7.0.7",
76
- "tsc-alias": "^1.9.2",
75
+ "ignore": "^7.0.9",
76
+ "tsc-alias": "^1.9.5",
77
77
  "typescript": "^7.0.2",
78
78
  "vitest": "^4.1.11"
79
79
  }
@@ -17,9 +17,10 @@ await createApp({
17
17
  tools: [echoTool, echoAppTool],
18
18
  resources: [echoResource, echoAppUiResource],
19
19
  prompts: [echoPrompt],
20
- // instructions: 'Server-level orientation forwarded to the model on every initialize.\n' +
21
- // '- Use shortcut `X` for the most common case\n' +
22
- // '- Tools require auth via the `inventory:read` scope',
20
+ // Server-level orientation forwarded to the model on every initialize: two to three
21
+ // cohesive sentences in one string literal, written for the calling agent (which tool
22
+ // opens a workflow, what chains into what). Operator configuration stays in the README.
23
+ // instructions: 'Resolve a name to an id with example_search, then pass that id to example_get for the full record. Results are paged; follow nextOffset until it is absent.',
23
24
 
24
25
  // Session posture in code rather than in a Dockerfile. MCP_SESSION_MODE still
25
26
  // wins when it is set. Add `require: 'stateful'` — `{ default: 'stateful',