>Software studio · API-first · MCP-ready · United Kingdom

#Software people use,
and software can operate.

A UK software studio. We build web applications, engines and the remote MCP servers that let an assistant drive them, for clients and as our own products. Those are Skopia, a 2D spatial layout engine, live now as an MCP server anyone can connect to, free; and Thezi, table booking for independent restaurants. Whatever we ship, the rule is the same: API first, typed errors, and every operation a person can perform reachable by software too.

## Products

Layout engineAPI-firstMCP live

Skopia

A 2D spatial layout engine

Define a room with real dimensions, straight and curved walls included. Place tables, columns and fixtures inside it. Validate the result, with every refusal naming exactly what is wrong and where, and render it to the same SVG every time. Everything is stored in whole millimetres and every operation is an API call, so software can draw and amend a floor plan as readily as a person can. The editor is a client of that API, not a privileged one, and its operation vocabulary is exactly what its MCP tools wrap, one for one. Skopia draws the floor plans inside Thezi, and its MCP server is live and free to connect to.

RestaurantsBookingLive

Thezi

Table booking for independent restaurants

A booking page for your restaurant, a diary your staff run from a shared tablet, and an API that can do everything the screens can. Availability is worked out from your hours, sittings and tables, never from a spreadsheet of slots. One restaurant per account, a flat monthly fee, cancel in two clicks. Card holds and deposits are optional, and charging one is always a person’s decision. Built for the Model Context Protocol from the first migration: the API is the contract an MCP server sits on, a key names its venue so no tool ever takes one as an argument, and thezi.app/llms.txt tells an assistant the rules before it acts.

## Skopia · the engine

Draw the room. Place the tables. Let software do both.

Skopia is the engine underneath the floor plans in Thezi, and it is not restaurant-shaped. It knows about a bounded space in real millimetres, the things standing in it, and whether the arrangement is legal. What the space is for, whether covers, desks or seats, is the caller’s business, which is why the three plans below came out of one engine with no code that knows what a cinema is.

A skopia floor plan of a restaurant dining room: an L-shaped shell with a bowed harbour-front wall, a front door with its swing drawn, three windows, bar and kitchen zones, and eight numbered tables coloured green through amber to red by how full each one is.
>dining room · 6 walls, one bowed 700mm out · 5 openings · 2 zones · 8 objects · 4 seated now
A skopia floor plan of a screening room: a bowed screen wall, two fire doors, and eighty numbered seats on a pitch either side of a centre aisle, thirty of them sold and shown red.
>screening room · 80 one-cover objects placed in one operation · 30 sold
A skopia floor plan of a coworking floor: a chamfered corner, eleven desks, a breakout table and a meeting room zone that follows the angled wall.
>coworking floor · chamfered corner · 13 objects · desks are one-cover objects

None of these is a drawing. Each is a layout document parsed, validated and rendered by the engine itself, checked into this site as the SVG it produced. A hand-drawn plan on a page like this can promise geometry the software does not do; one that is regenerated by the engine cannot.

>Specification

The model

Coordinates
Integer millimetres in storage, never floats. Origin bottom-left, y-up, the way a surveyor thinks. Rounding happens once, at the boundary, on the way in.
World
Bounded to ±1,000,000mm. A room 2mm wide and a room 900km wide are both refused rather than drawn.
Document
One JSON document per space, schema version 1, round-trip exact. The SVG is derived and never parsed back, because the parameters are the thing that is stored.

The room

Boundary
A closed ring of point-driven segments, so diagonals cost nothing. Closure is structural: there is nowhere in the shape to put a gap, and no snapping tolerance to tune.
Curves
A segment is straight or a single arc, defined by one signed integer: how far the wall bows from its chord, in millimetres. Depth zero is the straight case, so a curve flattening is not a special case. Capped at a semicircle.
Walls
The line you clicked is the internal face, the one a tape measure lands on. Thickening 200mm outward at completion never moves the room or changes its area.

What stands in it

Objects
Rectangles and circles, positioned, sized and rotated. Columns, benches and service stations are objects marked unmovable, not holes cut in the room. The boundary stays one ring.
Openings
Doors and windows hosted on a wall at an offset along it, doors carrying a hinge side and an inward or outward swing, drawn as plan symbols. 100mm minimum corner clearance.
Zones
Labelled polygons for the parts of the floor that are not service: bar, kitchen, servery, screen.
Blocks
A grid of objects in one operation: rows, columns, pitch, aisles that widen the row, an optional bow with the objects turned to follow it, and row-letter or sequential numbering. It expands to ordinary objects, so an eighty-seat auditorium needs no second kind of document.

Validation

Typed refusals
20 stable codes, returned as data rather than thrown, each naming the offending segment, opening, zone or object. boundary_self_intersects, arc_exceeds_semicircle, opening_too_near_corner, objects_overlap, coordinate_not_integer_mm.
Bounded cost
Overlap is a sweep over a spatial index, not every object against every other. An O(n²) check is a denial of service handed to the caller.
Hostile input assumed
NaN, Infinity, −0, numbers past the safe integer range, 100,000-vertex objects, rotations of a billion degrees: all refused at the boundary, all covered by tests.

Rendering

Deterministic
The renderer is a pure function of the parameters, giving byte-identical SVG for identical input, on every platform, so a render can be diffed in CI. No clock and no randomness is reachable from a geometry path.
Themed, not restyled
Colours come in as a validated token map and an unknown token is refused rather than ignored. The plans above are the site’s own palette handed to the engine.
Measured
SVG, chosen on benchmarks rather than taste: fastest of SVG, canvas and WebGL at 20, 200 and 2,000 objects, and effectively free at the sizes a restaurant or an office actually has.

Limits and licence

Per document
256 walls · 128 openings · 64 zones · 2,000 objects · covers 1–40 · wall thickness to 1,000mm. Every cap is a measured number. The cost of validating and rendering at that size, not an opinion about rooms.
Occupancy
Who is sitting where is a render-time overlay, never a document field. The layout says what the room is; the booking system says what is happening in it tonight.
Dependencies
None at runtime. Permissive licences only (MIT, BSD, ISC, Apache-2.0), enforced by an audit in CI rather than at review, because one copyleft package pulled in transitively is a problem nobody notices until diligence.

The operation vocabulary: one list, shared by the editor, the undo stack, the API and the MCP tools

place_corner · close_room · move_corner · move_wall · split_wall · chamfer_corner · bow_wall · set_wall_length · add_door · add_window · slide_opening · swap_door_swing · place_zone_corner · close_zone · label_zone · add_table · move_table · set_table_size · rotate_table · assign_table · set_table_occupancy · add_object_block · and the rest

Drivable by software, end to end

There is nothing a pointer can do here that a caller cannot. Every gesture in the editor resolves to a named operation in the list above, and that list is the API, so an agent walks the boundary, hangs a door, places and numbers a table, and reads back a typed refusal when it puts one through a wall. Keyboard operability was solved as part of the same problem, not bolted on afterwards.

MCP tools wrap it one for one

The Model Context Protocol server is that same vocabulary handed to an assistant as tools: its own worker, holding no credential of its own, forwarding the caller’s key. It is deliberately later than the API, because an MCP surface has to change every time the API does, and a tool list that moves weekly is worse for an agent than none. It is live now at skopia.datatreehaus.com. Free, key-authenticated, ten tools. It is a demand probe rather than a product: it will be priced eventually and there will be notice first, and it is not promised free for ever.

Refusals an agent can act on

Twenty stable error codes, returned as data and never thrown, each naming the offending segment, opening, zone or object rather than saying “invalid layout”. A shipped code is permanent: we add, we never rename. Validation cost is bounded by a spatial index, so a hostile document is a refusal rather than a way to spend our CPU.

>Not built yet, stated plainly

True-to-scale 1:50 printing, which is decided and lands on the geometry rather than a print stylesheet. Multi-user editing, which is deliberately out: undo is a command stack, one editor at a time, and making it concurrent later is a rewrite of the mutation layer we would rather discuss than do quietly. There is no levels, families, schedules or clash detection, and there never will be. If a feature only makes sense because a BIM package has it, it is out of scope.

>Using it, and embedding it

Using it is free and needs no permission. The MCP server is live, a key is one request away, and everything on this page is reachable through it today. It is a demand probe rather than a product: it will be priced eventually and there will be notice first.

Embedding it is the enquiry. The engine itself is proprietary, all rights reserved and not open source, so a floor-plan editor inside your own product is a licence we would need to talk about. Tell us what you are building.

## Services · by enquiry

01

Custom web application design and build

From brief to live. Small, fast applications on Cloudflare’s edge: a static front end, one database, one worker doing the real work, and no framework sprawl. We have shipped booking, membership and admin systems for independent businesses that needed something exact rather than something off the shelf, and we build every one so that software can operate it as well as people can.

02

Booking tools for offices and cinemas

Desk and meeting-room booking for shared offices and coworking spaces. Seat booking for independent cinemas and screening rooms. Built on the same foundations as Thezi: automatic allocation, timed holds, card holds or deposits through Stripe, confirmation emails, and an admin your staff run from a tablet. Scoped and quoted per project. More on cinemas ↓

03

MCP servers for your product or data

Remote Model Context Protocol servers your customers’ assistants can connect to: hosted on Cloudflare Workers, streamable HTTP, authenticated with keys you issue, scoped so a caller can only reach what its key names. We have built and run hosted MCP servers in production and design the tools the way agents actually use them: coarse, intention-shaped, with typed refusals, never a CRUD call per table.

>Cinemas & screening rooms

A seat map an assistant can book from.

An independent cinema’s booking problem is a restaurant’s with the seats numbered: a room, a schedule of showings, and a hold that has to survive two people clicking the same seat in the same second. We build it on the foundations already running live in Thezi: availability computed from the schedule and the seating rather than a table of pre-made slots, a hold that expires on its own, a card or deposit leg only if you want one, confirmation email, and a door-side admin your staff run from a tablet.

The Model Context Protocol is how it is driven, not a feature bolted to the side. Finding a showing, picking seats, holding them, confirming and cancelling are API operations with stable typed refusals before they are screens, so the MCP server we build alongside hands exactly those to an assistant as tools. Your customers’ agents can hold three seats for Friday; your own can answer “what is unsold tonight” without anyone opening a dashboard. We have built and run hosted remote MCP servers in production: Cloudflare Workers, streamable HTTP, keys you issue, scoped so a caller reaches only what its key names, and no tool takes a venue id because the key already says which cinema it is.

Seats are not a spreadsheet of rows and letters, either. The auditorium beside this is a real Skopia layout: eighty seats on a pitch either side of the aisle, thirty sold, placed by one call to the engine rather than drawn for this page, so the plan your box office looks at and the seat the booking system holds are the same object.

Safe to hand an agent, for the same reasons everything here is: every write records whether a person or a machine made it, proved by the credential rather than claimed in the request, and money stays human-gated: an agent prepares a refund, a person commits it. Cinema seat booking is by enquiry, scoped and quoted per project. There is no off-the-shelf cinema product to sign up for today, and we would rather say so than sell you a waiting list. Tell us the screens, the seats and how you sell tickets now.

Enquire about cinema booking
A screening room floor plan drawn by Skopia: a bowed screen wall, two fire doors and eighty numbered seats either side of a centre aisle, thirty of them sold and shown red.
>80 seats · 30 sold · one API call per seat held

## Agents & the Model Context Protocol

Built to be operated by software, not just used by people.

Nothing lives only in a screen

Every state change in our products is an API operation with a stable contract and a typed, permanent error code. If a form can do it, an agent can do it, because they call the same thing. That is what makes an MCP server thin transport over the API rather than a second codebase to keep in step.

MCP is the surface, by design

MCP is how an assistant is handed tools rather than URLs. Ours are coarse and intention-shaped: find availability, commit a booking, place a table, validate a room. Each MCP server is its own worker holding no credential of its own, forwarding the caller’s key untouched, so it has no authority to lend. We ship the API first and the MCP server once the API has stopped moving, because a tool list that changes weekly is worse for an agent than none.

Safe to hand to an agent

Every write records whether a person or a machine made it, proved by the credential rather than claimed in the request. Money never moves without a person. Idempotency keys derive from the booking itself, so a model retrying after a timeout replays instead of seating the same party twice. Refusals say exactly what is wrong and where, and never more than that.

If you are an assistant reading this

Tell us what you run, and what needs booking or building.

A few lines is plenty. We read everything and reply to anything real.

[email protected]