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:
| Field | Meaning |
|---|---|
filters | An array of conditions, the same filters as the web client |
options.limit | Page size. The server does not return more than its ceiling. If the field is empty, the server inserts the ceiling |
options.order | Sort: attribute and direction ASC or DESC. Without it, row order is not stable. Exception: autotest steps come by sort_order |
options.add | Which extras to attach. For custom property values, send custom_properties |
response | Optional response object, as the web client sends it |
One filter condition:
{
"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:
{ "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.
| Tail | Permission code |
|---|---|
search, summary, project trees, load_body, read_content, check_syntax, get_current_user_tasks | READ |
create | CREATE |
update_property | UPDATE |
| any other mutating tail | the same tail in uppercase: save_json → SAVE_JSON |
Project
| Call | Permission |
|---|---|
project_search | project READ |
project_get_test_structure | project READ |
project_get_autotest_structure | project READ |
project_get_text_document_structure | project READ |
Resources, the same READ:
| URI | What 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_structure | Tree of test suites and test cases |
complexqa://project/{project_id}/autotest_structure | Autotest tree |
complexqa://project/{project_id}/text_document_structure | Text document tree |
project_id in the URI must match the key's project.
Bug and journal
| Call | Permission |
|---|---|
bug_search, bug_summary | bug READ |
bug_create | bug CREATE |
bug_update_property | bug UPDATE |
bug_relation_search | bug_relation READ |
bug_relation_create | bug_relation CREATE |
bug_relation_update_property | bug_relation UPDATE |
event_search | event READ |
For the journal, options.add may include subjects, actors, projects, field_changes. Names on actor_id arrive even without actors.
Test documentation
| Call | Permission |
|---|---|
test_suite_search | test_suite READ |
test_suite_create | test_suite CREATE |
test_suite_update_property | test_suite UPDATE |
test_suite_clone_element | test_suite CLONE_ELEMENT |
test_case_search | test_case READ |
test_case_create | test_case CREATE |
test_case_update_property | test_case UPDATE |
test_case_step_search | test_case_step READ |
test_case_step_create | test_case_step CREATE |
test_case_step_update_property | test_case_step UPDATE |
test_run_search | test_run READ |
test_run_create | test_run CREATE |
test_run_update_property | test_run UPDATE |
test_run_add_test_cases | test_run ADD_TEST_CASES |
test_run_result_search | test_run_result READ |
test_run_result_create | test_run_result CREATE |
test_run_result_update_property | test_run_result UPDATE |
Autotests
| Call | Permission |
|---|---|
autotest_suite_search | autotest_suite READ |
autotest_suite_create | autotest_suite CREATE |
autotest_suite_update_property | autotest_suite UPDATE |
autotest_suite_clone_element | autotest_suite CLONE_ELEMENT |
autotest_case_search | autotest_case READ |
autotest_case_create | autotest_case CREATE |
autotest_case_create_from_test_case | autotest_case CREATE_FROM_TEST_CASE |
autotest_case_update_property | autotest_case UPDATE |
autotest_case_check_syntax | autotest_case READ |
autotest_step_search | autotest_step READ |
autotest_step_create | autotest_step CREATE |
autotest_step_save_json | autotest_step SAVE_JSON |
autotest_step_update_property | autotest_step UPDATE |
autotest_run_search | autotest_run READ |
autotest_run_create | autotest_run CREATE |
autotest_run_update_property | autotest_run UPDATE |
autotest_result_search | autotest_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
| Call | Permission |
|---|---|
object_repository_folder_search / create / update_property / clone_element | object_repository_folder and the tail code |
object_repository_page_search / create / update_property / clone_element | object_repository_page and the tail code |
object_repository_element_search / create / update_property / clone_element | object_repository_element and the tail code |
text_document_search, text_document_load_body | text_document READ |
text_document_create | text_document CREATE |
text_document_update_property | text_document UPDATE |
text_document_folder_search | text_document_folder READ |
text_document_folder_create | text_document_folder CREATE |
text_document_folder_update_property | text_document_folder UPDATE |
tag_search | tag READ |
tag_create | tag CREATE |
tag_update_property | tag UPDATE |
tag_clone_element | tag CLONE_ELEMENT |
tag_clone_from_templates | tag CLONE_FROM_TEMPLATES |
tag_relation_search | tag_relation READ |
tag_relation_create | tag_relation CREATE |
tag_relation_update_property | tag_relation UPDATE |
attachment_search, attachment_read_content | attachment READ |
attachment_create | attachment CREATE |
attachment_update_property | attachment UPDATE |
execution_context_search | execution_context READ |
execution_context_create | execution_context CREATE |
execution_context_update_property | execution_context UPDATE |
execution_context_clone_element | execution_context CLONE_ELEMENT |
custom_property_search | custom_property READ |
custom_property_create | custom_property CREATE |
custom_property_update_property | custom_property UPDATE |
custom_property_clone_element | custom_property CLONE_ELEMENT |
custom_property_clone_from_templates | custom_property CLONE_FROM_TEMPLATES |
custom_property_option_search | custom_property_option READ |
custom_property_option_create | custom_property_option CREATE |
custom_property_option_update_property | custom_property_option UPDATE |
custom_property_value_set | custom_property_value SET |
custom_property_value_add | custom_property_value ADD |
task_get_current_user_tasks | task 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.
| Name | Argument | Meaning |
|---|---|---|
bug_to_test_case | bug_id | From a bug, build a test case and its steps |
test_case_to_autotest | test_case_id | From a test case, build an autotest as ComplexQA step data |
autotest_run_and_result | autotest_case_id | Create an autotest run and read the result later |
failure_to_bug | autotest_result_id | From 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.
Did this page help?