Skip to main content
Glama

Get project margin

well_get_project_margin
Read-only

Read the revenue, expense, margin and margin rate of one workspace project. The result is one row per accounting currency, with revenue and expense taken from the project's allocation rows on posted (VALIDATED or LOCKED) journal lines, plus its allocation rows on live invoice items whose invoice has no posted journal entry yet; unbooked_revenue and unbooked_expense give that part per currency, and each allocation row says whether it is booked. Revenue counts positive on credit revenue lines and negative on debit revenue lines; expense counts positive on debit expense lines and negative on credit expense lines. The rate is margin divided by revenue, as a percentage with one decimal place; it is null when revenue is zero. A project with no allocations, a deleted project, or a project of another workspace returns an empty margins list. project_name is the live project's display name, or null when the id names no live project of the workspace. monthly is the same revenue, expense and margin grouped per calendar month of the posted entry date (or of the issue date of an unbooked invoice), per currency: it is never truncated, so the months of one currency sum back to its margin row. The result also lists the project's allocations on posted revenue or expense lines and on unbooked invoice items, newest entry first and at most 200 rows, each with its entry date, account name, account type, share, signed amount and currency. allocations_truncated is true when older rows were left out: the margins and the monthly rows still count every row, and the answer says the list shows only the newest rows. budget lists the project's budget cells summed per budget version, fiscal year, fiscal month (1 to 12) and currency, with planned revenue, expense and margin; actual_by_period lists the same actual revenue, expense and margin per fiscal year and fiscal period of the posted entries (period 13 is year-end), so a budget row compares with the actual row of the same fiscal period. Budget rows come from budget versions and are never summed into the actual figures.

Use it to answer "what is the margin on Acme?" after project allocations have been written.

When the token authorizes one workspace, call this directly — no workspace call is needed first. When it authorizes several, this read will not guess which one you mean: pass workspace_id on the call.

Input Schema

NameRequiredDescriptionDefault
project_idYesThe project, from well_list_projects.
workspace_idNoTarget workspace. Omit when the token authorizes one workspace. Required when it authorizes several: this read reports one workspace's own figures and will not choose which.
conversation_idNoThe conversation id returned by the previous Well result, in its meta under well/conversation_id, in its structuredContent, or in its JSON text block. Pass it back on every call in the same conversation, including a call a card makes, so the chosen workspace and the earlier answers still apply. It decides the conversation on its own: nothing the host states about the session replaces it. Omit it only on the first call of a conversation.
workspace_scopeNoRestrict this call to the family: the token's primary workspace plus the company workspaces under it that you are a member of. Unrelated authorized workspaces drop out of the read; row reads merge across the family, while a per-workspace figure still reports exactly one workspace.

Output Schema

NameRequiredDescriptionDefault
errorNo
budgetYes
marginsYes
monthlyYes
successYes
allocationsYes
project_nameYes
conversation_idNoThe conversation this result belongs to. Pass it back as the conversation_id argument on every later Well call in the same conversation.
newly_connectedNoTools that connected to this workspace since the last result and that no session was told about yet, oldest first. Present only when at least one tool is new. The connected-line rule says when to tell an entry; when it does, one line per entry, in the person's language: "<name> is connected.". Never fold several entries into one sentence. Each entry comes back once, on one result only: never repeat its line later.
actual_by_periodYes
resolved_workspaceNoThe workspace that answered, when the caller named none and the token authorizes several.
conversation_id_noteNoPresent only when the server opened a fresh lane, stating that no choice recorded earlier was read.
allocations_truncatedYes
conversation_id_sourceNoWhere the conversation id came from: the host's own request meta, the caller's argument, or a fresh lane the server opened.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed14 schema fields changed
    • removedOutput schema / properties / actual_by_period / items / properties / currency / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / actual_by_period / items / properties / currency / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / allocations / items / properties / currency / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / allocations / items / properties / currency / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / margins / items / properties / currency / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / margins / items / properties / currency / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / margins / items / properties / rate / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / margins / items / properties / rate / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / monthly / items / properties / currency / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / monthly / items / properties / currency / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / project_name / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / project_name / type
      Added value: +[
      +  "string",
      +  "null"
      +]
    • removedOutput schema / properties / resolved_workspace / properties / name / anyOf
      Removed value: -[
      -  {
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]
    • addedOutput schema / properties / resolved_workspace / properties / name / type
      Added value: +[
      +  "string",
      +  "null"
      +]
  2. Changed3 schema fields changed
    • addedOutput schema / properties / actual_by_period
      Added value: +{
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "currency": {
      +        "anyOf": [
      +          {
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ]
      +      },
      +      "expense": {
      +        "type": "string"
      +      },
      +      "fiscal_period": {
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "fiscal_year": {
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "margin": {
      +        "type": "string"
      +      },
      +      "revenue": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "fiscal_year",
      +      "fiscal_period",
      +      "currency",
      +      "revenue",
      +      "expense",
      +      "margin"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / budget
      Added value: +{
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "currency": {
      +        "type": "string"
      +      },
      +      "expense": {
      +        "type": "string"
      +      },
      +      "fiscal_period": {
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "fiscal_year": {
      +        "maximum": 9007199254740991,
      +        "minimum": -9007199254740991,
      +        "type": "integer"
      +      },
      +      "forecast_id": {
      +        "type": "string"
      +      },
      +      "forecast_name": {
      +        "type": "string"
      +      },
      +      "margin": {
      +        "type": "string"
      +      },
      +      "revenue": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "forecast_id",
      +      "forecast_name",
      +      "fiscal_year",
      +      "fiscal_period",
      +      "currency",
      +      "revenue",
      +      "expense",
      +      "margin"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "success",
      -  "project_name",
      -  "margins",
      -  "monthly",
      -  "allocations",
      -  "allocations_truncated"
      -]New value: +[
      +  "success",
      +  "project_name",
      +  "margins",
      +  "monthly",
      +  "allocations",
      +  "allocations_truncated",
      +  "budget",
      +  "actual_by_period"
      +]
  3. Changed5 schema fields changed
    • addedOutput schema / properties / allocations / items / properties / booked
      Added value: +{
      +  "type": "boolean"
      +}
    • changedOutput schema / properties / allocations / items / required
      Previous value: -[
      -  "entry_date",
      -  "account_name",
      -  "account_type",
      -  "percent",
      -  "amount",
      -  "currency"
      -]New value: +[
      +  "entry_date",
      +  "account_name",
      +  "account_type",
      +  "percent",
      +  "amount",
      +  "currency",
      +  "booked"
      +]
    • addedOutput schema / properties / margins / items / properties / unbooked_expense
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / margins / items / properties / unbooked_revenue
      Added value: +{
      +  "type": "string"
      +}
    • changedOutput schema / properties / margins / items / required
      Previous value: -[
      -  "project_id",
      -  "currency",
      -  "revenue",
      -  "expense",
      -  "margin",
      -  "rate"
      -]New value: +[
      +  "project_id",
      +  "currency",
      +  "revenue",
      +  "expense",
      +  "margin",
      +  "rate",
      +  "unbooked_revenue",
      +  "unbooked_expense"
      +]
  4. Changed7 schema fields changed
    • addedOutput schema / properties / allocations
      Added value: +{
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "account_name": {
      +        "type": "string"
      +      },
      +      "account_type": {
      +        "enum": [
      +          "REVENUE",
      +          "EXPENSE"
      +        ],
      +        "type": "string"
      +      },
      +      "amount": {
      +        "type": "string"
      +      },
      +      "currency": {
      +        "anyOf": [
      +          {
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ]
      +      },
      +      "entry_date": {
      +        "type": "string"
      +      },
      +      "percent": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "entry_date",
      +      "account_name",
      +      "account_type",
      +      "percent",
      +      "amount",
      +      "currency"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / allocations_truncated
      Added value: +{
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / margins / items / properties / rate
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ]
      +}
    • changedOutput schema / properties / margins / items / required
      Previous value: -[
      -  "project_id",
      -  "currency",
      -  "revenue",
      -  "expense",
      -  "margin"
      -]New value: +[
      +  "project_id",
      +  "currency",
      +  "revenue",
      +  "expense",
      +  "margin",
      +  "rate"
      +]
    • addedOutput schema / properties / monthly
      Added value: +{
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "currency": {
      +        "anyOf": [
      +          {
      +            "type": "string"
      +          },
      +          {
      +            "type": "null"
      +          }
      +        ]
      +      },
      +      "expense": {
      +        "type": "string"
      +      },
      +      "margin": {
      +        "type": "string"
      +      },
      +      "month": {
      +        "type": "string"
      +      },
      +      "revenue": {
      +        "type": "string"
      +      }
      +    },
      +    "required": [
      +      "currency",
      +      "month",
      +      "revenue",
      +      "expense",
      +      "margin"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
    • addedOutput schema / properties / project_name
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ]
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "success",
      -  "margins"
      -]New value: +[
      +  "success",
      +  "project_name",
      +  "margins",
      +  "monthly",
      +  "allocations",
      +  "allocations_truncated"
      +]
  5. Added

TDQS

A4.2/5.0
Behavior5/5

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

Annotations only declare it is a safe read. The description adds real behavioural detail beyond that: which journal-line states count (VALIDATED/LOCKED), how unbooked invoice items are folded in, sign conventions for revenue and expense, null rate on zero revenue, and the empty-list outcomes for deleted/foreign projects.

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

Conciseness2/5

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

Most of the text enumerates return values (margins, monthly, allocations, budget, actual_by_period, truncation flags) even though an output schema exists. The usage and workspace guidance the agent actually needs to call the tool is buried at the very end after a long block of result documentation.

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?

Given a read-only tool with a rich output schema, everything needed to call it correctly is present: prerequisites, workspace scoping, and the key caveats (200-row allocation cap, budget never summed into actuals).

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 description coverage is 100%, so the schema already documents project_id, workspace_id, conversation_id and workspace_scope. The description repeats the single-vs-multiple-workspace rule rather than adding syntax or format meaning, so it lands at the baseline.

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?

Opens with a specific verb and resource: 'Read the revenue, expense, margin and margin rate of one workspace project.' That clearly distinguishes it from sibling reads like well_get_project (metadata) and well_get_computed_figures (general figures).

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

Usage Guidelines4/5

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

Gives a concrete trigger ('Use it to answer "what is the margin on Acme?" after project allocations have been written') and workspace-selection preconditions. It does not name the neighbouring alternatives an agent might otherwise pick, such as well_get_computed_figures or well_get_project, so the routing is clear but not exhaustive.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources