<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>ConfigDirector Blog</title>
    <link>https://www.configdirector.com/blog</link>
    <description>Articles on feature flags, remote configuration, and shipping software safely with ConfigDirector.</description>
    <language>en</language>
    <lastBuildDate>Sat, 19 Sep 2026 00:00:00 GMT</lastBuildDate>
    <atom:link href="https://www.configdirector.com/blog/rss.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>Why your feature flag service should validate values</title>
      <link>https://www.configdirector.com/blog/why-your-feature-flag-service-should-validate-values</link>
      <guid isPermaLink="true">https://www.configdirector.com/blog/why-your-feature-flag-service-should-validate-values</guid>
      <pubDate>Sat, 19 Sep 2026 00:00:00 GMT</pubDate>
      <dc:creator>Alejandro Beiderman</dc:creator>
      <description>A feature flag service lets you change production without a deploy. It should also refuse the change that would break it.</description>
      <content:encoded><![CDATA[<p>Every feature flag and remote config service offers the same value proposition: change how production behaves without deploying a new build. That is the purpose of the tool, but it is also the risk. A deploy goes through a CI pipeline running test suites, static analysis, and functional tests. A remote config change goes through a text box on a dashboard.</p><p>Outages caused by a configuration update usually come down to small values that were slightly wrong:</p><ul><li>A timeout entered in seconds when the code expects milliseconds</li><li>A URL pasted without the scheme</li><li>A JSON document saved with a typo on one field, or a field missing</li><li>A rollout percentage typed as <code>10</code> into a field that expected <code>0.1</code></li></ul><p>Each of these mistakes is obvious in hindsight, but invisible at the moment someone clicks Save.</p><p>The service hosting the value is the only thing standing between that click and your users. It should know what a valid value looks like, and prevent those mistakes.</p><h2 id="a-value-is-not-a-string">A value is not a string</h2><p>Most services store a configuration value as one of a few loose types: boolean, string, number, JSON. That is enough to render an appropriate input field, but it is not enough to know the value makes sense in the context it will be used.</p><p>Your code and your application have specific expectations for each value. They expect the timeout to be a positive integer under thirty seconds. They expect an API endpoint to be HTTPS. They expect the theme to be one of <code>light</code>, <code>dark</code>, or <code>system</code>. They expect the JSON payload to have a <code>version</code> field, and an array of at most twenty items. None of that knowledge lives in the feature flag service, so the service cannot validate any of it.</p><p>In ConfigDirector, every config has a fine-grained type, and each type carries the constraints your application actually depends on:</p><ul><li><strong>Integer and Float</strong> with minimum and maximum bounds. A <code>search-page-size</code> config bounded to 10 through 100 cannot be saved as <code>0</code> or as <code>10000</code>. A <code>free-shipping-threshold</code> bounded to 0 through 500 cannot be saved as a negative number or as ten times what you meant.</li><li><strong>Timespan</strong> for bounded durations, so the unit is part of the input field rather than a comment nobody reads.</li><li><strong>URL</strong> with an HTTPS-only option. A URL without the scheme is no longer a possibility, nor is HTTP when you expect HTTPS.</li><li><strong>Enum</strong> with the allowed set of values. Not as variations of an experiment, but rather baked into the value type of a config used for any given purpose.</li><li><strong>JSON</strong> with a JSON Schema, covered in detail below.</li><li><strong>Boolean</strong> for feature flags and kill switches, which don't need complicated validation at save time, but do need monitoring and alerting for unexpected evaluation behavior.</li></ul><p>The constraints are enforced when a value is saved, in every environment, through all interfaces, before anything reaches an SDK. A bad value never leaves the dashboard, the Terraform file, or the code assistant chat window.</p><h2 id="json-is-where-it-matters-most">JSON is where it matters most</h2><p>JSON documents are the most powerful kind of remote config and also the most dangerous. A single document can drive a pricing table, a navigation menu, a set of rate limits, or an experiment's parameters. It is also the value most likely to be edited by hand or copied and pasted inadvertently from an unrelated JSON document, and most likely to fail at read time by the code consuming it.</p><p>A JSON Schema turns the structure your code expects into something the service can validate and enforce. In ConfigDirector, a JSON config can carry a schema (draft-07), and from then on every value the config can return is validated against the schema before it is saved. All values that could be returned by the service are validated: the default targeting rule value, every conditional rule value, percentage rollout value, every experiment variation, in every environment.</p><p>There is a second check. The schema itself is validated when you update it. Every existing value in every environment is checked against the new schema, and the schema change is rejected if any environment holds a value that would no longer pass. You cannot tighten a schema and leave staging holding a value that the schema would refuse. The values and the contract move together.</p><h2 id="validation-has-to-apply-everywhere-a-value-can-change">Validation has to apply everywhere a value can change</h2><p>A check that only runs in the dashboard is a suggestion. Values change from more places than the dashboard, via the API, Terraform, a script someone wrote in an afternoon, and now AI coding assistants through an MCP server.</p><p>That last one deserves a closer look. When an assistant creates a flag or updates a rollout on your behalf, it is working from a description of the task, not from your source code. It will produce a plausible value. Plausible is not the same as valid. If the service enforces the type and the schema on every write, the assistant gets the same rejection message a person would see in the dashboard, and it can correct itself. If the service does not, the plausible (but invalid) value is now live.</p><p>In ConfigDirector, the same validations run for every path that can write a value. The dashboard, the Admin API, the Terraform provider, and the MCP server all go through it, and all of them get the same error messages.</p><h2 id="the-sdk-is-the-last-line-not-the-first">The SDK is the last line, not the first</h2><p>SDKs should be defensive, and ConfigDirector's are. If a value arrives that cannot be converted to the type your code asked for, the SDK returns the in-code default value you passed and reports why: the code requested a boolean but the config value is a string, or a JSON document that could not be coerced into the requested type. Your code keeps running.</p><p>That fallback is the right behavior to keep the application from failing, but it should not be a <em>silent</em> behavior. The in-code default value is usually the conservative choice and not the one you wanted in production. If a rollout falls back to "false" because the code asked for a boolean and the config is a string, the feature is not broken, it is just not happening.</p><p>So the SDKs report the reason for every fallback in their telemetry, and ConfigDirector watches for patterns to alert on:</p><ul><li><strong>Type mismatches.</strong> Code is requesting a config as a type it cannot be converted to, for example reading an Enum config as a boolean. You get an alert naming the config, the environment, and the SDK that is doing it, while it is still happening.</li><li><strong>In-code default values that are not part of the targeting rules.</strong> This is a classic problem. When you first add the flag or config to the code you give it an in-code fallback default that makes sense at the time. Later, things change, the value evolves, but the in-code default stays the same. If the evaluation ever failed, and the SDK had to fall back to the default, the in-code fallback value is outdated and likely no longer what you would want. ConfigDirector detects this and alerts you about in-code defaults that don't match any of the values configured in the targeting rules, meaning it is <em>very</em> likely that the in-code default is outdated. You get notified as soon as the drift is detected, <em>before</em> that outdated fallback value becomes a problem.</li></ul><p>Validation on save means the mistake is caught by the person making it, at the moment they make it, with a message that says what was wrong. The alerts cover the other end, the code drifting away from the config.</p><h2 id="try-it">Try it</h2><p>Create a JSON config, attach a schema, and try to save a value that does not match it. Then change the schema so an existing value no longer passes and watch the service refuse the change. It is a powerful feature, and once you have it you will not want a config service without it.</p><p>The <a href="https://docs.configdirector.com/getting-started/json-schema-validation" rel="noopener" target="_blank">docs on JSON Schema validation</a> cover the limits and the details. The Free plan has no card and includes all of it.</p>]]></content:encoded>
    </item>
    <item>
      <title>Managing feature flags from Claude Code and Cursor with MCP</title>
      <link>https://www.configdirector.com/blog/managing-feature-flags-from-claude-code-and-cursor-with-mcp</link>
      <guid isPermaLink="true">https://www.configdirector.com/blog/managing-feature-flags-from-claude-code-and-cursor-with-mcp</guid>
      <pubDate>Thu, 17 Sep 2026 00:00:00 GMT</pubDate>
      <dc:creator>Alejandro Beiderman</dc:creator>
      <description>Connect your coding assistant to ConfigDirector and create flags, roll them out, and check what is live without leaving the editor.</description>
      <content:encoded><![CDATA[<p>Most feature flag work happens in two places at once. You write the code that reads the flag in your editor, then switch to a dashboard to create the flag, enable it for dev/test, and later roll it out in production. With the ConfigDirector MCP server, the code assistant that is already in your editor can do the second half for you.</p><h2 id="what-the-mcp-server-is">What the MCP server is</h2><p>The <a href="https://modelcontextprotocol.io" rel="noopener" target="_blank">Model Context Protocol</a> is how coding assistants such as Claude Code, Cursor, and Copilot interact with outside tools. A server exposes a set of tools, the assistant reads the tool descriptions and calls them when a task needs them.</p><p>ConfigDirector's MCP server is hosted, so there is nothing to install or run. It sits in front of the same Admin API that the dashboard and the Terraform provider use, and it authenticates with an ordinary API token. Every update it makes goes through the same validation as an update from the dashboard, it is recorded in the audit log with the source <strong>MCP</strong>, and counts as one Admin API request per tool call.</p><h2 id="connecting-claude-code">Connecting Claude Code</h2><p>Create an API token in the dashboard with the permissions you want the assistant to have. For a first try, read permissions on projects, environments, and configs are enough to explore. To support a full workflow, add the create, update settings, and update targeting rules permissions on configs. Copy the token to your clipboard before dismissing the page (the token is only shown at creation time).</p><p>Then add the MCP server to claude. The token is read from an environment variable, so it never lands in a file you might commit:</p><pre><code class="language-bash">claude mcp add --transport http configdirector https://mcp.configdirector.com \
  --header "Authorization: Bearer ${CONFIGDIRECTOR_TOKEN}"
</code></pre><p>Type <code>/mcp</code> inside Claude Code and the server shows as connected, with only the tools your token allows. Cursor, VS Code, Windsurf, Codex CLI, and Gemini CLI each have a two-line setup of their own. The <a href="https://docs.configdirector.com/integrations/mcp" rel="noopener" target="_blank">MCP docs page</a> has all of them.</p><h2 id="a-session">A session</h2><p>Here is what an ordinary afternoon looks like once the server is connected. Each request is typed to the assistant in plain words, the tool calls happen underneath.</p><p><strong>Creating a kill switch.</strong> "Create a kill switch called <code>payments-v2</code> in the checkout project, off in every environment." The assistant lists the projects to find checkout, creates the config with the kill switch role, and reports the key. The switch is off in every environment because that is the initial default targeting rule value it was created with.</p><p><strong>Rolling out a flag.</strong> "In production, roll <code>new-search</code> out to 10 percent of users, and to everyone whose email ends in <code>@example.com</code>." The assistant reads the flag's current rules for production, then replaces them with two rules: a conditional rule that matches the email domain, and a percentage rule that splits the rest. Because the MCP server provides the assistant with the exact targeting rules format and the operators each attribute supports, it does not have to guess.</p><p><strong>Checking what is still in use.</strong> "Which flags in the checkout project have not been evaluated in the last week?" The assistant reads the recent evaluation activity of each config, which comes from the SDKs' telemetry, and tells you which ones have not been requested by any SDK. Those are the candidates for cleanup, and the dashboard is where you archive them.</p><p>Open the audit log afterwards and each change is there, attributed to the token's owner with the source <strong>MCP</strong>, next to the changes made from the dashboard and from Terraform.</p><h2 id="what-the-server-will-not-do">What the server will not do</h2><p>The assistant only sees the tools its token has permission for. A read-only token produces a read-only assistant. There is no tool to archive a config, or to delete a project or an environment. Those destructive operations stay in the dashboard on purpose.</p><p>Each organization can make up to 60 tool calls per minute. Past that, the assistant is told to wait for the next minute rather than being cut off, which keeps a retry loop from doing any harm.</p><h2 id="try-it">Try it</h2><p>The <a href="https://docs.configdirector.com/integrations/mcp" rel="noopener" target="_blank">docs page</a> has the setup for every supported tool and the full list of what the assistant can do. If you already use ConfigDirector, an API token is all you need. If you do not, the Free plan includes the MCP server.</p>]]></content:encoded>
    </item>
  </channel>
</rss>
