GUIDES

The MCP provisioning server

Point a coding agent at one URL and it builds the project for you — prompt, user schema, tools, policies, connected MCP servers, limits, budget and scheduling.

Agentifys runs a hosted MCP server at https://agentifys.ai/mcp. Connect it to Claude Code, claude.ai or Claude Desktop with a scoped Agentifys API token and the agent gets twelve tools that take an organisation from nothing to a configured project — and then tell you, honestly, what is still missing. It creates and configures. It never deletes anything, and it never accepts a secret as a tool argument.

Two different things share the letters MCP here. MCP servers is Agentifys as an MCP client — you attach someone else's server to a project so its tools become your agent's tools. This page is Agentifys as an MCP server, driving the console API. The two must never be pointed at each other: registering https://agentifys.ai/mcp as a project's MCP server is refused, because it would hand that project's end users the ability to create and configure projects.

Get a token

The server holds no credential of its own. Every call forwards your token to the console API, so it can never do anything you could not already do. Mint one in the console under Team → API tokens.

FieldTypeDescription
scopeconfigureWhat provisioning needs: create and configure. The other value, read, can only read — every write comes back as EERRAA_FORBIDDEN.
project_idoptionalPins the token to exactly one project. Every other project in the org answers 403. Leave it unset to let an agent create new projects.
expires_days90Default 90 days, between 1 and 365. A token can also be revoked at any time; revocation lands on the very next request, with no cache in between.
The valueeat_…eat_ followed by a 16-hex id and a 48-hex secret, 69 characters. Returned exactly once — only a SHA-256 hash is stored, so it cannot be shown again or recovered.

Minting is admin-and-above. A token can never mint another token, and its powers are capped at its creator's current membership — promote the creator and existing tokens do not widen; remove them and their tokens are revoked outright.

This is not the era_ project key, and the two are handled in opposite ways. era_ is publishable: it belongs in browser code and authenticates the public /v1 surface. eat_ is an admin credential: server-side only, never in a page, never in a file you commit. They ride the same Authorization: Bearer header, which is exactly why a mix-up is easy — and why it is a real incident in either direction.

Connect your client

The transport is Streamable HTTP. Authentication is the token on the Authorization header, and nothing else — there is no OAuth flow to complete.

Claude Code

bash
# One project, one command. --scope user keeps it out of the repo.
claude mcp add --transport http agentifys https://agentifys.ai/mcp \
  --header "Authorization: Bearer eat_..." \
  --scope user

--scope user stores the server in your personal config, available in every project. --scope project stores it in .mcp.json inside the repository, which is shared with everyone who checks it out.

Do not put a real token in a --scope project entry. .mcp.json is a file in your repo, so the credential goes into version control and into every clone. Use --scope user, or use an environment-variable expansion in the header so the file carries a name and not a secret.

claude.ai — custom connector

FieldTypeDescription
Remote MCP server URLrequiredhttps://agentifys.ai/mcp
AuthenticationNoneNot "Always required". That setting starts an OAuth handshake, and this server has no OAuth — its 401 is deliberately not advertised as an OAuth challenge, so probing it mis-detects and the connector never finishes connecting.
Additional request headersAuthorizationValue: Bearer eat_… — this is where the credential goes.
The server answers 401 on every method, including initialize, when the header is missing or is not an eat_ token. A browser session token is refused on purpose: a session carries no scope, so accepting one would skip every restriction described on this page.

Claude Desktop

json
{
  "mcpServers": {
    "agentifys": {
      "type": "http",
      "url": "https://agentifys.ai/mcp",
      "headers": {
        "Authorization": "Bearer eat_..."
      }
    }
  }
}

The twelve tools

One tool is one logical provisioning step, not one HTTP call — eerraa_get_project reads six endpoints, eerraa_enable_tools turns on forty tools in one request. They are listed here in the order an agent uses them.

FieldTypeDescription
eerraa_list_projectsreadThe entry point. Resolves a project NAME to an id — no other tool accepts a name.
eerraa_get_projectreadOne project’s whole configuration, plus a list of what is still missing from it.
eerraa_create_projectcreateCreates a bare project and returns its id. Never a starter template: a template seeds tools and a policy that nothing here can delete.
eerraa_configureconfigureModel, rate limit, monthly token budget, alerts and scheduling. Expect to call it twice — see the order below.
eerraa_set_user_schemaconfigureDeclares the user.data fields the prompt, the policies and the tools all reference. Merges by default; can replace outright.
eerraa_set_promptconfigureReplaces the system prompt. Auto-versioned, so the previous version is kept and restorable, and it reports any variable that will not resolve.
eerraa_add_toolcreateCreates one tool with a JSON Schema input. Created as a mock — see what it will not do.
eerraa_connect_mcp_servercreateRegisters an external MCP server on the project. For an unauthenticated server it also imports the catalogue, which doubles as the connectivity test.
eerraa_discover_mcp_toolsconfigureRe-imports a registered server’s catalogue and returns it. Imported tools arrive disabled; a re-run preserves every enable and confirmation choice already made.
eerraa_enable_toolsconfigureEnables or disables many tools in ONE call. Disabling is reversible configuration — it is the supported way to "remove" a tool.
eerraa_add_policycreateCreates one policy: deny named tools, or inject context, when a condition about the end user holds. Every tool it names is checked against the project’s real tools first.
eerraa_verify_projectreadThe readiness checklist: every check as pass / warn / fail with the exact fix, the outstanding manual steps, and one next action.

The order, and how the agent keeps it

The sequence has real constraints, and an agent will not infer them from twelve descriptions. So every response carries status, what changed, a manual_steps array, and next_action — one imperative sentence naming the tool to call next. Following that chain is how the ordering survives.

text
eerraa_create_project
  -> eerraa_configure {identity_mode: "signed"}   returns the console step; a token may not set it
  -> eerraa_set_user_schema                       declare the user.data fields first
  -> eerraa_set_prompt
  -> eerraa_add_tool          (once per tool)
  -> eerraa_connect_mcp_server
       -> [manual: paste the server's token in the console]
       -> eerraa_discover_mcp_tools
       -> eerraa_enable_tools                     ONE call with every tool
  -> eerraa_add_policy        (once per policy)
  -> eerraa_configure {scheduling.writable_tools} now that the tools exist
  -> [manual: add a model provider key in the console]
  -> eerraa_verify_project
FieldTypeDescription
Schema before prompthardA prompt may use {{user.data.<field>}} only for fields the schema declares. An undeclared one is left as literal braces in the text the model reads, with no error anywhere.
Tools before policieshardA policy naming a tool that does not exist still matches, still counts a trigger, and changes nothing. The tool refuses rather than creating one.
Tools before writable_toolshardThe scheduling endpoint does not validate that field at all, so a name sent before its tool exists is stored dead and every scheduled task that asks for it is refused at run time, months later.
Signed identity before per-user OAuthhardPer-user OAuth binds each token to a verified user, so the project must be in signed identity mode before such a server will attach.
configure, twiceby designOnce after create for limits, budget, alerts and identity; again after the tools exist for scheduling.writable_tools. The server drops any name that is not an existing tool with requires_confirmation set, and reports every drop.
eerraa_verify_project is the recovery path, not just the final check. An agent that has lost the thread gets one sentence back instead of a checklist to re-derive. It is also the honest answer to "is this done?" — run it before believing any claim that a project is ready.

A prompt that puts an agent on the rails:

text
Use the agentifys MCP server to build me a support agent.

Create the project, declare a user schema with plan_tier and account_id,
write the prompt, add a create_ticket tool, and deny it for viewers.

Follow next_action on every response rather than guessing the order, read
the manual_steps array out to me at the end, and do not tell me the
project is ready until eerraa_verify_project says so.

What it will not do, and why

These are structural, not advisory. Most of them are enforced twice — once by the token itself, and once by the provisioning server's own capability list, which is narrower still.

FieldTypeDescription
No deletes, at allstructuralNot a project, tool, policy, MCP server, document, session or user. There is no delete verb anywhere on the server’s outbound surface, so one cannot be written at a call site. Disabling is reversible; deleting is not. A request shaped like a removal is refused by name, with a pointer to the console.
Cannot spend your tokensstructuralThe playground and every test route are closed to a machine credential, so the agent cannot run a turn against your provider key while it works. This is the real cost control, not a rate limit.
Cannot touch your teamstructuralNo adding, removing or re-roling a member, no invites, and no minting another API token. A stolen token must not be able to widen the blast radius of its own theft.
Cannot rotate the project keystructuralRotating the era_ widget key breaks every embedded page live, instantly, with nothing to notice it.
Never ownerstructuralA token’s role is admin or viewer and the database refuses anything else, so every owner-only check in the console API fails closed against a machine.
Cannot read end usersstructuralTranscripts, logs payloads, end-user profiles, memory and the credential-vault inventory are all closed. A provisioning agent configures the tenant; it does not read the tenant’s customers. Non-personal telemetry stays readable.
Cannot downgrade identitystructuralidentity_mode and the origin allowlist are refused from a token, so a stolen credential cannot quietly turn a signed project back into a forgeable one. Ask for identity_mode and you get a console step back, never a silent no-op.
Cannot set a tool’s egressstructuralexecutor_type and the webhook_* fields decide where an end user’s stored credentials get sent, so they are refused from a machine token. Everything else about a tool — description, schema, confirmation, triggers, enable state — stays available.

Secrets are never tool arguments.

There is no tool that takes a model provider key, and eerraa_connect_mcp_server takes no server token. A credential passed as a tool argument is written to your transcript and to your model provider's logs before it ever reaches Agentifys. Those steps come back instead as an entry in the manual_steps array — {id, title, why, who, where, steps, blocks, verify}, with a deep link into your console.

When a manual step blocks a required capability, the response's top-level status is blocked, not ok — however well the call itself went. Reporting success on a project that cannot answer a single message is the failure this whole surface is built against, so the status is demoted rather than the warning being buried in prose.

The one auth value the server may set is not a secret. Connecting a server with per_user_credential stores the template {{user.creds.<name>}}, which is resolved per turn from each end user's own vault — see per-user credentials.

The honest limits

Two of these are not bugs to be fixed later. They are what the design chose, and knowing them up front saves an afternoon.

FieldTypeDescription
Token only, no OAuthby designThere is no OAuth flow. A client that goes looking for OAuth metadata gets a clean JSON 404 saying so. In claude.ai, set Authentication to None and put the token in a request header.
Provisioning ends by handby designA project with no model provider key cannot answer a single message, and adding that key is a console action — so a clean run ends at a manual step, not at "ready". Hand the manual_steps list to a human and re-run eerraa_verify_project afterwards.
Every tool starts as a mockconsequenceA tool created here answers with a canned placeholder and changes nothing anywhere until a human sets its webhook in the console. eerraa_verify_project FAILS a project whose enabled tools are all mocks, and warns when some are.
No console-only fieldsconsequenceIdentity mode, the origin allowlist, the widget key, tool egress and provider keys are all set by a person. The agent gets a deep link for each, not an error you have to decode.
Discovery is slowpracticaleerraa_discover_mcp_tools drives a full remote MCP handshake and can take up to a minute against a slow server. Give your client a timeout above that.
Retries can duplicatepracticalThe four creating tools honour an Idempotency-Key for 15 minutes, keyed on your credential, the key, the tool and its arguments. Reusing a key with different arguments is refused, never replayed. Without a key, a retried create is a second thing that nothing here can delete.
Tool failures arrive as data, not as a protocol error, and every code is prefixed so you can branch on it: EERRAA_INVALID (fix the argument — the backend's own validation message is passed through verbatim), EERRAA_NOT_FOUND, EERRAA_FORBIDDEN (this token's scope, role or project pin is too narrow), EERRAA_OUT_OF_SCOPE (no token would help), EERRAA_RATE_LIMITED (carries retry_after), and EERRAA_TIMEOUT / EERRAA_UNAVAILABLE / EERRAA_UPSTREAM for a fault that is ours rather than yours. After a timeout on a write, run eerraa_verify_project before retrying — it may already have been applied.