You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Implement MCP server features and enhance documentation (#56)
* Implement MCP server with `raid context serve` command and update documentation
* Enhance MCP toolset: implement read-only handlers for profiles and repositories, update documentation, and add tests for new functionality
* Refactor mutating tool handlers to capture output and ensure thread safety; update documentation and tests for new functionality
* feat: implement cross-process mutation locking using flock
- Added a new locking mechanism using flock to serialize mutating operations across processes.
- Introduced WithMutationLock function to wrap user-visible mutating operations, ensuring they are executed atomically.
- Updated various commands (install, env switch, run task, profile add/remove) to utilize the new locking mechanism.
- Refactored tests to isolate state files and prevent interference during concurrent test runs.
- Added tests for the new locking functionality to ensure correct behavior under concurrent access.
- Updated documentation to reflect changes in how mutating operations are handled.
* feat: enhance `raid context serve` command help text with executable path snippets for MCP host configuration
* feat: update `raid context` command description to include MCP server functionality
* feat version bump
* feat: update Go version to 1.25.5 in workflow files
* feat: add tests for recent command status and duration, enhance profile YAML parsing tests
* feat: implement syncBuffer for goroutine-safe output capture and update RemoveProfileCmd to handle lock acquisition errors
Go 1.25.5 CLI. Cobra+Viper. yaml.v3 parsing, jsonschema/v6 validation. mark3labs/mcp-go for the MCP server (`raid context serve`). GoReleaser (.goreleaser.yaml stable, .goreleaser.preview.yaml preview).
2
2
3
3
Build: `go build -o raid .` Test: `go test ./...` Run: `go run . <cmd>`
4
4
5
-
Layout: main.go→src/cmd. src/cmd/raid.go=root cmd+subcommand registration+version check. Reserved built-in subcmds: doctor/, env/, install/, profile/ (user cmds w/ same name ignored w/ warning). src/raid/=core domain (profile loading, env resolution, cmd execution). src/internal/=lib/ (shared types), sys/ (OS helpers, GitHub release checks), utils/. schemas/=JSON schemas (raid-repo.schema.json, raid-profile.schema.json, raid-defs.schema.json). src/resources/=embedded assets (app.properties, profile-template, repo-template) via go:embed; resources.go exposes them. site/=Docusaurus source (merged from docsite-source 2026-04-10); builds to gh-pages via .github/workflows/docs.yml on site/** changes.
5
+
Layout: main.go→src/cmd. src/cmd/raid.go=root cmd+subcommand registration+version check. Reserved built-in subcmds: context/, doctor/, env/, install/, profile/ (user cmds w/ same name ignored w/ warning). context/ has subcmd serve (MCP stdio server). src/raid/=core domain (profile loading, env resolution, cmd execution). src/internal/=lib/ (shared types), sys/ (OS helpers, GitHub release checks), utils/. schemas/=JSON schemas (raid-repo.schema.json, raid-profile.schema.json, raid-defs.schema.json). src/resources/=embedded assets (app.properties, profile-template, repo-template) via go:embed; resources.go exposes them. site/=Docusaurus source (merged from docsite-source 2026-04-10); builds to gh-pages via .github/workflows/docs.yml on site/** changes.
6
6
7
7
Config: raid.yaml=per-repo (environments+tasks: Shell|Script|HTTP|Wait|Template|Group|Git|Prompt|Confirm|Set|Print). profile.raid.yml=user profile (tracked repos, global settings).
8
8
@@ -13,6 +13,10 @@ Non-obvious:
13
13
- Info-cmd fast path: QuietGetCommands() does read-only load (no config creation/warnings) so --help works without valid config
14
14
- User commands registered at runtime from config via registerUserCommands; not in source
15
15
- WriteProfileFile and CreateRepoConfigs prepend embedded templates (src/resources/profile-template, repo-template) to new files; schema URL constants live in the templates, not in Go code
16
+
- src/cmd/context (Go package literally named `context`) imports stdlib context as `stdctx` and the raid wrapper as `rctx` to avoid the package-vs-import name collision
17
+
-`raid context serve` blocks on stdin (stdio MCP transport); BuildServer() in src/cmd/context/serve.go is exported so tests can introspect the server without driving stdio.
18
+
- Mutating tools (raid_install, raid_env_switch, raid_run_task) route command output through raid.SetCommandOutput / lib.commandStdout because os.Stdout is reserved for JSON-RPC framing in the MCP server. Any new lib code that writes user-facing progress should use commandStdout/commandStderr (not fmt.Printf or os.Stdout) so it's captured cleanly.
19
+
- Cross-process mutation lock at ~/.raid/.lock via gofrs/flock. raid.WithMutationLock(fn) wraps the lock+release; every mutating cobra entry point and every MCP mutating handler must call it so CLI usage and the MCP server serialize against each other. Read paths don't acquire the lock. Tests must redirect lib.LockPathOverride (alongside RecentPathOverride) in any setup helper that exercises a mutating path; cmd/context tests use a TestMain to do this once for the whole package.
Output is intentionally token-efficient and bounded — useful for piping into a chat agent or another tool.
109
109
110
-
For more details, see [Context](/docs/usage/context).
110
+
### raid context serve
111
+
112
+
Run a Model Context Protocol server (stdio transport) that exposes the active workspace as resources and the raid agent toolkit as tools. Intended to be launched by an MCP host such as Claude Code or Cursor; the process blocks on stdin until the host disconnects.
113
+
114
+
```bash
115
+
raid context serve
116
+
```
117
+
118
+
For more details on either subcommand, see [Context](/docs/usage/context).
The same data the snapshot exposes statically is also available as a live [Model Context Protocol](https://modelcontextprotocol.io) server, suitable for wiring into Claude Code, Cursor, Claude.ai, Cline, or any MCP-compatible host. The server speaks JSON-RPC 2.0 over stdio.
171
+
172
+
```bash
173
+
raid context serve # blocks; intended to be launched by an MCP host
174
+
```
175
+
176
+
### What's exposed
177
+
178
+
**Resources** — five `raid://workspace/*` URIs that mirror the static snapshot's `workspace` object. Each is fetched live on demand:
179
+
180
+
| URI | MIME | Contents |
181
+
|---|---|---|
182
+
|`raid://workspace/profile`|`text/plain`| Active profile name |
183
+
|`raid://workspace/env`|`text/plain`| Active environment name |
184
+
|`raid://workspace/repos`|`application/json`| Repositories with current git state |
**Tools** — the canonical raid agent toolkit defined in [issue #45](https://github.com/8bitalex/raid/issues/45):
189
+
190
+
| Tool | Purpose |
191
+
|---|---|
192
+
|`raid_list_profiles`| List configured profiles, with the active one flagged |
193
+
|`raid_list_repos`| List repos in the active profile with URL + live git state |
194
+
|`raid_describe_repo`| Return the parsed `raid.yaml` for a repo (by name or path) as structured JSON |
195
+
|`raid_install`| Clone repositories and run install tasks. Optional `repo` argument limits to a single repo |
196
+
|`raid_env_switch`| Switch the active environment, write `.env` files into every repo, and run env tasks |
197
+
|`raid_run_task`| Run a user-defined `raid <command>` from the active profile |
198
+
199
+
Each tool calls straight into the existing raid library and returns its result as a JSON-structured tool result. Mutating tools (`raid_install`, `raid_env_switch`, `raid_run_task`) are serialised behind a process-wide [flock](https://en.wikipedia.org/wiki/File_locking) at `~/.raid/.lock` — that same lock is acquired by every mutating raid CLI invocation (`raid install`, `raid env <name>`, `raid <command>`, `raid profile add/remove/use`). Concurrent mutations from any combination of CLI usage and the MCP server's tools therefore wait for one another instead of racing on `~/.raid/config.toml` or repository state. The kernel releases the lock automatically if the holding process exits unexpectedly.
200
+
201
+
`raid_list_repos` accepts an optional `profile` argument; in this release it must match the active profile or the call returns an error explaining the limitation. Multi-profile lookups are tracked separately.
202
+
203
+
:::note Output capture for mutating tools
204
+
`raid_install`, `raid_env_switch`, and `raid_run_task` route the command output (git clone progress, shell task stdout/stderr, env-setup messages) through an internal buffer instead of letting it leak onto stdout — stdout is reserved for the JSON-RPC framing. The captured text is appended to the tool result so the agent can still inspect what happened.
**Cursor** — add to your project's or user-level `mcp.json`:
216
+
217
+
```json
218
+
{
219
+
"mcpServers": {
220
+
"raid": {
221
+
"command": "raid",
222
+
"args": ["context", "serve"]
223
+
}
224
+
}
225
+
}
226
+
```
227
+
228
+
Once wired, the host's `initialize` handshake reports raid's name and version, `resources/list` returns the five URIs above, and `tools/list` returns the six-tool catalog.
0 commit comments