Developer Tools
keelen.ai
An MCP server for managing software projects, where users can create GitHub-backed projects, submit plain-English change requests, track request status, and set product vision.
ENDPOINT 1
https://keelen.ai/mcp
MCP server metadata
- Name
- keelen-saas
keelen-saas Roadmap intake. Submit product requests; PM intake classifies each into roadmap items, clarifying questions, or steering rules. No project yet? There are TWO ways to get one - ASK the user which applies, do not assume: 0a. EXISTING repo -> import_project(repo_full_name[, build_description, project_kind, stack, preview_command, engine]) - connect a repo the user already has. list_github_repos() browses what the workspace's GitHub connection can see. `project_kind` is optional (auto-detected) but PASS IT for a monorepo or a stack with no standard root manifest (Java, Ruby, PHP, .NET) - detection yields 'unknown' there, which blocks the dev lane. 0b. NEW repo -> create_project(name, build_description, project_kind[, private, preview_command, org]) - scaffold a NEW GitHub repo + bootstrap project and submit build_description as the first Request. `name` is a concise repo slug; `project_kind` is required (library | node_library | python_library | web_app | godot_game | roblox_game); web_app needs preview_command. Pass `org` (a GitHub org login) to create the repo inside that organization; omit it to use a workspace member's personal account (repo-create OAuth). Then poll get_request_status with the returned thread_id. Workflow: 1. submit_request(project_id, text) - ONE feature/intent per call, text < 16000 chars. Split a multi-feature ask into separate requests. 2. Poll get_request_status. Intake runs async (~5min cadence) - wait between polls. Read next_action: wait | answer_questions | done | cancelled | failed | approve_plan (a planned request's plan awaits the user's approval in the dashboard). 3. If answer_questions -> answer_request (one answer per question). 4. After done -> optionally refine_request (max 5x) to adjust items. Project context (optional, anytime): - set_product_vision(project_id, vision_md) - set the product vision. - set_product_goal(project_id, goal_md) - set the product goal. Both are prepended to PM/dev/QA iter prompts as project context. Operating a running project: - project_status(project_id) - lifecycle status, open tasks, queued_roadmap_items (planned work awaiting expansion, separate from open tasks), iters today, prs_merged_today (the DELIVERY signal: distinct PRs merged today), ui_review (web_app only: scenarios/scenario_cap/captures/capture_cap of the default-branch ui-review.json — both caps are enforced at push time, not in your CI), pass_rate (the local verification pass rate over the last 14 days of dev/QA iterations - NOT a delivery measure; read prs_merged_today for that), verify_decided_14d / verify_errored_14d (the ratio's denominator and its sandbox-timeout share: when errored dominates, pass_rate measures the verify budget, not the code), open escalation COUNT, plus pause state (scheduler_enabled, scheduler_paused_until, pause_reason), freshness (last_iter_at, last_pm_iter_at, last_successful_deploy_at — a LEGACY pointer; read deployment {merged, deployed, verified, last_deploy_attempt} for the three facts kept separately, and treat only `verified` as a verified deployment), and glm_peak_paused (+ glm_peak_resumes_at) for the EPHEMERAL GLM peak-hours skip the pause columns can't show — to tell a paused-by-policy project from a genuine stall. pm_lane {last_pm_iter_at, repo_access} is the PLANNING lane's live health: repo_access 'failing' means that lane cannot read the repo from GitHub even while runs still start and github_connected reads true (that flag is presence-only). - list_roadmap(project_id) - the queued roadmap items + their priority_int; reorder_roadmap(project_id, ordered_ids) reprioritises that queue (first id = expanded next; horizon pins still dominate). - list_escalations(project_id) - the open dead-ends to surface + resolve (project_status only counts them). - resolve_escalation(escalation_id, decision_md) - acknowledge one handled ask only when a blocked task keeps another visible path; a project_pause/orphan_pause resolve RESUMES the project. - retry_blocked_task(escalation_id, decision_md) - after fixing the cause of an eligible recovery-budget task block, grant that task one fresh attempt. - requeue_for_review(task_id, expected_head_sha, reason, request_id) - owner only: return a blocked task whose own PR is green and verified at that exact head to normal review. Pass the TASK id, not an escalation id. A refusal returns a stable cause_code. - rearm_roadmap_item(escalation_id) - perform the dashboard's idempotent same-item dependency re-arm without changing its id or declared roadmap dependencies. - resolve_platform_policy_conflict(escalation_id, decision, decision_md[, project_cap][, selector_corrections]) - apply a structured product decision to the plan and atomically requeue the same task lineage; correct_evidence_selector is owner-only. - replan_task(project_id, task_id, title, body_md, acceptance_criteria, decision_md) - replace unretryable stale work under the same roadmap/attempt lineage and transfer its graph edges. - control_scheduler(project_id, action) - action enable|disable|resume|process_now to wake a dark or paused project. - run_security_review(project_id) - kick off a deep whole-repo security audit; findings post to the project's Security review to triage + send to the loop. - run_legal_exposure_review(project_id) - kick off a legal exposure review; it maps code observations to commonly cited legal obligations under the project's saved compliance profile. Needs that profile first. - get_legal_exposure_findings(project_id) - read those findings, worst exposure first, with the checks that could not decide. BOTH legal tools return a `disclaimer_md` field. Read it to the user before you summarise a finding. This lane is an ENGINEERING review, not legal advice and not a legal clearance, it is not exhaustive, and an empty result is never proof that anything is in order. Never turn its output into a score, a grade, or an overall verdict. - run_control_gap_review(project_id) - kick off a security control gap review after the user saves a framework selection and stack context. - get_control_gap_findings(project_id) - read source-bound observations, review boundaries, and items the review could not determine. BOTH control-review tools return a `disclaimer_md` field. Read it to the user before you summarise an observation. The output is evidence from named sources, not a framework outcome. An empty group never establishes that a control is in place. Most tool responses carry next_action + next_step. next_action is ALWAYS a string, one of: wait | answer_questions | done | cancelled | failed | approve_plan | call_tool | browser | collect_code | save_key_and_reconnect | none. 'call_tool' means call the tool named in the sibling `next_tool` field; 'browser' means send the user the URL named in next_step. When next_action is 'wait' AND poll_after_seconds is present, re-check after that many seconds - re-checking is YOUR job, the server does not push. A 'wait' with NO poll_after_seconds has nothing to poll over MCP (e.g. run_security_review, whose findings land on the project's Security review page, or an errored get_provisioning_status, which will not change until its reported cause is fixed): report it to the user instead of looping. Getting started (no account yet): This server accepts a tokenless connection for signup. If the user has no Keelen account, drive the whole setup from chat: 1. ASK THE USER for the email address, in chat, and WAIT for their answer before calling signup(email). Do NOT take the address from your client profile, the logged-in account, git config, or any other ambient source - the user's Keelen account is often NOT the account you are running under. If you already hold a candidate address, echo it back and get an explicit yes first. This matters because signup also doubles as agent LOGIN for an existing account: a guessed address silently signs you in to whatever workspace owns it, and the next steps then mint an API key on, and create a project in, the wrong account. signup(email) emails the user a 6-digit code. 2. Ask the user to read the code from their inbox, then verify_email(email, code) - it returns a reveal-once API key. 3. Save that key as this server's Authorization header ("Authorization: Bearer <api_key>") in the MCP CLIENT CONFIG, then RECONNECT. The key is shown once - never write it to a repo/file. 4. get_onboarding_status() - loop it and follow next_action/next_tool + next_step verbatim: engine connect happens in the DASHBOARD — call open_dashboard() for a one-click signed-in link (the user is already authenticated through this server, so no email login; NEVER paste Claude/Codex/GLM credentials in chat) -> connect_github() for the install link -> create_project (new repo) or import_project(repo) (existing; list_github_repos() to browse) -> get_provisioning_status(project_id) until ready (if it reports errored, stop polling and fix the cause first). 5. get_billing() when the user is ready to run compute - it returns a Stripe checkout link (the one step that must open a browser).
Known tools 44
create_projectStart building something new: creates a GitHub repo and begins work on it.
Inferred read-onlysubmit_requestAsk for a change in plain English: a feature, a bug fix, or a new direction.
Inferred read-onlyget_request_statusCheck what happened to a request, and read any questions it asked back.
Inferred read-onlyset_product_visionSay what this product is for, so every run knows what it is building toward.
Inferred read-onlyset_product_goalSet the outcome to aim at right now, so work is prioritised toward one thing.
Inferred read-onlycancel_roadmap_itemCancel / close a single roadmap item (list_roadmap returns its id).
Inferred read-onlyclear_horizon_pinClear a queued roadmap item's horizon pin (now/next/later → none).
Inferred read-onlyrollback_roblox_placeRoll a Roblox project's place back to a previously-published version.
Inferred read-onlyproject_statusCheck how a project is doing: what is in flight, what shipped, what is stuck.
Inferred read-onlyclose_taskClose a task that should not be built — a duplicate, or work already shipped.
Inferred read-onlyget_product_goalRead a project's current product goal (the outcome work is aimed at).
Inferred read-onlyget_product_visionRead a project's current product vision (what the product is for).
Inferred read-onlylist_escalationsSee what the work is stuck on and waiting for a human decision about.
Inferred read-onlyresolve_escalationAcknowledge a handled ask only when no blocked task becomes invisible.
Inferred read-onlyretry_blocked_taskGrant one fresh attempt after fixing a recovery-budget task block.
Inferred read-onlyrequeue_for_reviewReturn one blocked task's existing pull request to normal review.
Inferred read-onlyresolve_platform_policy_conflictResolve a platform-policy dead-end with a structured plan decision.
Inferred read-onlyset_ui_review_scenario_capSet this web_app project's ui-review scenario budget, or reset it.
Inferred read-onlyarchive_projectArchive a project (reversible shelve) — frees a project slot in-tool.
Inferred read-onlydelete_projectSoft-delete a project (the harder option) — frees a slot and hides it.
Potential side effectsrun_security_reviewFind security problems in a repository: a deep, whole-codebase review.
Inferred read-onlyrun_legal_exposure_reviewFind where a codebase creates legal exposure (privacy, consent, data handling).
Inferred read-onlyget_legal_exposure_findingsRead a project's legal exposure findings, worst exposure first.
Inferred read-onlyrun_control_gap_reviewStart a source-bound security control gap review for one project.
Inferred read-onlyget_control_gap_findingsRead a project's security-control observations and review boundaries.
Inferred read-onlyanswer_requestAnswer a thread's clarifying questions (status must be awaiting_answers).
Inferred read-onlyrefine_requestSay what is wrong with what a request produced, and have it reworked.
Inferred read-onlyget_onboarding_statusCheck what is set up so far and what to do next to get building.
Inferred read-onlyopen_dashboardGet a one-click, pre-authenticated dashboard sign-in link for the owner.
Inferred read-onlyconnect_githubGet the link that connects a GitHub account, so work can reach real repos.
Inferred read-onlylist_github_reposList repos the workspace's GitHub connection can see (for import_project).
Inferred read-onlyget_provisioning_statusCheck whether a new project has finished setting up and is ready to build.
Inferred read-onlyget_billingBilling status + a Stripe checkout link when a NEW subscription is needed.
Inferred read-onlyproject_digestRead a compact progress digest for one project (delivery, activity, holds, next decision).
Inferred read-onlyCONNECT WITH APPROVAL
Client installation
Review this server and its permissions before adding it. Secret placeholders must be set locally.
Codex
~/.codex/config.toml
[mcp_servers.keelen-saas]
url = "https://keelen.ai/mcp"
enabled = true
Claude Code
.mcp.json
{
"mcpServers": {
"keelen-saas": {
"type": "http",
"url": "https://keelen.ai/mcp"
}
}
}
Claude Desktop
Settings → Connectors → Add custom connector
Name: keelen-saas
Remote MCP URL: https://keelen.ai/mcp
Add this remote URL as a custom connector in Claude Desktop. Availability depends on the user plan and workspace policy.
Cursor
.cursor/mcp.json
{
"mcpServers": {
"keelen-saas": {
"url": "https://keelen.ai/mcp"
}
}
}
Visual Studio Code
.vscode/mcp.json
Add to Visual Studio Code{
"servers": {
"keelen-saas": {
"type": "http",
"url": "https://keelen.ai/mcp"
}
}
}
Generic MCP
Client-specific MCP configuration
{
"name": "keelen-saas",
"transport": "streamable-http",
"url": "https://keelen.ai/mcp"
}
MCP Inspector
Run the official MCP Inspector locally and enter the indexed Streamable HTTP endpoint.
TRUST AND VERIFICATION EVIDENCE
Loading Trust v2 evidence…
Checking the associated registrable domain. The BuiltWith key remains server-side.
Evidence is source-attributed and does not guarantee that a third-party server is safe. Risk labels are conservative metadata heuristics.