mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-14 13:52:11 +00:00
src/tokens/principal.ts: userToken, username, displayName, scopes, and the upstream credential. The provider hands the protected handler only the decrypted grant props, so finishAuthorization now stores userToken and the granted scopes in props alongside the credential and issue time; principalFromProps validates all of it and fails closed with PrincipalError (→ 403) on anything this build does not understand — unknown scopes, wrong token prefix, unrecognised credential kind, missing issue time. Personal tokens (M2) will produce the same props through resolveExternalToken and land on the same function. Also drops @hono/mcp: the SDK's WebStandardStreamableHTTPServerTransport is the right fit for Workers and carries our principal via AuthInfo.extra. Tests (8): rebuild, scope checks, no credential leak through JSON, and the fail-closed cases. Claude-Session: https://claude.ai/code/session_01H3gfN2NCx3hBXSrZXYHUQ3
Artcraft MCP server
Cloudflare Worker at mcp.getartcraft.com. Read CLAUDE.md first — it holds the constraints,
the architecture, and the working method; this file is only how to run things.
Run locally
corepack enable # once; provides the pinned pnpm
pnpm install
cp .dev.vars.example .dev.vars
pnpm --filter @artcraft/mcp-fake-upstream dev # fake API on http://localhost:12345
pnpm dev # MCP server on http://localhost:8787
Local never talks to production: wrangler.toml's top-level block points at the fake, and
src/config.ts refuses to start otherwise.
Check everything
pnpm check # typecheck (regenerates Worker types) · lint · format · test
pnpm test # vitest, inside workerd with the local bindings
Deploy
Deploys run from .github/workflows/mcp.yml on main once the Cloudflare secrets exist
(docs/infra-request.md). Manual deploys, when needed:
pnpm deploy:preview # workers.dev, talks to the deployed fake
pnpm deploy:production # mcp.getartcraft.com, talks to api.storyteller.ai
Layout
See CLAUDE.md → Layout.