Skip to main content
Managed Code Mode MCP turns an OpenAPI spec into a hosted MCP server that exposes your entire API surface through a single scriptable tool. Instead of generating one MCP tool per endpoint, Armature compiles your spec into an SDK bundle and serves it behind a search_sdk + execute_script pair. Agents browse the SDK, then write small TypeScript snippets that call your API directly — chaining requests, transforming responses, and returning the final value in one round trip. The endpoint lives at /product-mcp/<source-slug>, runs each script in an isolated sandbox with egress guardrails, and writes structured telemetry for every call.
Managed Code Mode is opt-in per MCP server source. Reach out to Armature support to enable it on an organization and to provision a source_slug for your API.

When to use Code Mode

Reach for Managed Code Mode MCP when:
  • Your API has more than a handful of endpoints and you do not want to expose each one as a separate MCP tool.
  • Agents need to chain calls (read, filter, then write) without burning tokens on intermediate tool round trips.
  • You want a typed client experience for agents — full parameter shapes, response types, and JSDoc examples — without authoring tool schemas by hand.
  • You want every script execution captured as telemetry you can analyze alongside your other Armature MCP runs.
If you only need a handful of tools or you already operate a hand-written MCP server, use Connect an MCP server instead.

How it works

  1. You upload an OpenAPI spec (plus an optional overlay and manifest) to Armature.
  2. Armature compiles the spec into a bundle containing a generated SDK, an operation map, an SDK index for prompting, and a vector search index.
  3. The bundle is stored as an immutable artifact and promoted to active for the source’s environment.
  4. Agents connect their MCP client to https://<your-org>.armature.app/product-mcp/<source-slug>.
  5. On initialize, the server sends back instructions plus the SDK index so the agent knows what calls are available.
  6. The agent uses search_sdk to look up exact schemas, then calls execute_script to run a TypeScript snippet against a client bound to your API.

Connect an MCP client

Add the managed endpoint to your client’s MCP server configuration. The URL is your Armature subdomain plus /product-mcp/<source-slug>, and authentication uses your Armature API key.
{
  "mcpServers": {
    "acme-api": {
      "url": "https://your-org.armature.app/product-mcp/acme-api",
      "headers": {
        "Authorization": "Bearer amt_<key-id>_<secret>"
      }
    }
  }
}
To target a non-production environment, append ?environment=staging to the URL. The server reads the mcp-session-id header on subsequent requests and groups telemetry by session.

The two tools

A managed Code Mode server exposes exactly two tools regardless of how large your spec is.

search_sdk

Use search_sdk when you need to confirm the shape of a request body, a response type, or a parameter list before writing a script. It runs against the bundle’s SDK index and returns ranked snippets with operation IDs and signatures.
ArgumentTypeRequiredDescription
querystringyesFree-text query (operation name, path fragment, or schema field).
limitintegernoNumber of matches to return. Defaults to 12, max 20.
search_sdk is annotated as read-only and idempotent — agents can call it freely without producing side effects.

execute_script

execute_script is the primary action. The script body is wrapped in an async IIFE and executed in a sandbox with a single global — the generated client — bound to your API. Use top-level await and return the final value; whatever you return becomes the tool result.
ArgumentTypeRequiredDescription
codestringyesTypeScript or JavaScript source to execute. Wrapped in async () => { … } automatically.
The client global is named after your manifest’s clientName (for example, acme or api). Auth is injected for you based on the manifest — agents never see raw credentials. Network egress is limited to the API’s base URL.
/**
 * @intent List the most recent open pull requests for a repo.
 * @context triage workflow for the on-call rotation
 * @frustration_level low
 */
const prs = await acme.repos.listPullRequests({
  owner: 'acme-tech',
  repo: 'platform',
  state: 'open',
  per_page: 5,
});

return prs.map((pr) => ({
  number: pr.number,
  title: pr.title,
  author: pr.user.login,
  updated_at: pr.updated_at,
}));
Prefix every script with JSDoc @intent, @context, and @frustration_level tags. Armature captures them as structured telemetry so you can analyze why agents reached for the tool and whether the run satisfied them.
execute_script is annotated as destructive and open-world. Treat it like any tool that can mutate upstream state — gate it behind appropriate API key roles and audit telemetry regularly.

Publish or update a bundle

Bundles are uploaded over HTTP and signed with the same Armature API key used to authenticate. Editor role or higher is required to upload a bundle; admin or owner is required to promote one to active. POST https://<your-org>.armature.app/api/openapi-artifacts/upload Required headers:
  • Authorization: Bearer amt_<key-id>_<secret>
  • x-armature-timestamp: <unix-seconds> — within 300 seconds of now.
  • x-armature-signature: <hex>HMAC-SHA256(secret = api_key, message = "<timestamp>.<raw-body>").
Body fields:
FieldRequiredDescription
sourceyesThe source_slug provisioned for your managed MCP server.
environmentnoTarget environment. Defaults to production.
openapiyesThe spec as a JSON object or a JSON/YAML string.
overlaynoOpenAPI overlay applied to the spec before compilation.
manifestnoOverrides for vendorName, clientName, auth, base URLs, and analytics tags.
repository, commitSha, branch, pullRequestNumbernoProvenance metadata recorded against the bundle row.
promotenoSet to true (admin+) to activate the bundle immediately. Otherwise it lands in generated.
A successful upload returns the bundle ID, storage path, OpenAPI and overlay hashes, an apiDiff against the currently active bundle (added, removed, signatureChanged, breaking), and a rollback.previousBundleId you can promote to revert.
TIMESTAMP=$(date -u +%s)
BODY=$(cat upload.json)
SIG=$(printf '%s' "$TIMESTAMP.$BODY" \
  | openssl dgst -sha256 -hmac "$ARMATURE_API_KEY" -hex \
  | awk '{print $2}')

curl -X POST "https://your-org.armature.app/api/openapi-artifacts/upload" \
  -H "Authorization: Bearer $ARMATURE_API_KEY" \
  -H "x-armature-timestamp: $TIMESTAMP" \
  -H "x-armature-signature: $SIG" \
  -H "content-type: application/json" \
  --data "$BODY"
Upload bodies are capped at 6 MB; compiled bundles are capped at 8 MB.

Sandbox and egress guardrails

Every execute_script call runs in an isolated VM. The sandbox:
  • Exposes only the generated client global and standard JavaScript primitives — no require, process, file system, or child process access.
  • Restricts outbound HTTP to the base URL declared in your manifest. Calls to other hosts are blocked.
  • Enforces a per-script timeout sourced from your manifest’s scriptTimeoutEnv.
  • Strips secret values from telemetry — only manifest-declared analytics tags and the JSDoc header you write are recorded.
If a script throws, the tool result is marked as an error and the exception message is returned to the agent. The script’s runtime, telemetry, and structured visible output are still recorded so you can replay the failure.

Roles and access

  • Connecting an agent requires any role with access to the source’s MCP server record. Standard tool authorization applies on top of the sandbox.
  • Uploading a bundle requires editor, admin, or owner.
  • Promoting a bundle to active requires admin or owner.
See Roles for the full permission matrix and Authentication for how to generate keys.

Connect an existing MCP server

Register a hand-written MCP server with Armature instead of compiling one from OpenAPI.

Tool monitors

Schedule recurring health checks against any MCP server’s tools.