@workpowers/speckle
v0.6.0
Published
Local MCP router for Speckle — resolves project context from a committed .speckle marker and forwards calls to the remote Speckle MCP endpoint.
Readme
@workpowers/speckle
The local MCP router for Speckle.
Speckle keeps a living specification of a product — what is true about it, what
you intend to do about it, and what changes are being proposed to that truth.
This package is the small stdio bridge that puts it in front of an AI agent. It
resolves which project you are in from a committed .speckle marker, then
forwards MCP calls to the remote Speckle endpoint.
Register it once per machine. Every repo you work in selects its own project through its own marker file — there is no per-project setup beyond that file.
Install
You do not install it directly; your MCP client runs it through npx. For
Claude Code:
claude mcp add speckle -s user \
-e SPECKLE_MCP_BASE_URL=https://speckle.workpowers.ai \
-e SPECKLE_MCP_KEY=lsk_your_key_here \
-- npx -y @workpowers/speckleGenerate the key at Account → MCP (/account#mcp) on your Speckle host. One
key covers every project you have access to.
Desktop and other GUI hosts
A desktop client starts the router from a fixed directory of its own — usually
your home directory — and its MCP client negotiates no roots capability, so
there is no way for it to tell the router where you are working. Name the
directory yourself:
{
"mcpServers": {
"speckle": {
"command": "npx",
"args": ["-y", "@workpowers/speckle"],
"env": {
"SPECKLE_MCP_BASE_URL": "https://speckle.workpowers.ai",
"SPECKLE_MCP_KEY": "lsk_your_key_here",
"SPECKLE_MCP_WORKSPACE_ROOT": "/Users/you/code/your-repo"
}
}
}
}Without it the session still works, but it runs rootless: discovery tools only,
and it cannot tell the server anything about your checkout — so freshness stays
unknown no matter what is installed on disk. speckle-mcp doctor prints which
directory it searched.
Point a repo at a project
Commit a .speckle marker at the repo root:
npx -y @workpowers/speckle init --project 5The marker is committed on purpose — it is how every agent working in that checkout agrees on which project it is looking at, without any local config.
Two modes
The router boots into one of two shapes depending on what it can see:
- Bound — a
.specklemarker resolved. The session is tied to that project and is served the full toolset for it. - Coordinator — no marker (the client launched outside a Speckle repo, such as Claude Desktop). Discovery tools are registered instead, so the agent can find its way to a project first.
Keep workflow guidance current
The router observes dedicated local Speckle guidance on each tool call and
surfaces process revisions during an open session. Fetch speckle_get_workflow
before planning/resuming. The guide and the small repository bootstrap have
independent revisions; local file observations are attributed to the router,
never presented as independent server verification.
From a repository with a .speckle marker and the router environment configured:
npx -y @workpowers/speckle workflow # preview only
npx -y @workpowers/speckle workflow --apply # dedicated bootstrap + local receipt
npx -y @workpowers/speckle workflow --apply --cache # also retain an offline planning cacheReview the diff and reference SPECKLE.md from AGENTS.md or CLAUDE.md.
Reconcile old copied Speckle guidance while preserving project-specific rules.
Keep .speckle-workflow.json local (for example via Git's local exclude file).
The command refuses edited/unowned files and symlinks. No commits are made.
Unavailable live guidance is reported explicitly with any valid cache's revision
and age; a cache is never called current. Server releases carry new guidance;
restart the router after updating the router package itself.
Diagnosing
npx -y @workpowers/speckle doctorResolves the marker, the workspace, and the environment, then prints what it found. It makes no network request — it diagnoses local configuration only, which makes it the right first command when something feels off.
Environment
| Variable | Required | Purpose |
|---|---|---|
| SPECKLE_MCP_KEY | yes | Your API key. The only secret the router accepts. |
| SPECKLE_MCP_BASE_URL | yes | The Speckle host. A marker's own speckle_url wins over it, so a repo can point at a different host than your default. |
| SPECKLE_MCP_WORKSPACE_ROOT | no | Directory to resolve the .speckle marker from, for hosts that cannot launch the router inside your repo. Takes priority over the process working directory. |
| SPECKLE_PROJECT_ID | no | Fallback project binding for contexts with no marker. |
| SPECKLE_MCP_ALLOW_REPO_MISMATCH | no | Set to 1 to proceed when the marker's repo does not match the checkout. |
SPECKLE_MCP_WORKSPACE_ROOT and SPECKLE_PROJECT_ID answer different
questions and do not substitute for each other. The project id says which
project a markerless session talks to; the workspace root says which
directory on disk to read. Only the second gives the router a checkout to
observe, so only the second lets it report whether your SPECKLE.md is current.
A key is scoped to one Speckle host. If the marker selects a host your
SPECKLE_MCP_BASE_URL disagrees with, the router refuses rather than sending
your key somewhere it does not belong.
Releases
Published from plugins/speckle-mcp in the Speckle monorepo by
.github/workflows/publish-router.yml, which fires when this package's
version field changes on main. It publishes over npm's OIDC trusted
publishing, so no npm token is stored anywhere in the repository.
License
MIT
