Skip to content

Commit 59d2324

Browse files
committed
init
0 parents  commit 59d2324

39 files changed

+18591
-0
lines changed

.github/workflows/validate.yml

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
name: deploy
2+
3+
concurrency:
4+
group: ${{ github.workflow }}-${{ github.ref }}
5+
cancel-in-progress: true
6+
7+
on:
8+
push:
9+
branches:
10+
- 'main'
11+
pull_request: {}
12+
13+
jobs:
14+
setup:
15+
name: 🔧 Setup
16+
timeout-minutes: 10
17+
strategy:
18+
matrix:
19+
os: [ubuntu-latest, windows-latest, macos-latest]
20+
runs-on: ${{ matrix.os }}
21+
steps:
22+
- name: ⬇️ Checkout repo
23+
uses: actions/checkout@v4
24+
25+
- name: ⎔ Setup node
26+
uses: actions/setup-node@v4
27+
with:
28+
node-version: 24
29+
30+
- name: ▶️ Run setup script
31+
run: npm run setup
32+
33+
- name: ʦ TypeScript
34+
run: npm run typecheck
35+
36+
- name: ⬣ ESLint
37+
run: npm run lint
38+
39+
tests:
40+
name: 🧪 Test
41+
timeout-minutes: 10
42+
runs-on: ubuntu-latest
43+
# Use continue-on-error to ensure this job doesn't fail the workflow
44+
continue-on-error: true
45+
46+
steps:
47+
- name: ⬇️ Checkout repo
48+
uses: actions/checkout@v4
49+
50+
- name: ⎔ Setup node
51+
uses: actions/setup-node@v4
52+
with:
53+
node-version: 24
54+
55+
- name: 📦 Install dependencies
56+
run: npm ci
57+
58+
- name: 🧪 Run tests
59+
id: run_tests
60+
run: node ./epicshop/test.js ..s
61+
62+
deploy:
63+
name: 🚀 Deploy
64+
timeout-minutes: 10
65+
runs-on: ubuntu-latest
66+
# only deploy main branch on pushes on non-forks
67+
if:
68+
${{ github.ref == 'refs/heads/main' && github.event_name == 'push' &&
69+
github.repository_owner == 'epicweb-dev' }}
70+
71+
steps:
72+
- name: ⬇️ Checkout repo
73+
uses: actions/checkout@v4
74+
75+
- name: 🎈 Setup Fly
76+
uses: superfly/flyctl-actions/[email protected]
77+
78+
- name: 🚀 Deploy
79+
run: flyctl deploy --remote-only
80+
working-directory: ./epicshop
81+
env:
82+
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

.gitignore

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
node_modules
2+
3+
workspace/
4+
**/.cache/
5+
**/build/
6+
**/public/build
7+
**/playwright-report
8+
data.db
9+
/playground
10+
**/tsconfig.tsbuildinfo
11+
12+
# in a real app you'd want to not commit the .env
13+
# file as well, but since this is for a workshop
14+
# we're going to keep them around.
15+
# .env

.npmrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
legacy-peer-deps=true
2+
registry=https://registry.npmjs.org/

.prettierignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
**/node_modules/**
2+
**/.cache/**
3+
**/build/**
4+
**/dist/**
5+
**/public/build/**
6+
**/package-lock.json
7+
**/playwright-report/**

LICENSE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
This material is available for private, non-commercial use under the
2+
[GPL version 3](http://www.gnu.org/licenses/gpl-3.0-standalone.html). If you
3+
would like to use this material to conduct your own workshop, please contact us
4+

README.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<div>
2+
<h1 align="center"><a href="https://www.epicweb.dev/workshops">MCP Auth 🔐</a></h1>
3+
<strong>
4+
Build remote MCP servers with users
5+
</strong>
6+
<p>
7+
In this workshop, we'll build a remote MCP server that supports authentication/authorization with standard OAuth2.1 in MCP.
8+
</p>
9+
</div>
10+
11+
<hr />
12+
13+
<div align="center">
14+
<a
15+
alt="Epic Web logo with the words Deployed Version"
16+
href="https://epicweb-dev-mcp-auth.fly.dev/"
17+
>
18+
<img
19+
width="300px"
20+
src="https://github-production-user-asset-6210df.s3.amazonaws.com/1500684/254000390-447a3559-e7b9-4918-947a-1b326d239771.png"
21+
/>
22+
</a>
23+
</div>
24+
25+
<hr />
26+
27+
<!-- prettier-ignore-start -->
28+
[![Build Status][build-badge]][build]
29+
[![GPL 3.0 License][license-badge]][license]
30+
[![Code of Conduct][coc-badge]][coc]
31+
<!-- prettier-ignore-end -->
32+
33+
## Prerequisites
34+
35+
- JavaScript/TypeScript experience
36+
- Node.js experience
37+
- [Advanced MCP Features](https://www.epicai.pro/advanced-mcp-features) or equivalent
38+
experience.
39+
40+
## Pre-workshop Resources
41+
42+
Here are some resources you can read before taking the workshop to get you up to
43+
speed on some of the tools and concepts we'll be covering:
44+
45+
- [Letting AI Interface with Your App with MCPs](https://www.epicai.pro/letting-ai-interface-with-your-app-with-mcps-talk)
46+
- [MCP Introduction](https://modelcontextprotocol.io/introduction)
47+
- [Your AI Assistant Instructor: The EpicShop MCP Server](https://www.epicai.pro/your-ai-assistant-instructor-the-epicshop-mcp-server-0eazr)
48+
- [How to Debug Your MCP Server](https://www.epicai.pro/how-to-debug-your-mcp-server-38qyl)
49+
- [OAuth 2.0 and OpenID Connect (in plain English)](https://www.youtube.com/watch?v=996OiexHze0) - (1 hour video, but it's really great!)
50+
51+
## System Requirements
52+
53+
- [git][git] v2.18 or greater
54+
- [NodeJS][node] v24 or greater
55+
- [npm][npm] v8 or greater
56+
57+
All of these must be available in your `PATH`. To verify things are set up
58+
properly, you can run this:
59+
60+
```shell
61+
git --version
62+
node --version
63+
npm --version
64+
```
65+
66+
If you have trouble with any of these, learn more about the PATH environment
67+
variable and how to fix it here for [windows][win-path] or
68+
[mac/linux][mac-path].
69+
70+
## Setup
71+
72+
This is a pretty large project (it's actually many apps in one) so it can take
73+
several minutes to get everything set up the first time. Please have a strong
74+
network connection before running the setup and grab a snack.
75+
76+
> **Warning**: This repo is _very_ large. Make sure you have a good internet
77+
> connection before you start the setup process. The instructions below use
78+
> `--depth` to limit the amount you download, but if you have a slow connection,
79+
> or you pay for bandwidth, you may want to find a place with a better
80+
> connection.
81+
82+
Follow these steps to get this set up:
83+
84+
```sh nonumber
85+
git clone --depth 1 https://github.com/epicweb-dev/mcp-auth.git
86+
cd mcp-auth
87+
npm run setup
88+
```
89+
90+
If you experience errors here, please open [an issue][issue] with as many
91+
details as you can offer.
92+
93+
## The Workshop App
94+
95+
Learn all about the workshop app on the
96+
[Epic Web Getting Started Guide](https://www.epicweb.dev/get-started).
97+
98+
[![Kent with the workshop app in the background](https://github-production-user-asset-6210df.s3.amazonaws.com/1500684/280407082-0e012138-e01d-45d5-abf2-86ffe5d03c69.png)](https://www.epicweb.dev/get-started)
99+
100+
<!-- prettier-ignore-start -->
101+
[npm]: https://www.npmjs.com/
102+
[node]: https://nodejs.org
103+
[git]: https://git-scm.com/
104+
[build-badge]: https://img.shields.io/github/actions/workflow/status/epicweb-dev/mcp-auth/validate.yml?branch=main&logo=github&style=flat-square
105+
[build]: https://github.com/epicweb-dev/mcp-auth/actions?query=workflow%3Avalidate
106+
[license-badge]: https://img.shields.io/badge/license-GPL%203.0%20License-blue.svg?style=flat-square
107+
[license]: https://github.com/epicweb-dev/mcp-auth/blob/main/LICENSE
108+
[coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
109+
[coc]: https://kentcdodds.com/conduct
110+
[win-path]: https://www.howtogeek.com/118594/how-to-edit-your-system-path-for-easy-command-line-access/
111+
[mac-path]: http://stackoverflow.com/a/24322978/971592
112+
[issue]: https://github.com/epicweb-dev/mcp-auth/issues/new
113+
<!-- prettier-ignore-end -->

epicshop/.npmrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
legacy-peer-deps=true
2+
registry=https://registry.npmjs.org/

epicshop/Dockerfile

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
FROM node:24-bookworm-slim as base
2+
3+
RUN apt-get update && apt-get install -y git
4+
5+
ENV EPICSHOP_GITHUB_REPO=https://github.com/epicweb-dev/mcp-auth
6+
ENV EPICSHOP_CONTEXT_CWD="/myapp/workshop-content"
7+
ENV EPICSHOP_HOME_DIR="/myapp/.epicshop"
8+
ENV EPICSHOP_DEPLOYED="true"
9+
ENV EPICSHOP_DISABLE_WATCHER="true"
10+
ENV FLY="true"
11+
ENV PORT="8080"
12+
ENV NODE_ENV="production"
13+
14+
WORKDIR /myapp
15+
16+
# Clone the workshop repo during build time, excluding database files
17+
RUN git clone --depth 1 ${EPICSHOP_GITHUB_REPO} ${EPICSHOP_CONTEXT_CWD}
18+
19+
ADD . .
20+
21+
RUN npm install --omit=dev
22+
23+
RUN cd ${EPICSHOP_CONTEXT_CWD} && \
24+
npx epicshop warm
25+
26+
CMD cd ${EPICSHOP_CONTEXT_CWD} && \
27+
npx epicshop start

epicshop/fix-watch.js

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import path from 'node:path'
2+
import { fileURLToPath } from 'node:url'
3+
import chokidar from 'chokidar'
4+
import { $ } from 'execa'
5+
6+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
7+
const here = (...p) => path.join(__dirname, ...p)
8+
9+
const workshopRoot = here('..')
10+
11+
// Watch the exercises directory
12+
const watcher = chokidar.watch(path.join(workshopRoot, 'exercises'), {
13+
ignored: [
14+
/(^|[\/\\])\../, // ignore dotfiles
15+
(path) => {
16+
// Only watch directories up to depth 2
17+
const relativePath = path.slice(workshopRoot.length + 1)
18+
return relativePath.split('/').length > 4
19+
},
20+
],
21+
persistent: true,
22+
ignoreInitial: true,
23+
})
24+
25+
const debouncedRun = debounce(run, 200)
26+
27+
// Add event listeners.
28+
watcher
29+
.on('addDir', (path) => {
30+
debouncedRun()
31+
})
32+
.on('unlinkDir', (path) => {
33+
debouncedRun()
34+
})
35+
.on('error', (error) => console.log(`Watcher error: ${error}`))
36+
37+
/**
38+
* Simple debounce implementation
39+
*/
40+
function debounce(fn, delay) {
41+
let timer = null
42+
return (...args) => {
43+
if (timer) clearTimeout(timer)
44+
timer = setTimeout(() => {
45+
fn(...args)
46+
}, delay)
47+
}
48+
}
49+
50+
let running = false
51+
52+
async function run() {
53+
if (running) {
54+
console.log('still running...')
55+
return
56+
}
57+
running = true
58+
try {
59+
await $({
60+
stdio: 'inherit',
61+
cwd: workshopRoot,
62+
})`node ./epicshop/fix.js`
63+
} catch (error) {
64+
throw error
65+
} finally {
66+
running = false
67+
}
68+
}
69+
70+
console.log('Watching exercises directory for changes...')
71+
console.log('running fix to start...')
72+
run()

0 commit comments

Comments
 (0)