JSON-RPC 2.0 and MCP Server Testing
Shift-Left Studio tests JSON-RPC 2.0 services and Model Context Protocol (MCP) servers alongside your REST, SOAP and GraphQL APIs. An MCP server is a JSON-RPC 2.0 server with a fixed set of methods, so the same capability covers both.
View as MarkdownApplies to: Trial and Enterprise editions · Web app and Desktop app
Overview
Shift-Left Studio tests JSON-RPC 2.0 services and Model Context Protocol (MCP) servers alongside your REST, SOAP and GraphQL APIs. An MCP server is a JSON-RPC 2.0 server with a fixed set of methods, so the same capability covers both.
JSON-RPC behaves differently from REST in one important way: a failed call usually comes back with HTTP 200. The transport succeeded; the operation did not, and the failure is described inside the response body. A test that only checks the status code will pass on a call that failed. Studio therefore gives JSON-RPC its own assertions that look inside the response, and generated tests use them automatically.
You can bring JSON-RPC services into a project from an OpenRPC document, or connect to a live MCP server and choose which of its tools to test. Each method or tool becomes its own endpoint, with generated positive and negative tests.
Key concepts
| Term | Meaning |
|---|---|
| Method | The operation name inside a JSON-RPC request, such as getBalance. Every method on a service shares one URL, so the method name — not the path — identifies an endpoint. |
| Params | The input to a method. A test's body is just the params; Studio adds the jsonrpc, id and method wrapper when it sends the request. |
| Result / error | A JSON-RPC reply contains either a result (success) or an error with a code and message (failure). |
| OpenRPC | A specification format for JSON-RPC services, similar to OpenAPI for REST. |
| MCP tool | An action an MCP server offers. Each tool becomes an endpoint that calls tools/call. |
| Protocol error vs tool error | An MCP server can refuse a call (a JSON-RPC error), or accept it and report that the tool itself failed. The second arrives as a successful reply and needs its own check. |
| Session | MCP servers over Streamable HTTP keep a session. Studio opens it, uses it for the call, and closes it for every run. |
Before you begin
- Your licence must be Trial or Enterprise. On other editions the JSON-RPC options do not appear in the import dialog.
- You need permission to import APIs into the project.
- For an MCP server: its Streamable HTTP address (for example
https://example.com/mcp) and, if it requires sign-in, a bearer token. - For a JSON-RPC service: an OpenRPC document (
.json), or a URL to one. - A project environment whose base URL points at the service's origin. JSON-RPC runs over HTTP, so, like REST, it needs one.
Step 1 — Import an OpenRPC document
- In the project tree, open the import dialog (Import API to Project, or Import API to Feature when a feature is selected).
- Set API Type: to JSON-RPC / MCP.
- Under Import Method, choose Upload File and select your OpenRPC
.jsonfile, or use URL import with the document's address. - Under Check before importing, click Preview methods to see the methods the document declares before anything is created.
- Complete the import.
Each method in the document becomes one endpoint. Its parameter schema drives generation the same way a REST request body does, and any documented error codes are stored for negative tests.
Tip: Most internal JSON-RPC services have no published OpenRPC document. A plain method list also imports: a JSON file containing the HTTP path and the method names, for example
{ "httpPath": "/rpc", "methods": ["getBalance", "transfer"] }.
Step 2 — Discover and import an MCP server
- Open the import dialog as above.
- Under Import Method, click MCP Server.
- Enter the MCP server URL.
- If the server requires sign-in, enter its bearer token in Access token (only if the server needs one). Leave it empty otherwise.
- Click Connect and list tools. Studio performs the real MCP handshake and lists the server's tools. Nothing is written yet.
- Review the Connected summary (Server and Tools). If the server lists more tools than could be read, a note says the list may be incomplete.
- Under Choose what to test, review the tools. Each is marked:
- Safe to run — the server declares the tool read-only. These start ticked.
- May change data — the tool does not declare itself read-only. These start unticked, because a generated happy-path test really runs the tool against your server.
- Tick or untick tools, then click Import N tools.
Each selected tool becomes one endpoint. The tool's own input schema becomes the schema for its arguments, so generated tests exercise the tool's real parameters. Re-importing the same server later compares against what already exists instead of duplicating it. The project's base URL is filled in from the server address when it is not already set.
Important: The access token entered here is used to discover the server and is not stored on the endpoints. For runs against a server that requires sign-in, set the endpoint's Auth token reference (see Step 3).
Step 3 — Review and adjust an endpoint
Open an imported JSON-RPC endpoint to see or edit its settings:
| Field | Purpose |
|---|---|
| RPC method | The method name sent in the request (tools/call for MCP tools). |
| HTTP path | The URL path every method is sent to, such as /rpc. |
| Params shape | Named (object) or Positional (array). |
| ID strategy | How the request id is set: Incrementing number, UUID or Fixed (1). |
| Default params | The params sent when a test does not set its own. Just the params — not the full request. |
| Auth token reference | A reference to a bearer token, resolved when a test runs. Use env:NAME for an environment variable, secretref://provider/path#field for a secret manager, or key:NAME for a saved access key. Never the token itself. |
| Documented error codes | Error codes the method's documentation promises (comma-separated). Used to generate negative tests. |
Note: If you paste a complete JSON-RPC request (with
jsonrpc,idandmethod) into a test body — for example, one copied from your logs — Studio accepts it and uses only the params.
Step 4 — Generate tests
Generate tests for JSON-RPC endpoints the same way as for any other endpoint. Generated tests include:
| Test | Checks |
|---|---|
| Happy path | JSON-RPC: No Error and JSON-RPC: Result Exists (plus MCP: Tool Call Succeeded for MCP tools). |
| Unknown method rejected | JSON-RPC: Has Error with the standard code -32601, at HTTP 200. |
| Invalid params and other negatives | JSON-RPC: Has Error with the documented or standard error code, at HTTP 200. |
For MCP tools marked May change data, only import them if you are prepared for generated happy-path tests to act on the server.
Step 5 — Run the tests
- Make sure the environment you run against has a base URL pointing at the service's origin (for example
https://api.example.com). Studio appends the endpoint's HTTP path. - Run a test, a test run pack or a workflow as usual. JSON-RPC tests can be steps in workflows.
- For MCP servers, Studio automatically opens a session, makes the call within it, and closes the session afterwards. If the server replies as an event stream instead of plain JSON, Studio unwraps it so the assertions see the same reply either way.
The run result shows a plain-language verdict instead of a bare HTTP status, because a green "200" would be misleading:
| Verdict | Meaning |
|---|---|
| Succeeded | The reply contained a result and no error. |
| Error reported | The call was delivered and the service answered with a JSON-RPC error. For a negative test, this is the expected outcome. |
| Rejected (HTTP N) | The request was refused before it reached the JSON-RPC layer — for example 401, 403, 404, 415 or 429. These keep their real HTTP status. |
| No reply | Nothing usable came back. |
Assertion results also read in plain words, such as Rejected for the expected reason or Rejected, but for a different reason than expected.
Note: You can run JSON-RPC tests on the Engine (server) or the Agent (local runner). On the Agent, only
env:NAMEtoken references resolve; akey:orsecretref:reference fails with a message naming it. Use the Engine for those.
Assertion reference
All JSON-RPC assertions are in the JSON-RPC category of the assertion picker.
| Assertion | What it checks | Typical use |
|---|---|---|
| JSON-RPC: No Error | The reply has no error member. Set it to false to require one. | Every positive test. |
| JSON-RPC: Has Error | The reply has an error member. | The core negative check. |
| JSON-RPC: Error Code Equals | The error code, for example -32601 (method not found) or -32602 (invalid params). | Checking a negative test failed for the right reason. |
| JSON-RPC: Error Message Contains | The error message contains the given text. | Checking a specific validation message. |
| JSON-RPC: Result Exists | The reply has a result member. | Positive tests. |
| MCP: Tool Call Succeeded | An MCP tool call returned a result and did not flag the tool itself as failed. | Every MCP positive test — a tool failure arrives as a successful reply, so nothing else catches it. |
| MCP: Tool Output Contains | The text the tool returned contains the given text. | Checking what a tool actually said. |
| JSON-RPC: Reply Matches Call | The reply carries the same id the request sent. | Hard-failing a reply that belongs to another request. Without it, a mismatch is shown as a warning in the run details. |
Field checks inside the result use the usual field assertions — for example, a field-equals check on result.balance. Dynamic tokens such as {{row.EXPECTED_CODE}} work in these assertions as in any other.
Standard JSON-RPC 2.0 error codes: -32700 parse error, -32600 invalid request, -32601 method not found, -32602 invalid params, -32603 internal error.
Current limitations
- Batch requests (an array of calls in one request) are not supported. A batch body is rejected with a message asking you to split it into individual tests. A plain array of values is still accepted as positional params.
- MCP over stdio is not supported; only Streamable HTTP.
- MCP resources and prompts are not modelled; tools only.
- MCP OAuth sign-in is not supported; bearer tokens only.
- Studio has been verified against the official MCP reference server and a standard JSON-RPC 2.0 library. It has not been verified against every vendor's server; if yours behaves differently, contact support.
Troubleshooting
| Symptom | Why it happens | What to do |
|---|---|---|
| JSON-RPC / MCP and MCP Server are not offered in the import dialog | Your edition does not include JSON-RPC testing, or it is turned off on your installation. | Check your licence (Trial or Enterprise), or ask your administrator. |
| A negative test expecting HTTP 400 never passes | A compliant JSON-RPC server reports errors with HTTP 200. | Replace the status check with JSON-RPC: Has Error and JSON-RPC: Error Code Equals. |
| A positive test passes although the call failed | The test checks only the status code. | Add JSON-RPC: No Error (and MCP: Tool Call Succeeded for MCP). |
| Could not reach the MCP server | Wrong URL, the server is down, or it requires a token. | Check the address and token, then click Connect and list tools again. |
| Runs are Rejected (HTTP 401) after an MCP import | The discovery token is not kept on the endpoints. | Set Auth token reference on the endpoint. |
| A run fails before sending, asking for a base URL | The environment has no base URL. | Set the environment's base URL to the service origin. |
| A token reference fails on the Agent | The Agent resolves only env: references. | Run on the Engine, or use an env: reference. |
Best practices
- Never rely on a status check alone for JSON-RPC. Every test should include at least one JSON-RPC assertion.
- For MCP, pair MCP: Tool Call Succeeded with MCP: Tool Output Contains to check what the tool actually returned.
- Keep tools marked May change data unticked unless you are testing against a disposable environment.
- Record documented error codes on each endpoint so negative tests assert the right code.
- If you created JSON-RPC tests in an older release, regenerate them to pick up the current negative-test assertions.
Related articles
- Test run
- Environments
- Project settings: environments and auth
- WebSocket-RPC Testing
- Testing Server-Sent Events (Streaming) Responses
Automating this
Named access keys for JSON-RPC endpoints (used as key:NAME in Auth token reference) can be saved with POST /api/jsonrpc/keys and listed with GET /api/jsonrpc/keys. The list returns key names only, never the credential. Saving under an existing name replaces the credential without breaking endpoints that reference it.
For administrators (self-hosted installations)
| Setting | Default | What switching it does |
|---|---|---|
JSONRPC_PROTOCOL_ENABLED | true | Set to false to remove JSON-RPC and MCP testing entirely. Nothing can create a JSON-RPC endpoint and the import options disappear. |
MCP_DISCOVERY_ALLOW_INTERNAL | Allowed on single-tenant installs; blocked when multi-tenant | Set true or false to override whether MCP discovery may connect to localhost and internal network addresses. |
Previous
Fix with AI: Grounded Repair
Product documentation
Next
WebSocket-RPC Testing
Product documentation
Related articles
- Generate Endpoint Test Cases · Product documentation
- Test Cases: Open, Edit, and Save · Product documentation
- Test Configuration · Product documentation
- Execution Mode · Product documentation
- Run Tests and Review Results · Product documentation
- Test Generation Settings · Product documentation
Next steps
- Getting started · Install + connect your spec
- Configuration fundamentals · Stabilize runs
- Initial configuration · Users, licensing, projects
- Release notes · Updates and fixes
Still stuck?
Tell us what you’re trying to accomplish and we’ll point you to the right setup—installation, auth, or CI/CD wiring.