[{"data":1,"prerenderedAt":566},["ShallowReactive",2],{"blog-/en/mcp-server-faster-image-ingest":3,"blog-related-/en/mcp-server-faster-image-ingest":404},{"id":4,"title":5,"author":6,"body":7,"date":387,"description":388,"extension":389,"image":390,"meta":391,"navigation":392,"path":393,"seo":394,"stem":395,"tags":396,"__hash__":403},"blog/en/mcp-server-faster-image-ingest.md","The same AI build went from 30 minutes to 4 — here's what we changed in our MCP server","Martin Swoboda",{"type":8,"value":9,"toc":379},"minimark",[10,20,23,35,42,45,50,53,61,64,71,75,78,84,114,117,127,136,143,147,150,239,242,249,268,271,275,281,292,302,306,309,316,327,334,338,344,347,350,370,375],[11,12,13,14,19],"p",{},"We build a lot of sites by prompt. It's the whole point of shipping a CMS with a ",[15,16,18],"a",{"href":17},"/docs/developer/mcp","native MCP server",": you point Claude at a finished HTML page, and it comes back as a component-driven site with every headline, link and image editable.",[11,21,22],{},"So we did what you should always do with your own product — we sat down and timed it.",[11,24,25,26,30,31,34],{},"Our original build recipe took around ",[27,28,29],"strong",{},"30 minutes"," for a single landing page. We rewrote it, cut the redundant steps, and got that to ",[27,32,33],{},"14 minutes",". Good progress. But then we looked at where those 14 minutes actually went, and the answer was uncomfortable.",[11,36,37,38,41],{},"The site itself — fifteen components, a layout, a page, all wired up — took ",[27,39,40],{},"3 minutes 40 seconds."," The remaining ten minutes were five images. Fourteen kilobytes of them.",[11,43,44],{},"Five small images cost nearly three times more than the entire rest of the site. That's not a slow step you optimise. That's a design flaw, and no amount of prompt tuning was going to fix it — it had to be fixed in the server.",[46,47,49],"h2",{"id":48},"why-images-were-slow-it-isnt-what-youd-guess","Why images were slow (it isn't what you'd guess)",[11,51,52],{},"The obvious theory is network or storage. It was neither — it was the AI.",[11,54,55,56,60],{},"When an agent uploads a file through a tool call, the bytes travel as base64 text — and that text has to be ",[57,58,59],"em",{},"generated by the model, token by token",". A 5 KB image becomes roughly 7,000 characters the model has to type out, one piece at a time. The CMS wasn't slow. The upload was slow because a language model was laboriously spelling out a picture.",[11,62,63],{},"It was also fragile in a way that's genuinely hard to debug. One of our test files failed twice with a padding error. The cause turned out to be a long run of repeated characters inside the base64 getting collapsed somewhere in transit — the server received 1,621 characters where 1,624 were sent. It doesn't fail loudly at the transport layer; it shows up much later as a corrupt-file error that points you at entirely the wrong problem.",[11,65,66,67,70],{},"The second issue was quieter but bigger in aggregate: ",[27,68,69],{},"our API was too chatty."," Every write returned the full saved record. Save a page with eleven elements and you got back every element's complete component definition — template, CSS, JavaScript, form schema — repeated once per element. That's about 55 KB of JSON echoing back content the caller had just sent. Multiply across a whole build and the majority of the token cost wasn't instructions. It was us talking to ourselves.",[46,72,74],{"id":73},"what-we-shipped","What we shipped",[11,76,77],{},"Two changes, both at the protocol level.",[11,79,80,83],{},[27,81,82],{},"1. Images can now be ingested inline."," Instead of uploading a file and then wiring its ID into your content, you put the URL directly in the element data:",[85,86,91],"pre",{"className":87,"code":88,"language":89,"meta":90,"style":90},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\"data\": {\n  \"image\": { \"sourceUrl\": \"https://example.com/studio.jpg\" }\n}\n","json","",[92,93,94,102,108],"code",{"__ignoreMap":90},[95,96,99],"span",{"class":97,"line":98},"line",1,[95,100,101],{},"\"data\": {\n",[95,103,105],{"class":97,"line":104},2,[95,106,107],{},"  \"image\": { \"sourceUrl\": \"https://example.com/studio.jpg\" }\n",[95,109,111],{"class":97,"line":110},3,[95,112,113],{},"}\n",[11,115,116],{},"The server fetches it, stores it, and substitutes the real file ID — inside the same save, on the same transaction. No base64. No separate upload step. The bytes never pass through the model at all.",[11,118,119,122,123,126],{},[27,120,121],{},"2. Responses can be quiet."," Every write tool now takes an optional ",[92,124,125],{},"verbose: false",":",[85,128,130],{"className":87,"code":129,"language":89,"meta":90,"style":90},"{ \"id\": 53 }\n",[92,131,132],{"__ignoreMap":90},[95,133,134],{"class":97,"line":98},[95,135,129],{},[11,137,138,139,142],{},"That's the whole response now, instead of three kilobytes. For pages and layouts you still get back the element ID mapping — the one thing the caller genuinely can't work out for itself — and nothing else. It defaults to ",[92,140,141],{},"true",", so nothing breaks for anyone already calling it.",[46,144,146],{"id":145},"the-numbers","The numbers",[11,148,149],{},"Same page, same components, same five images, three points in the journey:",[151,152,153,171],"table",{},[154,155,156],"thead",{},[157,158,159,162,165,168],"tr",{},[160,161],"th",{},[160,163,164],{},"Original recipe",[160,166,167],{},"Rewritten recipe",[160,169,170],{},"After the server changes",[172,173,174,191,208,224],"tbody",{},[157,175,176,180,183,186],{},[177,178,179],"td",{},"Full build with images",[177,181,182],{},"~30 min",[177,184,185],{},"~14 min",[177,187,188],{},[27,189,190],{},"4 min 0 s",[157,192,193,196,199,202],{},[177,194,195],{},"Image phase",[177,197,198],{},"~10 min",[177,200,201],{},"10 min 25 s",[177,203,204,207],{},[27,205,206],{},"0 s"," — folded into the page save",[157,209,210,213,216,219],{},[177,211,212],{},"Tokens",[177,214,215],{},"—",[177,217,218],{},"~225,000",[177,220,221],{},[27,222,223],{},"~40,000",[157,225,226,229,231,234],{},[177,227,228],{},"Tool calls",[177,230,215],{},[177,232,233],{},"21 + uploads",[177,235,236],{},[27,237,238],{},"19",[11,240,241],{},"Worth separating those two jumps honestly, because they're different kinds of work.",[11,243,244,245,248],{},"Getting from 30 to 14 minutes was ",[27,246,247],{},"prompt engineering"," — fewer redundant calls, better use of defaults, dropping steps that existed out of superstition. Useful, but we'd taken it about as far as it went.",[11,250,251,252,255,256,259,260,263,264,267],{},"Getting from 14 to 4 was ",[27,253,254],{},"protocol work",", and it's the bigger result: roughly ",[27,257,258],{},"3.5× faster and 6× cheaper"," on an identical build. The saving comes from deleting a phase rather than speeding one up. Because a page can now be created ",[57,261,262],{},"with"," its elements ",[57,265,266],{},"and"," resolve image URLs in one call, the sequence went from \"create empty page → upload five files → write everything back\" to a single save.",[11,269,270],{},"Which is the general lesson for anyone building agent tooling: once you've tidied the prompt, the remaining cost is almost always in the API's shape, not the agent's instructions.",[46,272,274],{"id":273},"why-this-matters-if-you-build-on-neleto","Why this matters if you build on Neleto",[11,276,277,280],{},[27,278,279],{},"Your agent runs cost less."," Token usage on a standard page build dropped by roughly 85%. If you're running builds repeatedly — client sites, templates, a course, a test suite — that's the difference between an experiment and something you do routinely.",[11,282,283,286,287,291],{},[27,284,285],{},"There's one less way to break your content."," Our element data is replace-semantics: send a partial update and the omitted values are cleared. The old image workflow forced a second write pass over content you'd already saved, which is exactly the situation where that bites. We managed to blank an entire page's text this way during testing — every section still rendered, just empty. With inline ingest there is no second pass, so the trap is gone. (It's the same class of silent failure we built ",[15,288,290],{"href":289},"/blog/self-verifying-ai","self-verifying checks"," to catch — deleting the failure mode outright is even better than catching it.)",[11,293,294,297,298,301],{},[27,295,296],{},"It composes with everything else."," ",[92,299,300],{},"sourceUrl"," accepts any URL the server can reach: a client's existing media library, a CDN, a generated image, or a file already in Neleto. For an agency migrating a site, that means images can move over in the same call that creates the page.",[46,303,305],{"id":304},"the-honest-part","The honest part",[11,307,308],{},"A few edges worth knowing before you hit them.",[11,310,311,312,315],{},"Inline ingest needs a URL the ",[57,313,314],{},"server"," can reach. If your images only exist on your laptop, you still need to get them somewhere hosted first — the base64 path still exists for small files, and it's fine at a few KB. It's large payloads where it falls apart.",[11,317,318,319,322,323,326],{},"There's also a rough edge we found in our own API while testing this: a file's ",[92,320,321],{},"serveUrl"," returns a 400 if you fetch it bare, without a scaling query string appended. Which means the most obvious thing you'd try — ingesting from a file already in your Neleto media library — fails unless you add ",[92,324,325],{},"?options=w_800,f_webp",". We're fixing it. Until then, append the options.",[11,328,329,330,333],{},"And one lesson that isn't about images at all. The inline ingest worked the instant it deployed, because element data is free-form — no contract change. The ",[92,331,332],{},"verbose"," flag needed a schema change, and schemas are negotiated once when a client connects, so it stayed invisible to our own editor until we reconnected. If you build MCP tooling: behaviour-level changes reach agents immediately, schema-level ones need a client round-trip. Plan your rollouts accordingly.",[46,335,337],{"id":336},"try-it","Try it",[11,339,340,341,343],{},"Both changes are live. If you're already connected to the Neleto MCP server, inline ingest works right now — put a URL where a file ID goes. For ",[92,342,332],{},", reconnect your client so it picks up the updated schema.",[11,345,346],{},"If you haven't built a site by prompt yet, this is a decent moment. The slowest, most fragile part of the workflow just stopped existing.",[348,349],"hr",{},[11,351,352,297,355,359,360,364,365,369],{},[27,353,354],{},"Try it yourself:",[15,356,358],{"href":357},"/pricing","start a free Neleto project",", point an agent at it, and drop an image URL straight into the element data — watch the whole upload phase disappear. ",[15,361,363],{"href":362},"/features","That's what a native MCP server is for",", and if you want the deep dive on how it works, ",[15,366,368],{"href":367},"/blog/mcp-server-explained","we wrote one",".",[11,371,372],{},[27,373,374],{},"Fast websites. Easy content. AI native.",[376,377,378],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":90,"searchDepth":104,"depth":104,"links":380},[381,382,383,384,385,386],{"id":48,"depth":104,"text":49},{"id":73,"depth":104,"text":74},{"id":145,"depth":104,"text":146},{"id":273,"depth":104,"text":274},{"id":304,"depth":104,"text":305},{"id":336,"depth":104,"text":337},"2026-09-07","Uploading images was the slowest, most fragile part of building a site with an AI agent. We fixed it at the protocol level. Here's what changed in Neleto's MCP server, and the before/after numbers.","md","/img/blog/mcp-server-faster-image-ingest.svg",{},true,"/en/mcp-server-faster-image-ingest",{"title":5,"description":388},"en/mcp-server-faster-image-ingest",[397,398,399,400,401,402],"Neleto","MCP","AI","Agents","Build in Public","Performance","FMvoYd56CGZOhax3jfbJ9yh56zOaRkAUPw1x_O0DKCw",[405,407,418,425,436,445,455,465,475,484,493,503,513,521,532,541,551,558],{"path":393,"title":5,"description":388,"date":387,"author":6,"image":390,"tags":406},[397,398,399,400,401,402],{"path":408,"title":409,"description":410,"date":411,"author":6,"image":412,"tags":413},"/en/full-cms-vs-headless","Full CMS vs Headless: Why All-in-One Wins for Most of the Web","Headless earned its reputation for real reasons. Here's the honest trade-off — and why, for most sites, a complete CMS is the better deal.","2026-08-31","/img/blog/full-cms-vs-headless.svg",[414,415,416,398,417,397],"Comparison","CMS","Headless","EU Hosting",{"path":419,"title":420,"description":421,"date":422,"author":6,"image":423,"tags":424},"/en/self-verifying-ai","The AI That Checks Its Own Work","Most AI-plus-CMS setups write content through an API and hope it rendered. Neleto closes the loop three ways — typed structured output, LSP template checks before publish, and the agent opening your live page to see what it actually built. Here's how each layer works, and where a human still has to look.","2026-08-24","/img/blog/self-verifying-ai.svg",[397,399,398,400,401,415],{"path":426,"title":427,"description":428,"date":429,"author":6,"image":430,"tags":431},"/en/five-plugins-built-in","Five New Neleto Plugins — Built In, Not Bolted On","Search, comments, Google reviews, SEO/accessibility audits, and galleries — five new plugins that run inside your Neleto instance on your EU server, with no third-party scripts and no extra subscriptions. Here's what each does, and where the edges are.","2026-08-17","/img/blog/five-plugins-built-in.svg",[397,432,415,401,433,434,435],"Plugins","SEO","Search","DSGVO",{"path":437,"title":438,"description":439,"date":440,"author":6,"image":441,"tags":442},"/en/why-neleto-runs-on-rust","Why Neleto Runs on Rust (And the Benchmarks to Prove It)","The honest story behind choosing Rust for a CMS backend — real single-instance benchmarks (11 ms TTFB, ~9,400 req/s, 78 MB RAM) and the parts that actually cost us: slower dev, harder hiring, younger libraries.","2026-08-10","/img/blog/why-neleto-runs-on-rust.svg",[397,443,402,444,401],"Rust","Benchmarks",{"path":446,"title":447,"description":448,"date":449,"author":6,"image":450,"tags":451},"/en/page-builder-walkthrough","Building a Landing Page in Neleto: A Real Walkthrough (Mouse and Prompt)","I built the same landing page twice — once by hand in our visual builder, once by prompting Claude through our MCP server — and timed both. Here's exactly what happened, including the bits that were slower than I'd like.","2026-07-27","/img/blog/page-builder-walkthrough.svg",[397,452,415,398,453,454],"Page Builder","AI CMS","No-Code",{"path":456,"title":457,"description":458,"date":459,"author":6,"image":460,"tags":461},"/en/mcp-connectors","Connect Neleto to Anything: The Native MCP Server and Connector Ecosystem","Your CMS shouldn't be an island. Here's how Claude, Cursor, and Windsurf talk to your content directly — and where it goes next.","2026-07-20","/img/blog/mcp-connectors.svg",[398,462,399,463,464,397,415],"Connectors","Claude Code","Cursor",{"path":466,"title":467,"description":468,"date":469,"author":6,"image":470,"tags":471},"/en/wordpress-migration-walkthrough","Migrating a 40-Page Site Off WordPress: An Honest, Start-to-Finish Walkthrough","The content migration took under an hour. The full cutover — domain, DNS, redirects, forms, QA — took the better part of a day. Here's every step, every gotcha, and the parts the migration guides skip.","2026-07-13","/img/blog/wordpress-migration-walkthrough.svg",[472,473,415,474,417,397],"WordPress","Migration","GDPR",{"path":476,"title":477,"description":478,"date":479,"author":6,"image":480,"tags":481},"/en/html-to-editable-cms","I turned a static HTML page into an editable CMS site with one prompt","Web designers lose days rebuilding finished designs as a CMS. Here's how Neleto's native MCP server does it from a single prompt — animations, custom cursor and all.","2026-07-06","/img/blog/html-to-editable-cms.svg",[398,482,483,463,415,397],"AI Agents","Web Design",{"path":485,"title":486,"description":487,"date":488,"author":6,"image":489,"tags":490},"/en/console-launch-free-tier","Neleto Console Is Live — and the Free Tier Is Open","Sign up at console.neleto.io, get a real CMS, and pay us nothing. Here's why we built it that way.","2026-06-29","/img/blog/console-launch-free-tier.svg",[401,397,491,492,417,415],"Free Tier","Self-Serve",{"path":494,"title":495,"description":496,"date":497,"author":6,"image":498,"tags":499},"/en/mcp-server-explained","MCP Server Explained: The Deep Dive","How the Model Context Protocol enables secure, native AI agent interaction with your applications — and why native implementation matters.","2026-06-22","/img/blog/mcp-server-explained.svg",[398,500,501,482,502],"MCP Server","Model Context Protocol","AI Integration",{"path":504,"title":505,"description":506,"date":507,"author":6,"image":508,"tags":509},"/en/neleto-vs-contentful","Neleto vs Contentful: Which CMS Should You Choose in 2026?","A practical comparison for developers, agencies, and growing businesses — covering pricing, performance, AI integration, editor experience, and EU compliance.","2026-06-16","/img/blog/neleto-vs-contentful.svg",[397,510,511,512,453],"Contentful","Headless CMS","CMS Comparison",{"path":514,"title":515,"description":516,"date":517,"author":6,"image":518,"tags":519},"/en/agentic-traffic-surpassed-humans","Bots Just Out-Numbered Us: What the Agentic Web Means for Your CMS","Cloudflare says AI agents now drive the majority of web traffic — 18 months early. Here's why that changes how you publish content, and what to do about it.","2026-06-08","/img/blog/agentic-traffic-surpassed-humans.svg",[520,482,398,415,397],"Agentic Web",{"path":522,"title":523,"description":524,"date":525,"author":6,"image":526,"tags":527},"/en/glw-gmbh-case-study","Modernizing a 40-Year Family Business: GLW GmbH's New Website with Neleto","How we delivered a fast, multilingual, and CRM-integrated website for a leading German cable processing specialist — in close collaboration with agency Inhalt.","2026-06-05","/img/blog/glw-gmbh-case-study.svg",[528,529,397,530,531],"Case Study","Customer Story","CRM Integration","Custom Plugin",{"path":533,"title":534,"description":535,"date":536,"author":6,"image":537,"tags":538},"/en/eu-hosting-compliance","Why EU Hosting Compliance Matters for Your Website","Data sovereignty, GDPR, and choosing the right infrastructure in 2026","2026-06-01","/img/blog/eu-hosting-compliance.svg",[474,417,539,540,397],"Data Compliance","Privacy",{"path":542,"title":543,"description":544,"date":545,"author":6,"image":546,"tags":547},"/en/buergerstiftung-ravensburg","Bürgerstiftung Ravensburg: A Modern Website for Community Impact with Neleto","How we built a clear, fast, and emotionally engaging website for a regional community foundation using Neleto CMS — in close collaboration with agency Inhalt.","2026-05-29","/img/blog/buergerstiftung-ravensburg.svg",[528,548,549,397,550],"Nonprofit","Foundation","Website",{"path":552,"title":553,"description":554,"date":555,"author":6,"image":556,"tags":557},"/en/what-is-mcp","What is the Model Context Protocol (MCP)?","The new standard connecting AI agents to your tools and data","2026-05-25","/img/blog/what-is-mcp.svg",[398,399,501,482,415],{"path":559,"title":560,"description":561,"date":562,"author":6,"image":563,"tags":564},"/en/why-neleto-exists","Why Neleto Exists","The CMS Built for Speed, Simplicity, and the AI Era","2026-05-18","/img/blog/why-neleto-exists.svg",[415,399,565,402,397],"Web Development",1788961306020]