ARCNM

Tools

MCP — agents and IDEs

Connect Claude Code, Cursor, or any MCP client to ARCNM over HTTP with a bearer token.

ARCNM ships a Model Context Protocol server, auto-generated from the REST API. MCP-speaking agents and IDEs can quote parts, inspect calculations, and read your data through typed tools — without you writing glue code.

Endpoint: https://api.arcnm.io/mcp-server/mcp (HTTP transport, bearer-JWT protected).


Why MCP, not REST

If you're writing application code, use REST. Pick MCP when an agent is the client (Claude, Cursor, custom runtimes): it discovers tools automatically and routes arguments through structured schemas.


Authentication

The MCP server is a bearer-token protected resource. It publishes RFC 9728 protected-resource metadata at /.well-known/oauth-protected-resource. The verifier accepts either credential in the Authorization: Bearer … header:

  • an ARCNM API key (ak_live_… / ak_test_…) — recommended for agents: long-lived, revocable, scoped (tried first); or
  • a tenant-scoped session access token (JWT, audience-pinned to /api/v1; refresh tokens and other-audience tokens are rejected).

Mint an API key in the dashboard (Settings → API keys) and pass it as the bearer token — that's all most agents need.

Interactive clients (Claude, …) can instead sign in with OAuth when the deployment enables it: ARCNM runs a full OAuth 2.1 authorization-code flow with dynamic client registration and a consent screen where the user picks the org and the scopes to grant (read-only by default). The client receives a short-lived, org-scoped, scope-limited token — no key to copy. Either way the credential resolves to the same tenancy + scope checks.


Connect

Claude Code (CLI)

claude mcp add -t http arcnm https://api.arcnm.io/mcp-server/mcp \
  --header "Authorization: Bearer $ARCNM_MCP_TOKEN"

Cursor

Add to ~/.cursor/mcp.json (or project-scoped .cursor/mcp.json):

{
  "mcpServers": {
    "arcnm": {
      "transport": {
        "type": "http",
        "url": "https://api.arcnm.io/mcp-server/mcp",
        "headers": { "Authorization": "Bearer ${ARCNM_MCP_TOKEN}" }
      }
    }
  }
}

Restart Cursor; tools appear under the MCP picker.

Other clients

Any MCP-compliant HTTP client works. Point the transport at https://api.arcnm.io/mcp-server/mcp, send the bearer header, and call the standard tools/list method to discover the surface.


What's exposed

The surface is the public developer API and nothing else, exposed as Tools — everything in one tools/list (a strict, deny-by-default allow-list; an MCP tool is model-invoked, so the surface is the security boundary):

  • Reads (parts, calculations, uploads, environments, materials, calibration) are read-only Tools (readOnlyHint=true) — plus a read-only view of your own identity (GET /users/me, /users/me/context). Material search (materials_suggest, materials_lookup) counts as a read even though it is a POST: the query rides in the body, nothing is written.
  • Writes (create a part, create/run/quote a calculation, upload inputs) are Tools carrying an idempotent / destructive hint.

There are no Resources or Resource Templates — an agent-first data API is model-invoked, which is Tool semantics, so reads and writes live in one tools/list (matching GitHub's and Stripe's MCP servers) rather than being split across tools/list and resources/list. Use readOnlyHint to tell a data-fetch from a mutation.

Tool names are generated from the REST operation ids (roughly <tag>_<operation>, e.g. calculations_get_calculation, calculations_create_calculation). The authoritative list is whatever tools/list returns for your token — generate it from the live server rather than hardcoding names.

What's never exposed. Everything outside the public developer API: wallet and billing operations, plan changes, member invites/roster, API-key minting, the credential vault, SSO/SCIM, raw payment-provider webhooks, feature flags, auth/session primitives, the audit log and other admin-only endpoints, the AI and generic /jobs surfaces, and all user identity mutations (including cross-user reads). An agent with a tenant token cannot move money, escalate access, mint credentials, read the admin plane, or rewrite the tenant — those stay human-dashboard-only by design. The environment effective-rates surface (read + edit) is likewise app-only: rate configuration is a pricing decision an agent must not make on the operator's behalf.

Scopes mirror the REST scope catalog: a token needs parts:read to read and parts:write to create or run a calculation. Request the minimum the agent needs.

tools/list is filtered to your token's scopes. The server returns only the tools your credential can actually call — a parts:read key sees the read-only tools and the identity reads, not the write tools it could only 403 on. (Scopeless first-party session tokens are unrestricted and see everything, matching the REST gate.) So the surface an agent discovers is already least-privilege; widen it by minting a broader-scoped key, not by working around a missing tool.

The list is intentionally not paginated — the whole (already scope-scoped) surface is returned in one tools/list response. The MCP cursor is optional and we don't emit one; paging wouldn't help anyway, since a client that holds the surface ends up holding all of it either way.

What it costs you is worth knowing, because most hosts put every tool definition into the model's context. Two things keep it down, and one of them is yours: the generated tools describe their arguments but not their response shape — read response schemas from the API reference, which publishes them once instead of repeating them per tool — and a narrower credential is a smaller surface, since the list is scope-filtered. A parts:read key sees about half the tools of a full-scope one. Scope the credential to what the agent actually does. For the cost loop, prefer the curated arcnm_* tools: those do declare typed output and are built to be token-light.


Agent-first workflow tools

On top of the generated CRUD tools the server ships a few curated arcnm_* tools built for an agent's cost-optimisation loop. Each returns a concise, structured result (with an outputSchema) instead of the full response blob, so they're cheap on context:

Tool What it returns
arcnm_explain_cost Headline unit / total / setup cost and setup / cycle / unit time, the prediction band, the cost breakdown, the machine used, the material-resolution assumption, and the top cost drivers. detail="detailed" widens the driver list.
arcnm_cost_drivers The top cost drivers, ranked — each with its cost, its share of the unit cost, and why it's costly.
arcnm_cost_breakdown One calculation as a single rough-to-detailed hierarchy — headline → cost category → operation → feature, time and cost side by side — with a persona knob (procurement / workprep / operations / design / full) that returns just the slice that persona needs.
arcnm_process_plan The ordered process plan (routing) all the way to a finished part: the machining steps, each with its process, work center and cycle time, then the post-machining chain (welding, heat treatment, surface finishing, coating) in the order it is performed — plus the plan-level setup / cycle / total time and machine(s). The work plan a work-preparation user acts on. Post-machining steps carry no cycle time: they are priced per lot, in the subcontract line.
arcnm_compare_calculations The unit-cost delta between two calculations, flagging when they aren't comparable (different lot size / environment).
arcnm_rank_calculations The N-way generalization of compare: ranks 2–20 calculations cheapest-unit-cost first, each with its premium over the cheapest and time beside cost, flags when they aren't like-with-like, and lists blocked / unpriced calcs last. Pick between several quotes at once.
arcnm_compare_environments The parts × environments matrix of a multi-environment run — per part the unit cost in every environment and the cheapest environment (ties included); per environment the win count, basket total and median delta vs the baseline. Pass a batch_id (from a multi-environment quote/batch) or an ad-hoc calculation_ids list; all figures are server-computed, identical to the REST comparison endpoints. Up to 200 ids, and the pivoted grid may not exceed 500 cells (parts × environments).
arcnm_optimize_lot_size The total-cost optimal lot size (production plus inventory holding, capped at one year of demand), the net EUR/yr saving of moving there, the Andler/EOQ cross-check, the cost-vs-quantity curve (with the per-unit-variable split), and at most two lot-size/setup directions.
arcnm_optimization_directions Every optimization direction for a calculation — lot sizing, setup reduction, tolerance-cost review, material utilization, external-process benchmarking, plus the live supplier-quote gap — each tagged with its lever, confidence, and method.
arcnm_check_quota This organization's remaining calculation quota for the current window — included / used / remaining, the overage rate, how overage settles (wallet = prepaid, with wallet_funded_calculations telling you how many more fit), how much of any monthly spend cap is left, and whether billing is suspended — so you can check before committing a run instead of parking a calc as blocked.

All of these are read-only and inherit the same scopes, tenancy, and redaction as the REST API — ideal building blocks for a "cost it, find the drivers, change the design, re-cost, compare" loop driven from a CAD/agent toolchain.

Reads are tools too

Everything you need to read — a full calculation (poll calculations_get_calculation for its status), an environment and its machine fleet / rates, a part's revisions, the material catalogue — is a read-only Tool in the same tools/list as the writes (look for readOnlyHint=true), so there is no second surface to discover. There is no separate job-status tool — a calculation carries its own status, so polling calculations_get_calculation is the deterministic way to wait for a result.

Getting a CAD file in over MCP

An MCP client can only pass strings, so the multipart upload-and-quote / datasets_upload_dataset tools can't carry a file. Use upload_and_quote_json (POST /calculations/upload-and-quote-json): the same one-shot upload + quote, but the CAD (and optional drawing / RFQ) ride as base64 (or data: URI) strings in a JSON body. Best for small single-part STEP files — base64 inflates ~33% and rides inside the tool call, so for large assemblies use the uploads_presign → PUT → uploads_confirm flow instead.

Finding a material

materials_lookup resolves an exact reference; on a near-miss it now returns the closest grades in the error detail. For a fuzzy "did you mean" list that never dead-ends — a partial code, a trade name, or a generic term like Stahl — use materials_suggest, then pass a candidate's urn back as material_ref.

What you get back

The MCP surface is the public face of the platform, so responses carry the cost answer and the explanation a buyer needs to act — never the engine internals. Selection scoring, per-operation cycle-time math, raw extraction output, calibration parameters, and the platform machine-cost model are stripped from every response an agent receives (the first-party app keeps the full detail). Design around the result, not the derivation.

Read-only mode

A deployment can run the MCP server in read-only mode (MCP_READ_ONLY): the write tools disappear from tools/list entirely, leaving only the read resources and the read-only arcnm_* tools. Pair it with a read-only API key for defence in depth when the agent only needs to read and analyse.


Tool annotations

Each tool carries MCP annotations the agent uses to decide how to call it:

  • openWorldHint is false — every tool acts on your own tenant data (a closed domain), not an open external world like web search.
  • readOnlyHint is true on the curated arcnm_* analysis tools.
  • idempotentHint is false for POST / PATCH, true for PUT.
  • destructiveHint and idempotentHint are true for DELETE.

A well-behaved agent confirms with the user before calling a destructiveHint tool.


Prompts

The tools are CRUD-shaped because they're generated from the REST API. On top of them the server ships a small set of prompts — the task-oriented "verbs that matter" — that walk an agent through a whole workflow using whatever tools your token exposes. Call prompts/list to discover them:

Prompt What it does Arguments
cost_a_part Upload a CAD file, create + run a calculation, poll to completion, report unit / total / setup cost. part_number, lot_size, environment
compare_calculations Read two calculations and explain the cost delta and its drivers. calculation_id_a, calculation_id_b
compare_environments Price part(s) across several environments in one batch, poll the grid, and recommend the best environment per part and overall. part_numbers_or_ids, environment_names_or_ids
explain_cost Explain one calculation's cost in plain language — decomposition and drivers. calculation_id
find_cost_drivers Rank the top cost drivers for a calculation to target a redesign or re-quote. calculation_id, top_n

Prompts are guidance, not privilege: they describe the workflow by capability and tell the agent to resolve exact tool names from tools/list, so they keep working as the generated surface evolves. A prompt that ends in a write your token can't perform simply has that final call rejected at the REST boundary.


Worked example — agent quotes a part

user: Quote this STEP file at lot size 50, on our production env.
      [attaches bracket.step]

agent: <calls the parts upload-and-quote tool>
       cad_file=<bytes>, part_number="BRACKET-001",
       lot_size=50, costing_environment_id=<prod env id>

agent: ← { id: "9d…", status: "queued" }

agent: <polls the get-calculation resource for 9d… until status=succeeded>

agent: Unit cost at lot size 50 is €12.84 (total €642.00, setup €52.50).
       The full breakdown is on the calculation's analytics blob.

The agent didn't write a line of REST glue.

Worked example — agent compares environments

user: Which of our environments makes these 3 brackets cheapest?

agent: <calls arcnm_check_quota>                 # a grid costs parts × envs
agent: <lists environments, resolves the 3 part revisions>
agent: <calls the batch-calculation tool>
       part_revision_ids=[…,…,…],
       costing_environment_ids=[<prod>, <staging>, <sub_a>]
agent: ← { batch_id: "b4…", requested: 9, enqueued: 9 }

agent: <polls arcnm_compare_environments(batch_id="b4…") until complete>

agent: Subcontractor A is cheapest for 2 of 3 parts; basket −9.8% vs
       production. BRACKET-002 stays cheaper in-house (+4.1% at Sub A).

One batch call instead of nine single quotes — and the matrix (wins, deltas, basket totals) is computed server-side, so the agent reports the same numbers the UI shows. The compare_environments prompt walks this flow end to end.


Rate limits & billing

MCP traffic is handled by the MCP server's own verification and is not subject to the REST per-request quota bucket. You're billed for the underlying billable operation (a successful calculation), not per tool call — read-only tools and resources are free. A multi-environment batch is one tool call but bills one calculation per (revision × environment) cell; arcnm_check_quota first tells you whether the grid fits.


Local development

Run a local backend and point your MCP client at http://localhost:8000/mcp-server/mcp with a dev bearer token — an ak_test_… API key works well locally. The MCP transport reads the Authorization: Bearer header only (an API key or a session JWT); there is no X-API-Key header path on the MCP server — that header is REST-only.


See also