MySpec
Spec-driven development platform. Lets Cursor, Claude Code and other MCP clients read and write MySpec projects and spec bundles (constitution, requirements, solution, tasks). 31 tools. Requires a MySpec account; free plan available.
Hosted MCP Server
npx add-mcp 'https://mcp.myspec.dev/mcp'Installs into Claude Code, Codex, Cursor and more
Documentation
INTEGRATION PROTOCOL · MCP · v0.4
MCP Server
@myspec/mcp-server - specs in your AI coding agent
A Model Context Protocol server that exposes your MySpec projects, spec files, attachments, spec sessions, and artifact bundles to Cursor, Claude Code, Claude Desktop and any MCP client - over stdio with OAuth, or over HTTPS with an API token.
Install with npx or as a Claude Code plugin. 31 tools. No separate CLI to learn.
Three ways to connect
stdio server (default)
Your AI editor is the MCP client; npx -y @myspec/mcp-server is the server on your machine. Sign in once with login, or drop in an API token. Can download files to disk.
HTTP server (hosted)
https://mcp.myspec.dev/mcp - a stateless Streamable HTTP endpoint for clients with no filesystem: hosted agent platforms, browser clients, connectors, CI runners. Requires a Personal Access Token in the Authorization header - there is no browser sign-in. Same 31 tools, content moves inline. Full guide ↓
reverse (opt-in)
Run reverse --root <dir> and the roles flip: your machine serves a read-only view of one directory to the MySpec cloud agent, so brownfield workflows can read your existing codebase before proposing a change.
Configure your client
Add MySpec to your .mcp.json (Claude Code, Cursor), Claude Desktop's claude_desktop_config.json, or the equivalent MCP client config:
{
"mcpServers": {
"myspec": {
"command": "npx",
"args": ["-y", "@myspec/mcp-server"]
}
}
}
Claude Code users can register it user-wide in one command:
$ claude mcp add --scope user myspec -- npx -y @myspec/mcp-server
Want the in-development build? Use the @next dist-tag (@myspec/mcp-server@next) - a prerelease published on every merge. Prefer the untagged package for daily use.
Alternative · Claude Code plugin
Claude Code: install the official plugin instead
The myspec-mcp plugin registers this same server for you - no config to write, no secrets in it - and adds Spec-Driven Development skills to implement, analyze, and write MySpec spec bundles. Run inside Claude Code, restart, then sign in with npx -y @myspec/mcp-server login:
/plugin marketplace add myspecs/claude-plugins
/plugin install myspec-mcp@myspec
Use one method, not both: if the plugin is installed, remove any myspec entry from .mcp.json or claude mcp add (claude mcp remove myspec), or Claude Code loads two sets of MySpec tools.
Plugin quick start: install, sign in, first prompts →
Unattended setups: API tokens
login needs a browser. For a server, a container, a CI job, or a shared machine - and always for the HTTP server - create a long-lived Personal Access Token (PAT, shown in the webapp as an API token, value msp_pat_…): avatar menu → API tokens → Create token. Pick the organization it acts in, read-only or read-write access, and an expiry - 30, 90, 180 or 365 days (90 by default; there is no never expires). The token is shown once.
{
"mcpServers": {
"myspec": {
"command": "npx",
"args": ["-y", "@myspec/mcp-server"],
"env": { "MYSPEC_API_TOKEN": "msp_pat_…" }
}
}
}
or in one command:
$ claude mcp add --scope user myspec --env MYSPEC_API_TOKEN=msp_pat_… -- npx -y @myspec/mcp-server
- No
login, no files: the token is exchanged for a short-lived access token on every run and is never written to disk. Unset the variable and the credential is gone. - Precedence:
MYSPEC_API_TOKEN>apiTokenin~/.myspec/oauth_creds.json> the refresh token saved bylogin. Whichever wins is used exclusively - a rejected token fails the run rather than quietly falling back to another identity. - A token's organization and access mode are fixed at creation; its expiry can be extended without changing the value, up to a hard total life of two years from creation - past that, create a new one.
- You can hold 25 active tokens and create 10 per hour. Revoking is permanent: a revoked token can never be re-enabled or refreshed, only replaced.
Platform tools
31 tools on each server, in six groups. Names and argument shapes are identical across the stdio and HTTP servers - the only differences are the rows in the comparison table below - so a prompt that works in Cursor works from a hosted agent too.
Projects
7 tools
list_projectsget_projectcreate_projectupdate_projectarchive_projectunarchive_projectdelete_project
delete_project only works on an archived project - archiving is the confirmation step.
Spec files
6 tools
list_spec_fileget_spec_fileread_spec_filedownload_spec_fileupload_spec_fileupdate_spec_file
Reads return content_version; writes become new revisions. download_spec_file is stdio-only and lands in.specs/.
Trash Bin
2 tools
move_spec_file_to_trashrestore_spec_file_from_trash
Nothing is destroyed by accident: trashed files stay restorable indefinitely (list them with list_spec_file trashed=true).
Attachments
4 tools
list_attachmentsget_attachmentread_attachmentupload_attachment
PDF, DOCX, XLSX, images, and any UTF-8 text file up to 10 MiB. Text is paginated by line; images come back inline.
Spec sessions
6 tools
list_spec_sessionsget_spec_sessionrename_spec_sessionarchive_spec_sessionunarchive_spec_sessiondelete_spec_session
Session metadata and summaries only - the chat transcript is never returned. Delete requires archiving first.
Artifacts
6 tools
list_artifactsget_artifactread_artifact_filecreate_artifactwrite_artifact_revisionrollback_artifact
New - available over MCP only for now: multi-file bundles (an HTML mockup is index.html + styles.css + app.js) versioned as one snapshot. There is no browser UI for artifacts yet. rollback_artifact appends a revision rather than rewriting history, like git revert.
Downloads land in.specs/
download_spec_file mirrors the remote path under a dot-prefixed .specs/ folder in the server's working directory - conventionally gitignored, so a downloaded copy never shows up as untracked noise next to your repo's own specs/. Pass an absolute destination_path to save anywhere else.
download_spec_file(file_id) # -> .specs/<bundle>/requirements.md
download_spec_file(file_id, destination_path="/tmp/req.md") # explicit path, honored as given
Concurrent edits are never silently overwritten
Several people and AI sessions can work on the same project. get_spec_file and read_spec_file return a content_version; pass it to update_spec_file as expected_version and a write that raced someone else's save is rejected with a message naming who changed it - re-read, merge, then update again. The HTTP server makes expected_version mandatory.
read_spec_file(file_id) -> { content, content_version: 42 }
update_spec_file(file_id, content, expected_version: 42)
# someone saved in between? -> rejected, nothing overwritten; re-read, merge, retry
MCP SERVER HTTP · mcp.myspec.dev
The HTTP server for hosted agents
@myspec/mcp-server-http is the sibling of the stdio server, deployed as a stateless Cloudflare Worker at https://mcp.myspec.dev/mcp. It exists for MCP clients that connect over HTTPS and have no filesystem - hosted agent platforms, browser-based clients, ChatGPT- or Claude-style connectors, CI runners. Same 31 tool names, same platform underneath; everything that needed a local disk (OAuth login, credential files, downloads, the reverse bridge) is deliberately absent, and content moves inline, paginated.
REQUIRED · PERSONAL ACCESS TOKEN IN THE REQUEST HEADER
Every request to mcp.myspec.dev must carry a MySpec Personal Access Token. There is no browser sign-in on this server - a request without the header is rejected with HTTP 401 before it is even parsed.
Authorization: Bearer msp_pat_…
- 01 · CREATE
In the MySpec webapp: avatar menu → API tokens → Create token. Choose the organization, read-only or read-write, and an expiry (30 / 90 / 180 / 365 days, 90 by default). The value (
msp_pat_…) is shown once. - 02 · CONFIGURE
Put it in your client's request headers as
Authorization: Bearer <token>- the--headerflag, theheadersblock ofmcp.json, or your SDK's custom-headers option (snippets below). - 03 · VERIFY
A
tools/listcall answers 200 when the token is accepted and 401 when it is missing, revoked, expired, or belongs to the other environment.
curl -sS -o /dev/null -w '%{http_code}\n' https://mcp.myspec.dev/mcp \
-H "Authorization: Bearer msp_pat_…" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
# 200 → token accepted · 401 → missing, revoked, expired, or a token from the other environment
Treat the token like a password: it grants the access level and organization it was created with for as long as it is valid. Store it in a secret manager or an environment variable, never in a committed config file.
Endpoints
| Route | Auth | Purpose |
|---|---|---|
| POST /mcp | Personal Access Token (required) | Stateless Streamable HTTP - one JSON-RPC message per request (initialize, tools/list, tools/call). No SSE stream, no sessions; an Mcp-Session-Id header is ignored. Other verbs answer 405. |
| GET /health | None | Liveness probe reporting service, version, environment; makes zero upstream calls. |
Production: mcp.myspec.dev. Staging: mcp.myspecs.dev. Tokens are environment-specific - a production token does not work against staging and vice versa.
Authentication: Personal Access Token only
Every request carries Authorization: Bearer msp_pat_… - the same Personal Access Token described above (webapp → avatar menu → API tokens). No other credential type is accepted. The Worker exchanges it for a short-lived platform token on each request; there is no OAuth flow, no login, and nothing stored on either side. A missing or rejected token is a transport-level HTTP 401 with WWW-Authenticate: Bearer before the JSON-RPC body is even parsed, and the body names the reason: MALFORMED_TOKEN (not an msp_pat_ value), TOKEN_INVALID (unknown, expired, revoked or disabled), or ORG_ACCESS_LOST (its owner is no longer in the organization). A 502 carrying EXCHANGE_UNAVAILABLE or EXCHANGE_MALFORMED means the token exchange itself failed, not your token.
- A read-only token still sees all 31 tools listed - 14 read-only, 17 mutating; calling a mutating one returns an actionable "this API token is read-only" tool error rather than a transport failure.
- A token is scoped to one organization at creation - the tools operate on that organization's projects only.
- Exchanged tokens are cached in isolate memory for at most 60 seconds, so a token revoked in the webapp can keep working for up to a minute. Treat that window as the exposure when you rotate.
Connect a client
In every snippet, replace msp_pat_… with your own Personal Access Token - it is the only credential the server accepts.
Claude Code - register the remote server with its header:
$ claude mcp add --transport http myspec https://mcp.myspec.dev/mcp --header "Authorization: Bearer msp_pat_…"
Cursor, Windsurf, VS Code, and any client that accepts a remote MCP server with custom headers - mcp.json style:
{
"mcpServers": {
"myspec": {
"url": "https://mcp.myspec.dev/mcp",
"headers": { "Authorization": "Bearer msp_pat_…" }
}
}
}
Hosted agent SDKs, connectors, and CI - the raw JSON-RPC round-trip any HTTP client can make:
# 1. handshake
curl -sS https://mcp.myspec.dev/mcp \
-H "Authorization: Bearer msp_pat_…" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}'
# 2. list the tools (optionally narrowed with X-MCP-Tools)
curl -sS https://mcp.myspec.dev/mcp \
-H "Authorization: Bearer msp_pat_…" \
-H "Content-Type: application/json" \
-H "X-MCP-Tools: list_projects,read_spec_file" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
# 3. call one
curl -sS https://mcp.myspec.dev/mcp \
-H "Authorization: Bearer msp_pat_…" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"list_projects","arguments":{"limit":5}}}'
$ curl -sS https://mcp.myspec.dev/health # {"service":"…","version":"…","environment":"production"}
Clients that only support OAuth-based remote servers (some consumer connector UIs) cannot attach a static bearer header; use the stdio server there, or a proxy that injects the header.
What differs from the stdio server
stdio (npx @myspec/mcp-server) | HTTP (mcp.myspec.dev) | |
|---|---|---|
| Auth | OAuth login or API token | Personal Access Token required in every request header |
| Transport | stdio, long-lived process | Stateless Streamable HTTP, one JSON-RPC message per POST |
| Large files | read_spec_file paginates by line, files above 8 MiB refused; download_spec_file saves binary or large files (up to 50 MiB) to .specs/ | Same pagination and same 8 MiB cap; no downloads - view larger or binary files in the webapp |
| Trash listing | list_spec_file trashed=true | list_spec_file trashed=true - the older list_trashed_spec_files is deprecated, kept only for backward compatibility |
| Spec file body | content inline or local_file_path read from disk | content inline only |
| Attachments in | upload_attachment takes a local file_path | upload_attachment takes content_base64 |
| Concurrent edits | expected_version optional | expected_version required on update_spec_file |
| Download URLs / disk cache | Signed URLs, ~/.myspec cache | None - content is always inline |
| Local codebase access | reverse --root | Not available (no machine to expose) |
read_spec_file(file_id, offset=1, limit=2000)
-> { content, start_line, end_line, read_lines, total_lines, truncated, next_offset, content_version }
update_spec_file(file_id, content, expected_version) # expected_version is REQUIRED here
Narrow the tool surface with X-MCP-Tools
An optional request header listing the tools a client should see, comma-separated and case-sensitive: X-MCP-Tools: list_projects,list_spec_file,read_spec_file. The server is built per request from exactly that intersection - unknown names are dropped, and a list that resolves to nothing yields an empty tool set rather than the full one, so a connector that asked for read-only access is never handed a writer. Enforced on both tools/list and tools/call.
Limits
| What | Limit | Notes |
|---|---|---|
| read_spec_file / read_attachment (text) | 2,000 lines per call (default and cap), 1 MiB per response | Paginate with offset (1-based) and next_offset instead of downloading. |
| read_spec_file file size | Files above 8 MiB are refused | The whole file is materialised in the Worker before pagination. |
| upload_attachment | 10 MiB decoded (≈ 13.4 MiB base64) via content_base64 | Matches the platform attachment cap; PDF, DOCX, XLSX, images, UTF-8 text. |
| read_attachment (images) | png / jpeg / gif / webp returned whole, up to 10 MiB | Other binary types are directed to the webapp. |
| list_spec_sessions | 20 per page | Session context is parsed server-side; page rather than fetch everything. |
| get_spec_session include_context | 1 MiB | Check context_size_bytes and context_keys first. |
| read_artifact_file | 2,000 lines per call, 1 MiB per response; files above 8 MiB are refused | Same pagination as read_spec_file. Binary artifact files (images, fonts) are not readable here - get_artifact lists their size and checksum. |
| create_artifact / write_artifact_revision | 50 files per bundle, 2 MiB per file, 10 MiB per revision | A revision is one immutable snapshot; the newest 50 are retained, older ones pruned. |
| X-MCP-Tools header | 4,096 bytes / 64 names | Longer lists return HTTP 400. |
| JSON-RPC batches | Rejected with -32600 | One message per POST; no SSE, no sessions. |
| Token revocation | Up to 60 s | Exchanged tokens are cached in isolate memory for at most 60 s. |
Security notes
- The Worker holds no persistent state - no database, KV, or object storage; nothing of yours is stored between requests.
- Structured logs redact the
Authorizationheader and anymsp_pat_substring. - Writes are attributed to the AI actor, so a human editing the same spec file in the webapp wins any race; deleting a project or session still requires archiving it first.
- Prefer a read-only token for connectors that only need to read specs, and set an expiry - it can be extended later without changing the value, up to two years from creation.
Local file access for brownfield work (read-only)
The MySpec brownfield and OpenSpec workflows refuse to propose a change until they have read real files from your repository. There are two ways to let the cloud architect see your code:
Option 1 - Mount a folder in the browser
Click Mount folder in the Local Workspace panel of a chat session. Uses the File System Access API, so it works in Chrome and Chromium-based browsers (Edge 86+), not Firefox or Safari.
Option 2 - reverse mode
Any browser, any OS: the CLI connects out over WebSocket and serves one directory. Only one reverse connection per user is active; a newer one replaces the old.
$ npx -y @myspec/mcp-server reverse --root./my-project
local_fs_list_dir- list directory entries under the granted rootlocal_fs_read_file- read a file under the granted rootlocal_fs_grep- search for a pattern under the granted rootlocal_pack_codebase/local_pack_codebase_read_page- pack the codebase into a paginated text bundle the agent reads in one go (its preferred first move)
Every path is sandboxed to the directory you pass with --root, binary files are rejected, and secret files (SSH keys, .env -style credentials) are always excluded - this is read-only exposure, not a sync engine. The agent WebSocket URL is discovered from your account after login; --agent-url or MYSPEC_AI_AGENT_WS_URL overrides it.
Authentication at a glance
login (OAuth) | API token | |
|---|---|---|
| Needs a browser | Yes (or --paste) | No |
| Credential rotates | Yes, on every refresh | No |
| Scope | Whatever the session can reach (pinned org) | One organization, fixed at creation |
| Access | Full | Read-only or read-write, fixed at creation |
| Works with HTTP server | No | Yes - and it is the only option there |
Local state lives under ~/.myspec/: settings.json (which auth server you signed in to, plus discovered service URLs) and oauth_creds.json (tokens, mode 0600 - the server refuses a file readable by group or other). logout ends the session and leaves settings.json alone; if the file holds a configured apiToken it is rewritten with just that token, otherwise it is removed.
Environment variables
MYSPEC_API_TOKEN- long-lived API token (msp_pat_…) for unattended use; takes precedence over saved credentials and is never written to diskMYSPEC_USER_AUTH_URL- auth server to exchange against (defaulthttps://auth.myspec.dev); set it for a non-production token so a 401 reads as the environment mismatch it isMYSPEC_DOWNLOAD_ROOT- on-disk cache root used byread_spec_file(default~/.myspec); tools never write outside itMYSPEC_AI_AGENT_WS_URL- ai-agent WebSocket URL forreverse; skips discovery
Spec file conventions
Spec paths are relative, rooted at specs/ or openspec/, and nest at most three directory levels deep. The file type is derived from the filename - constitution, requirements, solution, tasks, proposal, and a generic openspec-spec for everything else (Spec Kit's spec.md and plan.md, OpenSpec delta specs and design.md). Older bundles named the solution file design.md; match on file_type, not the filename.
Read the field guide to every spec file type →
Frequently asked questions
What can I do with the MySpec MCP server?
Once it's connected to Claude Desktop, Claude Code, or Cursor, your AI editor can list and manage your MySpec projects; read, download, upload, and update spec files as versioned revisions; read attachments; inspect or tidy spec sessions; and version multi-file artifact bundles - no switching to the browser to copy content back and forth.
Can I upload existing local spec files into a MySpec project?
Yes. Point your AI editor at a local file and ask it to upload it - upload_spec_file accepts a local path directly on the stdio server (local_file_path; the HTTP server takes the body inline as content), so a requirements.md, a Spec Kit spec.md, or an OpenSpec change already sitting in your repo can be brought into a project without copy-pasting. Use update_spec_file the same way to save a new revision.
Can it see my local codebase, not just spec files?
Yes, if you opt in. Running npx -y @myspec/mcp-server reverse --root ./my-project exposes a read-only view of that directory to the cloud AI agent, so it can list files, read them, grep across them, or pack the whole codebase into a bundle for context - exactly what the brownfield workflows need before drafting a proposal. In Chrome you can mount a folder from the chat page instead.
My agent runs in the cloud and has no disk. Can it still use MySpec?
Yes - point it at https://mcp.myspec.dev/mcp and configure a Personal Access Token in its request headers (Authorization: Bearer msp_pat_…); the HTTP server has no browser sign-in and rejects unauthenticated requests. It gets the same tool names, with file content returned inline and paginated instead of downloaded. See the HTTP server guide.
Do I need to install a separate CLI first?
No. npx -y @myspec/mcp-server runs the server directly - there's nothing to install globally, and no other CLI is required.
Is there a Claude Code plugin?
Yes. Run /plugin marketplace add myspecs/claude-plugins and /plugin install myspec-mcp@myspec inside Claude Code. The plugin registers this server for you and adds skills that implement, analyze, and write MySpec spec bundles; a second plugin, myspec-factory, runs a whole bundle with parallel worker sessions. See the Claude Code plugin quick start.
Does the MCP server replace app.myspec.dev?
No. The MCP server gives your AI editor access to specs that already exist - it doesn't run the Architect interview or the generate workflows. To create a new bundle you still start at app.myspec.dev; the MCP server is how you then pull those specs into your editor, keep them updated, and feed in local context.