# Ugga Intranet & Document Portal

> Ugga is a hierarchical intranet, wiki, and versioned document portal with built-in Model Context Protocol (MCP) and Browser WebMCP (`navigator.modelContext`) support for AI agents.

## Discovery & Machine-Readable Endpoints
- [LLM Capability Guide (this document)](https://halse.app/llms.txt)
- [MCP Server Manifest](https://halse.app/.well-known/mcp.json)
- [A2A Agent Card](https://halse.app/.well-known/agent.json)
- [MCP Streamable HTTP / JSON-RPC Endpoint](https://halse.app/api/mcp)
- [User Profile & Personal Access Token Management](https://halse.app/profile)

## How AI Agents Authenticate as the Current User

### 1. External LLM / CLI / MCP Clients (Antigravity, Claude Desktop, Cursor)
1. The user logs into Ugga in their browser and visits `/profile`.
2. Under **Personal Access Tokens (MCP & CLI)**, the user generates a token starting with `ugga_pat_...`.
3. Include the header `Authorization: Bearer ugga_pat_...` (or `X-Ugga-Token: ugga_pat_...`) on requests to `/api/mcp` or `/llms.txt`.
4. All operations execute strictly with that user's resolved subsite and page permissions (`owner`, `editor`, `reader`).

### 2. In-Browser AI Assistants (WebMCP / `navigator.modelContext`)
- When a user is logged into Ugga in a browser tab, Ugga automatically registers all tools on `navigator.modelContext` (and `window.uggaWebMCP`).
- Browser agents do not need a separate token; tool calls automatically use the active `secure_session` cookie and trigger live UI updates on the open page.
- Call `navigator.modelContext.listTools()` to inspect tools, or `await navigator.modelContext.callTool(name, args)` to execute a tool.

## Current Request Status
- **Unauthenticated**: Fetch `/llms.txt` with `Authorization: Bearer ugga_pat_...` or while logged in to see a live directory of your accessible subsites and pages.

## Available MCP & WebMCP Tools

### `get_current_user`
Get the currently authenticated Ugga user profile, role, and authentication method.

### `list_subsites`
List all Ugga subsites accessible to the current user along with their resolved access level (owner, editor, reader).

### `list_pages`
List all pages in a given subsite that the current user has permission to view.
**Parameters:**
- `site_id` (string, *optional*): Subsite ID (e.g., "root" for the main site). Defaults to "root".

### `get_page`
Get a page by subsite ID and slug, including its layout sections, blocks, rich markdown editor contents, and embedded document metadata.
**Parameters:**
- `site_id` (string, *optional*): Subsite ID (defaults to "root").
- `page_slug` (string, *required*): Page slug (e.g., "home").

### `create_page`
Create a new page in a subsite with optional initial markdown content. Requires editor or owner access on the subsite.
**Parameters:**
- `site_id` (string, *optional*): Subsite ID (defaults to "root").
- `title` (string, *required*): Display title for the new page.
- `slug` (string, *optional*): Optional URL slug (auto-generated from title if omitted).
- `initial_content` (string, *optional*): Optional initial Markdown content for the page.
- `block_type` (string, *optional*): Type of initial content block to create ("markdown-editor" for rich ToastUI markdown document or "text-block" for simple text). Defaults to "markdown-editor".

### `update_page_content`
Add, update, or remove content blocks (markdown-editor, text-block, document-viewer, image-block) on a page, replace its layout, or update page settings (title, background_color, background_image_id). Requires editor or owner access on the page.
**Parameters:**
- `site_id` (string, *optional*): Subsite ID (defaults to "root").
- `page_slug` (string, *required*): Target page slug (e.g., "home").
- `action` (string, *required*): "update_block" updates an existing block (or the first markdown/text block if component_id is omitted); "add_block" appends a new block; "remove_block" deletes a block by component_id; "set_layout" replaces the entire layout object; "update_page_settings" updates page title and/or background styling.
- `title` (string, *optional*): Optional new page title (can be passed with update_page_settings or any other action).
- `background_color` (string, *optional*): Optional page background color CSS value, e.g. "#0f172a" (pass "" to clear). Stored in pages.theme_config.backgroundColor.
- `background_image_id` (string, *optional*): Optional document ID of an uploaded image in the subsite to use as the full-bleed page background (pass "" to clear). Stored in pages.theme_config.backgroundImageId.
- `component_id` (string, *optional*): ID of the block component to update or remove (e.g., "comp-home-1"). For update_block, if omitted, the first markdown-editor or text-block on the page is updated.
- `block_type` (string, *optional*): Block type when adding a new block. Defaults to "markdown-editor".
- `content` (string, *optional*): Markdown or text content when adding or updating a markdown-editor or text-block.
- `config` (object, *optional*): Optional block config object (e.g., { documentId, title, showPreview: true, viewerId: "markdown-editor", hidePanelCard: true, style: { panelBgColor, borderColor, borderRadius, boxShadow } }).
- `section_index` (number, *optional*): 0-based section index when adding a block (defaults to 0).
- `column_index` (number, *optional*): 0-based column index when adding a block (defaults to 0).
- `layout` (object, *optional*): Full layout JSON object ({ sections: [...] }) when action is "set_layout".

### `list_documents`
List all uploaded documents and their version histories in a subsite.
**Parameters:**
- `site_id` (string, *optional*): Subsite ID (defaults to "root").

### `read_document`
Read the metadata and content of an uploaded document in a subsite by document_id or filename, optionally for a specific historical version.
**Parameters:**
- `site_id` (string, *optional*): Subsite ID (defaults to "root").
- `document_id` (string, *optional*): Document UUID (provide either document_id or filename).
- `filename` (string, *optional*): Document filename, e.g., "handbook.md" (provide either document_id or filename).
- `version` (number, *optional*): Optional version number to read (defaults to current_version).

### `save_document`
Create a new document or save a new version of an existing document in a subsite. If a document with the same filename exists, the previous version is archived to document_versions and current_version is incremented automatically. Optionally embeds the document onto a page.
**Parameters:**
- `site_id` (string, *optional*): Subsite ID (defaults to "root").
- `filename` (string, *required*): Filename including extension (e.g., "architecture.md", "report.txt").
- `content` (string, *required*): Document content (UTF-8 text by default, or base64 if encoding="base64").
- `encoding` (string, *optional*): Content encoding ("utf8" or "base64"). Defaults to "utf8".
- `mime_type` (string, *optional*): Optional MIME type (auto-detected from filename extension if omitted).
- `embed_on_page_slug` (string, *optional*): Optional page slug in the same subsite where a document-viewer block for this document should be embedded.

### `delete_document`
Delete a document and all of its archived versions from a subsite. Requires editor or owner access.
**Parameters:**
- `site_id` (string, *optional*): Subsite ID (defaults to "root").
- `document_id` (string, *optional*): Document UUID (provide either document_id or filename).
- `filename` (string, *optional*): Document filename (provide either document_id or filename).

## Quick Examples

### Save or Update a Versioned Document via HTTP POST
```bash
curl -X POST https://halse.app/api/mcp \
  -H "Authorization: Bearer ugga_pat_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"tool":"save_document","arguments":{"site_id":"root","filename":"notes.md","content":"# Meeting Notes\n\nUpdated via MCP.","embed_on_page_slug":"home"}}'
```
