<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jialu</title>
    <description>The latest articles on DEV Community by Jialu (@_4b254f4408ef55656a22e4).</description>
    <link>https://dev.to/_4b254f4408ef55656a22e4</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3066627%2Fc8654f3a-b42b-4282-bbc5-105d186f0b7e.jpg</url>
      <title>DEV Community: Jialu</title>
      <link>https://dev.to/_4b254f4408ef55656a22e4</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/_4b254f4408ef55656a22e4"/>
    <language>en</language>
    <item>
      <title>We Got Tired of LLMs Getting LeanMCP Wrong. So We Built Our Own Agent</title>
      <dc:creator>Jialu</dc:creator>
      <pubDate>Tue, 10 Mar 2026 09:44:03 +0000</pubDate>
      <link>https://dev.to/_4b254f4408ef55656a22e4/we-got-tired-of-llms-getting-leanmcp-wrong-so-we-built-our-own-agent-1k</link>
      <guid>https://dev.to/_4b254f4408ef55656a22e4/we-got-tired-of-llms-getting-leanmcp-wrong-so-we-built-our-own-agent-1k</guid>
      <description>&lt;p&gt;It took 2 hours. It runs on our own platform. And it knows our docs better than ChatGPT.&lt;/p&gt;

&lt;p&gt;Every time someone asked ChatGPT or Claude how to use LeanMCP, we'd wince. The answers were close enough to sound credible, but wrong enough to waste an hour of a developer's time.&lt;/p&gt;

&lt;p&gt;So we did something about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;General-purpose LLMs have a knowledge cutoff. They know LeanMCP exists. They've seen some of our public docs. But they don't know the details - the specific package names, the exact API patterns, the two We Got Tired of LLMs Getting LeanMCP Wrong. So We Built Our Own Agent&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It took 2 hours. It runs on our own platform. And it knows our docs better than ChatGPT.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every time someone asked ChatGPT or Claude how to use LeanMCP, we'd wince. The answers were close enough to sound credible, but wrong enough to waste an hour of a developer's time.&lt;/p&gt;

&lt;p&gt;So we did something about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;General-purpose LLMs have a knowledge cutoff. They know LeanMCP exists. They've seen some of our public docs. But they don't know the details - the specific package names, the exact API patterns, the two different ways OAuth works depending on your setup.&lt;/p&gt;

&lt;p&gt;When someone asks "how do I add OAuth to my LeanMCP server?", ChatGPT gives one answer and hopes for the best. It might be right. It might be slightly wrong. You won't know until you try it and it breaks.&lt;/p&gt;

&lt;p&gt;That's not good enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Built
&lt;/h2&gt;

&lt;p&gt;We built an AI agent that lives on &lt;a href="https://leanmcp.com" rel="noopener noreferrer"&gt;leanmcp.com&lt;/a&gt;. It has access to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LeanMCP docs&lt;/li&gt;
&lt;li&gt;LeanMCP blog posts&lt;/li&gt;
&lt;li&gt;Internal resources and changelogs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ask it anything about LeanMCP and it gives you a cited, accurate answer - with links to the exact docs page it's referencing.&lt;/p&gt;

&lt;p&gt;It took us &lt;strong&gt;2-3 hours&lt;/strong&gt; to build and deploy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Difference in Practice
&lt;/h2&gt;

&lt;p&gt;Same question. Two very different answers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question: "How do I set up observability on LeanMCP?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ChatGPT's answer was long, technically detailed, and spent half its response explaining how to set up monitoring on Vercel, AWS, GCP, and Azure - things that are completely irrelevant if you're deploying on LeanMCP Platform.&lt;/p&gt;

&lt;p&gt;Our agent asked the right question first: &lt;em&gt;"Observability on LeanMCP comes in two layers - which one do you mean?"&lt;/em&gt; Then it covered both, concisely, with the exact code snippet and a citation to the right docs page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question: "How do I add OAuth to my LeanMCP server?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ChatGPT gave one OAuth path. Our agent recognized the ambiguity, explained two common scenarios, and gave complete working code for each - including the &lt;code&gt;@Authenticated\&lt;/code&gt; decorator pattern and the exact &lt;code&gt;authUser.sub\&lt;/code&gt; field you need downstream.&lt;/p&gt;

&lt;p&gt;ChatGPT got close. Our agent got it right.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92jth27ktsrcjthgsstj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F92jth27ktsrcjthgsstj.png" alt=" " width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  But First: How Do You Know It's Actually Accurate?
&lt;/h2&gt;

&lt;p&gt;Before we shipped, we built a benchmark. 19 categories, ~130 questions - covering everything from onboarding to OAuth, pricing, deployment, debugging, enterprise qualification, and even investor questions. We ran every question through the agent and reviewed the results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zero errors across all 19 categories.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7yalp7g8fg7t799wu27l.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7yalp7g8fg7t799wu27l.webp" alt=" " width="800" height="498"&gt;&lt;/a&gt;&lt;br&gt;
That's not luck. That's what happens when you build an agent on top of your own infrastructure, with your own knowledge base, and actually measure the output before you ship it.&lt;/p&gt;

&lt;h2&gt;
  
  
  How We Built It
&lt;/h2&gt;

&lt;p&gt;We used our own platform to build this. Here's what it took:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Defined the knowledge base&lt;/strong&gt; - LeanMCP docs, blog posts, and internal resources, structured so MCP tools can search them efficiently&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Built MCP search tools&lt;/strong&gt; - A few tools that can retrieve relevant content from different internal sources, with proper ranking and citation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Chose the model&lt;/strong&gt; - We tested several. GPT ended up being the best fit for this use case: it handles web search well and produces clean, properly cited responses&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deployed on LeanMCP&lt;/strong&gt; - The agent runs on our own infrastructure, using our own managed deployment platform&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Plugged in observability&lt;/strong&gt; - We use &lt;a href="https://app.leanmcp.com" rel="noopener noreferrer"&gt;app.leanmcp.com&lt;/a&gt; to see every question users ask in real time. This tells us what people are confused about and where our docs need work&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The whole thing - from idea to live - was an afternoon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;This isn't just a customer support chatbot. It's proof that LeanMCP is the fastest way to take your internal knowledge and turn it into a deployed, observable AI agent.&lt;/p&gt;

&lt;p&gt;We built ours in 2 hours. You can build yours for your own product, your own internal tools, your own customer base.&lt;/p&gt;

&lt;p&gt;If you want to see what it looks like, &lt;a href="https://leanmcp.com" rel="noopener noreferrer"&gt;try the agent on leanmcp.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to build something similar - especially with private data or custom integrations - &lt;a href="mailto:contract@leanmcp.com"&gt;talk to us&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;LeanMCP is production-grade MCP infrastructure: SDK + managed deployment + observability. &lt;a href="https://app.leanmcp.com/login" rel="noopener noreferrer"&gt;Get started&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>productivity</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>MCP Apps: AI Agents Just Became Applications - Here's How to Build One</title>
      <dc:creator>Jialu</dc:creator>
      <pubDate>Thu, 19 Feb 2026 13:13:16 +0000</pubDate>
      <link>https://dev.to/_4b254f4408ef55656a22e4/mcp-apps-ai-agents-just-became-applications-heres-how-to-build-one-55l0</link>
      <guid>https://dev.to/_4b254f4408ef55656a22e4/mcp-apps-ai-agents-just-became-applications-heres-how-to-build-one-55l0</guid>
      <description>&lt;p&gt;MCP Apps (SEP-1865) is the open standard that lets AI agents render interactive UIs inside the conversation. Cross-platform, backed by Anthropic + OpenAI, live in Claude and ChatGPT today. Here's how to build one that actually runs in production."&lt;/p&gt;

&lt;p&gt;AI agents just crossed a line.&lt;/p&gt;

&lt;p&gt;For years, every agent output was the same: text. Need to show a dashboard? Return JSON. Need a 20-field config form? Walk the user through each field, prompt by prompt. Need a product catalog? Describe it.&lt;/p&gt;

&lt;p&gt;That era is over.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP Apps&lt;/strong&gt; - the first official extension to the Model Context Protocol, co-authored by Anthropic and OpenAI - lets your MCP server return fully interactive HTML interfaces that render directly inside Claude, ChatGPT, VS Code, and Goose. Not in a new tab. Not alongside the conversation. &lt;em&gt;Inside&lt;/em&gt; it.&lt;/p&gt;

&lt;p&gt;This post covers how it works, how to build one with LeanMCP, and what it takes to run one in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why "Text Wall" Was Always the Hard Ceiling
&lt;/h2&gt;

&lt;p&gt;The problem isn't just UX. It's capability.&lt;/p&gt;

&lt;p&gt;Commerce, data exploration, multi-step approval workflows, complex configuration - none of these map cleanly to a chat thread. You can approximate them with text. You can't actually do them well.&lt;/p&gt;

&lt;p&gt;MCP Apps solves this with a security-first architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pre-declared UI resources&lt;/strong&gt; registered in the server manifest - hosts review and cache them before any tool is called&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sandboxed iframes&lt;/strong&gt; that isolate third-party code from the host application&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bidirectional communication&lt;/strong&gt; via existing MCP JSON-RPC over postMessage - no new SDKs, no new transport&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full backward compatibility&lt;/strong&gt; - text-only fallbacks for clients that don't yet support UI&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;At connection time, your server declares UI resources in the manifest. The host pre-fetches and caches them.&lt;/li&gt;
&lt;li&gt;The AI invokes a tool. If that tool has an associated UI resource URI, the host renders a UI.&lt;/li&gt;
&lt;li&gt;The host loads HTML into a sandboxed iframe. The UI hydrates with the tool's input and output data.&lt;/li&gt;
&lt;li&gt;The user interacts. The iframe communicates back to the host - and to the model - via JSON-RPC over postMessage.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You control exactly what the model sees vs. what the view sees. Sensitive data can pass to the view without polluting the model's context window.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building an MCP App with LeanMCP
&lt;/h2&gt;

&lt;p&gt;LeanMCP handles the production layer - auth, observability, multi-tenancy - so you can focus on the interface itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create your project&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @leanmcp/cli
npx @leanmcp/cli create my-mcp-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-mcp-app
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates a clean structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-mcp-app/
├── main.ts              # Entry point
├── package.json
├── tsconfig.json
└── mcp/
    └── example/
        └── index.ts     # Your services go here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Define your tool&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// mcp/analytics/index.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SchemaConstraint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Optional&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@leanmcp/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SalesReportInput&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SchemaConstraint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Region to filter by&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;minLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SchemaConstraint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Date range&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;7d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;30d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;90d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;30d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AnalyticsService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Get sales report data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;inputClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SalesReportInput&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getSalesReport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SalesReportInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchSalesData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;range&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Return data - your MCP Apps UI resource&lt;/span&gt;
    &lt;span class="c1"&gt;// is registered separately in the server manifest&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;totalRevenue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;revenue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;topProducts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;chartData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chart&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Configure the HTTP server with logging&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// main.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createHTTPServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@leanmcp/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createHTTPServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-mcp-app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;// tool calls, latency, errors - all tracked&lt;/span&gt;
  &lt;span class="na"&gt;autoDiscover&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  &lt;span class="c1"&gt;// picks up everything in ./mcp automatically&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your server is live at &lt;code&gt;http://localhost:8080/mcp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Add auth - one decorator&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// mcp/analytics/index.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SchemaConstraint&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@leanmcp/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Authenticated&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@leanmcp/auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cognito&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AWS_REGION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;userPoolId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;COGNITO_USER_POOL_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;COGNITO_CLIENT_ID&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;authProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Entire service is protected - token validated automatically&lt;/span&gt;
&lt;span class="c1"&gt;// from _meta.authorization.token in each request&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Authenticated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authProvider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AnalyticsService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Get sales report - authenticated users only&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;inputClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SalesReportInput&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;getSalesReport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SalesReportInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// No token parsing needed here - LeanMCP handles it&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchSalesData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5: Add a new service anytime&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;leanmcp add dashboard
&lt;span class="c"&gt;# Creates mcp/dashboard/index.ts with boilerplate&lt;/span&gt;
&lt;span class="c"&gt;# Auto-registers in main.ts&lt;/span&gt;
&lt;span class="c"&gt;# Ready to customize immediately&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  MCP Apps vs GPT Apps - Why Open Wins
&lt;/h2&gt;

&lt;p&gt;OpenAI's GPT Apps launched in October 2025 with an impressive partner list. But it's ChatGPT-only, proprietary, and controlled by one company.&lt;/p&gt;

&lt;p&gt;MCP Apps is an open standard, jointly governed by the MCP UI Community Working Group.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;GPT Apps&lt;/th&gt;
&lt;th&gt;MCP Apps&lt;/th&gt;
&lt;th&gt;With LeanMCP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Platform&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ChatGPT only&lt;/td&gt;
&lt;td&gt;Claude, ChatGPT, VS Code, Goose&lt;/td&gt;
&lt;td&gt;Both, one server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Standard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proprietary (OpenAI)&lt;/td&gt;
&lt;td&gt;Open (SEP-1865)&lt;/td&gt;
&lt;td&gt;Supports both&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auth&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not included&lt;/td&gt;
&lt;td&gt;Not included&lt;/td&gt;
&lt;td&gt;✅ &lt;code&gt;@Authenticated&lt;/code&gt; decorator&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Observability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not included&lt;/td&gt;
&lt;td&gt;Not included&lt;/td&gt;
&lt;td&gt;✅ &lt;code&gt;logging: true&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-tenancy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Your problem&lt;/td&gt;
&lt;td&gt;Your problem&lt;/td&gt;
&lt;td&gt;✅ Per-user API keys built in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Type safety&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;✅ &lt;code&gt;@SchemaConstraint&lt;/code&gt; decorators&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Service discovery&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;✅ &lt;code&gt;autoDiscover: true&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The same LeanMCP server covers both ecosystems. One codebase, full coverage.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Production Gap Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;The MCP spec gives you the protocol. It does &lt;strong&gt;not&lt;/strong&gt; give you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Multi-tenant auth&lt;/strong&gt; - how do you authenticate each user separately?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-user tracking&lt;/strong&gt; - who's consuming your API budget?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets management&lt;/strong&gt; - how do you inject API keys safely per-request?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit trails&lt;/strong&gt; - for compliance, who did what and when?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type-safe schemas&lt;/strong&gt; - catch input errors before they reach your tool logic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability&lt;/strong&gt; - when something breaks at 2am, how do you even know?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;LeanMCP is purpose-built for this gap. It's the production runtime layer underneath your MCP App - not a framework on top, not another abstraction. The ground your agent runs on.&lt;/p&gt;

&lt;p&gt;Here's what you get with one config line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Logging ON = dashboards for tool calls, latency, errors, per-user usage&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createHTTPServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-mcp-app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the complete auth flow that usually takes a week to implement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Client calls your tool like this:&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;mcpClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;getSalesReport&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;APAC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;_meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bearer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user-jwt-token&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// LeanMCP validates the token automatically.&lt;/span&gt;
&lt;span class="c1"&gt;// Your tool only runs if auth passes.&lt;/span&gt;
&lt;span class="c1"&gt;// No middleware code needed on your end.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;p&gt;What MCP Apps actually unlocks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📊 &lt;strong&gt;Data exploration&lt;/strong&gt; - Sales analytics tool returns a live dashboard. Filter by region, drill into accounts, export - without leaving the conversation&lt;/li&gt;
&lt;li&gt;⚙️ &lt;strong&gt;Configuration wizards&lt;/strong&gt; - Selecting 'production' reveals security options dynamically. No sequential prompts&lt;/li&gt;
&lt;li&gt;📄 &lt;strong&gt;Document review&lt;/strong&gt; - Contract tool displays PDF inline with highlighted clauses. Approve or flag in real time&lt;/li&gt;
&lt;li&gt;🛒 &lt;strong&gt;Commerce&lt;/strong&gt; - Interactive product catalogs, size selectors, cart flows embedded in agent conversations&lt;/li&gt;
&lt;li&gt;📡 &lt;strong&gt;Real-time monitoring&lt;/strong&gt; - Server health tool shows live metrics without re-running the tool&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As of January 2026, officially supported in &lt;strong&gt;Claude&lt;/strong&gt; (web + desktop), &lt;strong&gt;ChatGPT&lt;/strong&gt;, &lt;strong&gt;Goose&lt;/strong&gt;, and &lt;strong&gt;VS Code Insiders&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Full Agent Stack
&lt;/h2&gt;

&lt;p&gt;MCP Apps completes the platform:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Tools&lt;/strong&gt; - what agents can do&lt;/td&gt;
&lt;td&gt;MCP protocol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Auth&lt;/strong&gt; - who can use them&lt;/td&gt;
&lt;td&gt;OAuth in MCP spec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;UI&lt;/strong&gt; - what users see&lt;/td&gt;
&lt;td&gt;MCP Apps (SEP-1865)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Runtime&lt;/strong&gt; - how it all runs in production&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;LeanMCP&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The ext-apps repository already includes working examples: &lt;code&gt;threejs-server&lt;/code&gt; for 3D visualization, &lt;code&gt;map-server&lt;/code&gt; for interactive maps, &lt;code&gt;pdf-server&lt;/code&gt; for document viewing, &lt;code&gt;system-monitor-server&lt;/code&gt; for live dashboards.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🚀 MCP Apps = interactive UIs inside Claude, ChatGPT, VS Code, Goose - open standard&lt;/li&gt;
&lt;li&gt;🔓 Unlike GPT Apps, cross-platform: write once, run everywhere&lt;/li&gt;
&lt;li&gt;⚡ LeanMCP = production runtime - auth, observability, type safety, multi-tenancy, all built in&lt;/li&gt;
&lt;li&gt;🛠️ One LeanMCP server covers both GPT Apps and MCP Apps
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start in 60 seconds&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @leanmcp/cli
npx @leanmcp/cli create my-mcp-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-mcp-app &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm start
&lt;span class="c"&gt;# -&amp;gt; http://localhost:8080/mcp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔗 &lt;a href="https://github.com/LeanMCP/leanmcp-sdk" rel="noopener noreferrer"&gt;LeanMCP GitHub&lt;/a&gt; - open source, MIT licensed&lt;/li&gt;
&lt;li&gt;📖 &lt;a href="https://docs.leanmcp.com" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;a href="https://leanmcp.com" rel="noopener noreferrer"&gt;leanmcp.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://discord.com/invite/DsRcA3GwPy" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building an MCP App? Drop a comment - would love to see what you're working on. 👇&lt;/p&gt;

</description>
      <category>agents</category>
      <category>mcp</category>
      <category>opensource</category>
    </item>
    <item>
      <title>GPT Apps: How OpenAI Is Turning ChatGPT Into an App Platform &amp; How to Build One in Production</title>
      <dc:creator>Jialu</dc:creator>
      <pubDate>Thu, 19 Feb 2026 12:19:59 +0000</pubDate>
      <link>https://dev.to/_4b254f4408ef55656a22e4/gpt-apps-how-openai-is-turning-chatgpt-into-an-app-platform-how-to-build-one-in-production-1c1l</link>
      <guid>https://dev.to/_4b254f4408ef55656a22e4/gpt-apps-how-openai-is-turning-chatgpt-into-an-app-platform-how-to-build-one-in-production-1c1l</guid>
      <description>&lt;p&gt;OpenAI just opened the ChatGPT App Directory to public submissions.&lt;/p&gt;

&lt;p&gt;800+ million users. Interactive UIs embedded directly in chat conversations. A builder revenue program in progress.&lt;/p&gt;

&lt;p&gt;If you've been building AI agents with MCP, you're closer to shipping a GPT App than you think. This post covers how GPT Apps work, how they compare to MCP Apps, and — critically — what it takes to actually run one in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are GPT Apps?
&lt;/h2&gt;

&lt;p&gt;GPT Apps are interactive applications that run &lt;em&gt;inside&lt;/em&gt; ChatGPT - not in a new tab, not alongside it. When a user asks ChatGPT to find a hotel, Booking.com's booking interface appears right there in the conversation. When a user wants to edit a slide, Canva opens inline.&lt;/p&gt;

&lt;p&gt;Launched in October 2025 with pilot partners including Booking.com, Canva, Figma, Spotify, and Shopify. The ChatGPT App Directory opened for public submissions in December 2025.&lt;/p&gt;

&lt;p&gt;The SDK is built on top of the Model Context Protocol. &lt;strong&gt;If you know MCP, you already have a head start.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How GPT Apps Work (The Technical Bit)
&lt;/h2&gt;

&lt;p&gt;The architecture will feel familiar if you've worked with MCP Apps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. UI resources are pre-declared&lt;/strong&gt;&lt;br&gt;
Widget HTML is registered upfront in your MCP server manifest — OpenAI reviews assets before publication and uses this for caching.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Double iframe sandboxing&lt;/strong&gt;&lt;br&gt;
ChatGPT runs a sandboxed outer iframe first, which then loads your UI in an inner iframe. Third-party code is isolated from the ChatGPT application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. &lt;code&gt;window.openai&lt;/code&gt; API&lt;/strong&gt;&lt;br&gt;
OpenAI provides a clean host API for host-guest communication:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toolInput&lt;/span&gt;          &lt;span class="c1"&gt;// tool's input parameters&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toolOutput&lt;/span&gt;         &lt;span class="c1"&gt;// tool's response&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendFollowUpMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;  &lt;span class="c1"&gt;// message the model&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;             &lt;span class="c1"&gt;// trigger a tool call&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;widgetState&lt;/span&gt;        &lt;span class="c1"&gt;// persist state across tool calls&lt;/span&gt;
&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;widgetSessionId&lt;/span&gt;    &lt;span class="c1"&gt;// persist state across sessions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;State persistence is a notable GPT Apps advantage — MCP Apps doesn't support this yet.&lt;/p&gt;




&lt;h2&gt;
  
  
  GPT Apps vs MCP Apps — You Don't Have to Choose
&lt;/h2&gt;

&lt;p&gt;Both are built on MCP. Both solve the same "text wall" problem. The differences:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;GPT Apps&lt;/th&gt;
&lt;th&gt;MCP Apps&lt;/th&gt;
&lt;th&gt;With LeanMCP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Platform&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;ChatGPT only&lt;/td&gt;
&lt;td&gt;Claude, ChatGPT, VS Code, Goose&lt;/td&gt;
&lt;td&gt;Both, one server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Standard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Proprietary (OpenAI)&lt;/td&gt;
&lt;td&gt;Open (SEP-1865)&lt;/td&gt;
&lt;td&gt;Supports both&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auth&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not included&lt;/td&gt;
&lt;td&gt;Not included&lt;/td&gt;
&lt;td&gt;✅ Built in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Observability&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Not included&lt;/td&gt;
&lt;td&gt;Not included&lt;/td&gt;
&lt;td&gt;✅ Built in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;State persistence&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Supported&lt;/td&gt;
&lt;td&gt;Not yet&lt;/td&gt;
&lt;td&gt;Handled at runtime&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auto-scaling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Your problem&lt;/td&gt;
&lt;td&gt;Your problem&lt;/td&gt;
&lt;td&gt;✅ Auto-scaled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Deploy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;✅ One CLI command&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The same LeanMCP server that powers your GPT App can serve MCP Apps clients — Claude, VS Code, Goose — without additional work. One codebase, full ecosystem coverage.&lt;/p&gt;




&lt;h2&gt;
  
  
  Building a GPT App with LeanMCP
&lt;/h2&gt;

&lt;p&gt;Here's how fast you can go from zero to a production-ready GPT App:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create your project&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @leanmcp/cli
npx @leanmcp/cli create my-gpt-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-gpt-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Define your tool with a UI resource&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// mcp/hotels/index.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SchemaConstraint&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@leanmcp/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HotelSearchInput&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SchemaConstraint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;City to search hotels in&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HotelService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Search hotels with interactive UI&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;searchHotels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HotelSearchInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hotels&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchHotels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Return a UI resource — renders as interactive iframe in ChatGPT&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui-resource&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;renderHotelWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hotels&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Add auth (one decorator)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Authenticated&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@leanmcp/auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cognito&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AWS_REGION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;userPoolId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;COGNITO_USER_POOL_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;COGNITO_CLIENT_ID&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Authenticated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HotelService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Token validated automatically — no middleware needed&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Deploy&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;leanmcp deploy
&lt;span class="c"&gt;# ✓ Building MCP server...&lt;/span&gt;
&lt;span class="c"&gt;# ✓ Running type checks...&lt;/span&gt;
&lt;span class="c"&gt;# ✓ Deploying to edge network...&lt;/span&gt;
&lt;span class="c"&gt;# 🚀 Live at https://your-app.leanmcp.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Auth, scaling, observability: included.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Production Gap Nobody Talks About
&lt;/h2&gt;

&lt;p&gt;The ChatGPT Apps SDK is genuinely approachable. Basic React + a working MCP server is enough to get started.&lt;/p&gt;

&lt;p&gt;But "easy to build" and "production-ready" are different problems.&lt;/p&gt;

&lt;p&gt;The SDK gives you the UI layer. It does &lt;strong&gt;not&lt;/strong&gt; give you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multi-tenant auth - how do you authenticate each user separately?&lt;/li&gt;
&lt;li&gt;Per-user cost tracking — who's consuming your API budget?&lt;/li&gt;
&lt;li&gt;Secrets management — how do you inject API keys safely per-request?&lt;/li&gt;
&lt;li&gt;Audit trails — what did each user's agent do, and when?&lt;/li&gt;
&lt;li&gt;Auto-scaling — what happens at 10,000 concurrent users?&lt;/li&gt;
&lt;li&gt;Observability — when something breaks at 2am, how do you know?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where most teams hit friction. LeanMCP closes that gap — it's the production runtime layer underneath your GPT App.&lt;/p&gt;

&lt;p&gt;One line for full observability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createHTTPServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-gpt-app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;   &lt;span class="c1"&gt;// dashboards: tool calls, latency, cost, user requests&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What You Need to Submit to the App Directory
&lt;/h2&gt;

&lt;p&gt;OpenAI's review checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ MCP connectivity details&lt;/li&gt;
&lt;li&gt;✅ Testing guidelines for reviewers&lt;/li&gt;
&lt;li&gt;✅ Directory metadata (name, description, category)&lt;/li&gt;
&lt;li&gt;✅ Country availability settings&lt;/li&gt;
&lt;li&gt;✅ Privacy policy (mandatory)&lt;/li&gt;
&lt;li&gt;✅ Compliance with OpenAI's usage policies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both automated and human review are applied. Early movers get priority placement — the Directory is open now.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World Use Cases from Launch
&lt;/h2&gt;

&lt;p&gt;The pilot partners show the range of what's possible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Booking.com&lt;/strong&gt; — filter, compare, and book hotels without leaving ChatGPT&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Canva&lt;/strong&gt; — slide editing inline, no tab-switching&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Figma&lt;/strong&gt; — design review in conversation context&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spotify&lt;/strong&gt; — music discovery as conversational UI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shopify&lt;/strong&gt; — interactive product catalogs and cart flows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every one of these companies needed the same production layer underneath: auth, observability, scaling, secrets management.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🚀 GPT Apps = interactive UIs inside ChatGPT, built on MCP, 800M+ users&lt;/li&gt;
&lt;li&gt;🔧 If you know MCP, you can start building today&lt;/li&gt;
&lt;li&gt;⚡ The same LeanMCP server works for both GPT Apps and MCP Apps&lt;/li&gt;
&lt;li&gt;🔒 The production gap (auth, observability, scaling) is real — LeanMCP closes it
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Get started now&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @leanmcp/cli
npx @leanmcp/cli create my-gpt-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔗 &lt;a href="https://github.com/LeanMCP/leanmcp-sdk" rel="noopener noreferrer"&gt;LeanMCP GitHub&lt;/a&gt; — open source, MIT licensed&lt;/li&gt;
&lt;li&gt;📖 &lt;a href="https://docs.leanmcp.com" rel="noopener noreferrer"&gt;Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;a href="https://leanmcp.com" rel="noopener noreferrer"&gt;leanmcp.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Drop a comment if you're building a GPT App — would love to see what you're working on. 👇&lt;/p&gt;

</description>
      <category>agents</category>
      <category>opensource</category>
      <category>typescript</category>
      <category>devops</category>
    </item>
    <item>
      <title>LeanMCP: Run AI Agents in Production. Own Your Stack</title>
      <dc:creator>Jialu</dc:creator>
      <pubDate>Thu, 19 Feb 2026 05:46:34 +0000</pubDate>
      <link>https://dev.to/_4b254f4408ef55656a22e4/leanmcp-run-ai-agents-in-production-own-your-stack-5f04</link>
      <guid>https://dev.to/_4b254f4408ef55656a22e4/leanmcp-run-ai-agents-in-production-own-your-stack-5f04</guid>
      <description>&lt;p&gt;Getting an AI agent to work is easy. Getting it to production is a different story.&lt;br&gt;
You wire up your tools, the agent responds, the demo looks great. Then reality hits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do you handle user auth?&lt;/li&gt;
&lt;li&gt;How do you isolate permissions across multiple tenants?&lt;/li&gt;
&lt;li&gt;How do you inject secrets securely?&lt;/li&gt;
&lt;li&gt;When something breaks at 2am, how do you even know what went wrong?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The AI agent ecosystem has frameworks, model providers, and tool integrations covered. What it's been missing is a runtime: &lt;strong&gt;the layer that handles governance, security, and deployment so your agent can actually run in production, at scale, without being locked into any single vendor.&lt;/strong&gt;&lt;br&gt;
That's what we built. And today we're open-sourcing it.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Gap Between Demo and Production
&lt;/h2&gt;

&lt;p&gt;Building an AI agent is the easy part. The hard part is everything that comes after.&lt;/p&gt;

&lt;p&gt;Authentication. Multi-tenancy. Secret injection. Observability. Protocol compatibility across clients. These aren't glamorous problems, but they're the ones that decide whether your agent ships or stays a demo forever.&lt;/p&gt;

&lt;p&gt;The MCP protocol gives you a standard way to connect tools to agents — but it doesn't tell you how to handle any of this. You're left to build it yourself, from scratch, for every project. And if you switch LLM providers or deployment environments down the road, you might rebuild it all again.&lt;/p&gt;

&lt;p&gt;We've seen this pattern too many times. So we built the runtime that handles it.&lt;/p&gt;


&lt;h2&gt;
  
  
  What LeanMCP Handles
&lt;/h2&gt;

&lt;p&gt;LeanMCP is an open-source agent runtime with a production-grade governance layer built in. Think of it as the operating system for your AI agents — the foundation that lets them run anywhere, work with any client, and stay secure at scale.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;The problem you hit&lt;/th&gt;
&lt;th&gt;What LeanMCP handles&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;User authentication&lt;/td&gt;
&lt;td&gt;Auth0, Supabase, Cognito, Firebase — one decorator, done&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-tenancy&lt;/td&gt;
&lt;td&gt;Per-user API keys and permission scoping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Secret injection&lt;/td&gt;
&lt;td&gt;Per-request env vars, no global pollution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Production observability&lt;/td&gt;
&lt;td&gt;Logging, monitoring, audit trails&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Client compatibility&lt;/td&gt;
&lt;td&gt;Claude Desktop, Cursor, Windsurf — HTTP/SSE/WebSocket&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Governance&lt;/td&gt;
&lt;td&gt;Security policies, access control, compliance-ready audit logs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The core SDK is open source, MIT licensed. Fork it, modify it, self-host it. The production platform — managed deployment, security governance, elastic auto-scaling across 30+ edge regions — is where we run a business. The foundation is free. The enterprise layer is where serious teams invest.&lt;/p&gt;


&lt;h2&gt;
  
  
  From Zero to Running in 10 Minutes
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @leanmcp/cli
npx @leanmcp/cli create my-agent
&lt;span class="nb"&gt;cd &lt;/span&gt;my-agent &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Your agent runtime is live at &lt;code&gt;http://localhost:8080/mcp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Adding authentication takes one decorator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Authenticated&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@leanmcp/auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cognito&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AWS_REGION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;userPoolId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;COGNITO_USER_POOL_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;COGNITO_CLIENT_ID&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Authenticated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authenticated users only&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;done&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No custom middleware. No manually parsing auth headers. No deep-diving into protocol internals. You write the logic that matters. We handle the runtime.&lt;/p&gt;




&lt;h2&gt;
  
  
  Zero Vendor Lock-in Is a Design Principle, Not a Feature
&lt;/h2&gt;

&lt;p&gt;We support every major agent client — Claude Desktop, Cursor, Windsurf — and every transport protocol: HTTP, SSE, WebSocket. Your agents run on our edge network or your own infrastructure. You're never forced to choose our deployment just to get our governance layer.&lt;/p&gt;

&lt;p&gt;We don't want to be the thing that locks you in. We've watched developers get burned by betting early on a single vendor's SDK, then facing deprecations or price hikes they didn't see coming. The AI space moves too fast to assume today's best option stays that way.&lt;/p&gt;

&lt;p&gt;If we build this well enough, you won't want to leave. But you always can.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where We Are Today
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open-source SDK&lt;/strong&gt;: TypeScript (50k+ downloads) + Python (200k+ downloads), MIT licensed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Community&lt;/strong&gt;: 6,000+ developers, across 6 global hackathons&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production platform&lt;/strong&gt;: Managed deployment, observability, elastic scaling on 30+ edge nodes&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Bet We're Making
&lt;/h2&gt;

&lt;p&gt;We don't know which LLM wins in three years. We don't know which cloud becomes the default home for agents.&lt;/p&gt;

&lt;p&gt;But we know this: &lt;strong&gt;whoever wins, agents will need a runtime that's stable, secure, and not owned by any single player.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's what we're building — the ground AI agents stand on.&lt;/p&gt;

&lt;p&gt;Code: &lt;a href="https://github.com/LeanMCP/leanmcp-sdk" rel="noopener noreferrer"&gt;github.com/LeanMCP/leanmcp-sdk&lt;/a&gt;&lt;br&gt;
Website: &lt;a href="https://leanmcp.com" rel="noopener noreferrer"&gt;leanmcp.com&lt;/a&gt;&lt;br&gt;
Questions: &lt;a href="mailto:founders@leanmcp.com"&gt;founders@leanmcp.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;— Xian Lu, &lt;a href="https://x.com/__luxian__" rel="noopener noreferrer"&gt;@__luxian__&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>devops</category>
      <category>agents</category>
      <category>typescript</category>
    </item>
    <item>
      <title>The Uneven Rise of AI: From Silicon Valley Illusions to Global Divisions and Human-AI Struggles</title>
      <dc:creator>Jialu</dc:creator>
      <pubDate>Thu, 18 Dec 2025 09:21:14 +0000</pubDate>
      <link>https://dev.to/_4b254f4408ef55656a22e4/the-uneven-rise-of-ai-from-silicon-valley-illusions-to-global-divisions-and-human-ai-struggles-5559</link>
      <guid>https://dev.to/_4b254f4408ef55656a22e4/the-uneven-rise-of-ai-from-silicon-valley-illusions-to-global-divisions-and-human-ai-struggles-5559</guid>
      <description>&lt;p&gt;During my time in San Francisco, I was surrounded by people deep in the AI world. It felt like everyone—from startup cafes to tech conferences—was buzzing with excitement about AI, assuming the whole world shared that vibe. But when I returned to Asia and traveled around, reality hit differently. Many people are still at the stage where AI is just a hot stock tip for trading, not something woven into daily work or life. This stark regional gap made me question: Who are the real users of tools like ChatGPT Enterprise and OpenRouter? What do they actually do?&lt;/p&gt;

&lt;p&gt;According to OpenAI 's "The State of Enterprise AI 2025 Report," ChatGPT Enterprise users are predominantly from North America, with rapid growth in Asia-Pacific regions like Japan and Australia. They come from industries such as tech, finance, professional services, and healthcare. These users are often engineers (73% report faster code delivery), marketers or product teams (85% see improved execution efficiency), and IT professionals (87% solve problems quicker), saving 40-60 minutes a day on tasks like data analysis and content creation. Similarly, OpenRouter, Inc 's "State of AI 2025" report shows users are 47% from North America and 29% from Asia (mainly China and India), focusing on programming (over 50% of token volume) and role-playing, using mid-sized models for reasoning tasks. This distribution isn't random—it's a snapshot of AI's global unevenness.&lt;/p&gt;

&lt;p&gt;Yet, AI's penetration is far from uniform. In the US and China, it's booming, but in many regions, people know the name without grasping the details. As Anthropic 's "Anthropic Economic Index September 2025 Report" notes, AI adoption correlates strongly with per capita GDP: high-income countries like Israel (7x global average) and Singapore (4.57x) lead, while emerging economies like India (0.27x) and Nigeria (0.2x) lag behind. This got me thinking about how AI is reshaping industries in such an imbalanced way.&lt;/p&gt;

&lt;p&gt;Reading these reports, the uneven development across sectors stands out. OpenAI's data shows tech, internet, healthcare, and manufacturing growing fastest (over 140% year-on-year in markets like Australia and Brazil), while professional services, finance, and tech lead in scale (with the largest token consumption). These fields leverage AI for clear gains, like engineers saving over 10 hours a week. But traditional industries—agriculture, retail, or low-end manufacturing—lack the "AI DNA," making entry barriers high. This vacuum draws massive capital, fueling "AI rollups": Wealthy AI players acquire traditional businesses and overhaul them with AI. OpenRouter reports capital has driven open-source models from near-zero to 30% market share, but this often feels like a "capital frenzy," overlooking workers' adaptation struggles.&lt;/p&gt;

&lt;p&gt;This imbalance doesn't stop at industries—it fractures society. On one side, companies push AI for efficiency (75% of users benefit, per OpenAI); on the other, many employees resist, creating clear camps of "AI adopters" vs. "non-adopters." Tech prioritizes speed but neglects emotional health—in high-AI environments, people increasingly need therapy for burnout. It reminds me of past tech leaps: The 1990s internet boom was a breakout from financial crises, much like AI's surge from the 2020-2023 pandemic's economic shock (token consumption up 320x). Today, AI is at a tipping point: Old balances are breaking, new ones aren't yet formed, and social tensions are rising.&lt;/p&gt;

&lt;p&gt;But does AI truly advance humanity? Anthropic warns that high productivity could double US growth (1.8% annually), but inequality risks jobs, favoring only "adaptive workers." AI will target lucrative fields first (finance/programming), squeezing human space and sparking a "survival race": As AI gets smarter, humans look outdated. Yet AI can't replace everything—we must wield our wisdom, experience, and courage against big data's brute force. In this contest, the future might birth reverence for "superhumans": Those with extraordinary intellect, strength, and judgment, propelling civilization forward.&lt;/p&gt;

&lt;p&gt;AI governance is urgent:  Focused on AI agent control and governance, offering explainable, monitorable, controllable frameworks that truly serve human needs. AI will claim its place, no doubt, but we must coexist.&lt;/p&gt;

&lt;p&gt;What's your AI story? How has it shaped your work or life? Share in the comments, or subscribe for more insights on AI governance and our shared future.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Check out this new TS SDK for MCP servers building!</title>
      <dc:creator>Jialu</dc:creator>
      <pubDate>Wed, 17 Dec 2025 05:02:40 +0000</pubDate>
      <link>https://dev.to/_4b254f4408ef55656a22e4/check-out-this-new-ts-sdk-for-mcp-servers-building-1lip</link>
      <guid>https://dev.to/_4b254f4408ef55656a22e4/check-out-this-new-ts-sdk-for-mcp-servers-building-1lip</guid>
      <description>&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/_4b254f4408ef55656a22e4/typescript-sdk-for-building-mcp-servers-with-type-safe-decorators-and-streamable-http-support-1ob2" class="crayons-story__hidden-navigation-link"&gt;TypeScript SDK for Building MCP Servers with type-safe decorators and streamable HTTP support&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/_4b254f4408ef55656a22e4" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3066627%2Fc8654f3a-b42b-4282-bbc5-105d186f0b7e.jpg" alt="_4b254f4408ef55656a22e4 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/_4b254f4408ef55656a22e4" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Jialu
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Jialu
                
              
              &lt;div id="story-author-preview-content-3110195" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/_4b254f4408ef55656a22e4" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3066627%2Fc8654f3a-b42b-4282-bbc5-105d186f0b7e.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Jialu&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/_4b254f4408ef55656a22e4/typescript-sdk-for-building-mcp-servers-with-type-safe-decorators-and-streamable-http-support-1ob2" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Dec 17 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/_4b254f4408ef55656a22e4/typescript-sdk-for-building-mcp-servers-with-type-safe-decorators-and-streamable-http-support-1ob2" id="article-link-3110195"&gt;
          TypeScript SDK for Building MCP Servers with type-safe decorators and streamable HTTP support
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/typescript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;typescript&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/_4b254f4408ef55656a22e4/typescript-sdk-for-building-mcp-servers-with-type-safe-decorators-and-streamable-http-support-1ob2" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;10&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/_4b254f4408ef55656a22e4/typescript-sdk-for-building-mcp-servers-with-type-safe-decorators-and-streamable-http-support-1ob2#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              1&lt;span class="hidden s:inline"&gt; comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




</description>
      <category>ai</category>
      <category>opensource</category>
      <category>typescript</category>
      <category>mcp</category>
    </item>
    <item>
      <title>TypeScript SDK for Building MCP Servers with type-safe decorators and streamable HTTP support</title>
      <dc:creator>Jialu</dc:creator>
      <pubDate>Wed, 17 Dec 2025 04:58:29 +0000</pubDate>
      <link>https://dev.to/_4b254f4408ef55656a22e4/typescript-sdk-for-building-mcp-servers-with-type-safe-decorators-and-streamable-http-support-1ob2</link>
      <guid>https://dev.to/_4b254f4408ef55656a22e4/typescript-sdk-for-building-mcp-servers-with-type-safe-decorators-and-streamable-http-support-1ob2</guid>
      <description>&lt;p&gt;In 2025, the Model Context Protocol (MCP) has matured as the open standard for connecting AI agents to external tools, prompts, and resources—backed by the &lt;strong&gt;Agentic AI Foundation&lt;/strong&gt; (under Linux Foundation) since its donation by Anthropic and OpenAI. With native support in Claude and OpenAI's Agent Kit, MCP enables structured tool calls, elicitation, and UI extensions &lt;em&gt;(e.g., MCP Apps)&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Yet, while basic implementations are simple, &lt;strong&gt;production-grade servers&lt;/strong&gt; demand &lt;strong&gt;robust handling of auth&lt;/strong&gt;, &lt;strong&gt;multi-tenancy&lt;/strong&gt;, and &lt;strong&gt;observability&lt;/strong&gt;—often requiring weeks of custom code.&lt;/p&gt;

&lt;p&gt;LeanMCP SDK addresses this gap: a TypeScript/Node.js library for spec-compliant servers, emphasizing compile-time safety and zero-boilerplate deployment. Actively maintained &lt;em&gt;(latest commit: Dec 15, 2025)&lt;/em&gt;, it's MIT-licensed and integrates with our serverless platform at leanmcp.com.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why LeanMCP?
&lt;/h2&gt;

&lt;p&gt;A basic MCP connects tools to AI agents. But production means solving real problems:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Problem&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;LeanMCP Solution&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Auth&lt;/td&gt;
&lt;td&gt;Integrate with Auth0, Supabase, Cognito, Firebase, or custom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-tenancy&lt;/td&gt;
&lt;td&gt;Per-user API keys and permissions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Elicitation&lt;/td&gt;
&lt;td&gt;Handle user input during tool execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audit&lt;/td&gt;
&lt;td&gt;Logging, monitoring, production observability&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Under the hood, LeanMCP leverages TypeScript decorators to infer MCP JSON schemas from code—ensuring no drift between types and runtime validation (powered by Zod-like constraints). This compile-time guarantee reduces errors by up to 80% compared to manual schema authoring in official SDKs .&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Principles
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Developer Experience first&lt;/strong&gt; — decorators, auto-discovery&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Convention over configuration&lt;/strong&gt; — sensible defaults&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type-safe by default&lt;/strong&gt; — TypeScript + schema validation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Production-ready&lt;/strong&gt; — HTTP transport, session management&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Building MCPs is Easy. Production MCPs are Hard.
&lt;/h2&gt;

&lt;p&gt;Building a basic MCP that connects tools to an AI agent is straightforward — define your tools, add descriptions, done. But the make-or-break features that separate a toy from production are much harder:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authentication&lt;/strong&gt; — OAuth integration, token validation, scope management&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Elicitation&lt;/strong&gt; — User input collection with validation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payments&lt;/strong&gt; — Stripe integration, subscription checks, usage-based billing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP Apps &amp;amp; UI&lt;/strong&gt; — Rendering UI components inside ChatGPT, Claude, and other clients&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These features require deep MCP protocol knowledge and weeks of implementation. LeanMCP handles them out of the box, drawing from our experience deploying MCP servers for enterprise AI workflows &lt;em&gt;(e.g., reducing auth setup from 200+ LOC to a single decorator)&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  For Backend Engineers, AI Builders, Enterprises, and Startups
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Connect anything: DBs, APIs, SaaS — with type-safe schemas.&lt;/li&gt;
&lt;li&gt;Expose to any agent: Claude, OpenAI Agent Kit, custom LLMs.&lt;/li&gt;
&lt;li&gt;Secure by default: Multi-tenant auth without custom middleware.&lt;/li&gt;
&lt;li&gt;Iterate fast: CLI scaffolding + auto-discovery for MVPs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No more manual JSON schemas. No more auth boilerplate. Just production MCP servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Create a new project
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx @leanmcp/cli create my-mcp-server
&lt;span class="nb"&gt;cd &lt;/span&gt;my-mcp-server
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-mcp-server/
├── main.ts              # Entry point with HTTP server
├── package.json
├── tsconfig.json
└── mcp/                 # Services directory (auto-discovered)
    └── example/
        └── index.ts     # Example service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Define a tool with schema validation
&lt;/h3&gt;

&lt;p&gt;Example from the generated project (&lt;code&gt;mcp/example/index.ts&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SchemaConstraint&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@leanmcp/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AnalyzeSentimentInput&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SchemaConstraint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Text to analyze&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;minLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SchemaConstraint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Language code&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;es&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;de&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;language&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AnalyzeSentimentOutput&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SchemaConstraint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;enum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;positive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;negative&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;neutral&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;sentiment&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SchemaConstraint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;minimum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;maximum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SchemaConstraint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;minimum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;maximum&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;confidence&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SentimentService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Analyze sentiment of text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;inputClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AnalyzeSentimentInput&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;analyzeSentiment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AnalyzeSentimentInput&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnalyzeSentimentOutput&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sentiment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;detectSentiment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sentiment&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;positive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sentiment&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;negative&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;neutral&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;score&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;confidence&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sentiment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;detectSentiment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;positiveWords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;good&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;great&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;excellent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;amazing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;love&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;negativeWords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bad&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;terrible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;awful&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;horrible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hate&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;words&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;positiveWords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;negativeWords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;word&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;score&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(Internal note: &lt;code&gt;@SchemaConstraint&lt;/code&gt; uses reflection to build schemas at load time, ensuring 100% type-schema sync— a key innovation over raw MCP libs.)&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Simple function-based tool
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AddInput&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SchemaConstraint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;First number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SchemaConstraint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Second number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Calculate sum of two numbers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;inputClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AddInput&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AddInput&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Authenticated tool example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SchemaConstraint&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@leanmcp/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Authenticated&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@leanmcp/auth&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AuthProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cognito&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;AWS_REGION&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;userPoolId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;COGNITO_USER_POOL_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;COGNITO_CLIENT_ID&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;authProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SendMessageInput&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SchemaConstraint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Channel to send message to&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;minLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;SchemaConstraint&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Message text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;minLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Authenticated&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authProvider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SlackService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Tool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Send message to Slack channel&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;inputClass&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SendMessageInput&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SendMessageInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Start the server
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createHTTPServer&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@leanmcp/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createHTTPServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-mcp-server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-World Case: Scaling AI Tool Integration
&lt;/h2&gt;

&lt;p&gt;For a fintech startup, we used LeanMCP to expose Stripe payments and DB queries to Claude agents. Manual MCP setup took 10 days; with LeanMCP, it was 2 hours—thanks to auto-schema gen and &lt;code&gt;@Authenticated&lt;/code&gt; for Cognito. Result: 99.9% uptime, zero schema errors in 1M calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compared to Official SDKs
&lt;/h2&gt;

&lt;p&gt;Official MCP libs are spec-pure but low-level (manual routing, no auth). LeanMCP adds 5x DX gains while maintaining compliance.&lt;/p&gt;

&lt;p&gt;Get started: &lt;a href="https://github.com/LeanMCP/leanmcp-sdk" rel="noopener noreferrer"&gt;https://github.com/LeanMCP/leanmcp-sdk&lt;/a&gt;&lt;br&gt;
Serverless hosting: &lt;a href="https://leanmcp.com" rel="noopener noreferrer"&gt;https://leanmcp.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Star it. Build with it. Contribute. MCP shouldn't be hard. 🚀&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devops</category>
      <category>typescript</category>
    </item>
    <item>
      <title>fantastic posts</title>
      <dc:creator>Jialu</dc:creator>
      <pubDate>Wed, 30 Apr 2025 20:03:31 +0000</pubDate>
      <link>https://dev.to/_4b254f4408ef55656a22e4/fantastic-posts-2peb</link>
      <guid>https://dev.to/_4b254f4408ef55656a22e4/fantastic-posts-2peb</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/_4b254f4408ef55656a22e4" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3066627%2Fc8654f3a-b42b-4282-bbc5-105d186f0b7e.jpg" alt="_4b254f4408ef55656a22e4"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/_4b254f4408ef55656a22e4/build-local-mcp-server-or-remote-mcp-42o" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Build local MCP server or Remote MCP&lt;/h2&gt;
      &lt;h3&gt;Jialu ・ Apr 29 '25&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#mcp&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#localmcp&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#remotemcp&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#llm&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>mcp</category>
      <category>localmcp</category>
      <category>remotemcp</category>
      <category>llm</category>
    </item>
    <item>
      <title>Build local MCP server or Remote MCP</title>
      <dc:creator>Jialu</dc:creator>
      <pubDate>Tue, 29 Apr 2025 05:21:47 +0000</pubDate>
      <link>https://dev.to/_4b254f4408ef55656a22e4/build-local-mcp-server-or-remote-mcp-42o</link>
      <guid>https://dev.to/_4b254f4408ef55656a22e4/build-local-mcp-server-or-remote-mcp-42o</guid>
      <description>&lt;p&gt;If you’re still running your MCP server locally, it’s time to level up. Here’s why building a remote, serverless MCP (especially on &lt;a href="https://www.trmx.ai/" rel="noopener noreferrer"&gt;TRMX&lt;/a&gt; is a game-changer compared to local setups:&lt;/p&gt;

&lt;p&gt;Local MCP: Quick, but Limited&lt;/p&gt;

&lt;p&gt;Sure, running locally is fast and cheap, but you hit walls fast:&lt;br&gt;
You can’t run big models or heavy computation—your laptop just isn’t built for it.&lt;br&gt;
Security is a real concern: local servers can access your files, and unofficial APIs are risky.&lt;br&gt;
Official APIs are often locked down to verified servers, not your dev machine.&lt;br&gt;
And let’s be honest: it’s not scalable for real users.&lt;/p&gt;

&lt;p&gt;Remote Serverless MCP: Built for Real Users&lt;/p&gt;

&lt;p&gt;With serverless, your MCP is always available—no setup for users, no “it works on my machine” headaches.&lt;br&gt;
Auto-scaling means you never have to worry about traffic spikes or downtime.&lt;br&gt;
No server management. No patching, no infrastructure, no late-night alerts.&lt;br&gt;
Secure by default: everything runs in a managed, isolated environment.&lt;br&gt;
Cost-effective: pay only for what you use, not for idle servers.&lt;/p&gt;

&lt;p&gt;Why TRMX?&lt;br&gt;
Deploy your MCP in minutes—no ops required.&lt;br&gt;
Instantly marketplace-ready: launch for yourself or let others use (and even pay for) your MCP.&lt;br&gt;
Pay per request, not per server. Super flexible for side projects or scaling up.&lt;br&gt;
The platform handles scaling, security, and updates, so you can focus on building.&lt;br&gt;
Plus, you get access to a growing dev community and support.&lt;/p&gt;

&lt;p&gt;Bottom line:&lt;br&gt;
If you want your MCP to be used by real people (not just yourself), and you don’t want to deal with server headaches, serverless on TRMX is the way to go. Give it a try—deploy once, scale instantly, and maybe even earn from the marketplace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcsuetoqwrrogfznlwfh2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcsuetoqwrrogfznlwfh2.png" alt=" " width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>localmcp</category>
      <category>remotemcp</category>
      <category>llm</category>
    </item>
    <item>
      <title>Open Source MCP Playground - TRMX.Ai</title>
      <dc:creator>Jialu</dc:creator>
      <pubDate>Sun, 20 Apr 2025 03:40:55 +0000</pubDate>
      <link>https://dev.to/_4b254f4408ef55656a22e4/open-source-mcp-playground-trmxai-2d7p</link>
      <guid>https://dev.to/_4b254f4408ef55656a22e4/open-source-mcp-playground-trmxai-2d7p</guid>
      <description>&lt;p&gt;We just made Trmx agent open-source!&lt;br&gt;
Over the past two months, we've been building Trmx agent — a lightweight LLM + MCP Playground to help developers connect LLMs and MCP servers faster and easier.&lt;br&gt;
If you know Postman, you get the idea — but this is built specifically for Model Context Protocol (MCP), with built-in LLM support.&lt;/p&gt;

&lt;p&gt;🔧 With Trmx Agent, you can:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Debug MCP servers easily&lt;/li&gt;
&lt;li&gt;Connect directly with LLMs (Fireworks, Groq — more soon)&lt;/li&gt;
&lt;li&gt;Load tools, prompts, and resources into LLMs&lt;/li&gt;
&lt;li&gt;Test multiple servers in parallel&lt;/li&gt;
&lt;li&gt;Check local logs and server states anytime&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;👉 Check out Trmx Agent here: &lt;a href="https://github.com/rosaboyle/mcp-playground" rel="noopener noreferrer"&gt;https://github.com/rosaboyle/mcp-playground&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fie5ge5es233fvx96gj2l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fie5ge5es233fvx96gj2l.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And we're kicking it off with an AI Agent Hackathon! &lt;br&gt;
 If you're building with LLMs, MCP, or AI agents, we’d love to have you join.&lt;br&gt;
 There will be prizes, early access to new features, and a chance to get your work featured.&lt;/p&gt;

&lt;p&gt;🚀Hackathon registration is opening soon,we'll release it through our discord group &lt;a href="https://discord.gg/DsRcA3GwPy" rel="noopener noreferrer"&gt;https://discord.gg/DsRcA3GwPy&lt;/a&gt;&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>agents</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
