@cyanheads/mcp-ts-core 0.10.8 → 0.10.9
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/AGENTS.md +1 -1
- package/CLAUDE.md +1 -1
- package/README.md +1 -1
- package/changelog/0.10.x/0.10.9.md +16 -0
- package/dist/logs/combined.log +19 -8
- package/dist/logs/error.log +10 -4
- package/package.json +3 -2
- package/scripts/check-dependency-specifiers.ts +190 -0
- package/scripts/devcheck.ts +21 -3
- package/scripts/lint-packaging.ts +152 -0
- package/skills/polish-docs-meta/SKILL.md +7 -5
- package/templates/devcheck.config.json +3 -0
package/AGENTS.md
CHANGED
package/CLAUDE.md
CHANGED
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
<div align="center">
|
|
7
7
|
|
|
8
|
-
[](./CHANGELOG.md) [](./LICENSE) [](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-11-25/changelog.mdx)
|
|
9
9
|
|
|
10
10
|
[](https://modelcontextprotocol.io/) [](https://www.typescriptlang.org/) [](https://bun.sh/)
|
|
11
11
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "devcheck gains two static guards: floating dependency specifiers (latest/*/dist-tags) in package.json + bun.lock workspaces, and plugin marketplace manifest correctness (descriptions + scoped/unscoped identity)"
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.10.9 — 2026-06-20
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **`check-dependency-specifiers` devcheck step** — new `scripts/check-dependency-specifiers.ts`, registered in `ALL_CHECKS` (`Dependency Specifiers`, flag `--no-dep-specifiers`), hard-fails on floating specifiers in the manifests we control: `package.json`'s four dependency sections and `bun.lock`'s `workspaces` specifier maps (never the `packages` section, which records third-party nested declarations that legitimately float). `latest` fails in every section; `*` and the pre-release dist-tags `next`/`beta`/`canary`/`rc` fail in `dependencies`/`devDependencies` but are allowed in `peerDependencies`/`optionalDependencies` ("any host version"). Catches the case where `bun update --latest` writes a literal `latest` dist-tag into the lock's workspace map — correct at write time, so it clears every other gate, then lets the next `bun install` re-resolve the dep past the `package.json` range and past any intentional hold. Static and local (no network, no git), so it runs in the default and `--fast` passes; ships to consumers via `package.json` `files:`. ([#246](https://github.com/cyanheads/mcp-ts-core/issues/246))
|
|
12
|
+
- **Plugin marketplace manifest checks in `lint:packaging`** — `scripts/lint-packaging.ts` gains check 10, validating `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`, and `.codex-plugin/mcp.json` when present: non-empty descriptions, display fields (`name`, server key, `interface.displayName`) carrying the **unscoped** machine name, and the `npx -y` install arg carrying the **full** `package.json` name. An unscoped install arg for a scoped package is a guaranteed install 404 — the high-value catch. Gated by a new `devcheck.config.json` `packaging.pluginManifests` flag (default on; surfaced in `templates/devcheck.config.json`); each manifest is skipped cleanly when absent, so HTTP-only and non-plugin consumers are unaffected. The `devcheck` "Packaging" gate, previously skipped unless `manifest.json` existed, now also runs when any plugin manifest is present. `skills/polish-docs-meta` step 10 documents the automated subset. ([#240](https://github.com/cyanheads/mcp-ts-core/issues/240))
|
|
13
|
+
|
|
14
|
+
## Changed
|
|
15
|
+
|
|
16
|
+
- **Dependency:** `@cloudflare/workers-types` 4.20260619.1 → 4.20260620.1
|
package/dist/logs/combined.log
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
{"level":40,"time":
|
|
2
|
-
{"level":40,"time":
|
|
3
|
-
{"level":50,"time":
|
|
4
|
-
{"level":50,"time":
|
|
5
|
-
{"level":40,"time":
|
|
6
|
-
{"level":
|
|
7
|
-
{"level":50,"time":
|
|
8
|
-
{"level":
|
|
1
|
+
{"level":40,"time":1781941716382,"env":"testing","version":"0.10.9","pid":63392,"transport":"http","requestId":"2MPNT-BJ5A1","timestamp":"2026-06-20T07:48:36.381Z","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":1781941718200,"env":"testing","version":"0.10.9","pid":63392,"component":"HttpTransport","requestId":"IERKD-MLXU9","timestamp":"2026-06-20T07:48:38.200Z","operation":"HttpRpcRequest","sessionId":"not-a-real-session-1781941718198","msg":"Session validation failed - invalid or hijacked session"}
|
|
3
|
+
{"level":50,"time":1781941725554,"env":"testing","version":"0.0.0-test","pid":63571,"requestId":"PP1XS-CJ3YO","timestamp":"2026-06-20T07:48:45.554Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"1f8f79dd7650efad787547e6d186503c524849b86f7028eb0a48f8dc6f0971e5","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"1f8f79dd7650efad787547e6d186503c524849b86f7028eb0a48f8dc6f0971e5","toolName":"scoped_echo","requestId":"PP1XS-CJ3YO","timestamp":"2026-06-20T07:48:45.554Z","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 (file:///Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:84:54)\n at withRequiredScopes (file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/authUtils.js:68:15)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:283:17\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)"},"stack":"McpError: Insufficient permissions.\n at ErrorHandler.handleError (file:///Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:19)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:332:26\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)","msg":"Error in tool:scoped_echo: Insufficient permissions."}
|
|
4
|
+
{"level":50,"time":1781941725565,"env":"testing","version":"0.0.0-test","pid":63571,"requestId":"8R56N-EA925","timestamp":"2026-06-20T07:48:45.565Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"4ff9f61440a71ba0f9c889f48708530881f35b46ef14e342bebfd3a5d386648d","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":"4ff9f61440a71ba0f9c889f48708530881f35b46ef14e342bebfd3a5d386648d","toolName":"scoped_echo","requestId":"8R56N-EA925","timestamp":"2026-06-20T07:48:45.565Z","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 (file:///Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:84:54)\n at withRequiredScopes (file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/authUtils.js:68:15)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:283:17\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)"},"stack":"McpError: Insufficient permissions.\n at ErrorHandler.handleError (file:///Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:19)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:332:26\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)","msg":"Error in tool:scoped_echo: Insufficient permissions."}
|
|
5
|
+
{"level":40,"time":1781941739460,"env":"testing","version":"0.10.9","pid":63828,"transport":"http","requestId":"1B8KU-RX0D2","timestamp":"2026-06-20T07:48:59.460Z","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."}
|
|
6
|
+
{"level":50,"time":1781941769956,"env":"testing","version":"0.0.0-test","pid":64367,"requestId":"BXZXW-ITAUJ","timestamp":"2026-06-20T07:49:29.955Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"d0084a4d9af8dde128d867a6ff54d073155e05898a72f6bf5971ae8834e267b4","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"d0084a4d9af8dde128d867a6ff54d073155e05898a72f6bf5971ae8834e267b4","toolName":"scoped_echo","requestId":"BXZXW-ITAUJ","timestamp":"2026-06-20T07:49:29.955Z","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:283: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:332: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."}
|
|
7
|
+
{"level":50,"time":1781941769966,"env":"testing","version":"0.0.0-test","pid":64367,"requestId":"VFS62-PJ4HJ","timestamp":"2026-06-20T07:49:29.966Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"faf86ac4e0fa052ce32c646aab8dbbc7621060afc517e7dcf6a4c102cf021ee2","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":"faf86ac4e0fa052ce32c646aab8dbbc7621060afc517e7dcf6a4c102cf021ee2","toolName":"scoped_echo","requestId":"VFS62-PJ4HJ","timestamp":"2026-06-20T07:49:29.966Z","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:283: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:332: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."}
|
|
8
|
+
{"level":40,"time":1781941790323,"env":"testing","version":"0.10.9","pid":64810,"transport":"http","requestId":"5WVSR-FFHLN","timestamp":"2026-06-20T07:49:50.322Z","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."}
|
|
9
|
+
{"level":40,"time":1781941792076,"env":"testing","version":"0.10.9","pid":64810,"component":"HttpTransport","requestId":"UOW2E-42D2F","timestamp":"2026-06-20T07:49:52.076Z","operation":"HttpRpcRequest","sessionId":"not-a-real-session-1781941792076","msg":"Session validation failed - invalid or hijacked session"}
|
|
10
|
+
{"level":50,"time":1781941796117,"env":"testing","version":"0.0.0-test","pid":64938,"requestId":"QE8W3-P4XQM","timestamp":"2026-06-20T07:49:56.116Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"cd72d96dbf83183020b6d476224a4654587c8ce298a6cac2dce03c8a8eca5391","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"cd72d96dbf83183020b6d476224a4654587c8ce298a6cac2dce03c8a8eca5391","toolName":"scoped_echo","requestId":"QE8W3-P4XQM","timestamp":"2026-06-20T07:49:56.116Z","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:283: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:332: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."}
|
|
11
|
+
{"level":50,"time":1781941796125,"env":"testing","version":"0.0.0-test","pid":64938,"requestId":"O5VM6-4511G","timestamp":"2026-06-20T07:49:56.125Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"d8bd62ea8033d5f366561ebe1a7edeee06ea1fd415a0485a9c8e3e0405db7813","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":"d8bd62ea8033d5f366561ebe1a7edeee06ea1fd415a0485a9c8e3e0405db7813","toolName":"scoped_echo","requestId":"O5VM6-4511G","timestamp":"2026-06-20T07:49:56.125Z","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:283: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:332: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."}
|
|
12
|
+
{"level":40,"time":1781941850599,"env":"testing","version":"0.10.9","pid":66654,"transport":"http","requestId":"AVHC2-TQ4WB","timestamp":"2026-06-20T07:50:50.598Z","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."}
|
|
13
|
+
{"level":40,"time":1781941852475,"env":"testing","version":"0.10.9","pid":66654,"component":"HttpTransport","requestId":"IWBB2-XM5RC","timestamp":"2026-06-20T07:50:52.475Z","operation":"HttpRpcRequest","sessionId":"not-a-real-session-1781941852473","msg":"Session validation failed - invalid or hijacked session"}
|
|
14
|
+
{"level":50,"time":1781941859690,"env":"testing","version":"0.0.0-test","pid":66848,"requestId":"AZFXD-PQ7DK","timestamp":"2026-06-20T07:50:59.689Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"85e4333dbe697b7516d227521c97236ddd17f6ec81f2c9ee0196ce2645fb0dbd","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"85e4333dbe697b7516d227521c97236ddd17f6ec81f2c9ee0196ce2645fb0dbd","toolName":"scoped_echo","requestId":"AZFXD-PQ7DK","timestamp":"2026-06-20T07:50:59.689Z","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 (file:///Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:84:54)\n at withRequiredScopes (file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/authUtils.js:68:15)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:283:17\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)"},"stack":"McpError: Insufficient permissions.\n at ErrorHandler.handleError (file:///Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:19)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:332:26\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)","msg":"Error in tool:scoped_echo: Insufficient permissions."}
|
|
15
|
+
{"level":50,"time":1781941859700,"env":"testing","version":"0.0.0-test","pid":66848,"requestId":"SKS94-73A9N","timestamp":"2026-06-20T07:50:59.700Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"d22d4188544ccf25509b8570e83d6d33c0603fd1cf90dccbcd46321b282ba941","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":"d22d4188544ccf25509b8570e83d6d33c0603fd1cf90dccbcd46321b282ba941","toolName":"scoped_echo","requestId":"SKS94-73A9N","timestamp":"2026-06-20T07:50:59.700Z","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 (file:///Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:84:54)\n at withRequiredScopes (file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/authUtils.js:68:15)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:283:17\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)"},"stack":"McpError: Insufficient permissions.\n at ErrorHandler.handleError (file:///Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:19)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:332:26\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)","msg":"Error in tool:scoped_echo: Insufficient permissions."}
|
|
16
|
+
{"level":40,"time":1781941873566,"env":"testing","version":"0.10.9","pid":67154,"transport":"http","requestId":"P8B3O-4P9SU","timestamp":"2026-06-20T07:51:13.566Z","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."}
|
|
17
|
+
{"level":40,"time":1781941875328,"env":"testing","version":"0.10.9","pid":67154,"component":"HttpTransport","requestId":"KI665-ND0RJ","timestamp":"2026-06-20T07:51:15.328Z","operation":"HttpRpcRequest","sessionId":"not-a-real-session-1781941875328","msg":"Session validation failed - invalid or hijacked session"}
|
|
18
|
+
{"level":50,"time":1781941875790,"env":"testing","version":"0.0.0-test","pid":67189,"requestId":"14TZ3-3ZCS0","timestamp":"2026-06-20T07:51:15.789Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"ec0f8fbb4adfb0331f4128a3485b72a67a52d2875a3260079ddfb802757ac9ba","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"ec0f8fbb4adfb0331f4128a3485b72a67a52d2875a3260079ddfb802757ac9ba","toolName":"scoped_echo","requestId":"14TZ3-3ZCS0","timestamp":"2026-06-20T07:51:15.789Z","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:283: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:332: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."}
|
|
19
|
+
{"level":50,"time":1781941875797,"env":"testing","version":"0.0.0-test","pid":67189,"requestId":"SOHUW-Y0E4B","timestamp":"2026-06-20T07:51:15.797Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"2113a55565c3b427bbf85447bec3eb27975594598131a4bd4dba72532b7a88b9","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":"2113a55565c3b427bbf85447bec3eb27975594598131a4bd4dba72532b7a88b9","toolName":"scoped_echo","requestId":"SOHUW-Y0E4B","timestamp":"2026-06-20T07:51:15.797Z","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:283: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:332: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."}
|
package/dist/logs/error.log
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
{"level":50,"time":
|
|
2
|
-
{"level":50,"time":
|
|
3
|
-
{"level":50,"time":
|
|
4
|
-
{"level":50,"time":
|
|
1
|
+
{"level":50,"time":1781941725554,"env":"testing","version":"0.0.0-test","pid":63571,"requestId":"PP1XS-CJ3YO","timestamp":"2026-06-20T07:48:45.554Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"1f8f79dd7650efad787547e6d186503c524849b86f7028eb0a48f8dc6f0971e5","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"1f8f79dd7650efad787547e6d186503c524849b86f7028eb0a48f8dc6f0971e5","toolName":"scoped_echo","requestId":"PP1XS-CJ3YO","timestamp":"2026-06-20T07:48:45.554Z","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 (file:///Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:84:54)\n at withRequiredScopes (file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/authUtils.js:68:15)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:283:17\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)"},"stack":"McpError: Insufficient permissions.\n at ErrorHandler.handleError (file:///Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:19)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:332:26\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)","msg":"Error in tool:scoped_echo: Insufficient permissions."}
|
|
2
|
+
{"level":50,"time":1781941725565,"env":"testing","version":"0.0.0-test","pid":63571,"requestId":"8R56N-EA925","timestamp":"2026-06-20T07:48:45.565Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"4ff9f61440a71ba0f9c889f48708530881f35b46ef14e342bebfd3a5d386648d","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":"4ff9f61440a71ba0f9c889f48708530881f35b46ef14e342bebfd3a5d386648d","toolName":"scoped_echo","requestId":"8R56N-EA925","timestamp":"2026-06-20T07:48:45.565Z","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 (file:///Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:84:54)\n at withRequiredScopes (file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/authUtils.js:68:15)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:283:17\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)"},"stack":"McpError: Insufficient permissions.\n at ErrorHandler.handleError (file:///Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:19)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:332:26\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)","msg":"Error in tool:scoped_echo: Insufficient permissions."}
|
|
3
|
+
{"level":50,"time":1781941769956,"env":"testing","version":"0.0.0-test","pid":64367,"requestId":"BXZXW-ITAUJ","timestamp":"2026-06-20T07:49:29.955Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"d0084a4d9af8dde128d867a6ff54d073155e05898a72f6bf5971ae8834e267b4","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"d0084a4d9af8dde128d867a6ff54d073155e05898a72f6bf5971ae8834e267b4","toolName":"scoped_echo","requestId":"BXZXW-ITAUJ","timestamp":"2026-06-20T07:49:29.955Z","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:283: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:332: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":1781941769966,"env":"testing","version":"0.0.0-test","pid":64367,"requestId":"VFS62-PJ4HJ","timestamp":"2026-06-20T07:49:29.966Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"faf86ac4e0fa052ce32c646aab8dbbc7621060afc517e7dcf6a4c102cf021ee2","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":"faf86ac4e0fa052ce32c646aab8dbbc7621060afc517e7dcf6a4c102cf021ee2","toolName":"scoped_echo","requestId":"VFS62-PJ4HJ","timestamp":"2026-06-20T07:49:29.966Z","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:283: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:332: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":1781941796117,"env":"testing","version":"0.0.0-test","pid":64938,"requestId":"QE8W3-P4XQM","timestamp":"2026-06-20T07:49:56.116Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"cd72d96dbf83183020b6d476224a4654587c8ce298a6cac2dce03c8a8eca5391","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"cd72d96dbf83183020b6d476224a4654587c8ce298a6cac2dce03c8a8eca5391","toolName":"scoped_echo","requestId":"QE8W3-P4XQM","timestamp":"2026-06-20T07:49:56.116Z","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:283: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:332: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."}
|
|
6
|
+
{"level":50,"time":1781941796125,"env":"testing","version":"0.0.0-test","pid":64938,"requestId":"O5VM6-4511G","timestamp":"2026-06-20T07:49:56.125Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"d8bd62ea8033d5f366561ebe1a7edeee06ea1fd415a0485a9c8e3e0405db7813","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":"d8bd62ea8033d5f366561ebe1a7edeee06ea1fd415a0485a9c8e3e0405db7813","toolName":"scoped_echo","requestId":"O5VM6-4511G","timestamp":"2026-06-20T07:49:56.125Z","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:283: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:332: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."}
|
|
7
|
+
{"level":50,"time":1781941859690,"env":"testing","version":"0.0.0-test","pid":66848,"requestId":"AZFXD-PQ7DK","timestamp":"2026-06-20T07:50:59.689Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"85e4333dbe697b7516d227521c97236ddd17f6ec81f2c9ee0196ce2645fb0dbd","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"85e4333dbe697b7516d227521c97236ddd17f6ec81f2c9ee0196ce2645fb0dbd","toolName":"scoped_echo","requestId":"AZFXD-PQ7DK","timestamp":"2026-06-20T07:50:59.689Z","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 (file:///Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:84:54)\n at withRequiredScopes (file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/authUtils.js:68:15)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:283:17\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)"},"stack":"McpError: Insufficient permissions.\n at ErrorHandler.handleError (file:///Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:19)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:332:26\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)","msg":"Error in tool:scoped_echo: Insufficient permissions."}
|
|
8
|
+
{"level":50,"time":1781941859700,"env":"testing","version":"0.0.0-test","pid":66848,"requestId":"SKS94-73A9N","timestamp":"2026-06-20T07:50:59.700Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"d22d4188544ccf25509b8570e83d6d33c0603fd1cf90dccbcd46321b282ba941","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":"d22d4188544ccf25509b8570e83d6d33c0603fd1cf90dccbcd46321b282ba941","toolName":"scoped_echo","requestId":"SKS94-73A9N","timestamp":"2026-06-20T07:50:59.700Z","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 (file:///Users/casey/Developer/github/mcp-ts-core/dist/types-global/errors.js:84:54)\n at withRequiredScopes (file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/transports/auth/lib/authUtils.js:68:15)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:283:17\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)"},"stack":"McpError: Insufficient permissions.\n at ErrorHandler.handleError (file:///Users/casey/Developer/github/mcp-ts-core/dist/utils/internal/error-handler/errorHandler.js:170:19)\n at file:///Users/casey/Developer/github/mcp-ts-core/dist/mcp-server/tools/utils/toolHandlerFactory.js:332:26\n at McpServer.executeToolHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:233:42)\n at file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/mcp.js:126:43\n at async wrappedHandler (file:///Users/casey/Developer/github/mcp-ts-core/node_modules/@modelcontextprotocol/sdk/dist/esm/server/index.js:125:32)","msg":"Error in tool:scoped_echo: Insufficient permissions."}
|
|
9
|
+
{"level":50,"time":1781941875790,"env":"testing","version":"0.0.0-test","pid":67189,"requestId":"14TZ3-3ZCS0","timestamp":"2026-06-20T07:51:15.789Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"ec0f8fbb4adfb0331f4128a3485b72a67a52d2875a3260079ddfb802757ac9ba","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"ec0f8fbb4adfb0331f4128a3485b72a67a52d2875a3260079ddfb802757ac9ba","toolName":"scoped_echo","requestId":"14TZ3-3ZCS0","timestamp":"2026-06-20T07:51:15.789Z","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:283: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:332: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."}
|
|
10
|
+
{"level":50,"time":1781941875797,"env":"testing","version":"0.0.0-test","pid":67189,"requestId":"SOHUW-Y0E4B","timestamp":"2026-06-20T07:51:15.797Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"2113a55565c3b427bbf85447bec3eb27975594598131a4bd4dba72532b7a88b9","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":"2113a55565c3b427bbf85447bec3eb27975594598131a4bd4dba72532b7a88b9","toolName":"scoped_echo","requestId":"SOHUW-Y0E4B","timestamp":"2026-06-20T07:51:15.797Z","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:283: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:332: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."}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyanheads/mcp-ts-core",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.9",
|
|
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",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"dist/",
|
|
11
11
|
"scripts/build-changelog.ts",
|
|
12
12
|
"scripts/build.ts",
|
|
13
|
+
"scripts/check-dependency-specifiers.ts",
|
|
13
14
|
"scripts/check-docs-sync.ts",
|
|
14
15
|
"scripts/check-framework-antipatterns.ts",
|
|
15
16
|
"scripts/check-skill-versions.ts",
|
|
@@ -198,7 +199,7 @@
|
|
|
198
199
|
"devDependencies": {
|
|
199
200
|
"@biomejs/biome": "2.5.0",
|
|
200
201
|
"@cloudflare/vitest-pool-workers": "^0.16.18",
|
|
201
|
-
"@cloudflare/workers-types": "4.
|
|
202
|
+
"@cloudflare/workers-types": "4.20260620.1",
|
|
202
203
|
"@duckdb/node-api": "^1.5.4-r.1",
|
|
203
204
|
"@hono/otel": "^1.1.2",
|
|
204
205
|
"@opentelemetry/exporter-metrics-otlp-http": "^0.219.0",
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Rejects floating dependency specifiers — `latest`, `*`, and
|
|
4
|
+
* pre-release dist-tags (`next`/`beta`/`canary`/`rc`) — in the manifests we
|
|
5
|
+
* control: `package.json`'s dependency sections and `bun.lock`'s `workspaces`
|
|
6
|
+
* specifier maps. `bun update --latest` bumps `package.json` to a caret range
|
|
7
|
+
* but writes the literal `latest` dist-tag into the lock's workspace map; the
|
|
8
|
+
* concrete resolution is correct at write time, so it clears every other gate
|
|
9
|
+
* and ships unnoticed, letting the next `bun install` re-resolve the dep past
|
|
10
|
+
* the `package.json` range and past any intentional version hold (#246).
|
|
11
|
+
*
|
|
12
|
+
* Section-specific rules — `peer`/`optional` may legitimately float to "any
|
|
13
|
+
* host version", so `*` and dist-tags are allowed there; `latest` never is:
|
|
14
|
+
*
|
|
15
|
+
* | specifier | dependencies / devDependencies | peer / optional |
|
|
16
|
+
* |---------------------------|:------------------------------:|:---------------:|
|
|
17
|
+
* | latest | fail | fail |
|
|
18
|
+
* | * | fail | allow |
|
|
19
|
+
* | next / beta / canary / rc | fail | allow |
|
|
20
|
+
*
|
|
21
|
+
* Only the `workspaces` section of `bun.lock` is inspected — the `packages`
|
|
22
|
+
* section records third-party packages' own nested declarations, which can
|
|
23
|
+
* legitimately be `latest`/`*` (e.g. a vendored `"@edge-runtime/vm": "*"`), so
|
|
24
|
+
* a naive whole-file grep false-positives on those. The lock is JSONC (trailing
|
|
25
|
+
* commas), so it is normalized before parsing.
|
|
26
|
+
*
|
|
27
|
+
* Shipped to consumers via `package.json` `files:` because `devcheck` invokes
|
|
28
|
+
* it. Runs standalone (`bun run scripts/check-dependency-specifiers.ts`) and as
|
|
29
|
+
* a devcheck step; no network, no git — runs in the default and `--fast` passes.
|
|
30
|
+
*
|
|
31
|
+
* @module scripts/check-dependency-specifiers
|
|
32
|
+
*/
|
|
33
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
34
|
+
import { resolve } from 'node:path';
|
|
35
|
+
import process from 'node:process';
|
|
36
|
+
|
|
37
|
+
const ROOT = resolve('.');
|
|
38
|
+
|
|
39
|
+
const DEP_SECTIONS = [
|
|
40
|
+
'dependencies',
|
|
41
|
+
'devDependencies',
|
|
42
|
+
'peerDependencies',
|
|
43
|
+
'optionalDependencies',
|
|
44
|
+
] as const;
|
|
45
|
+
type DepSection = (typeof DEP_SECTIONS)[number];
|
|
46
|
+
|
|
47
|
+
/** Sections where a host project legitimately accepts "any version" (`*`/dist-tag). */
|
|
48
|
+
const HOST_SECTIONS = new Set<DepSection>(['peerDependencies', 'optionalDependencies']);
|
|
49
|
+
|
|
50
|
+
/** Pre-release dist-tags that float like `latest`, narrower in reach. */
|
|
51
|
+
const FLOATING_DIST_TAGS = new Set(['next', 'beta', 'canary', 'rc']);
|
|
52
|
+
|
|
53
|
+
interface Offender {
|
|
54
|
+
location: string;
|
|
55
|
+
name: string;
|
|
56
|
+
specifier: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
type DepMap = Record<string, string>;
|
|
60
|
+
type SectionedManifest = Partial<Record<DepSection, DepMap>>;
|
|
61
|
+
|
|
62
|
+
/** A specifier floats if it can re-resolve to a different version over time. */
|
|
63
|
+
function isFloating(specifier: string, section: DepSection): boolean {
|
|
64
|
+
const spec = specifier.trim();
|
|
65
|
+
if (spec === 'latest') return true; // never reproducible, in any section
|
|
66
|
+
if (HOST_SECTIONS.has(section)) return false; // `*` / dist-tags are legitimate here
|
|
67
|
+
return spec === '*' || FLOATING_DIST_TAGS.has(spec);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Scan the four dependency sections of one manifest object. */
|
|
71
|
+
function scanManifest(manifest: SectionedManifest, label: string): Offender[] {
|
|
72
|
+
const offenders: Offender[] = [];
|
|
73
|
+
for (const section of DEP_SECTIONS) {
|
|
74
|
+
const deps = manifest[section];
|
|
75
|
+
if (!deps || typeof deps !== 'object') continue;
|
|
76
|
+
for (const [name, specifier] of Object.entries(deps)) {
|
|
77
|
+
if (typeof specifier === 'string' && isFloating(specifier, section)) {
|
|
78
|
+
offenders.push({ name, specifier, location: `${label} ${section}` });
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return offenders;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Minimal JSONC → object parse: strips `//` and block comments and trailing
|
|
87
|
+
* commas while preserving string contents verbatim, then `JSON.parse`s.
|
|
88
|
+
* `bun.lock` is emitted with trailing commas, which strict `JSON.parse` rejects.
|
|
89
|
+
*/
|
|
90
|
+
function parseJsonc<T>(text: string): T {
|
|
91
|
+
let out = '';
|
|
92
|
+
let i = 0;
|
|
93
|
+
const n = text.length;
|
|
94
|
+
while (i < n) {
|
|
95
|
+
const ch = text[i] as string;
|
|
96
|
+
if (ch === '"') {
|
|
97
|
+
// Copy a string literal verbatim, honoring escapes.
|
|
98
|
+
out += ch;
|
|
99
|
+
i++;
|
|
100
|
+
while (i < n) {
|
|
101
|
+
const c = text[i] as string;
|
|
102
|
+
out += c;
|
|
103
|
+
if (c === '\\') {
|
|
104
|
+
out += text[i + 1] ?? '';
|
|
105
|
+
i += 2;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
i++;
|
|
109
|
+
if (c === '"') break;
|
|
110
|
+
}
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (ch === '/' && text[i + 1] === '/') {
|
|
114
|
+
const nl = text.indexOf('\n', i);
|
|
115
|
+
if (nl === -1) break;
|
|
116
|
+
i = nl;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (ch === '/' && text[i + 1] === '*') {
|
|
120
|
+
const end = text.indexOf('*/', i + 2);
|
|
121
|
+
i = end === -1 ? n : end + 2;
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (ch === ',') {
|
|
125
|
+
// Drop the comma when the next significant char closes an object/array.
|
|
126
|
+
let j = i + 1;
|
|
127
|
+
while (j < n && /\s/.test(text[j] as string)) j++;
|
|
128
|
+
if (text[j] === '}' || text[j] === ']') {
|
|
129
|
+
i++;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
out += ch;
|
|
134
|
+
i++;
|
|
135
|
+
}
|
|
136
|
+
return JSON.parse(out) as T;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const offenders: Offender[] = [];
|
|
140
|
+
|
|
141
|
+
// ── package.json (all four dependency sections) ──
|
|
142
|
+
const pkgPath = resolve(ROOT, 'package.json');
|
|
143
|
+
if (existsSync(pkgPath)) {
|
|
144
|
+
try {
|
|
145
|
+
offenders.push(
|
|
146
|
+
...scanManifest(
|
|
147
|
+
JSON.parse(readFileSync(pkgPath, 'utf-8')) as SectionedManifest,
|
|
148
|
+
'package.json',
|
|
149
|
+
),
|
|
150
|
+
);
|
|
151
|
+
} catch (err) {
|
|
152
|
+
console.error(`Failed to parse package.json: ${err instanceof Error ? err.message : err}`);
|
|
153
|
+
process.exit(2);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ── bun.lock (workspaces specifier maps only — never the `packages` section) ──
|
|
158
|
+
const lockPath = resolve(ROOT, 'bun.lock');
|
|
159
|
+
if (existsSync(lockPath)) {
|
|
160
|
+
try {
|
|
161
|
+
const lock = parseJsonc<{ workspaces?: Record<string, SectionedManifest> }>(
|
|
162
|
+
readFileSync(lockPath, 'utf-8'),
|
|
163
|
+
);
|
|
164
|
+
for (const [ws, manifest] of Object.entries(lock.workspaces ?? {})) {
|
|
165
|
+
const label = ws === '' ? 'bun.lock workspaces[root]' : `bun.lock workspaces["${ws}"]`;
|
|
166
|
+
offenders.push(...scanManifest(manifest, label));
|
|
167
|
+
}
|
|
168
|
+
} catch (err) {
|
|
169
|
+
console.error(`Failed to parse bun.lock: ${err instanceof Error ? err.message : err}`);
|
|
170
|
+
process.exit(2);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (offenders.length === 0) {
|
|
175
|
+
console.log('No floating dependency specifiers found.');
|
|
176
|
+
process.exit(0);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const lines = [
|
|
180
|
+
`${offenders.length} floating dependency specifier(s) found:`,
|
|
181
|
+
'',
|
|
182
|
+
...offenders.map((o) => ` - ${o.name} → ${o.specifier} (${o.location})`),
|
|
183
|
+
'',
|
|
184
|
+
'Fix: pin to a concrete semver range (e.g. ^1.2.3). A `latest`/`*`/dist-tag',
|
|
185
|
+
'specifier lets `bun install` re-resolve the dep past the package.json range',
|
|
186
|
+
'and past any intentional hold. After `bun update --latest`, run a plain',
|
|
187
|
+
'`bun install` to reconcile bun.lock to the package.json ranges.',
|
|
188
|
+
];
|
|
189
|
+
console.error(lines.join('\n'));
|
|
190
|
+
process.exit(1);
|
package/scripts/devcheck.ts
CHANGED
|
@@ -437,10 +437,16 @@ const ALL_CHECKS: Check[] = [
|
|
|
437
437
|
flag: '--no-packaging',
|
|
438
438
|
canFix: false,
|
|
439
439
|
// Validates env var alignment between manifest.json (MCPB bundle) and
|
|
440
|
-
// server.json (MCP Registry)
|
|
441
|
-
//
|
|
440
|
+
// server.json (MCP Registry), plus plugin marketplace manifests (#240).
|
|
441
|
+
// Runs when manifest.json OR any plugin manifest is present; skipped cleanly
|
|
442
|
+
// when none exist — consumers on an HTTP-only deploy are unaffected.
|
|
442
443
|
getCommand: () => {
|
|
443
|
-
|
|
444
|
+
const hasManifest = existsSync(path.join(ROOT_DIR, 'manifest.json'));
|
|
445
|
+
const hasPluginManifest =
|
|
446
|
+
existsSync(path.join(ROOT_DIR, '.claude-plugin/plugin.json')) ||
|
|
447
|
+
existsSync(path.join(ROOT_DIR, '.codex-plugin/plugin.json')) ||
|
|
448
|
+
existsSync(path.join(ROOT_DIR, '.codex-plugin/mcp.json'));
|
|
449
|
+
if (!hasManifest && !hasPluginManifest) return null;
|
|
444
450
|
return ['bun', 'run', 'scripts/lint-packaging.ts'];
|
|
445
451
|
},
|
|
446
452
|
tip: (c) =>
|
|
@@ -458,6 +464,18 @@ const ALL_CHECKS: Check[] = [
|
|
|
458
464
|
tip: (c) =>
|
|
459
465
|
`Remove the flagged SDK-coupling shortcut. See ${c.bold('scripts/check-framework-antipatterns.ts')} for rule rationale.`,
|
|
460
466
|
},
|
|
467
|
+
{
|
|
468
|
+
name: 'Dependency Specifiers',
|
|
469
|
+
flag: '--no-dep-specifiers',
|
|
470
|
+
canFix: false,
|
|
471
|
+
// Rejects floating specifiers (latest/*/dist-tags) in package.json + the
|
|
472
|
+
// bun.lock workspaces map (#246). Static and local — no network, no git —
|
|
473
|
+
// so it runs in the default and --fast passes. Shipped to consumers via
|
|
474
|
+
// package.json `files:`; reads package.json/bun.lock directly, no guard.
|
|
475
|
+
getCommand: () => ['bun', 'run', 'scripts/check-dependency-specifiers.ts'],
|
|
476
|
+
tip: (c) =>
|
|
477
|
+
`Pin the flagged dep to a concrete range; after ${c.bold('bun update --latest')} run a plain ${c.bold('bun install')} to reconcile ${c.bold('bun.lock')}.`,
|
|
478
|
+
},
|
|
461
479
|
{
|
|
462
480
|
name: 'Open-Indexed Interfaces',
|
|
463
481
|
flag: '--no-open-index',
|
|
@@ -32,6 +32,15 @@
|
|
|
32
32
|
* `createWorkerHandler()` (src/index.ts, src/worker.ts) and manifest
|
|
33
33
|
* `display_name` must equal the unscoped package name; a partial
|
|
34
34
|
* `name`/`title` pair warns without failing (issue #231).
|
|
35
|
+
* 10. Plugin marketplace manifests (`.claude-plugin/plugin.json`,
|
|
36
|
+
* `.codex-plugin/plugin.json`, `.codex-plugin/mcp.json`): non-empty
|
|
37
|
+
* descriptions, and identity/install correctness — display fields
|
|
38
|
+
* (`name`, server key, `interface.displayName`) carry the unscoped machine
|
|
39
|
+
* name while the `npx -y` install arg carries the full `package.json`
|
|
40
|
+
* name (scoped if scoped). An unscoped install arg for a scoped package
|
|
41
|
+
* is a guaranteed install 404. Gated by `devcheck.config.json`
|
|
42
|
+
* `packaging.pluginManifests` (default on); each manifest is skipped
|
|
43
|
+
* cleanly when absent (issue #240).
|
|
35
44
|
*
|
|
36
45
|
* Every check skips cleanly when its input is absent — consumers who deleted
|
|
37
46
|
* `manifest.json` for an HTTP-only deploy, or who haven't built a bundle,
|
|
@@ -374,6 +383,128 @@ export function checkManifestIdentity(manifest: Manifest, unscopedName: string):
|
|
|
374
383
|
return [];
|
|
375
384
|
}
|
|
376
385
|
|
|
386
|
+
/** Parsed plugin marketplace manifests; an absent manifest is `undefined`. */
|
|
387
|
+
export interface PluginManifestInputs {
|
|
388
|
+
claudePlugin?: unknown;
|
|
389
|
+
codexMcp?: unknown;
|
|
390
|
+
codexPlugin?: unknown;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const isRecord = (v: unknown): v is Record<string, unknown> => typeof v === 'object' && v !== null;
|
|
394
|
+
const isNonEmptyString = (v: unknown): boolean => typeof v === 'string' && v.trim().length > 0;
|
|
395
|
+
|
|
396
|
+
/** The `npx -y <pkg>` install target is the arg after the `-y` flag (args[1]). */
|
|
397
|
+
function installArg(entry: Record<string, unknown>): unknown {
|
|
398
|
+
return Array.isArray(entry.args) ? entry.args[1] : undefined;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Check 10: plugin marketplace manifests. Display fields (`name`, server key,
|
|
403
|
+
* `interface.displayName`) must equal the unscoped machine name; the install
|
|
404
|
+
* arg must equal the full `package.json` name (the real `npx` target). Empty
|
|
405
|
+
* descriptions ship blank marketplace cards. Each manifest is validated only
|
|
406
|
+
* when present, so HTTP-only and non-plugin consumers are unaffected. The
|
|
407
|
+
* caller gates the whole check on `packaging.pluginManifests`.
|
|
408
|
+
*/
|
|
409
|
+
export function checkPluginManifests(
|
|
410
|
+
inputs: PluginManifestInputs,
|
|
411
|
+
unscopedName: string,
|
|
412
|
+
fullName: string,
|
|
413
|
+
): string[] {
|
|
414
|
+
const errors: string[] = [];
|
|
415
|
+
const optOut =
|
|
416
|
+
'(or set "packaging": { "pluginManifests": false } in devcheck.config.json to opt out)';
|
|
417
|
+
|
|
418
|
+
// ── .claude-plugin/plugin.json ──
|
|
419
|
+
const claude = inputs.claudePlugin;
|
|
420
|
+
if (isRecord(claude)) {
|
|
421
|
+
const f = '.claude-plugin/plugin.json';
|
|
422
|
+
if (!isNonEmptyString(claude.description)) {
|
|
423
|
+
errors.push(`${f} "description" is empty — populate it ${optOut}`);
|
|
424
|
+
}
|
|
425
|
+
if (claude.name !== unscopedName) {
|
|
426
|
+
errors.push(
|
|
427
|
+
`${f} "name" is "${String(claude.name)}" — must equal the unscoped package name "${unscopedName}"`,
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
const servers = claude.mcpServers;
|
|
431
|
+
if (isRecord(servers)) {
|
|
432
|
+
if (!(unscopedName in servers)) {
|
|
433
|
+
errors.push(
|
|
434
|
+
`${f} mcpServers has no "${unscopedName}" entry — the server key must be the unscoped package name`,
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
const entry = servers[unscopedName];
|
|
438
|
+
if (isRecord(entry) && installArg(entry) !== fullName) {
|
|
439
|
+
errors.push(
|
|
440
|
+
`${f} mcpServers["${unscopedName}"] install arg is "${String(installArg(entry))}" — ` +
|
|
441
|
+
`must be the full package name "${fullName}" (the npx -y target; an unscoped arg for a scoped package 404s)`,
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// ── .codex-plugin/plugin.json ──
|
|
448
|
+
const codex = inputs.codexPlugin;
|
|
449
|
+
if (isRecord(codex)) {
|
|
450
|
+
const f = '.codex-plugin/plugin.json';
|
|
451
|
+
if (!isNonEmptyString(codex.description)) {
|
|
452
|
+
errors.push(`${f} "description" is empty — populate it ${optOut}`);
|
|
453
|
+
}
|
|
454
|
+
if (codex.name !== unscopedName) {
|
|
455
|
+
errors.push(
|
|
456
|
+
`${f} "name" is "${String(codex.name)}" — must equal the unscoped package name "${unscopedName}"`,
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
const iface = codex.interface;
|
|
460
|
+
if (isRecord(iface)) {
|
|
461
|
+
if (iface.displayName !== unscopedName) {
|
|
462
|
+
errors.push(
|
|
463
|
+
`${f} interface.displayName is "${String(iface.displayName)}" — must equal the unscoped package name "${unscopedName}"`,
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
if (!isNonEmptyString(iface.shortDescription)) {
|
|
467
|
+
errors.push(`${f} interface.shortDescription is empty — populate it ${optOut}`);
|
|
468
|
+
}
|
|
469
|
+
if (!isNonEmptyString(iface.longDescription)) {
|
|
470
|
+
errors.push(`${f} interface.longDescription is empty — populate it ${optOut}`);
|
|
471
|
+
}
|
|
472
|
+
} else {
|
|
473
|
+
errors.push(
|
|
474
|
+
`${f} is missing the "interface" object (displayName / shortDescription / longDescription)`,
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// ── .codex-plugin/mcp.json ──
|
|
480
|
+
const codexMcp = inputs.codexMcp;
|
|
481
|
+
if (isRecord(codexMcp)) {
|
|
482
|
+
const f = '.codex-plugin/mcp.json';
|
|
483
|
+
if (!(unscopedName in codexMcp)) {
|
|
484
|
+
errors.push(
|
|
485
|
+
`${f} has no "${unscopedName}" server entry — the server key must be the unscoped package name`,
|
|
486
|
+
);
|
|
487
|
+
}
|
|
488
|
+
const entry = codexMcp[unscopedName];
|
|
489
|
+
if (isRecord(entry) && installArg(entry) !== fullName) {
|
|
490
|
+
errors.push(
|
|
491
|
+
`${f} "${unscopedName}" install arg is "${String(installArg(entry))}" — ` +
|
|
492
|
+
`must be the full package name "${fullName}" (the npx -y target)`,
|
|
493
|
+
);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
return errors;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/** Read `packaging.pluginManifests` from devcheck.config.json; default on. */
|
|
501
|
+
function pluginManifestsEnabled(): boolean {
|
|
502
|
+
const cfg = tryReadJson<{ packaging?: { pluginManifests?: boolean } }>(
|
|
503
|
+
resolve('devcheck.config.json'),
|
|
504
|
+
);
|
|
505
|
+
return cfg?.packaging?.pluginManifests ?? true;
|
|
506
|
+
}
|
|
507
|
+
|
|
377
508
|
async function main(): Promise<void> {
|
|
378
509
|
const errors: string[] = [];
|
|
379
510
|
const warnings: string[] = [];
|
|
@@ -496,6 +627,27 @@ async function main(): Promise<void> {
|
|
|
496
627
|
}
|
|
497
628
|
}
|
|
498
629
|
|
|
630
|
+
// ── Plugin marketplace manifests (check 10) ──
|
|
631
|
+
if (unscopedName && pkg?.name) {
|
|
632
|
+
if (pluginManifestsEnabled()) {
|
|
633
|
+
errors.push(
|
|
634
|
+
...checkPluginManifests(
|
|
635
|
+
{
|
|
636
|
+
claudePlugin: tryReadJson(resolve('.claude-plugin/plugin.json')),
|
|
637
|
+
codexPlugin: tryReadJson(resolve('.codex-plugin/plugin.json')),
|
|
638
|
+
codexMcp: tryReadJson(resolve('.codex-plugin/mcp.json')),
|
|
639
|
+
},
|
|
640
|
+
unscopedName,
|
|
641
|
+
pkg.name,
|
|
642
|
+
),
|
|
643
|
+
);
|
|
644
|
+
} else {
|
|
645
|
+
notes.push(
|
|
646
|
+
'Plugin-manifest checks disabled via devcheck.config.json packaging.pluginManifests.',
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
499
651
|
for (const note of notes) console.log(note);
|
|
500
652
|
for (const warning of warnings) console.warn(` ⚠ ${warning}`);
|
|
501
653
|
|
|
@@ -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.9"
|
|
8
8
|
audience: external
|
|
9
9
|
type: workflow
|
|
10
10
|
---
|
|
@@ -169,20 +169,22 @@ Never hand-edit `CHANGELOG.md` when using this pattern — it's a build artifact
|
|
|
169
169
|
|
|
170
170
|
### 10. Plugin Metadata (Codex / Claude Code)
|
|
171
171
|
|
|
172
|
+
`lint:packaging` (run by `devcheck`) now enforces the high-value subset automatically when these manifests are present: non-empty descriptions, and identity/install correctness — display fields (`name`, server key, `interface.displayName`) must be the **unscoped** machine name, while the `npx -y` install arg must be the full `package.json` `name` (scoped if scoped). Opt out per project with `"packaging": { "pluginManifests": false }` in `devcheck.config.json`. The checks below cover the fields the gate doesn't (version / repository / license sync, category, env vars).
|
|
173
|
+
|
|
172
174
|
If `.codex-plugin/plugin.json` exists, verify it's populated and in sync with `package.json` and `server.json`:
|
|
173
175
|
|
|
174
|
-
- `name`
|
|
176
|
+
- `name` is the unscoped `package.json` `name` (display identity is the machine name on every surface)
|
|
175
177
|
- `version` matches `package.json` `version`
|
|
176
178
|
- `description` matches `package.json` `description`
|
|
177
179
|
- `repository` matches `package.json` `repository.url`
|
|
178
180
|
- `license` matches `package.json` `license`
|
|
179
|
-
- `interface.displayName`
|
|
181
|
+
- `interface.displayName` is the unscoped `package.json` `name`
|
|
180
182
|
- `interface.shortDescription` matches `package.json` `description`
|
|
181
183
|
- `interface.category` is set to a meaningful category
|
|
182
184
|
|
|
183
|
-
If `.codex-plugin/mcp.json` exists, verify the server
|
|
185
|
+
If `.codex-plugin/mcp.json` exists, verify the server-name key is the unscoped `package.json` `name`, the `npx -y` install arg is the full `package.json` `name`, and env vars include any required API keys from the server config schema.
|
|
184
186
|
|
|
185
|
-
If `.claude-plugin/plugin.json` exists, apply the same checks: `name
|
|
187
|
+
If `.claude-plugin/plugin.json` exists, apply the same checks: `name` (unscoped), `version`, `description`, `repository`, `license` from `package.json`. Verify the inline `mcpServers` entry key is the unscoped name, its `npx -y` install arg is the full `package.json` `name`, and env vars include any required API keys.
|
|
186
188
|
|
|
187
189
|
### 11. MCPB Bundling Artifacts
|
|
188
190
|
|