Skip to main content
Glama
README.md
# mcp-fleet

Four MCP servers I wrote for myself and use daily: a fitness wearable, a hosting platform, a domain registrar, and my editor's own hook configuration. 3,364 lines of server source plus 500 in the auth and smoke scripts, 47 tools, stdio transport.

They share no code and I wrote them in a week without planning a house style. Reading them back afterwards, they had converged on the same three patterns — and that convergence is the only part of this repository I would call a finding, so it is written up first: **[docs/patterns.md](docs/patterns.md)**.

Short version:

1. **Single-flight credential refresh.** Agents are concurrent; refresh tokens usually are not. Six tool calls landing on an expired token must produce one refresh, not six.
2. **Dry-run by default on anything irreversible.** The gate lives in the tool's own schema, so the model sees it before calling and the default path is the safe one.
3. **One composite tool per server that fans out and returns a ranked action list** — where each finding names the tool that fixes it, so the model doesn't have to plan.

## The servers

| Package                                           | Tools | What it's for                                                                       |
| ------------------------------------------------- | ----- | ----------------------------------------------------------------------------------- |
| [`whoop`](packages/whoop)                         | 12    | Recovery, sleep, strain, workouts, cycles. Full OAuth with rotating refresh tokens. |
| [`vercel`](packages/vercel)                       | 16    | Deployments, env vars, domains, logs — plus `vercel_project_audit`.                 |
| [`spaceship`](packages/spaceship)                 | 15    | Domain registration and DNS, with a confirm gate on anything that costs money.      |
| [`claude-code-hooks`](packages/claude-code-hooks) | 4     | Reads and analyses a Claude Code hook configuration.                                |

### The piece I'd point at first

`packages/whoop/src/auth/token-manager.ts`. The OAuth flow is a real authorization-code flow: an ephemeral callback server on `:4567`, CSRF state generated and _verified_ on return, a 404 on any other path, tokens written at mode `0600`, and the listener closed the moment authorization completes.

The runtime half is twenty lines and every line is load-bearing:

```ts
if (!cached) cached = await deps.readTokens();
if (cached.expires_at - REFRESH_SKEW_MS > deps.now()) {
  return cached.access_token;
}
if (!inFlight) {
  inFlight = refresh(cached).finally(() => {
    inFlight = null;
  });
}
cached = await inFlight;
```

In-memory cache so disk is read once per process. A 60-second skew so a token that would expire mid-flight is refreshed before the request rather than after a 401. The promise itself as the lock. `.finally` so a failed refresh doesn't poison the next attempt.

Refreshing it for this repository meant making the dependencies injectable, which is why there is now a test that actually pins the concurrency property rather than asserting it in a comment:

```ts
it("issues one refresh for six concurrent callers", async () => {
  const pending = Array.from({ length: 6 }, () => manager.getAccessToken());
  release();
  const results = await Promise.all(pending);

  expect(h.refreshCalls()).toBe(1);
  expect(results).toEqual(Array(6).fill("access-2"));
  expect(h.writes()).toHaveLength(1);
});
```

Sixteen tests over the token manager, covering the skew boundary, rotation, the latch clearing after failure, and the case where a provider omits the rotated token.

## Honest state

`docs/patterns.md` ends with the list of what is still wrong; the headlines are that **only the WHOOP token manager has unit tests** — everything else has live-API smoke scripts and nothing that runs offline — that annotation coverage is uneven (12/12 on WHOOP, 0 on the other three, including destructive tools), and that the `confirm` gate is missing on three destructive tools whose siblings have it.

These four were published to npm under an account that no longer exists, so every package's `repository` field currently points at a 404. Republishing under a working identity is pending.

## Running them

```bash
pnpm install
pnpm test          # 16 tests
pnpm build
```

Then point an MCP client at the built entry point. WHOOP needs one-time authorization:

```bash
cd packages/whoop
WHOOP_CLIENT_ID=... WHOOP_CLIENT_SECRET=... pnpm auth
```

Credentials come from the environment. Nothing in this repository reads a credential from a file it also tracks.

## License

MIT.