<?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: Pierre- Laurent Medori</title>
    <description>The latest articles on DEV Community by Pierre- Laurent Medori (@pierrelaurentmedori).</description>
    <link>https://dev.to/pierrelaurentmedori</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4022967%2F06fd4098-6c66-4406-b44d-43d0e63b179f.png</url>
      <title>DEV Community: Pierre- Laurent Medori</title>
      <link>https://dev.to/pierrelaurentmedori</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pierrelaurentmedori"/>
    <language>en</language>
    <item>
      <title>Privacy by design at the binary level: no ghost SDK in your build</title>
      <dc:creator>Pierre- Laurent Medori</dc:creator>
      <pubDate>Fri, 17 Jul 2026 07:15:20 +0000</pubDate>
      <link>https://dev.to/goodbarber/privacy-by-design-at-the-binary-level-no-ghost-sdk-in-your-build-1bl0</link>
      <guid>https://dev.to/goodbarber/privacy-by-design-at-the-binary-level-no-ghost-sdk-in-your-build-1bl0</guid>
      <description>&lt;p&gt;Most apps ship with passengers nobody invited: trackers, analytics and ad SDKs baked into the binary by default. We took the problem the other way around: nothing ships unless the app's owner explicitly turned it on. Here's the engineering, down to the compilation flags.&lt;/p&gt;

&lt;p&gt;Quick context: GoodBarber is a no-code app builder (running since 2011). Customers configure an app in a web back office and the platform compiles real native builds, Swift for iOS and Kotlin for Android, plus a PWA. The people who own these apps will never open Xcode. Which makes the question sharper: who decides what code ends up in their binary?&lt;/p&gt;

&lt;h2&gt;
  
  
  The ghost SDK problem
&lt;/h2&gt;

&lt;p&gt;A ghost SDK is any library that lives in an app's binary without the app's maker having chosen it. The pattern is everywhere, no-code or not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Template runtimes.&lt;/strong&gt; Many app factories compile every app from the same master project. Every feature the platform supports, and every SDK behind it, ships in every binary, used or not.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transitive passengers.&lt;/strong&gt; An SDK pulls its own dependencies. You added a video player; you also got its analytics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default-on integrations.&lt;/strong&gt; Analytics and crash reporting wired in "for your own good", opt-out at best.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why it matters, concretely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Data can move without anyone deciding it.&lt;/strong&gt; An embedded SDK is code that runs with your users, and some of it phones home whether or not the feature is used.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Attack surface.&lt;/strong&gt; Every library is code you now answer for, including its CVEs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Weight.&lt;/strong&gt; Dead SDKs are dead bytes on every install.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You can't answer the stores honestly.&lt;/strong&gt; Apple's privacy manifests and Google Play's Data safety form ask what your app collects. If you don't know what's inside your binary, you're guessing on a compliance document.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The industry default is opt-out. We think a binary should be opt-in.&lt;/p&gt;

&lt;h2&gt;
  
  
  A library ships only if the feature is on
&lt;/h2&gt;

&lt;p&gt;We call the model &lt;strong&gt;on-demand embedded code&lt;/strong&gt;, and the principle fits in one sentence: a library is embedded in the binary only if the corresponding feature is activated in the app.&lt;/p&gt;

&lt;p&gt;How it actually works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Every app has a feature graph.&lt;/strong&gt; Sections, extensions, monetization, push, integrations: the back office knows exactly what an app uses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The graph drives conditional compilation.&lt;/strong&gt; At build time, the feature graph toggles compilation flags (pragmas) that include or exclude whole modules and third-party SDKs from the project. Off doesn't mean disabled or dormant. It means the code is not compiled in at all.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Privacy Center is the control tower.&lt;/strong&gt; One place where the app's owner sees what runs in their app and decides what is allowed to.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Builds happen on demand.&lt;/strong&gt; We don't recompile on every toggle. A binary is generated when it's needed, typically when an update is about to be submitted to the stores, with exactly what the app's current configuration requires. For the owner this is transparent: they configure, we tailor the build.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On iOS, for example: AdMob is in the binary only if ads are enabled. The Facebook SDK, only if that integration is on. Even the in-app purchase stack (our StoreKit integration) stays out of the build unless in-app purchases are part of the app.&lt;/p&gt;

&lt;p&gt;The consequence is easy to state and rare in practice: the app doesn't just &lt;em&gt;declare&lt;/em&gt; less, it &lt;em&gt;contains&lt;/em&gt; less.&lt;/p&gt;

&lt;p&gt;And it's measurable. An &lt;strong&gt;Apps for Kids&lt;/strong&gt; build, which by construction embeds none of these third-party SDKs, weighs about &lt;strong&gt;a third of a full-featured build&lt;/strong&gt; (from our build data, July 2026).&lt;/p&gt;

&lt;h2&gt;
  
  
  The data question: hosted by us, in Europe
&lt;/h2&gt;

&lt;p&gt;A clean binary is half the story. The other half is where the data lives.&lt;/p&gt;

&lt;p&gt;GoodBarber is its own hosting provider. Customer and end-user data is hosted exclusively on our servers in Europe, and it does not leave the EU. No hyperscaler region to audit, no transfer mechanism to squint at: sovereignty here is one company, one jurisdiction. That baseline is what makes GDPR (and Germany's stricter BDSG) tractable for the small teams who build on the platform.&lt;/p&gt;

&lt;p&gt;Consent gets the same treatment. For apps that do turn on ads or analytics, the platform ships an integrated CMP supporting the IAB Transparency &amp;amp; Consent Framework v2, plus Google Funding Choices for ad-monetized apps. So what is in the binary is disclosed, and consented to, per user and per purpose.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this changes at store review
&lt;/h2&gt;

&lt;p&gt;Apple's privacy manifests and Play's Data safety form stop being archaeology. Our privacy declarations are fed by the same source of truth as the build itself: the feature graph. What we declare is what we compiled, because both derive from the same place. There is no "wait, what does that SDK actually collect?" moment, because an SDK nobody chose is not in the build to begin with.&lt;/p&gt;

&lt;p&gt;The extreme case proves the model: &lt;strong&gt;Apps for Kids&lt;/strong&gt;. One declaration in the back office marks an app as a kids' title (Apple Kids Category, Google Play Designed for Families), and the platform disables every feature incompatible with those programs: third-party analytics, behavioral ads, intrusive permissions. The build that comes out is compliant by construction, because compliance is enforced where it's real: in what gets compiled.&lt;/p&gt;

&lt;p&gt;Now the honest limits, because a claim like "nothing you didn't invite" deserves its footnotes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The iOS push stack is always there.&lt;/strong&gt; Our pipeline has never been wired to produce an iOS binary without push. Nobody ever needed that build, so that path doesn't exist. If you never use push, its code is still in your binary.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Clean" means no uninvited third parties, not zero code.&lt;/strong&gt; GoodBarber's own runtime is in every build. The difference: we own it, we answer for it, and it is one vendor you already chose.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;We don't make your app compliant by magic.&lt;/strong&gt; What owners collect through their own content (forms, orders, accounts) is their responsibility. We ship a clean binary, honest declarations and the consent tooling; the rest is theirs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;If you build a platform that compiles other people's apps, the transferable pattern is this: derive everything from one feature graph. Binary contents, privacy declarations, consent configuration, all from the same source of truth. The moment two of those are maintained by hand, they drift, and drift in privacy is how ghost SDKs are born.&lt;/p&gt;

&lt;p&gt;More on the platform's privacy stance: &lt;a href="https://www.goodbarber.com/privacy-compliance/" rel="noopener noreferrer"&gt;goodbarber.com/privacy-compliance&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Questions in the comments. I'll answer with build-level details where I can.&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>nocode</category>
      <category>ios</category>
      <category>android</category>
    </item>
    <item>
      <title>Building a production MCP server: How we made GoodBarber agent-ready (without the glue code)</title>
      <dc:creator>Pierre- Laurent Medori</dc:creator>
      <pubDate>Wed, 15 Jul 2026 12:10:40 +0000</pubDate>
      <link>https://dev.to/goodbarber/building-a-production-mcp-server-how-we-made-goodbarber-agent-ready-without-the-glue-code-4co6</link>
      <guid>https://dev.to/goodbarber/building-a-production-mcp-server-how-we-made-goodbarber-agent-ready-without-the-glue-code-4co6</guid>
      <description>&lt;p&gt;We wanted an AI agent to manage a real production app (its content, its catalog, its push notifications) natively, not through screenshots and simulated clicks. So we built an MCP server. Here's the whole thing: why, how, a real session, and where it still falls short.&lt;/p&gt;

&lt;p&gt;One line of context so the rest makes sense: GoodBarber is a no-code app builder (running since 2011). Customers configure an app in a web back office; the platform compiles native iOS and Android builds plus a PWA. The question we set out to answer: can an AI agent &lt;a href="https://dev.to/goodbarber/the-first-interface-you-dont-have-to-learn-1f9b"&gt;operate one of those apps, end to end, the way its owner does&lt;/a&gt;?&lt;/p&gt;

&lt;h2&gt;
  
  
  We already had APIs. That wasn't the point.
&lt;/h2&gt;

&lt;p&gt;The platform has had APIs for years. Exposing endpoints was never the problem. The problem was that every "connect your assistant" integration is custom glue: tool definitions written for one vendor, an auth flow, retry logic, docs written for a model to read. Then you do it all again for the next assistant. The classic N×M integration mess: N assistants × M platforms.&lt;/p&gt;

&lt;p&gt;The Model Context Protocol (introduced by Anthropic in November 2024, donated to the Linux Foundation in late 2025) standardizes exactly the parts we kept rewriting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Discovery.&lt;/strong&gt; The client asks the server what tools exist; no hardcoded catalog on the agent side.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Typing.&lt;/strong&gt; Every tool ships a JSON Schema; the model knows what arguments are legal before it calls.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auth.&lt;/strong&gt; OAuth is part of the protocol conversation, not a bespoke setup doc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The practical difference is blunt: with a classic API, you write an integration for each agent. With an MCP server, any MCP client (Claude, ChatGPT, Claude Code, Cursor, n8n) connects and figures out how to drive the app on its own. We shipped one server and got every current and future MCP client for free.&lt;/p&gt;

&lt;p&gt;So the goal was never "another API". It was: make the app itself drivable by an agent. Here's how that's wired.&lt;/p&gt;

&lt;h2&gt;
  
  
  The architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Claude · ChatGPT · Cursor · n8n        (any MCP client)
      │      natural language → typed tool calls
      ▼
GoodBarber MCP server (hosted)         https://mcp.goodbarber.dev/mcp/sse
      │      OAuth 2 sign-in · scoped to *your* app
      ▼
Platform APIs                          CMS · push · shop · orders · customers · stats
      ▼
Your live app                          iOS · Android · PWA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To be clear up front: &lt;strong&gt;the server itself is a hosted GoodBarber service, not an open-source package you install.&lt;/strong&gt; What's open source is the Skills layer (below). The reproducible part for you as a reader is the connection: plug the endpoint into an MCP client, sign in, and an agent is operating a live app a couple of minutes later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tool design.&lt;/strong&gt; Tools are namespaced by domain (&lt;code&gt;cms_*&lt;/code&gt;, &lt;code&gt;shop_*&lt;/code&gt;, &lt;code&gt;classic_*&lt;/code&gt;) and map one-to-one onto what the back office can do. The full machine-readable inventory is public in the &lt;a href="https://mcp.goodbarber.dev/.well-known/mcp/server-card.json" rel="noopener noreferrer"&gt;server card&lt;/a&gt;: 150 tools at the time of writing (July 2026). That card is the contract: when the platform grows, the card grows, and connected agents pick up the new tools automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scoping.&lt;/strong&gt; Sign-in is OAuth 2, and every session is scoped to the authenticated customer's app. An agent connected to app A cannot see or touch app B. Agencies running several client apps connect each one separately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server-side guardrails.&lt;/strong&gt; Two design decisions we'd defend in any review:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Forced read-back on writes.&lt;/strong&gt; Every write returns &lt;code&gt;_mcp_policy.verification_required: true&lt;/code&gt;. The agent is expected to re-read the object it just created or changed and confirm the result. Hallucinated success is the failure mode we fear most.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feature gating.&lt;/strong&gt; An app that doesn't have push configured doesn't expose push tools at all. Agents can't call what isn't there.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The open-source layer: 44 Claude Skills.&lt;/strong&gt; On top of the server we publish &lt;a href="https://github.com/goodbarber/goodbarber-skills" rel="noopener noreferrer"&gt;&lt;code&gt;goodbarber-skills&lt;/code&gt;&lt;/a&gt;: 44 open-source Claude Skills, plain markdown recipes that wrap common workflows (create a product with variants, schedule a push campaign, refund an order…). Two distinct artifacts: the server is the live connection; the Skills are curated entry points that call it. The repo is deliberately white-label-friendly, so agencies can rebrand and redistribute it.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real session: an agent managing an e-commerce catalog
&lt;/h2&gt;

&lt;p&gt;Enough theory. A real task, run from Claude with the server connected:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Add a black "Storm" T-shirt at €29 in S, M and L, put it in the Summer 2026 collection, and schedule a push for 6 p.m. announcing the drop.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What the agent actually does:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;shop_list_collections      → resolves "Summer 2026" to a collection id
shop_create_product        → creates the product (name, €29, collection)
                             ← verification_required: true
shop_get_product           → read-back: confirms the product exists as intended
shop_create_variant  ×3    → S, M, L
shop_create_push_broadcast → drafts the push, scheduled for 18:00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then it stops and shows me the push copy before anything is scheduled: interactive clients like Claude ask before executing writes. The agent does the plumbing (id resolution, argument formatting, sequencing, verification); I approve what goes out. In the back office this task is a dozen screens; by conversation it's one prompt and one approval.&lt;/p&gt;

&lt;p&gt;Nothing in the session is Claude-specific: the same flow works from ChatGPT connectors, Claude Code, or Cursor. And because the tools are typed, the failure mode is honest: pass a malformed price and you get a schema error back, not a silently broken product.&lt;/p&gt;

&lt;h2&gt;
  
  
  What doesn't work (yet)
&lt;/h2&gt;

&lt;p&gt;The honest list, because this is the part most write-ups skip:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No design tools, on purpose.&lt;/strong&gt; The server covers operations: content, catalog, campaigns, orders, stats. Layout and design stay in the builder. We don't believe pushing visual design through text-shaped tools produces good apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-app tool subsets surprise agents.&lt;/strong&gt; Feature gating means two apps expose different tool lists. Correct behavior, but an agent following a generic recipe can look for a tool that isn't there. The Skills handle this; raw prompting sometimes doesn't.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Writes are chatty by design.&lt;/strong&gt; Forced read-back costs tokens and latency on every mutation. We accept the trade: verified writes beat fast fiction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One thing we chose &lt;strong&gt;not&lt;/strong&gt; to build into the server: a mandatory approval flow. How much autonomy an agent gets is the operator's decision, made in the client. Interactive assistants like Claude ask before they act; the same tools, &lt;a href="https://www.goodbarber.com/blog/how-to-automate-your-goodbarber-app-with-n8n-and-mcp-no-code-required-a1523/" rel="noopener noreferrer"&gt;wired into n8n&lt;/a&gt;, run fully unattended. The server's job is to keep both modes safe, with per-app OAuth scope, typed tools, and verified writes.&lt;/p&gt;

&lt;p&gt;We fully intend to take this further. The list above is just where the honest line sits today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If you have a GoodBarber app: add a custom connector in Claude (or any MCP client), point it at &lt;code&gt;https://mcp.goodbarber.dev/mcp/sse&lt;/code&gt;, sign in with your account, and ask for something small. "Fix the typo in my latest article" is a good first test. The &lt;a href="https://www.goodbarber.com/mcp-complete-guide/" rel="noopener noreferrer"&gt;complete MCP guide&lt;/a&gt; covers per-client setup.&lt;/p&gt;

&lt;p&gt;If you're building an MCP server for your own platform: the pattern that held up for us in production is boring and worth stealing. Typed tools namespaced by domain, per-tenant OAuth scoping, feature-gated tool exposure, and forced read-back on every write.&lt;/p&gt;

&lt;p&gt;Questions welcome in the comments. I'll answer with real payloads where I can.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>nocode</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
