@applogico/blipr-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.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +95 -0
  3. package/dist/index.js +104 -0
  4. package/package.json +45 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Applogico LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # @applogico/blipr-mcp
2
+
3
+ An [MCP](https://modelcontextprotocol.io) server that lets AI agents send
4
+ **[Blipr](https://blipr.dev)** push alerts to your phone. Your agent finishes a
5
+ long task, breaks a build, needs approval, or gets stuck — and it pages you.
6
+
7
+ It's a thin stdio client: your MCP host (Claude Code, Cursor, …) launches it,
8
+ the agent calls a tool, and this process makes one outbound HTTPS `POST` to your
9
+ Blipr server. No inbound socket, nothing to host.
10
+
11
+ ```
12
+ Claude Code ──stdio──► blipr-mcp ──POST /api/notify/<topic>──► blipr.dev ──APNs──► 📱
13
+ ```
14
+
15
+ ## Setup
16
+
17
+ No install needed — `npx` fetches it on demand. Point it at a Blipr server
18
+ (`blipr.dev` or your own self-hosted instance) and a default topic.
19
+
20
+ ### Claude Code
21
+
22
+ ```bash
23
+ claude mcp add blipr \
24
+ --env BLIPR_URL=https://blipr.dev \
25
+ --env BLIPR_TOPIC=agent-alerts \
26
+ -- npx -y @applogico/blipr-mcp
27
+ ```
28
+
29
+ ### Cursor / Claude Desktop / any MCP host (JSON)
30
+
31
+ ```jsonc
32
+ {
33
+ "mcpServers": {
34
+ "blipr": {
35
+ "command": "npx",
36
+ "args": ["-y", "@applogico/blipr-mcp"],
37
+ "env": {
38
+ "BLIPR_URL": "https://blipr.dev",
39
+ "BLIPR_TOPIC": "agent-alerts"
40
+ }
41
+ }
42
+ }
43
+ }
44
+ ```
45
+
46
+ Then subscribe to the same topic (`agent-alerts`) in the Blipr iOS app, and
47
+ you'll get the agent's pushes on your phone.
48
+
49
+ ## Configuration
50
+
51
+ | Env var | Default | Description |
52
+ | ------------- | ------------------- | ------------------------------------------------------ |
53
+ | `BLIPR_URL` | `https://blipr.dev` | Base URL of your Blipr server (hosted or self-hosted). |
54
+ | `BLIPR_TOPIC` | _(none)_ | Default topic used when a tool call omits one. |
55
+
56
+ ## Tools
57
+
58
+ ### `send_alert`
59
+
60
+ Send a push notification. Parameters:
61
+
62
+ - `message` (required) — the alert body.
63
+ - `title` — short bold title.
64
+ - `topic` — overrides `BLIPR_TOPIC`.
65
+ - `priority` — `1` silent · `2` low · `3` default · `4` time-sensitive (breaks
66
+ Focus) · `5` critical.
67
+ - `tags` — emoji shortcodes, e.g. `["warning"]`.
68
+ - `click` — URL opened when the notification is tapped.
69
+
70
+ ### `send_critical`
71
+
72
+ A priority-5 page for things that genuinely can't wait. Bypasses silent/Focus
73
+ when the Blipr app has Apple's Critical Alerts entitlement enabled; otherwise
74
+ it's delivered as time-sensitive.
75
+
76
+ ## Example prompts
77
+
78
+ > "Run the migration, and `send_alert` me when it's done — priority 4 if it
79
+ > fails."
80
+
81
+ > "You're about to delete production data — `send_critical` me for approval
82
+ > first."
83
+
84
+ ## Develop
85
+
86
+ ```bash
87
+ npm install
88
+ npm run build # → dist/index.js
89
+ BLIPR_URL=https://blipr.dev BLIPR_TOPIC=demo node dist/index.js # stdio
90
+ ```
91
+
92
+ ## License
93
+
94
+ MIT © Applogico LLC. This is the open client adapter; the Blipr server is
95
+ distributed as a container image.
package/dist/index.js ADDED
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Blipr MCP server (stdio).
4
+ *
5
+ * A thin client that lets an MCP-capable AI agent (Claude Code, Cursor, …) send
6
+ * push notifications to a phone via a Blipr instance. The agent calls a tool;
7
+ * this process POSTs to `${BLIPR_URL}/api/notify/<topic>`. No inbound socket —
8
+ * stdio in, outbound HTTPS out.
9
+ *
10
+ * Config (env):
11
+ * BLIPR_URL Base URL of the Blipr server. Default: https://blipr.dev
12
+ * BLIPR_TOPIC Default topic when a tool call omits one. Optional.
13
+ */
14
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
15
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
16
+ import { z } from "zod";
17
+ const BLIPR_URL = (process.env.BLIPR_URL ?? "https://blipr.dev").replace(/\/+$/, "");
18
+ const DEFAULT_TOPIC = process.env.BLIPR_TOPIC?.trim() || undefined;
19
+ /** POST a message to a Blipr topic; returns the resolved topic on success. */
20
+ async function publish(opts) {
21
+ const topic = (opts.topic ?? DEFAULT_TOPIC ?? "").trim();
22
+ if (!topic) {
23
+ throw new Error("No topic given and BLIPR_TOPIC is not set. Pass `topic`, or set the BLIPR_TOPIC env var.");
24
+ }
25
+ const headers = { "Content-Type": "text/plain" };
26
+ if (opts.title)
27
+ headers["X-Title"] = opts.title;
28
+ if (opts.priority)
29
+ headers["X-Priority"] = String(opts.priority);
30
+ if (opts.tags?.length)
31
+ headers["X-Tags"] = opts.tags.join(",");
32
+ if (opts.click)
33
+ headers["X-Click"] = opts.click;
34
+ let res;
35
+ try {
36
+ res = await fetch(`${BLIPR_URL}/api/notify/${encodeURIComponent(topic)}`, {
37
+ method: "POST",
38
+ headers,
39
+ body: opts.message,
40
+ });
41
+ }
42
+ catch (e) {
43
+ throw new Error(`Could not reach Blipr at ${BLIPR_URL}: ${e.message}`);
44
+ }
45
+ if (!res.ok) {
46
+ const body = await res.text().catch(() => "");
47
+ throw new Error(`Blipr returned ${res.status} ${res.statusText}${body ? ` — ${body}` : ""}`);
48
+ }
49
+ return topic;
50
+ }
51
+ const server = new McpServer({ name: "blipr", version: "0.1.0" });
52
+ server.registerTool("send_alert", {
53
+ title: "Send a Blipr alert",
54
+ description: "Send a push notification to the user's phone via Blipr. Use this to reach the human: a long task finished, a build broke, you need approval, or you're blocked and need input. Priority 1 (silent) to 5 (critical); defaults to 3.",
55
+ inputSchema: {
56
+ message: z.string().describe("The alert body — what happened or what you need."),
57
+ title: z.string().optional().describe("Short title, shown bold above the message."),
58
+ topic: z
59
+ .string()
60
+ .optional()
61
+ .describe("Topic to publish to. Defaults to the BLIPR_TOPIC env var."),
62
+ priority: z
63
+ .number()
64
+ .int()
65
+ .min(1)
66
+ .max(5)
67
+ .optional()
68
+ .describe("1=min/silent, 2=low, 3=default, 4=time-sensitive (breaks Focus), 5=critical."),
69
+ tags: z
70
+ .array(z.string())
71
+ .optional()
72
+ .describe('Tags / emoji shortcodes, e.g. ["warning", "rocket"].'),
73
+ click: z.string().url().optional().describe("URL opened when the notification is tapped."),
74
+ },
75
+ }, async ({ message, title, topic, priority, tags, click }) => {
76
+ try {
77
+ const sent = await publish({ message, title, topic, priority, tags, click });
78
+ return { content: [{ type: "text", text: `Sent to "${sent}" (priority ${priority ?? 3}).` }] };
79
+ }
80
+ catch (e) {
81
+ return { content: [{ type: "text", text: e.message }], isError: true };
82
+ }
83
+ });
84
+ server.registerTool("send_critical", {
85
+ title: "Page the user (critical)",
86
+ description: "Send a priority-5 critical page. Use ONLY for things that genuinely cannot wait (production down, urgent approval, safety). Bypasses silent/Focus when the Blipr app has Apple's Critical Alerts entitlement enabled; otherwise it is delivered as time-sensitive.",
87
+ inputSchema: {
88
+ message: z.string().describe("What is wrong or what you need, urgently."),
89
+ title: z.string().optional().describe("Short title."),
90
+ topic: z.string().optional().describe("Topic. Defaults to BLIPR_TOPIC."),
91
+ },
92
+ }, async ({ message, title, topic }) => {
93
+ try {
94
+ const sent = await publish({ message, title, topic, priority: 5, tags: ["rotating_light"] });
95
+ return { content: [{ type: "text", text: `Paged "${sent}" (priority 5 / critical).` }] };
96
+ }
97
+ catch (e) {
98
+ return { content: [{ type: "text", text: e.message }], isError: true };
99
+ }
100
+ });
101
+ const transport = new StdioServerTransport();
102
+ await server.connect(transport);
103
+ // stderr is safe for logs; stdout is the MCP channel and must stay clean.
104
+ console.error(`blipr-mcp ready → ${BLIPR_URL}${DEFAULT_TOPIC ? ` (default topic: ${DEFAULT_TOPIC})` : ""}`);
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@applogico/blipr-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server that lets AI agents send Blipr push alerts to your phone — your agent can page you.",
5
+ "type": "module",
6
+ "bin": {
7
+ "blipr-mcp": "dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "engines": {
13
+ "node": ">=18"
14
+ },
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "prepare": "npm run build",
18
+ "start": "node dist/index.js"
19
+ },
20
+ "keywords": [
21
+ "mcp",
22
+ "modelcontextprotocol",
23
+ "blipr",
24
+ "notifications",
25
+ "push",
26
+ "alerts",
27
+ "apns",
28
+ "ai-agents",
29
+ "claude"
30
+ ],
31
+ "author": "Applogico LLC",
32
+ "homepage": "https://blipr.dev",
33
+ "license": "MIT",
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "dependencies": {
38
+ "@modelcontextprotocol/sdk": "^1.17.0",
39
+ "zod": "^3.23.8"
40
+ },
41
+ "devDependencies": {
42
+ "@types/node": "^22.0.0",
43
+ "typescript": "^5.6.0"
44
+ }
45
+ }