Server4Agent
Guides

A full agent loop

Connect Server4Agent to your agent over MCP and it can build and ship software on its own. The model sees Server4Agent's tools and decides when to use them.

The loop

This page shows the lower-level path. Your agent drives the primitives itself. If you just want a build done, call prompt and let the build agent handle it (see Examples). The loop below is for cases where your agent wants direct control over each step.

Expose Server4Agent's MCP tools to your agent, then run a normal tool-calling loop. Your agent provisions a server, writes files, runs commands, and deploys, all by emitting tool calls. Framework-agnostic Python; the same pattern works in any runtime that speaks MCP.

agent.py
import asyncio
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

MCP_URL = "https://mcp.server4agent.com"
HEADERS = {"Authorization": f"Bearer {SERVER4AGENT_API_KEY}"}

async def run(goal: str):
    async with streamablehttp_client(MCP_URL, headers=HEADERS) as (r, w, _):
        async with ClientSession(r, w) as mcp:
            await mcp.initialize()

            # Server4Agent's tools become callable functions for your model.
            tools = (await mcp.list_tools()).tools

            messages = [{"role": "user", "content": goal}]
            while True:
                # your LLM of choice, it sees the Server4Agent tools
                reply = llm.chat(messages, tools=tools)

                if not reply.tool_calls:
                    print(reply.content)        # agent is done
                    return

                for call in reply.tool_calls:
                    # the model decided to create_server / write_file / deploy / ...
                    result = await mcp.call_tool(call.name, call.arguments)
                    messages.append({
                        "role": "tool",
                        "tool_call_id": call.id,
                        "content": result.content[0].text,
                    })

asyncio.run(run("Build a landing page with a waitlist form and deploy it."))

What the agent does

You give it a goal; it figures out the steps. A common trace looks like this:

trace
# A typical trace the model produces on its own:
→ create_server()                                  # gets srv_2k9, a persistent box
→ write_file(srv_2k9, "app/page.tsx", "...")       # authors the app
→ write_file(srv_2k9, "package.json", "...")
→ exec(srv_2k9, "npm install && npm run build")    # builds it
→ deploy(srv_2k9)                                  # → https://srv_2k9.apps.server4agent.com
"Done, your waitlist page is live at https://srv_2k9.apps.server4agent.com"

Bringing up imported code

A project doesn't have to start empty. Create it with a git or archive source and Server4Agent seeds the workspace with your code, then initializes it — a two-part bring-up. First a deterministic seed (clone or unpack, no agent). Then the on-server agent detects the stack, installs dependencies, starts the app, and confirms the service responds. The project reports its progress as seeding → installing → starting → ready (or failed) on init_phase.

bring-up trace
# Point a project at a repo; the on-server agent brings it up on its own:
→ seeding           git clone … ; scan .env.example + process.env for required env
→ awaiting_secrets  needs DATABASE_URL, STRIPE_SECRET_KEY → you supply them, then:
→ installing        detects package.json → npm ci
→ starting          nohup npm start &          # binds the project's listen port
→ ready             curl -s localhost:$PORT → 200   # service confirmed up
# It writes .server4agent/{install.sh,start.sh,healthcheck.json} so re-imports
# and pause/resume replay the exact recipe instead of re-detecting.

"Ready" means the app's port is listening and its healthcheck path answers below the expected status — a confirmed-up service, not just a process that started. A repo that ships a .server4agent/ recipe (an install.sh, the start.sh the runtime already uses for pause/resume, and an optional healthcheck.json) comes up deterministically with no tokens spent; a repo without one gets the agent, which writes the recipe as it goes so the next bring-up is free.

Bring-up also reads the code's environment: it scans .env.example and process.env / os.environ references and lists them as required_secrets. Anything you didn't set up front pauses the project at awaiting_secrets and fires project.secrets_required — so instead of a cryptic crash you get a typed list of the keys to provide. Supply them (secrets are write-only env, bound to the project or server-wide) and bring-up resumes.

Long-running work

Builds, bring-ups, and deploys can take a while. Rather than poll, subscribe to webhooks and let your agent react when a project reports project.ready or a deployment goes live.

webhook.sh
# Don't block your agent waiting for long builds, subscribe to events.
curl -X POST https://api.server4agent.com/webhooks \
  -H "Authorization: Bearer $SERVER4AGENT_API_KEY" \
  -d '{ "url": "https://example.com/hooks",
        "events": ["project.ready", "deployment.live"] }'

That's the whole model: your agent brings the intelligence, Server4Agent gives it hands, a real server, a workspace, and a public URL.

Connect an agent

Create a key, paste the MCP config, and give your agent a persistent server it can build on.

MCP setup →