@oneentry/mcp-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # OneEntry MCP Server
2
+
3
+ MCP server for OneEntry SDK — serves rules and skills to Claude Code automatically from a remote server.
4
+
5
+ Users don't need to copy any files. Connect once — always get the latest rules.
6
+
7
+ ## How it works
8
+
9
+ | MCP concept | What it serves |
10
+ |-------------|----------------|
11
+ | **Resources** | Rules (`oneentry://rules/*`) + `CLAUDE.md` — readable context documents |
12
+ | **Prompts** | Skills (`create-page`, `inspect-api`, etc.) — invocable by the user |
13
+
14
+ Content is fetched from GitHub (configurable) and cached for 5 minutes.
15
+
16
+ ---
17
+
18
+ ## Quick start for users
19
+
20
+ ### Option 1 — npx (no install needed)
21
+
22
+ Add to `~/.claude/claude_desktop_config.json` or `.mcp.json` in your project:
23
+
24
+ ```json
25
+ {
26
+ "mcpServers": {
27
+ "oneentry": {
28
+ "command": "npx",
29
+ "args": ["-y", "@oneentry/mcp-server"]
30
+ }
31
+ }
32
+ }
33
+ ```
34
+
35
+ ### Option 2 — global install
36
+
37
+ ```bash
38
+ npm install -g @oneentry/mcp-server
39
+ ```
40
+
41
+ ```json
42
+ {
43
+ "mcpServers": {
44
+ "oneentry": {
45
+ "command": "oneentry-mcp"
46
+ }
47
+ }
48
+ }
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Available resources
54
+
55
+ Read them in Claude Code by typing `@oneentry://rules/<name>`:
56
+
57
+ | URI | Description |
58
+ |-----|-------------|
59
+ | `oneentry://claude-md` | Full CLAUDE.md — main SDK instructions |
60
+ | `oneentry://rules/forms` | Forms & FormsData rules |
61
+ | `oneentry://rules/tokens` | Tokens & makeUserApi rules |
62
+ | `oneentry://rules/attribute-values` | attributeValues access by type |
63
+ | `oneentry://rules/auth-provider` | AuthProvider — auth/signUp rules |
64
+ | `oneentry://rules/nextjs-pages` | Next.js pages, params as Promise |
65
+ | `oneentry://rules/server-actions` | Server Actions rules |
66
+ | `oneentry://rules/orders` | Orders & Payments rules |
67
+ | `oneentry://rules/attribute-sets` | AttributeSets — schema vs values |
68
+ | `oneentry://rules/localization` | Localization, locale from params |
69
+
70
+ ## Available prompts (skills)
71
+
72
+ Invoke in Claude Code with `/skill-name`:
73
+
74
+ | Prompt | Description |
75
+ |--------|-------------|
76
+ | `oneentry-context` | Load full SDK context at session start |
77
+ | `setup-oneentry` | Initialize SDK in a Next.js project |
78
+ | `create-page` | Create Next.js page with CMS content |
79
+ | `inspect-api` | Inspect real API markers and structure |
80
+ | `create-auth` | Auth/registration form |
81
+ | `create-product-list` | Product catalog with filters and pagination |
82
+ | `create-product-card` | Single product page |
83
+ | `create-cart-manager` | Cart — Redux + persist |
84
+ | `create-favorites` | Favorites — Redux + persist |
85
+ | `create-filter-panel` | Filter panel with FilterContext |
86
+ | `create-checkout` | Checkout form + payment |
87
+ | `create-orders-list` | User orders list |
88
+ | `create-profile` | User profile page |
89
+ | `create-form` | Dynamic form from Forms API |
90
+ | `create-reviews` | Reviews with hierarchy |
91
+ | `create-menu` | Navigation menu with submenus |
92
+ | `create-search` | Search bar with debounce |
93
+ | `create-locale-switcher` | Locale switcher |
94
+ | `create-server-action` | Next.js Server Action |
95
+ | `create-subscription-events` | Price/availability subscription |
96
+
97
+ ---
98
+
99
+ ## For OneEntry team — updating content
100
+
101
+ Rules and skills are fetched from the GitHub repo configured in `ONEENTRY_MCP_BASE_URL`.
102
+
103
+ **Default URL:**
104
+ ```
105
+ https://raw.githubusercontent.com/ONEENTRY-PLATFORM/oneentry-sdk-rules/main
106
+ ```
107
+
108
+ Update rules in the repo — all users get the changes automatically within 5 minutes (cache TTL).
109
+
110
+ **To point to a custom repo:**
111
+ ```json
112
+ {
113
+ "mcpServers": {
114
+ "oneentry": {
115
+ "command": "npx",
116
+ "args": ["-y", "@oneentry/mcp-server"],
117
+ "env": {
118
+ "ONEENTRY_MCP_BASE_URL": "https://raw.githubusercontent.com/your-org/your-repo/main"
119
+ }
120
+ }
121
+ }
122
+ }
123
+ ```
124
+
125
+ ---
126
+
127
+ ## Local development
128
+
129
+ ```bash
130
+ cd mcp-server
131
+ npm install
132
+ npm run dev
133
+ ```
134
+
135
+ To point at local files during development:
136
+ ```bash
137
+ ONEENTRY_MCP_BASE_URL=file:///Users/you/claude-next npm run dev
138
+ ```
139
+
140
+ Build for production:
141
+ ```bash
142
+ npm run build
143
+ ```
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Fetches content from a remote URL (GitHub raw or any HTTP server).
3
+ * Caches results for TTL_MS to avoid hammering the server.
4
+ *
5
+ * Configure the base URL via env var:
6
+ * ONEENTRY_MCP_BASE_URL=https://raw.githubusercontent.com/your-org/your-repo/main
7
+ *
8
+ * Default points to the oneentry public repo.
9
+ */
10
+ export declare function fetchContent(path: string): Promise<string>;
11
+ export declare function clearCache(): void;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Fetches content from a remote URL (GitHub raw or any HTTP server).
3
+ * Caches results for TTL_MS to avoid hammering the server.
4
+ *
5
+ * Configure the base URL via env var:
6
+ * ONEENTRY_MCP_BASE_URL=https://raw.githubusercontent.com/your-org/your-repo/main
7
+ *
8
+ * Default points to the oneentry public repo.
9
+ */
10
+ const BASE_URL = process.env.ONEENTRY_MCP_BASE_URL ??
11
+ "https://raw.githubusercontent.com/ONEENTRY-PLATFORM/oneentry-sdk-rules/main";
12
+ const TTL_MS = 5 * 60 * 1000; // 5 minutes
13
+ const cache = new Map();
14
+ export async function fetchContent(path) {
15
+ const cached = cache.get(path);
16
+ if (cached && cached.expires > Date.now()) {
17
+ return cached.text;
18
+ }
19
+ const url = `${BASE_URL}/${path}`;
20
+ const res = await fetch(url, {
21
+ headers: {
22
+ "User-Agent": "oneentry-mcp-server/1.0",
23
+ },
24
+ });
25
+ if (!res.ok) {
26
+ throw new Error(`Failed to fetch content (${res.status}): ${url}`);
27
+ }
28
+ const text = await res.text();
29
+ cache.set(path, { text, expires: Date.now() + TTL_MS });
30
+ return text;
31
+ }
32
+ export function clearCache() {
33
+ cache.clear();
34
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,136 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
+ import { fetchContent } from "./content.js";
6
+ import { RULES, SKILLS } from "./registry.js";
7
+ const CLAUDE_MD_PATH = "CLAUDE.md";
8
+ // ---------------------------------------------------------------------------
9
+ // Server
10
+ // ---------------------------------------------------------------------------
11
+ const server = new Server({ name: "oneentry-sdk", version: "1.0.0" }, {
12
+ capabilities: {
13
+ resources: {},
14
+ prompts: {},
15
+ },
16
+ });
17
+ // ---------------------------------------------------------------------------
18
+ // Resources — rules + CLAUDE.md
19
+ // ---------------------------------------------------------------------------
20
+ server.setRequestHandler(ListResourcesRequestSchema, async () => ({
21
+ resources: [
22
+ {
23
+ uri: "oneentry://claude-md",
24
+ name: "OneEntry SDK — Main Instructions (CLAUDE.md)",
25
+ description: "Full system prompt with OneEntry SDK rules, patterns, anti-hallucination guidelines and module reference",
26
+ mimeType: "text/markdown",
27
+ },
28
+ ...RULES.map((rule) => ({
29
+ uri: `oneentry://rules/${rule.name}`,
30
+ name: rule.displayName,
31
+ description: rule.description,
32
+ mimeType: "text/markdown",
33
+ })),
34
+ ],
35
+ }));
36
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
37
+ const { uri } = request.params;
38
+ // CLAUDE.md
39
+ if (uri === "oneentry://claude-md") {
40
+ const text = await fetchContent(CLAUDE_MD_PATH);
41
+ return { contents: [{ uri, mimeType: "text/markdown", text }] };
42
+ }
43
+ // Rules
44
+ if (uri.startsWith("oneentry://rules/")) {
45
+ const name = uri.replace("oneentry://rules/", "");
46
+ const rule = RULES.find((r) => r.name === name);
47
+ if (!rule) {
48
+ throw new Error(`Unknown rule: ${name}`);
49
+ }
50
+ const text = await fetchContent(rule.path);
51
+ return { contents: [{ uri, mimeType: "text/markdown", text }] };
52
+ }
53
+ throw new Error(`Unknown resource URI: ${uri}`);
54
+ });
55
+ // ---------------------------------------------------------------------------
56
+ // Prompts — skills
57
+ // ---------------------------------------------------------------------------
58
+ server.setRequestHandler(ListPromptsRequestSchema, async () => ({
59
+ prompts: [
60
+ // Special prompt: load full context from CLAUDE.md
61
+ {
62
+ name: "oneentry-context",
63
+ description: "Load full OneEntry SDK context — system instructions, rules and anti-hallucination guidelines. Use this at the start of a session.",
64
+ arguments: [],
65
+ },
66
+ // All skills
67
+ ...SKILLS.map((skill) => ({
68
+ name: skill.name,
69
+ description: skill.description,
70
+ arguments: skill.hasArguments
71
+ ? [
72
+ {
73
+ name: "arguments",
74
+ description: skill.argumentDescription ?? "Optional arguments",
75
+ required: false,
76
+ },
77
+ ]
78
+ : [],
79
+ })),
80
+ ],
81
+ }));
82
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
83
+ const { name, arguments: args } = request.params;
84
+ // Load full CLAUDE.md as system context
85
+ if (name === "oneentry-context") {
86
+ const text = await fetchContent(CLAUDE_MD_PATH);
87
+ return {
88
+ description: "OneEntry SDK — full system context loaded",
89
+ messages: [
90
+ {
91
+ role: "user",
92
+ content: {
93
+ type: "text",
94
+ text: `The following are the complete instructions and rules for working with OneEntry SDK. Apply them to all subsequent code generation:\n\n${text}`,
95
+ },
96
+ },
97
+ ],
98
+ };
99
+ }
100
+ // Skills
101
+ const skill = SKILLS.find((s) => s.name === name);
102
+ if (!skill) {
103
+ throw new Error(`Unknown prompt: ${name}`);
104
+ }
105
+ let text = await fetchContent(skill.path);
106
+ // Replace $ARGUMENTS placeholder (used in inspect-api and create-page skills)
107
+ const userArguments = args?.["arguments"];
108
+ if (userArguments) {
109
+ text = text.replace(/\$ARGUMENTS/g, userArguments);
110
+ }
111
+ return {
112
+ description: skill.description,
113
+ messages: [
114
+ {
115
+ role: "user",
116
+ content: {
117
+ type: "text",
118
+ text,
119
+ },
120
+ },
121
+ ],
122
+ };
123
+ });
124
+ // ---------------------------------------------------------------------------
125
+ // Start
126
+ // ---------------------------------------------------------------------------
127
+ async function main() {
128
+ const transport = new StdioServerTransport();
129
+ await server.connect(transport);
130
+ // Log to stderr so it doesn't interfere with MCP stdio protocol
131
+ process.stderr.write("OneEntry MCP server running\n");
132
+ }
133
+ main().catch((err) => {
134
+ process.stderr.write(`Fatal error: ${err}\n`);
135
+ process.exit(1);
136
+ });
@@ -0,0 +1,15 @@
1
+ export interface Rule {
2
+ name: string;
3
+ displayName: string;
4
+ description: string;
5
+ path: string;
6
+ }
7
+ export interface Skill {
8
+ name: string;
9
+ description: string;
10
+ path: string;
11
+ hasArguments?: boolean;
12
+ argumentDescription?: string;
13
+ }
14
+ export declare const RULES: Rule[];
15
+ export declare const SKILLS: Skill[];
@@ -0,0 +1,157 @@
1
+ export const RULES = [
2
+ {
3
+ name: "forms",
4
+ displayName: "Forms & FormsData",
5
+ description: "Rules for working with OneEntry Forms API — getFormByMarker, postFormsData, formData types by field type",
6
+ path: ".claude/rules/forms.md",
7
+ },
8
+ {
9
+ name: "tokens",
10
+ displayName: "Tokens & Auth",
11
+ description: "Rules for auth tokens — makeUserApi, refreshToken, race condition handling, getNewToken",
12
+ path: ".claude/rules/tokens.md",
13
+ },
14
+ {
15
+ name: "attribute-values",
16
+ displayName: "AttributeValues",
17
+ description: "How to access attributeValues by type — image, text, list, date, timeInterval, etc.",
18
+ path: ".claude/rules/attribute-values.md",
19
+ },
20
+ {
21
+ name: "auth-provider",
22
+ displayName: "AuthProvider",
23
+ description: "Rules for auth/signUp — IAuthPostBody structure, notificationData, server actions",
24
+ path: ".claude/rules/auth-provider.md",
25
+ },
26
+ {
27
+ name: "nextjs-pages",
28
+ displayName: "Next.js Pages",
29
+ description: "Rules for Next.js pages with OneEntry — params as Promise, pageUrl vs route, localizeInfos",
30
+ path: ".claude/rules/nextjs-pages.md",
31
+ },
32
+ {
33
+ name: "server-actions",
34
+ displayName: "Server Actions",
35
+ description: "Rules for Next.js Server Actions with OneEntry — getApi() vs makeUserApi(), which methods need SA",
36
+ path: ".claude/rules/server-actions.md",
37
+ },
38
+ {
39
+ name: "orders",
40
+ displayName: "Orders & Payments",
41
+ description: "Rules for Orders and Payments — getAllOrdersStorage structure, createOrder, createSession, paymentUrl",
42
+ path: ".claude/rules/orders.md",
43
+ },
44
+ {
45
+ name: "attribute-sets",
46
+ displayName: "AttributeSets",
47
+ description: "Rules for AttributesSets — schema vs values, listTitles, additionalFields, validators",
48
+ path: ".claude/rules/attribute-sets.md",
49
+ },
50
+ {
51
+ name: "localization",
52
+ displayName: "Localization",
53
+ description: "Rules for localization — locale from params, langCode, localizeInfos, useParams in client components",
54
+ path: ".claude/rules/localization.md",
55
+ },
56
+ ];
57
+ export const SKILLS = [
58
+ {
59
+ name: "setup-oneentry",
60
+ description: "Initialize OneEntry SDK in a Next.js project — creates lib/oneentry.ts with singleton pattern, configures next.config.ts for images",
61
+ path: ".claude/skills/setup-oneentry/SKILL.md",
62
+ },
63
+ {
64
+ name: "create-page",
65
+ description: "Create a Next.js page with content from OneEntry CMS — getPageByUrl, getBlocksByPageUrl, localizeInfos",
66
+ path: ".claude/skills/create-page/SKILL.md",
67
+ hasArguments: true,
68
+ argumentDescription: "pageMarker — the pageUrl marker in OneEntry (e.g. 'home', 'about')",
69
+ },
70
+ {
71
+ name: "inspect-api",
72
+ description: "Read .env.local and execute curl requests to OneEntry API to get real markers, attributes and data structures before writing code",
73
+ path: ".claude/skills/inspect-api/SKILL.md",
74
+ hasArguments: true,
75
+ argumentDescription: "pages|menus|forms|products|product-statuses|auth-providers|all",
76
+ },
77
+ {
78
+ name: "create-auth",
79
+ description: "Create auth/registration form with OneEntry AuthProvider — Server Actions, dynamic fields from Forms API, token sync",
80
+ path: ".claude/skills/create-auth/SKILL.md",
81
+ },
82
+ {
83
+ name: "create-product-list",
84
+ description: "Create product catalog with URL-based filters, infinite scroll, Server Actions, FilterPanel and ProductGrid",
85
+ path: ".claude/skills/create-product-list/SKILL.md",
86
+ },
87
+ {
88
+ name: "create-product-card",
89
+ description: "Create a single product page with getProductById, attribute extraction, image gallery, price block, related products",
90
+ path: ".claude/skills/create-product-card/SKILL.md",
91
+ },
92
+ {
93
+ name: "create-cart-manager",
94
+ description: "Create cart manager — Redux slice + redux-persist, add/remove/quantity, StoreProvider",
95
+ path: ".claude/skills/create-cart-manager/SKILL.md",
96
+ },
97
+ {
98
+ name: "create-favorites",
99
+ description: "Create favorites list — Redux slice + persist, stores only product IDs, button and page with API data loading",
100
+ path: ".claude/skills/create-favorites/SKILL.md",
101
+ },
102
+ {
103
+ name: "create-filter-panel",
104
+ description: "Create filter panel — price, color, availability + FilterContext + Apply/Reset buttons",
105
+ path: ".claude/skills/create-filter-panel/SKILL.md",
106
+ },
107
+ {
108
+ name: "create-checkout",
109
+ description: "Create checkout form — fields from Forms API, timeInterval delivery slots, one makeUserApi for createOrder + createSession, redirect to payment",
110
+ path: ".claude/skills/create-checkout/SKILL.md",
111
+ },
112
+ {
113
+ name: "create-orders-list",
114
+ description: "Create user orders list — load via all storages, one makeUserApi, client pagination, token race condition protection",
115
+ path: ".claude/skills/create-orders-list/SKILL.md",
116
+ },
117
+ {
118
+ name: "create-profile",
119
+ description: "Create user profile page — Users API fields, data update, token race condition handling",
120
+ path: ".claude/skills/create-profile/SKILL.md",
121
+ },
122
+ {
123
+ name: "create-form",
124
+ description: "Create dynamic form with fields from OneEntry Forms API — all field types including spam (reCAPTCHA)",
125
+ path: ".claude/skills/create-form/SKILL.md",
126
+ },
127
+ {
128
+ name: "create-reviews",
129
+ description: "Create reviews with hierarchy — FormData, isNested, entityIdentifier, replayTo",
130
+ path: ".claude/skills/create-reviews/SKILL.md",
131
+ },
132
+ {
133
+ name: "create-menu",
134
+ description: "Create navigation menu with submenu support — hierarchy via parentId, URL normalization",
135
+ path: ".claude/skills/create-menu/SKILL.md",
136
+ },
137
+ {
138
+ name: "create-search",
139
+ description: "Create search bar — 300ms debounce, Server Action, dropdown results",
140
+ path: ".claude/skills/create-search/SKILL.md",
141
+ },
142
+ {
143
+ name: "create-locale-switcher",
144
+ description: "Create locale switcher — loads locales via getLocales(), builds links to current page with different locale segment",
145
+ path: ".claude/skills/create-locale-switcher/SKILL.md",
146
+ },
147
+ {
148
+ name: "create-server-action",
149
+ description: "Create Next.js Server Action for OneEntry — getApi() for public methods, makeUserApi() for user-authorized methods",
150
+ path: ".claude/skills/create-server-action/SKILL.md",
151
+ },
152
+ {
153
+ name: "create-subscription-events",
154
+ description: "Create product price/availability subscription — Events.subscribeByMarker / unsubscribeByMarker",
155
+ path: ".claude/skills/create-subscription-events/SKILL.md",
156
+ },
157
+ ];
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@oneentry/mcp-server",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for OneEntry SDK — rules and skills for Claude Code",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "oneentry-mcp": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsx src/index.ts",
13
+ "start": "node dist/index.js"
14
+ },
15
+ "dependencies": {
16
+ "@modelcontextprotocol/sdk": "^1.10.1",
17
+ "zod": "^3.24.1"
18
+ },
19
+ "devDependencies": {
20
+ "@types/node": "^22.0.0",
21
+ "tsx": "^4.19.0",
22
+ "typescript": "^5.7.0"
23
+ },
24
+ "engines": {
25
+ "node": ">=18"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ }
30
+ }
package/src/content.ts ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Fetches content from a remote URL (GitHub raw or any HTTP server).
3
+ * Caches results for TTL_MS to avoid hammering the server.
4
+ *
5
+ * Configure the base URL via env var:
6
+ * ONEENTRY_MCP_BASE_URL=https://raw.githubusercontent.com/your-org/your-repo/main
7
+ *
8
+ * Default points to the oneentry public repo.
9
+ */
10
+
11
+ const BASE_URL =
12
+ process.env.ONEENTRY_MCP_BASE_URL ??
13
+ "https://raw.githubusercontent.com/ONEENTRY-PLATFORM/oneentry-sdk-rules/main";
14
+
15
+ const TTL_MS = 5 * 60 * 1000; // 5 minutes
16
+
17
+ interface CacheEntry {
18
+ text: string;
19
+ expires: number;
20
+ }
21
+
22
+ const cache = new Map<string, CacheEntry>();
23
+
24
+ export async function fetchContent(path: string): Promise<string> {
25
+ const cached = cache.get(path);
26
+ if (cached && cached.expires > Date.now()) {
27
+ return cached.text;
28
+ }
29
+
30
+ const url = `${BASE_URL}/${path}`;
31
+ const res = await fetch(url, {
32
+ headers: {
33
+ "User-Agent": "oneentry-mcp-server/1.0",
34
+ },
35
+ });
36
+
37
+ if (!res.ok) {
38
+ throw new Error(`Failed to fetch content (${res.status}): ${url}`);
39
+ }
40
+
41
+ const text = await res.text();
42
+ cache.set(path, { text, expires: Date.now() + TTL_MS });
43
+ return text;
44
+ }
45
+
46
+ export function clearCache(): void {
47
+ cache.clear();
48
+ }
package/src/index.ts ADDED
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import {
5
+ ListResourcesRequestSchema,
6
+ ReadResourceRequestSchema,
7
+ ListPromptsRequestSchema,
8
+ GetPromptRequestSchema,
9
+ } from "@modelcontextprotocol/sdk/types.js";
10
+ import { fetchContent } from "./content.js";
11
+ import { RULES, SKILLS } from "./registry.js";
12
+
13
+ const CLAUDE_MD_PATH = "CLAUDE.md";
14
+
15
+ // ---------------------------------------------------------------------------
16
+ // Server
17
+ // ---------------------------------------------------------------------------
18
+
19
+ const server = new Server(
20
+ { name: "oneentry-sdk", version: "1.0.0" },
21
+ {
22
+ capabilities: {
23
+ resources: {},
24
+ prompts: {},
25
+ },
26
+ }
27
+ );
28
+
29
+ // ---------------------------------------------------------------------------
30
+ // Resources — rules + CLAUDE.md
31
+ // ---------------------------------------------------------------------------
32
+
33
+ server.setRequestHandler(ListResourcesRequestSchema, async () => ({
34
+ resources: [
35
+ {
36
+ uri: "oneentry://claude-md",
37
+ name: "OneEntry SDK — Main Instructions (CLAUDE.md)",
38
+ description:
39
+ "Full system prompt with OneEntry SDK rules, patterns, anti-hallucination guidelines and module reference",
40
+ mimeType: "text/markdown",
41
+ },
42
+ ...RULES.map((rule) => ({
43
+ uri: `oneentry://rules/${rule.name}`,
44
+ name: rule.displayName,
45
+ description: rule.description,
46
+ mimeType: "text/markdown",
47
+ })),
48
+ ],
49
+ }));
50
+
51
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
52
+ const { uri } = request.params;
53
+
54
+ // CLAUDE.md
55
+ if (uri === "oneentry://claude-md") {
56
+ const text = await fetchContent(CLAUDE_MD_PATH);
57
+ return { contents: [{ uri, mimeType: "text/markdown", text }] };
58
+ }
59
+
60
+ // Rules
61
+ if (uri.startsWith("oneentry://rules/")) {
62
+ const name = uri.replace("oneentry://rules/", "");
63
+ const rule = RULES.find((r) => r.name === name);
64
+ if (!rule) {
65
+ throw new Error(`Unknown rule: ${name}`);
66
+ }
67
+ const text = await fetchContent(rule.path);
68
+ return { contents: [{ uri, mimeType: "text/markdown", text }] };
69
+ }
70
+
71
+ throw new Error(`Unknown resource URI: ${uri}`);
72
+ });
73
+
74
+ // ---------------------------------------------------------------------------
75
+ // Prompts — skills
76
+ // ---------------------------------------------------------------------------
77
+
78
+ server.setRequestHandler(ListPromptsRequestSchema, async () => ({
79
+ prompts: [
80
+ // Special prompt: load full context from CLAUDE.md
81
+ {
82
+ name: "oneentry-context",
83
+ description:
84
+ "Load full OneEntry SDK context — system instructions, rules and anti-hallucination guidelines. Use this at the start of a session.",
85
+ arguments: [],
86
+ },
87
+ // All skills
88
+ ...SKILLS.map((skill) => ({
89
+ name: skill.name,
90
+ description: skill.description,
91
+ arguments: skill.hasArguments
92
+ ? [
93
+ {
94
+ name: "arguments",
95
+ description: skill.argumentDescription ?? "Optional arguments",
96
+ required: false,
97
+ },
98
+ ]
99
+ : [],
100
+ })),
101
+ ],
102
+ }));
103
+
104
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
105
+ const { name, arguments: args } = request.params;
106
+
107
+ // Load full CLAUDE.md as system context
108
+ if (name === "oneentry-context") {
109
+ const text = await fetchContent(CLAUDE_MD_PATH);
110
+ return {
111
+ description: "OneEntry SDK — full system context loaded",
112
+ messages: [
113
+ {
114
+ role: "user" as const,
115
+ content: {
116
+ type: "text" as const,
117
+ text: `The following are the complete instructions and rules for working with OneEntry SDK. Apply them to all subsequent code generation:\n\n${text}`,
118
+ },
119
+ },
120
+ ],
121
+ };
122
+ }
123
+
124
+ // Skills
125
+ const skill = SKILLS.find((s) => s.name === name);
126
+ if (!skill) {
127
+ throw new Error(`Unknown prompt: ${name}`);
128
+ }
129
+
130
+ let text = await fetchContent(skill.path);
131
+
132
+ // Replace $ARGUMENTS placeholder (used in inspect-api and create-page skills)
133
+ const userArguments = args?.["arguments"];
134
+ if (userArguments) {
135
+ text = text.replace(/\$ARGUMENTS/g, userArguments);
136
+ }
137
+
138
+ return {
139
+ description: skill.description,
140
+ messages: [
141
+ {
142
+ role: "user" as const,
143
+ content: {
144
+ type: "text" as const,
145
+ text,
146
+ },
147
+ },
148
+ ],
149
+ };
150
+ });
151
+
152
+ // ---------------------------------------------------------------------------
153
+ // Start
154
+ // ---------------------------------------------------------------------------
155
+
156
+ async function main() {
157
+ const transport = new StdioServerTransport();
158
+ await server.connect(transport);
159
+ // Log to stderr so it doesn't interfere with MCP stdio protocol
160
+ process.stderr.write("OneEntry MCP server running\n");
161
+ }
162
+
163
+ main().catch((err) => {
164
+ process.stderr.write(`Fatal error: ${err}\n`);
165
+ process.exit(1);
166
+ });
@@ -0,0 +1,173 @@
1
+ export interface Rule {
2
+ name: string;
3
+ displayName: string;
4
+ description: string;
5
+ path: string;
6
+ }
7
+
8
+ export interface Skill {
9
+ name: string;
10
+ description: string;
11
+ path: string;
12
+ hasArguments?: boolean;
13
+ argumentDescription?: string;
14
+ }
15
+
16
+ export const RULES: Rule[] = [
17
+ {
18
+ name: "forms",
19
+ displayName: "Forms & FormsData",
20
+ description: "Rules for working with OneEntry Forms API — getFormByMarker, postFormsData, formData types by field type",
21
+ path: ".claude/rules/forms.md",
22
+ },
23
+ {
24
+ name: "tokens",
25
+ displayName: "Tokens & Auth",
26
+ description: "Rules for auth tokens — makeUserApi, refreshToken, race condition handling, getNewToken",
27
+ path: ".claude/rules/tokens.md",
28
+ },
29
+ {
30
+ name: "attribute-values",
31
+ displayName: "AttributeValues",
32
+ description: "How to access attributeValues by type — image, text, list, date, timeInterval, etc.",
33
+ path: ".claude/rules/attribute-values.md",
34
+ },
35
+ {
36
+ name: "auth-provider",
37
+ displayName: "AuthProvider",
38
+ description: "Rules for auth/signUp — IAuthPostBody structure, notificationData, server actions",
39
+ path: ".claude/rules/auth-provider.md",
40
+ },
41
+ {
42
+ name: "nextjs-pages",
43
+ displayName: "Next.js Pages",
44
+ description: "Rules for Next.js pages with OneEntry — params as Promise, pageUrl vs route, localizeInfos",
45
+ path: ".claude/rules/nextjs-pages.md",
46
+ },
47
+ {
48
+ name: "server-actions",
49
+ displayName: "Server Actions",
50
+ description: "Rules for Next.js Server Actions with OneEntry — getApi() vs makeUserApi(), which methods need SA",
51
+ path: ".claude/rules/server-actions.md",
52
+ },
53
+ {
54
+ name: "orders",
55
+ displayName: "Orders & Payments",
56
+ description: "Rules for Orders and Payments — getAllOrdersStorage structure, createOrder, createSession, paymentUrl",
57
+ path: ".claude/rules/orders.md",
58
+ },
59
+ {
60
+ name: "attribute-sets",
61
+ displayName: "AttributeSets",
62
+ description: "Rules for AttributesSets — schema vs values, listTitles, additionalFields, validators",
63
+ path: ".claude/rules/attribute-sets.md",
64
+ },
65
+ {
66
+ name: "localization",
67
+ displayName: "Localization",
68
+ description: "Rules for localization — locale from params, langCode, localizeInfos, useParams in client components",
69
+ path: ".claude/rules/localization.md",
70
+ },
71
+ ];
72
+
73
+ export const SKILLS: Skill[] = [
74
+ {
75
+ name: "setup-oneentry",
76
+ description: "Initialize OneEntry SDK in a Next.js project — creates lib/oneentry.ts with singleton pattern, configures next.config.ts for images",
77
+ path: ".claude/skills/setup-oneentry/SKILL.md",
78
+ },
79
+ {
80
+ name: "create-page",
81
+ description: "Create a Next.js page with content from OneEntry CMS — getPageByUrl, getBlocksByPageUrl, localizeInfos",
82
+ path: ".claude/skills/create-page/SKILL.md",
83
+ hasArguments: true,
84
+ argumentDescription: "pageMarker — the pageUrl marker in OneEntry (e.g. 'home', 'about')",
85
+ },
86
+ {
87
+ name: "inspect-api",
88
+ description: "Read .env.local and execute curl requests to OneEntry API to get real markers, attributes and data structures before writing code",
89
+ path: ".claude/skills/inspect-api/SKILL.md",
90
+ hasArguments: true,
91
+ argumentDescription: "pages|menus|forms|products|product-statuses|auth-providers|all",
92
+ },
93
+ {
94
+ name: "create-auth",
95
+ description: "Create auth/registration form with OneEntry AuthProvider — Server Actions, dynamic fields from Forms API, token sync",
96
+ path: ".claude/skills/create-auth/SKILL.md",
97
+ },
98
+ {
99
+ name: "create-product-list",
100
+ description: "Create product catalog with URL-based filters, infinite scroll, Server Actions, FilterPanel and ProductGrid",
101
+ path: ".claude/skills/create-product-list/SKILL.md",
102
+ },
103
+ {
104
+ name: "create-product-card",
105
+ description: "Create a single product page with getProductById, attribute extraction, image gallery, price block, related products",
106
+ path: ".claude/skills/create-product-card/SKILL.md",
107
+ },
108
+ {
109
+ name: "create-cart-manager",
110
+ description: "Create cart manager — Redux slice + redux-persist, add/remove/quantity, StoreProvider",
111
+ path: ".claude/skills/create-cart-manager/SKILL.md",
112
+ },
113
+ {
114
+ name: "create-favorites",
115
+ description: "Create favorites list — Redux slice + persist, stores only product IDs, button and page with API data loading",
116
+ path: ".claude/skills/create-favorites/SKILL.md",
117
+ },
118
+ {
119
+ name: "create-filter-panel",
120
+ description: "Create filter panel — price, color, availability + FilterContext + Apply/Reset buttons",
121
+ path: ".claude/skills/create-filter-panel/SKILL.md",
122
+ },
123
+ {
124
+ name: "create-checkout",
125
+ description: "Create checkout form — fields from Forms API, timeInterval delivery slots, one makeUserApi for createOrder + createSession, redirect to payment",
126
+ path: ".claude/skills/create-checkout/SKILL.md",
127
+ },
128
+ {
129
+ name: "create-orders-list",
130
+ description: "Create user orders list — load via all storages, one makeUserApi, client pagination, token race condition protection",
131
+ path: ".claude/skills/create-orders-list/SKILL.md",
132
+ },
133
+ {
134
+ name: "create-profile",
135
+ description: "Create user profile page — Users API fields, data update, token race condition handling",
136
+ path: ".claude/skills/create-profile/SKILL.md",
137
+ },
138
+ {
139
+ name: "create-form",
140
+ description: "Create dynamic form with fields from OneEntry Forms API — all field types including spam (reCAPTCHA)",
141
+ path: ".claude/skills/create-form/SKILL.md",
142
+ },
143
+ {
144
+ name: "create-reviews",
145
+ description: "Create reviews with hierarchy — FormData, isNested, entityIdentifier, replayTo",
146
+ path: ".claude/skills/create-reviews/SKILL.md",
147
+ },
148
+ {
149
+ name: "create-menu",
150
+ description: "Create navigation menu with submenu support — hierarchy via parentId, URL normalization",
151
+ path: ".claude/skills/create-menu/SKILL.md",
152
+ },
153
+ {
154
+ name: "create-search",
155
+ description: "Create search bar — 300ms debounce, Server Action, dropdown results",
156
+ path: ".claude/skills/create-search/SKILL.md",
157
+ },
158
+ {
159
+ name: "create-locale-switcher",
160
+ description: "Create locale switcher — loads locales via getLocales(), builds links to current page with different locale segment",
161
+ path: ".claude/skills/create-locale-switcher/SKILL.md",
162
+ },
163
+ {
164
+ name: "create-server-action",
165
+ description: "Create Next.js Server Action for OneEntry — getApi() for public methods, makeUserApi() for user-authorized methods",
166
+ path: ".claude/skills/create-server-action/SKILL.md",
167
+ },
168
+ {
169
+ name: "create-subscription-events",
170
+ description: "Create product price/availability subscription — Events.subscribeByMarker / unsubscribeByMarker",
171
+ path: ".claude/skills/create-subscription-events/SKILL.md",
172
+ },
173
+ ];
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "declaration": true,
12
+ "types": ["node"]
13
+ },
14
+ "include": ["src"]
15
+ }