snapy-mcp 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.
Files changed (3) hide show
  1. package/README.md +36 -0
  2. package/index.js +75 -0
  3. package/package.json +25 -0
package/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # snapy-mcp
2
+
3
+ An MCP server that gives an AI assistant (Claude and other MCP clients) a `publish` tool. The assistant can publish text or HTML to snapy and get back a shareable link.
4
+
5
+ ## Use it
6
+
7
+ Add this to your MCP client config (for example Claude Desktop):
8
+
9
+ ```json
10
+ {
11
+ "mcpServers": {
12
+ "snapy": {
13
+ "command": "npx",
14
+ "args": ["-y", "snapy-mcp"],
15
+ "env": { "SNAPY_API_KEY": "snapy_live_..." }
16
+ }
17
+ }
18
+ }
19
+ ```
20
+
21
+ Or run it directly from this folder:
22
+
23
+ ```
24
+ npm install
25
+ node index.js
26
+ ```
27
+
28
+ The tool calls the public snapy publish API at `https://api.snapy.host`. Set `SNAPY_API` to override.
29
+
30
+ ## Tool
31
+
32
+ - **publish** — args: `content` (required text/HTML), `name` (optional link name), `filename` (optional, default index.html). Returns the live link and a private analytics link.
33
+
34
+ ## The API key
35
+
36
+ Publishing a **web page** needs an API key. Create one in your snapy dashboard under **API keys** and pass it as `SNAPY_API_KEY`. Plain text formats (`.txt`, `.md`, `.csv`, `.json`) publish without one, so the connector works with no setup and gains page publishing when a key is present.
package/index.js ADDED
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env node
2
+ // snapy MCP server: gives an assistant (Claude, etc.) a "publish" tool that uploads
3
+ // text or HTML to snapy and returns a shareable link. Talks to the public publish API.
4
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
7
+
8
+ const API = process.env.SNAPY_API || "https://api.snapy.host";
9
+
10
+ // Publishing a web page needs an API key; plain text formats do not. Left optional
11
+ // so the connector still works with no setup at all, and gains page publishing the
12
+ // moment a key is present. Create one in the Snapy dashboard under API keys.
13
+ const API_KEY = process.env.SNAPY_API_KEY || "";
14
+
15
+ const server = new Server(
16
+ { name: "snapy", version: "1.0.0" },
17
+ { capabilities: { tools: {} } }
18
+ );
19
+
20
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
21
+ tools: [
22
+ {
23
+ name: "publish",
24
+ description:
25
+ "Publish text or HTML content to snapy and get back a shareable link that opens in any browser. Use this to host a page or file you created and return the link.",
26
+ inputSchema: {
27
+ type: "object",
28
+ properties: {
29
+ content: { type: "string", description: "The text or HTML to publish." },
30
+ name: { type: "string", description: "Optional custom link name (the subdomain)." },
31
+ filename: { type: "string", description: "Optional file name, defaults to index.html." },
32
+ },
33
+ required: ["content"],
34
+ },
35
+ },
36
+ ],
37
+ }));
38
+
39
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
40
+ if (req.params.name !== "publish") {
41
+ return { content: [{ type: "text", text: "Unknown tool" }], isError: true };
42
+ }
43
+ const { content, name, filename } = req.params.arguments || {};
44
+ try {
45
+ const headers = { "content-type": "application/json" };
46
+ if (API_KEY) headers.authorization = `Bearer ${API_KEY}`;
47
+ const res = await fetch(`${API}/api/publish`, {
48
+ method: "POST",
49
+ headers,
50
+ body: JSON.stringify({ content, name, filename }),
51
+ });
52
+ const data = await res.json();
53
+ if (!res.ok) {
54
+ // The most likely failure by far: publishing a page with no key set. The API's
55
+ // own message is clearer than anything generic, so pass it through and add the
56
+ // one instruction it cannot know, which is where the key comes from.
57
+ const hint = !API_KEY && (res.status === 401 || res.status === 403)
58
+ ? " Set SNAPY_API_KEY to publish a web page: create a key in your Snapy dashboard under API keys."
59
+ : "";
60
+ return {
61
+ content: [{ type: "text", text: "snapy error: " + (data.error || res.status) + hint }],
62
+ isError: true,
63
+ };
64
+ }
65
+ return {
66
+ content: [{ type: "text", text: `Published. Link: ${data.url}\nPrivate analytics: ${data.stats_url}` }],
67
+ };
68
+ } catch (e) {
69
+ return { content: [{ type: "text", text: "Request failed: " + e.message }], isError: true };
70
+ }
71
+ });
72
+
73
+ const transport = new StdioServerTransport();
74
+ await server.connect(transport);
75
+ console.error("snapy MCP server running on stdio");
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "snapy-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP server to publish files and pages to snapy and get a shareable link.",
5
+ "homepage": "https://snapy.host/integrations/mcp",
6
+ "keywords": [
7
+ "mcp",
8
+ "modelcontextprotocol",
9
+ "snapy",
10
+ "publish",
11
+ "hosting",
12
+ "claude",
13
+ "ai"
14
+ ],
15
+ "type": "module",
16
+ "bin": {
17
+ "snapy-mcp": "index.js"
18
+ },
19
+ "engines": {
20
+ "node": ">=18"
21
+ },
22
+ "dependencies": {
23
+ "@modelcontextprotocol/sdk": "^1.0.0"
24
+ }
25
+ }