Skip to content

codemeasandwich/MCP-atom

Repository files navigation

MCP-Atom

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 notifications
  • DELETE /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:

  1. Start your server with HTTP transport:

    npm run start:http
    # Or with custom port:
    PORT=8080 npm run start:http
  2. In 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 Direct connection type, you do not need to fill in the Proxy Address or Proxy Session Token fields. Those are only required when using via proxy connection type.

  3. 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, unknown
  • Date (converted to ISO string)

Collections

  • string[] or Array<string> - arrays
  • { key: value } - objects

Advanced

  • "value1" | "value2" - unions
  • { prop?: type } - optional properties
  • Promise<{ 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.jsconfig://app
    • Dynamic: resources/users/{userId}/profile.jsusers://{userId}/profile

How It Works

  1. Discovery: MCP-Atom scans the register/ folder recursively
  2. Parsing: Each .js file is analyzed for:
    • JSDoc comments (title, description, types)
    • Default export function
    • Optional autocomplete export (for resources)
  3. Schema Generation: JSDoc types are converted to Zod schemas
  4. Registration: Tools, prompts, and resources are automatically registered with the MCP server
  5. Validation: All inputs are validated against generated schemas

Best Practices

  1. Always include JSDoc: Every file needs a JSDoc block with @param and @returns
  2. Use descriptive titles: The first line becomes the tool/prompt/resource title
  3. Document optional parameters: Use ? in type definitions for optional fields
  4. Keep functions pure when possible: Easier to test and reason about
  5. Handle errors gracefully: Return meaningful error messages
  6. 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:

  1. 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
    }));
  2. Authentication: Add authentication middleware before the MCP routes if needed

  3. HTTPS: Use a reverse proxy (nginx, Caddy) or load balancer to add HTTPS

  4. Port Security: Ensure your firewall only allows necessary ports

Next Steps

  • 📖 See register/README.md for detailed examples of all file types with real code
  • 🔧 Check out builderBot/readme.md for internal implementation details
  • 📚 Read the MCP Specification for protocol details

About

MCP-Atom is a zero-boilerplate framework

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published