mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-15 14:22:14 +00:00
mcp: scaffold Worker, environment guardrails, fake-upstream skeleton, CI
Cloudflare Worker scaffold for the MCP server (Hono, TypeScript strict, pnpm 11 via corepack, wrangler 4, vitest 4 in workerd). - wrangler.toml declares local/preview/production; production alone pins https://api.storyteller.ai. Binding types are generated by `wrangler types`. - src/config.ts parses the bindings and asserts the upstream-host invariant per environment; src/index.ts fails every request with a 500 naming the mismatch if the invariant is violated. - Guardrail tests: config invariant, wrangler.toml environment mapping, MCP_ENVIRONMENT referenced only in config.ts and never branched on, /healthz through the Worker entry. - fake-upstream/: separate Worker (artcraft-api-fake) that will hold the ported fake API routes; eslint forbids imports across the boundary in both directions. - .github/workflows/mcp.yml: typecheck, lint, format, test on mcp/**; production deploy skips with a notice until Cloudflare secrets exist. pnpm check: typecheck, eslint, prettier, 28 tests passing. Claude-Session: https://claude.ai/code/session_01H3gfN2NCx3hBXSrZXYHUQ3
This commit is contained in:
1 parent
984e8d3845
commit
59a7cc5fb4
25 files changed
+3331
No files matched your search
@@ -0,0 +1,71 @@
|
||||
name: mcp
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "mcp/**"
|
||||
- ".github/workflows/mcp.yml"
|
||||
pull_request:
|
||||
paths:
|
||||
- "mcp/**"
|
||||
- ".github/workflows/mcp.yml"
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: mcp
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: typecheck · lint · format · test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
package_json_file: mcp/package.json
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: pnpm
|
||||
cache-dependency-path: mcp/pnpm-lock.yaml
|
||||
- run: pnpm install --frozen-lockfile
|
||||
- run: pnpm typecheck
|
||||
- run: pnpm lint
|
||||
- run: pnpm format
|
||||
- run: pnpm test
|
||||
|
||||
deploy-production:
|
||||
name: deploy · production
|
||||
needs: check
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||
runs-on: ubuntu-latest
|
||||
environment: production
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v4
|
||||
with:
|
||||
package_json_file: mcp/package.json
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: pnpm
|
||||
cache-dependency-path: mcp/pnpm-lock.yaml
|
||||
- run: pnpm install --frozen-lockfile
|
||||
# Deploys are skipped, not failed, until the Cloudflare secrets exist (docs/infra-request.md §2).
|
||||
- id: creds
|
||||
run: |
|
||||
if [ -n "$CLOUDFLARE_API_TOKEN" ] && [ -n "$CLOUDFLARE_ACCOUNT_ID" ]; then
|
||||
echo "present=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "::notice::Cloudflare secrets not configured; skipping deploy."
|
||||
echo "present=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
env:
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
- if: steps.creds.outputs.present == 'true'
|
||||
run: pnpm exec wrangler deploy --env production
|
||||
env:
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
|
||||
Reference in new issue
Block a user