Define once.
Deploy everywhere.
Build MCP servers, REST APIs, and CLI tools from a single set of actions. No framework lock-in. No boilerplate. Just composition.
pnpm add @silkweave/core The Problem
Agents need services. Services need many doors.
The agentic landscape demands that services be reachable via MCP, REST, CLI, and more. Building each transport from scratch is unsustainable.
Fragmented Transports
MCP stdio, HTTP, REST, CLI - each requires a different server setup, different libraries, different patterns.
Boilerplate Overload
Every new endpoint means repeating validation, error handling, and serialization. Your business logic drowns in glue code.
Framework Lock-in
Pick Express? Now you're stuck. Pick Fastify? Same story. Your actions are trapped inside your transport choice.
Quick Start
Up and running in 3 steps.
Install
pnpm add @silkweave/core @silkweave/mcp zod Define an action
import { createAction } from '@silkweave/core'
import z from 'zod'
export const GreetAction = createAction({
name: 'greet',
description: 'Greet a user by name',
input: z.object({
name: z.string().describe('Name to greet')
}),
run: async ({ name }) => {
return { message: `Hello, ${name}!` }
}
}) Pick an adapter and start
import { silkweave } from '@silkweave/core'
import { stdio } from '@silkweave/mcp'
import { GreetAction } from './actions/greet.js'
await silkweave({ name: 'my-server', version: '1.0.0' })
.adapter(stdio())
.action(GreetAction)
.start() How It Works
One action. Every transport.
Define your business logic once as an Action. Pick an Adapter. Silkweave wires them together.
import { createAction } from '@silkweave/core'
import z from 'zod'
export const GreetAction = createAction({
name: 'greet',
description: 'Greet a user by name',
input: z.object({
name: z.string().describe('Name of the person to greet')
}),
run: async ({ name }) => {
return { message: `Hello, ${name}!` }
}
}) Adapters
Same action. Seven adapters.
Swap one line to change how your action is served. The business logic stays identical.
import { silkweave } from '@silkweave/core'
import { stdio } from '@silkweave/mcp'
import { GreetAction } from './actions/greet.js'
await silkweave({ name: 'my-server', version: '1.0.0' })
.adapter(stdio())
.action(GreetAction)
.start() import { silkweave } from '@silkweave/core'
import { http } from '@silkweave/mcp'
import { GreetAction } from './actions/greet.js'
await silkweave({ name: 'my-server', version: '1.0.0' })
.adapter(http({ port: 8080 }))
.action(GreetAction)
.start() import { silkweave } from '@silkweave/core'
import { fastify } from '@silkweave/fastify'
import { GreetAction } from './actions/greet.js'
await silkweave({ name: 'my-server', version: '1.0.0' })
.adapter(fastify({ port: 8080 }))
.action(GreetAction)
.start() import { silkweave } from '@silkweave/core'
import { trpc, type InferTrpcRouter } from '@silkweave/trpc'
import { GreetAction } from './actions/greet.js'
const server = silkweave({ name: 'my-api', version: '1.0.0' })
.adapter(trpc({ port: 8080 }))
.action(GreetAction)
export type AppRouter = InferTrpcRouter<typeof server>
await server.start() import { silkweave } from '@silkweave/core'
import { cli } from '@silkweave/cli'
import { GreetAction } from './actions/greet.js'
await silkweave({ name: 'my-tool', version: '1.0.0' })
.adapter(cli())
.action(GreetAction)
.start() import { silkweave } from '@silkweave/core'
import { edge } from '@silkweave/edge'
import { GreetAction } from './actions/greet.js'
const { adapter, handler } = edge()
await silkweave({ name: 'my-server', version: '1.0.0' })
.adapter(adapter)
.action(GreetAction)
.start()
export default { fetch: handler } import { silkweave } from '@silkweave/core'
import { typegen } from '@silkweave/typegen'
import { GreetAction } from './actions/greet.js'
await silkweave({ name: 'my-server', version: '1.0.0' })
.adapter(typegen({ path: 'types/actions.d.ts' }))
.action(GreetAction)
.start()
// Generates: export interface GreetInput { name: string } Integrations
Drop into your framework of choice.
Adapters are one transport each. Integrations compose them with the conventions of a host framework - decorators, DI, file-based routing - so Silkweave feels native.
Standalone
StableCompose the fluent builder yourself. Pick whichever adapters fit; run it as a Node process, container, or serverless function.
- Chain unlimited adapters; one action served everywhere
- Per-action
isEnabledfiltering across transports - Drop into Astro / Vercel / Workers via fetch handlers
NestJS
StableExpose your existing NestJS controllers as MCP tools by adding one @Mcp() decorator. Tool input is reflected from the route + @Param/@Query/@Body + swagger/class-validator metadata. Additive - controllers serve HTTP unchanged.
@Mcp()on existing controller routes,DiscoveryService-driven- Input schema reflected from params + swagger/class-validator (+ optional OpenAPI doc)
@UseGuards()fires over MCP, reading inbound tool-call headers
Next.js
BetaApp Router adapter. defineSilkweave({ actions }) projects one action set onto route handlers - MCP tools for agents and a typed tRPC endpoint for your frontend - from a single source of truth. Additive, App Router only.
app.mcp()+app.trpc()route handlers from one action set- End-to-end-typed tRPC for your frontend, MCP tools for agents
- Wraps
edge()+trpcFetch(); nonext/reactdependency
Features
Everything you need. Nothing you don't.
Zod-Powered Schemas
Define inputs with Zod. Get validation, type inference, and auto-generated docs for free.
Learn more →Built-in OAuth 2.1
Full OAuth proxy with PKCE, refresh tokens, and dynamic client registration out of the box.
Learn more →Auto-Generated Swagger
The Fastify adapter produces OpenAPI specs and interactive Swagger UI automatically.
Learn more →Session & Context
Fluent .set() API for per-request context. Actions receive a typed context bag - no globals.
Learn more →Streaming Actions
Yield chunks from an async generator. Silkweave delivers them as MCP progress, SSE, NDJSON, or tRPC subscriptions.
Learn more →Vercel AI SDK Native
useChat over a tRPC subscription with a custom transport. No /api/chat route, no Data Stream Protocol - just typed UIMessageChunks.
Learn more →Edge / Serverless
Deploy stateless MCP servers to Vercel, Cloudflare Workers, or Bun. Web Standard APIs, zero lock-in.
Learn more →CLI with Prompts
Expose the same actions as a CLI tool with interactive prompts, powered by Commander + Clack.
Learn more →Type Generation
Auto-generate .d.ts interfaces from your Zod schemas at build time. Zero runtime cost, full type safety.
Learn more →