@promptforge/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 +84 -0
- package/index.js +168 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# PromptForge MCP Server
|
|
2
|
+
|
|
3
|
+
Search and retrieve AI prompts from [PromptForge](https://promptforge-rose.vercel.app) using any MCP-compatible client — Claude Desktop, Claude Code, Cursor, VS Code, ChatGPT, opencode, and more.
|
|
4
|
+
|
|
5
|
+
## Tools
|
|
6
|
+
|
|
7
|
+
| Tool | Description |
|
|
8
|
+
|------|-------------|
|
|
9
|
+
| `search_prompts` | Search prompts by keyword, model, or category with pagination |
|
|
10
|
+
| `get_prompt` | Retrieve a full prompt by ID with content and metadata |
|
|
11
|
+
| `list_categories` | Browse all available categories |
|
|
12
|
+
| `get_trending` | Get currently trending prompts |
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
### Claude Desktop
|
|
17
|
+
|
|
18
|
+
Add to your `claude_desktop_config.json`:
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"mcpServers": {
|
|
23
|
+
"promptforge": {
|
|
24
|
+
"command": "npx",
|
|
25
|
+
"args": ["@promptforge/mcp-server"]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### opencode
|
|
32
|
+
|
|
33
|
+
Add to your `opencode.json`:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"mcpServers": {
|
|
38
|
+
"promptforge": {
|
|
39
|
+
"command": "npx",
|
|
40
|
+
"args": ["@promptforge/mcp-server"]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### VS Code / Cursor
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"mcpServers": {
|
|
51
|
+
"promptforge": {
|
|
52
|
+
"command": "npx",
|
|
53
|
+
"args": ["@promptforge/mcp-server"]
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Run directly
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npx @promptforge/mcp-server
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Usage Examples
|
|
66
|
+
|
|
67
|
+
Once connected, ask your AI assistant:
|
|
68
|
+
|
|
69
|
+
- *"Search PromptForge for prompts about React hooks"*
|
|
70
|
+
- *"Find trending ChatGPT prompts for copywriting"*
|
|
71
|
+
- *"Get the prompt with ID abc-123 and show me the full content"*
|
|
72
|
+
- *"What categories are available on PromptForge?"*
|
|
73
|
+
|
|
74
|
+
## Development
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
cd mcp-server
|
|
78
|
+
npm install
|
|
79
|
+
node index.js
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
MIT
|
package/index.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import {
|
|
6
|
+
CallToolRequestSchema,
|
|
7
|
+
ListToolsRequestSchema,
|
|
8
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
9
|
+
|
|
10
|
+
const BASE_URL = process.env.PROMPT_FORGE_URL || "https://promptforge-rose.vercel.app";
|
|
11
|
+
|
|
12
|
+
const server = new Server(
|
|
13
|
+
{ name: "promptforge-mcp", version: "1.0.0" },
|
|
14
|
+
{ capabilities: { tools: {} } }
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
async function fetchApi(path) {
|
|
18
|
+
const res = await fetch(`${BASE_URL}${path}`);
|
|
19
|
+
if (!res.ok) throw new Error(`API error: ${res.status}`);
|
|
20
|
+
return res.json();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function formatPrompt(p) {
|
|
24
|
+
const stats = p.stats || {};
|
|
25
|
+
const author = p.author || {};
|
|
26
|
+
const category = p.category || null;
|
|
27
|
+
return {
|
|
28
|
+
id: p.id,
|
|
29
|
+
title: p.title,
|
|
30
|
+
description: p.description || "",
|
|
31
|
+
model: p.model || "any",
|
|
32
|
+
author: author.displayName || author.username || "anonymous",
|
|
33
|
+
category: category?.name || null,
|
|
34
|
+
tags: (p.tags || []).map((t) => t.name),
|
|
35
|
+
stats: {
|
|
36
|
+
upvotes: stats.upvotes || 0,
|
|
37
|
+
saves: stats.saves || 0,
|
|
38
|
+
views: stats.views || 0,
|
|
39
|
+
},
|
|
40
|
+
url: `${BASE_URL}/prompts/${p.id}`,
|
|
41
|
+
created: p.createdAt,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
46
|
+
tools: [
|
|
47
|
+
{
|
|
48
|
+
name: "search_prompts",
|
|
49
|
+
description: "Search the PromptForge library for AI prompts by keyword, model, or category",
|
|
50
|
+
inputSchema: {
|
|
51
|
+
type: "object",
|
|
52
|
+
properties: {
|
|
53
|
+
q: { type: "string", description: "Search query (keyword, topic, or use case)" },
|
|
54
|
+
model: { type: "string", description: "Filter by AI model: chatgpt, claude, gemini, midjourney, dall-e, gpt-4" },
|
|
55
|
+
category: { type: "string", description: "Filter by category slug: coding, seo, marketing, copywriting, etc." },
|
|
56
|
+
sort: { type: "string", enum: ["trending", "newest", "most-upvoted", "most-saved"], default: "trending" },
|
|
57
|
+
limit: { type: "number", default: 10, description: "Number of results (max 50)" },
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
name: "get_prompt",
|
|
63
|
+
description: "Get a specific prompt by ID with full content",
|
|
64
|
+
inputSchema: {
|
|
65
|
+
type: "object",
|
|
66
|
+
properties: {
|
|
67
|
+
id: { type: "string", description: "Prompt ID (UUID)" },
|
|
68
|
+
},
|
|
69
|
+
required: ["id"],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: "list_categories",
|
|
74
|
+
description: "List all prompt categories available on PromptForge",
|
|
75
|
+
inputSchema: {
|
|
76
|
+
type: "object",
|
|
77
|
+
properties: {},
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: "get_trending",
|
|
82
|
+
description: "Get currently trending prompts",
|
|
83
|
+
inputSchema: {
|
|
84
|
+
type: "object",
|
|
85
|
+
properties: {
|
|
86
|
+
limit: { type: "number", default: 10, description: "Number of results (max 50)" },
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
}));
|
|
92
|
+
|
|
93
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
94
|
+
const { name, arguments: args } = request.params;
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
switch (name) {
|
|
98
|
+
case "search_prompts": {
|
|
99
|
+
const params = new URLSearchParams();
|
|
100
|
+
if (args?.q) params.set("q", args.q);
|
|
101
|
+
if (args?.model) params.set("model", args.model);
|
|
102
|
+
if (args?.category) params.set("category", args.category);
|
|
103
|
+
if (args?.sort) params.set("sort", args.sort);
|
|
104
|
+
if (args?.limit) params.set("limit", Math.min(args.limit, 50).toString());
|
|
105
|
+
const data = await fetchApi(`/api/v1/prompts?${params}`);
|
|
106
|
+
const prompts = (data.data || []).map(formatPrompt);
|
|
107
|
+
return {
|
|
108
|
+
content: [{
|
|
109
|
+
type: "text",
|
|
110
|
+
text: JSON.stringify({ count: prompts.length, prompts, total: data.pagination?.total || 0 }, null, 2),
|
|
111
|
+
}],
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
case "get_prompt": {
|
|
116
|
+
if (!args?.id) throw new Error("Missing required parameter: id");
|
|
117
|
+
const data = await fetchApi(`/api/v1/prompts/${args.id}`);
|
|
118
|
+
return {
|
|
119
|
+
content: [{
|
|
120
|
+
type: "text",
|
|
121
|
+
text: JSON.stringify(formatPrompt(data), null, 2),
|
|
122
|
+
}],
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
case "list_categories": {
|
|
127
|
+
const data = await fetchApi("/api/categories");
|
|
128
|
+
return {
|
|
129
|
+
content: [{
|
|
130
|
+
type: "text",
|
|
131
|
+
text: JSON.stringify(data, null, 2),
|
|
132
|
+
}],
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
case "get_trending": {
|
|
137
|
+
const limit = args?.limit ? Math.min(args.limit, 50) : 10;
|
|
138
|
+
const data = await fetchApi(`/api/v1/prompts?sort=trending&limit=${limit}`);
|
|
139
|
+
const prompts = (data.data || []).map(formatPrompt);
|
|
140
|
+
return {
|
|
141
|
+
content: [{
|
|
142
|
+
type: "text",
|
|
143
|
+
text: JSON.stringify({ count: prompts.length, prompts }, null, 2),
|
|
144
|
+
}],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
default:
|
|
149
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
150
|
+
}
|
|
151
|
+
} catch (error) {
|
|
152
|
+
return {
|
|
153
|
+
content: [{ type: "text", text: `Error: ${error.message}` }],
|
|
154
|
+
isError: true,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
async function main() {
|
|
160
|
+
const transport = new StdioServerTransport();
|
|
161
|
+
await server.connect(transport);
|
|
162
|
+
console.error("PromptForge MCP server running on stdio");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
main().catch((error) => {
|
|
166
|
+
console.error("Server error:", error);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@promptforge/mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for PromptForge — search and retrieve AI prompts from any MCP-compatible client (Claude, Cursor, VS Code, ChatGPT)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"promptforge-mcp": "index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"index.js"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"mcp",
|
|
15
|
+
"promptforge",
|
|
16
|
+
"ai",
|
|
17
|
+
"prompts",
|
|
18
|
+
"modelcontextprotocol"
|
|
19
|
+
],
|
|
20
|
+
"publishConfig": { "access": "public" },
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"repository": {
|
|
23
|
+
"type": "git",
|
|
24
|
+
"url": "https://github.com/jordan-thirkle/promptforge.git",
|
|
25
|
+
"directory": "mcp-server"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@modelcontextprotocol/sdk": "^1.29.0"
|
|
29
|
+
}
|
|
30
|
+
}
|