@cyanheads/mcp-ts-core 0.9.5 → 0.9.6

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/CLAUDE.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Developer Protocol
2
2
 
3
3
  **Package:** `@cyanheads/mcp-ts-core`
4
- **Version:** 0.9.5
4
+ **Version:** 0.9.6
5
5
  **Engines:** Bun ≥1.3.0, Node ≥24.0.0
6
6
  **MCP SDK:** `@modelcontextprotocol/sdk` ^1.29.0
7
7
  **Zod:** ^4.4.3
@@ -548,4 +548,6 @@ Badge order when both set: `· ⚠️ Breaking · 🛡️ Security`. Summary > 3
548
548
 
549
549
  ## Publishing
550
550
 
551
- If the user requests it, run the `release-and-publish` skill — it runs the verification gate (`devcheck`, `rebuild`, `test:all`), pushes commits and tags, and publishes to every applicable destination. The full reference:
551
+ If the user requests it, run the `release-and-publish` skill — it runs the verification gate (`devcheck`, `rebuild`, `test:all`), pushes commits and tags, and publishes to every applicable destination. After pushing, create a GitHub Release on the annotated tag (`gh release create v<VERSION> --verify-tag --notes-from-tag`) — no assets to attach, but the Release surfaces the tag's notes in the repo UI. **Skip the Docker build/push step** — this framework package is consumed via npm, not as a container image.
552
+
553
+ **Tag annotation subjects must omit the version number.** GitHub prepends `v<VERSION>:` to the release title when using `--notes-from-tag`. A subject like `0.9.5 — some change` renders as `v0.9.5: 0.9.5 — some change`. Write the subject as just the description: `mcpbignore recursive-match fix, zod to dependencies`.
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  [![Framework](https://img.shields.io/badge/Built%20on-@cyanheads/mcp--ts--core-67E8F9?style=flat-square)](https://www.npmjs.com/package/@cyanheads/mcp-ts-core)
9
9
 
10
- [![Version](https://img.shields.io/badge/Version-0.9.5-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![MCP Spec](https://img.shields.io/badge/MCP%20Spec-2025--11--25-8A2BE2.svg?style=flat-square)](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-11-25/changelog.mdx)
10
+ [![Version](https://img.shields.io/badge/Version-0.9.6-blue.svg?style=flat-square)](./CHANGELOG.md) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![MCP Spec](https://img.shields.io/badge/MCP%20Spec-2025--11--25-8A2BE2.svg?style=flat-square)](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-11-25/changelog.mdx)
11
11
 
12
12
  [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.29.0-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![TypeScript](https://img.shields.io/badge/TypeScript-^6.0.3-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.3.0%2B-blueviolet.svg?style=flat-square)](https://bun.sh/)
13
13
 
@@ -0,0 +1,20 @@
1
+ ---
2
+ summary: "lint-packaging validates manifest name scope and user_config fields; multi-server-orchestration and polish-docs-meta skill gaps from pipeline run 2"
3
+ breaking: false
4
+ ---
5
+
6
+ # 0.9.6 — 2026-05-23
7
+
8
+ ## Added
9
+
10
+ - **lint-packaging** validates `manifest.json` `name` doesn't contain an npm scope prefix (`@scope/`) — catches the scoped-name copy from `package.json` that renders in the mcpb install dialog ([#148](https://github.com/cyanheads/mcp-ts-core/issues/148))
11
+ - **lint-packaging** validates every `user_config` entry has `title` and `type` fields — catches the missing-field failures that `mcpb pack` would otherwise surface at release time ([#149](https://github.com/cyanheads/mcp-ts-core/issues/149))
12
+ - **lint-packaging** manifest-only checks (name scope, user_config fields) now run independently of `server.json`; cross-validation checks remain conditional on `server.json` presence
13
+
14
+ ## Changed
15
+
16
+ - **polish-docs-meta** v2.2: cross-file consistency section expanded — scope-stripped manifest name, `user_config` field completeness, `isRequired` accuracy, description alignment across 5 surfaces, baseline `package.json` keywords/topics
17
+ - **multi-server-orchestration** v1.2: parent gotcha table adds `--notes-from-tag` + `--repo` incompatibility
18
+ - **maintenance-pass** v1.2: pre-flight checks for `publish-mcp` script and `manifest.json` existence; Phase 3.5 double-check/normalization pass; gotchas for `internal`-audience skill sync, scoped manifest name, missing `user_config` fields
19
+ - **release-and-publish-pass** v1.3: Phase 5 adds MCPB bundle step (`bun run bundle` + `gh release create` with `.mcpb` asset); gotchas for `--notes-from-tag`+`--repo`, post-version tag movement, `user_config` field validation
20
+ - **wrapup-pass** v1.1: Phase 4 version bump step notes manifest name scope check
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyanheads/mcp-ts-core",
3
- "version": "0.9.5",
3
+ "version": "0.9.6",
4
4
  "mcpName": "io.github.cyanheads/mcp-ts-core",
5
5
  "description": "Agent-native TypeScript framework for building MCP servers. Declarative definitions with auth, multi-backend storage, OpenTelemetry, and first-class support for Bun/Node/Cloudflare Workers.",
6
6
  "main": "dist/core/index.js",
@@ -8,12 +8,16 @@
8
8
  * `npm run lint:packaging`.
9
9
  *
10
10
  * Checks:
11
- * 1. Every `${user_config.X}` reference in manifest `mcp_config.env` must
11
+ * 1. Manifest `name` must not contain a scope prefix (`@scope/`).
12
+ * 2. Every `user_config` entry must include `title` and `type` fields.
13
+ * 3. Every `${user_config.X}` reference in manifest `mcp_config.env` must
12
14
  * appear in server.json stdio `environmentVariables[]` (the registry
13
15
  * advertises the configurable knob the bundle surfaces).
14
- * 2. Every required stdio env var in server.json (no default) must appear
16
+ * 4. Every required stdio env var in server.json (no default) must appear
15
17
  * as a key in manifest `mcp_config.env` (the bundle can receive it).
16
18
  *
19
+ * Checks 1–2 run with `manifest.json` alone; 3–4 require `server.json`.
20
+ *
17
21
  * Skips cleanly when `manifest.json` is absent — consumers who deleted it for
18
22
  * an HTTP-only deploy should not fail this check.
19
23
  *
@@ -37,9 +41,16 @@ interface ServerJson {
37
41
  packages?: ServerJsonPackage[];
38
42
  }
39
43
 
44
+ interface ManifestUserConfigEntry {
45
+ title?: unknown;
46
+ type?: unknown;
47
+ [key: string]: unknown;
48
+ }
49
+
40
50
  interface Manifest {
51
+ name?: string;
41
52
  server?: { mcp_config?: { env?: Record<string, string> } };
42
- user_config?: Record<string, unknown>;
53
+ user_config?: Record<string, ManifestUserConfigEntry>;
43
54
  }
44
55
 
45
56
  const USER_CONFIG_REF = /^\$\{user_config\.([\w-]+)\}$/;
@@ -67,42 +78,59 @@ function main(): void {
67
78
  process.exit(1);
68
79
  }
69
80
 
70
- const serverJson = tryReadJson<ServerJson>(resolve('server.json'));
71
- if (!serverJson) {
72
- console.log('No server.json — skipping cross-validation.');
73
- process.exit(0);
74
- }
75
-
76
- const manifestEnv = manifest.server?.mcp_config?.env ?? {};
77
- const manifestEnvKeys = new Set(Object.keys(manifestEnv));
78
-
79
- const manifestUserConfigKeys = new Set(
80
- Object.entries(manifestEnv)
81
- .filter(([, v]) => typeof v === 'string' && USER_CONFIG_REF.test(v))
82
- .map(([k]) => k),
83
- );
84
-
85
- const stdioEnvVars = (serverJson.packages ?? [])
86
- .filter((p) => p.transport?.type === 'stdio')
87
- .flatMap((p) => p.environmentVariables ?? []);
88
- const stdioEnvNames = new Set(stdioEnvVars.map((v) => v.name));
89
- const requiredStdioEnvNames = new Set(
90
- stdioEnvVars.filter((v) => v.isRequired === true && v.default == null).map((v) => v.name),
91
- );
92
-
93
- const missingInServerJson = [...manifestUserConfigKeys].filter((k) => !stdioEnvNames.has(k));
94
- const missingInManifest = [...requiredStdioEnvNames].filter((k) => !manifestEnvKeys.has(k));
95
-
96
81
  const errors: string[] = [];
97
- if (missingInServerJson.length > 0) {
82
+
83
+ if (manifest.name?.includes('/')) {
98
84
  errors.push(
99
- `manifest.json references user_config env var(s) not advertised in server.json stdio environmentVariables[]: ${missingInServerJson.join(', ')}`,
85
+ `manifest.json "name" contains a scope prefix ("${manifest.name}") use the bare package name (e.g. "${manifest.name.split('/').pop()}")`,
100
86
  );
101
87
  }
102
- if (missingInManifest.length > 0) {
103
- errors.push(
104
- `server.json declares required stdio env var(s) without default missing from manifest.json mcp_config.env: ${missingInManifest.join(', ')}`,
88
+
89
+ const userConfig = manifest.user_config ?? {};
90
+ for (const [key, entry] of Object.entries(userConfig)) {
91
+ if (typeof entry !== 'object' || entry === null) continue;
92
+ const missing = (['title', 'type'] as const).filter(
93
+ (f) => typeof entry[f] !== 'string' || (entry[f] as string).length === 0,
94
+ );
95
+ if (missing.length > 0) {
96
+ errors.push(
97
+ `manifest.json user_config["${key}"] is missing required field(s): ${missing.join(', ')} — mcpb pack will reject this`,
98
+ );
99
+ }
100
+ }
101
+
102
+ const serverJson = tryReadJson<ServerJson>(resolve('server.json'));
103
+ if (serverJson) {
104
+ const manifestEnv = manifest.server?.mcp_config?.env ?? {};
105
+ const manifestEnvKeys = new Set(Object.keys(manifestEnv));
106
+
107
+ const manifestUserConfigKeys = new Set(
108
+ Object.entries(manifestEnv)
109
+ .filter(([, v]) => typeof v === 'string' && USER_CONFIG_REF.test(v))
110
+ .map(([k]) => k),
105
111
  );
112
+
113
+ const stdioEnvVars = (serverJson.packages ?? [])
114
+ .filter((p) => p.transport?.type === 'stdio')
115
+ .flatMap((p) => p.environmentVariables ?? []);
116
+ const stdioEnvNames = new Set(stdioEnvVars.map((v) => v.name));
117
+ const requiredStdioEnvNames = new Set(
118
+ stdioEnvVars.filter((v) => v.isRequired === true && v.default == null).map((v) => v.name),
119
+ );
120
+
121
+ const missingInServerJson = [...manifestUserConfigKeys].filter((k) => !stdioEnvNames.has(k));
122
+ const missingInManifest = [...requiredStdioEnvNames].filter((k) => !manifestEnvKeys.has(k));
123
+
124
+ if (missingInServerJson.length > 0) {
125
+ errors.push(
126
+ `manifest.json references user_config env var(s) not advertised in server.json stdio environmentVariables[]: ${missingInServerJson.join(', ')}`,
127
+ );
128
+ }
129
+ if (missingInManifest.length > 0) {
130
+ errors.push(
131
+ `server.json declares required stdio env var(s) without default missing from manifest.json mcp_config.env: ${missingInManifest.join(', ')}`,
132
+ );
133
+ }
106
134
  }
107
135
 
108
136
  if (errors.length === 0) {
@@ -4,7 +4,7 @@ description: >
4
4
  Orchestrate parallel sub-agent fanouts across one or more MCP server projects — the same workflow run independently per target. Use for greenfield builds across N new servers, maintenance passes across N existing ones, or any repeatable workflow that benefits from fresh-context per-target sub-agents. Encodes the orient template every sub-agent needs (CLAUDE.md chain + list-skills + spec artifacts), the universal hard rules around git tooling and authorization, common gotchas that bite across runs, and a router into per-scenario references for the phase pattern.
5
5
  metadata:
6
6
  author: cyanheads
7
- version: "1.1"
7
+ version: "1.2"
8
8
  audience: internal
9
9
  type: workflow
10
10
  ---
@@ -118,6 +118,7 @@ These commonly bite across all scenarios. Scenario-specific gotchas live in thei
118
118
  | 6 | Independent agents diverge on incidental conventions (scoping, scripts, README hero) | Plan an explicit normalization pass; don't expect alignment for free |
119
119
  | 7 | Sub-agent skips the orient block and proceeds with pattern-matched defaults | Put orient as a numbered prerequisite in the prompt with "Only after that, begin the task"; spot-check the first tool calls in the agent's response |
120
120
  | 8 | Sub-agent runs `git stash` to "test something safely" | Restate the global rule verbatim in every sub-agent prompt that may touch git: "NEVER `git stash` for any reason." |
121
+ | 9 | `gh release create --notes-from-tag` fails when combined with `--repo` flag | `gh` CLI limitation. Always `cd` into the target repo dir for `gh release` commands; don't use `--repo` with `--notes-from-tag` |
121
122
 
122
123
  ## Extending the pattern
123
124
 
@@ -4,7 +4,7 @@ description: >
4
4
  Multi-server-orchestration reference for maintenance passes. Drives parallel `bun update --latest`, changelog investigation (via the changelog skill), framework adoption per the maintenance skill's auto-adopt rule, skill/script sync (Phase A/B/C), and verification across N existing MCP server projects. Optional Bash-git wrap-up fanout commits adoptions after user authorization.
5
5
  metadata:
6
6
  author: cyanheads
7
- version: "1.1"
7
+ version: "1.2"
8
8
  audience: internal
9
9
  type: reference
10
10
  ---
@@ -27,7 +27,9 @@ Before spawning any sub-agents:
27
27
  2. **Verify each target is a git repo with a clean working tree.** Run `git status` per target. Halt if any is dirty — user fixes locally and re-invokes.
28
28
  3. **Verify each target has `scripts/list-skills.ts` and the `list-skills` package script.** Both ship via `init`; older projects pick them up on the next `maintenance` Phase C sync — which is what's about to run. If missing at this moment, that's fine; note it and the sub-agent will pick them up.
29
29
  4. **Verify each target has the `maintenance` skill available** (in `skills/` or `.claude/skills/`). If missing, that's a sign the project hasn't been initialized from a recent framework version — flag it; the sub-agent can still work from the package's copy at `node_modules/@cyanheads/mcp-ts-core/skills/maintenance/SKILL.md`.
30
- 5. **Clarify the user authorization scope.** Do they want sub-agents to commit/push at the end, or stop at "changes applied, working tree dirty, awaiting review"? Default is the latter.
30
+ 5. **Check `publish-mcp` script presence** when `server.json` exists. If missing, flag it the maintenance sub-agent or a follow-up agent should add it.
31
+ 6. **Check `manifest.json` existence.** If missing and the project has `server.json`, flag it — the maintenance sub-agent should scaffold it from `templates/manifest.json` during framework adoption (Step 6).
32
+ 7. **Clarify the user authorization scope.** Do they want sub-agents to commit/push at the end, or stop at "changes applied, working tree dirty, awaiting review"? Default is the latter.
31
33
 
32
34
  ## Phase pattern
33
35
 
@@ -83,6 +85,19 @@ The orchestrator collects each sub-agent's Step 8 summary and produces a consoli
83
85
 
84
86
  Wait for user direction before Phase 4 — they may want to inspect diffs locally first.
85
87
 
88
+ ### Phase 3.5: Double-check / normalization pass (recommended)
89
+
90
+ Independent maintenance agents diverge on incidental choices and miss adoption sites under context pressure. A lightweight follow-up fanout catches gaps before wrap-up:
91
+
92
+ - **Adoption gaps** — features the updated skills say to do that weren't applied (error code semantic audit, missing scaffolding files like `manifest.json`/`.mcpbignore`, `publish-mcp` script)
93
+ - **Audience compliance** — only skills with `metadata.audience: external` should be in project `skills/`; agents sometimes sync `internal`-audience skills
94
+ - **Content accuracy** — `isRequired` flags in `server.json` match the upstream API's actual requirement; `manifest.json` `name` doesn't include the npm scope prefix; `user_config` entries have required `title` and `type` fields
95
+ - **Cross-target consistency** — if a feature shows up in 3 of 5 Step 8 summaries, the other 2 likely missed it
96
+
97
+ These agents should **fix, not just report** — analysis-only agents create unnecessary follow-up. After fixing, re-run `bun run rebuild && bun run devcheck && bun run test`.
98
+
99
+ Use a lighter model (e.g. Sonnet) for this pass — it's verification and targeted fixes, not deep adoption work.
100
+
86
101
  ### Phase 4: Wrap-up fanout (optional, Bash git only)
87
102
 
88
103
  Run only after explicit user authorization. Per-target commit decisions are driven by the change shape:
@@ -110,10 +125,13 @@ If the maintenance pass should drive a version bump (breaking framework upgrade,
110
125
  | 5 | Sub-agent runs write git commands despite instruction (commit/push/reset/stash/etc.) | Restate the no-write-git list + the no-`stash` rule in the prompt body; verify via `git log --oneline -1` per target after Phase 2 — should show no new commits since pre-flight |
111
126
  | 6 | Targets at the same framework version produce inconsistent adoption choices | Usually means one agent missed a site; spot-check the Step 8 "Features adopted" lists across targets. If a feature shows up for 3 of 4, the 4th likely missed it — spawn a narrow finish-pass agent for that target |
112
127
  | 7 | Big monorepo or many adoptions cause context exhaustion in a sub-agent | Narrow the prompt: if a target has many breaking framework changes, split the sub-agent's work into "update deps + verify" and "adopt features" as two phases against that target |
128
+ | 8 | Agent syncs `internal`-audience skills into project `skills/` | Restate in the prompt: "Only sync skills with `metadata.audience: external`." The maintenance skill's Phase A step 2 says this, but agents miss it under context pressure |
129
+ | 9 | `manifest.json` scaffolded with scoped name from `package.json` (e.g. `@cyanheads/bls-mcp-server`) — renders in the mcpb install dialog | Double-check pass should verify `manifest.json` `name` doesn't contain `/`; the `polish-docs-meta` skill's cross-file consistency section covers this |
130
+ | 10 | `manifest.json` `user_config` entries missing required `title`/`type` fields — `mcpb pack` fails at release time | Agents scaffold from memory, not the template. Double-check pass should verify all `user_config` entries have `title` and `type` |
113
131
 
114
132
  ## Checklist
115
133
 
116
- - [ ] Pre-flight: target list confirmed, clean working trees verified, `list-skills` presence noted per target, `maintenance` skill availability noted per target, auth scope clarified with user
134
+ - [ ] Pre-flight: target list confirmed, clean working trees verified, `list-skills` presence noted per target, `maintenance` skill availability noted per target, `publish-mcp` and `manifest.json` presence noted, auth scope clarified with user
117
135
  - [ ] Phase 2: maintenance fanout spawned; each sub-agent returned a Step 8 summary
118
136
  - [ ] All targets: green `bun run devcheck` and `bun run test` post-adoption
119
137
  - [ ] Phase 3: consolidated roll-up presented to user with per-target headlines, cross-target patterns, open decisions, outliers
@@ -4,7 +4,7 @@ description: >
4
4
  Multi-server-orchestration reference for release-and-publish passes — the end-to-end ship workflow combining wrap-up (version bump, changelog, commit, annotated tag) and publish (push + npm + MCP Registry + GHCR) across N MCP server projects. Drives parallel verification → README polish → wrap-up (Bash git, local only — distilled from `git_wrapup_instructions`) → publish (via the standalone `release-and-publish` skill per target) → optional GH issue closure. Phase 5 runs serial when npm 2FA prompts interactively; parallel when bypass is configured. Disambiguated from the single-target `release-and-publish` skill it invokes per target.
5
5
  metadata:
6
6
  author: cyanheads
7
- version: "1.2"
7
+ version: "1.3"
8
8
  audience: internal
9
9
  type: reference
10
10
  ---
@@ -137,8 +137,9 @@ Each target invokes the `release-and-publish` skill end-to-end. Execution mode d
137
137
  > 3. Push commits and tags to origin via Bash git
138
138
  > 4. `bun publish --access public` (npm — uses the configured bypass token)
139
139
  > 5. `bun run publish-mcp` if `server.json` exists (MCP Registry)
140
- > 6. `docker buildx build --platform linux/amd64,linux/arm64 --push ...` if `Dockerfile` exists (GHCR)
141
- > 7. Report deployed artifact URLs (npm, MCP Registry, GHCR)
140
+ > 6. `bun run bundle` + `gh release create v<version> --verify-tag --notes-from-tag <dist/*.mcpb>` if `manifest.json` exists (MCPB GitHub Release). Must run from inside the repo dir — `--notes-from-tag` is incompatible with `--repo`.
141
+ > 7. `docker buildx build --platform linux/amd64,linux/arm64 --push ...` if `Dockerfile` exists (GHCR)
142
+ > 8. Report deployed artifact URLs (npm, MCP Registry, GitHub Release, GHCR)
142
143
  >
143
144
  > Honor the skill's retry/halt protocol — transient network errors retry up to 2× with backoff; idempotent-success signals ("version already exists", "cannot publish duplicate version") are treated as success and proceed. Bash git for all git ops. Never skip the verification gate.
144
145
 
@@ -176,6 +177,9 @@ Skip Phase 6 for any target whose Phase 5 didn't complete — there's nothing to
176
177
  | 8 | Annotated tag message bloats into a CHANGELOG copy | Restate the rule in Phase 4 prompt: terse release theme + notable changes + dep arrows in `pkg ^old → ^new` form. Length is earned |
177
178
  | 9 | Sub-agent uses `git-mcp-server` instead of Bash git in Phase 4 or 5 | Hard Rule 1 restated explicitly in every fanout prompt that touches git |
178
179
  | 10 | Failed publish leaves a tag pushed but no npm package — looks shipped, isn't | Collect per-destination status per target in Phase 5 roll-up; surface partial-state targets explicitly to the user before Phase 6 |
180
+ | 11 | `gh release create --notes-from-tag` fails with `--repo` flag | `gh` CLI limitation. Always `cd` into the target repo dir for `gh release` commands instead of using `--repo` |
181
+ | 12 | Post-version doc changes (install badges, description fixes) land after the version commit — tag points at stale content | Move the tag forward: delete remote release, delete remote+local tag, recreate tag at new HEAD with same annotation, re-push, recreate release with `.mcpb`. This is authorized within the pipeline for same-day follow-ups |
182
+ | 13 | `mcpb pack` fails because `manifest.json` `user_config` entries are missing `title`/`type` fields | Verify `manifest.json` `user_config` entries during Phase 3 or a pre-Phase-5 check; the `polish-docs-meta` skill's cross-file consistency section covers this |
179
183
 
180
184
  ## Checklist
181
185
 
@@ -4,7 +4,7 @@ description: >
4
4
  Multi-server-orchestration reference for git wrap-up passes — distilled from `git-mcp-server`'s `git_wrapup_instructions` protocol. Drives parallel verification → optional doc review → wrap-up (version bump, changelog, commit, annotated tag — Bash git, local only, no push) → roll-up across N MCP server projects. Stops at "committed and tagged locally". No push, no publish — those are separate, separately-authorized workflows.
5
5
  metadata:
6
6
  author: cyanheads
7
- version: "1.0"
7
+ version: "1.1"
8
8
  audience: internal
9
9
  type: reference
10
10
  ---
@@ -100,7 +100,7 @@ One sub-agent per target. The agent executes the seven acceptance criteria via B
100
100
  > 2. **Version bump.** Start from current `package.json` `version`; apply the bump intent (`[patch/minor/major or explicit string]`). Bump every place version is declared:
101
101
  > - `package.json` `version`
102
102
  > - `server.json` `version` at the top level AND every `packages[].version` entry
103
- > - `manifest.json` (if present) `version`
103
+ > - `manifest.json` (if present) `version`. Also verify `name` doesn't include the npm scope prefix — it should be the bare package name (e.g. `bls-mcp-server`, not `@cyanheads/bls-mcp-server`)
104
104
  > - README version badge and any hero pinning
105
105
  > - Dockerfile OCI labels (if pinned to version)
106
106
  > - Any agent-instruction file (`CLAUDE.md`, `AGENTS.md`) that pins the version
@@ -4,7 +4,7 @@ description: >
4
4
  Finalize documentation and project metadata for a ship-ready MCP server. Use after implementation is complete, tests pass, and devcheck is clean. Safe to run at any stage — each step checks current state and only acts on what still needs work.
5
5
  metadata:
6
6
  author: cyanheads
7
- version: "2.1"
7
+ version: "2.2"
8
8
  audience: external
9
9
  type: workflow
10
10
  ---
@@ -181,7 +181,11 @@ If the project ships as an `.mcpb` bundle for Claude Desktop (check for `manifes
181
181
 
182
182
  - `manifest.json` version matches `package.json` version
183
183
  - Env var names in `manifest.json` (`mcp_config.env` + `user_config`) match `server.json` `environmentVariables` — `lint:packaging` enforces this, but verify the set is complete
184
- - `manifest.json` `name` and `description` match `package.json`
184
+ - `manifest.json` `name` matches `package.json` name **without the npm scope prefix** (e.g. `bls-mcp-server`, not `@cyanheads/bls-mcp-server`); `description` matches `package.json`
185
+ - `manifest.json` `user_config` entries must include `title` and `type` fields — `mcpb pack` validates these
186
+ - `server.json` env var `isRequired` must match the upstream API's actual requirement — if the API works without the value (rate-limited, DEMO_KEY fallback, polite pool), mark `isRequired: false` and describe the tradeoff in the description
187
+ - Server description aligned across all surfaces: `package.json`, `manifest.json`, `server.json` (condensed, hard 100-char limit), README header `<p><b>`, and GitHub repo description (`gh repo edit --description`)
188
+ - `package.json` `keywords` include baseline terms: `mcp`, `mcp-server`, `model-context-protocol`, `typescript`, `bun`, `stdio`, `streamable-http`, plus data-domain terms. GitHub repo topics (`gh repo edit --add-topic`) should match.
185
189
 
186
190
  **README install badges:**
187
191
 
@@ -4,7 +4,7 @@ description: >
4
4
  Ship a release end-to-end across every registry the project targets (npm, MCP Registry, GitHub Releases for `.mcpb` bundles, GHCR). Runs the final verification gate, pushes commits and tags, then publishes to each applicable destination. Assumes git wrapup (version bumps, changelog, commit, annotated tag) is already complete — this skill is the post-wrapup publish workflow. Retries transient network failures on publish steps; halts with a partial-state report when retries are exhausted or the failure is terminal.
5
5
  metadata:
6
6
  author: cyanheads
7
- version: "2.4"
7
+ version: "2.5"
8
8
  audience: external
9
9
  type: workflow
10
10
  ---
@@ -131,7 +131,7 @@ Halt on any publisher error other than "cannot publish duplicate version".
131
131
 
132
132
  Only if `manifest.json` exists at the repo root (otherwise skip).
133
133
 
134
- Build the bundle, then create a Release on the existing annotated tag and attach the `.mcpb`. The Release sits on top of the tag from wrapup — `--verify-tag` enforces that the tag already exists on the remote and prevents `gh` from creating a lightweight tag that would shadow the annotated one. `--notes-from-tag` pulls release notes directly from the annotated tag message (no duplication).
134
+ Build the bundle, then create a Release on the existing annotated tag and attach the `.mcpb`. The Release sits on top of the tag from wrapup — `--verify-tag` enforces that the tag already exists on the remote and prevents `gh` from creating a lightweight tag that would shadow the annotated one. `--notes-from-tag` pulls release notes directly from the annotated tag message (no duplication). Note: GitHub prepends `v<VERSION>:` to the release title, so the tag annotation subject must omit the version number to avoid stutter.
135
135
 
136
136
  ```bash
137
137
  bun run bundle # produces dist/<name>.mcpb (stable filename, no version)
@@ -1,7 +0,0 @@
1
- {"level":40,"time":1779525180302,"env":"testing","version":"0.9.5","pid":19119,"transport":"http","requestId":"8I7DR-QK3Q5","timestamp":"2026-05-23T08:33:00.301Z","operation":"TransportManager.start","component":"HttpTransportSetup","msg":"MCP_ALLOWED_ORIGINS is not set — CORS is wildcard for CLI clients; browser Origin headers are restricted to loopback. Set MCP_ALLOWED_ORIGINS for production deployments accepting remote browser origins."}
2
- {"level":40,"time":1779525182035,"env":"testing","version":"0.9.5","pid":19119,"transport":"http","requestId":"8I7DR-QK3Q5","timestamp":"2026-05-23T08:33:00.301Z","operation":"TransportManager.start","component":"HttpTransportSetup","sessionId":"not-a-real-session-1779525182035","msg":"Session validation failed - invalid or hijacked session"}
3
- {"level":50,"time":1779525186246,"env":"testing","version":"0.0.0-test","pid":19207,"requestId":"5BTFB-9TCTE","timestamp":"2026-05-23T08:33:06.245Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"5798bcd4468074f87ca9d8bce75ddd7d971b63fce0ae460a8a1c93ef422b742e","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"5798bcd4468074f87ca9d8bce75ddd7d971b63fce0ae460a8a1c93ef422b742e","toolName":"scoped_echo","requestId":"5BTFB-9TCTE","timestamp":"2026-05-23T08:33:06.245Z","tenantId":"authz-tenant","operation":"HandleToolRequest","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"originalErrorName":"McpError","originalMessage":"Insufficient permissions.","originalStack":"McpError: Insufficient permissions.\n at forbidden (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:84:58)\n at withRequiredScopes (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/authUtils.js:68:15)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:146:17)\n at executeToolHandler (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:231:34)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Insufficient permissions.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:184:26)\n at executeToolHandler (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:231:34)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43)\n at processTicksAndRejections (native:7:39)","msg":"Error in tool:scoped_echo: Insufficient permissions."}
4
- {"level":50,"time":1779525186253,"env":"testing","version":"0.0.0-test","pid":19207,"requestId":"KLWMG-6WVT6","timestamp":"2026-05-23T08:33:06.253Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"00625ce1a231065e2a92c4423cf94c6f9dc139a6e16bfbba8888d34226fde894","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["openid","email","profile","offline_access"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"00625ce1a231065e2a92c4423cf94c6f9dc139a6e16bfbba8888d34226fde894","toolName":"scoped_echo","requestId":"KLWMG-6WVT6","timestamp":"2026-05-23T08:33:06.253Z","tenantId":"authz-tenant","operation":"HandleToolRequest","auth":{"sub":"authz-user","scopes":["openid","email","profile","offline_access"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"originalErrorName":"McpError","originalMessage":"Insufficient permissions.","originalStack":"McpError: Insufficient permissions.\n at forbidden (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:84:58)\n at withRequiredScopes (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/authUtils.js:68:15)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:146:17)\n at executeToolHandler (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:231:34)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Insufficient permissions.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:184:26)\n at executeToolHandler (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:231:34)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43)\n at processTicksAndRejections (native:7:39)","msg":"Error in tool:scoped_echo: Insufficient permissions."}
5
- {"level":50,"time":1779525187678,"env":"testing","version":"0.9.5","pid":19245,"requestId":"ET1UM-D2PSZ","timestamp":"2026-05-23T08:33:07.678Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"POST","errorData":{"path":"/mcp","method":"POST","requestId":"ET1UM-D2PSZ","timestamp":"2026-05-23T08:33:07.678Z","operation":"httpErrorHandler","originalErrorName":"McpError","originalMessage":"Missing or invalid Authorization header. Bearer scheme required.","originalStack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at unauthorized (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:86:61)\n at authMiddleware (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/authMiddleware.js:64:19)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpTransport.js:232:22)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at cors2 (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/middleware/cors/index.js:79:11)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpErrorHandler.js:59:39)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:26:25)\n at processTicksAndRejections (native:7:39)","msg":"Error in httpTransport: Missing or invalid Authorization header. Bearer scheme required."}
6
- {"level":50,"time":1779525187693,"env":"testing","version":"0.9.5","pid":19245,"requestId":"KHCYN-C8IAD","timestamp":"2026-05-23T08:33:07.693Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"POST","errorData":{"path":"/mcp","method":"POST","requestId":"KHCYN-C8IAD","timestamp":"2026-05-23T08:33:07.693Z","operation":"httpErrorHandler","originalErrorName":"McpError","originalMessage":"Token has expired.","originalStack":"McpError: Token has expired.\n at unauthorized (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:86:61)\n at handleJoseVerifyError (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/claimParser.js:72:11)\n at verify (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/strategies/jwtStrategy.js:91:13)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Token has expired.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpErrorHandler.js:59:39)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:26:25)\n at processTicksAndRejections (native:7:39)","msg":"Error in httpTransport: Token has expired."}
7
- {"level":50,"time":1779525187697,"env":"testing","version":"0.9.5","pid":19245,"requestId":"GVI8J-0B2W0","timestamp":"2026-05-23T08:33:07.697Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"GET","errorData":{"path":"/mcp","method":"GET","requestId":"GVI8J-0B2W0","timestamp":"2026-05-23T08:33:07.697Z","operation":"httpErrorHandler","originalErrorName":"McpError","originalMessage":"Missing or invalid Authorization header. Bearer scheme required.","originalStack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at unauthorized (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:86:61)\n at authMiddleware (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/authMiddleware.js:64:19)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpTransport.js:232:22)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at cors2 (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/middleware/cors/index.js:79:11)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpErrorHandler.js:59:39)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:26:25)\n at processTicksAndRejections (native:7:39)","msg":"Error in httpTransport: Missing or invalid Authorization header. Bearer scheme required."}
@@ -1,5 +0,0 @@
1
- {"level":50,"time":1779525186246,"env":"testing","version":"0.0.0-test","pid":19207,"requestId":"5BTFB-9TCTE","timestamp":"2026-05-23T08:33:06.245Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"5798bcd4468074f87ca9d8bce75ddd7d971b63fce0ae460a8a1c93ef422b742e","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"5798bcd4468074f87ca9d8bce75ddd7d971b63fce0ae460a8a1c93ef422b742e","toolName":"scoped_echo","requestId":"5BTFB-9TCTE","timestamp":"2026-05-23T08:33:06.245Z","tenantId":"authz-tenant","operation":"HandleToolRequest","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"originalErrorName":"McpError","originalMessage":"Insufficient permissions.","originalStack":"McpError: Insufficient permissions.\n at forbidden (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:84:58)\n at withRequiredScopes (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/authUtils.js:68:15)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:146:17)\n at executeToolHandler (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:231:34)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Insufficient permissions.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:184:26)\n at executeToolHandler (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:231:34)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43)\n at processTicksAndRejections (native:7:39)","msg":"Error in tool:scoped_echo: Insufficient permissions."}
2
- {"level":50,"time":1779525186253,"env":"testing","version":"0.0.0-test","pid":19207,"requestId":"KLWMG-6WVT6","timestamp":"2026-05-23T08:33:06.253Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"00625ce1a231065e2a92c4423cf94c6f9dc139a6e16bfbba8888d34226fde894","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["openid","email","profile","offline_access"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"00625ce1a231065e2a92c4423cf94c6f9dc139a6e16bfbba8888d34226fde894","toolName":"scoped_echo","requestId":"KLWMG-6WVT6","timestamp":"2026-05-23T08:33:06.253Z","tenantId":"authz-tenant","operation":"HandleToolRequest","auth":{"sub":"authz-user","scopes":["openid","email","profile","offline_access"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"originalErrorName":"McpError","originalMessage":"Insufficient permissions.","originalStack":"McpError: Insufficient permissions.\n at forbidden (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:84:58)\n at withRequiredScopes (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/authUtils.js:68:15)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:146:17)\n at executeToolHandler (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:231:34)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Insufficient permissions.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:184:26)\n at executeToolHandler (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:231:34)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43)\n at processTicksAndRejections (native:7:39)","msg":"Error in tool:scoped_echo: Insufficient permissions."}
3
- {"level":50,"time":1779525187678,"env":"testing","version":"0.9.5","pid":19245,"requestId":"ET1UM-D2PSZ","timestamp":"2026-05-23T08:33:07.678Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"POST","errorData":{"path":"/mcp","method":"POST","requestId":"ET1UM-D2PSZ","timestamp":"2026-05-23T08:33:07.678Z","operation":"httpErrorHandler","originalErrorName":"McpError","originalMessage":"Missing or invalid Authorization header. Bearer scheme required.","originalStack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at unauthorized (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:86:61)\n at authMiddleware (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/authMiddleware.js:64:19)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpTransport.js:232:22)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at cors2 (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/middleware/cors/index.js:79:11)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpErrorHandler.js:59:39)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:26:25)\n at processTicksAndRejections (native:7:39)","msg":"Error in httpTransport: Missing or invalid Authorization header. Bearer scheme required."}
4
- {"level":50,"time":1779525187693,"env":"testing","version":"0.9.5","pid":19245,"requestId":"KHCYN-C8IAD","timestamp":"2026-05-23T08:33:07.693Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"POST","errorData":{"path":"/mcp","method":"POST","requestId":"KHCYN-C8IAD","timestamp":"2026-05-23T08:33:07.693Z","operation":"httpErrorHandler","originalErrorName":"McpError","originalMessage":"Token has expired.","originalStack":"McpError: Token has expired.\n at unauthorized (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:86:61)\n at handleJoseVerifyError (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/claimParser.js:72:11)\n at verify (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/strategies/jwtStrategy.js:91:13)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Token has expired.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpErrorHandler.js:59:39)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:26:25)\n at processTicksAndRejections (native:7:39)","msg":"Error in httpTransport: Token has expired."}
5
- {"level":50,"time":1779525187697,"env":"testing","version":"0.9.5","pid":19245,"requestId":"GVI8J-0B2W0","timestamp":"2026-05-23T08:33:07.697Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"GET","errorData":{"path":"/mcp","method":"GET","requestId":"GVI8J-0B2W0","timestamp":"2026-05-23T08:33:07.697Z","operation":"httpErrorHandler","originalErrorName":"McpError","originalMessage":"Missing or invalid Authorization header. Bearer scheme required.","originalStack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at unauthorized (/Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:86:61)\n at authMiddleware (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/authMiddleware.js:64:19)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpTransport.js:232:22)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:22:23)\n at cors2 (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/middleware/cors/index.js:79:11)\n at processTicksAndRejections (native:7:39)"},"stack":"McpError: Missing or invalid Authorization header. Bearer scheme required.\n at handleError (/Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:23)\n at <anonymous> (/Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/http/httpErrorHandler.js:59:39)\n at dispatch (/Users/casey/Developer/github/mcp-ts-core/node_modules/hono/dist/compose.js:26:25)\n at processTicksAndRejections (native:7:39)","msg":"Error in httpTransport: Missing or invalid Authorization header. Bearer scheme required."}
File without changes