Model recipe

MCP calls

MCP calls ​

This recipe tells an agent how to call ComplexQA through MCP (Model Context Protocol) with a key for one project. A person who presses buttons on the profile needs Issuing an MCP key, not this page.

The protocol name of a call is the tool field. Below, that name is monospace. The tools list is the same for every key. Permission is checked when the call runs.

Input ​

An ACTIVE key, the secret in Authorization: Bearer, and the address from Connecting an agent.

Search accepts an object:

FieldMeaning
filtersAn array of conditions, the same filters as the web client
options.limitPage size. The server does not return more than its ceiling. If the field is empty, the server inserts the ceiling
options.orderSort: attribute and direction ASC or DESC. Without it, row order is not stable. Exception: autotest steps come by sort_order
options.addWhich extras to attach. For custom property values, send custom_properties
responseOptional response object, as the web client sends it

One filter condition:

json
{
  "object": { "element": "bug", "attribute": "bug_id" },
  "operator": "EQUAL",
  "value": 446
}

element and attribute are the technical names of the entity and the field. operator is a word, not a sign. Allowed values are LIKE, NOT_LIKE, EQUAL, NOT_EQUAL, GT, GTE, LT, LTE, IN, NOT_IN, IS_NULL, IS_NOT_NULL. The sign = is refused. IN and NOT_IN need an array value.

options.offset is not in the schema: the call is refused before main backend. A reply whose row count equals the page ceiling adds hint: this is not the whole set, and there is no next page. Narrow the filters.

Create, clone, set, add, add_test_cases, save_json, and create_from_test_case require an idempotency_key of 1 to 191 characters and a body object. Updating one field requires body with the identifier, key, and value, and no idempotency key.

Create on the MCP channel does not drop an unknown field silently. An unknown name is a refusal, api_code -102, with unknown_fields and accepted_fields in the body. Browser /web_api does not run this check. The channel sets project_id, team_id, user_id, and mcp_key_id itself. A successful create stored every field you sent.

A successful ComplexQA body has api_code 200. Otherwise the call is a refusal for the client, and the response text is returned whole.

Constraints ​

Do not invent fields, steps, or links that are not in the response. Do not call delete: that call does not exist. Do not replace the key's project_id. Do not wait for an autotest run to finish inside one call: create the run and read the result on a later call.

The key is never wider than the person. Both checks must pass: the permission on the key, and that person's role in ComplexQA.

People's names arrive as an object, not as a team roster. The fields assigned_to, reporter_id, created_by_user_id, and actor_id when actor_type is USER (or when the type is absent) look like this:

json
{ "user_id": 21, "first_name": "Alina", "last_name": "QA" }

The object has no email. An unknown identifier stays a number. actor_type SERVICE is not replaced. In field_changes, the same rule applies to old_value and new_value when field is one of these fields. Team membership, roles, and domains have no calls.

Custom property values do not arrive on their own. Search asks for them: options.add includes custom_properties. There is no separate custom_property_value read. Writing a value is custom_property_value_set and custom_property_value_add.

event_search is limited to the key's project. The actor is the key's person. When the publisher stored the channel, the row has actor_interface: UI or MCP. With MCP there is mcp_key_id. Older rows may have no channel.

A test account is not returned: stand passwords do not enter the model context. Utils (url.inspect, a page screenshot, site monitoring) are not in this catalog.

These are not registered, even if the profile table has a cell: delete, update_property_mass, delete_file, and run cancellation autotest_run_cancel.

A repeated create with the same idempotency_key after success returns the first response and does not increase the monthly counter. After a failure the same key can run again. A fresh PENDING row asks you to wait 60 seconds. A PENDING row older than 60 seconds runs again.

Output ​

A call name is {entity}_{route tail}. The permission on the key is the uppercase action code, not the tail.

TailPermission code
search, summary, project trees, load_body, read_content, check_syntax, get_current_user_tasksREAD
createCREATE
update_propertyUPDATE
any other mutating tailthe same tail in uppercase: save_json → SAVE_JSON

Project ​

CallPermission
project_searchproject READ
project_get_test_structureproject READ
project_get_autotest_structureproject READ
project_get_text_document_structureproject READ

Resources, the same READ:

URIWhat it is
complexqa://bug/{bug_id}One bug card
complexqa://test_case/{test_case_id}One test case card
complexqa://autotest_case/{autotest_case_id}One autotest card
complexqa://project/{project_id}/test_structureTree of test suites and test cases
complexqa://project/{project_id}/autotest_structureAutotest tree
complexqa://project/{project_id}/text_document_structureText document tree

project_id in the URI must match the key's project.

Bug and journal ​

CallPermission
bug_search, bug_summarybug READ
bug_createbug CREATE
bug_update_propertybug UPDATE
bug_relation_searchbug_relation READ
bug_relation_createbug_relation CREATE
bug_relation_update_propertybug_relation UPDATE
event_searchevent READ

For the journal, options.add may include subjects, actors, projects, field_changes. Names on actor_id arrive even without actors.

Test documentation ​

CallPermission
test_suite_searchtest_suite READ
test_suite_createtest_suite CREATE
test_suite_update_propertytest_suite UPDATE
test_suite_clone_elementtest_suite CLONE_ELEMENT
test_case_searchtest_case READ
test_case_createtest_case CREATE
test_case_update_propertytest_case UPDATE
test_case_step_searchtest_case_step READ
test_case_step_createtest_case_step CREATE
test_case_step_update_propertytest_case_step UPDATE
test_run_searchtest_run READ
test_run_createtest_run CREATE
test_run_update_propertytest_run UPDATE
test_run_add_test_casestest_run ADD_TEST_CASES
test_run_result_searchtest_run_result READ
test_run_result_createtest_run_result CREATE
test_run_result_update_propertytest_run_result UPDATE

Autotests ​

CallPermission
autotest_suite_searchautotest_suite READ
autotest_suite_createautotest_suite CREATE
autotest_suite_update_propertyautotest_suite UPDATE
autotest_suite_clone_elementautotest_suite CLONE_ELEMENT
autotest_case_searchautotest_case READ
autotest_case_createautotest_case CREATE
autotest_case_create_from_test_caseautotest_case CREATE_FROM_TEST_CASE
autotest_case_update_propertyautotest_case UPDATE
autotest_case_check_syntaxautotest_case READ
autotest_step_searchautotest_step READ
autotest_step_createautotest_step CREATE
autotest_step_save_jsonautotest_step SAVE_JSON
autotest_step_update_propertyautotest_step UPDATE
autotest_run_searchautotest_run READ
autotest_run_createautotest_run CREATE
autotest_run_update_propertyautotest_run UPDATE
autotest_result_searchautotest_result READ

autotest_step_save_json updates existing steps of one autotest_case_id. Each steps item needs autotest_step_id. Omitted steps stay. This call does not create new steps: use autotest_step_create for a new step.

Send a step locator as target with an object {kind, value, name}, not as an HTML-escaped string. The column is target_json. kind is ROLE, LABEL, PLACEHOLDER, TESTID, TEXT, TITLE, ALT, CSS, ID, NAME, XPATH, or SELECTOR. value_source_type INLINE is stored as null: that null is the inline value_text. The other type is TEST_ACCOUNT.

autotest_case_status is PENDING, READY, or DISABLED. A new run includes only READY. DISABLED stays out of new runs. DRAFT and DEPRECATED are not statuses.

autotest_suite_clone_element copies that suite and the autotests that sit directly inside it, including their steps. Nested suites are not copied. The reply includes the new copy's identifier.

Autotest steps are ComplexQA data (autotest_step, save_json). This server does not write Playwright code into the customer's repository.

Object repository, documents, and the rest ​

CallPermission
object_repository_folder_search / create / update_property / clone_elementobject_repository_folder and the tail code
object_repository_page_search / create / update_property / clone_elementobject_repository_page and the tail code
object_repository_element_search / create / update_property / clone_elementobject_repository_element and the tail code
text_document_search, text_document_load_bodytext_document READ
text_document_createtext_document CREATE
text_document_update_propertytext_document UPDATE
text_document_folder_searchtext_document_folder READ
text_document_folder_createtext_document_folder CREATE
text_document_folder_update_propertytext_document_folder UPDATE
tag_searchtag READ
tag_createtag CREATE
tag_update_propertytag UPDATE
tag_clone_elementtag CLONE_ELEMENT
tag_clone_from_templatestag CLONE_FROM_TEMPLATES
tag_relation_searchtag_relation READ
tag_relation_createtag_relation CREATE
tag_relation_update_propertytag_relation UPDATE
attachment_search, attachment_read_contentattachment READ
attachment_createattachment CREATE
attachment_update_propertyattachment UPDATE
execution_context_searchexecution_context READ
execution_context_createexecution_context CREATE
execution_context_update_propertyexecution_context UPDATE
execution_context_clone_elementexecution_context CLONE_ELEMENT
custom_property_searchcustom_property READ
custom_property_createcustom_property CREATE
custom_property_update_propertycustom_property UPDATE
custom_property_clone_elementcustom_property CLONE_ELEMENT
custom_property_clone_from_templatescustom_property CLONE_FROM_TEMPLATES
custom_property_option_searchcustom_property_option READ
custom_property_option_createcustom_property_option CREATE
custom_property_option_update_propertycustom_property_option UPDATE
custom_property_value_setcustom_property_value SET
custom_property_value_addcustom_property_value ADD
task_get_current_user_taskstask READ

attachment_read_content returns text and an image while the file is inside the byte ceiling. A larger file returns a short access_url. This page does not fix the ceiling number.

task_get_current_user_tasks returns tasks of the person who owns the key, not of the whole team.

The custom property catalog and options belong to the team. A slot has no project_id field. Writing the catalog is available to a team administrator.

Bug relation, tag relation, and autotest result search are scoped to the team and then limited by the parent in the key's project.

Prompts ​

The server registers four prompts. The argument is a string.

NameArgumentMeaning
bug_to_test_casebug_idFrom a bug, build a test case and its steps
test_case_to_autotesttest_case_idFrom a test case, build an autotest as ComplexQA step data
autotest_run_and_resultautotest_case_idCreate an autotest run and read the result later
failure_to_bugautotest_result_idFrom an autotest result failure, create a bug

A prompt does not bypass the key's permissions. Delete is not called inside a prompt.

Check ​

A response is usable when api_code is 200, the identifiers belong to the key's project, and people on cards are user_id / first_name / last_name objects, or a number when the name is missing.

A refusal This key cannot … means the pair is not on the key. HTTP 401 means the secret was not accepted. HTTP 429 means rate or the team's monthly ceiling. A repeated create without a new idempotency_key after success does not create a second row.

Version 1.1.0 · Last updated 2026-10-09

Did this page help?