@cyanheads/mcp-ts-core 0.1.8 → 0.1.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/CLAUDE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Agent Protocol
2
2
 
3
- **Package:** `@cyanheads/mcp-ts-core` · **Version:** 0.1.8
3
+ **Package:** `@cyanheads/mcp-ts-core` · **Version:** 0.1.9
4
4
  **npm:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core) · **Docker:** [ghcr.io/cyanheads/mcp-ts-core](https://ghcr.io/cyanheads/mcp-ts-core)
5
5
 
6
6
  > **Developer note:** Never assume. Read related files and docs before making changes. Read full file content for context. Never edit a file before reading it.
@@ -128,7 +128,7 @@ interface ServerHandle {
128
128
 
129
129
  ## Server Structure
130
130
 
131
- ```
131
+ ```text
132
132
  src/
133
133
  index.ts # createApp() entry point
134
134
  worker.ts # createWorkerHandler() (if using Workers)
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  <div align="center">
7
7
 
8
- [![Version](https://img.shields.io/badge/Version-0.1.8-blue.svg?style=flat-square)](./CHANGELOG.md) [![MCP Spec](https://img.shields.io/badge/MCP%20Spec-2025--11--25-8A2BE2.svg?style=flat-square)](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-11-25/changelog.mdx) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.27.1-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE)
8
+ [![Version](https://img.shields.io/badge/Version-0.1.9-blue.svg?style=flat-square)](./CHANGELOG.md) [![MCP Spec](https://img.shields.io/badge/MCP%20Spec-2025--11--25-8A2BE2.svg?style=flat-square)](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-11-25/changelog.mdx) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.27.1-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE)
9
9
 
10
10
  [![TypeScript](https://img.shields.io/badge/TypeScript-^5.9.3-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.3.2-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
@@ -107,7 +107,7 @@ It also works on Cloudflare Workers with `createWorkerHandler()` — same defini
107
107
 
108
108
  ## Server structure
109
109
 
110
- ```
110
+ ```text
111
111
  my-mcp-server/
112
112
  src/
113
113
  index.ts # createApp() entry point
package/biome.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://biomejs.dev/schemas/2.4.7/schema.json",
2
+ "$schema": "https://biomejs.dev/schemas/2.4.8/schema.json",
3
3
  "vcs": {
4
4
  "enabled": true,
5
5
  "clientKind": "git",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyanheads/mcp-ts-core",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "mcpName": "io.github.cyanheads/mcp-ts-core",
5
5
  "description": "TypeScript framework for building Model Context Protocol (MCP) servers. Declarative tool/resource/prompt definitions, pluggable auth, multi-backend storage, OpenTelemetry observability, and support for both local (stdio/HTTP) and edge (Cloudflare Workers) runtimes.",
6
6
  "main": "dist/core/app.js",
package/scripts/tree.ts CHANGED
@@ -241,7 +241,7 @@ function buildOutputContent(projectName: string, treeContent: string, maxDepth:
241
241
  const timestamp = new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '');
242
242
  const header = `# ${projectName} - Directory Structure\n\nGenerated on: ${timestamp}\n`;
243
243
  const depthInfo = maxDepth !== Infinity ? `\n_Depth limited to ${maxDepth} levels_\n\n` : '\n';
244
- const treeBlock = `\`\`\`\n${projectName}/\n${treeContent}\`\`\`\n`;
244
+ const treeBlock = `\`\`\`text\n${projectName}/\n${treeContent}\`\`\`\n`;
245
245
  const footer = `\n_Note: This tree excludes files and directories matched by .gitignore and default patterns._\n`;
246
246
  return header + depthInfo + treeBlock + footer;
247
247
  }
package/skills/README.md CHANGED
@@ -14,7 +14,7 @@ Skills flow through three locations. Each tier has a distinct role:
14
14
 
15
15
  ### Flow
16
16
 
17
- ```
17
+ ```text
18
18
  npm publish init CLI agent sync
19
19
  [package skills/] ──────────> [project skills/] ──────────> [.claude/skills/]
20
20
 
@@ -19,6 +19,7 @@ The build uses `tsconfig.build.json` (not `tsconfig.json`) with `rootDir: ./src`
19
19
 
20
20
  1. **Create the entry point** source file under `src/` (e.g., `src/utils/new-util.ts`)
21
21
  2. **Add the subpath** to `package.json` `exports`, mirroring the source path:
22
+
22
23
  ```jsonc
23
24
  // source: src/utils/new-util.ts → dist: dist/utils/new-util.js
24
25
  "./newutil": {
@@ -26,9 +27,11 @@ The build uses `tsconfig.build.json` (not `tsconfig.json`) with `rootDir: ./src`
26
27
  "import": "./dist/utils/new-util.js"
27
28
  }
28
29
  ```
30
+
29
31
  3. **Update the exports catalog** in `CLAUDE.md` — add a row to the table
30
32
  4. **Build** with `bun run build` to generate `dist/` output
31
33
  5. **Verify the export** by inspecting the compiled output directly:
34
+
32
35
  ```bash
33
36
  # Confirm the compiled file exists at the expected dist path
34
37
  ls dist/utils/new-util.js
@@ -36,6 +39,7 @@ The build uses `tsconfig.build.json` (not `tsconfig.json`) with `rootDir: ./src`
36
39
  # Confirm the declared exports resolve to real files
37
40
  bun -e "import('./dist/utils/new-util.js').then(m => console.log(Object.keys(m)))"
38
41
  ```
42
+
39
43
  6. **Run `bun run devcheck`** to verify
40
44
 
41
45
  ## Naming conventions
@@ -49,6 +49,7 @@ Provider file location and naming differ by domain:
49
49
  2. **Create the provider file** following the file convention for its domain (see above).
50
50
  3. **Implement the interface** — all methods must be implemented.
51
51
  4. **Lazy-load dependencies** if Tier 3:
52
+
52
53
  ```typescript
53
54
  let _client: SomeClient | undefined;
54
55
  async function getClient(): Promise<SomeClient> {
@@ -59,6 +60,7 @@ Provider file location and naming differ by domain:
59
60
  return _client;
60
61
  }
61
62
  ```
63
+
62
64
  5. **Register the provider** — the registration point differs by domain:
63
65
 
64
66
  - **Storage** — add a `case` to the `switch` in `src/storage/core/storageFactory.ts`
@@ -79,10 +81,12 @@ Provider file location and naming differ by domain:
79
81
  6. **Update the Worker-compatible provider list** if the new storage provider runs in
80
82
  Cloudflare Workers. The list is an inline array in `storageFactory.ts` at the
81
83
  `isServerless()` guard:
84
+
82
85
  ```typescript
83
86
  // src/storage/core/storageFactory.ts ~line 112
84
87
  !['in-memory', 'cloudflare-r2', 'cloudflare-kv', 'cloudflare-d1'].includes(providerType)
85
88
  ```
89
+
86
90
  Add the new provider string to this array. Non-storage providers have no equivalent
87
91
  gate.
88
92
 
@@ -50,6 +50,7 @@ handler: async (input, ctx) => {
50
50
  **Signature:** `checkScopes(ctx: Context, requiredScopes: string[]): void`
51
51
 
52
52
  **Throws:**
53
+
53
54
  - `McpError(Forbidden)` — auth is active and one or more required scopes are missing
54
55
  - `McpError(Unauthorized)` — auth is enabled but no auth context exists on the request
55
56
  - No-ops when `MCP_AUTH_MODE=none`
@@ -56,7 +56,7 @@ Utility exports from `@cyanheads/mcp-ts-core/utils`. Utilities with complex APIs
56
56
 
57
57
  | Export | API | Notes |
58
58
  |:-------|:----|:------|
59
- | `schedulerService` | `.schedule(id, schedule, taskFunction, description) -> Promise<Job>` `.start(id) -> void` `.stop(id) -> void` `.remove(id) -> void` `.listJobs() -> Job[]` | **Async** `schedule()` — Tier 3 peer: `node-cron`. **Node-only** (throws `ConfigurationError` in Workers). Jobs start in stopped state; call `start(id)` to activate. Skips overlapping executions. Each tick gets fresh `RequestContext`. `Job: { id, schedule, description, isRunning, task }`. `taskFunction: (context: RequestContext) => void | Promise<void>`. |
59
+ | `schedulerService` | `.schedule(id, schedule, taskFunction, description) -> Promise<Job>` `.start(id) -> void` `.stop(id) -> void` `.remove(id) -> void` `.listJobs() -> Job[]` | **Async** `schedule()` — Tier 3 peer: `node-cron`. **Node-only** (throws `ConfigurationError` in Workers). Jobs start in stopped state; call `start(id)` to activate. Skips overlapping executions. Each tick gets fresh `RequestContext`. `Job: { id, schedule, description, isRunning, task }`. `taskFunction: (context: RequestContext) => void` \| `Promise<void>`. |
60
60
 
61
61
  ---
62
62
 
@@ -24,7 +24,7 @@ import { markdown, MarkdownBuilder, diffFormatter, tableFormatter, treeFormatter
24
24
  | `codeBlock` | `(content, language?) -> this` | Fenced block; `language` defaults to `''` |
25
25
  | `inlineCode` | `(code) -> this` | Backtick-wrapped; no trailing newline |
26
26
  | `paragraph` | `(text) -> this` | Text + `\n\n` |
27
- | `blockquote` | `(text) -> this` | Each line prefixed with `> ` |
27
+ | `blockquote` | `(text) -> this` | Each line prefixed with `>` + space |
28
28
  | `hr` | `() -> this` | `---` |
29
29
  | `link` | `(text, url) -> this` | `[text](url)`; no trailing newline |
30
30
  | `table` | `(headers, rows) -> this` | GFM table; no-ops if headers or rows empty |
@@ -150,7 +150,7 @@ interface TableFormatterOptions {
150
150
  | Style | Description |
151
151
  |:------|:------------|
152
152
  | `markdown` | GFM pipes with alignment indicators in separator row |
153
- | `ascii` | `+`/`-`/`|` box drawing |
153
+ | `ascii` | `+`/`-`/`\|` box drawing |
154
154
  | `grid` | Unicode box drawing (`┌─┬─┐` / `│` / `├─┼─┤` / `└─┴─┘`) |
155
155
  | `compact` | Space-separated, no borders |
156
156
 
@@ -211,7 +211,7 @@ interface TreeFormatterOptions {
211
211
  | Style | Connectors |
212
212
  |:------|:-----------|
213
213
  | `unicode` | `├──` / `└──` / `│` |
214
- | `ascii` | `+--` / `\--` / `|` |
214
+ | `ascii` | `+--` / `\--` / `\|` |
215
215
  | `compact` | Indented list, no connectors |
216
216
 
217
217
  ### Usage
@@ -7,6 +7,7 @@ import { yamlParser, xmlParser, csvParser, jsonParser, pdfParser, dateParser, fr
7
7
  All parsers are **Tier 3** — lazy-load their peer dependency on first call. All methods are **async** unless noted.
8
8
 
9
9
  **Common behavior:**
10
+
10
11
  - Singleton instances exported alongside classes
11
12
  - `<think>...</think>` blocks at the start of input are automatically stripped and logged at `debug` level (except `dateParser` and `pdfParser`)
12
13
  - All `context?: RequestContext` parameters are optional (synthetic context created if omitted)
@@ -240,6 +240,7 @@ For each resource:
240
240
  ### 6. Design Prompts (if needed)
241
241
 
242
242
  Optional. Use when the server has recurring interaction patterns worth structuring:
243
+
243
244
  - Analysis frameworks, report templates, multi-step workflows
244
245
 
245
246
  Skip for purely data/action-oriented servers.
@@ -34,6 +34,7 @@ If these aren't met, address them first.
34
34
  Read all tool, resource, and prompt definitions. Build a mental model of what the server actually does — names, descriptions, input/output shapes, auth scopes. This inventory drives every document below.
35
35
 
36
36
  Read:
37
+
37
38
  - `src/index.ts` (what's registered in `createApp()`)
38
39
  - All files in `src/mcp-server/tools/definitions/`
39
40
  - All files in `src/mcp-server/resources/definitions/`
@@ -27,6 +27,7 @@ The scaffolded template includes a `## First Session` section with one-time onbo
27
27
  Check the Patterns section for generic template examples (e.g., `searchItems`, `itemData`, `reviewCode`). If still present, replace them with actual tool/resource/prompt definitions from the server — or the most representative ones if there are many. If the examples already reflect real definitions, verify they're still accurate.
28
28
 
29
29
  Pick examples that:
30
+
30
31
  - Show the most common or important capability
31
32
  - Demonstrate any non-trivial patterns the server uses (e.g., `ctx.state`, `ctx.elicit`, `task: true`, services)
32
33
  - Include a handler with real business logic, not just passthrough
@@ -82,7 +82,7 @@ bun run build
82
82
 
83
83
  ### 9. Commit
84
84
 
85
- ```
85
+ ```text
86
86
  chore: release v{{VERSION}}
87
87
  ```
88
88
 
@@ -96,7 +96,7 @@ git tag -a v{{VERSION}} -m "v{{VERSION}}: <one-line summary of key changes>"
96
96
 
97
97
  The tag message should capture the most important change(s) — not the full changelog, just enough to orient someone browsing tags. Examples:
98
98
 
99
- ```
99
+ ```text
100
100
  v0.2.0: Cloudflare Workers support, task tools, Graph service
101
101
  v0.1.7: OTel instrumentation refactor, lighter semconv
102
102
  v0.1.6: Error factory functions, auto-classification patterns
@@ -32,7 +32,7 @@ Read that file once per session. It contains the exports catalog, tool/resource/
32
32
 
33
33
  What `init` actually creates:
34
34
 
35
- ```
35
+ ```text
36
36
  CLAUDE.md # Agent protocol (project-specific)
37
37
  AGENTS.md # Same content — delete whichever you don't use
38
38
  skills/ # Project skills (source of truth)
@@ -49,7 +49,7 @@ src/
49
49
 
50
50
  Add these as needed:
51
51
 
52
- ```
52
+ ```text
53
53
  src/
54
54
  worker.ts # createWorkerHandler() — only for Cloudflare Workers
55
55
  config/
@@ -156,7 +156,7 @@ Plain `Error` is fine for most cases. Use factories when the error code matters.
156
156
 
157
157
  ## Structure
158
158
 
159
- ```
159
+ ```text
160
160
  src/
161
161
  index.ts # createApp() entry point
162
162
  config/
@@ -156,7 +156,7 @@ Plain `Error` is fine for most cases. Use factories when the error code matters.
156
156
 
157
157
  ## Structure
158
158
 
159
- ```
159
+ ```text
160
160
  src/
161
161
  index.ts # createApp() entry point
162
162
  config/