@inova.dev/devspace-mcp
v0.4.0
Published
MCP server that lets AI clients (Claude Desktop, Claude Code, etc.) read and update DevSpace tests for a specific codebase, scoped via an Unkey-issued API key.
Downloads
386
Maintainers
Readme
@inova.dev/devspace-mcp
MCP server that lets any AI client (Claude Desktop, Claude Code, Cursor, etc.) read and update DevSpace tests for a specific codebase, authenticated with an Unkey-issued API key.
Tools exposed:
Tests (/tests function)
| Tool | Maps to |
| --- | --- |
| codebase_context | POST /tests/context — returns the decrypted project + codebase names + ids |
| list_tests | POST /tests/list |
| get_test | POST /tests/get |
| create_test | POST /tests/create |
| mark_test_status | POST /tests/setStatus |
| delete_test | POST /tests/delete |
Issues (/issues function — unified codebase_issues table)
Covers everything that lands in codebase_issues, distinguished by source:
manual(typed by humans)github_issue,github_vulnerabilityaikido,aikido_licensesentryuser_submitted
| Tool | Maps to |
| --- | --- |
| list_issues | POST /issues/list (filter by source, status, severity, etc.) |
| get_issue | POST /issues/get |
| search_similar_issues | POST /issues/searchSimilar — call this BEFORE create_issue to avoid duplicates |
| create_issue | POST /issues/create (defaults source: 'manual', writes aiSummary/fixRef into ai_log) |
| update_issue | POST /issues/update (re-encrypts title/description; appends to ai_log) |
| mark_issue_status | POST /issues/setStatus (stamps resolved_at on resolved/closed; appends to ai_log) |
| delete_issue | POST /issues/delete |
AI accountability: every create/update/setStatus appends an event to the row's ai_log jsonb column ({actor, action, summary, fixRef, ts}). Pass aiSummary to write a human-readable line and fixRef (commit sha / PR url) so downstream review knows what changed. Cap is 200 events per row — oldest events fall off after that.
Submissions (/submissions function — contact_messages table)
Inbound contact-form receiver. Form submissions from the customer's website (proxied through their own backend) land here.
| Tool | Maps to |
| --- | --- |
| list_submissions | POST /submissions/list (filter by kind, status, unread, archived) |
| get_submission | POST /submissions/get (also marks as read) |
| mark_submission_status | POST /submissions/setStatus (optionally appends a reply to conversation jsonb) |
| archive_submission | POST /submissions/archive (pass unarchive: true to restore) |
No create_submission MCP tool — submissions only come from the customer's backend POSTing to /submissions/submit with the API key in their server's env.
The bound codebase is whatever the API key was minted for — there is no codebase argument and no way to widen scope.
Setup (one-time)
In the DevSpace desktop app, open the codebase you want the AI to manage → API Keys → New key. Give it a label like "Claude Desktop" and decide:
- Permissions:
tests:readfor read-only AI,tests:read tests:writefor "AI can also add and update tests." - Rate limit: e.g. 60/min — useful guardrail for runaway agents.
- Expiry: leave off, or set 30/60/90 days for rotation discipline.
Copy the key when shown (
ds_org_…). You won't see it again.- Permissions:
Install the MCP server. You can
npxit directly (the snippets below do that) ornpm i -g @inova.dev/devspace-mcpif you want it onPATH.Wire it into your AI client. The exact file varies — see below.
Wiring it in
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"devspace": {
"command": "npx",
"args": ["-y", "@inova.dev/devspace-mcp"],
"env": {
"DEVSPACE_API_KEY": "ds_org_xxxxxxxxxxxxxxxxxxxxxxxx",
"DEVSPACE_API_URL": "https://YOUR-PROJECT.supabase.co/functions/v1/tests"
}
}
}
}Restart Claude Desktop. New "devspace" tools appear in the tool picker.
Claude Code
claude mcp add devspace, then edit the entry:
{
"command": "npx",
"args": ["-y", "@inova.dev/devspace-mcp"],
"env": {
"DEVSPACE_API_KEY": "ds_org_…",
"DEVSPACE_API_URL": "https://YOUR-PROJECT.supabase.co/functions/v1/tests"
}
}Cursor / other MCP-aware clients
Same shape — stdio transport, command + args + env.
Conventional prompts to try
Once connected, the AI can drive the codebase's tests directly:
"What's the test coverage status for this codebase?" Calls
codebase_context+list_testsand summarizes by status.
"Add a test under Auth: 'New user signs up with email' — steps: open Sign Up, enter credentials, confirm. Expected: lands on dashboard." Calls
create_testwith structured fields.
"Mark
<test-id>as passing — I tested it on iOS 26." Callsmark_test_statuswithrunBy: "<your name>"and the note.
"For every test still marked 'pending' under Billing, generate a one-paragraph steps section." Reads via
list_tests, then loopsmark_test_statuswith notes.
Security model
- The key authorizes only this codebase. It cannot see, list, or modify tests on any other codebase or org — that's enforced server-side by the Edge Function reading
meta.codebaseIdoff the verified Unkey result. - Each key carries its own sealed envelope so the Edge Function can return decrypted project + codebase names to the AI for
codebase_context. The envelope can only be unsealed by holders of this specific key string. - Revoking the key in the DevSpace admin sheet immediately revokes AI access — the next request fails with HTTP 401.
- Rotating = mint a new key, update
DEVSPACE_API_KEYin the AI client config, restart, then revoke the old one.
Local development
npm install
npm run build
DEVSPACE_API_KEY=ds_org_… \
DEVSPACE_API_URL=https://your-project.supabase.co/functions/v1/tests \
npm startStdio is the transport — drop it into any MCP client that speaks stdio. For a quick poke without an AI client, the @modelcontextprotocol/inspector tool will let you call tools by hand.
Adding new tools
- Add a
Toolentry insrc/index.ts(toolsarray). - Add a Zod schema for the inputs.
- Add a case in the
CallToolRequestSchemahandler that parses args and callscallEdge(action, args). - On the Edge Function side, add a matching switch case in
supabase/functions/tests/index.ts.
That's it — no SDK regen, no protocol negotiation.
