> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentfront.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Blog

> Updates, features and explore the world of MCP, AI infrastructure, and the AgentFront ecosystem.

export const posts = [{
  "slug": "nx-plugin",
  "title": "Your MCP Codebase Just Hit 50 Files. Here's How to Stop the Chaos.",
  "description": "@frontmcp/nx brings monorepo-scale development to MCP servers — 16 generators, 7 executors, a 3-layer architecture, multi-platform deployment, and full Nx integration with caching, dependency graphs, and affected commands.",
  "author": "David Antoon",
  "authorEmail": "david@frontegg.com",
  "date": "2026-02-25",
  "readingTime": "15 min",
  "product": "frontmcp",
  "category": "announcement",
  "tags": ["frontmcp", "mcp", "nx", "monorepo"],
  "image": "/assets/banners/nx-plugin/banner.png",
  "imageDark": "",
  "link": "/blog/posts/nx-plugin"
}, {
  "slug": "tool-ui",
  "title": "Beyond Text: How to Render Rich UI Widgets from Your MCP Tools",
  "description": "Transform your MCP tool responses into interactive HTML widgets that work across ChatGPT, Claude, and other AI platforms—with type-safe templates, XSS protection, and automatic platform detection.",
  "author": "David Antoon",
  "authorEmail": "david@frontegg.com",
  "date": "2025-12-19",
  "readingTime": "12 min",
  "product": "frontmcp",
  "category": "guide",
  "tags": ["frontmcp", "mcp", "ui", "widgets"],
  "image": "/assets/banners/tool-ui/banner.png",
  "imageDark": "",
  "link": "/blog/posts/tool-ui"
}, {
  "slug": "deploy-to-vercel",
  "title": "Zero to Production: Deploy Your MCP Server to Vercel in 5 Minutes",
  "description": "A complete guide to deploying FrontMCP servers on Vercel's serverless infrastructure—including Vercel KV for sessions, edge-compatible patterns, and one-command deployment with automatic scaling.",
  "author": "David Antoon",
  "authorEmail": "david@frontegg.com",
  "date": "2025-12-12",
  "readingTime": "8 min",
  "product": "frontmcp",
  "category": "tutorial",
  "tags": ["frontmcp", "mcp", "vercel", "deployment"],
  "image": "/assets/banners/deploy-to-vercel/banner.png",
  "imageDark": "",
  "link": "/blog/posts/deploy-to-vercel"
}, {
  "slug": "agent-as-tool",
  "title": "From 10 Lines to Autonomous Agents: How FrontMCP Turns Any Agent Into an MCP Tool",
  "description": "Learn how FrontMCP's Agent as Tool pattern transforms autonomous AI agents into standard MCP tools—enabling multi-agent orchestration, tool isolation, and LLM-agnostic execution with just a decorator.",
  "author": "David Antoon",
  "authorEmail": "david@frontegg.com",
  "date": "2025-12-05",
  "readingTime": "15 min",
  "product": "frontmcp",
  "category": "guide",
  "tags": ["frontmcp", "mcp", "agents", "multi-agent"],
  "image": "/assets/banners/agent-as-tool/banner.png",
  "imageDark": "",
  "link": "/blog/posts/agent-as-tool"
}, {
  "slug": "codecall-plugin",
  "title": "Your MCP Server Has 100 Tools. Here's Why That's Breaking Your AI Agent.",
  "description": "CodeCall solves the tool explosion problem that's costing you tokens, slowing your agents, and forcing you to build endpoints you shouldn't need. Open source. Self-hosted. Works with any LLM.",
  "author": "David Antoon",
  "authorEmail": "david@frontegg.com",
  "date": "2025-11-22",
  "readingTime": "12 min",
  "product": "frontmcp",
  "category": "guide",
  "tags": ["frontmcp", "mcp", "codecall", "plugins"],
  "image": "/assets/banners/codecall-plugin/code-call-plugin.png",
  "imageDark": "",
  "link": "/blog/posts/codecall-plugin"
}, {
  "slug": "openapi-mcp-security",
  "title": "The OpenAPI-to-MCP Security Nightmare You Didn't Know You Had",
  "description": "Why most OpenAPI-to-MCP tools are leaking your credentials, mixing headers between requests, and routing your customer tokens through someone else's cloud—and how to fix it.",
  "author": "David Antoon",
  "authorEmail": "david@frontegg.com",
  "date": "2025-11-18",
  "readingTime": "18 min",
  "product": "frontmcp",
  "category": "deep-dive",
  "tags": ["frontmcp", "mcp", "security", "openapi"],
  "image": "/assets/banners/openapi-mcp-security.png",
  "imageDark": "",
  "link": "/blog/posts/openapi-mcp-security"
}, {
  "slug": "mcp-run-out-of-socket",
  "title": "Stop Spawning MCP Servers for Every Agent",
  "description": "One server, many agents. How FrontMCP makes multi-agent, multi-app MCP servers the default—with sessions, scoping, auth, DI, and decorators.",
  "author": "David Antoon",
  "authorEmail": "david@frontegg.com",
  "date": "2025-11-11",
  "readingTime": "13 min",
  "product": "frontmcp",
  "category": "deep-dive",
  "tags": ["frontmcp", "mcp", "multi-agent", "architecture"],
  "image": "/assets/banners/mcp-run-out-of-socket.svg",
  "imageDark": "",
  "link": "/blog/posts/mcp-run-out-of-socket"
}, {
  "slug": "introducing-frontmcp",
  "title": "Introducing FrontMCP",
  "description": "The TypeScript-first framework for building production-grade MCP servers with decorators, DI, and Streamable HTTP.",
  "author": "David Antoon",
  "authorEmail": "david@frontegg.com",
  "date": "2025-11-04",
  "readingTime": "6 min",
  "product": "frontmcp",
  "category": "announcement",
  "tags": ["frontmcp", "mcp", "typescript"],
  "image": "/assets/logo/banner.light.png",
  "imageDark": "/assets/logo/banner.dark.png",
  "link": "/blog/posts/introducing-frontmcp"
}];

export const BlogCard = ({author, date, title, link, img, imgDark, time, draft, product, children}) => {
  const PRODUCT_BADGE_COLORS = {
    frontmcp: {
      bg: '#fef3c7',
      text: '#92400e',
      darkBg: '#78350f',
      darkText: '#fde68a'
    },
    enclave: {
      bg: '#dbeafe',
      text: '#1e40af',
      darkBg: '#1e3a5f',
      darkText: '#93c5fd'
    },
    vectoriadb: {
      bg: '#d1fae5',
      text: '#065f46',
      darkBg: '#064e3b',
      darkText: '#6ee7b7'
    },
    general: {
      bg: '#f3f4f6',
      text: '#374151',
      darkBg: '#374151',
      darkText: '#d1d5db'
    }
  };
  const PRODUCT_LABELS = {
    frontmcp: 'FrontMCP',
    enclave: 'EnclaveVM',
    vectoriadb: 'VectoriaDB',
    general: 'General'
  };
  if (draft) {
    return null;
  }
  return <div className="blog-card">
      <a href={link} className="card group relative my-2 ring-2 ring-transparent rounded-2xl
                   bg-white dark:bg-background-dark
                   border border-gray-950/10 dark:border-white/10
                   overflow-hidden w-full cursor-pointer
                   hover:!border-primary dark:hover:!border-primary-light
                   flex flex-col md:flex-row">
        {}
        <div data-component-part="card-image" className="shrink-0">
          {imgDark ? <>
              {}
              <img src={img} alt={title} className="blog-full-image light-img w-full h-full object-cover object-center not-prose" />
              {}
              <img src={imgDark} alt={title} className="blog-full-image dark-img w-full h-full object-cover object-center not-prose" />
            </> : <img src={img} alt={title} className="blog-full-image w-full h-full object-cover object-center not-prose" />}
        </div>

        {}
        <div className="px-6 py-5 relative flex-1" data-component-part="card-content-container">
          {}
          <div id="card-link-arrow-icon" className="absolute text-gray-400 dark:text-gray-500
                       group-hover:text-primary dark:group-hover:text-primary-light
                       top-5 right-5">
            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-arrow-up-right w-4 h-4">
              <path d="M7 7h10v10" />
              <path d="M7 17 17 7" />
            </svg>
          </div>

          <div style={{
    height: 'calc(100% - 1.5rem)'
  }}>
            <div className="prose mt-1 font-normal text-base leading-6
                         text-gray-700 dark:text-gray-300
                         flex flex-col h-full" data-component-part="card-content">
              {product && PRODUCT_BADGE_COLORS[product] && <span className={`blog-product-badge blog-product-badge--${product}`}>
                  {PRODUCT_LABELS[product] || product}
                </span>}
              <h2 data-component-part="card-title" className="not-prose font-semibold text-base text-gray-800 dark:text-white group-hover:text-primary dark:group-hover:text-primary-light">
                {title}
              </h2>

              {children && <span data-as="p">{children}</span>}

              <div className="flex-1" />

              <div className="blog-by text-xs font-medium text-gray-700 dark:text-gray-300 mt-4 text-right">
                <span className="date">{date}</span> · <span className="time">{time}</span> ·{' '}
                <span className="author">{author}</span>
              </div>
            </div>
          </div>
        </div>
      </a>
    </div>;
};

export const BlogIndex = ({posts}) => {
  const PRODUCT_FILTERS = [{
    key: 'all',
    label: 'All'
  }, {
    key: 'frontmcp',
    label: 'FrontMCP'
  }, {
    key: 'enclave',
    label: 'EnclaveVM'
  }, {
    key: 'vectoriadb',
    label: 'VectoriaDB'
  }, {
    key: 'general',
    label: 'General'
  }];
  const [activeFilter, setActiveFilter] = React.useState('all');
  const filtered = activeFilter === 'all' ? posts : posts.filter(p => p.product === activeFilter);
  return <div style={{
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    padding: '2rem 1rem'
  }}>
      <h1 className="text-4xl font-bold mb-4 mt-8 text-gray-900 dark:text-gray-300">Blog</h1>

      <div className="text-lg font-light mb-6 text-gray-800 dark:text-gray-400">
        Explore the world of MCP, AI infrastructure, and the AgentFront ecosystem.
      </div>

      {}
      <div className="blog-filter-bar">
        {PRODUCT_FILTERS.map(({key, label}) => <button key={key} className={`blog-filter-btn ${activeFilter === key ? 'blog-filter-btn--active' : ''}`} onClick={() => setActiveFilter(key)}>
            {label}
          </button>)}
      </div>

      {}
      {filtered.length === 0 ? <div style={{
    textAlign: 'center',
    padding: '3rem 1rem'
  }}>
          <p className="text-gray-500 dark:text-gray-400 text-lg">
            No posts yet for this product. Stay tuned!
          </p>
        </div> : filtered.map(post => <BlogCard key={post.slug} author={post.author} date={new Date(post.date).toLocaleDateString('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  })} time={post.readingTime} title={post.title} email={post.authorEmail} link={post.link} img={post.image} imgDark={post.imageDark || undefined} product={post.product}>
            {post.description}
          </BlogCard>)}
    </div>;
};

<BlogIndex posts={posts} />
