This page describes the contract the MCP server of
Rillsoft Project keeps
with every client: how a tool is described, how input and output are
structured, what an error contains and which rules apply to undo, read-only
and session. Starting the server, the handshake and access protection are on
the MCP page. The complete tool catalogue is not maintained by
hand but generated from tools/list of the released product build; it
follows as soon as that build is named.
What an entry in tools/list carries#
| Field | Meaning |
|---|---|
name | canonical name with prefix rillsoft_, unique within the server |
title | short display name, English |
description | selection aid including effect, preconditions and limits, English |
inputSchema | complete JSON schema including nested objects and list items, additionalProperties: false |
outputSchema | schema of the successful structuredContent, equally complete |
annotations | readOnlyHint, destructiveHint, idempotentHint, openWorldHint |
destructiveHint is conservatively true wherever something is deleted,
overwritten, discarded or released with loss. idempotentHint is true only
if the same call repeatably has the same effect. openWorldHint is true
for file and network access, false for pure access to the document model.
The list is sorted ordinally by name so that a client keeps its cache; the
order is a sort, not a contract about positions.
Both schemas are enforced at runtime. The server validates arguments
before the call reaches the application; a structurally invalid call never
touches the project and leaves no undo step. Every successful
structuredContent is validated against its outputSchema; a violation is
an internal error, not a silent delivery.
Language boundary#
The server has no session language. It answers every client in the language of the running Rillsoft Project – German, English or Russian. What is read by machines stays the same everywhere:
| Level | DE build | EN build | RU build | Stability |
|---|---|---|---|---|
| tool names, arguments, result fields, enum values | English | English | English | identical |
title, description in tools/list | English | English | English | byte-identical |
error codes (error.data.code, _meta.errorCode) | English | English | English | identical |
error messages, note[], command, label, conflictText | German | English | Russian | localised |
Even a localised message names taskUuid, machine_role or
rillsoft_resource_pool_catalog_list unchanged – the reader should be able to
build the next call from it.
Field names and value ranges#
- Arguments and result fields carry English
lowerCamelCasenames, and the same business value has the same name in both directions: what the project tree returns asdurationHours, the task update accepts asdurationHours. An answer can be passed on without renaming. - Enum values are English
lower_snake_case:machine_role,capacity_driven,resource_chart; single-part values stay one word. The five dependency types arefinish_start,finish_start_no_delay,start_start,finish_finishandstart_finish. - Every bounded value range appears as an
enumin theinputSchema; thedescriptionexplains the meaning of the values and draws the line to the neighbouring value. - Dates in the format
DD.MM.YYYY hh:mm(time optional) orYYYY-MM-DDThh:mm; durations in hours. A date such as31.02.2026is rejected instead of silently rounded to 3 March. - Objects are addressed by their UUID; every creating call returns it. WBS codes are assigned by Rillsoft Project itself.
- Readable labels from the user interface are called
label; they depend on the language and are not keys.
Answer and error#
Every tool answer delivers the result twice: as plain text in
content[0].text (JSON, YAML for reports) and machine-readable in
structuredContent. A business rejection comes as isError: true with the
stable code in _meta.errorCode; the first line of the text repeats the
code:
{"id":9,"jsonrpc":"2.0","result":{"content":[{"text":"errorCode: rejected\nNo task with UUID 'xyz' found","type":"text"}],"isError":true,"_meta":{"errorCode":"rejected"}}}The same error in three builds – the code is the identifier, the text the explanation:
| Build | _meta.errorCode | content[0].text from line 2 |
|---|---|---|
| German | invalid_date_format | Ungültiger Wert für 'start': '32.13.2020' — erwartet wird DD.MM.YYYY hh:mm oder YYYY-MM-DDThh:mm |
| English | invalid_date_format | Invalid value for 'start': '32.13.2020' - DD.MM.YYYY hh:mm or YYYY-MM-DDThh:mm is expected |
| Russian | invalid_date_format | Недопустимое значение для 'start': '32.13.2020' — ожидается DD.MM.YYYY hh:mm или YYYY-MM-DDThh:mm |
Schema violations come as JSON-RPC error -32602 with error.data.code and
a language-neutral field path in error.data.field, e.g.
arguments.criterion with the list of permitted values. The error classes:
| Error class | Behaviour |
|---|---|
| schema error (type, required field, unknown field, value range) | -32602 before the jump into the application; the project is not touched |
| validation error (unknown UUID, invalid date, unknown id) | tool error before the command begins; project untouched |
| conflict on completion (working time, fixed dates, write protection) | automatic rollback; tool error with the conflict reason |
| unknown method, batch, lifecycle violation | -32601 or -32600 |
| session limit reached | -32000 |
The set of codes is cut at category level – around thirty codes instead of
three hundred messages. There is no rejection without a code; where a handler
sets none, the collective code rejected applies. Retry rules are built on
the code, never on the wording.
Access classes, undo and session#
Every tool belongs to exactly one access class. It yields both the
readOnlyHint and the filtering in read-only mode, so the two cannot
diverge.
| Class | Rule |
|---|---|
| read-only | changes neither task, assignment, date nor file; no undo step. Some tools of this class visibly change window or view state – their description says so |
| mutating | exactly one undo step per call, the same path as an action in the user interface; recalculation, critical path and view are updated on completion |
| session | file and session operations: create, open, save, export a project, switch the pool, undo and redo. They create no undo step; after creating or opening, the command history starts afresh |
Undo and redo are tools themselves and operate the same history as the user interface, including steps a person made there. The history stores a complete snapshot per command; very many single calls therefore take time.
Protocol rules that may differ from what you expect#
- Only protocol revision
2025-06-18is negotiated; older revisions are rejected. initializeassignsMcp-Session-Id;notifications/initializedunlocks the tools. Every further request carries session andMCP-Protocol-Version, otherwise400. At most 32 sessions, expiry after 30 minutes idle,DELETE /mcpends one.- JSON-RPC batches are rejected. Only the absence of
idmarks a notification;id: nullis a request. params.argumentsis required as soon as the tool has parameters; a forgottenargumentswould otherwise be a silent call with default values.- Paths are absolute (drive or UNC) with the matching extension; listing or deleting files deliberately does not exist.
- Portfolios have their own open tool; the project tool rejects an
.rppwith a hint and vice versa. In a portfolio mutating tools are rejected, the time scale excepted.
A walkthrough in eighteen calls#
The documented end-to-end sequence across all areas, using the mcp
function from the MCP page; <A> is the UUID from the result of
the creating call:
# build and assign
mcp '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"rillsoft_project_create","arguments":{"name":"Demo","discardChanges":true}}}'
mcp '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"rillsoft_project_update","arguments":{"start":"05.10.2026 08:00","finish":"27.11.2026 17:00","fixed":true}}}'
mcp '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"rillsoft_task_create","arguments":{"name":"Task A","start":"05.10.2026 08:00","durationHours":16}}}'
mcp '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"rillsoft_task_role_assignment_set","arguments":{"taskUuid":"<A>","roleId":11001,"quantity":2}}}'
# save a baseline, then change the plan
mcp '{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"rillsoft_baseline_create","arguments":{"name":"Plan V1"}}}'
mcp '{"jsonrpc":"2.0","id":6,"method":"tools/call","params":{"name":"rillsoft_task_update","arguments":{"uuid":"<A>","durationHours":24}}}'
# record actual data
mcp '{"jsonrpc":"2.0","id":7,"method":"tools/call","params":{"name":"rillsoft_task_progress_set","arguments":{"uuid":"<A>","progressPercent":50}}}'
mcp '{"jsonrpc":"2.0","id":8,"method":"tools/call","params":{"name":"rillsoft_project_status_date_set","arguments":{"statusDate":"07.10.2026 08:00"}}}'
# plan/actual (time) …
mcp '{"jsonrpc":"2.0","id":9,"method":"tools/call","params":{"name":"rillsoft_view_state_apply","arguments":{"view":{"name":"time_variance"}}}}'
mcp '{"jsonrpc":"2.0","id":10,"method":"tools/call","params":{"name":"rillsoft_variance_report_get","arguments":{}}}'
# → planned 16 h, actual 24 h, variance 8 h
# … and workload, condensed to weeks
mcp '{"jsonrpc":"2.0","id":11,"method":"tools/call","params":{"name":"rillsoft_view_state_apply","arguments":{"view":{"name":"employee_capacity"}}}}'
mcp '{"jsonrpc":"2.0","id":12,"method":"tools/call","params":{"name":"rillsoft_timescale_apply","arguments":{"unit":"week"}}}'
mcp '{"jsonrpc":"2.0","id":13,"method":"tools/call","params":{"name":"rillsoft_analysis_report_get","arguments":{}}}'
# save, take back a slip, reopen the saved state
mcp '{"jsonrpc":"2.0","id":14,"method":"tools/call","params":{"name":"rillsoft_project_file_save_as","arguments":{"path":"C:/Projects/Demo.rpj"}}}'
mcp '{"jsonrpc":"2.0","id":15,"method":"tools/call","params":{"name":"rillsoft_task_update","arguments":{"uuid":"<A>","durationHours":40}}}'
mcp '{"jsonrpc":"2.0","id":16,"method":"tools/call","params":{"name":"rillsoft_history_undo","arguments":{}}}'
mcp '{"jsonrpc":"2.0","id":17,"method":"tools/call","params":{"name":"rillsoft_project_file_save","arguments":{}}}'
mcp '{"jsonrpc":"2.0","id":18,"method":"tools/call","params":{"name":"rillsoft_project_file_open","arguments":{"path":"C:/Projects/Demo.rpj","discardChanges":true}}}'Every mutating step can be followed live in the visible Rillsoft Project and
taken back there individually with Ctrl+Z; the file steps create no undo
step. After every mutating call the recalculated plan is available – dates,
float, critical path –, not just the changed record; the evaluations in steps
10 and 13 read exactly this state. The documentation closes the walkthrough
with a 19th read-only call (rillsoft_project_tree_get) that checks the saved
state. The role id in the example comes from the reference pool of the
documentation – in your pool the catalogue call returns it.
What follows here#
After the contract freeze against the released product build: the catalogue
generated from tools/list per tool with purpose, access class, parameters,
answer schema, licence and undo notes and a verified example; pages on
authentication, security, troubleshooting and changes per product version.
Until then: what tools/list of your installation returns is the contract.
- Product version
- Rillsoft Project 10
- Verification
- Details from the Rillsoft Project 10 product documentation (as of 2026-09-08); reconciliation with the released build is pending.