@cyanheads/mcp-ts-core 0.9.4 → 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 +22 -108
- package/README.md +1 -1
- package/biome.json +1 -1
- package/changelog/0.9.x/0.9.5.md +17 -0
- package/changelog/0.9.x/0.9.6.md +20 -0
- package/package.json +4 -4
- package/scripts/lint-packaging.ts +62 -34
- package/skills/maintenance/SKILL.md +2 -1
- package/skills/multi-server-orchestration/SKILL.md +2 -1
- package/skills/multi-server-orchestration/references/maintenance-pass.md +21 -3
- package/skills/multi-server-orchestration/references/release-and-publish-pass.md +7 -3
- package/skills/multi-server-orchestration/references/wrapup-pass.md +2 -2
- package/skills/polish-docs-meta/SKILL.md +37 -5
- package/skills/release-and-publish/SKILL.md +2 -2
- package/templates/CLAUDE.md +1 -1
- package/templates/_.mcpbignore +0 -3
- package/dist/logs/combined.log +0 -7
- package/dist/logs/error.log +0 -5
- package/dist/logs/interactions.log +0 -0
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.
|
|
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
|
|
@@ -32,8 +32,8 @@ Both paths share the same public API. Init copies starter `package.json`, config
|
|
|
32
32
|
- **Full-stack observability.** The framework automatically instruments every tool/resource call — OTel span, duration/payload/memory metrics, structured completion log. Use `ctx.log` for additional domain-specific logging within handlers (external API calls, multi-step operations, business events). `requestId`, `traceId`, `tenantId` auto-correlated. No `console` calls.
|
|
33
33
|
- **Unified Context.** Handlers receive `ctx` with logging (`ctx.log`), tenant-scoped storage (`ctx.state`), optional protocol capabilities (`ctx.elicit`, `ctx.sample`), and cancellation (`ctx.signal`).
|
|
34
34
|
- **Decoupled storage.** `ctx.state` for tenant-scoped KV. Never access persistence backends directly.
|
|
35
|
-
- **Canvas tokens are capabilities, not tenant-scoped state.** A `canvasId` is a 10-char URL-safe token; possession grants full read/write/drop
|
|
36
|
-
- **Runtime parity.** All features work
|
|
35
|
+
- **Canvas tokens are capabilities, not tenant-scoped state.** A `canvasId` is a 10-char URL-safe token; possession grants full read/write/drop. Shareable between agents and across users in single-tenant deployments. Tools accept token in `input` (omit to create fresh) and return in `output`; collaboration is opt-in via token exchange.
|
|
36
|
+
- **Runtime parity.** All features work across `stdio`/`http`/Worker. Guard non-portable deps via `runtimeCaps` from `/utils` (`isNode`, `isBun`, `isWorkerLike`, `hasBuffer`, `hasProcess`, etc.). Prefer runtime-agnostic abstractions (Hono, Fetch APIs).
|
|
37
37
|
- **Definition linting is build-time only.** Run `bun run lint:mcp` (standalone) or `bun run devcheck` (gate). Not invoked at server startup — new lint rules are additive and never break deployed servers. Every diagnostic links to the rule reference in `api-linter` skill; see that skill for the full rule catalog.
|
|
38
38
|
- **Elicitation for missing input.** Use `ctx.elicit` when the client supports it.
|
|
39
39
|
|
|
@@ -106,7 +106,7 @@ await createApp({
|
|
|
106
106
|
});
|
|
107
107
|
```
|
|
108
108
|
|
|
109
|
-
**`instructions`** — Optional server-level orientation
|
|
109
|
+
**`instructions`** — Optional server-level orientation, surfaced on every `initialize` response as session-level system context. Use for deployment-specific guidance (connection aliases, regional notes, scope hints) instead of repeating in tool descriptions. Client adoption uneven but no downside when set.
|
|
110
110
|
|
|
111
111
|
### Cloudflare Workers — `createWorkerHandler(options)`
|
|
112
112
|
|
|
@@ -125,8 +125,6 @@ export default createWorkerHandler({
|
|
|
125
125
|
});
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
-
`instructions` on the Worker handler accepts either a plain string or a `(env) => string` resolver so deployment env (injected at request time) can shape the text.
|
|
129
|
-
|
|
130
128
|
Per-request `McpServer` factory (security: SDK GHSA-345p-7cg4-v4c7). Requires `compatibility_flags = ["nodejs_compat"]` and `compatibility_date >= "2025-09-01"` in `wrangler.toml`. Only `in-memory`, `cloudflare-r2`, `cloudflare-kv`, `cloudflare-d1` storage in Workers. See `api-workers` skill for full details.
|
|
131
129
|
|
|
132
130
|
### Interfaces
|
|
@@ -260,56 +258,6 @@ Handler receives `(params, ctx)` — URI on `ctx.uri` if needed. Optional `size`
|
|
|
260
258
|
|
|
261
259
|
---
|
|
262
260
|
|
|
263
|
-
## Adding a Prompt
|
|
264
|
-
|
|
265
|
-
```ts
|
|
266
|
-
import { prompt, z } from '@cyanheads/mcp-ts-core';
|
|
267
|
-
|
|
268
|
-
export const codeReview = prompt('code_review', {
|
|
269
|
-
description: 'Review code for security and best practices.',
|
|
270
|
-
args: z.object({
|
|
271
|
-
code: z.string().describe('Code to review'),
|
|
272
|
-
language: z.string().optional().describe('Programming language'),
|
|
273
|
-
}),
|
|
274
|
-
generate: (args) => [
|
|
275
|
-
{ role: 'user', content: { type: 'text', text: `Review this ${args.language ?? ''} code:\n${args.code}` } },
|
|
276
|
-
],
|
|
277
|
-
});
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
Prompts are pure message templates — no `Context`, no auth, no side effects.
|
|
281
|
-
|
|
282
|
-
---
|
|
283
|
-
|
|
284
|
-
## Adding a Service
|
|
285
|
-
|
|
286
|
-
Init/accessor pattern — initialized in `setup()`, accessed at request time.
|
|
287
|
-
|
|
288
|
-
```ts
|
|
289
|
-
export class MyService {
|
|
290
|
-
constructor(private readonly config: AppConfig, private readonly storage: StorageService) {}
|
|
291
|
-
async doWork(input: string, ctx: Context): Promise<string> {
|
|
292
|
-
ctx.log.debug('Working', { input });
|
|
293
|
-
return `done: ${input}`;
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
let _service: MyService | undefined;
|
|
298
|
-
export function initMyService(config: AppConfig, storage: StorageService): void {
|
|
299
|
-
_service = new MyService(config, storage);
|
|
300
|
-
}
|
|
301
|
-
export function getMyService(): MyService {
|
|
302
|
-
if (!_service) throw new Error('MyService not initialized — call initMyService() in setup()');
|
|
303
|
-
return _service;
|
|
304
|
-
}
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
Usage: `getMyService().doWork(input.query, ctx)`. Convention: `ctx.elicit`/`ctx.sample` only from tool handlers, not services.
|
|
308
|
-
|
|
309
|
-
**API efficiency:** Prefer batch endpoints over N+1 individual requests. Use field selection to minimize payload. Cross-reference batch responses against requested IDs to detect missing items. See `add-service` skill for patterns.
|
|
310
|
-
|
|
311
|
-
---
|
|
312
|
-
|
|
313
261
|
## Context
|
|
314
262
|
|
|
315
263
|
```ts
|
|
@@ -404,11 +352,9 @@ async handler(input, ctx) {
|
|
|
404
352
|
}
|
|
405
353
|
```
|
|
406
354
|
|
|
407
|
-
**`ctx.recoveryFor(reason)`**
|
|
408
|
-
|
|
409
|
-
**Declare contracts inline on each tool.** The contract is part of the tool's public surface — one file should give the full picture (input, output, errors, handler, format). Don't extract a shared `errors[]` constant; per-tool repetition is the intended cost of locality, and dynamic `recovery` hints need tool-specific context.
|
|
355
|
+
**`ctx.recoveryFor(reason)`** returns `{}` when no contract exists (spread-safe). Typed against the declared reason union on `HandlerContext<R>`. Works in services: `throw validationError(msg, { reason: 'X', ...ctx.recoveryFor('X') })`. Opt-in — author spreads explicitly.
|
|
410
356
|
|
|
411
|
-
|
|
357
|
+
**Contracts are inline, per-tool.** Don't extract shared `errors[]` constants — locality is the point, and dynamic `recovery` hints need tool-specific context. Declare domain-specific failures only; **baseline codes** (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`) are auto-allowed by conformance lint. The lint scans handler source only — service-layer throws still reach clients via auto-classification.
|
|
412
358
|
|
|
413
359
|
**Fallback for ad-hoc throws** (no contract entry fits, prototype tools, service-layer code): use error factories.
|
|
414
360
|
|
|
@@ -424,9 +370,9 @@ For HTTP responses from upstream APIs, use `httpErrorFromResponse(response, { se
|
|
|
424
370
|
|
|
425
371
|
**Auto-classification.** Plain `Error`, `ZodError`, and any other thrown value are caught and classified automatically. Resolution order: `McpError` code (preserved as-is) → JS constructor name (`TypeError` → `ValidationError`) → provider patterns (HTTP status codes, AWS errors, DB errors) → common message patterns → `AbortError` name → `InternalError` fallback.
|
|
426
372
|
|
|
427
|
-
**Error-path parity.** Tool errors
|
|
373
|
+
**Error-path parity.** Tool errors: `content[]` carries markdown with `data.recovery.hint`; `structuredContent.error` carries `{ code, message, data? }`. No `_meta.error`. Resources re-throw via JSON-RPC error envelope.
|
|
428
374
|
|
|
429
|
-
|
|
375
|
+
**Lint rules** (all warnings, surfaced in `devcheck`): `prefer-mcp-error-in-handler`, `prefer-error-factory`, `preserve-cause-on-rethrow`, `no-stringify-upstream-error`, `error-contract-conformance`, `error-contract-prefer-fail`. See `api-linter` skill.
|
|
430
376
|
|
|
431
377
|
See `api-errors` skill for the full pattern-matching table, error code reference, and detailed examples.
|
|
432
378
|
|
|
@@ -447,7 +393,7 @@ Pick one convention per server and stay consistent. Verbs are typically `read`,
|
|
|
447
393
|
|
|
448
394
|
**Modes** (`MCP_AUTH_MODE`): `none` (default) | `jwt` (local secret via `MCP_AUTH_SECRET_KEY`) | `oauth` (JWKS via `OAUTH_ISSUER_URL`, `OAUTH_AUDIENCE`). See `api-auth` skill for claims, CORS, and detailed config.
|
|
449
395
|
|
|
450
|
-
**Granted scopes** union `scp`, `scope`, and `mcp_tool_scopes` JWT claims. `mcp_tool_scopes` is the escape hatch
|
|
396
|
+
**Granted scopes** union `scp`, `scope`, and `mcp_tool_scopes` JWT claims. `mcp_tool_scopes` is the OIDC escape hatch (Authentik, Keycloak < 26.5, Zitadel). `MCP_AUTH_DISABLE_SCOPE_CHECKS=true` bypasses scope checks while preserving auth-context verification (signature/audience/issuer/expiry). Logs `WARNING` at startup.
|
|
451
397
|
|
|
452
398
|
---
|
|
453
399
|
|
|
@@ -514,41 +460,11 @@ Detailed method signatures, options, and examples live in skill files. Read the
|
|
|
514
460
|
|
|
515
461
|
### Skill versioning
|
|
516
462
|
|
|
517
|
-
Each `skills/<name>/SKILL.md` carries
|
|
518
|
-
|
|
519
|
-
**Policy:**
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|:------|:-----|:-------|
|
|
523
|
-
| `api-utils` | `skills/api-utils/SKILL.md` | formatting, parsing, security, network, pagination, runtime, scheduling, types, logger, requestContext, errorHandler, telemetry helpers (`withSpan`, `createCounter`, …) |
|
|
524
|
-
| `api-telemetry` | `skills/api-telemetry/SKILL.md` | OTel catalog: span names, metric names + attributes, completion log fields, env config, runtime support, cardinality rules |
|
|
525
|
-
| `api-services` | `skills/api-services/SKILL.md` | LLM (OpenRouter), Speech (ElevenLabs TTS, Whisper STT), Graph (CRUD, traversal, pathfinding) |
|
|
526
|
-
| `api-context` | `skills/api-context/SKILL.md` | Context interface, createContext, ContextLogger/State/Progress |
|
|
527
|
-
| `api-errors` | `skills/api-errors/SKILL.md` | McpError, JsonRpcErrorCode, error handling patterns |
|
|
528
|
-
| `api-auth` | `skills/api-auth/SKILL.md` | Auth modes, scopes, JWT/OAuth strategies |
|
|
529
|
-
| `api-config` | `skills/api-config/SKILL.md` | AppConfig, parseConfig, env vars |
|
|
530
|
-
| `api-testing` | `skills/api-testing/SKILL.md` | createMockContext, test patterns, MockContextOptions |
|
|
531
|
-
| `api-workers` | `skills/api-workers/SKILL.md` | createWorkerHandler, CloudflareBindings, Worker runtime |
|
|
532
|
-
| `api-canvas` | `skills/api-canvas/SKILL.md` | DataCanvas primitive: acquire/register/query/export, token-sharing model, SQL gate, lifecycle, spillover pattern |
|
|
533
|
-
| `api-linter` | `skills/api-linter/SKILL.md` | Definition lint rules (`format-parity`, `schema-*`, `name-*`, `server-json-*`, …) — look here when devcheck reports a lint diagnostic |
|
|
534
|
-
| `add-tool` | `skills/add-tool/SKILL.md` | Scaffold a new MCP tool definition |
|
|
535
|
-
| `add-app-tool` | `skills/add-app-tool/SKILL.md` | Scaffold an MCP App tool + UI resource pair |
|
|
536
|
-
| `add-resource` | `skills/add-resource/SKILL.md` | Scaffold a new MCP resource definition |
|
|
537
|
-
| `add-prompt` | `skills/add-prompt/SKILL.md` | Scaffold a new MCP prompt definition |
|
|
538
|
-
| `add-service` | `skills/add-service/SKILL.md` | Scaffold a new domain service |
|
|
539
|
-
| `add-test` | `skills/add-test/SKILL.md` | Scaffold test file for a tool, resource, or service |
|
|
540
|
-
| `field-test` | `skills/field-test/SKILL.md` | Exercise tools/resources/prompts with real inputs, verify behavior, report issues |
|
|
541
|
-
| `security-pass` | `skills/security-pass/SKILL.md` | Review server for MCP-flavored security gaps: output injection, scope blast radius, elicit gaps, upstream auth, input sinks, tenant isolation, leakage, resource bounds |
|
|
542
|
-
| `add-provider` | `skills/add-provider/SKILL.md` | Add a new provider implementation |
|
|
543
|
-
| `add-export` | `skills/add-export/SKILL.md` | Add a new subpath export |
|
|
544
|
-
| `design-mcp-server` | `skills/design-mcp-server/SKILL.md` | Design tool surface, resources, and service layer for a new server |
|
|
545
|
-
| `setup` | `skills/setup/SKILL.md` | Initialize a new consumer server from the template |
|
|
546
|
-
| `polish-docs-meta` | `skills/polish-docs-meta/SKILL.md` | Finalize docs, README, metadata, and agent protocol for shipping |
|
|
547
|
-
| `report-issue-framework` | `skills/report-issue-framework/SKILL.md` | File a bug or feature request against `@cyanheads/mcp-ts-core` via `gh` CLI |
|
|
548
|
-
| `report-issue-local` | `skills/report-issue-local/SKILL.md` | File a bug or feature request against this server's own repo via `gh` CLI |
|
|
549
|
-
| `release-and-publish` | `skills/release-and-publish/SKILL.md` | Post-wrapup ship workflow: verification gate, push, publish to npm/MCP Registry/GHCR |
|
|
550
|
-
| `maintenance` | `skills/maintenance/SKILL.md` | Dependency updates, housekeeping tasks |
|
|
551
|
-
| `migrate-mcp-ts-template` | `skills/migrate-mcp-ts-template/SKILL.md` | Migrate legacy template fork to package dependency |
|
|
463
|
+
Each `skills/<name>/SKILL.md` carries `metadata.version` in frontmatter. The `maintenance` skill's Phase A uses this to sync consumer copies — replaces the **entire skill directory** as one unit. Without a version bump, Phase A skips the skill (content-hash backstop catches drift, but noisier).
|
|
464
|
+
|
|
465
|
+
**Policy:** Bump `metadata.version` when changing any file under `skills/<name>/` — SKILL.md is the single version knob for the directory. Typo/whitespace fixes exempt. One bump per release cycle suffices.
|
|
466
|
+
|
|
467
|
+
Skills live in `skills/<name>/SKILL.md`. Read the relevant skill before starting a task it covers. The full list is discoverable via the agent's skill registry at session start.
|
|
552
468
|
|
|
553
469
|
---
|
|
554
470
|
|
|
@@ -581,7 +497,7 @@ Each `skills/<name>/SKILL.md` carries a `metadata.version` string in its frontma
|
|
|
581
497
|
| `bun run build` | Build library output (`scripts/build.ts`) |
|
|
582
498
|
| `bun run rebuild` | Clean and rebuild (`scripts/clean.ts` + `build`) |
|
|
583
499
|
| `bun run devcheck` | **Use often.** Lint, format, typecheck, MCP definition linting, `bun audit`, `bun outdated` |
|
|
584
|
-
| `bun run audit:refresh` | Delete `bun.lock`, reinstall,
|
|
500
|
+
| `bun run audit:refresh` | Delete `bun.lock`, reinstall, re-audit. Use when `devcheck` flags a transitive advisory — stale lockfile can mask already-patched deps. If advisory survives, it's real. |
|
|
585
501
|
| `bun run lint:mcp` | Validate MCP definitions against spec |
|
|
586
502
|
| `bun run format` | Auto-fix Biome lint/format issues |
|
|
587
503
|
| `bun run test` | Unit/integration tests |
|
|
@@ -596,11 +512,9 @@ After `bun update --latest`, run the `maintenance` skill to investigate changelo
|
|
|
596
512
|
|
|
597
513
|
## Changelog
|
|
598
514
|
|
|
599
|
-
Directory-based
|
|
515
|
+
Directory-based. Source of truth: `changelog/<major.minor>.x/<version>.md` — one file per release (e.g. `changelog/0.5.x/0.5.4.md`), shipped in the npm package for direct agent access. `changelog/template.md` is the format reference (never edited).
|
|
600
516
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
`CHANGELOG.md` is a **navigation index**, not a copy of bodies — each entry is a clickable header + one-line summary pulled from the per-version file's frontmatter. Regenerated by `bun run changelog:build`. Devcheck runs `changelog:check` and hard-fails on drift. Never hand-edit `CHANGELOG.md` — edit the per-version file and rerun the build.
|
|
517
|
+
`CHANGELOG.md` is a **navigation index** — clickable headers + one-line summaries from frontmatter. Regenerated by `bun run changelog:build`; `changelog:check` hard-fails on drift in devcheck. Never hand-edit — edit the per-version file and rerun the build.
|
|
604
518
|
|
|
605
519
|
### Per-version file format
|
|
606
520
|
|
|
@@ -626,14 +540,14 @@ security: false # optional, default fals
|
|
|
626
540
|
| `breaking` | no (default `false`) | Flags releases with breaking changes. Renders as `· ⚠️ Breaking` badge in the rollup. Agents running the `maintenance` skill read this to prioritize review. |
|
|
627
541
|
| `security` | no (default `false`) | Flags releases with security fixes. Renders as `· 🛡️ Security` badge in the rollup so users can triage upgrade urgency. Pairs with the `## Security` body section. |
|
|
628
542
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
**Section order** (Keep a Changelog): Added, Changed, Deprecated, Removed, Fixed, Security. Include only sections with entries — don't ship empty headers.
|
|
543
|
+
Badge order when both set: `· ⚠️ Breaking · 🛡️ Security`. Summary > 350 chars or malformed boolean fails `changelog:check`.
|
|
632
544
|
|
|
633
|
-
|
|
545
|
+
**Section order** (Keep a Changelog): Added, Changed, Deprecated, Removed, Fixed, Security. Omit empty sections. Pre-release versions consolidate as sub-headers inside the final version's file — no separate files per pre-release.
|
|
634
546
|
|
|
635
547
|
---
|
|
636
548
|
|
|
637
549
|
## Publishing
|
|
638
550
|
|
|
639
|
-
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.
|
|
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
|
[](https://www.npmjs.com/package/@cyanheads/mcp-ts-core)
|
|
9
9
|
|
|
10
|
-
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-11-25/changelog.mdx)
|
|
11
11
|
|
|
12
12
|
[](https://modelcontextprotocol.io/) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
13
13
|
|
package/biome.json
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "mcpbignore recursive-match fix, zod promoted to dependencies, polish-docs-meta MCPB step, maintenance template-file adoption, CLAUDE.md condensed"
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# 0.9.5 — 2026-05-23
|
|
6
|
+
|
|
7
|
+
## Fixed
|
|
8
|
+
|
|
9
|
+
- `.mcpbignore` template: removed bare `src/`, `tests/`, `coverage/` entries that matched recursively and stripped `node_modules/**/build/src/`, breaking `@opentelemetry/api` CJS entry in MCPB bundles ([#146](https://github.com/cyanheads/mcp-ts-core/issues/146))
|
|
10
|
+
- `zod` added to `dependencies` (was peer-only); stale `node_modules` could leave zod unresolved since the framework imports it at runtime
|
|
11
|
+
|
|
12
|
+
## Changed
|
|
13
|
+
|
|
14
|
+
- `CLAUDE.md`/`AGENTS.md`: condensed prose across Error Handling, Auth, Changelog, Entry Points, Core Rules; removed Adding a Prompt, Adding a Service sections (covered by skills), removed 30-row skill table (redundant with session skill registry)
|
|
15
|
+
- `biome.json`: `noDuplicateDependencies` downgraded to `warn` — intentional `dependencies` + `peerDependencies` overlap for zod
|
|
16
|
+
- `skills/polish-docs-meta` v2.0 → v2.1: new Step 10 for MCPB bundling artifacts (`manifest.json`, `.mcpbignore`, `bundle`/`lint:packaging` scripts, README install badges)
|
|
17
|
+
- `skills/maintenance` v2.3 → v2.4: Step 4 scan table gains "New template-scaffolded files" row — flags missing files like `manifest.json` and `.mcpbignore` for adoption ([#147](https://github.com/cyanheads/mcp-ts-core/issues/147))
|
|
@@ -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.
|
|
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",
|
|
@@ -217,8 +217,7 @@
|
|
|
217
217
|
"unpdf": "^1.6.2",
|
|
218
218
|
"validator": "^13.15.35",
|
|
219
219
|
"vite": "8.0.14",
|
|
220
|
-
"vitest": "^4.1.7"
|
|
221
|
-
"zod": "^4.4.3"
|
|
220
|
+
"vitest": "^4.1.7"
|
|
222
221
|
},
|
|
223
222
|
"keywords": [
|
|
224
223
|
"agent",
|
|
@@ -278,7 +277,8 @@
|
|
|
278
277
|
"dotenv": "^17.4.2",
|
|
279
278
|
"hono": "^4.12.22",
|
|
280
279
|
"jose": "^6.2.3",
|
|
281
|
-
"pino": "^10.3.1"
|
|
280
|
+
"pino": "^10.3.1",
|
|
281
|
+
"zod": "^4.4.3"
|
|
282
282
|
},
|
|
283
283
|
"peerDependencies": {
|
|
284
284
|
"@duckdb/node-api": "^1.5.0",
|
|
@@ -8,12 +8,16 @@
|
|
|
8
8
|
* `npm run lint:packaging`.
|
|
9
9
|
*
|
|
10
10
|
* Checks:
|
|
11
|
-
* 1.
|
|
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
|
-
*
|
|
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,
|
|
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
|
-
|
|
82
|
+
|
|
83
|
+
if (manifest.name?.includes('/')) {
|
|
98
84
|
errors.push(
|
|
99
|
-
`manifest.json
|
|
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
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
Investigate, adopt, and verify dependency updates — with special handling for `@cyanheads/mcp-ts-core`. Captures what changed, understands why, cross-references against the codebase, adopts framework improvements, syncs project skills, and runs final checks. Supports two entry modes: run the full flow end-to-end, or review updates you already applied.
|
|
5
5
|
metadata:
|
|
6
6
|
author: cyanheads
|
|
7
|
-
version: "2.
|
|
7
|
+
version: "2.4"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -78,6 +78,7 @@ Scan specifically for:
|
|
|
78
78
|
| Config changes | New env vars, renamed keys, changed defaults |
|
|
79
79
|
| Linter rules | New definition-lint rules that may now flag existing tools/resources |
|
|
80
80
|
| New or materially-changed skills | Note new skills or workflow changes (renamed steps, new checklist items) worth surfacing at end-of-run. Don't auto-invoke — some skills (e.g. `security-pass`) are user-triggered. The per-version changelog entries (e.g. 0.6.14 calling out `skills/security-pass/ (v1.0)`) name what changed. |
|
|
81
|
+
| New template-scaffolded files | Compare `templates/` in the package against the project root. Files that `init` would create for a new project but don't exist in this project are adoption candidates — create them with project-specific values (version, name, description, env vars from `server.json`). Examples: `manifest.json`, `.mcpbignore`. Skip files the project has intentionally opted out of (documented in CLAUDE.md or a code comment). |
|
|
81
82
|
|
|
82
83
|
Cross-reference each finding against the server's code. Collect adoption opportunities for Step 6.
|
|
83
84
|
|
|
@@ -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.
|
|
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.
|
|
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. **
|
|
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.
|
|
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. `
|
|
141
|
-
> 7.
|
|
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.
|
|
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.
|
|
7
|
+
version: "2.2"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -163,11 +163,42 @@ Never hand-edit `CHANGELOG.md` when using this pattern — it's a build artifact
|
|
|
163
163
|
|
|
164
164
|
**Monolithic** — maintain `CHANGELOG.md` directly in [Keep a Changelog](https://keepachangelog.com/) format. To collapse from the template default: delete the `changelog/` directory, remove `changelog:build` and `changelog:check` from `package.json` scripts (and from `devcheck.config.json` if referenced), and drop `"changelog/"` from the `files` array. The `release` skill's directory-specific steps then don't apply — just edit `CHANGELOG.md` and bump version at release time.
|
|
165
165
|
|
|
166
|
-
### 10.
|
|
166
|
+
### 10. MCPB Bundling Artifacts
|
|
167
|
+
|
|
168
|
+
If the project ships as an `.mcpb` bundle for Claude Desktop (check for `manifest.json` at the project root), verify the full artifact set is present and consistent. If the project doesn't ship `.mcpb` bundles, skip this step.
|
|
169
|
+
|
|
170
|
+
**Files that must exist:**
|
|
171
|
+
|
|
172
|
+
- `manifest.json` — MCPB manifest with `mcp_config.env`, `user_config`, and metadata
|
|
173
|
+
- `.mcpbignore` — controls what's excluded from the bundle
|
|
174
|
+
|
|
175
|
+
**`package.json` scripts:**
|
|
176
|
+
|
|
177
|
+
- `bundle` — builds the `.mcpb` (e.g., `mcpb pack --output dist/`)
|
|
178
|
+
- `lint:packaging` — validates `manifest.json` ↔ `server.json` env var consistency (run by `devcheck`)
|
|
179
|
+
|
|
180
|
+
**Cross-file consistency:**
|
|
181
|
+
|
|
182
|
+
- `manifest.json` version matches `package.json` version
|
|
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` 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.
|
|
189
|
+
|
|
190
|
+
**README install badges:**
|
|
191
|
+
|
|
192
|
+
- If `manifest.json` exists, the README should include the Claude Desktop install badge linking to `releases/latest/download/<name>.mcpb`
|
|
193
|
+
- If the package is published to npm, include Cursor and VS Code install badges
|
|
194
|
+
- See `references/readme.md` for badge format and config generation commands
|
|
195
|
+
- See the **Bundling** section of `templates/CLAUDE.md` for `base64` / `encodeURIComponent` generation
|
|
196
|
+
|
|
197
|
+
### 11. `LICENSE`
|
|
167
198
|
|
|
168
199
|
Confirm a license file exists. If not, ask the user which license to use (default: Apache-2.0, matching the scaffolded `package.json`). Create the file.
|
|
169
200
|
|
|
170
|
-
###
|
|
201
|
+
### 12. `Dockerfile`
|
|
171
202
|
|
|
172
203
|
If a `Dockerfile` exists, verify the OCI labels and runtime config match the actual server:
|
|
173
204
|
|
|
@@ -178,7 +209,7 @@ If a `Dockerfile` exists, verify the OCI labels and runtime config match the act
|
|
|
178
209
|
|
|
179
210
|
If no `Dockerfile` exists and the server is deployed via HTTP transport, consider scaffolding one — the template is available via `npx @cyanheads/mcp-ts-core init`.
|
|
180
211
|
|
|
181
|
-
###
|
|
212
|
+
### 13. `docs/tree.md`
|
|
182
213
|
|
|
183
214
|
Regenerate the directory structure:
|
|
184
215
|
|
|
@@ -188,7 +219,7 @@ bun run tree
|
|
|
188
219
|
|
|
189
220
|
Review the output for anything unexpected (leftover files, missing directories).
|
|
190
221
|
|
|
191
|
-
###
|
|
222
|
+
### 14. Final Verification
|
|
192
223
|
|
|
193
224
|
Run the full check suite one last time:
|
|
194
225
|
|
|
@@ -210,6 +241,7 @@ Both must pass clean.
|
|
|
210
241
|
- [ ] GitHub repo description matches `package.json` description; topics ↔ keywords in sync
|
|
211
242
|
- [ ] `bunfig.toml` present
|
|
212
243
|
- [ ] Changelog current — either monolithic `CHANGELOG.md` (hand-edited, Keep a Changelog) or directory-based (`changelog/<minor>.x/<version>.md` + rollup regenerated and in sync)
|
|
244
|
+
- [ ] MCPB artifacts consistent (if `manifest.json` present) — version synced, env vars match `server.json`, `bundle` + `lint:packaging` scripts exist, README install badges present
|
|
213
245
|
- [ ] `LICENSE` file present
|
|
214
246
|
- [ ] `Dockerfile` OCI labels and runtime config accurate (if present)
|
|
215
247
|
- [ ] `docs/tree.md` regenerated
|
|
@@ -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.
|
|
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)
|
package/templates/CLAUDE.md
CHANGED
|
@@ -295,7 +295,7 @@ When you complete a skill's checklist, check the boxes and add a completion time
|
|
|
295
295
|
| `npm run rebuild` | Clean + build |
|
|
296
296
|
| `npm run clean` | Remove build artifacts |
|
|
297
297
|
| `npm run devcheck` | Lint + format + typecheck + security + changelog sync |
|
|
298
|
-
| `bun run audit:refresh` | Delete `bun.lock`, reinstall,
|
|
298
|
+
| `bun run audit:refresh` | Delete `bun.lock`, reinstall, re-audit. Use when `devcheck` flags a transitive advisory — stale lockfile can mask already-patched deps. If advisory survives, it's real. |
|
|
299
299
|
| `npm run tree` | Generate directory structure doc |
|
|
300
300
|
| `npm run format` | Auto-fix formatting |
|
|
301
301
|
| `npm test` | Run tests |
|
package/templates/_.mcpbignore
CHANGED
package/dist/logs/combined.log
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{"level":40,"time":1779513956718,"env":"testing","version":"0.9.4","pid":13469,"transport":"http","requestId":"4J7N0-VMN48","timestamp":"2026-05-23T05:25:56.717Z","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":1779513958440,"env":"testing","version":"0.9.4","pid":13469,"transport":"http","requestId":"4J7N0-VMN48","timestamp":"2026-05-23T05:25:56.717Z","operation":"TransportManager.start","component":"HttpTransportSetup","sessionId":"not-a-real-session-1779513958439","msg":"Session validation failed - invalid or hijacked session"}
|
|
3
|
-
{"level":50,"time":1779513962377,"env":"testing","version":"0.0.0-test","pid":13573,"requestId":"T1SL6-PDB7E","timestamp":"2026-05-23T05:26:02.376Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"b3cf5e7052663460e341825d87d31fc524d2fbe329b2fbc6a0d01e2d01d6f0ac","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"b3cf5e7052663460e341825d87d31fc524d2fbe329b2fbc6a0d01e2d01d6f0ac","toolName":"scoped_echo","requestId":"T1SL6-PDB7E","timestamp":"2026-05-23T05:26:02.376Z","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":1779513962384,"env":"testing","version":"0.0.0-test","pid":13573,"requestId":"UKSVK-KPL9I","timestamp":"2026-05-23T05:26:02.383Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"fc5e475d003413db328e15b2ffa9ee921e0926a9f2e4afff18d07b1136990f19","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":"fc5e475d003413db328e15b2ffa9ee921e0926a9f2e4afff18d07b1136990f19","toolName":"scoped_echo","requestId":"UKSVK-KPL9I","timestamp":"2026-05-23T05:26:02.383Z","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":1779513963761,"env":"testing","version":"0.9.4","pid":13581,"requestId":"36WC3-ADICM","timestamp":"2026-05-23T05:26:03.760Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"POST","errorData":{"path":"/mcp","method":"POST","requestId":"36WC3-ADICM","timestamp":"2026-05-23T05:26:03.760Z","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":1779513963776,"env":"testing","version":"0.9.4","pid":13581,"requestId":"1J9GZ-FP2NN","timestamp":"2026-05-23T05:26:03.776Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"POST","errorData":{"path":"/mcp","method":"POST","requestId":"1J9GZ-FP2NN","timestamp":"2026-05-23T05:26:03.776Z","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":1779513963778,"env":"testing","version":"0.9.4","pid":13581,"requestId":"XK1MI-79PW3","timestamp":"2026-05-23T05:26:03.778Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"GET","errorData":{"path":"/mcp","method":"GET","requestId":"XK1MI-79PW3","timestamp":"2026-05-23T05:26:03.778Z","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."}
|
package/dist/logs/error.log
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
{"level":50,"time":1779513962377,"env":"testing","version":"0.0.0-test","pid":13573,"requestId":"T1SL6-PDB7E","timestamp":"2026-05-23T05:26:02.376Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"b3cf5e7052663460e341825d87d31fc524d2fbe329b2fbc6a0d01e2d01d6f0ac","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"b3cf5e7052663460e341825d87d31fc524d2fbe329b2fbc6a0d01e2d01d6f0ac","toolName":"scoped_echo","requestId":"T1SL6-PDB7E","timestamp":"2026-05-23T05:26:02.376Z","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":1779513962384,"env":"testing","version":"0.0.0-test","pid":13573,"requestId":"UKSVK-KPL9I","timestamp":"2026-05-23T05:26:02.383Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"fc5e475d003413db328e15b2ffa9ee921e0926a9f2e4afff18d07b1136990f19","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":"fc5e475d003413db328e15b2ffa9ee921e0926a9f2e4afff18d07b1136990f19","toolName":"scoped_echo","requestId":"UKSVK-KPL9I","timestamp":"2026-05-23T05:26:02.383Z","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":1779513963761,"env":"testing","version":"0.9.4","pid":13581,"requestId":"36WC3-ADICM","timestamp":"2026-05-23T05:26:03.760Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"POST","errorData":{"path":"/mcp","method":"POST","requestId":"36WC3-ADICM","timestamp":"2026-05-23T05:26:03.760Z","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":1779513963776,"env":"testing","version":"0.9.4","pid":13581,"requestId":"1J9GZ-FP2NN","timestamp":"2026-05-23T05:26:03.776Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"POST","errorData":{"path":"/mcp","method":"POST","requestId":"1J9GZ-FP2NN","timestamp":"2026-05-23T05:26:03.776Z","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":1779513963778,"env":"testing","version":"0.9.4","pid":13581,"requestId":"XK1MI-79PW3","timestamp":"2026-05-23T05:26:03.778Z","operation":"httpErrorHandler","critical":false,"errorCode":-32006,"originalErrorType":"McpError","finalErrorType":"McpError","path":"/mcp","method":"GET","errorData":{"path":"/mcp","method":"GET","requestId":"XK1MI-79PW3","timestamp":"2026-05-23T05:26:03.778Z","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
|