MCP server
Connect your AI tools to aidrop.it over the Model Context Protocol — the same Service in every tool.
aidrop.it exposes your team’s Services as a remote MCP server at:
https://aidrop.it/mcpAny MCP-capable client — Claude Code, Codex, Cursor, Claude, and others — can connect to it to create a product, get its code in, build it, run it and open it to the internet. Only a client with a local shell and git (Claude Code, Codex, Cursor) can write code and get it into a repository; a chat-only client reads the record and can build code that is already in a repository. This is the whole programmable surface: there is no REST API beside it. Administering the organisation — its members and their roles (admin, developer, viewer), entering runtime values — is done in the dashboard and has no tool at all. Access is settled once, on the organisation: everyone in it can reach every Project, and what they may do there is their role. The reverse is true of a Project’s and a Service’s own lifecycle: since 1 September 2026 the dashboard neither creates nor removes one, so project_create, project_delete, service_build, service_update and service_delete are the only way — a Service is created by the first service_build rather than by a call of its own.
What is here is the whole of it. Tools are added and retired as the product changes, and a test fails the build when the table below and the tools the server actually answers with disagree — so if a tool is not in that table, it does not exist.
Every tool publishes an outputSchema in tools/list and answers the same
JSON document twice: as text, and as structuredContent in the shape that
schema promises. A client that reads the schema knows what service_get will
answer before it calls; one that only reads text loses nothing.
Authentication
OAuth, with dynamic client registration. Clients that speak MCP OAuth (Claude Code, Codex, Cursor, Claude) open a browser window and walk you through consent; there is nothing to pre-register and nothing to copy. What you approve on that screen is your Team and the scopes over it — the connection then reaches every Project in the Team, and what it may do in each is your role — and you revoke it again from Management → Connected apps in the dashboard.
Scopes are service:read (open a Service and its safe snapshot) and
service:write (create, prepare, and operate a Service). A connection made
before Service access existed must reconnect once to receive them — an old
credential may still carry the retired context:* or memory:* names, which
are accepted and gate nothing.
Glossary: Team, Project and Service
A Team is the membership and billing boundary. An agent authorizes against one Team and, according to the member role, can discover that Team’s Projects. It is not the boundary for a database connection or a runtime value.
A Project is one durable product and its operational boundary. It owns its
Services, backing services and Project values. Use the current project_id for
every resource, connection string and secret: a backing service or value from
another Project is not attachable and is not delivered at deploy.
A Service is one deployable application inside a Project — for example a web app, API or worker. It has its own build, runtime settings, address and lifecycle. It does not own a database or a secret; it receives only the named Project values and backing services attached to it. A managed PostgreSQL, cache or queue is a backing service, not an application Service: it belongs to the Project and may be attached only to that Project’s Services.
The shape: Team → Projects → Services, and the Team’s repositories
A Project is the customer’s product — the thing they name. A Service is
one deployable inside it: a frontend, a backend, a worker. A plan counts Projects;
the Services inside one draw on the plan’s memory and CPU and never take a slot.
projects_list and services_list are where every session starts;
service_build takes a project_id from the first and a name for the
deployable, and makes the Service on its first call, so the first deploy still
happens in one session.
A repository is the Team’s, not a Service’s. It exists before any Service
builds from it and outlives the Services that do, and one repository may back
several Services — a monorepo whose API and web app are separately deployable is
two Services over one repository. repositories_list shows the Team’s: the ones on
its own aidrop.it Git service and the GitHub ones the Aidrop GitHub App can
reach, with the Services each backs. A Service is created without a repository;
the first service_build links one, for good.
The build loop
Code reaches a repository from your shell and nowhere else. For code that is
not on GitHub, repository_create makes an empty repository on the Team’s
aidrop.it Git service and answers its clone URL and a push credential, and
your own git push puts the code there; repository_get answers the same
credential again for a repository that already exists. A GitHub repository
needs nothing created — once a person has installed the Aidrop GitHub App for
its account, it appears in repositories_list and Aidrop syncs it on push.
Then the loop, which is the whole of deploying:
service_buildbuilds the head of the tracked branch and deploys the image to the Service’s address when the build succeeds — that address is open to the internet from this first deploy. The first call links the repository — passrepository_ref, fromrepositories_listorrepository_create— and records the runtime settings:container_portis the one value nothing can default;health_path,resource_class,runtime_kind,build_typeandrequired_secret_nameshave defaults that are defaults, not guesses. Nothing is read out of the code to fill them in: the image is built with nixpacks — no Dockerfile required — unlessbuild_type: dockerfileandbuild_dockerfile_pathname one to build instead. Every later call keeps the settings unless one is passed again, and needs norepository_ref. Passbranchto build, and from then on follow, another branch. The build is queued and takes minutes.service_getsays how far it got: the repository and commit, the build’s stage and status, the deployment, the address, the settings, and anext_stepnaming the one call that follows from that state. Poll it; do not narrate the wait.deploymentis the latest attempt;applicationseparately names the active deployment, commit and tag serving the address, which can be an earlier revision when a later attempt failed.service_logsis the latest build’s log, credential-redacted and bounded. When the build failed, read it, fix the code, push, and callservice_buildagain.
Every successful build keeps its image under a tag — the first twelve
characters of the commit it was built from, named in service_build’s answer.
service_tags_list lists the images a Service has, newest first, and
service_start with a tag starts that image without rebuilding it: a
rollback is that call with an older tag, and returning to the tip is the same
call with the newest. Without a tag, service_start resumes the current
image after service_stop paused it.
service_update renames a Service and restates what it is for. Nothing else
is settable there: the address is open from the first deploy, so there is no
lock to take off.
service_build refuses up front with the same sentences a build would stop on —
a runtime value nobody has stored, a size the plan does not include, hosting
paused — rather than recording a run that stops at checked.
Runtime values belong to the Project, not to one Service. project_secret_set
stores one under a name and project_secret_delete removes it; both take a
project_id, and neither ever answers a value back. Which of a Project’s values
reach a given Service is that Service’s own decision, made in service_build
through required_secret_names: exactly the names listed there are put into
that application’s environment, and a Project value a Service does not name
never reaches it. A person can store the same values on the Project’s Project
Secrets page in the dashboard — prefer that for anything the customer would
rather not type into a chat, because a value passed through a tool call is
recorded in model context and the action log.
service_get returns the runtime_envelope: the limits and rules the
code you are about to write has to fit. Read it before choosing a stack, not
after a build fails. Its keys:
resources— the CPU and memory the application runs under, its size, its port and its health path, once the first build has recorded them.storage— that there is no persistent disk, which scratch paths are writable (/tmp,/run,/var/tmp) and how large they are.databaseandbacking_services— what this Service can reach and under which environment variable; see below.branch— which branch is built, and why that one.build_rules— how an image is built: nixpacks by default, your own Dockerfile only whenbuild_type: dockerfilenames it, and which runtime versions nixpacks picks when the repository declares none.runtime_rules— a read-only root filesystem, exactly one replica, no published port and no host mount, every capability dropped but binding a privileged port, and why an image that switches user at start-up serves nothing.egress_rules— outbound traffic leaves through the proxy only, on 80 and 443.dockerfile— the plainest Dockerfile of this Service’s runtime kind, binding thePORTthe platform sets and built and run under those rules;nullfor the default kindcontainerand before the first build.available_resource_classes,environmentandsecrets— the sizes that exist, the one environment there is, and how values reach the application.
backing_services is the part most worth reading before choosing a stack.
It lists what this Service can actually reach — a PostgreSQL database, a Valkey
cache, a Valkey queue — each with the environment variable its connection
string arrives under, and whether it survives a restart. An agent that assumes
only a database is available writes its own cache into process memory and its
own queue into a table; neither is right here, and neither is guessable.
Two things it also tells you, and both change what you should do:
- The cache is not durable. It has no volume, so a restart empties it. Anything that must survive belongs in the database.
- A backing service is the Project’s, one per kind. Every Service in the Project that attaches it reads it under the same variable, so nothing in the code needs to know whether another Service uses it too — do not write logic that branches on it.
available_on_this_plan says which kinds the team’s plan includes.
You can attach one the Project already runs, and create one it does not.
shared_resources_list shows what exists, which Services use it and where its
data lives; shared_resource_update attaches one to a Service or detaches it,
and shared_resource_create runs a new one and attaches it in the same call —
with size for a PostgreSQL instance from Pro, and parent_resource_id to
make one more database inside an instance the Project already runs, which
keeps two Services’ data apart at no cost against the plan.
Choose the database shape before creating anything. Call
shared_resources_list for the current Project first. If it lists a PostgreSQL
instance, create the new database inside that instance with
shared_resource_create and its parent_resource_id; do not create a second
instance. If the Project has no PostgreSQL instance, creating one with
kind: "postgres" is the right step when the plan includes it and the user
confirms the billed service — even when another Project in the same Team already
runs PostgreSQL. Backing services never cross the Project boundary, so an
instance in another Project cannot be attached or used as this Project’s
database.
When a database is attached, the tool returns its connection string and the
environment-variable name for the application to use. The link does not
store that value automatically: save it with project_secret_set for the same
Project, then include exactly that name in the Service’s
required_secret_names on service_build. A deploy reads only its own
Project’s named values; a value from another Project is not supplied.
shared_resource_resize moves a running PostgreSQL instance to another size
the plan includes, or back to the cluster’s default: it restarts under the new
limits, clients reconnect, the data and every attached Service stay.
shared_resource_delete removes a service and everything in it — confirmed,
and not recoverable, because Aidrop keeps no backups. A copy is yours to take
first: Taking your work with you says how.
shared_resource_inspect looks inside a cache or a queue: memory against its
limit, how many keys, whether it has evicted anything, the hit rate, and each
key with its type and length. The lengths are the point — a queue’s depth is
the length of the key your application writes to, not a server statistic, so
this is what answers “is the queue draining”. A cache that evicts is a cache
working; a queue that evicts is full and has thrown away work nobody did, and
the reply says which of the two you are looking at.
shared_resource_purge empties a cache or a queue, or removes one named key.
Confirmed, and not recoverable: a cache refills itself, a queue holds work that
has not been done yet. There is no delete-by-pattern, on purpose — it would
mean scanning and then deleting what matched, and a key your application wrote
in between would go with it.
shared_database_query runs one SQL statement against a PostgreSQL instance,
or against one database inside it, and hands back what it printed as CSV. It
is the only way to reach that database from outside a deployed application:
the instance sits on a private network with no published port, so checking
whether a migration landed used to mean deploying something that checks it.
Any statement the database accepts — a SELECT to look, a CREATE TABLE or
INSERT to change — because it is your data and your agent already writes its
schema through the application it builds. A statement is stopped after 30
seconds and the answer is cut at 64 KB, which the reply says when it happens.
Three things bound creating. The plan decides which kinds may exist and
refuses the rest by name. One per kind per Project is the shape, so a
second request is refused with the name of the first rather than quietly
running another container. And it takes an explicit confirmed, because
the service is billed to the customer for as long as it exists — that is their
decision to make, not their agent’s.
A newly linked service reaches the application on its next build, not immediately.
When bringing a repository that might already be in Aidrop, read
repositories_list first: it says which Services already build from it, so the
agent offers the existing Service rather than creating a duplicate — or a second
Service on the same repository, when that is what the product needs. service_build
checks the repository itself when it links it — that it exists, that the App
can read it — and refuses by name when it cannot. The user must install the
Aidrop GitHub App in the browser before a GitHub repository can be linked; the
agent never asks for GitHub credentials or writes source code to GitHub.
An agent with no local git/shell at all — a chat-only client, not a terminal
or IDE agent — has no use for a credential, since there is no local git to
hand it to, and nothing else covers that case. Aidrop accepts no uploaded
archive and never commits on your behalf, so a chat-only session reads the
record and builds what is already pushed; code enters a Service from a shell or
from a connected GitHub repository.
Administering the organisation is not something an agent does. Its members and their roles, and its runtime values, are decisions made in the dashboard — there is no tool for either.
Its lifecycle is the opposite. A Project is the product and a Service is one
deployed piece of it, and which pieces a product needs is settled while it is
being built, so creating, renaming and removing them are project_create,
project_delete, service_build (the first call makes the Service),
service_update and service_delete. The dashboard
lists what is running and operates it. Confirm a delete with the customer
before calling it: their application comes off the cluster and its address
stops answering. Their code does not move — the repository stays in Team Git
and can still be cloned.
A Service is created with a name and a description, and nothing else decides
what it is; how it builds and runs is what the agent passes to service_build,
because the agent wrote or read the code and Aidrop did not. The repository
layout rule still holds and is enforced by the runtime: one deployable,
because a Service runs one container on one port.
Connecting
aidrop.it is not listed in any client’s connector directory yet. Claude Code, Codex and the ChatGPT desktop app install it as a plugin from the aidrop.it marketplace; every other client is set up as a custom connector: you give it the server address once, and the OAuth consent screen it opens on the first call does the rest. There is no key to paste and no skill or workflow to install — the connector carries what the agent needs. These are the same steps as on aidrop.it/install.
https://aidrop.it/mcpClaude (web & desktop)
- Open Settings → Connectors and choose Add custom connector. On a Team or Enterprise plan an owner adds it under Organization settings → Connectors → Add → Custom → Web first, and members then find it under their own Connectors.
- Name it aidrop.it, paste
https://aidrop.it/mcpas the remote MCP server URL and click Add. The server registers your client itself. - Click Connect and approve the access screen — your Team, with
service:readandservice:writeover it. - Ask your agent to deploy — for example, “Create a Service in aidrop.it and deploy this repository.” A chat-only session reads and builds what is already pushed; the code itself comes from Claude Code, Codex or Cursor.
Claude Code
aidrop.it ships as a plugin in its own marketplace, so Claude Code needs no server address typed by hand.
- Add the marketplace and install the plugin from your terminal:
claude plugin marketplace add aidropit/pluginsclaude plugin install aidropit@aidropit- Start
claude, run/mcp, pick aidropit and sign in. The browser opens the access screen — your Team, withservice:readandservice:writeover it. - Ask your agent to deploy — for example, “Create a Service in aidrop.it and deploy this repository.”
Codex
aidrop.it ships as a plugin in its own marketplace, so Codex needs no server address typed by hand.
- Add the marketplace and install the plugin from your terminal — the Codex desktop app and Codex in ChatGPT read the same configuration:
codex plugin marketplace add aidropit/plugins --sparse .agents/pluginscodex plugin add aidropit@aidropit- Sign in when the install prompts you, or run
codex mcp login aidropit, and approve the access screen — your Team, withservice:readandservice:writeover it. - Ask your agent to deploy — for example, “Create a Service in aidrop.it and deploy this repository.”
ChatGPT
The same plugin installs into the ChatGPT desktop app through the Plugins Directory.
- Register the marketplace once from your terminal (it needs the Codex CLI):
codex plugin marketplace add aidropit/plugins --sparse .agents/plugins- Restart the ChatGPT desktop app, open the Plugins Directory, pick the
aidrop.it marketplace and click Install plugin on aidrop.it.
Sign in when prompted and approve the access screen — your Team, with
service:readandservice:writeover it. - Ask your agent to deploy. ChatGPT has no shell, so it reads and builds what is already in a repository; use Codex to write and push the code.
Without the desktop app, ChatGPT on the web still takes the server as a custom
connector: Settings → Connectors → Advanced settings → Developer mode
(Plus, Pro, Team and Enterprise; a workspace admin turns it on), then
Connectors → Create, name it aidrop.it, paste
https://aidrop.it/mcp as the MCP server URL and choose OAuth.
Cursor
- Open Cursor → Settings… → Cursor Settings → Tools & MCP and click
New MCP Server. Cursor opens
mcp.json; add the entry:
{ "mcpServers": { "aidrop": { "url": "https://aidrop.it/mcp" } }}- Save, then click the server’s Needs login link on the same settings screen and approve the access screen.
- Ask your agent to deploy — for example, “Create a Service in aidrop.it and deploy this repository.”
Other agents
Any client that supports remote MCP servers over streamable HTTP works — VS Code, Continue, Cline, Windsurf, Zed, and others.
- Add the server to your client config — dynamic client registration means there is nothing to pre-register:
{ "mcpServers": { "aidrop": { "type": "http", "url": "https://aidrop.it/mcp" } }}- Complete the consent screen your client opens on the first call. A client that cannot perform an OAuth authorization cannot connect — that is the whole of the credential story since team API keys were removed.
- Ask your agent to deploy. A client with no local git or shell cannot put code into aidrop.it — use Claude Code, Codex or Cursor for that.
Every connection you make shows up under Management → Connected apps in the dashboard, and is revoked from there.
Try it
Verify the connection before relying on it:
- Claude Code: open
/mcpin a session —aidropitshould show as connected, and the same screen lets you re-authenticate. - Any client: ask the assistant to call
services_list— you should see the Services your Team member account can open. If the tool is missing, the OAuth grant predates Service access — reconnect so it carries theservice:readandservice:writescopes.
What the runtime gives your code
PORTis set in the environment, to the port the route points at. Bind it rather than a literal: an application that hard-codes 3000 while its profile says 8000 is running and unreachable, which reads as a broken app.- One container, one port, one replica. A Service deploys a single service. If a product genuinely needs two independently deployable services, that is two Services with two repositories, and worth saying to the owner rather than laying one repository out as though both will run.
- Your own
Dockerfileis the universal path. It is what makes Java, PHP, Ruby, Rust and .NET work here: passbuild_type: dockerfileandbuild_dockerfile_pathtoservice_build, and Aidrop builds that file as-is and infers nothing. activemeans a container is running and answering. A deployment whose container does not stay running isfailedand carries the task’s own error. One that runs but answers nothing on its port, or answers 5xx on itshealth_pathfor longer than a start-up takes, isfailedtoo, with the reason: bind thePORTAidrop sets, and make the health path answer.- Application files are not durable. The root filesystem is read-only and scratch is cleared on restart. Put records in PostgreSQL and uploads/media in object storage — the runtime gives a Service no data volume, so a local path is not a place to keep anything.
Tools
The product and its pieces
| Tool | Scope | What agents use it for |
|---|---|---|
projects_list |
service:read |
List the Team’s Projects — the products its Services belong to — with the ids service_build and services_list take. |
project_create |
service:write |
Create a Project: the product a set of Services belongs to. A developer or admin role in the Team is required. |
project_delete |
service:write |
Archive a Project and every Service in it. Admin role; confirm with the customer first. Code is not touched. |
services_list |
service:read |
List the Services the caller can open, with the Project each belongs to and whether its application is running. Narrow to one Project with project_id. |
service_get |
service:read |
Read one Service — its Project, repository, address, latest build and deployment attempt, the exact active deployment and commit serving now, and the runtime envelope the code has to fit. This is the call to poll after service_build. |
project_get |
service:read |
Read one Project: its name, what it is for, and the Services in it. |
project_update |
service:write |
Rename a Project or change what it is for. The address and the repository are unaffected. |
service_update |
service:write |
Change a Service’s settings: its name and what it is for. The address and the repository keep the slug the Service was created with. |
service_delete |
service:write |
Archive a Service: its application is removed from the cluster and its address stops answering. Code is not touched. Confirm with the customer first. |
Repositories
| Tool | Scope | What agents use it for |
|---|---|---|
repositories_list |
service:read |
List the Team’s repositories — on its aidrop.it Git service and on GitHub through the Aidrop GitHub App — with the Services each one backs. |
repository_get |
service:write |
Read one repository: its branch, whether it has commits yet, the Services it backs, and — for an aidrop.it one — the credential your own git pushes with. Developer or admin role. |
repository_create |
service:write |
Create an empty repository on the Team’s aidrop.it Git service, for code that is not on GitHub; answers the clone URL and the push credential. Developer or admin role. |
repository_delete |
service:write |
Delete a repository on the Team’s aidrop.it Git service, with every commit in it. confirmed, not recoverable, and refused while a Service still builds from it. |
The build loop
| Tool | Scope | What agents use it for |
|---|---|---|
service_build |
service:write |
Build the tracked branch’s head and deploy it to the Service’s address, which is open to the internet from that first deploy. The first call links the repository (repository_ref) and records the runtime settings; pass branch to follow another branch. |
service_logs |
service:read |
The latest build’s log, credential-redacted and bounded. A run that stopped before a build was queued answers its stop reason. |
service_tags_list |
service:read |
The images built for this Service, newest first: tag, commit, status, which one runs now, which are runnable. |
Run it, open it
| Tool | Scope | What agents use it for |
|---|---|---|
service_start |
service:write |
Resume the application after a pause; with a tag from service_tags_list, start that built image instead — a rollback is this call with an older tag. |
service_stop |
service:write |
Pause the application: the container stops and the address stops answering. Takes confirmed. |
Your own domain
| Tool | Scope | What agents use it for |
|---|---|---|
service_domain_add |
service:write |
Claim a domain the customer owns for a Service, and answer the one DNS record they have to create — a CNAME at the Service’s own address for a subdomain, an A record or apex alias for a bare domain. From the Pro plan, and only for a Service that has been built. Nothing resolves until the record exists and service_domain_verify proves it. |
service_domain_verify |
service:write |
Check the record and, when it is there, start serving the Service on that name — certificate included. DNS takes minutes to hours to spread; a name that is not proved yet is not a failure, call this again. |
service_domain_remove |
service:write |
Stop serving a custom domain. The Service keeps its aidrop address, which cannot be removed. confirmed. The DNS record at the registrar is the customer’s to delete. |
The values an application reads
| Tool | Scope | What agents use it for |
|---|---|---|
project_secret_set |
service:write |
Store a value the Project’s applications read from their environment — an API key, a token, a connection string to something Aidrop does not run. Never answered back by any tool. |
project_secret_delete |
service:write |
Remove one by name. A Service that still names it in required_secret_names will refuse to build. |
Backing services
| Tool | Scope | What agents use it for |
|---|---|---|
shared_resources_list |
service:read |
List the Project’s databases, caches and queues — status, the variable each arrives under, which Services use it, and where its data lives. |
shared_resource_create |
service:write |
Run a new database, cache or queue for the Project and attach it to a Service in one call, or create one more database inside a PostgreSQL instance with parent_resource_id. An instance is billed, so it takes confirmed; size picks a PostgreSQL class from Pro. |
shared_resource_update |
service:write |
Attach a backing service to a Service, detach it, or change the variable the Service reads it as. |
shared_resource_resize |
service:write |
Move a PostgreSQL instance to another size the plan includes — micro, compact from Pro, dual from Scale, large on Business — or back to the default. It restarts; the data and the attachments stay. A size the pot cannot hold is refused with the numbers. |
shared_resource_inspect |
service:read |
Look inside a cache or a queue: memory against its limit, key count, evictions, hit rate, and each key with its type and length — which is how a queue’s depth is read. |
shared_resource_purge |
service:write |
Empty a cache or a queue, or remove one named key. confirmed, and not recoverable. |
shared_database_query |
service:write |
Run one SQL statement against a PostgreSQL instance, or one database inside it, and get what it printed as CSV — the only way to read that data from outside a deployed application. Stopped after 30 seconds, answer cut at 64 KB. |
shared_resource_delete |
service:write |
Destroy a backing service and the data in it; deleting an instance deletes the databases inside it. confirmed, and not recoverable. |