@dalcontak/blogger-mcp-server 1.0.0 → 1.0.1
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/.github/workflows/publish.yml +3 -0
- package/AGENTS.md +2 -2
- package/README.md +194 -99
- package/package.json +5 -1
- package/dist/mcp-sdk-mock.d.ts +0 -57
- package/dist/mcp-sdk-mock.js +0 -227
package/AGENTS.md
CHANGED
|
@@ -6,7 +6,7 @@ MCP (Model Context Protocol) server for Google's Blogger API. Allows AI models t
|
|
|
6
6
|
interact with Blogger blogs via stdio or HTTP transport. Includes an optional web dashboard
|
|
7
7
|
(Express + Socket.IO) on a separate port when `UI_PORT` is set. Written in TypeScript, targeting Node.js 20.
|
|
8
8
|
|
|
9
|
-
Package: `@
|
|
9
|
+
Package: `@dalcontak/blogger-mcp-server` (v1.0.4)
|
|
10
10
|
|
|
11
11
|
## Build / Run / Test Commands
|
|
12
12
|
|
|
@@ -47,6 +47,7 @@ src/
|
|
|
47
47
|
config.ts # Environment-based configuration object
|
|
48
48
|
types.ts # Shared interfaces and type definitions
|
|
49
49
|
ui-manager.ts # Express + Socket.IO web dashboard
|
|
50
|
+
*.test.ts # Unit tests (Jest) alongside source files
|
|
50
51
|
public/ # Static web UI assets (HTML/JS/CSS)
|
|
51
52
|
dist/ # Compiled output (committed to repo)
|
|
52
53
|
```
|
|
@@ -146,7 +147,6 @@ dist/ # Compiled output (committed to repo)
|
|
|
146
147
|
## Known Issues / Gotchas
|
|
147
148
|
|
|
148
149
|
- `dist/` directory is committed to the repo -- rebuild before committing if you change source
|
|
149
|
-
- README.md has an unresolved merge conflict marker at line 171
|
|
150
150
|
- HTTP mode in `index.ts` has a manual tool-routing switch that duplicates `server.ts` logic
|
|
151
151
|
|
|
152
152
|
## Deployment
|
package/README.md
CHANGED
|
@@ -1,169 +1,264 @@
|
|
|
1
|
-
#
|
|
2
|
-
=======
|
|
3
|
-
# Serveur MCP pour Blogger
|
|
1
|
+
# Blogger MCP Server
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
MCP (Model Context Protocol) server for Google's Blogger API. Allows AI models like Claude to interact with Blogger blogs.
|
|
6
4
|
|
|
7
|
-
##
|
|
5
|
+
## Features
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
- **List and retrieve blogs** — Get blog details by ID or URL
|
|
8
|
+
- **Posts management** — List, search, retrieve, create, update, delete posts
|
|
9
|
+
- **Labels management** — List and retrieve labels
|
|
10
|
+
- **Dual authentication**:
|
|
11
|
+
- **API Key** (read-only) — Access public blogs
|
|
12
|
+
- **OAuth2** (full access) — Create, update, delete posts, list your blogs
|
|
13
|
+
- **Native search** — Uses Blogger's `posts/search` endpoint (not client-side filtering)
|
|
14
|
+
- **Blog discovery** — `get_blog_by_url` tool to find blog ID from URL
|
|
15
|
+
- **Optional Web UI** — Express + Socket.IO dashboard (enable with `UI_PORT`)
|
|
10
16
|
|
|
11
|
-
|
|
12
|
-
* Lister, rechercher, récupérer, créer, mettre à jour et supprimer des posts
|
|
13
|
-
* Lister et récupérer des labels
|
|
14
|
-
|
|
15
|
-
> **Note importante** : L'API Blogger de Google ne permet pas de créer de nouveaux blogs via API. Cette limitation est documentée par Google. Les blogs doivent être créés manuellement via l'interface web de Blogger.
|
|
16
|
-
|
|
17
|
-
## Prérequis
|
|
18
|
-
|
|
19
|
-
* Node.js (version 16 ou supérieure)
|
|
20
|
-
* Une clé API Blogger de Google
|
|
17
|
+
> **Note:** The Blogger API does not allow creating new blogs. Blogs must be created manually via the Blogger web interface.
|
|
21
18
|
|
|
22
19
|
## Installation
|
|
23
20
|
|
|
24
|
-
###
|
|
21
|
+
### From npm
|
|
25
22
|
|
|
26
23
|
```bash
|
|
27
|
-
npm install -g @
|
|
24
|
+
npm install -g @dalcontak/blogger-mcp-server
|
|
28
25
|
```
|
|
29
26
|
|
|
30
|
-
###
|
|
27
|
+
### From source
|
|
31
28
|
|
|
32
29
|
```bash
|
|
33
|
-
git clone https://github.com/
|
|
30
|
+
git clone https://github.com/dalcontak/blogger-mcp-server.git
|
|
34
31
|
cd blogger-mcp-server
|
|
35
32
|
npm install
|
|
36
33
|
npm run build
|
|
37
34
|
```
|
|
38
|
-
|
|
35
|
+
|
|
36
|
+
## Authentication
|
|
37
|
+
|
|
38
|
+
### Option 1: API Key (Read-only)
|
|
39
|
+
|
|
40
|
+
Access public blogs only.
|
|
41
|
+
|
|
42
|
+
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
|
|
43
|
+
2. Create/select a project or existing one
|
|
44
|
+
3. Enable the **Blogger API v3**
|
|
45
|
+
4. Create an **API Key**
|
|
46
|
+
5. Set the environment variable:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
export BLOGGER_API_KEY=your_api_key_here
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Works for: `get_blog`, `get_blog_by_url`, `list_posts`, `get_post`, `search_posts`, `list_labels`, `get_label`
|
|
53
|
+
|
|
54
|
+
### Option 2: OAuth2 (Full Access)
|
|
55
|
+
|
|
56
|
+
Required for: `list_blogs`, `create_post`, `update_post`, `delete_post`
|
|
57
|
+
|
|
58
|
+
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
|
|
59
|
+
2. Navigate to **Credentials** > **Create Credentials**
|
|
60
|
+
3. Select **OAuth client ID**
|
|
61
|
+
4. Application type: **Web application** or **Desktop app**
|
|
62
|
+
5. Name: Your app name
|
|
63
|
+
6. Authorized redirect URI: `http://localhost` (or your actual redirect)
|
|
64
|
+
7. Scopes: Select **`https://www.googleapis.com/auth/blogger`**
|
|
65
|
+
8. Create credentials and note the **Client ID** and **Client Secret**
|
|
66
|
+
|
|
67
|
+
To obtain a refresh token (one-time setup):
|
|
68
|
+
- Use the [OAuth Playground](https://developers.google.com/oauthplayground/)
|
|
69
|
+
- Select **Blogger API v3**
|
|
70
|
+
- Choose `https://www.googleapis.com/auth/blogger` scope
|
|
71
|
+
- Authorize and copy the **refresh token**
|
|
72
|
+
|
|
73
|
+
Set environment variables:
|
|
39
74
|
|
|
40
75
|
```bash
|
|
41
|
-
|
|
76
|
+
export GOOGLE_CLIENT_ID=your_client_id
|
|
77
|
+
export GOOGLE_CLIENT_SECRET=your_client_secret
|
|
78
|
+
export GOOGLE_REFRESH_TOKEN=your_refresh_token
|
|
42
79
|
```
|
|
43
|
-
## Configuration
|
|
44
80
|
|
|
45
|
-
|
|
81
|
+
> **Note:** If both authentication methods are configured, OAuth2 is used (it covers all operations).
|
|
82
|
+
|
|
83
|
+
## Usage
|
|
46
84
|
|
|
47
|
-
|
|
48
|
-
2. Créez un nouveau projet ou sélectionnez un projet existant
|
|
49
|
-
3. Activez l'API Blogger v3
|
|
50
|
-
4. Créez une clé API
|
|
51
|
-
5. Notez cette clé pour l'utiliser dans la configuration
|
|
85
|
+
### Local Development
|
|
52
86
|
|
|
53
|
-
|
|
87
|
+
```bash
|
|
88
|
+
# Using npm package
|
|
89
|
+
npm start
|
|
54
90
|
|
|
55
|
-
|
|
91
|
+
# Or from source (after build)
|
|
92
|
+
node dist/index.js
|
|
93
|
+
|
|
94
|
+
# Development mode with ts-node
|
|
95
|
+
npm run dev
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### With MCP Client (Claude Desktop)
|
|
99
|
+
|
|
100
|
+
Create or edit your Claude Desktop config file:
|
|
101
|
+
|
|
102
|
+
**Linux:** `~/.config/Claude/claude_desktop_config.json`
|
|
103
|
+
**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
104
|
+
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
56
105
|
|
|
57
106
|
```json
|
|
58
107
|
{
|
|
59
108
|
"mcpServers": {
|
|
60
109
|
"blogger": {
|
|
61
|
-
"command": "
|
|
62
|
-
"args": [
|
|
63
|
-
"-y",
|
|
64
|
-
"@mcproadev/blogger-mcp-server"
|
|
65
|
-
],
|
|
110
|
+
"command": "node",
|
|
111
|
+
"args": ["/home/dalcon/dev/ai/blogger-mcp-server/dist/index.js"],
|
|
66
112
|
"env": {
|
|
67
|
-
"BLOGGER_API_KEY": "
|
|
113
|
+
"BLOGGER_API_KEY": "your_api_key_here"
|
|
68
114
|
}
|
|
69
115
|
}
|
|
70
116
|
}
|
|
71
117
|
}
|
|
72
118
|
```
|
|
73
119
|
|
|
74
|
-
|
|
120
|
+
Replace `/home/dalcon/dev/ai/blogger-mcp-server/dist/index.js` with your actual path, and set your API key or OAuth2 credentials.
|
|
75
121
|
|
|
76
|
-
|
|
122
|
+
### Example Commands
|
|
77
123
|
|
|
78
|
-
|
|
124
|
+
```json
|
|
125
|
+
// List all your blogs (requires OAuth2)
|
|
126
|
+
{"tool": "list_blogs", "params": {}}
|
|
79
127
|
|
|
80
|
-
|
|
128
|
+
// Get blog details by ID
|
|
129
|
+
{"tool": "get_blog", "params": {"blogId": "123456789"}}
|
|
81
130
|
|
|
82
|
-
|
|
131
|
+
// Find blog ID from URL (useful when you don't know the ID)
|
|
132
|
+
{"tool": "get_blog_by_url", "params": {"url": "https://yourblog.blogspot.com"}}
|
|
83
133
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
./start-dev.sh
|
|
87
|
-
```
|
|
134
|
+
// List posts
|
|
135
|
+
{"tool": "list_posts", "params": {"blogId": "123456789", "maxResults": 10}}
|
|
88
136
|
|
|
89
|
-
|
|
137
|
+
// Search posts
|
|
138
|
+
{"tool": "search_posts", "params": {"blogId": "123456789", "query": "technology"}}
|
|
90
139
|
|
|
91
|
-
|
|
140
|
+
// Create a new post (requires OAuth2)
|
|
141
|
+
{"tool": "create_post", "params": {"blogId": "123456789", "title": "My Post", "content": "Content here", "labels": ["tech", "nodejs"]}}
|
|
92
142
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
143
|
+
// Update a post (requires OAuth2)
|
|
144
|
+
{"tool": "update_post", "params": {"blogId": "123456789", "postId": "789012", "title": "Updated Title"}}
|
|
145
|
+
|
|
146
|
+
// Delete a post (requires OAuth2)
|
|
147
|
+
{"tool": "delete_post", "params": {"blogId": "123456789", "postId": "789012"}}
|
|
148
|
+
|
|
149
|
+
// List labels
|
|
150
|
+
{"tool": "list_labels", "params": {"blogId": "123456789"}}
|
|
151
|
+
|
|
152
|
+
// Get label details
|
|
153
|
+
{"tool": "get_label", "params": {"blogId": "123456789", "labelName": "technology"}}
|
|
97
154
|
```
|
|
98
155
|
|
|
99
|
-
|
|
156
|
+
## Available Tools
|
|
157
|
+
|
|
158
|
+
| Tool | Description | Auth Required |
|
|
159
|
+
|-------|-------------|---------------|
|
|
160
|
+
| `list_blogs` | Lists all your blogs | OAuth2 |
|
|
161
|
+
| `get_blog` | Retrieves blog details by ID | None |
|
|
162
|
+
| `get_blog_by_url` | Finds blog ID from URL | None |
|
|
163
|
+
| `list_posts` | Lists posts from a blog | None |
|
|
164
|
+
| `search_posts` | Searches posts (uses native API) | None |
|
|
165
|
+
| `get_post` | Retrieves post details | None |
|
|
166
|
+
| `create_post` | Creates a new post | OAuth2 |
|
|
167
|
+
| `update_post` | Updates an existing post | OAuth2 |
|
|
168
|
+
| `delete_post` | Deletes a post | OAuth2 |
|
|
169
|
+
| `list_labels` | Lists all labels from a blog | None |
|
|
170
|
+
| `get_label` | Retrieves label details | None |
|
|
171
|
+
|
|
172
|
+
## Environment Variables
|
|
173
|
+
|
|
174
|
+
| Variable | Default | Description |
|
|
175
|
+
|----------|---------|-------------|
|
|
176
|
+
| `BLOGGER_API_KEY` | (optional) | Google Blogger API key (read-only) |
|
|
177
|
+
| `GOOGLE_CLIENT_ID` | (optional) | OAuth2 client ID (for full access) |
|
|
178
|
+
| `GOOGLE_CLIENT_SECRET` | (optional) | OAuth2 client secret |
|
|
179
|
+
| `GOOGLE_REFRESH_TOKEN` | (optional) | OAuth2 refresh token |
|
|
180
|
+
| `MCP_MODE` | `stdio` | Transport: `stdio` or `http` |
|
|
181
|
+
| `MCP_HTTP_HOST` | `0.0.0.0` | HTTP host (HTTP mode) |
|
|
182
|
+
| `MCP_HTTP_PORT` | `3000` | HTTP port (HTTP mode) |
|
|
183
|
+
| `BLOGGER_MAX_RESULTS` | `10` | Max results per query |
|
|
184
|
+
| `BLOGGER_API_TIMEOUT` | `30000` | API timeout (ms) |
|
|
185
|
+
| `LOG_LEVEL` | `info` | Logging level |
|
|
186
|
+
| `UI_PORT` | (disabled) | Web UI port (set to enable) |
|
|
187
|
+
|
|
188
|
+
**At least one auth method is required** — Either API key OR OAuth2 credentials.
|
|
189
|
+
|
|
190
|
+
## Project Structure
|
|
100
191
|
|
|
101
|
-
|
|
192
|
+
```
|
|
193
|
+
src/
|
|
194
|
+
index.ts # Entry point, main() function, HTTP mode routing
|
|
195
|
+
server.ts # MCP server tool registration (initMCPServer)
|
|
196
|
+
bloggerService.ts # Google Blogger API wrapper (BloggerService class)
|
|
197
|
+
config.ts # Environment-based configuration object
|
|
198
|
+
types.ts # Shared interfaces and type definitions
|
|
199
|
+
ui-manager.ts # Express + Socket.IO web dashboard
|
|
200
|
+
tests/ # Unit tests (Jest)
|
|
201
|
+
.github/workflows/ # GitHub Actions CI/CD
|
|
202
|
+
public/ # Static web UI assets (HTML/JS/CSS)
|
|
203
|
+
dist/ # Compiled output
|
|
204
|
+
```
|
|
102
205
|
|
|
103
|
-
|
|
206
|
+
## Development
|
|
104
207
|
|
|
105
|
-
|
|
208
|
+
```bash
|
|
209
|
+
# Install dependencies
|
|
210
|
+
npm install
|
|
106
211
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
* "Recherche des posts contenant le mot 'technologie' dans mon blog"
|
|
110
|
-
* "Mets à jour le post avec l'ID 789012 pour changer son titre en 'Nouveau titre'"
|
|
212
|
+
# Run development (stdio mode, auto-compiles with ts-node)
|
|
213
|
+
npm run dev
|
|
111
214
|
|
|
112
|
-
|
|
215
|
+
# Run in HTTP mode (useful for manual testing with curl)
|
|
216
|
+
MCP_MODE=http BLOGGER_API_KEY=your_key npm run dev
|
|
113
217
|
|
|
114
|
-
|
|
218
|
+
# Run tests
|
|
219
|
+
npm test
|
|
115
220
|
|
|
116
|
-
|
|
221
|
+
# Build for production
|
|
222
|
+
npm run build
|
|
223
|
+
```
|
|
117
224
|
|
|
118
|
-
|
|
119
|
-
2. Installez l'outil CLI Vercel : `npm install -g vercel`
|
|
120
|
-
3. Connectez-vous à votre compte Vercel : `vercel login`
|
|
121
|
-
4. Configurez votre variable d'environnement secrète : `vercel secrets add blogger_api_key "VOTRE_CLE_API_ICI"`
|
|
122
|
-
5. Déployez le projet : `vercel`
|
|
225
|
+
## Deployment
|
|
123
226
|
|
|
124
|
-
###
|
|
227
|
+
### Vercel
|
|
125
228
|
|
|
126
|
-
|
|
229
|
+
The project includes `vercel.json` for Vercel deployment:
|
|
127
230
|
|
|
128
|
-
1.
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
```
|
|
231
|
+
1. Install Vercel CLI: `npm install -g vercel`
|
|
232
|
+
2. Login: `vercel login`
|
|
233
|
+
3. Deploy: `vercel`
|
|
132
234
|
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
docker run -p 3000:3000 -e BLOGGER_API_KEY=votre_cle_api blogger-mcp-server
|
|
136
|
-
```
|
|
235
|
+
### Docker
|
|
137
236
|
|
|
138
|
-
|
|
237
|
+
Build and run:
|
|
139
238
|
|
|
140
|
-
|
|
239
|
+
```bash
|
|
240
|
+
docker build -t blogger-mcp-server .
|
|
241
|
+
docker run -p 3000:3000 -e BLOGGER_API_KEY=your_key blogger-mcp-server
|
|
242
|
+
```
|
|
141
243
|
|
|
142
|
-
|
|
143
|
-
2. **AWS Lambda** : Utilisez un adaptateur comme Serverless Framework
|
|
144
|
-
3. **Google Cloud Run** : Utilisez le Dockerfile inclus
|
|
244
|
+
### Other Platforms
|
|
145
245
|
|
|
146
|
-
|
|
246
|
+
The server can be deployed to any Node.js-compatible platform (Heroku, AWS Lambda, Google Cloud Run, etc.).
|
|
147
247
|
|
|
148
|
-
|
|
248
|
+
## Release Process
|
|
149
249
|
|
|
150
|
-
|
|
151
|
-
* `server.ts` : Configuration du serveur MCP
|
|
152
|
-
* `bloggerService.ts` : Service d'interaction avec l'API Blogger
|
|
153
|
-
* `config.ts` : Configuration du serveur
|
|
154
|
-
* `types.ts` : Définition des types et interfaces
|
|
250
|
+
For publishing new versions to npm, see [RELEASE.md](./RELEASE.md).
|
|
155
251
|
|
|
156
|
-
##
|
|
252
|
+
## Contributing
|
|
157
253
|
|
|
158
|
-
|
|
159
|
-
* **Recherche de posts** : La recherche utilise l'endpoint natif `posts/search?q=` de l'API Blogger v3.
|
|
160
|
-
* **Gestion des labels** : L'API Blogger ne fournit pas d'endpoints directs pour la gestion des labels. Cette fonctionnalité est implémentée en extrayant les labels des posts.
|
|
161
|
-
* **Authentification** : Le serveur supporte l'authentification par clé API (lecture seule, blogs publics) et OAuth2 (accès complet en lecture/écriture). OAuth2 est requis pour `list_blogs`, `create_post`, `update_post`, `delete_post`.
|
|
254
|
+
Contributions are welcome! Feel free to open an issue or pull request.
|
|
162
255
|
|
|
163
|
-
##
|
|
256
|
+
## License
|
|
164
257
|
|
|
165
|
-
|
|
258
|
+
MIT
|
|
166
259
|
|
|
167
|
-
##
|
|
260
|
+
## Acknowledgments
|
|
168
261
|
|
|
169
|
-
|
|
262
|
+
- Built with [TypeScript](https://www.typescriptlang.org/)
|
|
263
|
+
- Uses [googleapis](https://github.com/googleapis/google-api-nodejs-client) for Google APIs
|
|
264
|
+
- MCP SDK by [Model Context Protocol](https://modelcontextprotocol.io/)
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dalcontak/blogger-mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "MCP Server for Blogger API",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/dalcontak/blogger-mcp-server.git"
|
|
9
|
+
},
|
|
6
10
|
"main": "dist/index.js",
|
|
7
11
|
"types": "dist/index.d.ts",
|
|
8
12
|
"scripts": {
|
package/dist/mcp-sdk-mock.d.ts
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Mock du SDK MCP pour éviter les problèmes de dépendances
|
|
3
|
-
* Cette implémentation simplifiée fournit les fonctionnalités essentielles
|
|
4
|
-
* du SDK MCP sans dépendre de la version exacte du package
|
|
5
|
-
*/
|
|
6
|
-
import { z } from 'zod';
|
|
7
|
-
import { ServerMode } from './types';
|
|
8
|
-
export interface MCPTool<T extends z.ZodType> {
|
|
9
|
-
name: string;
|
|
10
|
-
description: string;
|
|
11
|
-
parameters: T;
|
|
12
|
-
handler: (params: z.infer<T>) => Promise<any>;
|
|
13
|
-
}
|
|
14
|
-
export interface MCPServerOptions {
|
|
15
|
-
name: string;
|
|
16
|
-
version: string;
|
|
17
|
-
mode: ServerMode;
|
|
18
|
-
}
|
|
19
|
-
export interface ServerTransport {
|
|
20
|
-
start: () => Promise<void>;
|
|
21
|
-
stop: () => Promise<void>;
|
|
22
|
-
onRequest?: (handler: (request: any) => Promise<any>) => void;
|
|
23
|
-
}
|
|
24
|
-
export declare class MCPServer {
|
|
25
|
-
private options;
|
|
26
|
-
private tools;
|
|
27
|
-
private transport;
|
|
28
|
-
constructor(options: MCPServerOptions);
|
|
29
|
-
addTool<T extends z.ZodType>(tool: MCPTool<T>): void;
|
|
30
|
-
connect(transport: ServerTransport): Promise<void>;
|
|
31
|
-
start(): Promise<void>;
|
|
32
|
-
stop(): Promise<void>;
|
|
33
|
-
}
|
|
34
|
-
export declare class StdioServerTransport implements ServerTransport {
|
|
35
|
-
private requestHandler;
|
|
36
|
-
start(): Promise<void>;
|
|
37
|
-
stop(): Promise<void>;
|
|
38
|
-
onRequest(handler: (request: any) => Promise<any>): void;
|
|
39
|
-
}
|
|
40
|
-
export declare class HttpServerTransport implements ServerTransport {
|
|
41
|
-
private server;
|
|
42
|
-
private requestHandler;
|
|
43
|
-
private host;
|
|
44
|
-
private port;
|
|
45
|
-
constructor(options: {
|
|
46
|
-
host: string;
|
|
47
|
-
port: number;
|
|
48
|
-
});
|
|
49
|
-
start(): Promise<void>;
|
|
50
|
-
stop(): Promise<void>;
|
|
51
|
-
onRequest(handler: (request: any) => Promise<any>): void;
|
|
52
|
-
}
|
|
53
|
-
export declare class ResourceTemplate<T> {
|
|
54
|
-
private resource;
|
|
55
|
-
constructor(resource: T);
|
|
56
|
-
get(): T;
|
|
57
|
-
}
|
package/dist/mcp-sdk-mock.js
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Mock du SDK MCP pour éviter les problèmes de dépendances
|
|
4
|
-
* Cette implémentation simplifiée fournit les fonctionnalités essentielles
|
|
5
|
-
* du SDK MCP sans dépendre de la version exacte du package
|
|
6
|
-
*/
|
|
7
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
-
if (k2 === undefined) k2 = k;
|
|
9
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
-
}
|
|
13
|
-
Object.defineProperty(o, k2, desc);
|
|
14
|
-
}) : (function(o, m, k, k2) {
|
|
15
|
-
if (k2 === undefined) k2 = k;
|
|
16
|
-
o[k2] = m[k];
|
|
17
|
-
}));
|
|
18
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
-
}) : function(o, v) {
|
|
21
|
-
o["default"] = v;
|
|
22
|
-
});
|
|
23
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
-
var ownKeys = function(o) {
|
|
25
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
-
var ar = [];
|
|
27
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
-
return ar;
|
|
29
|
-
};
|
|
30
|
-
return ownKeys(o);
|
|
31
|
-
};
|
|
32
|
-
return function (mod) {
|
|
33
|
-
if (mod && mod.__esModule) return mod;
|
|
34
|
-
var result = {};
|
|
35
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
-
__setModuleDefault(result, mod);
|
|
37
|
-
return result;
|
|
38
|
-
};
|
|
39
|
-
})();
|
|
40
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
-
exports.ResourceTemplate = exports.HttpServerTransport = exports.StdioServerTransport = exports.MCPServer = void 0;
|
|
42
|
-
const zod_1 = require("zod");
|
|
43
|
-
const http = __importStar(require("http"));
|
|
44
|
-
// Classe principale du serveur MCP
|
|
45
|
-
class MCPServer {
|
|
46
|
-
constructor(options) {
|
|
47
|
-
this.tools = new Map();
|
|
48
|
-
this.transport = null;
|
|
49
|
-
this.options = options;
|
|
50
|
-
}
|
|
51
|
-
// Ajoute un outil au serveur
|
|
52
|
-
addTool(tool) {
|
|
53
|
-
this.tools.set(tool.name, tool);
|
|
54
|
-
}
|
|
55
|
-
// Connecte le serveur à un transport
|
|
56
|
-
async connect(transport) {
|
|
57
|
-
this.transport = transport;
|
|
58
|
-
if (this.transport.onRequest) {
|
|
59
|
-
this.transport.onRequest(async (request) => {
|
|
60
|
-
try {
|
|
61
|
-
const { tool, params } = request;
|
|
62
|
-
if (!this.tools.has(tool)) {
|
|
63
|
-
return {
|
|
64
|
-
error: `Outil non trouvé: ${tool}`
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
const mcpTool = this.tools.get(tool);
|
|
68
|
-
try {
|
|
69
|
-
const validatedParams = mcpTool.parameters.parse(params);
|
|
70
|
-
const result = await mcpTool.handler(validatedParams);
|
|
71
|
-
return result;
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
if (error instanceof zod_1.z.ZodError) {
|
|
75
|
-
return {
|
|
76
|
-
error: `Paramètres invalides: ${error.message}`
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
return {
|
|
80
|
-
error: `Erreur lors de l'exécution de l'outil: ${error}`
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
return {
|
|
86
|
-
error: `Erreur interne du serveur: ${error}`
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
// Démarre le serveur
|
|
93
|
-
async start() {
|
|
94
|
-
if (!this.transport) {
|
|
95
|
-
throw new Error('Le serveur doit être connecté à un transport avant de démarrer');
|
|
96
|
-
}
|
|
97
|
-
await this.transport.start();
|
|
98
|
-
}
|
|
99
|
-
// Arrête le serveur
|
|
100
|
-
async stop() {
|
|
101
|
-
if (this.transport) {
|
|
102
|
-
await this.transport.stop();
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
exports.MCPServer = MCPServer;
|
|
107
|
-
// Transport pour le mode stdio
|
|
108
|
-
class StdioServerTransport {
|
|
109
|
-
constructor() {
|
|
110
|
-
this.requestHandler = null;
|
|
111
|
-
}
|
|
112
|
-
async start() {
|
|
113
|
-
process.stdin.setEncoding('utf-8');
|
|
114
|
-
process.stdin.on('data', async (data) => {
|
|
115
|
-
try {
|
|
116
|
-
const request = JSON.parse(data.toString());
|
|
117
|
-
if (this.requestHandler) {
|
|
118
|
-
const response = await this.requestHandler(request);
|
|
119
|
-
process.stdout.write(JSON.stringify(response) + '\n');
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
catch (error) {
|
|
123
|
-
process.stdout.write(JSON.stringify({ error: `Erreur de parsing: ${error}` }) + '\n');
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
async stop() {
|
|
128
|
-
// Rien à faire pour le mode stdio
|
|
129
|
-
}
|
|
130
|
-
onRequest(handler) {
|
|
131
|
-
this.requestHandler = handler;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
exports.StdioServerTransport = StdioServerTransport;
|
|
135
|
-
// Transport pour le mode HTTP
|
|
136
|
-
class HttpServerTransport {
|
|
137
|
-
constructor(options) {
|
|
138
|
-
this.server = null;
|
|
139
|
-
this.requestHandler = null;
|
|
140
|
-
this.host = options.host;
|
|
141
|
-
this.port = options.port;
|
|
142
|
-
}
|
|
143
|
-
async start() {
|
|
144
|
-
this.server = http.createServer(async (req, res) => {
|
|
145
|
-
res.setHeader('Content-Type', 'application/json');
|
|
146
|
-
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
147
|
-
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
|
148
|
-
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
149
|
-
if (req.method === 'OPTIONS') {
|
|
150
|
-
res.statusCode = 200;
|
|
151
|
-
res.end();
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
if (req.method !== 'POST') {
|
|
155
|
-
res.statusCode = 405;
|
|
156
|
-
res.end(JSON.stringify({ error: 'Méthode non autorisée' }));
|
|
157
|
-
return;
|
|
158
|
-
}
|
|
159
|
-
try {
|
|
160
|
-
let body = '';
|
|
161
|
-
req.on('data', (chunk) => {
|
|
162
|
-
body += chunk.toString();
|
|
163
|
-
});
|
|
164
|
-
req.on('end', async () => {
|
|
165
|
-
try {
|
|
166
|
-
const request = JSON.parse(body);
|
|
167
|
-
if (this.requestHandler) {
|
|
168
|
-
const response = await this.requestHandler(request);
|
|
169
|
-
res.statusCode = 200;
|
|
170
|
-
res.end(JSON.stringify(response));
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
res.statusCode = 500;
|
|
174
|
-
res.end(JSON.stringify({ error: 'Gestionnaire de requêtes non configuré' }));
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
catch (error) {
|
|
178
|
-
res.statusCode = 400;
|
|
179
|
-
res.end(JSON.stringify({ error: `Erreur de parsing: ${error}` }));
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
catch (error) {
|
|
184
|
-
res.statusCode = 500;
|
|
185
|
-
res.end(JSON.stringify({ error: `Erreur interne du serveur: ${error}` }));
|
|
186
|
-
}
|
|
187
|
-
});
|
|
188
|
-
return new Promise((resolve) => {
|
|
189
|
-
if (this.server) {
|
|
190
|
-
this.server.listen(this.port, this.host, () => {
|
|
191
|
-
resolve();
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
async stop() {
|
|
197
|
-
return new Promise((resolve, reject) => {
|
|
198
|
-
if (this.server) {
|
|
199
|
-
this.server.close((err) => {
|
|
200
|
-
if (err) {
|
|
201
|
-
reject(err);
|
|
202
|
-
}
|
|
203
|
-
else {
|
|
204
|
-
resolve();
|
|
205
|
-
}
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
else {
|
|
209
|
-
resolve();
|
|
210
|
-
}
|
|
211
|
-
});
|
|
212
|
-
}
|
|
213
|
-
onRequest(handler) {
|
|
214
|
-
this.requestHandler = handler;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
exports.HttpServerTransport = HttpServerTransport;
|
|
218
|
-
// Classe pour les templates de ressources
|
|
219
|
-
class ResourceTemplate {
|
|
220
|
-
constructor(resource) {
|
|
221
|
-
this.resource = resource;
|
|
222
|
-
}
|
|
223
|
-
get() {
|
|
224
|
-
return this.resource;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
exports.ResourceTemplate = ResourceTemplate;
|