@tuannvm/telegram-mcp-server 0.0.2
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 +141 -0
- package/dist/__tests__/server.test.d.ts +2 -0
- package/dist/__tests__/server.test.d.ts.map +1 -0
- package/dist/__tests__/server.test.js +12 -0
- package/dist/__tests__/server.test.js.map +1 -0
- package/dist/errors.d.ts +11 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +25 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +90 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/definitions.d.ts +3 -0
- package/dist/tools/definitions.d.ts.map +1 -0
- package/dist/tools/definitions.js +45 -0
- package/dist/tools/definitions.js.map +1 -0
- package/dist/tools/handlers.d.ts +12 -0
- package/dist/tools/handlers.d.ts.map +1 -0
- package/dist/tools/handlers.js +154 -0
- package/dist/tools/handlers.js.map +1 -0
- package/dist/types.d.ts +60 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +13 -0
- package/dist/types.js.map +1 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Telegram MCP Server
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@tuannvm/telegram-mcp-server)
|
|
4
|
+
[](https://www.npmjs.com/package/@tuannvm/telegram-mcp-server)
|
|
5
|
+
[](https://www.npmjs.com/package/@tuannvm/telegram-mcp-server)
|
|
6
|
+
|
|
7
|
+
Send Telegram notifications from anywhere — works seamlessly across local machines, remote SSH sessions, and containerized environments.
|
|
8
|
+
|
|
9
|
+
```mermaid
|
|
10
|
+
graph LR
|
|
11
|
+
A[Claude Code] --> B[Telegram MCP Server]
|
|
12
|
+
B --> C[Telegram Bot API]
|
|
13
|
+
C --> D[Your Telegram Chat]
|
|
14
|
+
|
|
15
|
+
style A fill:#FF6B35
|
|
16
|
+
style B fill:#4A90E2
|
|
17
|
+
style C fill:#0088cc
|
|
18
|
+
style D fill:#00D4AA
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### 1. Create Telegram Bot
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Message @BotFather on Telegram
|
|
27
|
+
/newbot
|
|
28
|
+
# Follow prompts to get your bot token
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### 2. Add to Claude Code
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
export TELEGRAM_BOT_TOKEN="your-bot-token"
|
|
35
|
+
export TELEGRAM_CHAT_ID="your-chat-id"
|
|
36
|
+
claude mcp add telegram -- npx -y @tuannvm/telegram-mcp-server
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 3. Start Using
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
Send notification "✅ DONE" to "Deployment complete"
|
|
43
|
+
Send telegram status to check configuration
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## One-Click Install
|
|
47
|
+
|
|
48
|
+
[](https://vscode.dev/redirect/mcp/install?name=telegram&config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@tuannvm/telegram-mcp-server%22%5D%2C%22env%22%3A%7B%22TELEGRAM_BOT_TOKEN%22%3A%22YOUR_BOT_TOKEN%22%2C%22TELEGRAM_CHAT_ID%22%3A%22YOUR_CHAT_ID%22%7D%7D)
|
|
49
|
+
[](https://insiders.vscode.dev/redirect/mcp/install?name=telegram&config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22@tuannvm/telegram-mcp-server%22%5D%2C%22env%22%3A%7B%22TELEGRAM_BOT_TOKEN%22%3A%22YOUR_BOT_TOKEN%22%2C%22TELEGRAM_CHAT_ID%22%3A%22YOUR_CHAT_ID%22%7D%7D)
|
|
50
|
+
[](https://cursor.com/en/install-mcp?name=telegram&config=eyJ0eXBlIjoic3RkaW8iLCJjb21tYW5kIjoibnB4IC15IEB0dWFubnZtL3RlbGVncmFtLW1jcC1zZXJ2ZXIiLCJlbnYiOnsiVEVMRUdSQU1fQk9UX1RPS0VOIjoiWU9VUl9CT1RfVE9LRU4iLCJURUxFR1JBTV9DSEFUX0lEIjoiWU9VUl9DSEFUX0lEIn19)
|
|
51
|
+
|
|
52
|
+
## Tools
|
|
53
|
+
|
|
54
|
+
| Tool | Description |
|
|
55
|
+
|------|-------------|
|
|
56
|
+
| `send_telegram` | Send Telegram notifications with HTML formatting |
|
|
57
|
+
| `telegram_status` | Check if Telegram credentials are configured |
|
|
58
|
+
|
|
59
|
+
## Examples
|
|
60
|
+
|
|
61
|
+
**Simple notification:**
|
|
62
|
+
```
|
|
63
|
+
Send notification "✅ DONE" to "Build completed successfully"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**With context:**
|
|
67
|
+
```
|
|
68
|
+
Send notification "🚫 BLOCKED" to "Need approval to continue
|
|
69
|
+
|
|
70
|
+
📁 /path/to/project
|
|
71
|
+
🌿 Branch: feature/new-auth
|
|
72
|
+
💻 Host: production-server
|
|
73
|
+
|
|
74
|
+
Task: Deploying to production
|
|
75
|
+
Issue: Requires manual approval"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Error reporting:**
|
|
79
|
+
```
|
|
80
|
+
Send notification "❌ ERROR" to "Deployment failed
|
|
81
|
+
|
|
82
|
+
Error: Database connection timeout
|
|
83
|
+
Exit code: 1
|
|
84
|
+
Duration: 45s"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Status check:**
|
|
88
|
+
```
|
|
89
|
+
Send telegram status to verify configuration
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Getting Your Chat ID
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# After creating your bot, send a message to it
|
|
96
|
+
# Then visit this URL in your browser:
|
|
97
|
+
https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates
|
|
98
|
+
|
|
99
|
+
# Look for "chat":{"id":123456789} in the response
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Requirements
|
|
103
|
+
|
|
104
|
+
- **Telegram Bot Token** — Create a bot via @BotFather on Telegram
|
|
105
|
+
- **Telegram Chat ID** — Your personal Telegram chat ID or group ID
|
|
106
|
+
- **Node.js 18+** — For local development
|
|
107
|
+
|
|
108
|
+
## Environment Variables
|
|
109
|
+
|
|
110
|
+
| Variable | Description | Required |
|
|
111
|
+
|----------|-------------|----------|
|
|
112
|
+
| `TELEGRAM_BOT_TOKEN` | Your Telegram bot token from @BotFather | Yes |
|
|
113
|
+
| `TELEGRAM_CHAT_ID` | Target chat ID for notifications | Yes |
|
|
114
|
+
|
|
115
|
+
## Development
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npm install # Install dependencies
|
|
119
|
+
npm run dev # Development mode
|
|
120
|
+
npm run build # Build for production
|
|
121
|
+
npm test # Run tests
|
|
122
|
+
npm run lint # Run ESLint
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## How It Works
|
|
126
|
+
|
|
127
|
+
This MCP server runs as a separate process communicating via stdio. When you call `send_telegram`:
|
|
128
|
+
|
|
129
|
+
1. The MCP server receives the request via stdio
|
|
130
|
+
2. It makes an HTTP request to Telegram's Bot API
|
|
131
|
+
3. Your notification appears instantly on Telegram
|
|
132
|
+
|
|
133
|
+
This works reliably across:
|
|
134
|
+
- Local development machines
|
|
135
|
+
- Remote SSH sessions
|
|
136
|
+
- Containerized environments
|
|
137
|
+
- CI/CD pipelines
|
|
138
|
+
|
|
139
|
+
## License
|
|
140
|
+
|
|
141
|
+
ISC
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/server.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { TelegramMcpServer } from '../server.js';
|
|
2
|
+
describe('TelegramMcpServer', () => {
|
|
3
|
+
it('should instantiate with correct config', () => {
|
|
4
|
+
const config = {
|
|
5
|
+
name: 'test-server',
|
|
6
|
+
version: '1.0.0',
|
|
7
|
+
};
|
|
8
|
+
const server = new TelegramMcpServer(config);
|
|
9
|
+
expect(server).toBeInstanceOf(TelegramMcpServer);
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
//# sourceMappingURL=server.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.test.js","sourceRoot":"","sources":["../../src/__tests__/server.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAEjD,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,MAAM,GAAG;YACb,IAAI,EAAE,aAAa;YACnB,OAAO,EAAE,OAAO;SACjB,CAAC;QACF,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare class ToolExecutionError extends Error {
|
|
2
|
+
readonly toolName: string;
|
|
3
|
+
readonly cause?: unknown | undefined;
|
|
4
|
+
constructor(toolName: string, message: string, cause?: unknown | undefined);
|
|
5
|
+
}
|
|
6
|
+
export declare class ValidationError extends Error {
|
|
7
|
+
readonly toolName: string;
|
|
8
|
+
constructor(toolName: string, message: string);
|
|
9
|
+
}
|
|
10
|
+
export declare function handleError(error: unknown, context: string): string;
|
|
11
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,kBAAmB,SAAQ,KAAK;aAEzB,QAAQ,EAAE,MAAM;aAEhB,KAAK,CAAC,EAAE,OAAO;gBAFf,QAAQ,EAAE,MAAM,EAChC,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,OAAO,YAAA;CAKlC;AAED,qBAAa,eAAgB,SAAQ,KAAK;aAEtB,QAAQ,EAAE,MAAM;gBAAhB,QAAQ,EAAE,MAAM,EAChC,OAAO,EAAE,MAAM;CAKlB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAKnE"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export class ToolExecutionError extends Error {
|
|
2
|
+
toolName;
|
|
3
|
+
cause;
|
|
4
|
+
constructor(toolName, message, cause) {
|
|
5
|
+
super(`Failed to execute tool "${toolName}": ${message}`);
|
|
6
|
+
this.toolName = toolName;
|
|
7
|
+
this.cause = cause;
|
|
8
|
+
this.name = 'ToolExecutionError';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class ValidationError extends Error {
|
|
12
|
+
toolName;
|
|
13
|
+
constructor(toolName, message) {
|
|
14
|
+
super(`Validation failed for tool "${toolName}": ${message}`);
|
|
15
|
+
this.toolName = toolName;
|
|
16
|
+
this.name = 'ValidationError';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export function handleError(error, context) {
|
|
20
|
+
if (error instanceof Error) {
|
|
21
|
+
return `Error in ${context}: ${error.message}`;
|
|
22
|
+
}
|
|
23
|
+
return `Error in ${context}: ${String(error)}`;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAEzB;IAEA;IAHlB,YACkB,QAAgB,EAChC,OAAe,EACC,KAAe;QAE/B,KAAK,CAAC,2BAA2B,QAAQ,MAAM,OAAO,EAAE,CAAC,CAAC;QAJ1C,aAAQ,GAAR,QAAQ,CAAQ;QAEhB,UAAK,GAAL,KAAK,CAAU;QAG/B,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAEtB;IADlB,YACkB,QAAgB,EAChC,OAAe;QAEf,KAAK,CAAC,+BAA+B,QAAQ,MAAM,OAAO,EAAE,CAAC,CAAC;QAH9C,aAAQ,GAAR,QAAQ,CAAQ;QAIhC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,MAAM,UAAU,WAAW,CAAC,KAAc,EAAE,OAAe;IACzD,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;QAC3B,OAAO,YAAY,OAAO,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC;IACjD,CAAC;IACD,OAAO,YAAY,OAAO,KAAK,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;AACjD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;GAMG"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Telegram MCP Server
|
|
4
|
+
*
|
|
5
|
+
* Environment variables:
|
|
6
|
+
* TELEGRAM_BOT_TOKEN - Your Telegram bot token
|
|
7
|
+
* TELEGRAM_CHAT_ID - Target chat ID for notifications
|
|
8
|
+
*/
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import { TelegramMcpServer } from './server.js';
|
|
11
|
+
const SERVER_CONFIG = {
|
|
12
|
+
name: 'telegram-mcp-server',
|
|
13
|
+
version: '1.0.0',
|
|
14
|
+
};
|
|
15
|
+
async function main() {
|
|
16
|
+
try {
|
|
17
|
+
const server = new TelegramMcpServer(SERVER_CONFIG);
|
|
18
|
+
await server.start();
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
console.error(chalk.red('Failed to start server:'), error);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
main();
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAEhD,MAAM,aAAa,GAAG;IACpB,IAAI,EAAE,qBAAqB;IAC3B,OAAO,EAAE,OAAO;CACR,CAAC;AAEX,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,iBAAiB,CAAC,aAAa,CAAC,CAAC;QACpD,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,CAAC,EAAE,KAAK,CAAC,CAAC;QAC3D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type ServerConfig } from './types.js';
|
|
2
|
+
export declare class TelegramMcpServer {
|
|
3
|
+
private readonly server;
|
|
4
|
+
private readonly config;
|
|
5
|
+
constructor(config: ServerConfig);
|
|
6
|
+
private setupHandlers;
|
|
7
|
+
private isValidToolName;
|
|
8
|
+
start(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,KAAK,YAAY,EAKlB,MAAM,YAAY,CAAC;AAKpB,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;gBAE1B,MAAM,EAAE,YAAY;IAiBhC,OAAO,CAAC,aAAa;IA4DrB,OAAO,CAAC,eAAe;IAIjB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAK7B"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import { TOOLS, } from './types.js';
|
|
6
|
+
import { handleError } from './errors.js';
|
|
7
|
+
import { toolDefinitions } from './tools/definitions.js';
|
|
8
|
+
import { toolHandlers } from './tools/handlers.js';
|
|
9
|
+
export class TelegramMcpServer {
|
|
10
|
+
server;
|
|
11
|
+
config;
|
|
12
|
+
constructor(config) {
|
|
13
|
+
this.config = config;
|
|
14
|
+
this.server = new Server({
|
|
15
|
+
name: config.name,
|
|
16
|
+
version: config.version,
|
|
17
|
+
}, {
|
|
18
|
+
capabilities: {
|
|
19
|
+
tools: {},
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
this.setupHandlers();
|
|
23
|
+
}
|
|
24
|
+
setupHandlers() {
|
|
25
|
+
// List tools handler
|
|
26
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
27
|
+
return { tools: toolDefinitions };
|
|
28
|
+
});
|
|
29
|
+
// Call tool handler
|
|
30
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
31
|
+
const { name, arguments: args } = request.params;
|
|
32
|
+
const progressToken = request.params._meta?.progressToken;
|
|
33
|
+
// Create progress sender that uses MCP notifications
|
|
34
|
+
const createProgressContext = () => {
|
|
35
|
+
let progressCount = 0;
|
|
36
|
+
return {
|
|
37
|
+
progressToken,
|
|
38
|
+
sendProgress: async (message, progress, total) => {
|
|
39
|
+
if (!progressToken)
|
|
40
|
+
return;
|
|
41
|
+
progressCount++;
|
|
42
|
+
try {
|
|
43
|
+
await extra.sendNotification({
|
|
44
|
+
method: 'notifications/progress',
|
|
45
|
+
params: {
|
|
46
|
+
progressToken,
|
|
47
|
+
progress: progress ?? progressCount,
|
|
48
|
+
total,
|
|
49
|
+
message,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (err) {
|
|
54
|
+
// Log but don't fail the operation if progress notification fails
|
|
55
|
+
console.error(chalk.yellow('Failed to send progress notification:'), err);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
try {
|
|
61
|
+
if (!this.isValidToolName(name)) {
|
|
62
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
63
|
+
}
|
|
64
|
+
const handler = toolHandlers[name];
|
|
65
|
+
const context = createProgressContext();
|
|
66
|
+
return await handler.execute(args, context);
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
return {
|
|
70
|
+
content: [
|
|
71
|
+
{
|
|
72
|
+
type: 'text',
|
|
73
|
+
text: handleError(error, `tool "${name}"`),
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
isError: true,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
isValidToolName(name) {
|
|
82
|
+
return Object.values(TOOLS).includes(name);
|
|
83
|
+
}
|
|
84
|
+
async start() {
|
|
85
|
+
const transport = new StdioServerTransport();
|
|
86
|
+
await this.server.connect(transport);
|
|
87
|
+
console.error(chalk.green(`${this.config.name} started successfully`));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/tools/definitions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAEzD,eAAO,MAAM,eAAe,EAAE,cAAc,EA6C3C,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { TOOLS } from '../types.js';
|
|
2
|
+
export const toolDefinitions = [
|
|
3
|
+
{
|
|
4
|
+
name: TOOLS.SEND_TELEGRAM,
|
|
5
|
+
description: 'Send a Telegram notification. Use for alerts, completion notices, or when blocked awaiting input.',
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: 'object',
|
|
8
|
+
properties: {
|
|
9
|
+
header: {
|
|
10
|
+
type: 'string',
|
|
11
|
+
description: 'Message header/title. Use emoji + status like: ✅ DONE, 🚫 BLOCKED, ❌ ERROR',
|
|
12
|
+
},
|
|
13
|
+
body: {
|
|
14
|
+
type: 'string',
|
|
15
|
+
description: 'Optional message body with details. Can be multiline. Supports basic context like PWD, branch, host.',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
required: ['header'],
|
|
19
|
+
},
|
|
20
|
+
annotations: {
|
|
21
|
+
title: 'Send Telegram',
|
|
22
|
+
readOnlyHint: true,
|
|
23
|
+
destructiveHint: false,
|
|
24
|
+
idempotentHint: false,
|
|
25
|
+
openWorldHint: true,
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: TOOLS.TELEGRAM_STATUS,
|
|
30
|
+
description: 'Check if Telegram credentials are configured',
|
|
31
|
+
inputSchema: {
|
|
32
|
+
type: 'object',
|
|
33
|
+
properties: {},
|
|
34
|
+
required: [],
|
|
35
|
+
},
|
|
36
|
+
annotations: {
|
|
37
|
+
title: 'Telegram Status',
|
|
38
|
+
readOnlyHint: true,
|
|
39
|
+
destructiveHint: false,
|
|
40
|
+
idempotentHint: true,
|
|
41
|
+
openWorldHint: false,
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
//# sourceMappingURL=definitions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/tools/definitions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAuB,MAAM,aAAa,CAAC;AAEzD,MAAM,CAAC,MAAM,eAAe,GAAqB;IAC/C;QACE,IAAI,EAAE,KAAK,CAAC,aAAa;QACzB,WAAW,EACT,mGAAmG;QACrG,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,WAAW,EACT,4EAA4E;iBAC/E;gBACD,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,WAAW,EACT,sGAAsG;iBACzG;aACF;YACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;SACrB;QACD,WAAW,EAAE;YACX,KAAK,EAAE,eAAe;YACtB,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,KAAK;YACrB,aAAa,EAAE,IAAI;SACpB;KACF;IACD;QACE,IAAI,EAAE,KAAK,CAAC,eAAe;QAC3B,WAAW,EAAE,8CAA8C;QAC3D,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE;YACd,QAAQ,EAAE,EAAE;SACb;QACD,WAAW,EAAE;YACX,KAAK,EAAE,iBAAiB;YACxB,YAAY,EAAE,IAAI;YAClB,eAAe,EAAE,KAAK;YACtB,cAAc,EAAE,IAAI;YACpB,aAAa,EAAE,KAAK;SACrB;KACF;CACF,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type ToolResult, type ToolHandlerContext } from '../types.js';
|
|
2
|
+
export declare class SendTelegramToolHandler {
|
|
3
|
+
execute(args: unknown, _context?: ToolHandlerContext): Promise<ToolResult>;
|
|
4
|
+
}
|
|
5
|
+
export declare class TelegramStatusToolHandler {
|
|
6
|
+
execute(args: unknown, _context?: ToolHandlerContext): Promise<ToolResult>;
|
|
7
|
+
}
|
|
8
|
+
export declare const toolHandlers: {
|
|
9
|
+
readonly send_telegram: SendTelegramToolHandler;
|
|
10
|
+
readonly telegram_status: TelegramStatusToolHandler;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../src/tools/handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,kBAAkB,EAKxB,MAAM,aAAa,CAAC;AA0HrB,qBAAa,uBAAuB;IAC5B,OAAO,CACX,IAAI,EAAE,OAAO,EACb,QAAQ,GAAE,kBAAmC,GAC5C,OAAO,CAAC,UAAU,CAAC;CA6BvB;AAED,qBAAa,yBAAyB;IAC9B,OAAO,CACX,IAAI,EAAE,OAAO,EACb,QAAQ,GAAE,kBAAmC,GAC5C,OAAO,CAAC,UAAU,CAAC;CA4BvB;AAGD,eAAO,MAAM,YAAY;;;CAGf,CAAC"}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { TOOLS, SendTelegramToolSchema, TelegramStatusToolSchema, } from '../types.js';
|
|
2
|
+
import { ToolExecutionError, ValidationError } from '../errors.js';
|
|
3
|
+
import { ZodError } from 'zod';
|
|
4
|
+
// Default no-op context for handlers that don't need progress
|
|
5
|
+
const defaultContext = {
|
|
6
|
+
sendProgress: async () => { },
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Escape HTML special characters to prevent injection
|
|
10
|
+
*/
|
|
11
|
+
function escapeHtml(text) {
|
|
12
|
+
const htmlEscapeMap = {
|
|
13
|
+
'&': '&',
|
|
14
|
+
'<': '<',
|
|
15
|
+
'>': '>',
|
|
16
|
+
};
|
|
17
|
+
return text.replace(/[&<>]/g, (char) => htmlEscapeMap[char]);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get Telegram configuration at runtime
|
|
21
|
+
*/
|
|
22
|
+
function getTelegramConfig() {
|
|
23
|
+
return {
|
|
24
|
+
botToken: process.env.TELEGRAM_BOT_TOKEN,
|
|
25
|
+
chatId: process.env.TELEGRAM_CHAT_ID,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
async function sendTelegramMessage(header, body) {
|
|
29
|
+
const { botToken, chatId } = getTelegramConfig();
|
|
30
|
+
if (!botToken || !chatId) {
|
|
31
|
+
return {
|
|
32
|
+
success: false,
|
|
33
|
+
error: 'Missing TELEGRAM_BOT_TOKEN or TELEGRAM_CHAT_ID environment variables',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// Escape HTML special characters to prevent injection
|
|
37
|
+
const escapedHeader = escapeHtml(header);
|
|
38
|
+
const escapedBody = body ? escapeHtml(body) : undefined;
|
|
39
|
+
const message = escapedBody
|
|
40
|
+
? `<b>${escapedHeader}</b>\n\n${escapedBody}`
|
|
41
|
+
: escapedHeader;
|
|
42
|
+
// Setup timeout for fetch request
|
|
43
|
+
const controller = new AbortController();
|
|
44
|
+
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10s timeout
|
|
45
|
+
try {
|
|
46
|
+
const response = await fetch(`https://api.telegram.org/bot${botToken}/sendMessage`, {
|
|
47
|
+
method: 'POST',
|
|
48
|
+
headers: { 'Content-Type': 'application/json' },
|
|
49
|
+
body: JSON.stringify({
|
|
50
|
+
chat_id: chatId,
|
|
51
|
+
text: message,
|
|
52
|
+
parse_mode: 'HTML',
|
|
53
|
+
disable_web_page_preview: true,
|
|
54
|
+
}),
|
|
55
|
+
signal: controller.signal,
|
|
56
|
+
});
|
|
57
|
+
// Clear timeout as request completed
|
|
58
|
+
clearTimeout(timeoutId);
|
|
59
|
+
// Check HTTP status code
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
return {
|
|
62
|
+
success: false,
|
|
63
|
+
error: `HTTP ${response.status}: ${response.statusText}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
// Handle non-JSON responses
|
|
67
|
+
const contentType = response.headers.get('content-type');
|
|
68
|
+
if (!contentType?.includes('application/json')) {
|
|
69
|
+
const text = await response.text();
|
|
70
|
+
return {
|
|
71
|
+
success: false,
|
|
72
|
+
error: `Unexpected response type: ${contentType || 'unknown'}. Response: ${text.slice(0, 200)}`,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const data = (await response.json());
|
|
76
|
+
if (data.ok) {
|
|
77
|
+
return { success: true, messageId: data.result?.message_id };
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
return { success: false, error: data.description || 'Unknown error' };
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
// Clear timeout if still active
|
|
85
|
+
clearTimeout(timeoutId);
|
|
86
|
+
// Handle timeout specifically
|
|
87
|
+
if (error instanceof Error && error.name === 'AbortError') {
|
|
88
|
+
return {
|
|
89
|
+
success: false,
|
|
90
|
+
error: 'Request timeout (10s)',
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
success: false,
|
|
95
|
+
error: error instanceof Error ? error.message : 'Network error',
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export class SendTelegramToolHandler {
|
|
100
|
+
async execute(args, _context = defaultContext) {
|
|
101
|
+
try {
|
|
102
|
+
const { header, body } = SendTelegramToolSchema.parse(args);
|
|
103
|
+
const result = await sendTelegramMessage(header, body);
|
|
104
|
+
return {
|
|
105
|
+
content: [
|
|
106
|
+
{
|
|
107
|
+
type: 'text',
|
|
108
|
+
text: result.success
|
|
109
|
+
? `✓ Telegram sent (ID: ${result.messageId})`
|
|
110
|
+
: `✗ Failed: ${result.error}`,
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
isError: !result.success,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
if (error instanceof ZodError) {
|
|
118
|
+
throw new ValidationError(TOOLS.SEND_TELEGRAM, error.message);
|
|
119
|
+
}
|
|
120
|
+
throw new ToolExecutionError(TOOLS.SEND_TELEGRAM, 'Failed to send Telegram message', error);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
export class TelegramStatusToolHandler {
|
|
125
|
+
async execute(args, _context = defaultContext) {
|
|
126
|
+
try {
|
|
127
|
+
// Handle undefined args for no-argument tools
|
|
128
|
+
TelegramStatusToolSchema.parse(args ?? {});
|
|
129
|
+
const { botToken, chatId } = getTelegramConfig();
|
|
130
|
+
const hasToken = !!botToken;
|
|
131
|
+
const hasChatId = !!chatId;
|
|
132
|
+
return {
|
|
133
|
+
content: [
|
|
134
|
+
{
|
|
135
|
+
type: 'text',
|
|
136
|
+
text: `Telegram Config:\n BOT_TOKEN: ${hasToken ? '✓ Set' : '✗ Missing'}\n CHAT_ID: ${hasChatId ? '✓ Set' : '✗ Missing'}`,
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
if (error instanceof ZodError) {
|
|
143
|
+
throw new ValidationError(TOOLS.TELEGRAM_STATUS, error.message);
|
|
144
|
+
}
|
|
145
|
+
throw new ToolExecutionError(TOOLS.TELEGRAM_STATUS, 'Failed to check Telegram status', error);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Tool handler registry
|
|
150
|
+
export const toolHandlers = {
|
|
151
|
+
[TOOLS.SEND_TELEGRAM]: new SendTelegramToolHandler(),
|
|
152
|
+
[TOOLS.TELEGRAM_STATUS]: new TelegramStatusToolHandler(),
|
|
153
|
+
};
|
|
154
|
+
//# sourceMappingURL=handlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/tools/handlers.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const TOOLS: {
|
|
3
|
+
readonly SEND_TELEGRAM: "send_telegram";
|
|
4
|
+
readonly TELEGRAM_STATUS: "telegram_status";
|
|
5
|
+
};
|
|
6
|
+
export type ToolName = typeof TOOLS[keyof typeof TOOLS];
|
|
7
|
+
export interface ToolAnnotations {
|
|
8
|
+
title?: string;
|
|
9
|
+
readOnlyHint?: boolean;
|
|
10
|
+
destructiveHint?: boolean;
|
|
11
|
+
idempotentHint?: boolean;
|
|
12
|
+
openWorldHint?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface ToolDefinition {
|
|
15
|
+
name: ToolName;
|
|
16
|
+
description: string;
|
|
17
|
+
inputSchema: {
|
|
18
|
+
type: 'object';
|
|
19
|
+
properties: Record<string, unknown>;
|
|
20
|
+
required: string[];
|
|
21
|
+
};
|
|
22
|
+
annotations?: ToolAnnotations;
|
|
23
|
+
}
|
|
24
|
+
export interface ToolResult {
|
|
25
|
+
content: Array<{
|
|
26
|
+
type: 'text';
|
|
27
|
+
text: string;
|
|
28
|
+
}>;
|
|
29
|
+
isError?: boolean;
|
|
30
|
+
_meta?: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
export interface ServerConfig {
|
|
33
|
+
name: string;
|
|
34
|
+
version: string;
|
|
35
|
+
}
|
|
36
|
+
export interface TelegramResponse {
|
|
37
|
+
ok: boolean;
|
|
38
|
+
description?: string;
|
|
39
|
+
result?: {
|
|
40
|
+
message_id: number;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export interface SendTelegramResult {
|
|
44
|
+
success: boolean;
|
|
45
|
+
messageId?: number;
|
|
46
|
+
error?: string;
|
|
47
|
+
}
|
|
48
|
+
export type ProgressToken = string | number;
|
|
49
|
+
export interface ToolHandlerContext {
|
|
50
|
+
progressToken?: ProgressToken;
|
|
51
|
+
sendProgress: (message: string, progress?: number, total?: number) => Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
export declare const SendTelegramToolSchema: z.ZodObject<{
|
|
54
|
+
header: z.ZodString;
|
|
55
|
+
body: z.ZodOptional<z.ZodString>;
|
|
56
|
+
}, z.core.$strip>;
|
|
57
|
+
export declare const TelegramStatusToolSchema: z.ZodObject<{}, z.core.$strip>;
|
|
58
|
+
export type SendTelegramToolArgs = z.infer<typeof SendTelegramToolSchema>;
|
|
59
|
+
export type TelegramStatusToolArgs = z.infer<typeof TelegramStatusToolSchema>;
|
|
60
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,KAAK;;;CAGR,CAAC;AAEX,MAAM,MAAM,QAAQ,GAAG,OAAO,KAAK,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC;AAGxD,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAGD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,EAAE,MAAM,EAAE,CAAC;KACpB,CAAC;IACF,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B;AAGD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAGD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAGD,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE;QACP,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAGD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAGD,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,MAAM,CAAC;AAG5C,MAAM,WAAW,kBAAkB;IACjC,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,YAAY,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACrF;AAGD,eAAO,MAAM,sBAAsB;;;iBAGjC,CAAC;AAEH,eAAO,MAAM,wBAAwB,gCAAe,CAAC;AAErD,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAC1E,MAAM,MAAM,sBAAsB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
// Tool constants
|
|
3
|
+
export const TOOLS = {
|
|
4
|
+
SEND_TELEGRAM: 'send_telegram',
|
|
5
|
+
TELEGRAM_STATUS: 'telegram_status',
|
|
6
|
+
};
|
|
7
|
+
// Zod schemas for tool arguments
|
|
8
|
+
export const SendTelegramToolSchema = z.object({
|
|
9
|
+
header: z.string().describe('Message header/title. Use emoji + status like: ✅ DONE, 🚫 BLOCKED, ❌ ERROR'),
|
|
10
|
+
body: z.string().optional().describe('Optional message body with details. Can be multiline. Supports basic context like PWD, branch, host.'),
|
|
11
|
+
});
|
|
12
|
+
export const TelegramStatusToolSchema = z.object({});
|
|
13
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,iBAAiB;AACjB,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,aAAa,EAAE,eAAe;IAC9B,eAAe,EAAE,iBAAiB;CAC1B,CAAC;AAkEX,iCAAiC;AACjC,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC7C,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,4EAA4E,CAAC;IACzG,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sGAAsG,CAAC;CAC7I,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tuannvm/telegram-mcp-server",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "MCP server for Telegram notifications - send notifications from Claude Code to Telegram",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"telegram-mcp-server": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"directories": {
|
|
13
|
+
"doc": "docs"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsc",
|
|
17
|
+
"start": "node dist/index.js",
|
|
18
|
+
"dev": "tsx src/index.ts",
|
|
19
|
+
"test": "jest",
|
|
20
|
+
"test:watch": "jest --watch",
|
|
21
|
+
"test:coverage": "jest --coverage",
|
|
22
|
+
"lint": "eslint src/**/*.ts",
|
|
23
|
+
"lint:fix": "eslint src/**/*.ts --fix",
|
|
24
|
+
"format": "prettier --write src/**/*.ts",
|
|
25
|
+
"format:check": "prettier --check src/**/*.ts",
|
|
26
|
+
"clean": "rm -rf dist"
|
|
27
|
+
},
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "git+https://github.com/tuannvm/telegram-mcp-server.git"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"mcp",
|
|
34
|
+
"telegram",
|
|
35
|
+
"notifications",
|
|
36
|
+
"claude",
|
|
37
|
+
"ai",
|
|
38
|
+
"cli"
|
|
39
|
+
],
|
|
40
|
+
"author": "",
|
|
41
|
+
"license": "ISC",
|
|
42
|
+
"type": "module",
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/tuannvm/telegram-mcp-server/issues"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/tuannvm/telegram-mcp-server#readme",
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
49
|
+
"chalk": "^5.6.0",
|
|
50
|
+
"zod": "^4.0.17"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@types/jest": "^30.0.0",
|
|
54
|
+
"@types/node": "^20.0.0",
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "^8.39.1",
|
|
56
|
+
"@typescript-eslint/parser": "^8.39.1",
|
|
57
|
+
"eslint": "^9.33.0",
|
|
58
|
+
"jest": "^30.0.5",
|
|
59
|
+
"prettier": "^3.6.2",
|
|
60
|
+
"ts-jest": "^29.4.1",
|
|
61
|
+
"tsx": "^4.20.4",
|
|
62
|
+
"typescript": "^5.0.0"
|
|
63
|
+
}
|
|
64
|
+
}
|