Skip to main content
Glama

Save a query

save_query

Save a filter set as a reusable OpenProject view to avoid rebuilding filters each session; the stored view appears in the OpenProject UI and can be rerun exactly.

Instructions

Save a filter set as a reusable OpenProject view.

Use it to keep a filter combination — "Overdue in Platform", "My open bugs" — instead of rebuilding it each session: the view shows up in the OpenProject UI too, and run_query reproduces it exactly. Prove filters with list_work_packages first.

Validated via POST /queries/form first, so an invalid filter name, unsupported operator, or project-scoped filter on a global view comes back as violations naming the attribute — nothing is saved. Returns the stored definition: {id, name, project, public, starred, filters (as readable sentences), group_by, sort_by, display_sums, updated_at, notes}. Keep the id — run_query takes it.

Pitfalls. If OpenProject keeps fewer filters than were sent, notes says so — read filters rather than assuming a match. Custom-field filters (customField12) are sent as plain values, since a list-typed one can't be told apart from a text one without asking the instance; a failing one means nothing was saved — save that view in the UI instead. Editing and deleting saved views isn't offered here: use the OpenProject UI.

Cross-references: list_queries lists what exists (with ids); run_query(query_id=...) runs this view; list_work_packages validates filters first; list_projects supplies project_id.

Input Schema

NameRequiredDescriptionDefault
nameYesName the view is saved under, e.g. 'Overdue in Platform'. Not unique upstream — a repeat name creates a second view.
starNoAlso star (favorite) the view, so it appears in the sidebar. A second call after the query exists; a failure still leaves it saved (noted in 'notes') — don't re-save.
publicNotrue shares the view with everyone who can see the project; false (default) keeps it private. Sharing usually needs 'manage public queries'.
filtersYesThe filters to store, same shape as run_query's override_filters / list_work_packages' raw_filters, e.g. [{'name': 'status', 'operator': 'o', 'values': []}, {'name': 'assignee', 'operator': '=', 'values': ['12']}]. Values are ids (or 'me'), not names. Pass [] for a view with no filters — unlike a listing, it then shows every status.
sort_byNoStored sort order, e.g. [['due_date', 'asc'], ['id', 'desc']]. Unknown keys are rejected locally, listing the allowed set. Omit for the default.
group_byNoColumn to group results by, e.g. 'status', 'assignee'. Makes run_query return 'groups' with per-group counts. Omit for a flat list.
project_idNoNumeric project id the view belongs to; from list_projects. Omit for a global view — project-scoped filters (version, category, subprojectId) are then rejected.

Output Schema

NameRequiredDescriptionDefault
idNo
nameNo
notesNo
publicNo
filtersNo
projectNo
sort_byNo
starredNo
group_byNo
updated_atNo
display_sumsNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed29 schema fields changedv0.4.0
    • removedOutput schema / description
      Removed value: -"The query ``save_query`` created, exactly as OpenProject stored it."
    • removedOutput schema / properties / display_sums / default
      Removed value: -false
    • removedOutput schema / properties / display_sums / description
      Removed value: -"True when the query asks for totals; then the result 'sums' is populated."
    • removedOutput schema / properties / filters / description
      Removed value: -"The stored filters as readable sentences, e.g. 'Status open' or 'Assignee is (OR) Grace Hopper'. Empty when the query filters nothing."
    • removedOutput schema / properties / group_by / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / group_by / default
      Removed value: -null
    • removedOutput schema / properties / group_by / description
      Removed value: -"Column the results are grouped by, when the query groups."
    • addedOutput schema / properties / group_by / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / id / anyOf
      Removed value: -[
      -  {
      -    "type": "integer"
      -  },
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / id / default
      Removed value: -null
    • removedOutput schema / properties / id / description
      Removed value: -"Query id — pass it to run_query as query_id."
    • addedOutput schema / properties / id / type
      Added value: +[
      +  "integer",
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / name / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / name / default
      Removed value: -null
    • removedOutput schema / properties / name / description
      Removed value: -"Query name as its author saved it."
    • addedOutput schema / properties / name / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / notes / description
      Removed value: -"What happened beyond the create itself: a failed star, filters OpenProject did not keep. Empty when everything landed as asked."
    • changedOutput schema / properties / project / anyOf
      Previous value: -[
      -  {
      -    "additionalProperties": false,
      -    "description": "A reference to another resource. Canonical output shape.",
      -    "properties": {
      -      "id": {
      -        "anyOf": [
      -          {
      -            "type": "integer"
      -          },
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "default": null,
      -        "description": "Resource id."
      -      },
      -      "name": {
      -        "anyOf": [
      -          {
      -            "type": "string"
      -          },
      -          {
      -            "type": "null"
      -          }
      -        ],
      -        "default": null,
      -        "description": "Human-readable name."
      -      }
      -    },
      -    "type": "object"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "additionalProperties": false,
      +    "properties": {
      +      "id": {
      +        "type": [
      +          "integer",
      +          "string",
      +          "null"
      +        ]
      +      },
      +      "name": {
      +        "type": [
      +          "string",
      +          "null"
      +        ]
      +      }
      +    },
      +    "type": "object"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / project / default
      Removed value: -null
    • removedOutput schema / properties / project / description
      Removed value: -"Owning project, or null for a global (cross-project) query."
    • removedOutput schema / properties / public / default
      Removed value: -false
    • removedOutput schema / properties / public / description
      Removed value: -"True when shared with everyone who can see the project; false when private to its owner."
    • removedOutput schema / properties / sort_by / description
      Removed value: -"Stored sort order, e.g. ['Finish date asc']."
    • removedOutput schema / properties / starred / default
      Removed value: -false
    • removedOutput schema / properties / starred / description
      Removed value: -"True when the current user starred (favorited) it."
    • removedOutput schema / properties / updated_at / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / updated_at / default
      Removed value: -null
    • removedOutput schema / properties / updated_at / description
      Removed value: -"ISO 8601 UTC timestamp."
    • addedOutput schema / properties / updated_at / type
      Added value: +[
      +  "string",
      +  "null"
      +]
  2. Changed7 schema fields changedv0.3.2
    • changedInput schema / properties / filters / description
      Previous value: -"The filters to store, in the same shape run_query's override_filters and list_work_packages' raw_filters take — e.g. [{'name': 'status', 'operator': 'o', 'values': []}, {'name': 'assignee', 'operator': '=', 'values': ['12']}]. Values are ids (or 'me'), not display names. Pass [] deliberately for a view that filters nothing: unlike a listing, a stored query with no filters shows every status."New value: +"The filters to store, same shape as run_query's override_filters / list_work_packages' raw_filters, e.g. [{'name': 'status', 'operator': 'o', 'values': []}, {'name': 'assignee', 'operator': '=', 'values': ['12']}]. Values are ids (or 'me'), not names. Pass [] for a view with no filters — unlike a listing, it then shows every status."
    • changedInput schema / properties / group_by / description
      Previous value: -"Column to group the results by, e.g. 'status', 'assignee', 'type' or 'version'. Grouping is what makes run_query return 'groups' with per-group counts. Omit for a flat list."New value: +"Column to group results by, e.g. 'status', 'assignee'. Makes run_query return 'groups' with per-group counts. Omit for a flat list."
    • changedInput schema / properties / name / description
      Previous value: -"Name the view is saved under, e.g. 'Overdue in Platform'. Names are not unique upstream, so a second save with the same name creates a second view."New value: +"Name the view is saved under, e.g. 'Overdue in Platform'. Not unique upstream — a repeat name creates a second view."
    • changedInput schema / properties / project_id / description
      Previous value: -"Numeric project id the view belongs to, from list_projects. Omit for a global (cross-project) view — but project-scoped filters such as version, category or subprojectId are then rejected."New value: +"Numeric project id the view belongs to; from list_projects. Omit for a global view — project-scoped filters (version, category, subprojectId) are then rejected."
    • changedInput schema / properties / public / description
      Previous value: -"true shares the view with everyone who can see the project; false (default) keeps it private to the authenticated user. Sharing usually needs the 'manage public queries' permission."New value: +"true shares the view with everyone who can see the project; false (default) keeps it private. Sharing usually needs 'manage public queries'."
    • changedInput schema / properties / sort_by / description
      Previous value: -"Stored sort order, e.g. [['due_date', 'asc'], ['id', 'desc']]. Keys are the snake_case work-package columns list_work_packages sorts by; unknown keys are rejected locally with the allowed set listed. Omit for the default."New value: +"Stored sort order, e.g. [['due_date', 'asc'], ['id', 'desc']]. Unknown keys are rejected locally, listing the allowed set. Omit for the default."
    • changedInput schema / properties / star / description
      Previous value: -"Also star (favorite) the view for the authenticated user, so it appears in their sidebar. Done as a second call after the query exists; if it fails the query is still saved and 'notes' says so."New value: +"Also star (favorite) the view, so it appears in the sidebar. A second call after the query exists; a failure still leaves it saved (noted in 'notes') — don't re-save."
  3. First observedv0.1.0

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations present, this goes well past the bar: it discloses server-side validation via POST /queries/form returning `violations` with nothing saved, silent filter dropping surfaced in `notes`, the custom-field value caveat where a failure means no save, and the star-as-second-call partial-failure semantics that pair with idempotentHint=false. It also warns that repeat names create duplicate views, consistent with the non-idempotent annotation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Structure is strong — purpose first, then validation/returns, then pitfalls, then cross-references — and each block carries operational content. It is long, but the density is warranted by a 7-parameter mutation tool with non-obvious failure modes; only minor trimming is possible without losing signal.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Even though an output schema exists, the description still sketches the return shape ({id, name, project, filters as readable sentences, ...}) and tells the agent to retain `id` for run_query. For a write tool with a validation step, partial-failure paths, and unsupported edit/delete, nothing an agent needs is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, yet the description still adds semantics the schema lacks: values are ids (or 'me') rather than names, empty values array for '*'/'!*', `[]` filters meaning an unfiltered view, sort_by rejecting unknown keys locally, group_by causing run_query to return per-group counts, and omitting project_id forcing rejection of project-scoped filters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first sentence names a specific verb (save) and resource (filter set as a reusable OpenProject view), and the following sentences pin down the exact scope: persisted view, visible in the UI, reproducible via run_query. An agent can distinguish it immediately from run_query (execution) and list_queries (enumeration).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit routing is given: use list_work_packages to prove filters first, list_queries to see existing views with ids, run_query(query_id=...) to execute this one, list_projects for project_id. Exclusions are also stated — editing and deleting saved views must be done in the OpenProject UI, which is not offered here.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.