Case study · MCP-native platform

Orbixio Studio

A content platform with no interface of its own. Claude Desktop is the client, six MCP tools are the API, and nothing reaches production until a human has explicitly approved it — enforced by the protocol surface, not by a convention people are trusted to follow.

Type
TypeScript monorepo · MCP server
Status
v0 — MCP server and core pipeline working; web app stubbed, not implemented
Stack
TypeScript · MCP SDK · Anthropic SDK · Prisma · PostgreSQL · zod · vitest
Source
github.com/AhmedAliQadir/orbixio-studio

Context

Orbixio produces video content, and the script stage is the bottleneck: it is the part that has to be right, and the part that is slowest to produce. It is also the part that language models are genuinely good at — provided the output is structured, reviewable, and never automatically acted on.

The interesting design question was not "can a model write a script". It was: if the model is going to be the drafting tool, what is the right shape for the software around it?

The problem

The default answer is to build a web app: a dashboard, a text editor, a generate button, an approval workflow, user management. That is several weeks of interface for a workflow whose entire content is ask for a script, read it, approve or reject.

Meanwhile the person doing the work is already sitting in Claude Desktop. Building a second, worse chat interface next to the good one is work that makes the product harder to use.

The real problem was the guarantee. "We always review before publishing" is a promise, and promises decay under deadline. It needed to be structurally impossible for unreviewed content to move downstream.

What I built

Six MCP tools over stdio, and no UI

list_channels      get_channel
generate_script    review_script
approve_script     reject_script

The MCP server is the entire product surface. You point Claude Desktop at it and say "list my channels, then generate a script about writing sales emails for the first channel" — Claude calls list_channels, then generate_script, and returns a structured draft. No dashboard was built, because none was needed.

Structured output, validated by zod

Scripts are not free text. They are validated structures: hooks, five tool entries each carrying an honest caveat, calls to action, and YouTube metadata. Validation happens at the boundary — if the model returns something that does not fit the schema, it fails there rather than three steps later in something that consumes it.

The "honest caveat" field is a product decision expressed in the data model: every tool a script recommends must carry its limitation. Making it a required field means the caveat cannot be quietly dropped when it is inconvenient.

The approval gate lives in the protocol

A script exists in a state, and the transition out of draft happens only through approve_script or reject_script. There is no code path from generation to downstream work that skips it. The human-in-the-loop requirement is not a documented process — it is the shape of the API.

Multi-tenant from the first migration

Every row is scoped to a userId, even though v0 runs single-user via an environment variable. Retrofitting tenancy onto a schema that never had it is a migration nobody enjoys; adding a column at the start costs nothing.

A monorepo shaped like the boundaries

packages/
  db/            Prisma schema, client, seed
  core/          Pipeline logic — LLM provider, script generator, schemas
  mcp-server/    MCP server wrapping core over stdio
apps/
  web/           Stubbed Next.js app (not implemented)

Core knows nothing about MCP. The MCP server is a thin transport wrapper around it. That separation is what lets a second consumer — a web app, a CLI, a scheduled job — attach later without touching the pipeline. It is the same principle behind the shared Duffel tool layer in Tourista.

Decisions I would defend

No microservices, no workflow engine — just functions

The README says this out loud because it is a decision, not an omission. The workload is a handful of operations against one database with one external API call. A workflow engine here would add operational surface, a second failure domain and a deployment story, in exchange for orchestration that a function composition already provides.

Shipping v0 with the web app stubbed

The Next.js app exists as an empty package, and I would rather say that plainly than pad the repository. The MCP server delivers the entire workflow today. Building the web UI first would have been building the part nobody needed in order to look more like a product.

Making the approval gate a protocol constraint

This is the decision I would most want to be asked about. Enforcing review in the UI means anyone with database access can bypass it. Enforcing it in the tool surface means the only way to move a script forward is to call the tool that records who approved it. In a domain where the AI writes and a human is accountable, that distinction is the whole design.

Ten minutes from clone to working

The setup path is documented as a numbered sequence including the exact Claude Desktop config JSON for macOS and Windows, and a first command to try. A reviewer who cannot get an MCP server running in ten minutes concludes the project does not work — which is nearly always a documentation failure rather than a code one.

The result

What I would do next

Implement the web app as a second consumer of core — proving the boundary holds — and add real multi-user auth in place of the environment-variable user. Then the downstream half: taking an approved script into production rather than stopping at approval.

My role and stack

Role: Solo engineer — architecture, schema, pipeline, MCP server, tests, documentation. Built under Orbixio Ltd, where I am Founder.

Stack: TypeScript, Prisma, PostgreSQL, @modelcontextprotocol/sdk, @anthropic-ai/sdk, zod, pino, vitest, Biome, pnpm workspaces.