Tutorial 7 of 7
Automate with the API / MCP
Advanced 12 min
Call Kinetica's forward kinematics, inverse kinematics, trajectory planner and collision check over HTTP or MCP, with real request and response examples.
Kinetica's engine is not locked inside the app. The same TypeScript code is exposed as four usefulweb tools, so scripts, spreadsheets and AI agents can use it:
| Tool | HTTP endpoint | MCP tool name |
|---|---|---|
| Forward kinematics | POST /api/v1/tools/kinetica-forward-kinematics/calculate | kinetica_forward_kinematics |
| Inverse kinematics | POST /api/v1/tools/kinetica-inverse-kinematics/calculate | kinetica_inverse_kinematics |
| Trajectory planner | POST /api/v1/tools/kinetica-trajectory-planner/calculate | kinetica_trajectory_planner |
| Collision check | POST /api/v1/tools/kinetica-collision-check/calculate | kinetica_collision_check |
In the app, Tools → Automate with the API / MCP… shows ready-to-copy request bodies for your current robot and project.

Units are always millimetres and degrees (prismatic joints in mm). The response is the usual usefulweb envelope: summary, result (validated against the tool's output schema), units, assumptions, warnings and presentation blocks.
Forward kinematics
POST /api/v1/tools/kinetica-forward-kinematics/calculate
Content-Type: application/json
{ "robot": "ur5-like", "joints": "0, -90, 90, -90, -90, 0" }
Response (excerpt):
{
"summary": "Cobot C5 (UR5-style DH table) at [0, -90, 90, -90, -90, 0] puts the TCP at x -486.9, y -109.15, z 431.86 mm with roll 180°, pitch 0°, yaw 90° (ok).",
"result": {
"tcp": { "x": -486.9, "y": -109.15, "z": 431.859, "roll": 180, "pitch": 0, "yaw": 90, "quat": [0, 0.707107, 0.707107, 0] },
"manipulability": { "inverseCondition": 0.104817, "status": "ok" }
}
}
robot can be a library id (kx6-1400, ur5-like, puma560, scara-550, gantry-xyz, planar2), custom-dh with a dh table, urdf with the URDF text in robotText, or json with a Kinetica robot object in robotText. A custom planar arm:
{
"robot": "custom-dh",
"convention": "dh",
"dh": [ { "type": "revolute", "a": 300 }, { "type": "revolute", "a": 250 } ],
"joints": "30, 60"
}
returns tcp.x = 259.8076, tcp.y = 400 — exactly 300·cos 30° + 250·cos 90° and 300·sin 30° + 250·sin 90°.
Inverse kinematics
{ "robot": "kx6-1400", "x": 700, "y": 200, "z": 600, "roll": 180, "pitch": 0, "yaw": 0 }
{
"summary": "4 IK solutions for (700, 200, 600) mm; best [15.9454, 1.604, 40.8931, 0, 47.5029, 15.9454] with residual 6.25e-8 mm.",
"result": {
"ok": true,
"solutions": [
{ "joints": [15.9454, 1.604, 40.8931, 0, 47.5029, 15.9454], "posError": 6.25e-8, "withinLimits": true, "status": "ok", "source": "numeric" }
],
"roundTrip": { "posResidual": 6.25e-8, "rotResidualDeg": 8.526e-12 }
}
}
Restarts are seeded (rngSeed, default 7), so the same request always returns the same solutions. An unreachable target returns ok: false with the distance from the first joint, the skeleton reach and the closest configuration found. SCARAs and planar arms use closed forms ("source": "analytic").
Trajectory planning
Waypoint targets are text: j: … for joint values or p: x, y, z, roll, pitch, yaw for a TCP pose. PTP speed/acceleration are percentages of the joint limits, LIN/CIRC speeds are mm/s.
{
"robot": "kx6-1400",
"profile": "scurve",
"outputDt": 0.25,
"waypoints": [
{ "name": "Home", "type": "PTP", "target": "j: 0, 0, 0, 0, 90, 0" },
{ "name": "Above", "type": "PTP", "target": "p: 800, -200, 700, 180, 0, 0", "vel": 80, "acc": 80, "blend": 30 },
{ "name": "Line", "type": "LIN", "target": "p: 800, 200, 700, 180, 0, 0", "vel": 250, "acc": 1500 }
]
}
{
"summary": "Kinetica KX6-1400 (generic 6R industrial arm): 2 moves, cycle time 2.401 s, peak joint speed 50.1% of its limit.",
"result": {
"segments": [
{ "name": "Above", "type": "PTP", "start": 0, "duration": 0.6892, "blendOverlap": 0.1551 },
{ "name": "Line", "type": "LIN", "start": 0.5342, "duration": 1.8667, "blendOverlap": 0 }
],
"peaks": { "jointVelPercent": [26.1, 10.3, 50.1, 0, 28.6, 6.6], "tcpSpeed": 1255.47 },
"samples": [
{ "t": 0, "joints": [0, 0, 0, 0, 90, 0], "tcp": [810, 0, 1075] },
{ "t": 0.25, "joints": [-3.399, 1.344, 6.533, 0, 82.122, -3.399], "tcp": [831.69, -49.4, 983.34] }
]
}
}
The blend radius of 30 mm lets the LIN move start 0.155 s before the PTP move ends. Instead of the fields above you can send a whole project as a string in projectJson; its robot, work objects and program are then used.
Collision check
{
"robot": "kx6-1400",
"joints": "0, 40, 30, 0, 20, 0",
"obstacles": [ { "name": "Machine", "shape": "box", "x": 1000, "y": 0, "z": 400, "sx": 600, "sy": 800, "sz": 800 } ],
"margin": 0
}
{
"summary": "Collision: 3 pairs closer than 0 mm, worst link5 ↔ Machine (minimum clearance -50.176 mm).",
"result": { "collides": true, "minClearance": -50.176, "links": ["link4", "link5", "link6"] }
}
MCP
Every tool is also an MCP tool. A JSON-RPC call to the MCP endpoint looks like this:
{
"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": { "name": "kinetica_inverse_kinematics", "arguments": { "robot": "scara-550", "x": 300, "y": 250, "z": 200, "roll": 180, "pitch": 0, "yaw": 45 } }
}
For this SCARA target the solver returns four solutions; the best one is [4.6375, 91.4693, 150, 51.1068] (closed form, residual below 1e-13 mm).
Projects for humans
An agent can also write a complete .kinetica.json project (the JSON schema is on the Kinetica landing page) — robot, work objects, obstacles and program — and hand it to a person, who opens it with File → Open…. Projects can also travel in a link: https://kinetica.usefulweb.site/app#project=<base64url of the JSON>.