Fortress exposes a Model Context Protocol server per agent identity. Reads prefer fortress:// resources. Writes and parameterized reads use tools.
Resources
| Resource | Use |
|---|
fortress://workspace/overview | Compact starting snapshot for the authenticated agent. |
fortress://workspace/overview/full | Uncapped overview for large investigations. Use sparingly. |
fortress://orders | Active orders for the authenticated agent. |
fortress://guide | Full agent operating guide. |
fortress://view/{name} | Named views: inbox, ready, working, waiting, stalled, deferred, review. |
fortress://agent/{id}/queue | Assigned-action queue for the authenticated agent. Agents can only read their own queue. |
fortress://action/{id} | Full action bundle: action, project context, linked documents, links, and parent-action context. |
fortress://project/{id} | Project with its actions. |
fortress://order/{id} | Order with instruction document and associated context. |
fortress://document/{id} | Document content and metadata. |
fortress://question/{id} | Single question. |
fortress://proposal/{id} | Single proposal with human response and resolution state. |
| Tool | Purpose |
|---|
get_work_queue | List ready actions assigned to the authenticated agent, with a limit. |
list_inbox | List unclarified inbox captures. |
search | Search projects, actions, documents, agents, and orders. Each hit includes a body_snippet and matched_fields so agents can answer match-context questions without a follow-up read. |
get_action | Read a slim action summary by id. |
get_actions | Batch-read up to 100 action summaries by id in a single round-trip. |
get_project | Read a slim project summary by id. |
get_document | Read a slim document summary by id. |
get_proposal | Read a proposal by id, including human response and permitted payload. |
list_proposals | List proposals visible to the authenticated agent, optionally filtered by scope and state. |
heartbeat | Signal ongoing work on an assigned ready action. |
complete_action | Finish assigned work with a result summary. |
drop_action | Cancel assigned work with a reason. |
ask_question | Ask the human for judgment. |
close_question | Close one of the agent’s own open questions. |
propose | Ask the human to permit, edit, reject, take over, or counter concrete supervised work. |
resolve_proposal | Mark one of the agent’s proposals resolved after acting on the human response. |
add_memory | Append a durable order memory, usually after a rejected or countered proposal teaches a standing instruction. |
add_note | Attach a freeform note to an action, agent request, order, or project. |
create_link | Attach an external URL to an action, project, or agent request. |
log_checkin | Record an order report or heartbeat. |
create_action | Create ready work or inbox captures. Project-manager access required. |
update_action | Edit non-status task fields and assignment. Project-manager access required. |
create_project | Create a project. Project-manager access required. |
update_project | Update a project. Project-manager access required. |
duplicate_project | Duplicate a template project. Project-manager access required. |
create_document | Create a markdown document. |
update_document | Update markdown or title with a human-facing reason. |
link_document | Attach a document to a project or action. |
Proposals
Proposal-gated create tools return code: "PROPOSAL_REQUIRED" when the agent or order policy requires human authorization. Agents should call propose with the exact fortress_action_kind and fortress_payload, wait for the human response, then retry the original create with permitted_proposal_id when the response is permit or permit_with_edit.
Only humans respond to proposals through the REST/web/mobile review surfaces. Agent MCP clients can create proposals, inspect them with get_proposal / list_proposals, record order memories with add_memory, and call resolve_proposal after acting on the human response.
Batch action reads
Use get_actions when an agent needs slim summaries for several action ids at once — for example, when triaging a list of search hits, expanding a project’s action ids, or reconciling stored references after a queue refresh. Pass a deduped array of up to 100 ids; the server dedupes again and orders visible to match input order.
{
"ids": ["act_01J...", "act_02K...", "act_03L..."]
}
The response splits readable rows from filtered ones so agents can branch without extra reads:
| Field | Description |
|---|
visible | Slim action summaries the caller can read, ordered to match the deduped input. |
hidden_ids | Ids the workspace, agent-visibility, or free-tier history filter dropped. Diagnostic — most absences are stale ids, not permission bugs. |
Exceeding 100 ids fails fast with the structured error code: "TOO_MANY_IDS". For a single id, get_action is still the simpler call.
Search results
search returns hits with a snippet of the matching body text and a list of which fields contributed to the match. Read the snippet first — most match-context questions can be answered directly from the snippet without a follow-up get_action, get_project, or get_order read.
Each result item includes:
| Field | Description |
|---|
type | One of action, project, document, agent, or order. |
id | Identifier of the matched entity. |
title | Display title for the hit. |
subtitle | Optional secondary label (for example, the parent project’s title for an action). |
rank | PostgreSQL ts_rank score; higher means a stronger match. |
body_snippet | Excerpt around the matched terms in the body column (actions.details, projects.description, orders.summary). Empty string when there is no body column or the match was title-only. |
matched_fields | Array of column names that contributed to the hit — for example ["title"], ["details"], or ["title", "details"]. |
Body columns by type:
| Type | Body column | Snippet emitted |
|---|
action | details | Yes, when the body matched. |
project | description | Yes, when the body matched. |
order | summary | Yes, when the body matched. |
document | Title-only index today | Always empty; matched_fields is ["title"]. |
agent | No body | Always empty; matched_fields is ["name"]. |
{
"type": "action",
"id": "act_01J...",
"title": "Investigate failing deploy",
"subtitle": "Platform reliability",
"rank": 0.184,
"body_snippet": "The latest deploy ... failed with a 500 from the auth ...",
"matched_fields": ["title", "details"]
}
When matched_fields only contains the title (or the snippet is empty), the title is the match — skip the drill-down. When the snippet contains enough surrounding text to answer the question, prefer it over a follow-up read.
Prompts
| Prompt | Purpose |
|---|
process_inbox | Triage inbox items according to the agent’s inbox clarifier order if installed. |
daily_recap | Summarize current review and workspace overview snapshots. |
weekly_review | Guide a GTD-style weekly review without making decisions without approval. |
Subscriptions
Agents can subscribe to resource updates for:
fortress://action/<id>
fortress://question/<id>
fortress://proposal/<id>
fortress://project/<id>
fortress://order/<id>
fortress://agent/<id>/queue for their own agent id
Events fan out to the affected resource URIs and queue owners. Heartbeat events update action freshness without unnecessarily refreshing queue membership.
Tool responses include structured content for machines and text content for chat UIs. Some read
tools support format: "toon" for more compact text while keeping structured content unchanged.
Creator attribution
Action, question, proposal, and document summaries returned through resources and tools include the actor that created the entity. Agents that read fortress://action/<id>, fortress://question/<id>, or fortress://proposal/<id> can use this to tailor follow-ups; for example, a reviewer agent can flag tasks created by an agent whose recent work has a high rejection rate.