Skip to main content
Glama

Create project

create_project

Create a top-level project or subproject after validating fields and identifiers through OpenProject's form endpoint, so conflicts return clear violations before commit.

Instructions

Create a project, validated through OpenProject's own form endpoint first.

Use it for a new workspace or, with parent_id, for a subproject of an existing one. The call runs POST /projects/form before committing, so a taken identifier, an unusable parent or a bad status comes back as violations naming the attribute instead of an opaque failure — and the identifier OpenProject derives from the name is used verbatim on the commit.

Returns the created project: {id, identifier, name, active, public, parent, status_code, description, status_explanation, created_at, updated_at}. Keep the id — every other tool's project_id accepts it, as does the identifier.

Pitfalls: creating projects usually requires the 'create project' permission or admin rights, so a 403 here is about the account, not the payload. The new project starts with the instance's default modules and types enabled — check get_project_metadata(project_id=...) before creating work packages in it. Members are not copied from the parent; add them with create_membership (admin-gated: hidden unless the server sets OPENPROJECT_MCP_ADMIN_TOOLS=1).

Cross-references: list_projects finds the parent id; update_project changes any of these fields afterwards; get_project_metadata lists the types, versions and categories valid inside the result.

Input Schema

NameRequiredDescriptionDefault
nameYesDisplay name of the new project, e.g. 'Apollo migration'. Names need not be unique on the instance; the identifier is what must be.
publicNoTrue makes the project visible to every logged-in user without a membership. Omit to take the instance default (normally private).
parent_idNoNumeric id or identifier of the parent project, to create a subproject. Ids come from list_projects. Omit for a top-level project. Creating a subproject needs the 'add subprojects' permission on the parent.
identifierNoURL slug for /projects/<identifier>: lowercase letters, digits, '-' and '_' only, unique across the whole instance. Omit it and OpenProject derives one from the name — the derived value is in the result. A slug that is already taken comes back as a validation violation, not a surprise rename.
descriptionNoProject description in markdown. Omit to leave it empty.
status_codeNoInitial project status: on_track, at_risk, off_track, not_started, finished or discontinued. These codes are the only accepted values — a free-text status is rejected rather than silently dropped. Omit for no status.

Output Schema

NameRequiredDescriptionDefault
idNo
nameNo
activeNo
parentNo
publicNo
created_atNo
identifierNo
updated_atNo
descriptionNo
status_codeNo
workspace_typeNo
status_explanationNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed48 schema fields changedv0.4.0
    • removedOutput schema / description
      Removed value: -"Full project detail: the row plus text fields and timestamps."
    • removedOutput schema / properties / active / anyOf
      Removed value: -[
      -  {
      -    "type": "boolean"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / active / default
      Removed value: -null
    • removedOutput schema / properties / active / description
      Removed value: -"False for archived projects (read-only in the UI)."
    • addedOutput schema / properties / active / type
      Added value: +[
      +  "boolean",
      +  "null"
      +]
    • removedOutput schema / properties / created_at / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / created_at / default
      Removed value: -null
    • removedOutput schema / properties / created_at / description
      Removed value: -"ISO 8601 UTC timestamp."
    • addedOutput schema / properties / created_at / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / description / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / description / default
      Removed value: -null
    • removedOutput schema / properties / description / description
      Removed value: -"Description as markdown (raw); html is dropped."
    • addedOutput schema / properties / description / 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: -"Numeric project id; accepted by every project_id parameter."
    • addedOutput schema / properties / id / type
      Added value: +[
      +  "integer",
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / identifier / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / identifier / default
      Removed value: -null
    • removedOutput schema / properties / identifier / description
      Removed value: -"URL slug from /projects/<identifier>; also accepted wherever an id is."
    • addedOutput schema / properties / identifier / type
      Added value: +[
      +  "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: -"Display name."
    • addedOutput schema / properties / name / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • changedOutput schema / properties / parent / 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 / parent / default
      Removed value: -null
    • removedOutput schema / properties / parent / description
      Removed value: -"Parent project, when this is a subproject."
    • removedOutput schema / properties / public / anyOf
      Removed value: -[
      -  {
      -    "type": "boolean"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / public / default
      Removed value: -null
    • removedOutput schema / properties / public / description
      Removed value: -"True when visible to users without a membership."
    • addedOutput schema / properties / public / type
      Added value: +[
      +  "boolean",
      +  "null"
      +]
    • removedOutput schema / properties / status_code / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / status_code / default
      Removed value: -null
    • removedOutput schema / properties / status_code / description
      Removed value: -"Project status code, one of: on_track, at_risk, off_track, not_started, finished, discontinued. A code, never a translated label; null means no status has been set."
    • addedOutput schema / properties / status_code / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / status_explanation / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / status_explanation / default
      Removed value: -null
    • removedOutput schema / properties / status_explanation / description
      Removed value: -"Free-text explanation of status_code, markdown (raw)."
    • addedOutput schema / properties / status_explanation / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • 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"
      +]
    • removedOutput schema / properties / workspace_type / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • removedOutput schema / properties / workspace_type / default
      Removed value: -null
    • removedOutput schema / properties / workspace_type / description
      Removed value: -"Workspace kind: 'project', 'program' or 'portfolio'. Pre-17 instances only have 'project'; on 17.x project listings mix all three kinds, so check this before treating a row as a plain project."
    • addedOutput schema / properties / workspace_type / type
      Added value: +[
      +  "string",
      +  "null"
      +]
  2. First observedv0.1.0

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare this as a non-idempotent write, but the description adds real substance beyond them: the pre-commit form validation that surfaces `violations` per attribute, the fact the derived identifier is committed verbatim, the 403-is-an-account-problem pitfall, default modules/types enabled on creation, and that members are not inherited from the parent. That is exactly the behavioral context annotations cannot carry.

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 the verb and the key differentiator, then organized into usage, returns, pitfalls and cross-references — dense but navigable. It is somewhat long, and the listed return fields partly duplicate the output schema, which costs a point.

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?

For a 6-param mutation with permissions implications, the description covers creation modes, validation behavior, failure semantics, post-creation caveats and related tools. Output schema exists yet the description's return-value hint (keep the id, identifier also accepted) adds routing value rather than pure redundancy.

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%, so the schema already documents every parameter richly, which sets the baseline at 3. The description largely restates schema content (identifier derivation, status codes, parent permission) rather than adding param-level meaning the schema lacks.

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 ('Create a project') and immediately distinguishes itself from siblings by noting the two-phase form-endpoint validation ('POST /projects/form before committing'). An agent can tell it apart from copy_project or create_work_package without opening another 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 covers the two usage modes (top-level workspace vs. subproject via parent_id) and the cross-references section names the alternatives and their roles — list_projects to find the parent, update_project to change fields afterwards, get_project_metadata to inspect types/versions. It also gives a when-not condition implicitly via the 403 permission caveat.

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