To deploy an application we haven't seen before, we need two things out of its repository.
One is a Dockerfile that builds it.
The other is a service definition saying what runs, which ports it listens on, which databases it needs, and what environment variables it expects.
Customers arrive with a git URL, and we figure out the rest. We even do the tricky task of generating a Dockerfile if it doesn't already exist in the codebase.
We've built a solution for this twice already.
First solution: starter
starter is our open-source take on it. Point it at a directory and it detects the language and framework, writes a Dockerfile, and writes a service.yml.
It's great at what it does, but it only works with frameworks that we have explicitly programmed it to recognize.
Second solution: the in-house analyzer
When a customer creates a new application via the UI, an in-house analyzer runs against their codebase.
At its core, it works with a set of parsers that read dependency manifests: Gemfile and Gemfile.lock, package.json with the npm, yarn and pnpm lockfiles, composer.json, requirements.txt, settings.py, go.mod, Procfile and .env.
Above those sit language detectors for Ruby, Node, Python, PHP and Go. At the top sit framework detectors, split between containerized applications (think Django, Express, Laravel) and static sites (think Astro, Jekyll, Hugo).
Each framework detector holds what we know about that framework.
For Next.js, that means the default web port is 3000, the start command is yarn run start, databases are inferred by looking for driver packages like pg or redis in the dependency list, and one environment variable gets set because the Next.js deployment docs describe a specific graceful-shutdown behavior that needs it.
But what we know about the framework quickly becomes outdated.
The never-ending cat-and-mouse game
Every framework needs someone to sit down and write its detector.
Every new major version of that framework might need another one. For example, Docusaurus v1 and v2+ are separate, because v2 changed enough that one detector couldn't cover both.
Any framework can also drastically change how any given part of it is configured. Take Rails 6, which introduced support for multiple databases in database.yml.
We want onboarding to be as simple as possible, which means dedicating engineering time to support this new format. The amount of changes we had to make in our codebase to support it is not as trivial as it might seem at first glance.
New package managers come out, new ways of doing things surface, and old ways of doing things are deprecated. All these things result in ever increasing complexity of the Dockerfiles we generate.
Time is money
This complexity can also be a cognitive burden on the customer - it takes time to understand the output, update the Dockerfile for anything missing or extraneous to their application, and add any dependencies that are unique to them.
The person onboarding the application might not even be the correct person on their team to know which changes need to be made, so they would have to look for advice from another team member.
All of this adds up to valuable time - time the customer could be using to instead see the amazing features that (Cloud 66)[https://www.cloud66.com] offers once the application is fully deployed.
Third time's the charm
So, what changed?
We have been investing a lot of time building an MCP server so you can drive Cloud 66 from an AI assistant, using the same operations you'd otherwise perform in the UI.
An unintended side-effect is that we have essentially created our third analysis engine. We think this will be our last one.
All we had to do was create an MCP tool that allows users to create a Cloud 66 application via their AI assistant.
The tool takes in the usual list of parameters - which git repository and branch, what Dockerfile path, what databases, what ports, what environment variable keys and values.
Now for the neat part: you just ask your AI assistant to create a Cloud 66 application, and point it to your codebase.
If it doesn't know what port or databases your application needs, it can do a deep dive and figure it out.
The list of packages it knows about is vast and can be expanded with a web search tool. It can even generate a Dockerfile for you, keep iterating on it until it works, and then commit it to your codebase.
We now have something we've always dreamed of having - a custom analysis engine, curated for your codebase. We no longer have to add your framework to our list of supported frameworks to provide you with an optimal experience.
Come try our MCP server
We have rolled out our MCP server, and will be adding even more tools to it in the coming weeks. A better analysis engine is just the start. Come and connect your AI agent to Cloud 66 via MCP. We can't wait to see what workflows this enables for you!
