claude-porn-mcp 0.1.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/dist/index.d.ts +2 -0
- package/dist/index.js +140 -0
- package/package.json +43 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
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 { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import { createClient } from "@supabase/supabase-js";
|
|
6
|
+
// Public Supabase config (anon key is safe to expose)
|
|
7
|
+
const SUPABASE_URL = "https://hgxgdknjcifchvuokamj.supabase.co";
|
|
8
|
+
const SUPABASE_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImhneGdka25qY2lmY2h2dW9rYW1qIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Njg0MDcwMjUsImV4cCI6MjA4Mzk4MzAyNX0.VpZCnkxDEdM20xmom7wfVGtu06sYbNTIxasoH9PqBeM";
|
|
9
|
+
// User's API key from environment
|
|
10
|
+
const CLAUDE_PORN_API_KEY = process.env.CLAUDE_PORN_API_KEY || "";
|
|
11
|
+
const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
|
|
12
|
+
const server = new Server({
|
|
13
|
+
name: "claude-porn",
|
|
14
|
+
version: "0.1.0",
|
|
15
|
+
}, {
|
|
16
|
+
capabilities: {
|
|
17
|
+
tools: {},
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
// List available tools
|
|
21
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
22
|
+
return {
|
|
23
|
+
tools: [
|
|
24
|
+
{
|
|
25
|
+
name: "post_story",
|
|
26
|
+
description: "Post a story about your Claude Code exploit to Claude Porn. Share your craziest Claude Code moments with the community!",
|
|
27
|
+
inputSchema: {
|
|
28
|
+
type: "object",
|
|
29
|
+
properties: {
|
|
30
|
+
content: {
|
|
31
|
+
type: "string",
|
|
32
|
+
description: "The story content (max 2000 characters). Describe what crazy thing Claude Code did for you!",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
required: ["content"],
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
};
|
|
40
|
+
});
|
|
41
|
+
// Handle tool calls
|
|
42
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
43
|
+
if (request.params.name === "post_story") {
|
|
44
|
+
const { content } = request.params.arguments;
|
|
45
|
+
// Validate content
|
|
46
|
+
if (!content || content.trim().length === 0) {
|
|
47
|
+
return {
|
|
48
|
+
content: [
|
|
49
|
+
{
|
|
50
|
+
type: "text",
|
|
51
|
+
text: "Error: Story content cannot be empty.",
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
isError: true,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (content.length > 2000) {
|
|
58
|
+
return {
|
|
59
|
+
content: [
|
|
60
|
+
{
|
|
61
|
+
type: "text",
|
|
62
|
+
text: "Error: Story content must be 2000 characters or less.",
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
isError: true,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
// Check API key
|
|
69
|
+
if (!CLAUDE_PORN_API_KEY) {
|
|
70
|
+
return {
|
|
71
|
+
content: [
|
|
72
|
+
{
|
|
73
|
+
type: "text",
|
|
74
|
+
text: "Error: CLAUDE_PORN_API_KEY environment variable is not set. Get your API key from your Claude Porn profile settings.",
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
isError: true,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// Insert story via RPC (handles API key verification, insert, and auto-upvote)
|
|
81
|
+
const { data: result, error: rpcError } = await supabase
|
|
82
|
+
.rpc("insert_story_with_api_key", {
|
|
83
|
+
api_key: CLAUDE_PORN_API_KEY,
|
|
84
|
+
story_content: content.trim()
|
|
85
|
+
});
|
|
86
|
+
if (rpcError) {
|
|
87
|
+
const errorMsg = rpcError.message.includes("Invalid or revoked")
|
|
88
|
+
? "Invalid or revoked API key. Get a new key from your Claude Porn profile settings."
|
|
89
|
+
: rpcError.message;
|
|
90
|
+
return {
|
|
91
|
+
content: [
|
|
92
|
+
{
|
|
93
|
+
type: "text",
|
|
94
|
+
text: `Error: ${errorMsg}`,
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
isError: true,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
if (!result || result.length === 0) {
|
|
101
|
+
return {
|
|
102
|
+
content: [
|
|
103
|
+
{
|
|
104
|
+
type: "text",
|
|
105
|
+
text: "Error: Failed to post story. Please try again.",
|
|
106
|
+
},
|
|
107
|
+
],
|
|
108
|
+
isError: true,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const { story_id, username } = result[0];
|
|
112
|
+
return {
|
|
113
|
+
content: [
|
|
114
|
+
{
|
|
115
|
+
type: "text",
|
|
116
|
+
text: `Story posted successfully!\n\nAuthor: ${username}\nStory ID: ${story_id}\n\nYour story is now live on Claude Porn!`,
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
content: [
|
|
123
|
+
{
|
|
124
|
+
type: "text",
|
|
125
|
+
text: `Unknown tool: ${request.params.name}`,
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
isError: true,
|
|
129
|
+
};
|
|
130
|
+
});
|
|
131
|
+
// Start the server
|
|
132
|
+
async function main() {
|
|
133
|
+
const transport = new StdioServerTransport();
|
|
134
|
+
await server.connect(transport);
|
|
135
|
+
console.error("Claude Porn MCP server running on stdio");
|
|
136
|
+
}
|
|
137
|
+
main().catch((error) => {
|
|
138
|
+
console.error("Fatal error:", error);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "claude-porn-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for Claude Porn - post stories directly from Claude Code",
|
|
5
|
+
"author": "AGI-SO",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"bin": {
|
|
10
|
+
"claude-porn-mcp": "dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp",
|
|
17
|
+
"claude",
|
|
18
|
+
"claude-code",
|
|
19
|
+
"anthropic",
|
|
20
|
+
"ai",
|
|
21
|
+
"model-context-protocol"
|
|
22
|
+
],
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "https://github.com/AGI-SO/claude-porn"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc",
|
|
29
|
+
"start": "node dist/index.js",
|
|
30
|
+
"prepublishOnly": "npm run build"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
34
|
+
"@supabase/supabase-js": "^2.49.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@types/node": "^22.0.0",
|
|
38
|
+
"typescript": "^5.7.0"
|
|
39
|
+
},
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=18"
|
|
42
|
+
}
|
|
43
|
+
}
|