Skip to main content
Glama

List file links

list_file_links
Read-onlyIdempotent

List external-storage files linked to a work package and return OpenProject URLs, so you can identify which documents belong to a ticket.

Instructions

List the external-storage files (Nextcloud, OneDrive/SharePoint) linked to a work package.

File links are OpenProject's other kind of file: instead of living inside OpenProject like an attachment, the document stays in a connected storage and the work package points at it. Use this to answer "which documents belong to this ticket" — and pair it with list_attachments, because the two lists are disjoint and neither implies the other.

Returns the standard list envelope, fetched in full (has_more is always false). Each row carries file_name, the storage it lives on, the file's origin_id inside that storage, mime_type, the creator and — the useful part — open_url and download_url. Those are absolute OpenProject URLs that redirect to the storage once OpenProject has resolved the link, so hand them to the user: they need the user's own OpenProject login, this server cannot fetch the bytes, and download_attachment does not work on them.

Pitfalls: this needs the storages module and a storage connected to the project. When it is missing (404) or this account may not read the links (403) the call still succeeds with an EMPTY list and a note explaining which — read notes before saying a ticket has no documents. An empty list is never proof either: an account lacking the 'view file links' permission gets an empty 200 rather than a 403, which is exactly what that note says. permission carries the storage's own wording — 'View allowed' means the URLs will work, 'View not allowed', 'Not found' and 'Error' mean they will not, and null means the storage said nothing. Creating and deleting file links, and browsing the remote storage, are out of scope for this server — do them in the OpenProject UI.

Related: list_attachments covers files stored inside OpenProject, download_attachment fetches those bytes, and get_work_package gives the ticket the links belong to.

Input Schema

NameRequiredDescriptionDefault
work_package_idYesNumeric work package id whose linked storage files to list. It comes from search_work_packages, list_work_packages or get_work_package — never an attachment id and never a project id.

Output Schema

NameRequiredDescriptionDefault
sumsNo
itemsNo
notesNo
groupsNo
paginationYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed52 schema fields changedv0.4.0
    • changedOutput schema / properties / groups / anyOf
      Previous value: -[
      -  {
      -    "items": {
      -      "description": "A server-side group bucket, computed over the full filtered set.",
      -      "properties": {
      -        "count": {
      -          "default": 0,
      -          "description": "Records in this group across all pages.",
      -          "type": "integer"
      -        },
      -        "sums": {
      -          "anyOf": [
      -            {
      -              "additionalProperties": {
      -                "type": "number"
      -              },
      -              "type": "object"
      -            },
      -            {
      -              "type": "null"
      -            }
      -          ],
      -          "default": null,
      -          "description": "Per-group sums when show_sums was requested."
      -        },
      -        "value": {
      -          "anyOf": [
      -            {
      -              "type": "string"
      -            },
      -            {
      -              "type": "null"
      -            }
      -          ],
      -          "default": null,
      -          "description": "Group value, e.g. a status name."
      -        }
      -      },
      -      "type": "object"
      -    },
      -    "type": "array"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "items": {
      +      "properties": {
      +        "count": {
      +          "type": "integer"
      +        },
      +        "sums": {
      +          "anyOf": [
      +            {
      +              "additionalProperties": {
      +                "type": "number"
      +              },
      +              "type": "object"
      +            },
      +            {
      +              "type": "null"
      +            }
      +          ]
      +        },
      +        "value": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "type": "array"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • removedOutput schema / properties / groups / default
      Removed value: -null
    • removedOutput schema / properties / groups / description
      Removed value: -"Present only when group_by was requested."
    • removedOutput schema / properties / items / description
      Removed value: -"The page of results."
    • removedOutput schema / properties / items / items / description
      Removed value: -"One file on an external storage linked to a work package."
    • removedOutput schema / properties / items / items / properties / created_at / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / items / items / properties / created_at / default
      Removed value: -null
    • removedOutput schema / properties / items / items / properties / created_at / description
      Removed value: -"ISO 8601 UTC time the link was created."
    • addedOutput schema / properties / items / items / properties / created_at / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • changedOutput schema / properties / items / items / properties / creator / 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 / items / items / properties / creator / default
      Removed value: -null
    • removedOutput schema / properties / items / items / properties / creator / description
      Removed value: -"OpenProject user who linked the file to the work package."
    • removedOutput schema / properties / items / items / properties / download_url / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / items / items / properties / download_url / default
      Removed value: -null
    • removedOutput schema / properties / items / items / properties / download_url / description
      Removed value: -"Absolute OpenProject URL that redirects to the file's download on the storage. Also an OpenProject endpoint needing the user's login, so download_attachment cannot use it."
    • addedOutput schema / properties / items / items / properties / download_url / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / items / items / properties / file_name / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / items / items / properties / file_name / default
      Removed value: -null
    • removedOutput schema / properties / items / items / properties / file_name / description
      Removed value: -"Name of the file as the storage reports it."
    • addedOutput schema / properties / items / items / properties / file_name / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / items / items / properties / id / anyOf
      Removed value: -[
      -  {
      -    "type": "integer"
      -  },
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / items / items / properties / id / default
      Removed value: -null
    • removedOutput schema / properties / items / items / properties / id / description
      Removed value: -"File-link id inside OpenProject; not the file's own id."
    • addedOutput schema / properties / items / items / properties / id / type
      Added value: +[
      +  "integer",
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / items / items / properties / mime_type / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / items / items / properties / mime_type / default
      Removed value: -null
    • removedOutput schema / properties / items / items / properties / mime_type / description
      Removed value: -"MIME type reported by the storage, when it reports one."
    • addedOutput schema / properties / items / items / properties / mime_type / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / items / items / properties / open_url / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / items / items / properties / open_url / default
      Removed value: -null
    • removedOutput schema / properties / items / items / properties / open_url / description
      Removed value: -"Absolute OpenProject URL that opens the file: it redirects to the storage after resolving the link server-side. Give it to the user — it needs their own OpenProject login, and this server cannot fetch the bytes."
    • addedOutput schema / properties / items / items / properties / open_url / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / items / items / properties / origin_id / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / items / items / properties / origin_id / default
      Removed value: -null
    • removedOutput schema / properties / items / items / properties / origin_id / description
      Removed value: -"The file's id INSIDE that storage (Nextcloud/OneDrive), not an OpenProject id."
    • addedOutput schema / properties / items / items / properties / origin_id / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / items / items / properties / permission / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / items / items / properties / permission / default
      Removed value: -null
    • removedOutput schema / properties / items / items / properties / permission / description
      Removed value: -"What the storage said about this account's access to the file: 'View allowed', 'View not allowed', 'Not found' or 'Error'. Null means the storage did not report a status, not that access is fine."
    • addedOutput schema / properties / items / items / properties / permission / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • changedOutput schema / properties / items / items / properties / storage / 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 / items / items / properties / storage / default
      Removed value: -null
    • removedOutput schema / properties / items / items / properties / storage / description
      Removed value: -"The external storage the file lives on ({id, name}), e.g. a Nextcloud instance."
    • removedOutput schema / properties / notes / default
      Removed value: -null
    • removedOutput schema / properties / notes / description
      Removed value: -"Degradation markers: capped aggregations, unavailable modules, …"
    • removedOutput schema / properties / pagination / description
      Removed value: -"Total/page/page_size/has_more."
    • removedOutput schema / properties / pagination / properties / has_more / description
      Removed value: -"True when further pages exist."
    • removedOutput schema / properties / pagination / properties / page / description
      Removed value: -"1-based page number of this result."
    • removedOutput schema / properties / pagination / properties / page_size / description
      Removed value: -"Records requested per page."
    • removedOutput schema / properties / pagination / properties / total / description
      Removed value: -"Total matching records on the server."
    • removedOutput schema / properties / sums / default
      Removed value: -null
    • removedOutput schema / properties / sums / description
      Removed value: -"Present only when show_sums was requested."
  2. First observedv0.1.0

TDQS

A4.5/5.0
Behavior5/5

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

Annotations only declare a safe read; the description adds substantial non-obvious behavior: 404/403 conditions still return a 200 with an EMPTY list plus a note, empty is never proof of no documents, permission values ('View allowed', 'Not found', null) determine whether URLs work, and returned URLs require the user's own OpenProject login since the server cannot fetch bytes. None of this is inferable from structured fields.

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?

Front-loaded with purpose, then the attachments pairing, pitfalls, and related tools in a logical order; the pitfall paragraph is dense but earns its place. It runs longer than needed, and the pitfall about 403/empty lists is stated twice in slightly different words.

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

Completeness4/5

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

Covers prerequisites (storages module, storage connected to project), failure modes, permission semantics and the envelope (has_more always false). Some redundancy with the output schema when enumerating row fields (file_name, mime_type, origin_id), but that enumeration supports the URL caveat, so the detail is justified rather than missing.

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

Parameters3/5

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

Schema coverage is 100% and the single parameter's description already specifies provenance ('from search_work_packages, list_work_packages or get_work_package — never an attachment id and never a project id'). The prose adds no further guidance on work_package_id, so the schema carries the load.

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?

States a specific verb and resource ('List the external-storage files ... linked to a work package') and immediately disambiguates the concept from attachments: 'instead of living inside OpenProject like an attachment, the document stays in a connected storage.' An agent can distinguish list_file_links from list_attachments without opening either schema.

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?

Explicitly says to pair with list_attachments because 'the two lists are disjoint and neither implies the other', and names out-of-scope operations (creating/deleting links, browsing remote storage) with a redirect to the UI. It also names the wrong tool to use for bytes (download_attachment does not work here).

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