Can an AI agent use Plane (plane.so)?
As of 15 Oct 2026, an AI agent gets into Plane on its own and does 90% of the core work.
- Find: Docs for agents: llms.txt, an OpenAPI and an MCP server; a docs page for each core task.
- Access: MCP sign-in, sign-up in a browser.
- Use: 90% of the work.
- Pay: Payment not tried.
- Leave: Cancels on its own: Deletes its data, but the login stays.
Ways in: MCP sign-in, 0 of 10 core tasks · Sign-up in a browser, 9 of 10 core tasks
To reach L5 · Autonomous: pay without a person.
What the levels meanDriven 15 Oct 2026Same level in 3 drives in a rowRules of 15 Oct 2026Claim this page
Written and checked by our agents from this drive's record. How we write.
Who gets in
- Agents on a serverGet in on their own.
- Signed agentsThe sign-up page opens.
- Agents in a person's browserNot measured yet.
Sign-up page checked 15 Oct 2026. Signed agents: the ones Cloudflare verifies. Where agents come from
What an agent can do in Plane (plane.so).
On its own
- Create, update, close and delete tasks, projects, sprints, modules, wiki pages, epics and cross-project initiatives, all checked by reading the result back
- Comment on tasks, link them together, log time, attach files, search, and set up labels, states and estimates
- Connect through the official programmatic assistant (MCP) to do the same things
What it can't, and why
- Sign up or get an API key without a browserSign-up needs an emailed code and keys are made only in the web interface
- Assign an AI agent to a taskThe page the product's own docs point to does not exist yet
- Pay for a plan on its ownCard entry is on a payment page the agent's own rules keep it off
1 more
- Delete the accountOnly deactivation exists, and signing back in with a code reactivates it
Can an AI agent sign up for Plane on its own?
Yes, in a browser, without a human. app.plane.so/sign-up: email, then a 6-digit code; no CAPTCHA; no sign-up API.
Every way in it offers, as our agent tried them
| Way in | What happened |
|---|---|
| Email and code | Got in, 9 min |
| Email and password | Not tried: the same as another way |
| Continue with GitHub | Not tried: no account yet |
| Continue with Google | Not tried: no account yet |
| Sign‑in for apps (OAuth, MCP) | Got in, 4 min |
| Company single sign‑on | Not tried: needs a person's account |
| A key from a person | Not tried: needs a person's account |
Does Plane (plane.so) have an MCP server, and can an agent connect to it?
Yes. Plane has an official MCP server. The server lists 30 tools, signs an agent in with OAuth and speaks the 25 Nov 2025 MCP spec.
A new agent can get in on its own: in the drive of 15 Oct 2026, our agent signed up, verified and got its key without a person. Through the MCP server, 11 of our agent's 12 attempts worked.
What the drive found
APIOpenAPIMCP · official–CLIllms.txtWebhooks–SandboxHow does an AI agent get a Plane (plane.so) API key?
In the drive of 15 Oct 2026, our agent got its Plane API key in a browser, without a person. Personal access token made in Profile > Personal Access Tokens (expiry required in the UI though the docs call it optional); no API or CLI to mint or revoke keys. MCP OAuth (DCR + one consent click) also works.
Can an AI agent delete its Plane account?
Not all of it: it deletes its data, but the login stays. Workspace deleted in the UI (data gone, PAT deleted, OAuth token refused); a temp workspace made only to reach the deactivate button may remain.
Can an AI agent pay for Plane?
Not tried yet.
Chose a plan; the checkout didn't open: Business, $15 a month.
Checkout: Stripe CheckoutNo CAPTCHA at checkoutWays to pay found: Stripe customer portal (billing.stripe.com).
It has a free plan.
What would let agents pay on their own
- Accept x402 or MPP on your API. Answer an unpaid call with 402 and a payment challenge, so an agent pays per call or buys credits without an account or a card.Step-by-step guide
- List your plans on Stripe Projects. Agents buy a plan with `stripe projects add`, paid with a token under a spend cap the owner sets (projects.dev).Step-by-step guide
No 402/x402/MPP, no billing API or MCP billing tool. A Business trial starts automatically with no card. Billing page 'Start subscription' shows $15.00/seat/month and 'Start subscription and pay' (not clicked); the card goes on Stripe's hosted portal (billing.stripe.com), which robots.txt closes to all user agents, so our agent stopped there. Pro ($8) is only offered as a trial switch.
Ways to pay checked 15 Oct 2026.
For the team behind Plane.
Where agents stop in Plane (plane.so) today, and the fixes that get them further, highest impact first.
The fixes, highest impact first
- Add an API to mint and revoke scoped tokensStep-by-step guide
- Offer a real account delete
- Serve MCP (the 28 Jul 2026 spec) and CIMDStep-by-step guide
3 more fixes
- Fix the AI agents docs or page
- Accept an agent payment rail Step-by-step guide
- Return 404 and 401 consistently in API v1
- Claim it free and reply next to the result.
- A Drive, $49: your private report, with where agents stop, the evidence and the fixes that move your level.
- Fixed something? Order a Drive ($49) any time, or the Monthly drive ($29/month).
Details
Your API, MCP server or CLI is the product? An Audit ($299) also checks every documented route, MCP tool and CLI command against your docs. Compare plans.
Already claimed it? Open it in your dashboard.
Rather not be driven? Block AgentDrivesAgent in robots.txt or write to us. We stop driving it ourselves; this page stays, with its date.
Embed the badge on your site
Behind the level.
The part scores and the measures behind them.
Part scores and the measures · the docs · level history · paid plans
Part scores
- Holds up: 74 of 100, fair
Agent-ready setup
- llms.txt: found
- OpenAPI: found
- MCP server: found
- CLI: not found
Not measured in this drive: Docs match (part of an Audit).
The measures
- Work done90
- Reliability78
- Crash test69
The docs
600 of 1,301 pages read. Complete.
- A getting-started page
- An auth page
- Errors listed with their codes
- Code examples on most pages
- Newest page updated 16 Oct 2026
- A page for 10 of 10 core tasks
Read on 15 Oct 2026.
Tried as documented
18 of 20 documented ways to do the core work worked when tried.
| What happened | Ways |
|---|---|
| Worked when tried | 18 |
| Documented, didn't work | 1 |
| Not tried (a paid plan, or no way to reach it) | 1 |
| Worked, but not in the docs | 0 |
Level history
- 1 Oct 2026L4Runs on its own
- 2 Oct 2026L4Runs on its own
- 15 Oct 2026L4Runs on its own
Needs a paid plan
Not counted in the level. Our drive used no-card trial (Business, 14 days, started automatically).
| Capability | Plan |
|---|---|
| Define a workflow with approval gates (custom workflows) | Enterprise |
| Audit logs via API | Enterprise |
How Plane handles an agent's mistakes · 9 probes · core run 3×
Malformed requests, a retry, a wrong key and a short burst of reads on our agent's own account, and how Plane answered.
- Clear errors70
- Recovery88
- Safe retries50
- Silentrepeat create with the same Idempotency-Key headerCreate a work item201 content-type: application/json {"first": 201, "same_id": false}
- Vaguewell-formed id that does not existCreate a work item403 content-type: application/json {"detail": "You don't have permission to view this workitem"}
- Vaguewrong API keyCreate a work item403 content-type: application/json {"detail": "Given API token is not valid"}
- Clearmissing required nameCreate a work item400 content-type: application/json {"name": ["This field is required."]}
- Clearbad enum priorityCreate a work item400 content-type: application/json {"priority": ["\"super-high\" is not a valid choice."]}
- Clearrepeat create with same external_id/external_sourceCreate a work item409 content-type: application/json {"first": 201, "second": {"error": "Issue with the same external id and external source already exists", "id": "e978f5cb-8dbc-4ccb-9497-5f0eeb64491b"}}
- Clearburst of up to 20 GET /users/me/Create a work item200 {"statuses": [200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200], "headers": ["x-ratelimit-remaining: 32", "x-ratelimit-reset: 1792049295"]}
- Clearinterrupt attachment upload after step 1 (no S3 upload, no confirm)Create a work item200 content-type: application/json {"pending_listed": false, "count": 1}
- Clearwrong API key on v2Create a work item401 content-type: application/problem+json {"type": "unauthorized", "code": "unauthorized", "detail": "Authentication credentials were not valid."}
For agents and builders.
The drive as data, every checkpoint and all 210 attempts.
How an agent connects · 6 tips
/api/tools/plane.json/tools/plane.mdMCP get_tool {"slug":"plane"}
- Use the REST API with X-API-Key (v2 for bulk ops and problem+json errors) or the MCP PAT endpoint https://mcp.plane.so/http/api-key/mcp with x-workspace-slug
- New projects made by API have cycles/modules/epics off: PATCH /projects/{id}/features/ first
- Make creates idempotent with external_id + external_source (409 on repeat); Idempotency-Key is ignored
- Estimate points must be POSTed as a raw JSON array to /estimate-points/, not in the estimate body
- Deleted objects can answer 403 instead of 404 in v1: confirm with the list endpoint
- MCP needs protocol 2025-11-25 (initialize), not 2026-07-28
Every checkpoint, in detail · 9 checkpoints
- DocsHeadlessllms.txt with Link headers, OpenAPI 3.1.0 (40 paths) plus a larger v1/v2 reference (982 pages in developers llms.txt), markdown by Accept and .md.
- Sign upIn a browserapp.plane.so/sign-up: email, then a 6-digit code; no CAPTCHA; no sign-up API.
- VerifyIn a browserThe emailed code verifies the address; it arrived within a minute and is valid 10 minutes.
- KeyIn a browserPersonal access token made in Profile > Personal Access Tokens (expiry required in the UI though the docs call it optional); no API or CLI to mint or revoke keys. MCP OAuth (DCR + one consent click) also works.
- First callHeadlessGET /api/v1/users/me/ and /workspaces/{slug}/projects/ with X-API-Key: 200.
- First actionHeadlessPOST /api/v1/workspaces/{slug}/projects/ 201, read back 200.
- PayIn a browserNo 402/x402/MPP, no billing API or MCP billing tool. A Business trial starts automatically with no card. Billing page 'Start subscription' shows $15.00/seat/month and 'Start subscription and pay' (not clicked); the card goes on Stripe's hosted portal (billing.stripe.com), which robots.txt closes to all user agents, so our agent stopped there. Pro ($8) is only offered as a trial switch.
- CancelIn a browserThe auto trial needed no card and downgrades to Free by itself; deleting the workspace required 'Cancel your trial first', done in the web UI; billing then showed Free Active, 'Free trial used'. No billing API.
- DeleteBlockedWorkspace deleted in the UI (data gone, PAT deleted, OAuth token refused); a temp workspace made only to reach the deactivate button may remain.
The attempt log · 210 attempts
| Capability | Route | Result | Evidence |
|---|---|---|---|
| Docs: Read llms.txt, docs_pass verdict | api | done ✓ | https://plane.so/llms.txt 200 text/plain, Link rel=describedby/service-desc; docs_pass verdict complete (600 pages) |
| robots: robots.txt + Content-Signal | api | done ✓ | plane.so robots: User-agent * Disallow /admin/*; AI agents group Allow /; "Content-Signal: search=yes, ai-train=yes, ai-input=yes" (Cloudflare Content Signals scheme, parses). api.plane.so robots: User-agent: * Disallow: / (crawler rule). No Content-Usage (aipref). |
| A2A card: /.well-known/agent-card.json | api | done ✓ | 200 application/json, protocolVersion "0.3.0" (behind A2A 1.0); legacy /.well-known/agent.json 404 |
| AI catalog / MCP server card: /.well-known/ai-catalog.json, <mcp>/server-card, /.well-known/mcp/server-card.json | api | failed ✓ | all 404; non-standard /.well-known/mcp.json (200 JSON, 28 tools, endpoints) and /.well-known/ai-agent.json present |
| Markdown: Accept: text/markdown and .md on docs | api | done ✓ | docs.plane.so and developers.plane.so return content-type text/markdown with vary: Accept; .md URLs 200 text/markdown |
| OpenAPI: plane.so/openapi.json | api | done ✓ | openapi 3.1.0, 40 paths, server https://api.plane.so/api/v1 |
| MCP discover: POST server/discover 2026-07-28 to https://mcp.plane.so/http/mcp | api | done ✓ | 401 invalid_token, WWW-Authenticate Bearer resource_metadata=https://mcp.plane.so/.well-known/oauth-protected-resource/http/mcp; PRM 200; AS metadata: registration_endpoint (DCR), no client_id_metadata_document_supported, S256, no device endpoint. Retry with credentials later. |
| auth.md / ucp: /auth.md, /.well-known/ucp | api | failed ✓ | /auth.md 404 (markdown 404 body), /.well-known/ucp 404 |
| Sign up: app.plane.so/sign-up email → unique code | browser | done ✓ | Email field + Continue; no CAPTCHA signals; code mail from team@mailer.plane.so within ~1 min; code accepted → /onboarding/ |
| Verify email: 6-digit login code from inbox | browser | done ✓ | Subject "Your unique Plane login code is ••••", valid 10 minutes; entering it verified the email and opened onboarding |
| Onboarding: Profile + workspace create in onboarding | browser | done ✓ | Workspace agentdrives-test-ebe971 created; dashboard shows "Business trial ends in 13d" (trial started automatically, no card asked); a default project "AgentDrives Test" was created |
| API key: Create Personal Access Token in Profile settings > Personal Access Tokens | browser | done ✓ | expiry required (1 week chosen); allowed_rate_limit 60/min |
| First API call: GET /api/v1/users/me/ and /workspaces/{slug}/projects/ with X-API-Key | api | done ✓ | 200 JSON; user id, email; projects list total_count 1 (cursor pagination) |
| API key: Use PAT | api | done ✓ | GET /api/v1/users/me/ 200; headers x-ratelimit-remaining/x-ratelimit-reset (legacy X- form) |
| Create a project: POST project | api | done ✓ | 201 {"id": "[id]", "identifier": "AD994", "name": "AD drive project AD994"} |
| Create a project: GET project | api | done ✓ | 200 {"name": "AD drive project AD994"} |
| Create a project: PATCH description, GET back | api | done ✓ | 200 {"desc": "updated by AgentDrives"} |
| Create a work item: POST work-items | api | done ✓ | 201 {"id": "[id]", "sequence_id": 1, "name": "AD test work item", "priority": "medium"} |
| Create a work item: GET work item | api | done ✓ | 200 {"name": "AD test work item"} |
| Update or close a work item: PATCH name/priority/state=Done, GET back | api | done ✓ | 200 {"state": "[id]", "priority": "high", "completed_at": "2026-10-15T07:07:14.939323Z"} |
| Update or close a work item: GET after close | api | done ✓ | 200 {"completed_at": "2026-10-15T07:07:14.939323Z"} |
| Create a work item: GET by readable identifier PROJ-N | api | done ✓ | 200 {"id": "[id]"} |
| Delete a work item: DELETE then GET | api | done ✓ | 204 {"get_after": 404, "body": {"error": "The requested resource does not exist."}} |
| Create a work item: DELETE then GET 404 | api | done ✓ | 204 {"get_after": 404} |
| Plan a cycle (sprint) with start/end dates: POST cycles with dates | api | failed | 400 {"non_field_errors": ["Cycles are not enabled for this project"]} |
| Break work into a module and assign items: POST modules | api | failed | 400 {"non_field_errors": ["Modules are not enabled for this project"]} |
| Plan a cycle: Enable cycles/modules/epics/intake on project via PATCH /projects/{id}/features/ | api | done ✓ | 200 {"epics": true, "modules": true, "cycles": true, "views": true, "pages": true, "intakes": true, "work_item_types": true, "workflows": false, "parallel_cycles": false, "manually_start_end_cycles": false, "project_updates": false, "milestones": true} |
| Plan a cycle (sprint) with start/end dates: POST cycles with dates | api | done ✓ | 201 {"id": "[id]", "name": "AD Sprint 11e5", "start_date": "2026-10-19T00:00:01Z", "end_date": "2026-11-01T23:59:00Z"} |
| Plan a cycle: GET cycle | api | done ✓ | 200 {"start": "2026-10-19T00:00:01Z", "end": "2026-11-01T23:59:00Z"} |
| Plan a cycle: PATCH end_date, GET back | api | done ✓ | 200 {"end": "2026-11-02T00:00:00Z"} |
| Plan a cycle: add work item to cycle, list cycle-issues | api | done ✓ | 200 {"add": "[{'id': '[id]', 'deleted_by': None, 'sub_issues_count': 0, 'created_at': '2026-10-15T07:", "listed": true} |
| Plan a cycle: DELETE cycle, GET | api | done ✓ | 204 {"get_after": 404} |
| Break work into a module and assign items: POST modules | api | done ✓ | 201 {"id": "[id]", "name": "AD Module d470", "status": "planned"} |
| Module: GET module | api | done ✓ | 200 {"name": "AD Module d470"} |
| Module: PATCH status in-progress | api | done ✓ | 200 {"status": "in-progress"} |
| Module: assign 2 items, list module-issues | api | done ✓ | 200 {"add": "[{'id': '[id]', 'deleted_by': None, 'sub_issues_count': 0, 'created_", "listed": [true, true]} |
| Module: DELETE module, GET | api | done ✓ | 204 {"get_after": 404} |
| Create and edit a wiki page: POST project page | api | done ✓ | 201 {"id": "[id]", "name": "AD spec page"} |
| Page: GET page | api | done ✓ | 200 {"name": "AD spec page", "html": "<p>Initial spec by AgentDrives</p>"} |
| Page: PUT title+content, GET back | api | done ✓ | 200 {"name": "AD spec page v2", "html": "<p class=\"editor-paragraph-block\" data-spacing-group=\"body\">Edited spec by Agent"} |
| Page: list project pages shows it | api | done ✓ | 200 {"listed": true} |
| Page: archive then DELETE, GET | api | done ✓ | 204 {"archive": 204, "delete": 204, "get_after": 404, "b": ""} |
| Create an epic and link child work items: POST epics | api | done ✓ | 201 {"id": "[id]", "name": "AD Epic"} |
| Epic: GET epic | api | done ✓ | 200 {"name": "AD Epic"} |
| Epic: PATCH name | api | done ✓ | 200 {"name": "AD Epic v2"} |
| Epic: link child item, list epic issues | api | done ✓ | 200 {"add": "[{'id': '[id]', 'deleted_by': None, 'type_id': '[id]', 'parent': '30300ca2-f1de-472a-8", "listed": true} |
| Epic: DELETE epic, GET | api | done ✓ | 204 {"get_after": 404} |
| Create an initiative to roll up multiple projects: POST v2 initiatives | api | done ✓ | 201 {"id": "[id]", "name": "AD Initiative 6ead"} |
| Initiative: GET initiative | api | done ✓ | 200 {"name": "AD Initiative 6ead"} |
| Initiative: PATCH initiative | api | done ✓ | 200 {"resp": "{'id': '[id]', 'name': 'AD Initiative 6ead', 'description': None, 'description_html': '<p>roll-up</p>', 'lead_id': Non", "state": "ACTIVE"} |
| Initiative: add 2 projects, list initiative projects | api | done ✓ | 200 {"add": "{'added': ['[id]', '[id]'], 'removed': []}", "list": "{'data': [{'id': '[id]', 'name': 'AD drive project AD994', 'description': 'updated by Agent |
| Initiative: DELETE, GET | api | done ✓ | 204 {"get_after": 404} |
| Create a project: POST project | api | done ✓ | 201 {"id": "[id]", "identifier": "ADF22", "name": "AD drive project ADF22"} |
| Create a project: GET project | api | done ✓ | 200 {"name": "AD drive project ADF22"} |
| Create a project: PATCH description, GET back | api | done ✓ | 200 {"desc": "updated by AgentDrives"} |
| Create a project: enable cycles/modules/epics on the project (features PATCH) | api | done ✓ | 200 {"cycles": true, "modules": true} |
| Create a work item: POST work-items | api | done ✓ | 201 {"id": "[id]", "sequence_id": 1, "name": "AD test work item", "priority": "medium"} |
| Create a work item: GET work item | api | done ✓ | 200 {"name": "AD test work item"} |
| Update or close a work item: PATCH name/priority/state=Done, GET back | api | done ✓ | 200 {"state": "[id]", "priority": "high", "completed_at": "2026-10-15T07:09:38.577404Z"} |
| Update or close a work item: GET after close | api | done ✓ | 200 {"completed_at": "2026-10-15T07:09:38.577404Z"} |
| Create a work item: GET by readable identifier PROJ-N | api | done ✓ | 200 {"id": "[id]"} |
| Delete a work item: DELETE then GET | api | done ✓ | 204 {"get_after": 404, "body": {"error": "The requested resource does not exist."}} |
| Create a work item: DELETE then GET 404 | api | done ✓ | 204 {"get_after": 404} |
| Plan a cycle (sprint) with start/end dates: POST cycles with dates | api | done ✓ | 201 {"id": "[id]", "name": "AD Sprint 6f26", "start_date": "2026-10-19T00:00:01Z", "end_date": "2026-11-01T23:59:00Z"} |
| Plan a cycle: GET cycle | api | done ✓ | 200 {"start": "2026-10-19T00:00:01Z", "end": "2026-11-01T23:59:00Z"} |
| Plan a cycle: PATCH end_date, GET back | api | done ✓ | 200 {"end": "2026-11-02T00:00:00Z"} |
| Plan a cycle: add work item to cycle, list cycle-issues | api | done ✓ | 200 {"add": "[{'id': '[id]', 'deleted_by': None, 'sub_issues_count': 0, 'created_at': '2026-10-15T07:", "listed": true} |
| Plan a cycle: DELETE cycle, GET | api | failed | 204 {"get_after": 403} |
| Break work into a module and assign items: POST modules | api | done ✓ | 201 {"id": "[id]", "name": "AD Module e7fe", "status": "planned"} |
| Module: GET module | api | done ✓ | 200 {"name": "AD Module e7fe"} |
| Module: PATCH status in-progress | api | done ✓ | 200 {"status": "in-progress"} |
| Module: assign 2 items, list module-issues | api | done ✓ | 200 {"add": "[{'id': '[id]', 'deleted_by': None, 'sub_issues_count': 0, 'created_", "listed": [true, true]} |
| Module: DELETE module, GET | api | done ✓ | 204 {"get_after": 404} |
| Plan a cycle: re-verify the same DELETE via list | api | done ✓ | GET cycles list no longer contains the deleted cycle; GET by id answered 403 "You don't have permission to view this cycle" (trial 1 answered 404 for the same situation) |
| Create and edit a wiki page: POST project page | api | done ✓ | 201 {"id": "[id]", "name": "AD spec page"} |
| Page: GET page | api | done ✓ | 200 {"name": "AD spec page", "html": "<p>Initial spec by AgentDrives</p>"} |
| Page: PUT title+content, GET back | api | done ✓ | 200 {"name": "AD spec page v2", "html": "<p class=\"editor-paragraph-block\" data-spacing-group=\"body\">Edited spec by Agent"} |
| Page: list project pages shows it | api | done ✓ | 200 {"listed": true} |
| Page: archive then DELETE, GET | api | done ✓ | 204 {"archive": 204, "delete": 204, "get_after": 404, "b": ""} |
| Create an epic and link child work items: POST epics | api | done ✓ | 201 {"id": "[id]", "name": "AD Epic"} |
| Epic: GET epic | api | done ✓ | 200 {"name": "AD Epic"} |
| Epic: PATCH name | api | done ✓ | 200 {"name": "AD Epic v2"} |
| Epic: link child item, list epic issues | api | done ✓ | 200 {"add": "[{'id': '[id]', 'deleted_by': None, 'type_id': '[id]', 'parent': '0d475c48-9aad-414e-b", "listed": true} |
| Epic: DELETE epic, GET | api | done ✓ | 204 {"get_after": 404} |
| Create an initiative to roll up multiple projects: POST v2 initiatives | api | done ✓ | 201 {"id": "[id]", "name": "AD Initiative 7270"} |
| Initiative: GET initiative | api | done ✓ | 200 {"name": "AD Initiative 7270"} |
| Initiative: PATCH initiative | api | done ✓ | 200 {"resp": "{'id': '[id]', 'name': 'AD Initiative 7270', 'description': None, 'description_html': '<p>roll-up</p>', 'lead_id': Non", "state": "ACTIVE"} |
| Initiative: add 2 projects, list initiative projects | api | done ✓ | 200 {"add": "{'added': ['[id]', '[id]'], 'removed': []}", "list": "{'data': [{'id': '[id]', 'name': 'AD drive project AD994', 'description': 'updated by Agent |
| Initiative: DELETE, GET | api | done ✓ | 204 {"get_after": 404} |
| Create a project: DELETE project, GET | api | failed | 204 {"get_after": 403, "b": "{'detail': \"You don't have permission to view this project\"}"} |
| Create a project: re-verify the same DELETE via projects list | api | done ✓ | projects list contains deleted project: False; GET by id 403 "You don't have permission to view this project" instead of 404 |
| First real action: POST /api/v1/workspaces/{slug}/projects/ then GET it back | api | done ✓ | 201 project [id] created; GET 200 returns it |
| Create a project: POST project | api | done ✓ | 201 {"id": "[id]", "identifier": "AD2B3", "name": "AD drive project AD2B3"} |
| Create a project: GET project | api | done ✓ | 200 {"name": "AD drive project AD2B3"} |
| Create a project: PATCH description, GET back | api | done ✓ | 200 {"desc": "updated by AgentDrives"} |
| Create a project: enable cycles/modules/epics on the project (features PATCH) | api | done ✓ | 200 {"cycles": true, "modules": true} |
| Create a work item: POST work-items | api | done ✓ | 201 {"id": "[id]", "sequence_id": 1, "name": "AD test work item", "priority": "medium"} |
| Create a work item: GET work item | api | done ✓ | 200 {"name": "AD test work item"} |
| Update or close a work item: PATCH name/priority/state=Done, GET back | api | done ✓ | 200 {"state": "[id]", "priority": "high", "completed_at": "2026-10-15T07:11:14.150287Z"} |
| Update or close a work item: GET after close | api | done ✓ | 200 {"completed_at": "2026-10-15T07:11:14.150287Z"} |
| Create a work item: GET by readable identifier PROJ-N | api | done ✓ | 200 {"id": "[id]"} |
| Delete a work item: DELETE then GET | api | done ✓ | 204 {"get_after": 404, "body": {"error": "The requested resource does not exist."}} |
| Create a work item: DELETE then GET 404 | api | done ✓ | 204 {"get_after": 404} |
| Plan a cycle (sprint) with start/end dates: POST cycles with dates | api | done ✓ | 201 {"id": "[id]", "name": "AD Sprint 786b", "start_date": "2026-10-19T00:00:01Z", "end_date": "2026-11-01T23:59:00Z"} |
| Plan a cycle: GET cycle | api | done ✓ | 200 {"start": "2026-10-19T00:00:01Z", "end": "2026-11-01T23:59:00Z"} |
| Plan a cycle: PATCH end_date, GET back | api | done ✓ | 200 {"end": "2026-11-02T00:00:00Z"} |
| Plan a cycle: add work item to cycle, list cycle-issues | api | done ✓ | 200 {"add": "[{'id': '[id]', 'deleted_by': None, 'sub_issues_count': 0, 'created_at': '2026-10-15T07:", "listed": true} |
| Plan a cycle: DELETE cycle, GET | api | done ✓ | 204 {"get_after": 404} |
| Break work into a module and assign items: POST modules | api | done ✓ | 201 {"id": "[id]", "name": "AD Module 104d", "status": "planned"} |
| Module: GET module | api | done ✓ | 200 {"name": "AD Module 104d"} |
| Module: PATCH status in-progress | api | done ✓ | 200 {"status": "in-progress"} |
| Module: assign 2 items, list module-issues | api | done ✓ | 200 {"add": "[{'id': '[id]', 'deleted_by': None, 'sub_issues_count': 0, 'created_", "listed": [true, true]} |
| Module: DELETE module, GET | api | done ✓ | 204 {"get_after": 404} |
| Create and edit a wiki page: POST project page | api | done ✓ | 201 {"id": "[id]", "name": "AD spec page"} |
| Page: GET page | api | done ✓ | 200 {"name": "AD spec page", "html": "<p>Initial spec by AgentDrives</p>"} |
| Page: PUT title+content, GET back | api | done ✓ | 200 {"name": "AD spec page v2", "html": "<p class=\"editor-paragraph-block\" data-spacing-group=\"body\">Edited spec by Agent"} |
| Page: list project pages shows it | api | done ✓ | 200 {"listed": true} |
| Page: archive then DELETE, GET | api | done ✓ | 204 {"archive": 204, "delete": 204, "get_after": 404, "b": ""} |
| Create an epic and link child work items: POST epics | api | done ✓ | 201 {"id": "[id]", "name": "AD Epic"} |
| Epic: GET epic | api | done ✓ | 200 {"name": "AD Epic"} |
| Epic: PATCH name | api | done ✓ | 200 {"name": "AD Epic v2"} |
| Epic: link child item, list epic issues | api | done ✓ | 200 {"add": "[{'id': '[id]', 'deleted_by': None, 'type_id': '[id]', 'parent': '97ccaa3f-7c89-4a29-a", "listed": true} |
| Epic: DELETE epic, GET | api | done ✓ | 204 {"get_after": 404} |
| Create an initiative to roll up multiple projects: POST v2 initiatives | api | done ✓ | 201 {"id": "[id]", "name": "AD Initiative 3811"} |
| Initiative: GET initiative | api | done ✓ | 200 {"name": "AD Initiative 3811"} |
| Initiative: PATCH initiative | api | done ✓ | 200 {"resp": "{'id': '[id]', 'name': 'AD Initiative 3811', 'description': None, 'description_html': '<p>roll-up</p>', 'lead_id': Non", "state": "ACTIVE"} |
| Initiative: add 2 projects, list initiative projects | api | done ✓ | 200 {"add": "{'added': ['[id]', '[id]'], 'removed': []}", "list": "{'data': [{'id': '[id]', 'name': 'AD drive project AD994', 'description': 'updated by Agent |
| Initiative: DELETE, GET | api | done ✓ | 204 {"get_after": 404} |
| Create a project: DELETE project, GET by id + list | api | done ✓ | 204 {"get_after": 403, "b": "{'detail': \"You don't have permission to view this project\"}", "in_list": false} |
| Comment on a work item: POST comment, list comments | api | done ✓ | 201 {"id": "[id]", "listed": true} |
| Link or relate two work items: POST link | api | done ✓ | 201 {"id": "[id]", "listed": true} |
| Link or relate two work items: POST relation blocking | api | done ✓ | 201 [{"id": "[id]", "project_id": "[id]", "sequence_id": 8, "relation_type": "blocked_by", "name": "AD secondary item 2", "type_id": "[id]", "is_epic": false, "state_id": "[id] |
| Log time against a work item: POST worklog 30 min, list | api | failed | 404 {"resp": "{'message': 'Worklog is not enabled for the project'}", "list": "{'message': 'Worklog is not enabled for the project'}"} |
| Search work items: GET work-items/search?search=secondary | api | done ✓ | 200 "{'issues': [{'name': 'AD secondary item 2', 'id': '[id]', 'sequence_id': 8, 'project__identifier': 'AD994', 'project_id': '[id]', 'workspace__slug': 'agentdrives-test-ebe971', 'type_id':" |
| Log time against a work item: PATCH project is_time_tracking_enabled, POST worklog 30, list | api | done ✓ | 201 {"resp": "{'id': '[id]', 'created_at': '2026-10-15T07:13:01.558395Z', 'updated_at': '2026-10-15T07:13:01.558407Z', 'description'", "list": "[{'id': '[id]', 'created_at': '2026-10-15T07:13:01.558395Z', 'updated_at': '2026-10-15T0"} |
| Set estimate points and assign to a work item: POST estimate (3 points), set project estimate, PATCH work item estimate_point | api | failed | POST estimate 201 with estimate_points in body, but GET estimate-points returned [] (points not created from the create body); work item estimate_point stays null |
| Create and assign labels and custom states: POST label + POST state, assign both to item | api | done ✓ | POST label 201, POST state 200 (not 201), PATCH item labels+state; GET item shows label ad-label (as expanded objects) and state AD Review |
| Define custom work item types and properties: POST work-item-types | api | done ✓ | 201 {"id": "[id]", "name": "AD Bug", "error": null, "detail": null} |
| Set estimate points and assign to a work item: POST estimate-points (raw array per docs example), PATCH work item estimate_point=3, GET | api | done ✓ | 200 {"estimate_point": "[id]", "ok": true} |
| Attach a file to a work item: POST attachments (upload creds) → POST file to S3 → PATCH is_uploaded → list | api | done ✓ | 200 {"s3": "204", "complete": 204, "listed": true} |
| Submit a request via intake and triage: POST intake-issues, list | api | done ✓ | 201 {"id": "[id]", "listed": true} |
| Customers: POST customers | api | failed | 403 {"error": "Customer feature is not enabled for this workspace"} |
| Create a teamspace: POST v2 teamspaces | api | done ✓ | 201 {"id": "[id]", "name": "AD Team", "error": null, "detail": null, "message": null} |
| Create a customer profile and link requests: PATCH workspace features customers=true, POST customer, POST request with work item, list | api | done ✓ | 201 {"cust": 201, "req": 201, "listed": true} |
| Invite and manage workspace members: POST v2 invitations to our own second inbox, list | api | done ✓ | 201 {"resp": "{'id': '[id]', 'email': 'the agent's inbox', 'role': 'member', 'accepted': False, 'responded_at': None, 'messa", "listed": true} |
| Bulk-edit properties across selected work items: POST v2 bulk-update priority=urgent on 2 items, GET both | api | done ✓ | 200 {"resp": "{'results': [{'index': 0, 'result': 'updated', 'id': '[id]'}, {'index': 1, 'result': 'updated', 'id': '63815079-fc92-4", "p": ["urgent", "urgent"]} |
| Create a work item template and apply it: POST v2 work-item-templates | api | done ✓ | 201 {"id": "[id]", "resp": "{'id': '[id]', 'name': 'AD template', 'short_description': '', 'description_html': '<p></p>', 'template_type': 'workit"} |
| MCP discover (with PAT): POST server/discover 2026-07-28 to https://mcp.plane.so/http/api-key/mcp, then initialize | mcp | done ✓ | server/discover → HTTP 400 JSON-RPC -32600 "Unsupported protocol version: 2026-07-28. Supported versions: 2024-11-05, 2025-03-26, 2025-06-18, 2025-11-25" (not -32022: legacy). initialize offering 2026-07-28 → protocolVersion 2025-11-25, serverInfo "Plane MCP Server (header-http)" 3.2.0, SSE reply, no Mcp-Session-Id. tools/list: 30 tools (mcp.json says 28). |
| Docs claim: Create a project: project(action="create") | mcp | done ✓ | create ok=True; retrieve name=AD MCP project |
| Docs claim: Create a work item: workitem(action="create") | mcp | done ✓ | create→retrieve {'id': '[id]', 'assignees': [], 'labels': [], 'type_id': 'b1bf060c-7824-4594-b968-b87111 |
| Docs claim: Update or close a work item: workitem(action="update") | mcp | done ✓ | priority after=urgent |
| Docs claim: Plan a cycle (sprint) with start/end dates: cycle(action="create") | mcp | done ✓ | {'id': '[id]', 'total_issues': None, 'cancelled_issues': None, 'completed_issues': None, 'started_issues': None, 'unstarted_issues': None, 'backlog_issues': None, 'tota |
| Docs claim: Break work into a module and assign items: module(action="create") | mcp | done ✓ | {'id': '[id]', 'total_issues': None, 'cancelled_issues': None, 'completed_issues': None, 'started_issues': None, 'unstarted_issues': None, 'backlog_issues': None, 'crea |
| Docs claim: Create and edit a wiki page: page(action="create") | mcp | done ✓ | {'id': '[id]', 'name': 'AD MCP page', 'description_stripped': None, 'description_html': '<p>mcp</p>', 'description_binary': None, 'description': None, 'created_at': '20 |
| Docs claim: Create an initiative to roll up multiple projects: initiative(action="create") | mcp | done ✓ | {'id': '[id]', 'name': 'AD MCP initiative', 'description': None, 'description_html': None, 'description_stripped': None, 'description_binary': None, 'start_date': None, |
| Docs claim: Create an epic and link child work items: see epics recipe (workitem_type resolve Epic → workitem create type_id) | mcp | done ✓ | type={'id': '[id]', 'deleted_at': None, 'project_ids': None, 'created_at' epic={'id': '[id]', 'type_id': '[id]', 'created_at': '2026-10 |
| Docs claim: Delete a work item: workitem(action="delete") | mcp | done ✓ | delete ok=True; retrieve after: Error calling tool 'workitem': HTTP 404: Not Found: The requested resource does not exist. |
| Docs claim: Create a work item: POST /workspaces/{workspace_slug}/projects/{project_id}/work-items/ | api | done ✓ | Done in the core chain on this account (see the create/read/update/delete lines); docs at developers.plane.so |
| Docs claim: Update or close a work item: PATCH /workspaces/{workspace_slug}/projects/{project_id}/work-items/{work_item_id}/ | api | done ✓ | Done in the core chain on this account (see the create/read/update/delete lines); docs at developers.plane.so |
| Docs claim: Delete a work item: DELETE /workspaces/{workspace_slug}/projects/{project_id}/work-items/{work_item_id}/ | api | done ✓ | Done in the core chain on this account (see the create/read/update/delete lines); docs at developers.plane.so |
| Docs claim: Create a project: POST /workspaces/{workspace_slug}/projects/ | api | done ✓ | Done in the core chain on this account (see the create/read/update/delete lines); docs at developers.plane.so |
| Docs claim: Plan a cycle (sprint) with start/end dates: POST /workspaces/{workspace_slug}/projects/{project_id}/cycles/ | api | done ✓ | Done in the core chain on this account (see the create/read/update/delete lines); docs at developers.plane.so |
| Docs claim: Break work into a module and assign items: POST /workspaces/{workspace_slug}/projects/{project_id}/modules/; POST .../module-issues/ | api | done ✓ | Done in the core chain on this account (see the create/read/update/delete lines); docs at developers.plane.so |
| Docs claim: Create and edit a wiki page: POST /workspaces/{workspace_slug}/projects/{project_id}/pages/; POST /workspaces/{workspace_slug}/pages/ | api | done ✓ | Done in the core chain on this account (see the create/read/update/delete lines); docs at developers.plane.so |
| Docs claim: Create an epic and link child work items: POST /workspaces/{workspace_slug}/projects/{project_id}/epics/; .../epics/{epic_id}/issues/ | api | done ✓ | Done in the core chain on this account (see the create/read/update/delete lines); docs at developers.plane.so |
| Docs claim: Create an initiative to roll up multiple projects: POST /workspaces/{workspace_slug}/initiatives/ | api | done ✓ | Done in the core chain on this account (see the create/read/update/delete lines); docs at developers.plane.so |
| Docs claim: Create a project: plane-compose apply (projects-as-code) | cli | skipped | not tried yet |
| Assign a background AI Agent to a work item: Create an agent at /{workspace}/ai-agents/create as the docs say, to assign to a work item | browser | failed | app.plane.so/agentdrives-test-ebe971/ai-agents/create/ → in-app 404 "Oops! Something went wrong. Sorry, the page you are looking for cannot be found"; Plane AI sidebar shows Skills, Usage, Analytics, Memory but no Agents section (Business trial workspace). MCP tools/list has no agent tool; no API page for agents in developers.plane.so/llms.txt. |
| Docs claim: Assign a background AI Agent to a work item: work item @mention / agent run lifecycle per MCP docs | mcp | failed | tools/list (30 tools) has no agent or agent-run tool; server instructions mention none |
| Ask Plane AI (Pi Chat) a question about workspace status: Activate Plane AI (in-app OAuth to pi.plane.so), ask how many work items the default project has | browser | done ✓ | Pi answered "The project AgentDrives Test has 7 work items." using PQL; API GET work-items total_count=7 confirms |
| Register a webhook for workspace events: POST v2 webhooks (our own URL, inactive), GET, DELETE, GET | api | done ✓ | 201 {"create": 201, "get": 200, "delete": 204, "after": 404, "resp": "{'id': '[id]', 'name': 'AD hook', 'url': 'https://agent.agentdrives.com/bot', 'is_active': False, 'version': 'v2', 'co"} |
| Define a workflow with approval gates between states: POST v2 workflows | api | plan_gated | 402 {"type": "payment_required", "code": "payment_required", "detail": "The feature 'FeatureFlag.MULTIPLE_WORKFLOWS' is not enabled for this workspace."} |
| View audit logs (API-enabled): GET v2 audit-logs | api | plan_gated | 402 "{'type': 'payment_required', 'code': 'payment_required', 'detail': \"The feature 'FeatureFlag.WORKSPACE_AUDIT_LOG' is not enabled for this workspace.\"}" |
| Define a workflow with approval gates: PATCH project features workflows=true, GET v2 workflows | api | partial ✓ | 200 "{'data': [{'id': '[id]', 'name': 'Default Workflow', 'description': 'Default workflow for the project', 'is_active': True, 'is_default': True, 'work_item_type_ids': []," |
| Switch layouts and save a view: POST v2 project view with display_filters layout=kanban, GET back | api | done ✓ | 201 {"get": 200, "df": "{'layout': 'kanban', 'group_by': 'state'}"} |
| Export work items / analytics data: Settings > Exports > Export (All projects, CSV) | browser | done ✓ | Previous exports table shows an inbox, 15th October 2026 07:22AM, CSV, Completed, Download |
| View real-time dashboard of workload, velocity, burndown: Dashboards > Add dashboard (name + project) in the browser | browser | partial ✓ | Dashboard "AD workload" created at /dashboards/dd71e6de-…; page shows Data source, Add widget; no widget added (no burndown viewed) |
| Import projects/issues from CSV: Settings > Imports > CSV: select project, upload 2-row CSV (Name,Priority), Import CSV | browser | failed | Migrations table: AD drive project AD994, Status "Error", start/end 07:25 AM; search for "imported" returns no work items |
| Connect GitHub/GitLab: Connect integration | browser | skipped | Settings > Integrations offers it; needs our own GitHub/Slack workspace account and an OAuth grant to it, which this drive does not have (no sso kit for this drive) |
| Connect Slack: Connect integration | browser | skipped | Settings > Integrations offers it; needs our own GitHub/Slack workspace account and an OAuth grant to it, which this drive does not have (no sso kit for this drive) |
| Define projects as YAML and deploy via Plane Compose: Install plane-compose CLI and apply a YAML project | cli | skipped | plane.so/plane-compose is a script-rendered page (no install text in the HTML fetched); the CLI was not installed in this drive |
| Docs claim: Create a project: plane-compose apply (projects-as-code) | cli | skipped | not run in this drive (see line) |
| Branding, SSO/SAML/OIDC, security policy: docs check | none | done | docs.plane.so/authentication/sso.md documents SSO; workspace settings show "Identity" and "Workspace Governance" sections (seen in the settings sidebar) |
| Generate a personal access token or OAuth app credential: docs check + UI | none | done | Done in this drive: Profile > Personal Access Tokens (expiry required). Workspace settings also list Developers > Access Tokens |
| Plane Marketplace: docs check | none | done | llms.txt: "[Integrations](https://plane.so/marketplace): Connect with GitHub, GitLab, and Slack"; settings sidebar lists Integrations |
| Self-hosted via Prime CLI: docs check | none | done | developers.plane.so/self-hosting/overview, methods/docker-compose, kubernetes, airgapped-edition (llms.txt); not installed: no Docker in this sandbox |
| Native iOS/Android/Desktop apps: docs check | none | done | llms.txt Downloads: App Store id6657986465, Play Store com.plane.so, plane.so/download |
| Scoped API key headless: Create a scoped key via API/CLI | api | blocked | developers.plane.so/api-reference/v2/authentication: keys are made in Profile Settings > Personal Access Tokens (UI); "there is no way to mint a read-only key"; no token endpoint in v1/v2 reference or MCP tools. OAuth apps are the scoped route (needs an app registration in the UI). |
| Pay probes: 402 challenges, well-known, registries, pricing.json | api | done ✓ | pay_probe.json: no 402 challenge on plane.so/api/x402./mpp. (agents.plane.so 200/405, no challenge); no /.well-known/ucp; OpenAPI has no x-payment-info; registries empty. pay_tx.json: nothing paid (no 402 asking USDC). Unauthenticated API call → 401, no WWW-Authenticate Payment. plane.so/pricing.json lists Free/Pro/Business per seat USD monthly+annual. Workspace started on a 14-day Business trial with no card asked. |
| Walk to the last click: Settings > Billing and plans: Start subscription (Business monthly, current trial plan); Add payment method | browser | done ✓ | Dialog "Start your Business subscription? This ends your trial now and starts billing for Business today. If you don't have a card on file, you'll finish this on the payment page." Price per seat $15.00 / month; buttons Keep trial / "Start subscription and pay" (not clicked: it ends the trial and starts billing). Add payment method opens billing.stripe.com/p/session (Stripe customer portal), which robots.txt disallows for all user agents, so our agent did not open it. Pro ($8) is offered only as "Switch to Pro trial". Billing page: "Your workspace will downgrade automatically to Free if you don't upgrade to a paid plan at the end of 14 days"; no card on file; next invoice shown as $30.00 Oct 29, 2026. |
| Sign up | none | skipped | No keyless route: unauthenticated API call → 401; llms.txt: credential needs a free workspace |
| Sign up | none | skipped | No sign-up API in v1/v2 reference, MCP tools, or llms.txt |
| Sign up | none | skipped | https://plane.so/auth.md 404; MCP AS metadata has no agent_auth block |
| Sign up | browser | skipped | "Sign up with GitHub" seen on app.plane.so/sign-up; pw sso github: this drive has no GitHub account |
| Sign up | browser | skipped | "Sign up with Google" seen on sign-up page; this drive has no Google account (drive.json sso empty) |
| Sign up | browser | skipped | "Sign up with Single Sign-On" seen; needs a company IdP configured by a person |
| Sign up | none | skipped | llms.txt: key from workspace settings; covered by our own account (email_code) in this drive |
| Sign up | none | skipped | pay_probe registries: Plane not in the Stripe Projects catalog |
| Sign up | none | skipped | No CLI login; MCP AS metadata lists no device_authorization_endpoint |
| MCP OAuth sign-in: DCR register at https://mcp.plane.so/http/register → /http/authorize (PKCE S256, resource) → consent "Allow Access" in browser → /http/token → MCP calls | mcp | done ✓ | Client registered (DCR, no CIMD advertised); consent page "Application Access Request" at mcp.plane.so/http/consent; token scope "read write", expires_in 36000; workspace retrieve → connected_via "oauth"; workitem create [id] then delete ok |
| Sign up | browser | skipped | Sign-up page offers email → code only; a password can be set on the profile step (we set one); the same account as email_code |
| Sign up | none | skipped | Not offered: the email sends a 6-digit code, not a link |
| Sign up | none | skipped | No Sign in with AgentID on the sign-up page; door_probe registries: not listed |
| Sign up | none | skipped | No claimable/unclaimed resource route in docs or llms.txt |
| Sign up | none | skipped | pay_tx.json: no 402 on Plane endpoints; nothing paid |
| Revoke API key: Profile > Personal Access Tokens > row menu > Delete > confirm | browser | done ✓ | "The token has been successfully deleted"; GET /api/v1/users/me/ with it → 403 "Given API token is not valid" |
| Cancel trial: Workspace delete asked "Cancel your trial first"; clicked Cancel trial | browser | done ✓ | Toast "Trial canceled. You can now delete the workspace."; billing page now "Free | Active | $0 for up to 12 seats", Business shows "Free trial used". Also in Billing > Plan actions > Cancel trial. |
| Delete workspace: Settings > General > Delete (type name + "delete my workspace") after cancelling the trial | browser | done ✓ | Redirected to /create-workspace/; data gone with the workspace |
| Delete account: Profile > General > Deactivate account > Confirm, then try to sign in again | browser | partial ✓ | Deactivate dialog: "Once deactivated, you can't be assigned work items and be billed for your workspace. To reactivate your account, you will need an invite to a workspace at this email address." After Confirm: signed out. Signing in again with the email code (mail 07:37) was accepted and opened /onboarding/ "Create your profile" with the name AgentDrives Test: the login still works. |
| Delete account (second try): Re-onboard (forced), create temp workspace to reach Profile settings, Deactivate again; then sign in to clean the temp workspace | browser | partial ✓ | Profile settings are unreachable until onboarding creates a workspace. Signing in again by email code reactivated the account and restarted onboarding at "Create your workspace"; the temp workspace was no longer listed, so it could not be opened to delete. |
Also in Project management.
BasecampL4Gets in on its ownPlane vs Basecamp
GitHubL4Gets in on its ownPlane vs GitHub
ShortcutL4Gets in on its ownPlane vs Shortcut
monday.comL3Gets in on its ownPlane vs monday.com