@dalcontak/blogger-mcp-server 1.0.0 → 1.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/.github/workflows/publish.yml +3 -0
- package/AGENTS.md +2 -2
- package/README.md +201 -100
- package/RELEASE.md +64 -32
- package/dist/bloggerService.d.ts +7 -100
- package/dist/bloggerService.js +17 -146
- package/dist/config.d.ts +3 -0
- package/dist/config.js +12 -12
- package/dist/index.js +80 -154
- package/dist/server.d.ts +0 -11
- package/dist/server.js +59 -339
- package/dist/types.d.ts +15 -44
- package/dist/ui-manager.js +8 -16
- package/package.json +5 -1
- package/src/bloggerService.test.ts +5 -1
- package/src/bloggerService.ts +26 -161
- package/src/config.test.ts +34 -20
- package/src/config.ts +17 -16
- package/src/index.ts +115 -194
- package/src/server.test.ts +128 -0
- package/src/server.ts +63 -332
- package/src/types.ts +12 -60
- package/src/ui-manager.ts +17 -26
- package/Dockerfile +0 -64
- package/dist/mcp-sdk-mock.d.ts +0 -57
- package/dist/mcp-sdk-mock.js +0 -227
package/Dockerfile
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
# Dockerfile amélioré pour blogger-mcp-server (compatibilité Glama)
|
|
2
|
-
|
|
3
|
-
# Étape 1: Construction de l'application
|
|
4
|
-
FROM node:20-alpine AS builder
|
|
5
|
-
|
|
6
|
-
# Définir le répertoire de travail
|
|
7
|
-
WORKDIR /app
|
|
8
|
-
|
|
9
|
-
# Copier les fichiers de manifeste et de verrouillage des dépendances
|
|
10
|
-
COPY package.json package-lock.json* ./
|
|
11
|
-
|
|
12
|
-
# Installer les dépendances de production et de développement pour la compilation
|
|
13
|
-
RUN npm install
|
|
14
|
-
|
|
15
|
-
# Copier le reste des fichiers sources de l'application
|
|
16
|
-
COPY . .
|
|
17
|
-
|
|
18
|
-
# Compiler le projet TypeScript
|
|
19
|
-
RUN npm run build
|
|
20
|
-
|
|
21
|
-
# Supprimer les dépendances de développement après la compilation
|
|
22
|
-
RUN npm prune --production
|
|
23
|
-
|
|
24
|
-
# Étape 2: Création de l'image de production
|
|
25
|
-
FROM node:20-alpine
|
|
26
|
-
|
|
27
|
-
# Définir le répertoire de travail
|
|
28
|
-
WORKDIR /app
|
|
29
|
-
|
|
30
|
-
# Créer un utilisateur non-root pour exécuter l'application
|
|
31
|
-
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
|
|
32
|
-
|
|
33
|
-
# Copier les dépendances de production et les fichiers compilés depuis l'étape de construction
|
|
34
|
-
COPY --from=builder /app/node_modules ./node_modules
|
|
35
|
-
COPY --from=builder /app/dist ./dist
|
|
36
|
-
COPY --from=builder /app/package.json ./
|
|
37
|
-
|
|
38
|
-
# Définir les variables d'environnement
|
|
39
|
-
# BLOGGER_API_KEY doit être fournie à l'exécution (docker run -e BLOGGER_API_KEY=VOTRE_CLE)
|
|
40
|
-
ENV MCP_MODE=http
|
|
41
|
-
ENV MCP_HTTP_HOST=0.0.0.0
|
|
42
|
-
ENV MCP_HTTP_PORT=3000
|
|
43
|
-
ENV BLOGGER_MAX_RESULTS=10
|
|
44
|
-
ENV BLOGGER_API_TIMEOUT=30000
|
|
45
|
-
ENV LOG_LEVEL=info
|
|
46
|
-
# NODE_ENV=production est souvent une bonne pratique pour les applications Node.js
|
|
47
|
-
ENV NODE_ENV=production
|
|
48
|
-
|
|
49
|
-
# Exposer le port sur lequel l'application écoute
|
|
50
|
-
EXPOSE 3000
|
|
51
|
-
|
|
52
|
-
# Changer le propriétaire des fichiers de l'application pour l'utilisateur non-root
|
|
53
|
-
RUN chown -R appuser:appgroup /app
|
|
54
|
-
|
|
55
|
-
# Basculer vers l'utilisateur non-root
|
|
56
|
-
USER appuser
|
|
57
|
-
|
|
58
|
-
# Commande pour démarrer le serveur
|
|
59
|
-
CMD ["node", "dist/index.js"]
|
|
60
|
-
|
|
61
|
-
# Métadonnées de l'image (optionnel, mais recommandé)
|
|
62
|
-
LABEL maintainer="niyonabil"
|
|
63
|
-
LABEL description="Serveur MCP pour interagir avec l'API Blogger de Google."
|
|
64
|
-
LABEL version="1.0.4" # Se baser sur la version du package.json si possible
|
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;
|