Questionnaire & QML Tools — MCP Tool Reference¶
Questionnaire tools manage the QML lifecycle: saving QML files, validating with Z3 formal analysis, publishing to projects, moving between projects, and unpublishing. The lifecycle enforces constraints — for example, unpublishing is blocked if active campaigns reference the questionnaire.
list_questionnaires¶
List all questionnaires, optionally filtered by name.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
name |
string |
No | — | Case-insensitive substring filter |
limit |
integer |
No | 100 |
Maximum results to return |
Returns: { items: [...], count, limit }
get_questionnaire¶
Get a questionnaire by ID.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
questionnaire_id |
string |
Yes | — | Questionnaire UUID |
Returns: Questionnaire object or { error }.
create_questionnaire¶
Create a new questionnaire referencing a QML file.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
name |
string |
Yes | — | Display name |
qml_name |
string |
Yes | — | QML filename (e.g., "demographic.qml") |
project_id |
string |
Yes | — | Parent project ID |
Returns: Created questionnaire object.
delete_questionnaire¶
Soft-delete a questionnaire.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
questionnaire_id |
string |
Yes | — | Questionnaire UUID |
Returns: { success: true, questionnaire_id } or error.
list_qml_files¶
List available QML files across all tiers (shared, project, root). No parameters required.
Returns:
{
"items": [
{"name": "demographic.qml", "tier": "shared"},
{"name": "projects/abc123/survey.qml", "tier": "project", "project_id": "abc123"},
{"name": "draft.qml", "tier": "root"}
],
"count": 3
}
Tiers:
| Tier | Location | Description |
|---|---|---|
shared |
shared/questionnaires/ |
Available to all projects |
project |
projects/{project_id}/ |
Scoped to a specific project |
root |
Organization root | Unpublished/draft files |
inspect_qml_file¶
Get a quick summary of a QML file's structure — item count and metadata without full content.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
qml_name |
string |
Yes | — | QML filename (e.g., "demographic.qml") |
Returns: { success, qml_name, items_count, metadata }
get_qml_content¶
Retrieve the raw YAML content of a QML file.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
qml_name |
string |
Yes | — | QML filename |
Returns: { success, qml_name, content, size_bytes }
save_qml_file¶
Write QML YAML content to disk within the organization directory. Validates against the QML JSON schema before saving — invalid content is rejected without writing to disk. Auto-creates parent directories. Path traversal is blocked.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
qml_name |
string |
Yes | — | Relative path (e.g., "projects/{project_id}/survey.qml") |
content |
string |
Yes | — | QML YAML content |
Returns: { success, qml_name, bytes_written }
Validation errors (file not written):
| Scenario | Response |
|---|---|
| Invalid YAML syntax | {"error": "Invalid YAML syntax: ..."} |
| Not a YAML mapping | {"error": "Invalid QML: content must be a YAML mapping"} |
| Schema violation | {"error": "QML schema validation failed at '{path}': {message}"} |
validate_qml_file¶
Run Z3 SMT formal validation on a QML file. Analyzes reachability, consistency, and postcondition satisfiability for every item.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
qml_name |
string |
Yes | — | QML filename |
Returns:
{
"is_valid": true,
"item_count": 12,
"block_count": 3,
"item_classifications": {
"q_age": {
"precondition": "REACHABLE",
"postcondition": "CONTINGENT"
}
},
"statistics": {
"preconditions": {"REACHABLE": 11, "NEVER": 1},
"postconditions": {"CONTINGENT": 8, "TAUTOLOGICAL": 3, "INFEASIBLE": 1}
},
"issues": [
{
"item_id": "q_unreachable",
"severity": "error",
"type": "unreachable_item",
"message": "Item is unreachable",
"suggestion": "Check preconditions"
}
],
"analysis_report": "..."
}
Classification Reference¶
Precondition statuses (can the item be reached?):
| Status | Meaning |
|---|---|
REACHABLE |
Item can be reached in at least one flow path |
NEVER |
Item is unreachable — dead code |
UNKNOWN |
Analysis could not determine reachability |
Postcondition statuses (are the item's conditions satisfiable?):
| Status | Meaning |
|---|---|
TAUTOLOGICAL |
Condition is always true (redundant) |
CONTINGENT |
Condition depends on responses (normal) |
INFEASIBLE |
Condition can never be satisfied |
UNKNOWN |
Analysis could not determine |
Issue Types¶
| Type | Severity | Description |
|---|---|---|
unreachable_item |
error | Precondition is NEVER — dead item |
infeasible_postcondition |
error | Postcondition can never be satisfied |
globally_false_postcondition |
error | Postcondition is always false |
tautological_postcondition |
warning | Postcondition is always true (redundant) |
vacuous_postcondition |
warning | Postcondition is vacuously true (unreachable item) |
file_not_found |
error | QML file does not exist |
validation_error |
error | Exception during parsing or analysis |
publish_qml_file¶
Move a QML file from the organization root to a project directory and create a questionnaire entity.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
filename |
string |
Yes | — | QML filename in org root (e.g., "survey.qml") |
project_id |
string |
Yes | — | Target project UUID |
questionnaire_name |
string |
No | "" |
Display name. Defaults to filename without extension |
Returns: { success, questionnaire_id, qml_name }
move_qml_to_project¶
Relocate a questionnaire's QML file between projects. The questionnaire ID remains stable — campaigns referencing it continue to work.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
questionnaire_id |
string |
Yes | — | Questionnaire UUID |
target_project_id |
string |
Yes | — | Destination project UUID |
Returns: { success, questionnaire_id, qml_name }
unpublish_qml_file¶
Retract a QML file from its project back to the organization root and soft-delete the questionnaire entity. Blocked if the questionnaire has active campaigns.
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
questionnaire_id |
string |
Yes | — | Questionnaire UUID |
Returns: { success, filename } or error.
If a file with the same name already exists in the org root, it is auto-renamed with a counter suffix (e.g., survey_1.qml).
Error Handling¶
QML Lifecycle Constraints¶
| Scenario | Response |
|---|---|
| Unpublish with active campaigns | {"error": "Cannot unpublish: questionnaire has active campaign {campaign_id}"} |
| File already exists in target | {"error": "File already exists in target project"} |
| Already in target project | {"error": "Questionnaire is already in this project"} |
| Source file not found | {"error": "Source QML file not found"} |
Path Traversal Protection¶
save_qml_file, publish_qml_file, and move_qml_to_project validate that the target path stays within the organization directory. Attempts to escape (e.g., ../../etc/passwd) return:
Common Errors¶
| Scenario | Response |
|---|---|
| Questionnaire not found | {"error": "Questionnaire {id} not found"} |
| Organization context not set | {"error": "Organization context not set"} |
| QML file not found | {"error": "QML file not found: {name}"} |
| QML parse error | {"error": "Failed to parse QML: {details}"} |