Technology8 min readNovember 16, 2025

Releasing LeanMCP SDK

Introducing the LeanMCP SDK - built to solve the framework gap in MCP development with best practices, built-in tools, and seamless agent integration.

Dheeraj Pai
Co-Founder
MCPSDKDeveloper ToolsLeanMCPCLI

Releasing LeanMCP SDK

Building a usable MCP server shouldn't eat a week of your time. You define the schema to the tools. And write the function calls and the LLM picks it up automatically. Simple right? Wrong. OAuth breaks. Sessions fail. Your Streamable HTTP server works locally but crashes or timeouts in production. You're 200 lines deep before you even call your actual MCP Call through your Agent.

MCP was supposed to solve the NxM integration problem. Instead, it created the "every developer reinvents the wheel" problem.

How will you include the UI? How will you make sure OAuth is supported? How will you make sure only specific people with specific permissions can access a specific tool? Things get extremely complicated when you integrate with agentic payment systems. How will you handle the card numbers? How will you make sure the payment is held secure? Do you send this to the agent? So, the nightmare comes with the security. The learning curve to understand the best practices is a bit steep. And LLMs fail at this miserably because of lack of training data related to the latest updates to the MCPs. At LeanMCP, we found these typical issues consistently among our users.

The Problems

1. Protocol Chaos
MCP is pretty young and ever evolving. To make sure your MCP server is actually useful to the users, it should keep up with the updates from the protocol. And so should the MCP clients. The STDIO MCPs you created in February 2024 don't work well with the clients supported now. The SSE MCPs you created in March are now getting deprecated. And deploying a STDIO and testing it locally should not make the developer change 50 lines of code. Same with the case of moving from a dev Supabase auth provider for your MCP to a self-hosted one.

2. Backward Compatibility Nightmare
You build your MCP server with HTTP+SSE transport (2024-11-05 spec). Works great. Then the protocol releases Streamable HTTP (2025-03-26 spec). Now you need to support both. That means maintaining two separate transport implementations - one with GET /mcp for SSE and POST /messages for requests, another with a single POST /mcp endpoint but complex request/response patterns. Your Express.js app suddenly needs to handle both protocols, manage different session states, route requests correctly. All this just to stay compatible.

3. Security Nightmare
43% of MCP implementations contain critical security vulnerabilities because developers don't know the best practices yet. Want to use Firebase Auth? You need to implement the entire OAuth 2.1 flow yourself. Supabase? Same thing. Auth0? Same story. Then you need to manage access tokens, refresh tokens, session management across different transport types. Each auth provider has its own quirks.

4. Boilerplate Code Overload
Lots of boilerplate code for even very basic MCPs. A simple "get weather" tool requires: Express setup, transport handling, session management, error handling, schema definition, tool registration, response formatting. That's 200+ lines of code before you even write the actual weather API call. Want to add logging? Add 50 more lines. Want proper error boundaries? Another 50 lines. Want to support both transports? Double everything.

The SDK in Action

SDK Architecture

Here's how LeanMCP SDK crushes each problem:

Before SDK: 200+ Lines of Boilerplate

// Express setup
import express from 'express';
import { MCPServer } from '@modelcontextprotocol/sdk/server';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse';
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamable';

const app = express();
app.use(express.json());

// Session management
const sessions = new Map();
app.use((req, res, next) => {
  const sessionId = req.headers['x-session-id'];
  if (!sessions.has(sessionId)) {
    sessions.set(sessionId, { transport: null, server: null });
  }
  next();
});

// Transport handlers for both SSE and Streamable HTTP
app.post('/mcp', async (req, res) => {
  const transport = new StreamableHTTPServerTransport(req, res);
  // Handle requests, manage lifecycle, error handling
});

app.get('/mcp', async (req, res) => {
  const transport = new SSEServerTransport('/messages', res);
  // Setup SSE, manage connections, handle timeouts
});

// Tool registration with manual schema definition
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [{
      name: 'getWeather',
      description: 'Get weather',
      inputSchema: {
        type: 'object',
        properties: {
          city: { type: 'string', description: 'City name' }
        },
        required: ['city']
      }
    }]
  };
});

// 200+ lines total before actual API call

After SDK: 50 Lines Total

import { Tool, SchemaConstraint, createHTTPServer } from "@leanmcp/core";

class WeatherInput {
  @SchemaConstraint({ description: 'City name', minLength: 1 })
  city!: string;
}

export class WeatherService {
  @Tool({ 
    description: 'Get weather for a city',
    inputClass: WeatherInput
  })
  async getWeather(input: WeatherInput) {
    return { temperature: 72, condition: 'sunny' };
  }
}

createHTTPServer((server) => {
  server.registerService(new WeatherService());
}, { port: 8080 });

That's it. Auth? Built in. Logging? Built in. Both transports? Handled.

Auth in 5 Lines

import { Authenticated, AuthProvider } from "@leanmcp/auth";

const authProvider = new AuthProvider('cognito', {
  region: 'us-east-1',
  userPoolId: 'us-east-1_XXXXXXXXX',
  clientId: 'your-client-id'
});

@Authenticated(authProvider)
export class SecureService {
  @Tool({ description: 'Send message to Slack' })
  async sendMessage(input: { channel: string; text: string }) {
    // Token automatically validated from _meta.authorization.token
    return { success: true };
  }
}

No OAuth flow implementation. No token management. No session juggling. The SDK handles it.

Currently Supported:

  • AWS Cognito

Coming Soon:

  • Supabase Auth
  • Clerk
  • Auth0
  • Firebase Auth

Want a specific auth provider? Open an issue on GitHub.

The Agent Experience Problem

It's not just about developer experience. Agents need good tools too.

The MCP protocol itself is growing super fast. But if you prompt Claude 3.5 Sonnet today (supposedly the best coding LLM), it still uses MCP versions from February 2024 - a highly outdated version of the libraries.

Not to blame the LLM providers - this was the state of the art when Claude 3.5 Sonnet was released.

This is hilarious because MCP was a protocol meant to overcome this exact problem. You're not supposed to rely on training data. You need the latest updates and the latest changes.

When you're using an SDK, you're better off preventing vulnerabilities if the SDK itself is MCP-able - built with numerous tools, letting the agent off from writing all the code by itself.

That's why the LeanMCP SDK exists. It's the solution to both the developer and agent experience problems.

CLI: Best Practices Through Command-Line Arguments

The LeanMCP CLI isn't just a scaffolding tool. It codifies best practices into simple commands.

leanmcp create my-mcp-server

One command gives you:

  • Proper TypeScript configuration with decorator support
  • Express server with session management
  • Hot reload with tsx watch
  • Example services with @Tool, @Prompt, @Resource decorators
  • Schema validation setup with @SchemaConstraint
  • Production-ready build scripts

Want to add a new service? Another command:

leanmcp add weather

This automatically:

  • Creates the service file with proper structure
  • Registers it in main.ts
  • Includes schema validation examples
  • Follows the same patterns as existing services

The CLI works everywhere:

  • Claude Code terminal
  • Cursor terminal
  • Windsurf terminal
  • Your local terminal
  • Remote servers via SSH

Here's the hilarious part: The CLI itself can be MCPfy-ed. You can wrap it as an MCP tool and use it inside any agent, anywhere. An agent can literally scaffold and generate MCP servers using the MCP protocol itself.

The CLI brings consistency. Every project follows the same structure. Every service uses the same patterns. No more "how did I do this last time?"

Get Started

Open source. MIT License. Free to use.

Install

npm install -g @leanmcp/cli
leanmcp create my-mcp-server
cd my-mcp-server
npm start

Your MCP server is running on http://localhost:8080.

Available Packages

Resources

Building your first MCP? Start with the weather API template. Ready for production? Check the examples folder for Slack integration with auth.

Released under MIT License. Just ship.