{
  "markdown": "# EZ@Work MCP Server\n\nConnect [EZ@Work](https://www.ezatwork.com) — all-in-one business management\nfor freelancers, lawyers, agencies, and service businesses — to Claude, Gemini,\nCursor, and any MCP-compatible AI.\n\n## Tools (v1)\n\n| Tool | Description | Type |\n|------|-------------|------|\n| `list_clients` | List your clients/customers | Read |\n| `list_projects` | List your projects/cases/work orders | Read |\n| `log_time_entry` | Log billable hours to a project | Write |\n| `create_invoice` | Create a draft invoice (auto currency/language/VAT) | Write |\n\n## Setup\n\n### Claude Desktop / Claude.ai (OAuth — recommended)\n\nSettings → Connectors → Add custom connector\n- URL: `https://mcp.ezatwork.com/mcp`\n- Authentication: OAuth (automatic)\n\n### Claude Code / Cursor / MCP Inspector (API token)\n\n1. Create a free EZ@Work account at https://app.ezatwork.com\n2. Generate an API token at https://app.ezatwork.com/settings/api-tokens\n3. Connect to `https://mcp.ezatwork.com/mcp` with header `Authorization: Bearer ezw_pat_...`\n\n**Local testing with MCP Inspector:**\n```bash\nnpx @modelcontextprotocol/inspector\n```\nConnect to `http://localhost:8080/mcp` with header `Authorization: Bearer ezw_pat_...`\n\n## Security\n\n- Your data stays in your EZ@Work account\n- OAuth mode: Google identity → EZ@Work account lookup; no credentials stored in the MCP\n- API token mode: scoped permissions — grant only what you need; mandatory expiration\n- Authorization is verified on every request\n\n## Privacy Policy\n\nhttps://www.ezatwork.com/privacy\n\n## Universal Design\n\nEZ@Work adapts to your business type: a lawyer sees \"cases,\" a freelancer sees\n\"projects,\" a service business sees \"work orders.\" Currency, language (24 supported),\nand tax rules auto-detect from your profile — no configuration needed in the MCP.\n\n---\n\n## Development\n\n### Run locally\n\n```bash\npython -m venv .venv\nsource .venv/bin/activate  # Windows: .venv\\Scripts\\activate\npip install -e .\n\ncp .env.example .env\n# Edit .env: EZ_API_BASE=http://localhost:5000 for local backend\n\npython -m ezatwork_mcp.server\n# Server starts at http://localhost:8080/mcp\n```\n\n### Run tests\n\n```bash\npip install pytest pytest-asyncio\npytest tests/\n```\n\n### Docker\n\n```bash\ndocker build -t ezatwork-mcp .\ndocker run -p 8080:8080 -e EZ_API_BASE=https://api.ezatwork.com ezatwork-mcp\n```\n\n### Deploy to Cloud Run\n\n```bash\ngcloud run deploy ezatwork-mcp \\\n  --source . \\\n  --region europe-west1 \\\n  --project ezatwork-production \\\n  --allow-unauthenticated \\\n  --port 8080 \\\n  --update-env-vars \"EZ_API_BASE=https://api.ezatwork.com,MCP_BASE_URL=https://mcp.ezatwork.com\" \\\n  --update-secrets \"GOOGLE_CLIENT_ID=ezmcp-google-client-id:latest\" \\\n  --update-secrets \"GOOGLE_CLIENT_SECRET=ezmcp-google-client-secret:latest\" \\\n  --update-secrets \"EZ_MCP_MASTER_TOKEN=ezmcp-master-token:latest\"\n```\n\n> `--allow-unauthenticated` is correct — auth is enforced at the MCP layer (OAuth or API token),\n> not at the Cloud Run IAM level.\n\n### Technical notes\n\n- **Transport:** Streamable HTTP (`/mcp` endpoint)\n- **Library:** `fastmcp 3.3.1`\n- **Auth (OAuth):** `GoogleProvider` from `fastmcp.server.auth.providers.google`\n- **Auth (token):** `get_http_headers()` from `fastmcp.server.dependencies`\n- **Dual-auth:** OAuth active when `GOOGLE_CLIENT_ID` + `GOOGLE_CLIENT_SECRET` + `MCP_BASE_URL` are set\n- **Backend:** `GET /api/users/me` for locale; `GET /api/internal/users/by-email` for OAuth→user mapping\n- **Time entries:** `POST /api/timeentry` with `isBillable` field\n- **Invoices:** `POST /api/invoices` with computed `dueDate` and `total` per item\n\n---\n\n## Built by\n\n[EZ@Work](https://www.ezatwork.com) — the business OS for independents.\n",
  "bytes": 3663,
  "sha": "40e8db8a3035358c8b8dc1b8fe1dbd197f12987368561e9698418d24396157f3",
  "repo_slug": "eranfinish/ezatwork-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_eranfinish_ezatwork_3d449379/readme"
}