About
MCP-Atom is a zero-boilerplate framework
README
Build MCP servers in minutes, not hours. MCP-Atom is a zero-boilerplate framework that automatically discovers, validates, and registers your tools, prompts, and resources by simply reading your file structure and JSDoc comments.
What is MCP?
The Model Context Protocol (MCP) is an open protocol that enables AI assistants to securely access external tools, data sources, and capabilities. Think of it as a standardized way for AI applications like Claude Desktop to connect to your services, databases, APIs, and custom functionality.
Why MCP-Atom?
Traditional MCP server development requires:
- ❌ Manual registration of every tool, prompt, and resource
- ❌ Writing JSON Schema definitions by hand
- ❌ Boilerplate code for each endpoint
- ❌ Maintaining type definitions separately from implementation
MCP-Atom eliminates all of this. Just write files with JSDoc comments, and everything is automatically discovered, validated, and registered.
Key Benefits
- 🚀 Zero Boilerplate: No manual
server.registerTool()calls - 📝 JSDoc-Driven: Schemas extracted automatically from your comments
- 🔍 Auto-Discovery: Drop files in folders, they're automatically registered
- ✅ Type-Safe: Automatic Zod schema generation with validation
- 🎯 Convention Over Configuration: File structure = API structure
Quick Start
Installation
npm install
Project Structure
Create a register/ folder with three subfolders:
register/
├── tools/ # Executable functions
├── prompts/ # Prompt templates
└── resources/ # Data sources (files, APIs, etc.)
Your First Tool
Create a file in register/tools/ with a JSDoc comment and default export. The tool will be automatically registered with:
- ✅ Input validation based on your JSDoc types
- ✅ Output schema
- ✅ Title and description from JSDoc
- ✅ Full type safety
Running the Server
MCP-Atom supports two transport modes: Stdio (default) and Streamable HTTP.
Stdio Transport (Default)
The default transport uses standard input/output, which is ideal for local development and integration with MCP clients like Claude Desktop.
npm start
Or use the MCP Inspector to test:
npm run start:inspect
Streamable HTTP Transport
For web-based clients or remote access, use the Streamable HTTP transport. This enables:
- HTTP/HTTPS connections
- Server-Sent Events (SSE) for real-time updates
- Session management with resumability
- CORS support for browser-based clients
Enable HTTP transport using the dedicated script:
npm run start:http
Or manually set environment variables:
# Option 1: Use TRANSPORT environment variable
TRANSPORT=http npm start
# Option 2: Use USE_HTTP flag
USE_HTTP=true npm start
Configure the port (default: 3001):
PORT=8080 npm run start:http
# Or with manual env var:
PORT=8080 TRANSPORT=http npm start
The server will listen on http://localhost:8080/mcp (or your specified port, default: 3001).
Endpoints:
POST /mcp- MCP requests (initialization and subsequent requests)GET /mcp- SSE stream for server-to-client notificationsDELETE /mcp- Session termination
Headers:
mcp-session-id- Session identifier (required for GET/DELETE, optional for initial POST)last-event-id- For resuming SSE streams after disconnection
Example with HTTP:
# Start server on port 3001 (default)
npm run start:http
# Or with custom port
PORT=8080 npm run start:http
Testing with HTTP:
You can use the MCP Inspector with HTTP transport:
# Start server with HTTP transport
npm run start:http
# Then in another terminal, run the inspector
npm run start:inspect
Or manually configure MCP Inspector:
Start your server with HTTP transport:
npm run start:http # Or with custom port: PORT=8080 npm run start:httpIn MCP Inspector, configure the connection:
- Connection Type: Select
Direct(for direct connection to your server) - URL:
http://localhost:3001/mcp(or your configured port, e.g.,http://localhost:8080/mcp) - Request Timeout:
300000(5 minutes, default) - Reset Timeout on Progress:
True(recommended) - Maximum Total Timeout:
60000(1 minute, default) - Inspector Proxy Address: Leave empty (only needed if Connection Type is "via proxy")
- Proxy Session Token: Leave empty (only needed if Connection Type is "via proxy")
Note: When using
Directconnection type, you do not need to fill in the Proxy Address or Proxy Session Token fields. Those are only required when usingvia proxyconnection type.- Connection Type: Select
Connect - The Inspector will automatically handle session initialization and SSE streams.
Or connect any MCP-compatible client to http://localhost:3001/mcp (or your configured port).
Configuration
Environment Variables
| Variable | Description | Default | Example |
|---|---|---|---|
TRANSPORT |
Transport mode: stdio or http |
stdio |
TRANSPORT=http npm start or npm run start:http |
USE_HTTP |
Enable HTTP transport (alternative to TRANSPORT=http) |
false |
USE_HTTP=true npm start |
PORT |
Port number for HTTP transport | 3001 |
PORT=8080 npm run start:http |
Transport Comparison
| Feature | Stdio | Streamable HTTP |
|---|---|---|
| Use Case | Local development, Claude Desktop | Web clients, remote access |
| Connection | Process stdio | HTTP/HTTPS |
| Real-time Updates | ✅ | ✅ (via SSE) |
| Session Management | Single session | Multiple concurrent sessions |
| Resumability | ❌ | ✅ (via Last-Event-ID) |
| CORS Support | N/A | ✅ |
| Port Required | ❌ | ✅ (default: 3001) |
File Format Reference
Tools
Tools are executable functions that perform actions. They accept input parameters and return results.
Location: register/tools/*.js
Format:
/**
* Tool Title - Brief description
*
* @param {{ param1: type1, param2?: type2 }} input
* @returns {{ result: type }}
*/
export default ({ param1, param2 }) => {
// Your implementation
return { result: /* ... */ };
}
Optional Parameters: Use ? in the type definition:
@param {{ name: string, style?: string }} input
Complex Types: Supports arrays, nested objects, unions, and more:
@param {{
items: string[],
config: { timeout: number, retry: boolean },
status: "active" | "inactive"
}} input
Returning Metadata: Return an array [output, ...meta] to include additional content. The first element is the main output, subsequent elements are metadata items (resource links, images, etc.).
📖 See register/README.md for detailed examples of all tool types.
Prompts
Prompts are template generators that create messages for AI assistants.
Location: register/prompts/*.js
Format:
/**
* Prompt Title - Brief description
*
* @param {{ arg1: type1, arg2?: type2 }} input
* @returns {{ messages: Array<{ role: string, content: { type: string, text: string } }> }}
*/
export default ({ arg1, arg2 = "default" }) => {
return {
messages: [
{
role: "user",
content: {
type: "text",
text: `Your prompt text using ${arg1} and ${arg2}`
}
}
]
};
}
Note: Prompts must return an object with a messages array following the MCP prompt format.
📖 See register/README.md for detailed prompt examples.
Resources
Resources are data sources that can be read by AI assistants. They can be static or dynamic with parameters.
Location: register/resources/{protocol}/*.js
Static Resource:
/**
* Resource Title - Brief description
*
* @returns {{ ... }}
*/
export default () => {
return { /* your data */ };
}
Dynamic Resource with Parameters:
Use folder names with {parameter} syntax to create parameterized resources:
/**
* Resource Title - Brief description
*
* @param {{ paramName: type }} input
* @returns {type}
* @mime text/plain
*/
export default ({ paramName }) => {
return /* your data */;
}
This creates a resource accessible at {protocol}://{path} where parameters are extracted from the folder structure.
Resource URI Structure:
- Folder path:
resources/github/repos/{owner}/{repo}.js - Resource URI:
github://repos/{owner}/{repo} - Registration name:
github-repos-owner-repo
Autocomplete Support:
Add an autocomplete export to provide intelligent completions. Each function receives value (current input) and context (with previously resolved parameters) and returns a filtered array of suggestions.
MIME Types: Specify content type with @mime tag:
/**
* @mime application/json
*/
📖 See register/README.md for detailed resource examples including autocomplete patterns.
Type System
MCP-Atom automatically converts JSDoc types to Zod schemas. Supported types:
Primitives
string,number,boolean,null,any,unknownDate(converted to ISO string)
Collections
string[]orArray<string>- arrays{ key: value }- objects
Advanced
"value1" | "value2"- unions{ prop?: type }- optional propertiesPromise<{ result: type }>- promises (unwrapped)
Examples
// Simple object
@param {{ name: string, age: number }} input
// With optional fields
@param {{ name: string, email?: string }} input
// Nested objects
@param {{
user: { id: string, name: string },
settings: { theme: "light" | "dark" }
}} input
// Arrays
@param {{ tags: string[], items: Array<{ id: number }> }} input
// Complex nested structure
@param {{
config: {
api: {
baseUrl: string,
timeout: number,
retry: boolean
},
features: {
enabled: boolean,
options: string[]
}
}
}} input
📖 See register/README.md for more type examples and patterns.
Project Structure
The register/ folder structure determines your API structure:
- Tools:
register/tools/*.js- each file becomes a tool - Prompts:
register/prompts/*.js- each file becomes a prompt - Resources:
register/resources/{protocol}/*.js- folder structure maps to resource URIs- Static:
resources/config/app.js→config://app - Dynamic:
resources/users/{userId}/profile.js→users://{userId}/profile
- Static:
How It Works
- Discovery: MCP-Atom scans the
register/folder recursively - Parsing: Each
.jsfile is analyzed for:- JSDoc comments (title, description, types)
- Default export function
- Optional
autocompleteexport (for resources)
- Schema Generation: JSDoc types are converted to Zod schemas
- Registration: Tools, prompts, and resources are automatically registered with the MCP server
- Validation: All inputs are validated against generated schemas
Best Practices
- Always include JSDoc: Every file needs a JSDoc block with
@paramand@returns - Use descriptive titles: The first line becomes the tool/prompt/resource title
- Document optional parameters: Use
?in type definitions for optional fields - Keep functions pure when possible: Easier to test and reason about
- Handle errors gracefully: Return meaningful error messages
- Use TypeScript-style JSDoc: The parser understands TypeScript syntax
Advanced Features
Async Functions
All handlers support async/await. Simply use async in your function declaration.
Returning Multiple Content Items
Tools can return an array where the first element is the output and subsequent elements are metadata (resource links, images, etc.).
Troubleshooting
Common Issues
"No default export found": Every file must have export default
"No JSDoc found": Every file needs a JSDoc comment block
Type parsing errors: Check your JSDoc syntax matches the examples
Resource not found: Verify folder structure matches resources/{protocol}/...
HTTP Transport Issues
"Port already in use": Change the port using PORT=8080 npm run start:http
"CORS errors": The server is configured with CORS enabled by default (origin: "*"). For production, consider restricting origins.
"Session not found": Ensure you're sending the mcp-session-id header for GET/DELETE requests after initialization
"Connection refused": Verify the server is running and the port matches your client configuration
Production Considerations
When using HTTP transport in production:
CORS Configuration: The default CORS setting allows all origins (
origin: "*"). Restrict this in production:// In index.js, update the CORS configuration app.use(cors({ origin: process.env.ALLOWED_ORIGINS?.split(',') || ['https://yourdomain.com'], // ... other options }));Authentication: Add authentication middleware before the MCP routes if needed
HTTPS: Use a reverse proxy (nginx, Caddy) or load balancer to add HTTPS
Port Security: Ensure your firewall only allows necessary ports
Next Steps
- 📖 See
register/README.mdfor detailed examples of all file types with real code - 🔧 Check out
builderBot/readme.mdfor internal implementation details - 📚 Read the MCP Specification for protocol details
Installing Atom
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/codemeasandwich/MCP-atomFAQ
Is Atom MCP free?
Yes, Atom MCP is free — one-click install via Unyly at no cost.
Does Atom need an API key?
No, Atom runs without API keys or environment variables.
Is Atom hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Atom in Claude Desktop, Claude Code or Cursor?
Open Atom on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
GitHub
PRs, issues, code search, CI status
by GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
by mcpdotdirectCompare Atom with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All development MCPs
