> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.taktoria.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.taktoria.com/_mcp/server.

# OKR Hub tools

> OKR Hub's MCP tools and skills: objectives, key results, check-ins and scorecard grades, read and written by the app's own rules.

OKR Hub's MCP server, `https://www.taktoria.com/mcp/<workspace>/okrhub` (each workspace has its own), has a tool for
everything a person can do in OKR Hub. Each runs as the person who connected,
through the same rules as the app and the REST API.

## Roles

What a connection may do follows the person's
[role in OKR Hub](/getting-started/authentication#app-roles):

* **An app admin** of OKR Hub (every workspace owner and admin is one) may
  edit any objective they can see, and its key results. It does not widen
  what they see: a private objective they have no part in stays hidden.
* **A member** creates objectives, changes the ones they own, their team's
  and the ones they created, and records progress on those and on the key
  results they own.
* **A viewer** reads what a member would. Their connection lists and accepts
  only the read tools, whatever it was granted: a write tool called anyway is
  refused (`viewer_only`), and the consent page offers them only **Read
  only**. See [MCP servers](/ai-assistants/mcp-servers#scopes).

## Rules

* **Seeing.** A public objective is everyone's. A private one is seen by its
  owner, its team (and the teams inside it), the owners of its key results,
  and whoever created it, whoever it belongs to. App admins are no exception. An objective
  the person may not see is not found, and reads exactly like one that does
  not exist.
* **Changing** an objective and its key results' definitions is for its owner,
  its team, whoever created it, or an app admin of OKR Hub.
* **Recording progress** (check-ins, scores, scorecard grades and comments) is
  for all of those, plus a key result's own owners, directly or through a team.
* **Creating** an objective is for anybody with an OKR Hub seat but a viewer, for anybody
  in the workspace and any of its teams, with or without key results. The
  creator keeps the right to see and change it. One created for somebody
  else or a team is not on the creator's `my_objectives`, which lists what
  they answer for; `browse_objectives` and `search` find it.
* **What is written** meets the same rules everywhere: titles are trimmed and
  never blank, a fiscal year is 2000 to 2100, a weight 0.01 to 100, and every
  owner is a member or team of the workspace (anybody else refuses the whole
  call; nobody is dropped). A score set on a key result, with
  `update_key_result` or `create_key_result`, is recorded as a check-in with
  no note, as `bulk_score` does; `record_check_in` adds the note.

Periods are the workspace's **fiscal** quarters and years, which need not match
the calendar's: `okr_periods` says which is current. Scores run from 0 to 1 and
are rolled up as weighted means of what is scored. Every objective and key
result comes back with the `url` of its page.

`whoami`, `search`, `find_people` and `find_teams` are on every server; see
[MCP servers](/ai-assistants/mcp-servers). Owners are named by id
(`ownerUserId`, `ownerUserIds`, `teamId`, `ownerTeamIds`, `teamIds`):
`find_people` finds people by name or email address, with whether each holds
an OKR Hub seat, and `find_teams` finds teams by name, as `team_scores` also
does.

## Read tools

Listed to every connection with `okrhub:read`.

| Tool                 | What it does                                                                                                      | Key inputs                                                                                            |
| -------------------- | ----------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `okr_periods`        | The current fiscal period, the periods offered, and the month the fiscal year starts                              | none                                                                                                  |
| `list_objectives`    | Every objective the person may see, newest year first, with key results and scores; paged by cursor               | `year`, `quarter`, `teamId`, `ownerUserId`, `visibility`, `draft`, `archived`, `q`, `limit`, `cursor` |
| `get_objective`      | One objective, with `canEdit` and `updatableKeyResultIds`                                                         | `objectiveId`                                                                                         |
| `list_key_results`   | An objective's key results, in their order, each with `lastCheckInAt`                                             | `objectiveId`, `draft`                                                                                |
| `get_key_result`     | One key result, with `canEdit` and `canUpdate`                                                                    | `keyResultId`                                                                                         |
| `list_check_ins`     | A key result's check-ins, newest first, with `metric` on those a connected metric recorded; paged by cursor       | `keyResultId`, `limit`, `cursor`                                                                      |
| `get_scorecard`      | A fiscal year's scorecard, with averages overall and by priority                                                  | `year`, `teamIds`, `priority`, `frames`, `mid`                                                        |
| `list_grades`        | What is written on a key result's scorecard cells                                                                 | `keyResultId`                                                                                         |
| `list_grade_changes` | Who changed a key result's grades, from what to what (`fromNoScore`/`toNoScore` for a reset); paged by cursor     | `keyResultId`, `limit`, `cursor`                                                                      |
| `my_objectives`      | My OKRs for a period: owned, the person's teams', written with no owner, or holding a key result; with the rollup | `period`, `teamIds`, `priority`, `includeTeams`, `q`, `sort`, `page`                                  |
| `browse_objectives`  | Everything the person may see in a period, or every period, with the rollup                                       | `period`, `allPeriods`, `teamIds`, `priority`, `q`, `sort`, `page`                                    |
| `team_scores`        | Every team's score for a period                                                                                   | `period`, `q`, `sort`, `onlyScored`, `page`                                                           |
| `team_okrs`          | One team's OKRs for a period, with who is on it and what the person may do                                        | `slug`, `period`                                                                                      |

A `period` is `{ "period": "QUARTERLY", "year": 2026, "quarter": 3 }`, or
`{ "period": "ANNUAL", "year": 2026 }`; left out, it is the current one.

## Write tools

Listed only to a connection with `okrhub:write`, and never to a Viewer of OKR
Hub.

| Tool                     | What it does                                                                                                                        | Key inputs                                                                                           |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `create_objective`       | Create an objective, optionally with its key results; anybody may, for anybody                                                      | `title`, `period`, `year`, `quarter`, `ownerUserId` or `teamId`, `visibility`, `draft`, `keyResults` |
| `update_objective`       | Change only the fields sent, including `archived`                                                                                   | `objectiveId`, any field                                                                             |
| `publish_objective`      | Take an objective out of draft                                                                                                      | `objectiveId`                                                                                        |
| `delete_objective`       | Delete an objective and everything under it (destructive)                                                                           | `objectiveId`                                                                                        |
| `reorder_objectives`     | Swap objectives among the places they hold in the workspace's order                                                                 | `ids`                                                                                                |
| `bulk_create_objectives` | Create a period's objectives and key results from text, as Bulk entry does                                                          | `text`, `period`, `year`, `quarter`, `ownerUserId` or `teamId`                                       |
| `create_key_result`      | Add a key result                                                                                                                    | `objectiveId`, `title`, `weight`, `priority`, `ownerUserIds`, `ownerTeamIds`                         |
| `update_key_result`      | Change a key result; `score` alone is also its owners', and is recorded as a check-in                                               | `keyResultId`, any field                                                                             |
| `publish_key_result`     | Take a key result out of draft                                                                                                      | `keyResultId`                                                                                        |
| `delete_key_result`      | Delete a key result with its check-ins and grades (destructive)                                                                     | `keyResultId`                                                                                        |
| `reorder_key_results`    | Put all of an objective's key results in a new order                                                                                | `objectiveId`, `ids`                                                                                 |
| `record_check_in`        | Record a score and a note, optionally as a scorecard checkpoint's grade                                                             | `keyResultId`, `score`, `note`, `recordedAt`, `checkpoint`                                           |
| `bulk_score`             | Score many key results at once; each new score is a check-in, and what it skipped is listed                                         | `scores` (key result id → score or `null`)                                                           |
| `set_scorecard_cell`     | Set or clear a scorecard cell's grade and comment, or reset its score with `noScore: true` (destructive: a cleared comment is gone) | `keyResultId`, `checkpoint`, `score`, `noScore`, `note`                                              |

## Skills

Alongside its tools the server offers skills: step-by-step guides for work
that spans several tools and needs some OKR know-how. Each is a resource,
`skill://okrhub/<name>/SKILL.md`, and a prompt of the same name. Write skills
use write tools, so they are offered only to a connection with `okrhub:write`.

| Skill                  | Access | What it is for                                                                                                        | Arguments         |
| ---------------------- | ------ | --------------------------------------------------------------------------------------------------------------------- | ----------------- |
| `find-anything`        | read   | Searching OKR Hub well with `search`, on every server                                                                 | `request`         |
| `okr-status-report`    | read   | How a team's, a person's or the workspace's OKRs stand in a fiscal period: scores, what is off track, what went quiet | `scope`, `period` |
| `draft-quarterly-okrs` | write  | Draft next fiscal quarter's objectives and measurable key results, from last quarter's, all left as drafts            | `owner`, `focus`  |
| `mid-quarter-check-in` | write  | Go through a person's or a team's key results and record an honest check-in on each                                   | `team`            |
| `score-the-quarter`    | write  | Give each key result its final grade on the scorecard, with comments where a grade needs one                          | `team`, `quarter` |

`draft-quarterly-okrs` comes with a reference,
`skill://okrhub/draft-quarterly-okrs/references/writing-good-key-results.md`,
on what makes a key result measurable. Every write skill asks the person to
confirm before it changes anything.

The read tools that return key results (`list_objectives`, `get_objective`,
`list_key_results`, `get_key_result`, `my_objectives`, `browse_objectives`
and `team_okrs`) give each one `lastCheckInAt`: when its newest check-in was
recorded, or `null` if it has none. That is how long it has gone quiet, without
a `list_check_ins` call per key result; `okr-status-report` uses it.

They give each one `metric` too: the connected metric that drives its score,
as `{ name, kind, paused }` (`kind` is `WEBHOOK` or `PULL`), or `null` if none.
A metric records a check-in each time its number moves, so a person's check-in
on such a key result stands only until the metric next moves;
`mid-quarter-check-in` notes or skips them. Metrics are set up on the key
result's page in the app; neither the tools nor the API reveal a metric's
address, token or secret.

## Errors

A refusal is a tool error (`isError: true`) saying why: not found (missing, or
not the person's to see), not allowed (who may do it instead), or the input
that was wrong, such as a checkpoint the objective's period does not have or
a check-in in the future.