Developer Docs

MCP Server

Install, authenticate, and use the willaOS MCP server.

The willaOS MCP server is available at:

https://os.willacreative.dev/api/mcp

It uses the Streamable HTTP transport and the same bearer API keys as REST.

Install

Add willaOS to an MCP client with an HTTP server entry:

{
  "mcpServers": {
    "willaos": {
      "url": "https://os.willacreative.dev/api/mcp",
      "headers": {
        "Authorization": "Bearer ${WILLA_API_KEY}"
      }
    }
  }
}

For local development:

{
  "mcpServers": {
    "willaos-local": {
      "url": "http://localhost:3000/api/mcp",
      "headers": {
        "Authorization": "Bearer ${WILLA_API_KEY}"
      }
    }
  }
}

Auth And RBAC

MCP tools call the same shared domain helpers and permission checks as REST.

The catalogue is filtered per key. A key only sees tools whose route it can reach, so the tool list differs between an admin key and a scoped one. A tool that is present can still return Forbidden when the key holds the route but not that specific client, project, or field.

  • Route not granted at all → the tool is absent from tools/list.
  • Route granted, resource or field denied → the tool is listed and returns Forbidden.

Route gates live in lib/mcp-tool-routes.ts. Every tool needs an entry there; a test fails if one is missing. Filtering is a token optimization — the enforcement is still the per-call permission check inside each tool.

Use:

  • Read-scoped keys for status, dashboard, and research agents.
  • Write-scoped keys only for agents that have an explicit approval or human review workflow.
  • Project/client-scoped user keys when an external collaborator should only see a subset of data.

Start With The Overview

get_project_overview is the entry point for any question about a project's current state. It is a single database-only call — no Asana, Figma, Harvest, or Google — returning the header and signals allowed by the calling key's fields_read grants, plus a drill_down list naming the tool for each domain and whether the key can reach it. An omitted signal is not authorized. A null signal means its database source was unavailable.

Drill down from there rather than calling the per-domain get_project_* tools speculatively. The expensive cross-system views (get_project_readiness_rollup, get_project_economics) are deliberately not inlined into the overview.

Tool Catalogue

The generated tool catalogue is in MCP Tool Catalog. It is generated from app/api/mcp/route.ts and should be refreshed whenever new tools land.

Pagination

list_clients and list_projects accept limit (default 100, max 500) and cursor, and return { items, next_cursor, total }. The cursor is the ID of the last row from the previous page; an unrecognized cursor restarts from the first page.

Response Shape

Tools return MCP content blocks. willaOS serializes structured payloads as compact JSON text:

{
  "content": [
    {
      "type": "text",
      "text": "{\"data\":[]}"
    }
  ]
}

Tool-level failures return a text error block. Auth failures use Forbidden; unexpected server errors return a generic tool failure message and log server-side details.

Mutation tools return Archived records are read-only when their client or project has been archived. Do not retry that error. Read tools can still return an archived client or project to an authorized internal key, but public links and child writes stop at archive.