Skip to content

Project Templates

DyneMCP provides two official templates to help you get started quickly with MCP servers. Each template is designed for a specific transport (STDIO or HTTP) and comes with pre-configured features, best practices, and real code examples.

A minimal, type-safe setup for MCP servers using the STDIO transport.

Terminal window
pnpm dlx @dynemcp/create-dynemcp my-project --template default-stdio
  • File-based auto-loading for tools, resources, prompts, and roots
  • TypeScript-first: full type safety and IntelliSense
  • JWT authentication middleware (ready to use)
  • Example tool, resource, prompt, and LLM sample
  • Clean, extensible project structure
src/
├── index.ts # Server entry point
├── middleware.ts # JWT authentication middleware
├── tools/ # Tools directory
│ └── greeter/ # Greeter tool folder
│ └── tool.ts # Main tool file (auto-loaded)
├── resources/ # Resources directory
│ └── framework-info/ # Framework info resource folder
│ └── resource.ts # Main resource file (auto-loaded)
├── prompts/ # Prompts directory
│ └── system-context/ # System context prompt folder
│ └── prompt.ts # Main prompt file (auto-loaded)
├── samples/ # LLM sample directory
│ └── hello-sample/ # Example LLM completion sample
│ └── sample.ts # Main sample file
└── roots/ # Roots helpers and examples
└── roots.ts # Example and helpers for roots
src/tools/greeter/tool.ts
import { tool } from '@dynemcp/dynemcp'
import { z } from 'zod'
const GreeterSchema = z.object({
name: z.string().describe('The name to greet'),
image: z.string().url().optional().describe('Optional image URL'),
})
export default tool(
GreeterSchema,
async ({ name, image }) => {
if (!name?.trim()) return 'Name cannot be empty'
if (!image) return `Hello, ${name}!`
return [
`Hello, ${name}!`,
{ type: 'image', url: image, alt: `Avatar for ${name}` },
]
},
{
name: 'greeter',
description: 'A simple tool that greets the user and can return an image',
}
)
src/resources/framework-info/resource.ts
import { resource } from '@dynemcp/dynemcp'
function getFrameworkInfo() {
return `# DyneMCP Framework\n\nThis is a TypeScript-first framework for building MCP servers.`
}
export default resource({
uri: 'info://framework',
name: 'Framework Information',
description: 'Information about the DyneMCP framework',
mimeType: 'text/markdown',
getContent: getFrameworkInfo,
})
src/prompts/system-context/prompt.ts
import { prompt as systemPrompt } from '@dynemcp/dynemcp'
const SystemContextArguments = [
{ name: 'user_role', description: 'The role of the user', required: false },
{
name: 'task_context',
description: 'The current task or context',
required: false,
},
]
async function getMessages(args = {}) {
const userRole = args.user_role || 'user'
const taskContext = args.task_context || 'general assistance'
return [
{
role: 'user',
content: {
type: 'text',
text: `You are an AI assistant for the DyneMCP framework.\nCurrent context: ${taskContext}`,
},
},
]
}
export default systemPrompt({
name: 'system_context',
description: 'Provides system context and instructions for the AI assistant',
arguments: SystemContextArguments,
getMessages,
})

Example: Creating a Sample (LLM Completion)

Section titled “Example: Creating a Sample (LLM Completion)”
src/samples/hello-sample/sample.ts
import { sample, SamplingRequest } from '@dynemcp/dynemcp'
async function runHelloSample() {
const request: SamplingRequest = {
messages: [
{
role: 'user',
content: { type: 'text', text: 'Say hello to the world!' },
},
],
maxTokens: 32,
}
return await sample(request)
}
export default {
name: 'hello-sample',
description: 'Requests a sample LLM completion',
run: runHelloSample,
}
import { root } from '@dynemcp/dynemcp/server/api/core/root'
export default root([
{
uri: 'file:///home/user/projects/myapp',
name: 'My Project',
},
])
  • The template includes a ready-to-use JWT authentication middleware in src/middleware.ts.
  • The server will refuse to start in production if you do not create src/middleware.ts.
  • In development, all requests are allowed by default, but a warning will be logged.

A minimal, type-safe setup for MCP servers using the streamable HTTP transport.

Terminal window
pnpx @dynemcp/create-dynemcp my-server --template default-http
  • File-based auto-loading for tools, resources, prompts, and roots
  • TypeScript-first: full type safety and IntelliSense
  • JWT authentication middleware (ready to use)
  • Example tool, resource, prompt, and LLM sample
  • Clean, extensible project structure
  • HTTP transport with CORS and security middleware
src/
├── index.ts # Server entry point
├── middleware.ts # JWT authentication middleware
├── tools/ # Tools directory
│ └── greeter/ # Greeter tool folder
│ └── tool.ts # Main tool file (auto-loaded)
├── resources/ # Resources directory
│ └── framework-info/ # Framework info resource folder
│ └── resource.ts # Main resource file (auto-loaded)
├── prompts/ # Prompts directory
│ └── system-context/ # System context prompt folder
│ └── prompt.ts # Main prompt file (auto-loaded)
├── samples/ # LLM sample directory
│ └── hello-sample/ # Example LLM completion sample
│ └── sample.ts # Main sample file
└── roots/ # Roots helpers and examples
└── roots.ts # Example and helpers for roots

Example code for tools, resources, prompts, samples, roots, and middleware is identical to the STDIO template above.

Section titled “Example code for tools, resources, prompts, samples, roots, and middleware is identical to the STDIO template above.”
  • The template includes a ready-to-use JWT authentication middleware in src/middleware.ts.
  • The server will refuse to start in production if you do not create src/middleware.ts.
  • In development, all requests are allowed by default, but a warning will be logged.

  • Only files named tool.ts, resource.ts, prompt.ts, or roots.ts in their respective folders are auto-loaded.
  • Any other files (e.g., utils.ts) are ignored by the loader and can be used for utilities.