mcp-tool-server
Why It Exists
This skill exists because its first design was wrong, and the record of why is
kept deliberately in .omc/plans/mcp-tooling-skills.md under a section titled
"Why v1 was wrong." The original plan (v1) was derived from a YouTube tutorial
transcript and proposed building a brand-new @cogs/mcp-kit package, a
three-backend auth-adapter matrix (Supabase/Zitadel/none), and a remote-MCP
plus Clerk-OAuth track. An architect review and a deep-exploration pass found
that almost all of this already existed, shipped and tested, in
cates-works/packages/mcp-content-server and its accompanying service-token
system — down to the detail that server.ts already isolated its
StdioServerTransport binding to a single line, meaning the "transport-
agnostic core" v1 wanted to design from scratch was already a proven property
of the real code. The plan was rewritten from a harvest-and-generalize job
instead of a greenfield build, and went through five revisions (v1 through v5)
under Architect and Codex-critic review before shipping — catching, along the
way, a false claim that a sibling repo (helmsman) was blocked on this work
(it explicitly wasn't — it had already ruled out a new token type in its own
architecture doc) and a real gap where the service-token contract specified
isCreatorLive(creatorId) without ever threading a creatorId into mint()
in the first place.
The HTTP transport binding exists for a similarly concrete reason: helmsman's
own auto-mcp-on-publish.md explicitly requires HTTP transport ("we do NOT
spawn a process per app — stdio is dev-only"), so an earlier draft that
deferred HTTP alongside the (genuinely unbuilt) OAuth track was citing a real
consumer's need and then not serving it — a defect the Codex critic pass
caught and fixed by shipping and testing a minimal index-http.ts binding
rather than leaving it as prose.
What It Does
Scaffolds an MCP tool with a single domain implementation exposed through four
front doors: a core layer with the actual operations, a commander-based CLI
adapter for humans and CI, a transport-agnostic server.ts, and one binding
file per transport (index-stdio.ts for local MCP clients, index-http.ts for
remote, bearer-token-authenticated callers). The HTTP binding authenticates via
@cogs/auth's createServiceTokenManager — prefixed, SHA-256-hashed,
TTL-capped service tokens with a live creator-revocation check on every
request, not a hand-rolled scheme.
How To Use It
Trigger phrases: "build an MCP server", "MCP tool with a CLI fallback", "stdio and HTTP MCP", "StreamableHTTPServerTransport auth", "authenticate an MCP server", "service token for an MCP tool", "mint/verify/revoke bearer token", "redact tokens from logs", "npx skills add for my tool", or scaffolding a new tool around an existing API.
skills add git@github.com:catesandrew/next-starters.git --skill skills/mcp-tool-server -g
npm install @next-starters/skill-mcp-tool-server
/plugin marketplace add catesandrew/next-starters
/plugin install mcp-tool-server@next-starters
Gotchas & Invariants
server.tsmust import no transport at all — a transport import there is the exact defect that forces a second server implementation into existence the next time a new transport is needed.- Tools stay thin: a non-2xx response is relayed as an MCP tool error carrying
the upstream's own
status/error/codeverbatim, never reinterpreted or downgraded. index-stdio.tsnever writes to stdout except MCP protocol frames — a strayconsole.logcorrupts the framing, and the resulting failure surfaces in a different process than the one that caused it.- The HTTP binding runs route check → token verify → scope check before
constructing the
McpServer, and this ordering is asserted with a call-counting fake, not just an HTTP status code — a status code alone can't distinguish "rejected before the handler ran" from "the handler ran and then something else 401'd." - Two capabilities are explicitly not built, on purpose: OAuth/Clerk remote-connector auth (zero shipped precedent anywhere in the source repo family) and a Zitadel auth backend (zero real consumers). Both are documented as deferred extension points, not silently absent.
- Constants (token prefix, mount path, scope vocabulary) are deliberately duplicated from the API rather than imported, so the tool package stays independently deployable — the tradeoff is drift risk, mitigated by a startup shape-check on the token prefix.
Related Skills
This skill doesn't have a close sibling in this catalog — it's the only one focused on scaffolding an MCP tool server.
Sourced from: skills/mcp-tool-server/metadata.json, skills/mcp-tool-server/SKILL.md, .omc/plans/mcp-tooling-skills.md (local research artifact, not tracked in this repo), docs/sessions/2026-08-09-mcp-tooling-harvest/SUMMARY.md, git commit d7188b7