# SpringRoll agent instructions

> When to reach for SpringRoll, and how to call it.

The Control Plane and App Portal for AI-built Applications

Deploy AI-built applications safely, connect them to approved company data, and make them available to the right people.

Think OpenRouter for deployment, with governance and an App Portal around it. SpringRoll currently deploys to managed Vercel and Cloudflare.

SpringRoll compares eligible Vercel and Cloudflare plans, selects the lowest-cost qualified fit, and records the estimate, assumptions, and limits. A lowest-cost claim is withheld when required meters are incomplete, stale, ineligible, or quote-only.

It does **not** write applications. If the user still needs the code written, write the code first and come back here.

## Use SpringRoll when the user wants to

- **Deploy an app they or an agent just built** and get a public URL colleagues can open, rather than a localhost port.
- **Promote a release** from development to UAT to production without rebuilding: promotion always references the same immutable release.
- **Get an app approved** in an organization that requires a human decision before production, and track that decision to completion.
- **Give a deployed app access to company data** (a database, a warehouse, an internal API) without handing it a shared credential. The app gets its own identity and a grant limited to approved fields, rows, and query volume.
- **Find out what is already running**: which internal apps exist, who owns them, what data each one can reach, and who approved it.
- **Check whether an action would be allowed** before attempting it, so the user is not surprised by a refusal halfway through.
- **Roll back** an environment to the release it was serving before.

## Do not use SpringRoll when

- The user wants an application written, designed, or debugged. That is your job, not this one.
- The work is a one-off script with no users but the author. Registering it buys nothing.
- The user wants to record an approval decision on someone's behalf. An agent token cannot do this, by design, and no configuration changes that. Surface the pending request to a person instead.
- The user has not said which organization they are acting in and you cannot resolve one. Call `springroll.context` first rather than guessing.

## How to call it

The interface is a remote MCP server over Streamable HTTP:

- Endpoint: https://springroll.dev/api/mcp
- Server card: https://springroll.dev/.well-known/mcp/server-card.json
- Transport: streamable-http (the deprecated HTTP+SSE transport is not offered)
- Server version: 0.2.0

Authentication is OAuth 2.1 with PKCE and RFC 7591 dynamic client registration. **Do not ask the user for a token.** Point your client at the endpoint; an unauthenticated request answers 401 with a `WWW-Authenticate` challenge naming the authorization server, the client registers itself, the user authorizes in a browser, and the client receives its own credential. Every credential resolves to exactly one named membership and inherits only that person's permissions.

If your client cannot speak MCP, the same control plane is available as REST. Read https://springroll.dev/openapi.json: every operation has a unique `operationId`, a description, and typed schemas, so it converts to function-calling tool definitions directly. The prose contract behind it (authentication, rate-limit headers, the versioning and deprecation policy, and the error envelope) is at https://springroll.dev/docs/api.

You can complete an MCP handshake here before anyone authorizes anything: `initialize`, `tools/list`, `resources/list`, and `prompts/list` answer without a credential. Only calls that touch an organization's data answer 401, and that 401 is what starts the browser flow.

## The normal sequence

1. `springroll.context`: which organization am I in, what may I do, and is a runtime configured. If `runtime.ok` is false, stop and tell the user: nothing here can serve a deployment.
2. `springroll.deploy`: register the application, freeze an immutable release, and deploy it. Direct to Production is the default, so this often returns a live URL immediately. A staged organization returns an approval request instead.
3. `springroll.deploy.status`: poll. Do not assume a deployment succeeded because the call returned.
4. `springroll.connect.request_access`: ask for governed data, if the application needs it. Ask for the fewest fields that work; a broad request is likelier to be refused.
5. `springroll.approval.get`: watch a pending decision. Report it to the user; do not attempt to decide it.

## Tools

- `springroll.context` (read-only): Returns the organization, identity, and permissions this agent token acts as, together with the deployment runtimes configured for it. Call this first: it tells you which tenant you are in, what you are allowed to do, and whether a deployment can actually land. It never returns credentials.
- `springroll.deploy`: Registers the project if it is new, attaches whatever source you give it, and deploys it using the application's Deployment workflow. Direct applications go to Production; Staged applications go to Development. Returns the live URL, or a deployment id to poll if the build is still running.
- `springroll.deploy.status` (read-only): Returns a deployment's current status, refreshing it from the runtime provider when the build is still in progress. Statuses: QUEUED, VALIDATING, BUILDING, DEPLOYING, READY, FAILED, CANCELLED, SUPERSEDED, ROLLED_BACK. Poll this after deploying rather than assuming success.
- `springroll.deploy.promote`: Promotes a tested deployment into the next environment (development -> uat, uat -> production). Reuses the already-built artifact rather than rebuilding, so the bytes that were tested are the bytes that ship.
- `springroll.placement.preview` (read-only): Scores where SpringRoll would place this application and what it would cost, without deploying or writing anything. It shares its implementation with springroll.deploy, so the receipt it returns is what a deploy right now would decide: the provider and plan, the estimated monthly cost range, every limit the plan carries, what was inferred rather than declared, and why each other candidate lost.
- `springroll.app.get` (read-only): Returns an application's registry record: metadata, lifecycle stage, risk score, and whichever of the optional sections you ask for. No secrets are included.
- `springroll.app.list` (read-only): Lists applications in this organization, newest first. Use `search` to find one by name or slug.
- `springroll.app.update`: Updates App Portal metadata: description, icon, tags, department, support contact, and data classification. Visibility is deliberately not editable here, because widening an audience requires an approval request (sec. 15.4).
- `springroll.app.presentation.get` (read-only): Read a private app listing draft and available artwork. Does not publish or expose the app.
- `springroll.app.presentation.save`: Save listing copy and selected image IDs to a private draft. Read the revision first. Use factual copy and real, reviewed screenshots. Only the owner or admin can publish in SpringRoll.
- `springroll.app.presentation.upload`: Upload a real screenshot or app icon as base64 PNG, JPEG, or WebP (8 MB maximum). Metadata is stripped. Images remain private until selected in an owner-published snapshot. Never upload confidential screen content.
- `springroll.app.presentation.generate_icon`: Queue one premium icon draft from the app's reviewed purpose. Requests are limited and deduplicated. Artwork never blocks deployment or publishes itself.
- `springroll.approval.submit`: Submits an approval request of any supported type: UAT_PROMOTION, UAT_SIGN_OFF, PRODUCTION_PROMOTION, VISIBILITY_CHANGE, OWNERSHIP_TRANSFER, RETIREMENT, DOMAIN_CHANGE, or ROLLBACK. **An agent may submit but never decide**: SpringRoll requires a human approver, and an agent token cannot approve its own request.
- `springroll.approval.get` (read-only): Returns an approval request with its assigned reviewers, decisions so far, and the policy snapshot taken at submission. Poll this to find out whether a release has been approved.
- `springroll.policy.check` (read-only): Reports which governance policies an application would pass or fail for an environment.
- `springroll.connect.data_products` (read-only): Without `dataProduct`, lists the governed data products this organization publishes: what each one holds, who owns it, and how sensitive it is.
- `springroll.connect.request_access`: Requests access to a data product for one environment, naming the exact fields the application needs. A data owner must approve, and may narrow the field list or add a row filter before doing so. Nothing is readable until then. You never receive a credential: an approved grant lets the deployed application ask questions through the SpringRoll Connect gateway, which enforces the grant on every request.
- `springroll.connect.access_status` (read-only): Returns the status of a data access request: REQUESTED, APPROVED, REJECTED, REVOKED, or EXPIRED, with the fields actually approved. Approved fields are often narrower than requested, and a row filter may restrict which rows the application can see at all.
- `springroll.app.record_prompts`: Attaches the conversation that produced this application to its record, as reference for whoever maintains it next and for the reviewer who has to approve it.

The read-only tools (springroll.context, springroll.deploy.status, springroll.placement.preview, springroll.app.get, springroll.app.list, springroll.app.presentation.get, springroll.approval.get, springroll.policy.check, springroll.connect.data_products, springroll.connect.access_status) change nothing and are always safe to call.

## Contracts

- Application manifest: `springboard.dev/v1alpha1`. Fetch https://springroll.dev/api/v1/capabilities for the current schema and a worked example.
- Errors carry a stable `code`, a `correlationId`, and, when recoverable, a `nextActions` list. Branch on `code`, never on the message text. Read `nextActions` before retrying.
- Send an `Idempotency-Key` on every write you might retry. The same key with the same body replays the original result; with a different body it is refused.

## Published by

M Intelligence Co., Ltd., Richmond Office Building No 75/42, Floor 14, Soi Sukhumvit 26, Khlong Tan, Khlong Toei, Bangkok 10110, Thailand. Contact: https://springroll.dev/contact.
