@cyanheads/mcp-ts-core 0.9.13 → 0.9.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/CLAUDE.md +6 -3
  2. package/README.md +30 -41
  3. package/changelog/0.9.x/0.9.14.md +31 -0
  4. package/dist/core/context.d.ts +103 -14
  5. package/dist/core/context.d.ts.map +1 -1
  6. package/dist/core/context.js +66 -1
  7. package/dist/core/context.js.map +1 -1
  8. package/dist/core/index.d.ts +1 -1
  9. package/dist/core/index.d.ts.map +1 -1
  10. package/dist/core/index.js.map +1 -1
  11. package/dist/linter/rules/enrichment-rules.d.ts +32 -0
  12. package/dist/linter/rules/enrichment-rules.d.ts.map +1 -0
  13. package/dist/linter/rules/enrichment-rules.js +116 -0
  14. package/dist/linter/rules/enrichment-rules.js.map +1 -0
  15. package/dist/linter/rules/index.d.ts +1 -0
  16. package/dist/linter/rules/index.d.ts.map +1 -1
  17. package/dist/linter/rules/index.js +1 -0
  18. package/dist/linter/rules/index.js.map +1 -1
  19. package/dist/linter/rules/tool-rules.d.ts.map +1 -1
  20. package/dist/linter/rules/tool-rules.js +4 -0
  21. package/dist/linter/rules/tool-rules.js.map +1 -1
  22. package/dist/mcp-server/tools/tool-registration.d.ts.map +1 -1
  23. package/dist/mcp-server/tools/tool-registration.js +7 -7
  24. package/dist/mcp-server/tools/tool-registration.js.map +1 -1
  25. package/dist/mcp-server/tools/utils/toolDefinition.d.ts +41 -7
  26. package/dist/mcp-server/tools/utils/toolDefinition.d.ts.map +1 -1
  27. package/dist/mcp-server/tools/utils/toolDefinition.js.map +1 -1
  28. package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts +23 -1
  29. package/dist/mcp-server/tools/utils/toolHandlerFactory.d.ts.map +1 -1
  30. package/dist/mcp-server/tools/utils/toolHandlerFactory.js +90 -9
  31. package/dist/mcp-server/tools/utils/toolHandlerFactory.js.map +1 -1
  32. package/dist/testing/index.d.ts +13 -0
  33. package/dist/testing/index.d.ts.map +1 -1
  34. package/dist/testing/index.js +21 -1
  35. package/dist/testing/index.js.map +1 -1
  36. package/dist/utils/internal/performance.d.ts +5 -1
  37. package/dist/utils/internal/performance.d.ts.map +1 -1
  38. package/dist/utils/internal/performance.js +10 -1
  39. package/dist/utils/internal/performance.js.map +1 -1
  40. package/dist/utils/telemetry/attributes.d.ts +2 -0
  41. package/dist/utils/telemetry/attributes.d.ts.map +1 -1
  42. package/dist/utils/telemetry/attributes.js +2 -0
  43. package/dist/utils/telemetry/attributes.js.map +1 -1
  44. package/package.json +1 -1
  45. package/skills/add-tool/SKILL.md +57 -32
  46. package/skills/api-context/SKILL.md +65 -2
  47. package/skills/api-linter/SKILL.md +48 -1
  48. package/skills/design-mcp-server/SKILL.md +2 -1
  49. package/skills/orchestrations/SKILL.md +9 -5
  50. package/skills/report-issue-framework/SKILL.md +8 -3
  51. package/skills/report-issue-local/SKILL.md +8 -3
  52. package/templates/src/mcp-server/tools/definitions/echo.tool.ts +10 -0
  53. package/dist/logs/combined.log +0 -4
  54. package/dist/logs/error.log +0 -2
  55. package/dist/logs/interactions.log +0 -0
@@ -4,7 +4,7 @@ description: >
4
4
  MCP definition linter rules reference. Use when `bun run lint:mcp` or `bun run devcheck` reports a lint error or warning (`format-parity`, `schema-is-object`, `name-format`, `server-json-*`, etc.) and you need to understand the rule, its severity, and how to fix it. Every rule ID the linter emits has an entry in this doc.
5
5
  metadata:
6
6
  author: cyanheads
7
- version: "1.3"
7
+ version: "1.4"
8
8
  audience: external
9
9
  type: reference
10
10
  ---
@@ -53,6 +53,7 @@ Grouped by family. Jump to any rule ID via its anchor.
53
53
  | Handler body | `prefer-mcp-error-in-handler`, `prefer-error-factory`, `preserve-cause-on-rethrow`, `no-stringify-upstream-error` | [Handler body rules](#handler-body-rules) |
54
54
  | Error contract (structural) | `error-contract-type`, `error-contract-empty`, `error-contract-entry-type`, `error-contract-code-type`, `error-contract-code-unknown`, `error-contract-code-unknown-error`, `error-contract-reason-required`, `error-contract-reason-format`, `error-contract-reason-unique`, `error-contract-when-required`, `error-contract-retryable-type`, `error-contract-recovery-required`, `error-contract-recovery-empty`, `error-contract-recovery-min-words` | [Error contract rules](#error-contract-rules) |
55
55
  | Error contract (conformance) | `error-contract-conformance`, `error-contract-prefer-fail` | [Error contract rules](#error-contract-rules) |
56
+ | Enrichment | `enrichment-type`, `enrichment-empty`, `enrichment-field-type`, `enrichment-output-collision`, `enrichment-prefer-block` | [Enrichment rules](#enrichment-rules) |
56
57
  | server.json | ~40 rules prefixed `server-json-*` | [server.json rules](#server-json-rules) |
57
58
 
58
59
  ---
@@ -708,6 +709,52 @@ The diagnostic message includes the declared reason(s) for the code so you can c
708
709
 
709
710
  ---
710
711
 
712
+ ## Enrichment rules
713
+
714
+ Validate the `enrichment` block — the success-path counterpart to `errors[]`. Enrichment fields are merged into `structuredContent` and advertised as `output.extend(enrichment)`, so the linter guards the block's shape and its disjointness from `output`. See `api-context`'s `ctx.enrich` and `add-tool`'s **Tool Response Design**.
715
+
716
+ ### enrichment-type
717
+
718
+ **Severity:** error
719
+
720
+ Fires when `enrichment` is present but isn't a plain object mapping field names to Zod schemas (a `ZodRawShape`) — e.g. an array or a primitive.
721
+
722
+ **Fix:** declare `enrichment: { <name>: <ZodType>, … }`.
723
+
724
+ ### enrichment-empty
725
+
726
+ **Severity:** warning
727
+
728
+ Fires when `enrichment: {}` is declared with no fields — a no-op.
729
+
730
+ **Fix:** drop the field, or declare the agent-facing fields `ctx.enrich(...)` will populate.
731
+
732
+ ### enrichment-field-type
733
+
734
+ **Severity:** error
735
+
736
+ Fires when an enrichment field's value isn't a Zod schema.
737
+
738
+ **Fix:** use a Zod type (`z.string().describe(…)`, `z.number().describe(…)`, …) for every enrichment field.
739
+
740
+ ### enrichment-output-collision
741
+
742
+ **Severity:** error
743
+
744
+ Fires when an enrichment key matches an `output` key. The effective output schema is `output.extend(enrichment)`, so a collision silently overrides the `output` field.
745
+
746
+ **Fix:** rename one side so enrichment keys are disjoint from output keys.
747
+
748
+ ### enrichment-prefer-block
749
+
750
+ **Severity:** warning
751
+
752
+ Advisory. Fires when a tool has **no** `enrichment` block but an `output` field whose name strongly signals agent-facing context (`notice`, `effectiveQuery`, `queryEcho`) rather than domain payload.
753
+
754
+ **Fix:** move the field into an `enrichment` block and populate it via `ctx.enrich(...)` — it reaches both client surfaces without a `format()` entry. Ignore if the field is genuinely domain data. Deliberately conservative — common domain fields like `totalCount` are not flagged.
755
+
756
+ ---
757
+
711
758
  ## Escape hatches
712
759
 
713
760
  ### Dynamic upstream data
@@ -4,7 +4,7 @@ description: >
4
4
  Design the tool surface, resources, and service layer for a new MCP server. Use when starting a new server, planning a major feature expansion, or when the user describes a domain/API they want to expose via MCP. Produces a design doc at docs/design.md that drives implementation.
5
5
  metadata:
6
6
  author: cyanheads
7
- version: "2.12"
7
+ version: "2.13"
8
8
  audience: external
9
9
  type: workflow
10
10
  ---
@@ -351,6 +351,7 @@ output: z.object({
351
351
  - **Truncate large output with counts.** When a list exceeds a reasonable display size, show the top N and append "...and X more". Don't silently drop results.
352
352
  - **Spill big tabular results to a queryable surface.** When a tool's row set can exceed any reasonable context budget — paginated APIs, streamed exports, big query results — pair an inline preview with a `DataCanvas` table holding the full set, returned as a token the agent can SQL. Compute distributions or refinement hints across the full result, not the preview, so aggregate signal stays honest. See `api-canvas` for the `spillover()` helper.
353
353
  - **`format()` is the markdown twin of `structuredContent` — make both content-complete.** Different MCP clients forward different surfaces to the model: some (e.g., Claude Code) read `structuredContent` from `output`, others (e.g., Claude Desktop) read `content[]` from `format()`. Both must carry the same data so every client sees the same picture — `format()` just dresses it up with markdown. A thin `format()` that returns only a count or title leaves `content[]`-only clients blind to data that `structuredContent` clients can see. Render all fields the LLM needs, with structured markdown (headers, bold labels, lists) for readability.
354
+ - **Agent-facing context must reach both client surfaces — put it in `enrichment`.** `structuredContent` (from `output`) and `content[]` (from `format()`) are read by different clients. Empty-result notices, the query/filter as the server parsed it, and pagination totals — the context the agent *reasons with*, distinct from the domain payload — reach only `content[]` if hand-authored into `format()` text alone, leaving `structuredContent`-only clients (Claude Code) blind. (The reverse can't happen: `format-parity` drags every `output` field into `format()`, so `output`-authored context already reaches both.) An `enrichment` block — the success-path counterpart to `errors[]`, populated via `ctx.enrich(...)` — reaches both automatically: merged into `structuredContent`, advertised as `output.extend(enrichment)`, mirrored into a `content[]` trailer, no `format()` entry needed. See `add-tool`'s **Tool Response Design**.
354
355
 
355
356
  #### Batch input design
356
357
 
@@ -69,7 +69,7 @@ The orchestrator owns the goals. Workflow phases are not "run skill X" — they
69
69
  Before running a phase (or spawning a sub-agent for it), write down four things:
70
70
 
71
71
  1. **Goal** — the verifiable end state this phase must produce. Concrete and testable: "v0.5.2 tag exists at HEAD with structured-markdown annotation; `bun run devcheck` green; `npm view <pkg>@0.5.2` resolves." Not fuzzy: "ran the release-and-publish skill."
72
- 2. **Primary sources** — the specific files, GH issues, and reference docs the sub-agent must read directly. Inlining content into the prompt is a paraphrase that loses nuance; agents grounded in the source catch details the orchestrator's summary missed. For GH issues, instruct `gh issue view N --comments` — body alone misses thread clarifications. The orchestrator reads these sources too (to construct the prompt), but that's prompt construction, not a substitute for the sub-agent reading them.
72
+ 2. **Primary sources** — the specific files, GH issues, and reference docs the sub-agent must read directly. Inlining content into the prompt is a paraphrase that loses nuance; agents grounded in the source catch details the orchestrator's summary missed. For GH issues, instruct both `gh issue view N --comments` (the comment thread) and the timeline cross-reference query in the Orient block (what references the issue, including cross-repo) the body alone misses both. The orchestrator reads these sources too (to construct the prompt), but that's prompt construction, not a substitute for the sub-agent reading them.
73
73
  3. **Path** — the Tier 1 skill(s) and steps that get to the goal. This is what gets handed to the sub-agent.
74
74
  4. **Verification** — the read-only checks that confirm the goal was hit. Defined upfront, not as an afterthought.
75
75
 
@@ -91,6 +91,8 @@ Sub-agents are optional. Match the mechanism to your platform's capability — t
91
91
 
92
92
  Phases, gates, goals, and constraints are identical across all three tiers — only the fanout mechanism changes. Use the most capable tier available, and don't hand-roll what the platform does natively (e.g., rolling concurrency). Choose by scope and capability, not by default.
93
93
 
94
+ **Model tier ≠ orchestration tier.** A higher orchestration tier is not automatically the right choice. On some platforms, programmatically-orchestrated or *nested* sub-agents (an agent spawning agents) silently run on a cheaper/downgraded model, while the strongest model is reachable only by sub-agents the **main loop spawns directly** (tier 2). When a phase needs the top model (heavy generation, design, framework adoption), prefer direct main-loop fanout even when a more "capable" orchestration primitive exists — the primitive can cost you the model. Verify the model your platform actually assigned via its UI/telemetry; never infer it from a sub-agent's transcript, which interleaves auxiliary calls (titles, summaries) on cheaper models and will mislead you.
95
+
94
96
  The decision tree below is orthogonal to tier — it governs *whether* a given phase fans out, by target count and conflict risk:
95
97
 
96
98
  | Situation | Strategy |
@@ -119,10 +121,12 @@ order. If any file does not exist, note it and continue.
119
121
  available skills with descriptions and locations.
120
122
  5. Read the skill file(s) for this task: `[Tier 1 skill paths]`.
121
123
  6. Read the primary sources for this task directly — design docs (`docs/design.md`),
122
- GH issues (use `gh issue view <N> --comments` to capture the full thread, not
123
- just the body), handoff documents, reference/gold-standard files. List each
124
- one explicitly: `[primary source paths and gh commands]`. Skip this step only
125
- if no primary source applies (rare).
124
+ GH issues, handoff documents, reference/gold-standard files. For a GH issue, read
125
+ both the comment thread and its cross-references the body alone misses both:
126
+ - `gh issue view <N> --comments` description + comment thread
127
+ - `gh api 'repos/{owner}/{repo}/issues/<N>/timeline' --paginate --jq '.[] | select(.event=="cross-referenced") | .source.issue | "\(.repository.full_name)#\(.number) — \(.title)"'` — issues/PRs that reference this one, including from other repos
128
+ List each source explicitly: `[primary source paths and gh commands]`. Skip this
129
+ step only if no primary source applies (rare).
126
130
 
127
131
  Only after that, begin the task below.
128
132
 
@@ -30,7 +30,12 @@ For general `gh` CLI workflows outside issue filing (PRs, workflows, API access)
30
30
  4. **Search existing issues** — don't file duplicates:
31
31
 
32
32
  ```bash
33
- gh issue list -R cyanheads/mcp-ts-core --search "your error message or keyword"
33
+ gh issue list -R cyanheads/mcp-ts-core --search "your error message or keyword" --state all
34
+
35
+ # Assess a close match before commenting — is it already linked to a fix or referenced elsewhere?
36
+ gh issue view <number> -R cyanheads/mcp-ts-core --comments
37
+ gh api 'repos/cyanheads/mcp-ts-core/issues/<number>/timeline' --paginate \
38
+ --jq '.[] | select(.event=="cross-referenced") | .source.issue | "\(.repository.full_name)#\(.number) — \(.title)"'
34
39
  ```
35
40
 
36
41
  5. **For documentation- or contract-shaped requests, audit all three doc layers first** — proposals to add reference docs, public-API conventions, attribute/event catalogs, or stability commitments often duplicate surface that already exists. Check `src/` for behavior, `docs/` for human-facing reference, and `skills/` for agent-facing reference. Skill files marked `audience: external` are the framework's public contract — treat them as authoritative when evaluating whether a documentation gap exists. Also verify the constants or types you'd reference aren't already exported from `@cyanheads/mcp-ts-core` or one of its subpaths.
@@ -273,8 +278,8 @@ ISSUE
273
278
  ## Following Up
274
279
 
275
280
  ```bash
276
- # Check issue status
277
- gh issue view <number> -R cyanheads/mcp-ts-core
281
+ # Check issue status (with comment thread)
282
+ gh issue view <number> -R cyanheads/mcp-ts-core --comments
278
283
 
279
284
  # Add context or respond to maintainer questions
280
285
  gh issue comment <number> -R cyanheads/mcp-ts-core --body "Additional context..."
@@ -35,7 +35,12 @@ gh repo view --json nameWithOwner -q '.nameWithOwner'
35
35
  2. **Search existing issues** — if a close match exists (same symptom, different tool; same tool, different symptom; closed issue that might cover the new case), add a comment on that issue instead of filing a new one — unless the symptom or scope is distinct enough to warrant separate tracking:
36
36
 
37
37
  ```bash
38
- gh issue list --search "your error message or keyword"
38
+ gh issue list --search "your error message or keyword" --state all
39
+
40
+ # Assess a close match before commenting — is it already linked to a fix or referenced elsewhere?
41
+ gh issue view <number> --comments
42
+ gh api 'repos/{owner}/{repo}/issues/<number>/timeline' --paginate \
43
+ --jq '.[] | select(.event=="cross-referenced") | .source.issue | "\(.repository.full_name)#\(.number) — \(.title)"'
39
44
  ```
40
45
 
41
46
  3. **Reproduce the issue** — confirm it's reproducible. Note the exact input, transport mode, and any relevant env vars.
@@ -280,8 +285,8 @@ When genuinely ambiguous, file against this server's repo and note that it might
280
285
  ## Following Up
281
286
 
282
287
  ```bash
283
- # View issue details
284
- gh issue view <number>
288
+ # View issue details (with comment thread)
289
+ gh issue view <number> --comments
285
290
 
286
291
  # Add context
287
292
  gh issue comment <number> --body "Additional findings..."
@@ -18,6 +18,14 @@ export const echoTool = tool('template_echo_message', {
18
18
  message: z.string().describe('The echoed message.'),
19
19
  }),
20
20
 
21
+ // Agent-facing context on the success path — the counterpart to errors[]. Merged
22
+ // into structuredContent AND mirrored into content[] automatically (no format()
23
+ // entry needed). Declare the fields here; populate via ctx.enrich(...) in the
24
+ // handler or service layer. Delete this block if your tool has no such context.
25
+ enrichment: {
26
+ characterCount: z.number().describe('Length of the echoed message.'),
27
+ },
28
+
21
29
  // Declare each domain failure mode the agent should plan around. The framework
22
30
  // types `ctx.fail(reason, …)` against the declared union. Baseline codes
23
31
  // (InternalError, ServiceUnavailable, Timeout, ValidationError,
@@ -36,6 +44,8 @@ export const echoTool = tool('template_echo_message', {
36
44
  if (input.message.trim().length === 0) {
37
45
  throw ctx.fail('empty_message', 'Message must contain at least one non-whitespace character.');
38
46
  }
47
+ // Reaches both client surfaces with no format() plumbing.
48
+ ctx.enrich({ characterCount: input.message.length });
39
49
  return { message: input.message };
40
50
  },
41
51
 
@@ -1,4 +0,0 @@
1
- {"level":40,"time":1780019885373,"env":"testing","version":"0.9.13","pid":31054,"transport":"http","requestId":"PVJSQ-5BH6C","timestamp":"2026-05-29T01:58:05.372Z","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":1780019887093,"env":"testing","version":"0.9.13","pid":31054,"transport":"http","requestId":"PVJSQ-5BH6C","timestamp":"2026-05-29T01:58:05.372Z","operation":"TransportManager.start","component":"HttpTransportSetup","sessionId":"not-a-real-session-1780019887092","msg":"Session validation failed - invalid or hijacked session"}
3
- {"level":50,"time":1780019890914,"env":"testing","version":"0.0.0-test","pid":31166,"requestId":"S2J27-VH41Q","timestamp":"2026-05-29T01:58:10.913Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"f059ed3a8dbb01fdae5ea9bea50187159ee975051d6e7ee1123e600e46f8a6e8","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"f059ed3a8dbb01fdae5ea9bea50187159ee975051d6e7ee1123e600e46f8a6e8","toolName":"scoped_echo","requestId":"S2J27-VH41Q","timestamp":"2026-05-29T01:58:10.913Z","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":1780019890921,"env":"testing","version":"0.0.0-test","pid":31166,"requestId":"16IJL-17Q6J","timestamp":"2026-05-29T01:58:10.921Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"3dc142c962ec9c4cab103e2e6bd4d09c0909beeb0773d00bb86da745a4d2a20e","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":"3dc142c962ec9c4cab103e2e6bd4d09c0909beeb0773d00bb86da745a4d2a20e","toolName":"scoped_echo","requestId":"16IJL-17Q6J","timestamp":"2026-05-29T01:58:10.921Z","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."}
@@ -1,2 +0,0 @@
1
- {"level":50,"time":1780019890914,"env":"testing","version":"0.0.0-test","pid":31166,"requestId":"S2J27-VH41Q","timestamp":"2026-05-29T01:58:10.913Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"f059ed3a8dbb01fdae5ea9bea50187159ee975051d6e7ee1123e600e46f8a6e8","toolName":"scoped_echo","tenantId":"authz-tenant","auth":{"sub":"authz-user","scopes":["tool:other:read"],"clientId":"authz-client","tenantId":"authz-tenant","token":"[REDACTED]"},"errorData":{"sessionId":"f059ed3a8dbb01fdae5ea9bea50187159ee975051d6e7ee1123e600e46f8a6e8","toolName":"scoped_echo","requestId":"S2J27-VH41Q","timestamp":"2026-05-29T01:58:10.913Z","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":1780019890921,"env":"testing","version":"0.0.0-test","pid":31166,"requestId":"16IJL-17Q6J","timestamp":"2026-05-29T01:58:10.921Z","operation":"HandleToolRequest","critical":false,"errorCode":-32005,"originalErrorType":"McpError","finalErrorType":"McpError","sessionId":"3dc142c962ec9c4cab103e2e6bd4d09c0909beeb0773d00bb86da745a4d2a20e","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":"3dc142c962ec9c4cab103e2e6bd4d09c0909beeb0773d00bb86da745a4d2a20e","toolName":"scoped_echo","requestId":"16IJL-17Q6J","timestamp":"2026-05-29T01:58:10.921Z","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."}
File without changes