@dain-os/mcp-server
v0.9.1
Published
MCP server for DainOS — manage projects, tasks, proposals, and proposal content from Claude Code and other MCP clients
Readme
@dain-os/mcp-server
MCP server for DainOS. Lets Claude Code and other MCP clients manage projects, tasks, proposals (including content drafting), PR reviews, instructions library, and developer knowledge (changelog, sessions, KB).
What it does
Wraps the DainOS Express API behind 20 tools: 3 generic tools that cover all standard CRUD operations across every resource, plus 17 semantic tools for operations with real business logic.
Generic tools (v0.8+)
| Tool | What it does |
|---|---|
| describe_schema | Returns the schema of all queryable resources. Call once per session to learn what data is available. |
| query | Read any resource: list with filters, get by ID, or free-text search. Replaces 30+ individual list/get tools. |
| mutate | Create, update, or delete any resource. Replaces 9+ individual create/update/delete tools. |
Resources available through query and mutate: projects, milestones, tasks, task comments, proposals, proposal options, proposal content, session context, developer changelog, developer knowledge base, IAM users, instructions, product repos, product task summaries, PR review findings.
Semantic tools
| Domain | Tools |
|---|---|
| Tasks | create_task (fuzzy milestone resolution), complete_task (status state machine), regenerate_client_view (Anthropic-powered) |
| Cadence | claim_next_task, report_task_progress, mark_blocked, request_unblock |
| Proposals | set_proposal_status, create_proposal_option, update_proposal_option, set_recommended_option |
| Proposal content | proposal_content (6 ops: upsert/delete sections and blocks, reorder, replace all), describe_proposal_block_types |
| Developer | log_changelog_entry, log_knowledge_base_entry, log_time_entry, score_pr_finding |
Setup
1. Mint a personal access token
Sign in to DainOS, go to Settings -> API tokens, click New token, give it a name (e.g. claude-code-laptop), and copy the value. The raw token is shown exactly once.
Tokens look like dain_pat_<43 base64url chars>.
2. Add the server to your MCP client
Option A: Cloud HTTP (recommended)
The MCP server is hosted at mcp.dainos.app. This is the recommended setup: it works with Claude Code subagents (which cannot access local stdio servers), requires no local install, and is always up to date.
{
"mcpServers": {
"dainos": {
"type": "http",
"url": "https://mcp.dainos.app/mcp",
"headers": {
"Authorization": "Bearer ${DAINOS_API_TOKEN}"
}
}
}
}Set the token in your environment:
export DAINOS_API_TOKEN=dain_pat_<your token>Option B: Local stdio
For offline development or if you prefer a local process:
claude mcp add dainos -- npx -y @dain-os/mcp-serverThen set the token:
export DAINOS_API_TOKEN=dain_pat_<your token>Or add it to your Claude Code config directly:
{
"mcpServers": {
"dainos": {
"command": "npx",
"args": ["-y", "@dain-os/mcp-server"],
"env": {
"DAINOS_API_TOKEN": "dain_pat_<your token>"
}
}
}
}3. Restart your MCP client
Claude Code picks up new MCP servers on restart.
Environment
| Variable | Required | Default | Notes |
|---|---|---|---|
| DAINOS_API_TOKEN | yes | n/a | Personal access token from /settings/api-tokens |
| DAINOS_API_URL | no | https://api.dainos.app | Override for local dev or staging |
Using the generic tools
Start by calling describe_schema to discover available resources and their fields. Then use query and mutate for all standard reads and writes.
query({ resource: "projects", filters: { status: "active" } })
query({ resource: "tasks", id: "<uuid>" })
query({ resource: "milestones", parentId: "<project-uuid>" })
query({ resource: "instructions", id: "rule-core-rules" })
query({ resource: "developer_knowledge_base", filters: { project: "dain-os" }, search: "auth" })
mutate({ resource: "projects", operation: "create", data: { name: "New Project" } })
mutate({ resource: "tasks", operation: "update", id: "<uuid>", data: { status: "in_progress" } })
mutate({ resource: "session_context", operation: "create", data: { project: "dain-os", ... } })For operations with business logic, use the dedicated semantic tools:
create_task({ title: "Wire up sidebar", projectId: "<uuid>", milestoneName: "Phase 1" })
complete_task({ id: "<uuid>" })
proposal_content({ proposalId: "<uuid>", op: "upsert_block", sectionKey: "exec", block: { ... } })Drafting proposal content
Proposal content lives in a structured JSON shape: { version: 2, sections: [{ id, key, title, blocks: ContentBlock[] }] }. Eight block types are supported: text, cards, diagram, chart, table, image, gantt, iframe.
Start a drafting session by calling describe_proposal_block_types for the full catalogue. Then use proposal_content with the appropriate op to add or change one block at a time. Available ops: upsert_section, delete_section, upsert_block, delete_block, reorder_blocks, replace_all.
query({ resource: "proposals", id: "<uuid>" }) includes a computed shareUrl field, populated as https://dainos.app/proposals/view/<token> once the proposal has been transitioned to sent. Draft proposals return shareUrl: null.
Usage examples
Once connected, ask Claude Code things like:
- "List my active projects in DainOS."
- "What tasks are assigned to me?"
- "Create a task on the Portunus project called 'wire up the new sidebar' due Friday."
- "Mark that task complete and add a comment that the PR is #312."
- "List all active rules for the herbert project."
- "Fetch the core-rules instruction with template variables resolved for dain-os."
Troubleshooting
401 Unauthorized
DainOS rejected the token (401). Mint a new one at https://dainos.app/settings/api-tokensThe token is revoked, expired, or never existed. Visit Settings -> API tokens, mint a new one, and update your MCP config.
403 Forbidden
The token is valid but your account does not have permission for the operation (e.g. archiving a project you do not own).
Tool is not visible to Claude Code
Restart Claude Code after adding the server. MCP servers are loaded once at startup.
MCP shows "still connecting" (HTTP mode)
Verify the endpoint is reachable: curl https://mcp.dainos.app/mcp should return a 405 JSON error (GET is not allowed; MCP uses POST). If you get an HTML page or SSL error, check your DNS and network.
Migration from v0.7
v0.8 replaces 56 individual tools with 20 (3 generic + 17 semantic). If you have scripts or prompts that reference old tool names:
| Old tool | New equivalent |
|---|---|
| list_projects, get_project | query({ resource: "projects", ... }) |
| create_project, update_project, archive_project | mutate({ resource: "projects", ... }) |
| list_tasks, get_task, update_task, archive_task | query / mutate with resource: "tasks" |
| list_milestones, update_milestone | query / mutate with resource: "milestones" |
| add_task_comment | mutate({ resource: "task_comments", operation: "create", parentId: taskId, ... }) |
| list_proposals, get_proposal, create_proposal, update_proposal, delete_proposal | query / mutate with resource: "proposals" |
| list_proposal_options, delete_proposal_option | query / mutate with resource: "proposal_options" |
| get_proposal_content | query({ resource: "proposal_content", parentId: proposalId }) |
| upsert_proposal_section, delete_proposal_section, upsert_proposal_block, delete_proposal_block, reorder_proposal_blocks, replace_proposal_content | proposal_content({ op: "...", ... }) |
| list_recent_sessions, log_session_context, update_session_context | query / mutate with resource: "session_context" |
| list_changelog, update_changelog_entry | query / mutate with resource: "developer_changelog" |
| search_knowledge_base, update_knowledge_base_entry | query / mutate with resource: "developer_knowledge_base" |
| list_tenant_users, get_user | query({ resource: "iam_users", ... }) |
| list_instructions, get_instruction, search_instructions | query({ resource: "instructions", ... }) |
| lookup_product_repos | query({ resource: "product_repos", filters: { owner, repo } }) |
| summarise_product_tasks | query({ resource: "product_task_summary", parentId: productId }) |
| list_unscored_pr_findings | query({ resource: "pr_review_findings", filters: { repo, prNumber, scoredBy } }) |
Semantic tools that kept their names unchanged: create_task, complete_task, regenerate_client_view, claim_next_task, report_task_progress, mark_blocked, request_unblock, set_proposal_status, create_proposal_option, update_proposal_option, set_recommended_option, describe_proposal_block_types, log_changelog_entry, log_knowledge_base_entry, log_time_entry, score_pr_finding.
Local development
git clone https://github.com/dain-agency/dain-os
cd dain-os/packages/mcp-server
npm install
npm run buildThen point your MCP client at the local build:
{
"mcpServers": {
"dainos-local": {
"command": "node",
"args": ["/path/to/dain-os/packages/mcp-server/dist/index.js"],
"env": {
"DAINOS_API_TOKEN": "dain_pat_...",
"DAINOS_API_URL": "http://localhost:3001"
}
}
}
}Licence
Proprietary. Internal use by Dain only.
