Skip to content

Commit 4414996

Browse files
committed
more vibes
1 parent af023c8 commit 4414996

File tree

3 files changed

+130
-61
lines changed

3 files changed

+130
-61
lines changed

README.md

Lines changed: 76 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,83 @@
1-
# React + Vite
1+
# mini-mcp-registry
22

3-
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
3+
A lightweight, self-hosted MCP registry that exposes a filtered subset of the [official MCP registry](https://registry.modelcontextprotocol.io). Deployable to GitHub Pages as a static site.
44

5-
Currently, two official plugins are available:
5+
## Copilot MCP Registry URL
66

7-
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
8-
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
7+
```
8+
https://vydia.github.io/mini-mcp-registry/allowed-servers
9+
```
910

10-
## React Compiler
11+
This endpoint returns only the **official Figma MCP server** (`com.figma.mcp/mcp`) in standard MCP registry format.
1112

12-
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
13+
## Running locally
1314

14-
## Expanding the ESLint configuration
15+
```bash
16+
npm install
17+
npm run dev
18+
```
1519

16-
If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.
20+
The UI will be available at `http://localhost:5173`. It fetches live from the official registry and filters results by preset.
21+
22+
To preview the production build locally:
23+
24+
```bash
25+
npm run build
26+
npm run preview
27+
```
28+
29+
## How the registry endpoint works
30+
31+
At build time, `scripts/build-registry.mjs` fetches the official Figma server entry from the MCP registry API and writes it to `public/allowed-servers`. Vite copies `public/` into `dist/` unchanged, so the file is served as a static JSON response at `/allowed-servers`.
32+
33+
To regenerate the file manually without a full build:
34+
35+
```bash
36+
node scripts/build-registry.mjs
37+
```
38+
39+
## Adding or changing allowed servers
40+
41+
Edit `scripts/build-registry.mjs`. The relevant section is:
42+
43+
```js
44+
// Fetch a specific server by name + version
45+
const url = 'https://registry.modelcontextprotocol.io/v0.1/servers/com.figma.mcp%2Fmcp/versions/latest';
46+
```
47+
48+
To allow multiple servers, fetch each one and push them into the `servers` array before writing the file:
49+
50+
```js
51+
const figma = await fetchServer('com.figma.mcp%2Fmcp');
52+
const github = await fetchServer('com.github.mcp%2Fgithub');
53+
54+
const payload = {
55+
servers: [figma, github],
56+
metadata: { count: 2, nextCursor: null },
57+
};
58+
```
59+
60+
Server names come from the [official registry](https://registry.modelcontextprotocol.io/docs). Use `%2F` to encode the `/` in the server name for the URL.
61+
62+
## Adding UI filter presets
63+
64+
Edit `src/presets.js`:
65+
66+
```js
67+
{
68+
id: 'linear',
69+
label: 'Linear',
70+
search: 'linear',
71+
description: 'MCP servers that integrate with Linear',
72+
},
73+
```
74+
75+
The `search` value is passed to the registry's `?search=` query param (substring match on server name).
76+
77+
## Deployment
78+
79+
Deploys automatically to GitHub Pages on every push to `main` via `.github/workflows/deploy.yml`.
80+
81+
**One-time setup:** In the GitHub repo go to **Settings → Pages → Source** and select **GitHub Actions**.
82+
83+
The build step (`npm run build`) runs `scripts/build-registry.mjs` first to fetch fresh server data, then builds the Vite app.

public/allowed-servers

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"servers": [
3+
{
4+
"server": {
5+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json",
6+
"name": "com.figma.mcp/mcp",
7+
"description": "The Figma MCP server brings Figma design context directly into your AI workflow.",
8+
"title": "Figma MCP Server",
9+
"repository": {
10+
"url": "https://github.com/figma/mcp-server-guide",
11+
"source": "github"
12+
},
13+
"version": "1.0.3",
14+
"remotes": [
15+
{
16+
"type": "streamable-http",
17+
"url": "https://mcp.figma.com/mcp"
18+
}
19+
]
20+
},
21+
"_meta": {
22+
"io.modelcontextprotocol.registry/official": {
23+
"status": "active",
24+
"publishedAt": "2025-10-16T17:40:56.949472Z",
25+
"updatedAt": "2025-10-16T17:40:56.949472Z",
26+
"isLatest": true
27+
}
28+
}
29+
}
30+
],
31+
"metadata": {
32+
"count": 1,
33+
"nextCursor": null
34+
}
35+
}

scripts/build-registry.mjs

Lines changed: 19 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env node
2-
// Fetches filtered MCP servers from the v0.1 registry API (server-side search + latest only)
3-
// and writes static JSON files to public/ for deployment.
2+
// Fetches the official Figma MCP server from the registry and writes
3+
// public/allowed-servers — a Copilot-compatible MCP registry endpoint.
44

55
import { writeFileSync, mkdirSync } from 'fs';
66
import { join, dirname } from 'path';
@@ -9,59 +9,26 @@ import { fileURLToPath } from 'url';
99
const __dirname = dirname(fileURLToPath(import.meta.url));
1010
const OUT_DIR = join(__dirname, '..', 'public');
1111

12-
const PRESETS = [
13-
{ id: 'figma', search: 'figma' },
14-
{ id: 'github', search: 'github' },
15-
{ id: 'notion', search: 'notion' },
16-
{ id: 'slack', search: 'slack' },
17-
{ id: 'postgres', search: 'postgres' },
18-
];
19-
20-
async function fetchPage(url, retries = 5) {
21-
for (let attempt = 0; attempt <= retries; attempt++) {
22-
const res = await fetch(url);
23-
if (res.status === 429) {
24-
await new Promise((r) => setTimeout(r, (attempt + 1) * 2000));
25-
continue;
26-
}
27-
if (!res.ok) throw new Error(`Registry API error: ${res.status}`);
28-
return res.json();
29-
}
30-
throw new Error('Too many retries due to rate limiting');
31-
}
32-
33-
async function fetchSearch(search) {
34-
const results = [];
35-
let cursor = null;
36-
37-
do {
38-
const url = new URL('https://registry.modelcontextprotocol.io/v0.1/servers');
39-
url.searchParams.set('search', search);
40-
url.searchParams.set('version', 'latest');
41-
url.searchParams.set('limit', '100');
42-
if (cursor) url.searchParams.set('cursor', cursor);
43-
44-
const data = await fetchPage(url.toString());
45-
results.push(...(data.servers ?? []));
46-
cursor = data.metadata?.nextCursor ?? null;
47-
} while (cursor);
48-
49-
return results;
12+
async function fetchFigmaOfficial() {
13+
const url = 'https://registry.modelcontextprotocol.io/v0.1/servers/com.figma.mcp%2Fmcp/versions/latest';
14+
const res = await fetch(url);
15+
if (!res.ok) throw new Error(`Registry API error: ${res.status}`);
16+
return res.json();
5017
}
5118

5219
mkdirSync(OUT_DIR, { recursive: true });
5320

54-
for (const preset of PRESETS) {
55-
process.stdout.write(` Fetching "${preset.search}"...`);
56-
const servers = await fetchSearch(preset.search);
21+
console.log('Fetching official Figma MCP server...');
22+
const entry = await fetchFigmaOfficial();
5723

58-
const payload = {
59-
servers,
60-
metadata: { count: servers.length, filter: preset.id, generatedAt: new Date().toISOString() },
61-
};
62-
63-
writeFileSync(join(OUT_DIR, `${preset.id}.json`), JSON.stringify(payload, null, 2));
64-
console.log(` ✓ ${servers.length} server(s) → public/${preset.id}.json`);
65-
}
24+
const payload = {
25+
servers: [entry],
26+
metadata: {
27+
count: 1,
28+
nextCursor: null,
29+
},
30+
};
6631

67-
console.log('Done.');
32+
const outPath = join(OUT_DIR, 'allowed-servers');
33+
writeFileSync(outPath, JSON.stringify(payload, null, 2));
34+
console.log('✓ public/allowed-servers written');

0 commit comments

Comments
 (0)