tino.mcp¶
MCP (Model Context Protocol) server exposing TINO as tools for AI agents.
The server is mounted into the main FastAPI app as a Streamable HTTP ASGI
sub-application at /mcp. It reuses TINO’s existing services and enforces the
same per-bucket role model as the REST API.
Authentication follows the MCP OAuth 2.0 specification: TINO acts as a Resource
Server and delegates authentication to the configured OIDC provider (it still
enforces its own per-bucket authorization). MCP clients
identify themselves to that provider with a Client ID Metadata Document
(CIMD) — their client_id is an HTTPS URL the provider dereferences, so there is
no Dynamic Client Registration — obtain an access token, and present it to TINO as a
Bearer token. TINO validates the token against the provider’s JWKS and runs each
tool as that user, with their real group memberships driving bucket access.
- tino.mcp.server.MCP_MAX_RESULTS = 50¶
Maximum number of file results the
searchtool returns across all buckets.
- tino.mcp.server.MCP_MIN_QUERY_LEN = 2¶
Search queries shorter than this are ignored (the tool returns an empty list).
- class tino.mcp.server.OIDCTokenVerifier(discovery_url: str, groups_claim: str)¶
Validate provider-issued JWT access tokens against the OIDC JWKS.
On success the token’s claims are turned into a
User(username + groups) and bound to the request context for the tools to use.
- async tino.mcp.server.commit(bucket: str, message: str, files: list[str] | None = None) dict¶
Commit changes in a bucket. Requires the committer role.
If files is omitted, all changed files in the working tree are committed.
- tino.mcp.server.compile_typst(bucket: str, path: str) dict¶
Compile a Typst file to verify it is valid.
Returns
{"success": true, "pages": N}when compilation succeeds, or{"success": false, "error": "..."}with the compiler error otherwise. Use this after editing to check your work before committing.
- async tino.mcp.server.create_dir(bucket: str, path: str) dict¶
Create an empty directory in a bucket. Requires the editor role.
Fails if the directory already exists or the path is invalid. Note that git does not track empty directories, so a created directory only persists once it contains a committed file.
- async tino.mcp.server.delete_dir(bucket: str, path: str) dict¶
Delete a directory and all its contents. Requires the editor role.
- async tino.mcp.server.delete_file(bucket: str, path: str) dict¶
Delete a file from a bucket. Requires the editor role.
- tino.mcp.server.git_log(bucket: str, path: str | None = None, max_count: int = 20) list[dict]¶
Return commit history for a bucket, optionally filtered to a single file.
- tino.mcp.server.git_status(bucket: str) list[dict]¶
Return the working-tree status (modified, untracked, deleted) of a bucket.
- tino.mcp.server.list_buckets() list[dict]¶
List all buckets the current user can access, with their role on each.
Buckets may include an
instructionsfield with specific guidance for working with that bucket’s content. Always read and follow these instructions before making changes.
- async tino.mcp.server.rename_dir(bucket: str, old_path: str, new_path: str) dict¶
Rename or move a directory and all its contents. Requires the editor role.
- async tino.mcp.server.rename_file(bucket: str, old_path: str, new_path: str) dict¶
Rename or move a file within a bucket. Requires the editor role.
Fails if the source is missing, the destination already exists, or the path is invalid.
- tino.mcp.server.search(query: str, bucket: str | None = None) list[dict]¶
Search file names and contents across the buckets you can access.
Pass bucket to limit the search to a single bucket, or omit it to search every accessible bucket. Each result is a file with
name_matchand any matching contentsnippets(line number + text). Prefer this over listing every bucket and reading files one by one when locating a document.
- async tino.mcp.server.write_file(bucket: str, path: str, content: str) dict¶
Create or overwrite a text file in a bucket. Requires the editor role.
Server-level MCP instructions, shared by the MCP server and the REST API.
Kept free of the MCP SDK so the bucket settings dialog can fetch the full
instruction text (built-in plus the TINO_MCP_INSTRUCTIONS override) without
pulling in the MCP server machinery.
- tino.mcp.instructions.BASE_INSTRUCTIONS = 'TINO is a collaborative Typst document platform.\nDocuments live in *buckets* (git repositories).\nUse these tools to list, read, write, compile, and commit Typst source files.\nAlways compile after editing to verify the document is valid.\nEach bucket may have specific instructions.\nAlways list buckets first and follow any per-bucket guidance.\nTo locate a document by file name or content, use the ``search`` tool instead of\nlisting and reading every file.\n'¶
Built-in instructions describing TINO and how an agent should use the tools.
- tino.mcp.instructions.server_instructions() str¶
Return the full server-level instructions an MCP agent receives.
This is
BASE_INSTRUCTIONSplus the optionalTINO_MCP_INSTRUCTIONSglobal override. Per-bucket instructions are appended separately (see thelist_bucketstool).