@dashtray/mcp-server 0.0.0-stage → 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 +304 -2
- package/dist/index.d.ts +22 -0
- package/dist/index.js +211 -0
- package/package.json +50 -3
package/README.md
CHANGED
|
@@ -1,3 +1,305 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Dashtray MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Model Context Protocol server for [Dashtray](https://dashtray.app) - send notifications to your phone from AI agents, build scripts, and automation tools.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Single, focused tool:** `send_notification` - send alerts to your phone
|
|
8
|
+
- **No preset management:** Notifications are automatically logged in history
|
|
9
|
+
- **Auto-prefixed:** All notifications prefixed with "MCP - " for clarity
|
|
10
|
+
- **Rate-limited:** Per-plan limits (Starter 100/min, Pro 1000/min)
|
|
11
|
+
- **Secure:** SHA256-hashed API keys, bearer token auth
|
|
12
|
+
- **Lightweight:** Minimal dependencies, ~30KB bundle
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
### Option 1: From npm
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @dashtray/mcp-server
|
|
20
|
+
# or run directly:
|
|
21
|
+
npx @dashtray/mcp-server
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Option 2: From source
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
git clone https://github.com/bhupeshpr25/dashtray.git
|
|
28
|
+
cd dashtray/packages/mcp-server
|
|
29
|
+
npm install
|
|
30
|
+
npm run build
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Setup
|
|
34
|
+
|
|
35
|
+
### 1. Get Your API Key
|
|
36
|
+
|
|
37
|
+
1. Open **Dashtray** on your phone
|
|
38
|
+
2. Go to **Settings → Integrations → API Keys**
|
|
39
|
+
3. Tap **Generate New Key**
|
|
40
|
+
4. Give it a name (e.g., "Claude Desktop")
|
|
41
|
+
5. **Copy the full key** (starts with `sk_test_` or `sk_live_`)
|
|
42
|
+
6. Save it securely - you won't see it again
|
|
43
|
+
|
|
44
|
+
### 2. Set Environment Variables
|
|
45
|
+
|
|
46
|
+
Create a `.env` file or export in your shell:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
export DASHTRAY_API_KEY="sk_test_your_key_here"
|
|
50
|
+
export DASHTRAY_API_ENDPOINT="https://api.dashtray.app" # Optional, uses default if omitted
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 3. Configure Your Agent
|
|
54
|
+
|
|
55
|
+
#### Claude Desktop
|
|
56
|
+
|
|
57
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"mcpServers": {
|
|
62
|
+
"dashtray": {
|
|
63
|
+
"command": "npx",
|
|
64
|
+
"args": ["-y", "@dashtray/mcp-server"],
|
|
65
|
+
"env": {
|
|
66
|
+
"DASHTRAY_API_KEY": "sk_test_your_key_here",
|
|
67
|
+
"DASHTRAY_API_ENDPOINT": "https://api.dashtray.app"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Or if installed from source, point `command` at `node` with the built path:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"mcpServers": {
|
|
79
|
+
"dashtray": {
|
|
80
|
+
"command": "node",
|
|
81
|
+
"args": ["/path/to/dashtray/packages/mcp-server/dist/index.js"],
|
|
82
|
+
"env": {
|
|
83
|
+
"DASHTRAY_API_KEY": "sk_test_your_key_here",
|
|
84
|
+
"DASHTRAY_API_ENDPOINT": "https://api.dashtray.app"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Then restart Claude Desktop.
|
|
92
|
+
|
|
93
|
+
#### Cline
|
|
94
|
+
|
|
95
|
+
In your project's `.cline/config.json`:
|
|
96
|
+
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"mcpServers": {
|
|
100
|
+
"dashtray": {
|
|
101
|
+
"command": "npx",
|
|
102
|
+
"args": ["-y", "@dashtray/mcp-server"],
|
|
103
|
+
"env": {
|
|
104
|
+
"DASHTRAY_API_KEY": "sk_test_your_key_here"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### Custom Agents
|
|
112
|
+
|
|
113
|
+
Start the server and connect via stdio:
|
|
114
|
+
|
|
115
|
+
```javascript
|
|
116
|
+
import { ChildProcess, spawn } from "child_process";
|
|
117
|
+
|
|
118
|
+
const server = spawn("node", ["/path/to/dashtray/packages/mcp-server/dist/index.js"], {
|
|
119
|
+
env: {
|
|
120
|
+
...process.env,
|
|
121
|
+
DASHTRAY_API_KEY: "sk_test_your_key_here",
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Connect to server via server.stdio
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Usage
|
|
129
|
+
|
|
130
|
+
### Send a Notification
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
// The send_notification tool accepts:
|
|
134
|
+
{
|
|
135
|
+
"title": "Build Passed", // Required: notification title (max 255 chars)
|
|
136
|
+
"body": "Production build #42 completed in 3m 21s" // Required: details (max 1000 chars)
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Examples
|
|
141
|
+
|
|
142
|
+
**Build Alert:**
|
|
143
|
+
```
|
|
144
|
+
Title: Build Failed
|
|
145
|
+
Body: Docker image build failed. Error: unauthorized. Check credentials.
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Deployment Status:**
|
|
149
|
+
```
|
|
150
|
+
Title: Deployment Complete
|
|
151
|
+
Body: App v1.2.3 deployed to production. 50 instances running, health check passed.
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
**Test Results:**
|
|
155
|
+
```
|
|
156
|
+
Title: Tests Passed
|
|
157
|
+
Body: All 342 tests passed. Coverage: 87%. Duration: 2m 15s.
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Long-Running Task:**
|
|
161
|
+
```
|
|
162
|
+
Title: Analysis Complete
|
|
163
|
+
Body: Dataset processed. 1.2M records. Anomalies: 3. Report: https://...
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## API Reference
|
|
167
|
+
|
|
168
|
+
### Tool: `send_notification`
|
|
169
|
+
|
|
170
|
+
**Description:** Send a notification to your Dashtray account. Notifications appear on your phone with "MCP - " prefix and are logged in history.
|
|
171
|
+
|
|
172
|
+
**Inputs:**
|
|
173
|
+
| Field | Type | Required | Max Length | Notes |
|
|
174
|
+
|-------|------|----------|-----------|-------|
|
|
175
|
+
| `title` | string | Yes | 255 | Notification title. Auto-prefixed with "MCP - " |
|
|
176
|
+
| `body` | string | Yes | 1000 | Notification details/body |
|
|
177
|
+
|
|
178
|
+
**Outputs:**
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"success": true,
|
|
182
|
+
"message": "Notification sent successfully!\n\nTitle: Build Passed\nBody: ...\n\nIt will appear on your phone with the \"MCP - \" prefix..."
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Errors:**
|
|
187
|
+
- `DASHTRAY_API_KEY not set` - Missing environment variable
|
|
188
|
+
- `Invalid input: title is required` - Missing or empty title
|
|
189
|
+
- `Invalid input: body must be 1000 chars or less` - Body too long
|
|
190
|
+
- `API error: 401 Unauthorized` - Invalid API key
|
|
191
|
+
- `API error: 429 Too Many Requests` - Rate limit exceeded
|
|
192
|
+
- `API error: 500 Internal Server Error` - Server error
|
|
193
|
+
|
|
194
|
+
## Configuration
|
|
195
|
+
|
|
196
|
+
### Environment Variables
|
|
197
|
+
|
|
198
|
+
| Variable | Required | Default | Description |
|
|
199
|
+
|----------|----------|---------|-------------|
|
|
200
|
+
| `DASHTRAY_API_KEY` | Yes | - | API key from Dashtray app |
|
|
201
|
+
| `DASHTRAY_API_ENDPOINT` | No | https://api.dashtray.app | Dashtray API URL (self-hosted or cloud) |
|
|
202
|
+
|
|
203
|
+
### API Key Formats
|
|
204
|
+
|
|
205
|
+
- `sk_test_*` - Test key (development/staging, no rate limiting)
|
|
206
|
+
- `sk_live_*` - Live key (production, subject to rate limits)
|
|
207
|
+
|
|
208
|
+
## Rate Limiting
|
|
209
|
+
|
|
210
|
+
Notifications are rate-limited per-plan:
|
|
211
|
+
|
|
212
|
+
| Plan | Limit | Window |
|
|
213
|
+
|------|-------|--------|
|
|
214
|
+
| Starter | 100/min | 1 minute sliding window |
|
|
215
|
+
| Pro | 1000/min | 1 minute sliding window |
|
|
216
|
+
|
|
217
|
+
When rate limit is exceeded, the API returns `429 Too Many Requests`.
|
|
218
|
+
|
|
219
|
+
## Troubleshooting
|
|
220
|
+
|
|
221
|
+
### "DASHTRAY_API_KEY environment variable is not set"
|
|
222
|
+
|
|
223
|
+
**Solution:** Set the environment variable in your shell or config file.
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
export DASHTRAY_API_KEY="sk_test_..."
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### "API error: 401 Unauthorized"
|
|
230
|
+
|
|
231
|
+
**Solution:** Check your API key:
|
|
232
|
+
1. Open Dashtray app
|
|
233
|
+
2. Go to Settings → Integrations → API Keys
|
|
234
|
+
3. Verify the key is still active (hasn't been revoked)
|
|
235
|
+
4. Generate a new key if needed
|
|
236
|
+
|
|
237
|
+
### "API error: 429 Too Many Requests"
|
|
238
|
+
|
|
239
|
+
**Solution:** You've hit your rate limit for this plan. Either:
|
|
240
|
+
- Wait a minute and retry
|
|
241
|
+
- Upgrade your plan in the app
|
|
242
|
+
- Batch notifications together
|
|
243
|
+
|
|
244
|
+
### "Failed to send notification: ECONNREFUSED"
|
|
245
|
+
|
|
246
|
+
**Solution:** Check that:
|
|
247
|
+
1. `DASHTRAY_API_ENDPOINT` is correct
|
|
248
|
+
2. The endpoint is reachable from your network
|
|
249
|
+
3. No firewall is blocking the connection
|
|
250
|
+
|
|
251
|
+
### Tool not appearing in Claude Desktop
|
|
252
|
+
|
|
253
|
+
**Solution:**
|
|
254
|
+
1. Restart Claude Desktop completely
|
|
255
|
+
2. Check `claude_desktop_config.json` is valid JSON
|
|
256
|
+
3. Verify Node 18+ is installed (`node --version`) so `npx` can fetch the server
|
|
257
|
+
|
|
258
|
+
### "Invalid input: title is required"
|
|
259
|
+
|
|
260
|
+
**Solution:** The title must be a non-empty string:
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
// ❌ Wrong
|
|
264
|
+
send_notification({ body: "Only body" })
|
|
265
|
+
|
|
266
|
+
// ✓ Right
|
|
267
|
+
send_notification({ title: "Alert", body: "Details" })
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Development
|
|
271
|
+
|
|
272
|
+
### Build
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
npm run build
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Watch Mode
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
npm run watch
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### Manual Testing
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
export DASHTRAY_API_KEY="sk_test_..."
|
|
288
|
+
node dist/index.js
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Then send a test request (requires MCP client like Claude Desktop).
|
|
292
|
+
|
|
293
|
+
## Support
|
|
294
|
+
|
|
295
|
+
- **Dashtray App Issues:** Settings → Help & Support
|
|
296
|
+
- **MCP Server Issues:** GitHub Issues
|
|
297
|
+
- **API Questions:** See [API Reference](https://docs.dashtray.app/api-reference/overview)
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
MIT
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
**Dashtray MCP Server** - Minimal, focused, production-ready.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Dashtray MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Model Context Protocol server that provides a single tool:
|
|
6
|
+
* - send_notification: Send notifications to your phone via Dashtray
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* - Local (stdio): node dist/index.js
|
|
10
|
+
* - Environment: Set DASHTRAY_API_KEY and DASHTRAY_API_ENDPOINT
|
|
11
|
+
*
|
|
12
|
+
* Configuration:
|
|
13
|
+
* - Get API key from: Dashtray app → Settings → Integrations → API Keys
|
|
14
|
+
* - Default endpoint: https://api.dashtray.app (or self-hosted)
|
|
15
|
+
*
|
|
16
|
+
* SDK notes (matches @modelcontextprotocol/sdk >= 1.x):
|
|
17
|
+
* - `Server` from `server/index.js`; the stdio transport lives in
|
|
18
|
+
* `server/stdio.js` and request schemas/types in `types.js`.
|
|
19
|
+
* - Handlers register against the exported request SCHEMAS (validated
|
|
20
|
+
* end-to-end by the SDK), not string method names.
|
|
21
|
+
*/
|
|
22
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Dashtray MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Model Context Protocol server that provides a single tool:
|
|
6
|
+
* - send_notification: Send notifications to your phone via Dashtray
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* - Local (stdio): node dist/index.js
|
|
10
|
+
* - Environment: Set DASHTRAY_API_KEY and DASHTRAY_API_ENDPOINT
|
|
11
|
+
*
|
|
12
|
+
* Configuration:
|
|
13
|
+
* - Get API key from: Dashtray app → Settings → Integrations → API Keys
|
|
14
|
+
* - Default endpoint: https://api.dashtray.app (or self-hosted)
|
|
15
|
+
*
|
|
16
|
+
* SDK notes (matches @modelcontextprotocol/sdk >= 1.x):
|
|
17
|
+
* - `Server` from `server/index.js`; the stdio transport lives in
|
|
18
|
+
* `server/stdio.js` and request schemas/types in `types.js`.
|
|
19
|
+
* - Handlers register against the exported request SCHEMAS (validated
|
|
20
|
+
* end-to-end by the SDK), not string method names.
|
|
21
|
+
*/
|
|
22
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
23
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
24
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
25
|
+
import { z } from "zod";
|
|
26
|
+
/**
|
|
27
|
+
* Dashtray Notification Schema
|
|
28
|
+
* Matches POST /api/v1/notifications/send endpoint
|
|
29
|
+
*/
|
|
30
|
+
// Limits match the backend's validateNotificationInput (title 1–200,
|
|
31
|
+
// body 1–500) exactly - rejecting early with a clear message beats letting
|
|
32
|
+
// the API 400 with a generic validation error.
|
|
33
|
+
const NotificationSchema = z.object({
|
|
34
|
+
title: z
|
|
35
|
+
.string()
|
|
36
|
+
.min(1, "Title is required")
|
|
37
|
+
.max(200, "Title must be 200 chars or less"),
|
|
38
|
+
body: z
|
|
39
|
+
.string()
|
|
40
|
+
.min(1, "Body is required")
|
|
41
|
+
.max(500, "Body must be 500 chars or less"),
|
|
42
|
+
});
|
|
43
|
+
/**
|
|
44
|
+
* Get API credentials from environment
|
|
45
|
+
*/
|
|
46
|
+
function getApiCredentials() {
|
|
47
|
+
const apiKey = process.env.DASHTRAY_API_KEY;
|
|
48
|
+
if (!apiKey) {
|
|
49
|
+
throw new Error("DASHTRAY_API_KEY environment variable is not set. " +
|
|
50
|
+
"Get it from: Dashtray app → Settings → Integrations → API Keys");
|
|
51
|
+
}
|
|
52
|
+
const endpoint = process.env.DASHTRAY_API_ENDPOINT || "https://api.dashtray.app";
|
|
53
|
+
return { apiKey, endpoint };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Send notification to Dashtray
|
|
57
|
+
*/
|
|
58
|
+
async function sendNotification(notification, apiKey, endpoint) {
|
|
59
|
+
const url = `${endpoint}/api/v1/notifications/send`;
|
|
60
|
+
try {
|
|
61
|
+
const response = await fetch(url, {
|
|
62
|
+
method: "POST",
|
|
63
|
+
headers: {
|
|
64
|
+
"Content-Type": "application/json",
|
|
65
|
+
Authorization: `Bearer ${apiKey}`,
|
|
66
|
+
},
|
|
67
|
+
body: JSON.stringify({
|
|
68
|
+
title: notification.title,
|
|
69
|
+
body: notification.body,
|
|
70
|
+
}),
|
|
71
|
+
});
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
const errorData = (await response.json().catch(() => ({})));
|
|
74
|
+
return {
|
|
75
|
+
ok: false,
|
|
76
|
+
error: `API error: ${response.status} ${response.statusText}. ${errorData.error || ""}`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const data = (await response.json());
|
|
80
|
+
return {
|
|
81
|
+
ok: true,
|
|
82
|
+
data: data.data || { ...notification, id: "sent", createdAt: Date.now() },
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
return {
|
|
87
|
+
ok: false,
|
|
88
|
+
error: `Failed to send notification: ${error instanceof Error ? error.message : String(error)}`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* MCP Server Main
|
|
94
|
+
*/
|
|
95
|
+
async function main() {
|
|
96
|
+
const { apiKey, endpoint } = getApiCredentials();
|
|
97
|
+
const server = new Server({
|
|
98
|
+
name: "dashtray",
|
|
99
|
+
version: "1.0.0",
|
|
100
|
+
}, {
|
|
101
|
+
capabilities: {
|
|
102
|
+
tools: {},
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
// Define the send_notification tool
|
|
106
|
+
const sendNotificationTool = {
|
|
107
|
+
name: "send_notification",
|
|
108
|
+
description: "Send a notification to your Dashtray account. " +
|
|
109
|
+
"Notifications appear on your phone with 'MCP - ' prefix and are also logged in history. " +
|
|
110
|
+
"Perfect for build alerts, deployment updates, workflow notifications, etc.",
|
|
111
|
+
inputSchema: {
|
|
112
|
+
type: "object",
|
|
113
|
+
properties: {
|
|
114
|
+
title: {
|
|
115
|
+
type: "string",
|
|
116
|
+
description: "Short notification title (max 200 chars). Will be prefixed with 'MCP - ' in the app.",
|
|
117
|
+
examples: [
|
|
118
|
+
"Build Complete",
|
|
119
|
+
"Deployment Failed",
|
|
120
|
+
"Test Suite Passed",
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
body: {
|
|
124
|
+
type: "string",
|
|
125
|
+
description: "Notification body/details (max 500 chars). Can include status, error details, links, etc.",
|
|
126
|
+
examples: [
|
|
127
|
+
"Build succeeded in 2m 15s. Ready to deploy.",
|
|
128
|
+
"E2E tests failed on 3 files. See logs for details.",
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
required: ["title", "body"],
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
// Register tools/list handler (schema-based, per current SDK contract)
|
|
136
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
137
|
+
return {
|
|
138
|
+
tools: [sendNotificationTool],
|
|
139
|
+
};
|
|
140
|
+
});
|
|
141
|
+
// Handle tool calls
|
|
142
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
143
|
+
if (request.params.name !== "send_notification") {
|
|
144
|
+
return {
|
|
145
|
+
content: [
|
|
146
|
+
{
|
|
147
|
+
type: "text",
|
|
148
|
+
text: `Unknown tool: ${request.params.name}`,
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
isError: true,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
// Validate input
|
|
156
|
+
const args = request.params.arguments;
|
|
157
|
+
const validated = NotificationSchema.parse({
|
|
158
|
+
title: args.title,
|
|
159
|
+
body: args.body,
|
|
160
|
+
});
|
|
161
|
+
// Send to Dashtray
|
|
162
|
+
const result = await sendNotification(validated, apiKey, endpoint);
|
|
163
|
+
if (!result.ok) {
|
|
164
|
+
return {
|
|
165
|
+
content: [
|
|
166
|
+
{
|
|
167
|
+
type: "text",
|
|
168
|
+
text: `Error sending notification: ${result.error}`,
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
isError: true,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
// Success response
|
|
175
|
+
return {
|
|
176
|
+
content: [
|
|
177
|
+
{
|
|
178
|
+
type: "text",
|
|
179
|
+
text: `Notification sent successfully!\n\nTitle: ${result.data?.title}\nBody: ${result.data?.body}\n\nIt will appear on your phone with the "MCP - " prefix and also be logged in your Dashtray history.`,
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
const message = error instanceof z.ZodError
|
|
186
|
+
? `Invalid input: ${error.issues.map((e) => `${e.path.join(".")}: ${e.message}`).join(", ")}`
|
|
187
|
+
: error instanceof Error
|
|
188
|
+
? error.message
|
|
189
|
+
: String(error);
|
|
190
|
+
return {
|
|
191
|
+
content: [
|
|
192
|
+
{
|
|
193
|
+
type: "text",
|
|
194
|
+
text: `Error: ${message}`,
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
isError: true,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
// Start server with stdio transport
|
|
202
|
+
const transport = new StdioServerTransport();
|
|
203
|
+
await server.connect(transport);
|
|
204
|
+
console.error("Dashtray MCP Server started");
|
|
205
|
+
console.error(`Using endpoint: ${endpoint}`);
|
|
206
|
+
console.error("Listening on stdio...");
|
|
207
|
+
}
|
|
208
|
+
main().catch((error) => {
|
|
209
|
+
console.error("Fatal error:", error);
|
|
210
|
+
process.exit(1);
|
|
211
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,53 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dashtray/mcp-server",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Dashtray MCP Server - send notifications to your phone via MCP agents",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"dashtray-mcp": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"keywords": [
|
|
22
|
+
"mcp",
|
|
23
|
+
"model-context-protocol",
|
|
24
|
+
"notifications",
|
|
25
|
+
"dashtray",
|
|
26
|
+
"agents"
|
|
27
|
+
],
|
|
28
|
+
"author": "Dashtray",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "git+https://github.com/bhupeshpr25/dashtray.git",
|
|
33
|
+
"directory": "packages/mcp-server"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://dashtray.app",
|
|
36
|
+
"bugs": "https://github.com/bhupeshpr25/dashtray/issues",
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
39
|
+
"zod": "^4.4.3"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^24.3.0",
|
|
43
|
+
"typescript": "^5.4.0"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=18.0.0"
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc",
|
|
50
|
+
"dev": "node dist/index.js",
|
|
51
|
+
"watch": "tsc --watch"
|
|
52
|
+
}
|
|
6
53
|
}
|