silkweave 1.3.1

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.
@@ -0,0 +1,36 @@
1
+
2
+ 
3
+ > silkweave@1.3.0 build /Users/atomic/projects/ai/silkweave/packages/silkweave
4
+ > tsup
5
+
6
+ CLI Building entry: src/auth.ts, src/cli.ts, src/core.ts, src/fastify.ts, src/logger.ts, src/mcp.ts, src/vercel.ts
7
+ CLI Using tsconfig: tsconfig.json
8
+ CLI tsup v8.5.1
9
+ CLI Using tsup config: /Users/atomic/projects/ai/silkweave/packages/silkweave/tsup.config.ts
10
+ CLI Target: es2022
11
+ CLI Cleaning output folder
12
+ ESM Build start
13
+ ESM build/cli.js 77.00 B
14
+ ESM build/core.js 80.00 B
15
+ ESM build/vercel.js 86.00 B
16
+ ESM build/mcp.js 77.00 B
17
+ ESM build/auth.js 80.00 B
18
+ ESM build/fastify.js 89.00 B
19
+ ESM build/logger.js 86.00 B
20
+ ESM build/cli.js.map 131.00 B
21
+ ESM build/core.js.map 133.00 B
22
+ ESM build/mcp.js.map 131.00 B
23
+ ESM build/vercel.js.map 137.00 B
24
+ ESM build/fastify.js.map 139.00 B
25
+ ESM build/auth.js.map 133.00 B
26
+ ESM build/logger.js.map 137.00 B
27
+ ESM ⚡️ Build success in 6ms
28
+ DTS Build start
29
+ DTS ⚡️ Build success in 592ms
30
+ DTS build/auth.d.ts 194.00 B
31
+ DTS build/cli.d.ts 32.00 B
32
+ DTS build/core.d.ts 33.00 B
33
+ DTS build/fastify.d.ts 36.00 B
34
+ DTS build/logger.d.ts 35.00 B
35
+ DTS build/mcp.d.ts 32.00 B
36
+ DTS build/vercel.d.ts 35.00 B
@@ -0,0 +1,44 @@
1
+
2
+ 
3
+ > silkweave@1.3.0 prepack /Users/atomic/projects/ai/silkweave/packages/silkweave
4
+ > pnpm clean && pnpm build
5
+
6
+
7
+ > silkweave@1.3.0 clean /Users/atomic/projects/ai/silkweave/packages/silkweave
8
+ > rimraf build
9
+
10
+
11
+ > silkweave@1.3.0 build /Users/atomic/projects/ai/silkweave/packages/silkweave
12
+ > tsup
13
+
14
+ CLI Building entry: src/auth.ts, src/cli.ts, src/core.ts, src/fastify.ts, src/logger.ts, src/mcp.ts, src/vercel.ts
15
+ CLI Using tsconfig: tsconfig.json
16
+ CLI tsup v8.5.1
17
+ CLI Using tsup config: /Users/atomic/projects/ai/silkweave/packages/silkweave/tsup.config.ts
18
+ CLI Target: es2022
19
+ CLI Cleaning output folder
20
+ ESM Build start
21
+ ESM build/core.js 80.00 B
22
+ ESM build/fastify.js 89.00 B
23
+ ESM build/logger.js 86.00 B
24
+ ESM build/auth.js 80.00 B
25
+ ESM build/vercel.js 86.00 B
26
+ ESM build/cli.js 77.00 B
27
+ ESM build/mcp.js 77.00 B
28
+ ESM build/fastify.js.map 139.00 B
29
+ ESM build/logger.js.map 137.00 B
30
+ ESM build/core.js.map 133.00 B
31
+ ESM build/cli.js.map 131.00 B
32
+ ESM build/auth.js.map 133.00 B
33
+ ESM build/mcp.js.map 131.00 B
34
+ ESM build/vercel.js.map 137.00 B
35
+ ESM ⚡️ Build success in 7ms
36
+ DTS Build start
37
+ DTS ⚡️ Build success in 598ms
38
+ DTS build/auth.d.ts 194.00 B
39
+ DTS build/cli.d.ts 32.00 B
40
+ DTS build/core.d.ts 33.00 B
41
+ DTS build/fastify.d.ts 36.00 B
42
+ DTS build/logger.d.ts 35.00 B
43
+ DTS build/mcp.d.ts 32.00 B
44
+ DTS build/vercel.d.ts 35.00 B
package/README.md ADDED
@@ -0,0 +1,772 @@
1
+ # Silkweave
2
+
3
+ **Write your logic once. Run it everywhere.**
4
+
5
+ Silkweave is a TypeScript toolkit that lets you define application logic as portable **Actions** and instantly expose them through any combination of transports — MCP servers (stdio and HTTP), REST APIs with auto-generated OpenAPI docs, and fully-featured CLIs. No glue code required.
6
+
7
+ ```
8
+ ┌─────────────────────┐
9
+ │ Action │
10
+ │ name + zod schema │
11
+ │ + async run() │
12
+ └──────────┬──────────┘
13
+
14
+ ┌──────────────┬───────┼───────┬──────────────┐
15
+ │ │ │ │ │
16
+ ┌──────▼──────┐ ┌─────▼─────┐ │ ┌─────▼──────┐ ┌────▼─────┐
17
+ │ MCP (stdio) │ │ Fastify │ │ │ CLI │ │ Vercel │
18
+ │ MCP (http) │ │ REST API │ │ │ commander │ │serverless│
19
+ │ │ │ + Swagger │ │ │ + clack │ │ MCP │
20
+ └─────────────┘ └───────────┘ │ └────────────┘ └──────────┘
21
+
22
+ ```
23
+
24
+ ---
25
+
26
+ ## Table of Contents
27
+
28
+ - [Why Silkweave](#why-silkweave)
29
+ - [Packages](#packages)
30
+ - [Quick Start](#quick-start)
31
+ - [Core Concepts](#core-concepts)
32
+ - [Actions](#actions)
33
+ - [Adapters](#adapters)
34
+ - [The Silkweave Builder](#the-silkweave-builder)
35
+ - [Adapters in Depth](#adapters-in-depth)
36
+ - [MCP Stdio](#mcp-stdio)
37
+ - [MCP Streamable HTTP](#mcp-streamable-http)
38
+ - [Fastify REST API](#fastify-rest-api)
39
+ - [CLI](#cli)
40
+ - [Vercel Serverless](#vercel-serverless)
41
+ - [Logging and Progress](#logging-and-progress)
42
+ - [Advanced Patterns](#advanced-patterns)
43
+ - [Multiple Adapters Simultaneously](#multiple-adapters-simultaneously)
44
+ - [CLI Arguments vs Options](#cli-arguments-vs-options)
45
+ - [Complex Input Types](#complex-input-types)
46
+ - [MCP Client Configuration](#mcp-client-configuration)
47
+ - [API Reference](#api-reference)
48
+ - [Development](#development)
49
+
50
+ ---
51
+
52
+ ## Why Silkweave
53
+
54
+ Building an MCP server usually means wiring up transports, registering tools, serializing responses, and handling errors — for every single tool. If you also want a CLI or REST API for the same logic, you're writing it all again.
55
+
56
+ Silkweave eliminates this duplication. You define an **Action** — a name, a Zod schema, and an async function — and Silkweave handles the rest:
57
+
58
+ - **MCP adapters** register your actions as MCP tools with proper notifications, progress reporting, and error handling
59
+ - **Fastify adapter** generates a REST API with full OpenAPI/Swagger documentation derived from your Zod schemas
60
+ - **CLI adapter** builds a complete command-line interface with argument parsing, option flags, and beautiful terminal output via clack
61
+
62
+ Your action doesn't know or care which transport is running it.
63
+
64
+ ---
65
+
66
+ ## Packages
67
+
68
+ Silkweave is organized as a monorepo with modular packages. Install only what you need:
69
+
70
+ | Package | npm | Description |
71
+ |---------|-----|-------------|
72
+ | `@silkweave/core` | [![npm](https://img.shields.io/npm/v/@silkweave/core)](https://www.npmjs.com/package/@silkweave/core) | Core library — actions, adapters, builder, context, logger, utilities |
73
+ | `@silkweave/mcp` | [![npm](https://img.shields.io/npm/v/@silkweave/mcp)](https://www.npmjs.com/package/@silkweave/mcp) | MCP adapters — stdio, streamable HTTP, CLI proxy |
74
+ | `@silkweave/cli` | [![npm](https://img.shields.io/npm/v/@silkweave/cli)](https://www.npmjs.com/package/@silkweave/cli) | CLI adapter — commander + clack terminal UI |
75
+ | `@silkweave/fastify` | [![npm](https://img.shields.io/npm/v/@silkweave/fastify)](https://www.npmjs.com/package/@silkweave/fastify) | Fastify REST adapter — auto-generated OpenAPI/Swagger docs |
76
+ | `@silkweave/vercel` | [![npm](https://img.shields.io/npm/v/@silkweave/vercel)](https://www.npmjs.com/package/@silkweave/vercel) | Vercel serverless adapter — stateless MCP over Streamable HTTP |
77
+ | `@silkweave/logger` | [![npm](https://img.shields.io/npm/v/@silkweave/logger)](https://www.npmjs.com/package/@silkweave/logger) | Logging utilities — pino, clack, and MCP notification support |
78
+
79
+ **`@silkweave/core`** is always required. Then add the adapter packages for the transports you need:
80
+
81
+ ```bash
82
+ # MCP server (stdio or HTTP)
83
+ pnpm add @silkweave/core @silkweave/mcp
84
+
85
+ # REST API with Swagger
86
+ pnpm add @silkweave/core @silkweave/fastify
87
+
88
+ # CLI tool
89
+ pnpm add @silkweave/core @silkweave/cli
90
+
91
+ # Vercel serverless MCP
92
+ pnpm add @silkweave/core @silkweave/vercel
93
+
94
+ # All of the above
95
+ pnpm add @silkweave/core @silkweave/mcp @silkweave/cli @silkweave/fastify @silkweave/vercel
96
+ ```
97
+
98
+ ---
99
+
100
+ ## Quick Start
101
+
102
+ ```bash
103
+ pnpm add @silkweave/core @silkweave/mcp
104
+ ```
105
+
106
+ Create an action:
107
+
108
+ ```typescript
109
+ // actions/greet.ts
110
+ import z from 'zod'
111
+ import { createAction } from '@silkweave/core'
112
+
113
+ export const GreetAction = createAction({
114
+ name: 'greet',
115
+ description: 'Greet someone by name',
116
+ input: z.object({
117
+ name: z.string().describe('The name to greet'),
118
+ enthusiastic: z.boolean().describe('Add excitement').default(false)
119
+ }),
120
+ run: async ({ name, enthusiastic }, { logger }) => {
121
+ const greeting = enthusiastic ? `HELLO, ${name.toUpperCase()}!!!` : `Hello, ${name}.`
122
+ logger.info(greeting)
123
+ return { greeting }
124
+ }
125
+ })
126
+ ```
127
+
128
+ Serve it as an MCP server:
129
+
130
+ ```typescript
131
+ // server.ts
132
+ import { silkweave } from '@silkweave/core'
133
+ import { stdio } from '@silkweave/mcp'
134
+ import { GreetAction } from './actions/greet.js'
135
+
136
+ await silkweave({ name: 'my-server', description: 'My MCP Server', version: '1.0.0' })
137
+ .adapter(stdio())
138
+ .action(GreetAction)
139
+ .start()
140
+ ```
141
+
142
+ That's it. Your action is now an MCP tool called `Greet` that any MCP client (Claude Desktop, Cursor, Claude Code, etc.) can discover and invoke.
143
+
144
+ ---
145
+
146
+ ## Core Concepts
147
+
148
+ ### Actions
149
+
150
+ An Action is the fundamental unit of logic in Silkweave. It is completely transport-agnostic.
151
+
152
+ ```typescript
153
+ import z from 'zod'
154
+ import { createAction } from '@silkweave/core'
155
+
156
+ export const SearchAction = createAction({
157
+ name: 'search',
158
+ description: 'Search documents by query',
159
+ input: z.object({
160
+ query: z.string().describe('Search query'),
161
+ limit: z.number().int().min(1).max(100).describe('Max results').default(10),
162
+ includeArchived: z.boolean().describe('Include archived documents').default(false)
163
+ }),
164
+ run: async ({ query, limit, includeArchived }, { logger }) => {
165
+ logger.info(`Searching for: ${query}`)
166
+ // ... your logic here
167
+ const results = await performSearch(query, { limit, includeArchived })
168
+ return { results, count: results.length }
169
+ }
170
+ })
171
+ ```
172
+
173
+ **`createAction`** accepts an object with:
174
+
175
+ | Field | Type | Description |
176
+ |-------|------|-------------|
177
+ | `name` | `string` | Unique identifier. Adapters transform this automatically (PascalCase for MCP tools, kebab-case for CLI commands, as-is for REST routes). |
178
+ | `description` | `string` | Human-readable description. Shown in MCP tool listings, CLI help, and Swagger docs. |
179
+ | `input` | `z.ZodObject` | A Zod object schema defining the input. `.describe()` on each field provides per-field documentation across all adapters. |
180
+ | `args` | `(keyof I)[]` | *(Optional)* Fields to expose as positional CLI arguments instead of `--options`. Only relevant for the CLI adapter. |
181
+ | `run` | `(input, context) => Promise<O>` | The implementation. Receives validated input and an `SilkweaveContext` with a `logger`. Returns any object — adapters handle serialization. |
182
+
183
+ ### Adapters
184
+
185
+ Adapters are the bridge between your actions and the outside world. Each adapter is a factory function that takes configuration and returns a generator compatible with the Silkweave builder.
186
+
187
+ ```typescript
188
+ import { stdio, http } from '@silkweave/mcp'
189
+ import { fastify } from '@silkweave/fastify'
190
+ import { cli } from '@silkweave/cli'
191
+
192
+ // No config needed
193
+ stdio()
194
+
195
+ // Host and port required
196
+ http({ host: 'localhost', port: 8080 })
197
+
198
+ // Full Fastify options pass-through
199
+ fastify({ host: 'localhost', port: 8080, logger: true })
200
+
201
+ // No config needed
202
+ cli()
203
+ ```
204
+
205
+ The adapter lifecycle:
206
+
207
+ 1. **Factory** — `stdio()` / `http({ ... })` / etc. captures configuration
208
+ 2. **Generator** — Silkweave calls the factory result with `{ name, description, version }` to produce an `Adapter`
209
+ 3. **Start** — `adapter.start(actions)` registers all actions and begins listening
210
+ 4. **Stop** — `adapter.stop()` tears down gracefully
211
+
212
+ ### The Silkweave Builder
213
+
214
+ The builder provides a fluent, chainable API:
215
+
216
+ ```typescript
217
+ import { silkweave } from '@silkweave/core'
218
+ import { stdio, http } from '@silkweave/mcp'
219
+
220
+ const app = silkweave({
221
+ name: 'my-toolkit',
222
+ description: 'A collection of useful tools',
223
+ version: '2.1.0'
224
+ })
225
+
226
+ app
227
+ .adapter(stdio()) // Add an adapter
228
+ .adapter(http({ ... })) // Add another — they run in parallel
229
+ .action(SearchAction) // Mount an action
230
+ .action(GreetAction) // Mount another
231
+
232
+ await app.start() // Start all adapters concurrently
233
+ ```
234
+
235
+ `.adapter()` and `.action()` return the same instance, so you can chain freely. `.start()` launches all adapters in parallel via `Promise.all`.
236
+
237
+ ---
238
+
239
+ ## Adapters in Depth
240
+
241
+ ### MCP Stdio
242
+
243
+ The standard MCP transport for local tool servers. Communicates over stdin/stdout using the MCP protocol.
244
+
245
+ ```typescript
246
+ import { silkweave } from '@silkweave/core'
247
+ import { stdio } from '@silkweave/mcp'
248
+
249
+ await silkweave({ name: 'my-tools', description: 'My Tools', version: '1.0.0' })
250
+ .adapter(stdio())
251
+ .action(MyAction)
252
+ .start()
253
+ ```
254
+
255
+ **How actions become MCP tools:**
256
+
257
+ | Action property | MCP tool property |
258
+ |-----------------|-------------------|
259
+ | `name: 'searchDocs'` | Tool name: `SearchDocs` (PascalCase) |
260
+ | `description` | Tool description |
261
+ | `input` (Zod schema) | `inputSchema` (JSON Schema via Zod) |
262
+ | Return value | `TextContent` JSON response |
263
+ | Thrown errors | Structured error response with name, message, and stack |
264
+
265
+ MCP logging notifications are wired automatically — `logger.info("message")` in your action sends a `notifications/message` to the MCP client. Progress reporting works via `logger.progress()` when the client provides a progress token.
266
+
267
+ **Claude Desktop / Claude Code configuration:**
268
+
269
+ ```json
270
+ {
271
+ "mcpServers": {
272
+ "my-tools": {
273
+ "command": "node",
274
+ "args": ["path/to/server.js"]
275
+ }
276
+ }
277
+ }
278
+ ```
279
+
280
+ ### MCP Streamable HTTP
281
+
282
+ A session-based MCP transport over HTTP with Server-Sent Events (SSE) for streaming. Supports multiple concurrent sessions, resumability via `Last-Event-ID`, and session termination.
283
+
284
+ ```typescript
285
+ import { silkweave } from '@silkweave/core'
286
+ import { http } from '@silkweave/mcp'
287
+
288
+ await silkweave({ name: 'my-tools', description: 'My Tools', version: '1.0.0' })
289
+ .adapter(http({
290
+ host: 'localhost',
291
+ port: 8080,
292
+ allowedHosts: ['localhost']
293
+ }))
294
+ .action(MyAction)
295
+ .start()
296
+ ```
297
+
298
+ **Endpoints exposed:**
299
+
300
+ | Method | Path | Purpose |
301
+ |--------|------|---------|
302
+ | `POST` | `/mcp` | Initialize session or invoke tools |
303
+ | `GET` | `/mcp` | Establish SSE stream for a session |
304
+ | `DELETE` | `/mcp` | Terminate a session |
305
+
306
+ The adapter manages session lifecycle automatically — each new `initialize` request creates a new `StreamableHTTPServerTransport` with a UUID session ID. Sessions are cleaned up when the transport closes.
307
+
308
+ CORS is configured out of the box, exposing MCP-specific headers (`Mcp-Session-Id`, `Mcp-Protocol-Version`, `Last-Event-Id`).
309
+
310
+ **`HttpAdapterOptions`:**
311
+
312
+ | Option | Type | Description |
313
+ |--------|------|-------------|
314
+ | `host` | `string` | Bind address |
315
+ | `port` | `number` | Listen port |
316
+ | `allowedHosts` | `string[]` | Hosts allowed to connect (passed to Express MCP app) |
317
+
318
+ ### Fastify REST API
319
+
320
+ Turns your actions into a REST API with auto-generated OpenAPI documentation and an interactive Swagger UI powered by Scalar.
321
+
322
+ ```typescript
323
+ import { silkweave } from '@silkweave/core'
324
+ import { fastify } from '@silkweave/fastify'
325
+
326
+ await silkweave({ name: 'my-api', description: 'My REST API', version: '1.0.0' })
327
+ .adapter(fastify({
328
+ host: 'localhost',
329
+ port: 8080,
330
+ logger: true
331
+ }))
332
+ .action(SearchAction)
333
+ .action(GreetAction)
334
+ .start()
335
+ ```
336
+
337
+ **Route mapping:**
338
+
339
+ Each action becomes a `POST /{action.name}` route. The Zod schema is converted to JSON Schema for request body validation and OpenAPI documentation.
340
+
341
+ | Action | Route | Body |
342
+ |--------|-------|------|
343
+ | `name: 'search'` | `POST /search` | `{ "query": "...", "limit": 10 }` |
344
+ | `name: 'greet'` | `POST /greet` | `{ "name": "World" }` |
345
+
346
+ Visit `http://localhost:8080/` for the interactive Scalar API reference with try-it-out functionality.
347
+
348
+ **`FastifyAdapterOptions`:**
349
+
350
+ Extends Fastify's native `FastifyHttpOptions`, so any Fastify config is supported:
351
+
352
+ ```typescript
353
+ fastify({
354
+ host: 'localhost',
355
+ port: 8080,
356
+ logger: {
357
+ level: 'debug',
358
+ transport: { target: 'pino-pretty' }
359
+ },
360
+ connectionTimeout: 30000
361
+ })
362
+ ```
363
+
364
+ ### CLI
365
+
366
+ Transforms your actions into a complete command-line application with help text, option parsing, and styled terminal output via clack.
367
+
368
+ ```typescript
369
+ import { silkweave } from '@silkweave/core'
370
+ import { cli } from '@silkweave/cli'
371
+
372
+ await silkweave({ name: 'mytool', description: 'My CLI Tool', version: '1.0.0' })
373
+ .adapter(cli())
374
+ .action(GreetAction)
375
+ .action(SearchAction)
376
+ .start()
377
+ ```
378
+
379
+ **How Zod types map to CLI options:**
380
+
381
+ | Zod Type | CLI Representation |
382
+ |----------|-------------------|
383
+ | `z.string()` | `--option-name <string>` |
384
+ | `z.number()` | `--option-name <number>` |
385
+ | `z.boolean()` | `--option-name` / `--no-option-name` |
386
+ | `z.record()` | `--option-name <json>` |
387
+ | `.default(value)` | Sets the default in help text |
388
+ | `.describe('...')` | Sets the option description |
389
+
390
+ Field names are automatically converted to `kebab-case` for flags. Action names become `kebab-case` subcommands.
391
+
392
+ **Example output:**
393
+
394
+ ```
395
+ $ mytool greet --name "World" --enthusiastic
396
+ ◇ mytool - greet
397
+ ℹ HELLO, WORLD!!!
398
+ ```
399
+
400
+ ### Vercel Serverless
401
+
402
+ Deploy your actions as a stateless MCP server on Vercel. Each request creates a fresh server instance — no sessions, no persistent connections, fully compatible with serverless constraints.
403
+
404
+ ```typescript
405
+ // api/mcp.ts (Vercel function)
406
+ import { silkweave } from '@silkweave/core'
407
+ import { vercel } from '@silkweave/vercel'
408
+ import { SearchAction } from '../actions/search.js'
409
+
410
+ const { adapter, handler } = vercel()
411
+
412
+ await silkweave({ name: 'my-tools', description: 'My Tools', version: '1.0.0' })
413
+ .adapter(adapter)
414
+ .action(SearchAction)
415
+ .start()
416
+
417
+ export default { fetch: handler }
418
+ ```
419
+
420
+ The `vercel()` function returns a compound object — `adapter` wires into the Silkweave builder, while `handler`/`GET`/`POST`/`DELETE` are the request handler for your Vercel route.
421
+
422
+ **For Next.js App Router** (`app/api/mcp/route.ts`):
423
+
424
+ ```typescript
425
+ const { adapter, GET, POST, DELETE } = vercel()
426
+
427
+ await silkweave({ name: 'my-tools', description: 'My Tools', version: '1.0.0' })
428
+ .adapter(adapter)
429
+ .action(SearchAction)
430
+ .start()
431
+
432
+ export { GET, POST, DELETE }
433
+ ```
434
+
435
+ **How it works:**
436
+
437
+ - Uses `WebStandardStreamableHTTPServerTransport` from the MCP SDK in stateless mode (`sessionIdGenerator: undefined`)
438
+ - Each request creates a fresh `McpServer` + transport, registers tools, handles the request, and returns a Web Standard `Response`
439
+ - Logging goes to `process.stderr` (Vercel log drain) and MCP client notifications
440
+ - No CORS handling — use Next.js middleware or `vercel.json` headers
441
+
442
+ **`VercelAdapterOptions`:**
443
+
444
+ | Option | Type | Default | Description |
445
+ |--------|------|---------|-------------|
446
+ | `enableJsonResponse` | `boolean` | `false` | Return JSON instead of SSE streams |
447
+
448
+ ---
449
+
450
+ ## Logging and Progress
451
+
452
+ Every action receives a `context.logger` with eight severity levels plus a progress reporter:
453
+
454
+ ```typescript
455
+ run: async (input, { logger }) => {
456
+ logger.debug('Starting operation...')
457
+ logger.info('Processing item')
458
+ logger.warning('Rate limit approaching')
459
+ logger.error('Failed to connect')
460
+
461
+ // Progress reporting (renders as MCP progress notifications,
462
+ // Fastify trace logs, or console output depending on adapter)
463
+ for (let i = 1; i <= total; i++) {
464
+ logger.progress({
465
+ progress: i,
466
+ total: total,
467
+ message: `Processing item ${i} of ${total}`
468
+ })
469
+ await processItem(i)
470
+ }
471
+
472
+ return { processed: total }
473
+ }
474
+ ```
475
+
476
+ **How logging is handled per adapter:**
477
+
478
+ | Level | MCP (stdio/http) | Fastify | CLI |
479
+ |-------|-------------------|---------|-----|
480
+ | `debug` | `notifications/message` | `logger.debug()` | `log.message()` |
481
+ | `info` | `notifications/message` | `logger.info()` | `log.info()` |
482
+ | `warning` | `notifications/message` | `logger.warn()` | `log.warn()` |
483
+ | `error` | `notifications/message` | `logger.error()` | `log.error()` |
484
+ | `critical` | `notifications/message` | `logger.fatal()` | `log.error()` |
485
+ | `progress` | `notifications/progress` | `logger.trace()` | `console.info()` |
486
+
487
+ ---
488
+
489
+ ## Advanced Patterns
490
+
491
+ ### Multiple Adapters Simultaneously
492
+
493
+ Run an MCP server and a REST API from the same set of actions:
494
+
495
+ ```typescript
496
+ import { silkweave } from '@silkweave/core'
497
+ import { stdio } from '@silkweave/mcp'
498
+ import { fastify } from '@silkweave/fastify'
499
+
500
+ await silkweave({ name: 'my-platform', description: 'Multi-transport', version: '1.0.0' })
501
+ .adapter(stdio())
502
+ .adapter(fastify({ host: 'localhost', port: 8080, logger: true }))
503
+ .action(SearchAction)
504
+ .action(GreetAction)
505
+ .action(AnalyzeAction)
506
+ .start()
507
+ ```
508
+
509
+ All adapters start concurrently. The MCP stdio server communicates over stdin/stdout while Fastify listens on port 8080 — each serving the exact same actions.
510
+
511
+ ### CLI Arguments vs Options
512
+
513
+ By default, all Zod fields become CLI `--options`. Use the `args` property to promote fields to positional arguments:
514
+
515
+ ```typescript
516
+ export const DeployAction = createAction({
517
+ name: 'deploy',
518
+ description: 'Deploy to an environment',
519
+ input: z.object({
520
+ environment: z.string().describe('Target environment'),
521
+ tag: z.string().describe('Release tag'),
522
+ dryRun: z.boolean().describe('Simulate without deploying').default(false)
523
+ }),
524
+ args: ['environment', 'tag'],
525
+ run: async ({ environment, tag, dryRun }, { logger }) => {
526
+ logger.info(`Deploying ${tag} to ${environment}${dryRun ? ' (dry run)' : ''}`)
527
+ // ...
528
+ return { deployed: !dryRun }
529
+ }
530
+ })
531
+ ```
532
+
533
+ ```
534
+ $ mytool deploy production v2.1.0 --dry-run
535
+ ◇ mytool - deploy
536
+ ℹ Deploying v2.1.0 to production (dry run)
537
+ ```
538
+
539
+ Fields listed in `args` become positional arguments in the CLI. All other fields remain as `--options`. The `args` property has no effect on MCP or REST adapters — they always receive all fields as a single input object.
540
+
541
+ ### Complex Input Types
542
+
543
+ Zod's full expressiveness is available for input schemas:
544
+
545
+ ```typescript
546
+ export const ImportAction = createAction({
547
+ name: 'import',
548
+ description: 'Import data from a source',
549
+ input: z.object({
550
+ source: z.string().describe('Data source URL'),
551
+ format: z.string().describe('File format').default('json'),
552
+ batchSize: z.number().int().min(1).max(10000).describe('Records per batch').default(500),
553
+ tags: z.record(z.string()).describe('Key-value metadata tags').optional(),
554
+ overwrite: z.boolean().describe('Overwrite existing records').default(false)
555
+ }),
556
+ run: async (input, { logger }) => {
557
+ logger.info(`Importing from ${input.source} in ${input.format} format`)
558
+ logger.info(`Batch size: ${input.batchSize}, overwrite: ${input.overwrite}`)
559
+ if (input.tags) {
560
+ logger.debug(`Tags: ${JSON.stringify(input.tags)}`)
561
+ }
562
+ // ...
563
+ return { imported: 1500 }
564
+ }
565
+ })
566
+ ```
567
+
568
+ In MCP, this becomes a tool with a full JSON Schema. In the CLI, `tags` becomes `--tags <json>` accepting a JSON string. In Fastify, it's a documented POST body.
569
+
570
+ ---
571
+
572
+ ## MCP Client Configuration
573
+
574
+ ### Claude Desktop
575
+
576
+ Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):
577
+
578
+ ```json
579
+ {
580
+ "mcpServers": {
581
+ "my-tools": {
582
+ "command": "node",
583
+ "args": ["/absolute/path/to/server.js"]
584
+ }
585
+ }
586
+ }
587
+ ```
588
+
589
+ ### Claude Code
590
+
591
+ Add to `.mcp.json` in your project root:
592
+
593
+ ```json
594
+ {
595
+ "mcpServers": {
596
+ "my-tools": {
597
+ "command": "pnpm",
598
+ "args": ["tsx", "server.ts"]
599
+ }
600
+ }
601
+ }
602
+ ```
603
+
604
+ ### MCP Inspector
605
+
606
+ For debugging with the MCP Inspector:
607
+
608
+ ```json
609
+ {
610
+ "mcpServers": {
611
+ "my-tools": {
612
+ "command": "pnpm",
613
+ "args": ["tsx", "server.ts"]
614
+ }
615
+ }
616
+ }
617
+ ```
618
+
619
+ ```bash
620
+ npx @modelcontextprotocol/inspector --config .mcp.json --server my-tools
621
+ ```
622
+
623
+ ### HTTP Transport
624
+
625
+ For the streamable HTTP adapter, point your client at the `/mcp` endpoint:
626
+
627
+ ```
628
+ http://localhost:8080/mcp
629
+ ```
630
+
631
+ ---
632
+
633
+ ## API Reference
634
+
635
+ ### `silkweave(options)`
636
+
637
+ Creates a new Silkweave builder instance.
638
+
639
+ ```typescript
640
+ import { silkweave } from '@silkweave/core'
641
+
642
+ function silkweave(options: SilkweaveOptions): Silkweave
643
+
644
+ interface SilkweaveOptions {
645
+ name: string // Server/app name
646
+ description: string // Human-readable description
647
+ version: string // Semantic version
648
+ }
649
+
650
+ interface Silkweave {
651
+ adapter(generator: AdapterGenerator): Silkweave // Add an adapter
652
+ action(action: Action): Silkweave // Mount an action
653
+ actions(actions: Action[]): Silkweave // Mount multiple actions
654
+ start(): Promise<Silkweave> // Start all adapters
655
+ }
656
+ ```
657
+
658
+ ### `createAction(action)`
659
+
660
+ Type-safe action factory. Returns the action object as-is with full type inference.
661
+
662
+ ```typescript
663
+ import { createAction } from '@silkweave/core'
664
+
665
+ function createAction<I extends object, O extends object>(
666
+ action: Action<I, O>
667
+ ): Action<I, O>
668
+
669
+ interface Action<I, O> {
670
+ name: string
671
+ description: string
672
+ input: z.ZodType<I> & { shape: Record<string, z.ZodTypeAny> }
673
+ args?: (keyof I)[]
674
+ isEnabled?: (context: SilkweaveContext) => boolean
675
+ run: (input: I, context: SilkweaveContext) => Promise<O>
676
+ }
677
+ ```
678
+
679
+ ### `Logger`
680
+
681
+ ```typescript
682
+ interface Logger {
683
+ debug: (data: unknown) => void
684
+ info: (data: unknown) => void
685
+ notice: (data: unknown) => void
686
+ warning: (data: unknown) => void
687
+ error: (data: unknown) => void
688
+ critical: (data: unknown) => void
689
+ alert: (data: unknown) => void
690
+ emergency: (data: unknown) => void
691
+ progress: (options: ProgressOptions) => void
692
+ }
693
+
694
+ interface ProgressOptions {
695
+ progress: number
696
+ total?: number
697
+ message?: string
698
+ }
699
+ ```
700
+
701
+ ### Adapter Factories
702
+
703
+ ```typescript
704
+ // MCP over stdin/stdout — from @silkweave/mcp
705
+ import { stdio } from '@silkweave/mcp'
706
+ function stdio(): AdapterFactory
707
+
708
+ // MCP Streamable HTTP — from @silkweave/mcp
709
+ import { http } from '@silkweave/mcp'
710
+ function http(options: HttpAdapterOptions): AdapterFactory
711
+ interface HttpAdapterOptions {
712
+ host: string
713
+ port: number
714
+ // ...plus CreateMcpExpressAppOptions (e.g., allowedHosts)
715
+ }
716
+
717
+ // Fastify REST API with Swagger — from @silkweave/fastify
718
+ import { fastify } from '@silkweave/fastify'
719
+ function fastify(options: FastifyAdapterOptions): AdapterFactory
720
+ interface FastifyAdapterOptions {
721
+ host?: string
722
+ port?: number
723
+ // ...plus all FastifyHttpOptions (logger, connectionTimeout, etc.)
724
+ }
725
+
726
+ // CLI via commander + clack — from @silkweave/cli
727
+ import { cli } from '@silkweave/cli'
728
+ function cli(): AdapterFactory
729
+
730
+ // Vercel serverless — from @silkweave/vercel
731
+ import { vercel } from '@silkweave/vercel'
732
+ function vercel(options?: VercelAdapterOptions): VercelAdapter
733
+ interface VercelAdapterOptions {
734
+ enableJsonResponse?: boolean
735
+ }
736
+ interface VercelAdapter {
737
+ adapter: AdapterGenerator // Pass to silkweave().adapter()
738
+ handler: (req: Request) => Promise<Response>
739
+ GET: (req: Request) => Promise<Response>
740
+ POST: (req: Request) => Promise<Response>
741
+ DELETE: (req: Request) => Promise<Response>
742
+ }
743
+ ```
744
+
745
+ ---
746
+
747
+ ## Development
748
+
749
+ ```bash
750
+ # Install dependencies
751
+ pnpm install
752
+
753
+ # Build all packages
754
+ pnpm build
755
+
756
+ # Lint + typecheck all packages
757
+ pnpm check
758
+
759
+ # Run example servers
760
+ pnpm tsx example/src/stdio.ts # MCP stdio server
761
+ pnpm tsx example/src/http.ts # MCP streamable HTTP server on :8080
762
+ pnpm tsx example/src/fastify.ts # Fastify REST API with Swagger on :8080
763
+ pnpm tsx example/src/cli.ts # CLI mode
764
+ ```
765
+
766
+ Requires Node.js >= 18.
767
+
768
+ ---
769
+
770
+ ## License
771
+
772
+ MIT
@@ -0,0 +1,7 @@
1
+ export * from '@silkweave/auth';
2
+ import '@silkweave/cli';
3
+ import '@silkweave/core';
4
+ import '@silkweave/fastify';
5
+ import '@silkweave/logger';
6
+ import '@silkweave/mcp';
7
+ import '@silkweave/vercel';
package/build/auth.js ADDED
@@ -0,0 +1,3 @@
1
+ // src/auth.ts
2
+ export * from "@silkweave/auth";
3
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/auth.ts"],"sourcesContent":["export * from '@silkweave/auth'\n"],"mappings":";AAAA,cAAc;","names":[]}
package/build/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from '@silkweave/cli';
package/build/cli.js ADDED
@@ -0,0 +1,3 @@
1
+ // src/cli.ts
2
+ export * from "@silkweave/cli";
3
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["export * from '@silkweave/cli'\n"],"mappings":";AAAA,cAAc;","names":[]}
@@ -0,0 +1 @@
1
+ export * from '@silkweave/core';
package/build/core.js ADDED
@@ -0,0 +1,3 @@
1
+ // src/core.ts
2
+ export * from "@silkweave/core";
3
+ //# sourceMappingURL=core.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core.ts"],"sourcesContent":["export * from '@silkweave/core'\n"],"mappings":";AAAA,cAAc;","names":[]}
@@ -0,0 +1 @@
1
+ export * from '@silkweave/fastify';
@@ -0,0 +1,3 @@
1
+ // src/fastify.ts
2
+ export * from "@silkweave/fastify";
3
+ //# sourceMappingURL=fastify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/fastify.ts"],"sourcesContent":["export * from '@silkweave/fastify'\n"],"mappings":";AAAA,cAAc;","names":[]}
@@ -0,0 +1 @@
1
+ export * from '@silkweave/logger';
@@ -0,0 +1,3 @@
1
+ // src/logger.ts
2
+ export * from "@silkweave/logger";
3
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/logger.ts"],"sourcesContent":["export * from '@silkweave/logger'\n"],"mappings":";AAAA,cAAc;","names":[]}
package/build/mcp.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from '@silkweave/mcp';
package/build/mcp.js ADDED
@@ -0,0 +1,3 @@
1
+ // src/mcp.ts
2
+ export * from "@silkweave/mcp";
3
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/mcp.ts"],"sourcesContent":["export * from '@silkweave/mcp'\n"],"mappings":";AAAA,cAAc;","names":[]}
@@ -0,0 +1 @@
1
+ export * from '@silkweave/vercel';
@@ -0,0 +1,3 @@
1
+ // src/vercel.ts
2
+ export * from "@silkweave/vercel";
3
+ //# sourceMappingURL=vercel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/vercel.ts"],"sourcesContent":["export * from '@silkweave/vercel'\n"],"mappings":";AAAA,cAAc;","names":[]}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "silkweave",
3
+ "version": "1.3.1",
4
+ "description": "Silkweave Umbrella Package",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+ssh://git@github.com/silkweave/silkweave.git",
8
+ "directory": "packages/silkweave"
9
+ },
10
+ "type": "module",
11
+ "exports": {
12
+ "./auth": {
13
+ "types": "./build/auth.d.ts",
14
+ "default": "./build/auth.js"
15
+ },
16
+ "./cli": {
17
+ "types": "./build/cli.d.ts",
18
+ "default": "./build/cli.js"
19
+ },
20
+ "./core": {
21
+ "types": "./build/core.d.ts",
22
+ "default": "./build/core.js"
23
+ },
24
+ "./fastify": {
25
+ "types": "./build/fastify.d.ts",
26
+ "default": "./build/fastify.js"
27
+ },
28
+ "./logger": {
29
+ "types": "./build/logger.d.ts",
30
+ "default": "./build/logger.js"
31
+ },
32
+ "./mcp": {
33
+ "types": "./build/mcp.d.ts",
34
+ "default": "./build/mcp.js"
35
+ },
36
+ "./vercel": {
37
+ "types": "./build/vercel.d.ts",
38
+ "default": "./build/vercel.js"
39
+ }
40
+ },
41
+ "dependencies": {
42
+ "@silkweave/auth": "1.3.1",
43
+ "@silkweave/cli": "1.3.1",
44
+ "@silkweave/core": "1.3.1",
45
+ "@silkweave/fastify": "1.3.1",
46
+ "@silkweave/logger": "1.3.1",
47
+ "@silkweave/vercel": "1.3.1",
48
+ "@silkweave/mcp": "1.3.1"
49
+ },
50
+ "devDependencies": {
51
+ "@eslint/js": "^10.0.1",
52
+ "@stylistic/eslint-plugin": "^5.10.0",
53
+ "@types/node": "^22.0.0",
54
+ "rimraf": "^6.1.3",
55
+ "tsup": "^8.5.1",
56
+ "tsx": "^4.21.0",
57
+ "typescript": "^5.9.3",
58
+ "typescript-eslint": "^8.56.1"
59
+ },
60
+ "scripts": {
61
+ "clean": "rimraf build",
62
+ "build": "tsup",
63
+ "watch": "tsup --watch",
64
+ "typecheck": "tsc --noEmit",
65
+ "lint": "eslint",
66
+ "check": "pnpm lint && pnpm typecheck"
67
+ }
68
+ }