@dalcontak/blogger-mcp-server 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/.github/workflows/publish.yml +34 -0
- package/AGENTS.md +155 -0
- package/Dockerfile +64 -0
- package/README.md +169 -0
- package/RELEASE.md +125 -0
- package/dist/bloggerService.d.ts +121 -0
- package/dist/bloggerService.js +323 -0
- package/dist/config.d.ts +20 -0
- package/dist/config.js +32 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +304 -0
- package/dist/mcp-sdk-mock.d.ts +57 -0
- package/dist/mcp-sdk-mock.js +227 -0
- package/dist/server.d.ts +16 -0
- package/dist/server.js +448 -0
- package/dist/types.d.ts +94 -0
- package/dist/types.js +2 -0
- package/dist/ui-manager.d.ts +22 -0
- package/dist/ui-manager.js +110 -0
- package/jest.config.js +7 -0
- package/package.json +43 -0
- package/public/index.html +201 -0
- package/public/main.js +271 -0
- package/public/styles.css +155 -0
- package/src/bloggerService.test.ts +398 -0
- package/src/bloggerService.ts +351 -0
- package/src/config.test.ts +121 -0
- package/src/config.ts +33 -0
- package/src/index.ts +349 -0
- package/src/server.ts +443 -0
- package/src/types.ts +113 -0
- package/src/ui-manager.ts +128 -0
- package/start-dev.sh +64 -0
- package/start-prod.sh +53 -0
- package/tsconfig.json +15 -0
- package/vercel.json +24 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: Build and Publish to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- 'release/**'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
id-token: write
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
build-and-publish:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- name: Checkout code
|
|
16
|
+
uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Setup Node.js
|
|
19
|
+
uses: actions/setup-node@v6
|
|
20
|
+
with:
|
|
21
|
+
node-version: '20'
|
|
22
|
+
registry-url: 'https://registry.npmjs.org'
|
|
23
|
+
|
|
24
|
+
- name: Install dependencies
|
|
25
|
+
run: npm ci
|
|
26
|
+
|
|
27
|
+
- name: Run tests
|
|
28
|
+
run: npm test
|
|
29
|
+
|
|
30
|
+
- name: Build
|
|
31
|
+
run: npm run build
|
|
32
|
+
|
|
33
|
+
- name: Publish to npm
|
|
34
|
+
run: npm publish --provenance --access public
|
package/AGENTS.md
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
# AGENTS.md - Coding Agent Guidelines
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
|
|
5
|
+
MCP (Model Context Protocol) server for Google's Blogger API. Allows AI models to
|
|
6
|
+
interact with Blogger blogs via stdio or HTTP transport. Includes an optional web dashboard
|
|
7
|
+
(Express + Socket.IO) on a separate port when `UI_PORT` is set. Written in TypeScript, targeting Node.js 20.
|
|
8
|
+
|
|
9
|
+
Package: `@mcproadev/blogger-mcp-server` (v1.0.4)
|
|
10
|
+
|
|
11
|
+
## Build / Run / Test Commands
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Install dependencies
|
|
15
|
+
npm install
|
|
16
|
+
|
|
17
|
+
# Build (compiles TypeScript to dist/)
|
|
18
|
+
npm run build # runs: tsc
|
|
19
|
+
|
|
20
|
+
# Run production
|
|
21
|
+
npm start # runs: node dist/index.js
|
|
22
|
+
|
|
23
|
+
# Run development
|
|
24
|
+
npm run dev # runs: ts-node src/index.ts
|
|
25
|
+
|
|
26
|
+
# Lint
|
|
27
|
+
npm run lint # runs: eslint src/**/*.ts
|
|
28
|
+
|
|
29
|
+
# Tests (jest is declared but NOT installed - no tests exist yet)
|
|
30
|
+
npm test # runs: jest
|
|
31
|
+
# Single test (once jest + ts-jest are installed):
|
|
32
|
+
# npx jest path/to/file.test.ts
|
|
33
|
+
# npx jest -t "test name pattern"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Note:** There is no eslint config file (`.eslintrc.*`). ESLint will use defaults.
|
|
37
|
+
Jest is referenced in the test script but is not in devDependencies and no test files
|
|
38
|
+
exist. If adding tests, install `jest`, `ts-jest`, and `@types/jest` first.
|
|
39
|
+
|
|
40
|
+
## Project Structure
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
src/
|
|
44
|
+
index.ts # Entry point, main() function, HTTP mode routing
|
|
45
|
+
server.ts # MCP server tool registration (initMCPServer)
|
|
46
|
+
bloggerService.ts # Google Blogger API wrapper (BloggerService class)
|
|
47
|
+
config.ts # Environment-based configuration object
|
|
48
|
+
types.ts # Shared interfaces and type definitions
|
|
49
|
+
ui-manager.ts # Express + Socket.IO web dashboard
|
|
50
|
+
public/ # Static web UI assets (HTML/JS/CSS)
|
|
51
|
+
dist/ # Compiled output (committed to repo)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## TypeScript Configuration
|
|
55
|
+
|
|
56
|
+
- **Target:** ES2020, **Module:** CommonJS
|
|
57
|
+
- **Strict mode:** enabled
|
|
58
|
+
- **Declaration files:** generated in `dist/`
|
|
59
|
+
- **Excludes:** `node_modules`, `dist`, `**/*.test.ts`
|
|
60
|
+
|
|
61
|
+
## Environment Variables
|
|
62
|
+
|
|
63
|
+
| Variable | Default | Description |
|
|
64
|
+
|----------|---------|-------------|
|
|
65
|
+
| `BLOGGER_API_KEY` | (optional) | Google Blogger API key (read-only access to public blogs) |
|
|
66
|
+
| `GOOGLE_CLIENT_ID` | (optional) | OAuth2 client ID (for full read/write access) |
|
|
67
|
+
| `GOOGLE_CLIENT_SECRET` | (optional) | OAuth2 client secret |
|
|
68
|
+
| `GOOGLE_REFRESH_TOKEN` | (optional) | OAuth2 refresh token (scope: `blogger`) |
|
|
69
|
+
| `MCP_MODE` | `stdio` | Transport: `stdio` or `http` |
|
|
70
|
+
| `MCP_HTTP_HOST` | `0.0.0.0` | HTTP host |
|
|
71
|
+
| `MCP_HTTP_PORT` | `3000` | HTTP port |
|
|
72
|
+
| `BLOGGER_MAX_RESULTS` | `10` | Max results per query |
|
|
73
|
+
| `BLOGGER_API_TIMEOUT` | `30000` | API timeout (ms) |
|
|
74
|
+
| `LOG_LEVEL` | `info` | Logging level |
|
|
75
|
+
| `UI_PORT` | (disabled) | Web dashboard port (set to enable) |
|
|
76
|
+
|
|
77
|
+
**Authentication:** At least one auth method is required:
|
|
78
|
+
- **API Key only** (`BLOGGER_API_KEY`): read-only access to public blogs. Works for `get_blog`,
|
|
79
|
+
`get_blog_by_url`, `list_posts`, `get_post`, `search_posts`, `list_labels`, `get_label`.
|
|
80
|
+
- **OAuth2** (`GOOGLE_CLIENT_ID` + `GOOGLE_CLIENT_SECRET` + `GOOGLE_REFRESH_TOKEN`): full access.
|
|
81
|
+
Required for `list_blogs`, `create_post`, `update_post`, `delete_post`.
|
|
82
|
+
- If both are set, OAuth2 is used (it covers all operations).
|
|
83
|
+
|
|
84
|
+
## Code Style Guidelines
|
|
85
|
+
|
|
86
|
+
### Imports
|
|
87
|
+
|
|
88
|
+
- Use **named imports** for local modules: `import { config } from './config'`
|
|
89
|
+
- Use **default imports** for third-party/Node.js modules: `import express from 'express'`
|
|
90
|
+
- Use **relative paths** only (`./config`, `./types`) -- no path aliases
|
|
91
|
+
- MCP SDK uses subpath imports with `.js` extension:
|
|
92
|
+
`import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'`
|
|
93
|
+
- Import order (not enforced but conventional):
|
|
94
|
+
1. Third-party packages
|
|
95
|
+
2. Node.js built-ins
|
|
96
|
+
3. Local modules
|
|
97
|
+
|
|
98
|
+
### Naming Conventions
|
|
99
|
+
|
|
100
|
+
| Element | Convention | Examples |
|
|
101
|
+
|---------|-----------|----------|
|
|
102
|
+
| Classes | PascalCase | `BloggerService`, `WebUIManager` |
|
|
103
|
+
| Interfaces | PascalCase | `BloggerBlog`, `ServerConfig` |
|
|
104
|
+
| Type aliases | PascalCase | `ServerMode` |
|
|
105
|
+
| Functions | camelCase | `initMCPServer`, `listBlogs` |
|
|
106
|
+
| Variables/properties | camelCase | `bloggerService`, `serverMode` |
|
|
107
|
+
| MCP tool names | snake_case | `list_blogs`, `get_blog`, `get_blog_by_url`, `create_post` |
|
|
108
|
+
| Environment vars | UPPER_SNAKE_CASE | `BLOGGER_API_KEY`, `MCP_MODE` |
|
|
109
|
+
| Files | camelCase or kebab-case | `bloggerService.ts`, `ui-manager.ts` |
|
|
110
|
+
|
|
111
|
+
### TypeScript Patterns
|
|
112
|
+
|
|
113
|
+
- Prefer `interface` over `type` for object shapes; use `type` for unions/aliases
|
|
114
|
+
- Use `Partial<T>` for optional update parameters
|
|
115
|
+
- Use `zod` for runtime validation of MCP tool parameters
|
|
116
|
+
- Use googleapis types directly: `blogger_v3.Schema$Blog`, `blogger_v3.Schema$Post`
|
|
117
|
+
- Avoid `any` -- only acceptable in generic SDK mock/adapter code
|
|
118
|
+
- Use `as const` for literal type narrowing where needed
|
|
119
|
+
- All exports are **named exports** (no default exports)
|
|
120
|
+
|
|
121
|
+
### Error Handling
|
|
122
|
+
|
|
123
|
+
- Wrap async method bodies in `try/catch`
|
|
124
|
+
- In service layer (`bloggerService.ts`): log with `console.error()`, then re-throw
|
|
125
|
+
- In MCP tool handlers (`server.ts`): log with `console.error()`, return error response:
|
|
126
|
+
```typescript
|
|
127
|
+
{ content: [{ type: 'text', text: `Error message: ${error}` }], isError: true }
|
|
128
|
+
```
|
|
129
|
+
- In entry point (`index.ts`): catch fatal errors and call `process.exit(1)`
|
|
130
|
+
- Error messages and console output are written in **French**
|
|
131
|
+
- No custom error classes -- use plain `Error` or re-throw caught errors
|
|
132
|
+
|
|
133
|
+
### Async Patterns
|
|
134
|
+
|
|
135
|
+
- Use `async/await` exclusively -- no raw Promise chains
|
|
136
|
+
- Use `Promise` constructor only when wrapping callback-based APIs (HTTP, streams)
|
|
137
|
+
- Top-level `main()` is async and called directly
|
|
138
|
+
|
|
139
|
+
### General Patterns
|
|
140
|
+
|
|
141
|
+
- One module per file with single responsibility
|
|
142
|
+
- Private/internal interfaces defined locally in the file that uses them
|
|
143
|
+
- Class-based design for services (`BloggerService`, `WebUIManager`)
|
|
144
|
+
- Functional approach for setup/registration (`initMCPServer`)
|
|
145
|
+
|
|
146
|
+
## Known Issues / Gotchas
|
|
147
|
+
|
|
148
|
+
- `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
|
+
- HTTP mode in `index.ts` has a manual tool-routing switch that duplicates `server.ts` logic
|
|
151
|
+
|
|
152
|
+
## Deployment
|
|
153
|
+
|
|
154
|
+
- **Vercel:** configured via `vercel.json` (uses `@vercel/node`, HTTP mode, port 3000)
|
|
155
|
+
- **Docker:** multi-stage build with `node:20-alpine`, runs as non-root, exposes port 3000
|
package/Dockerfile
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
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/README.md
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# blogger-mcp-server
|
|
2
|
+
=======
|
|
3
|
+
# Serveur MCP pour Blogger
|
|
4
|
+
|
|
5
|
+
Un serveur MCP (Model Context Protocol) qui permet aux modèles d'intelligence artificielle comme Claude d'interagir directement avec l'API Blogger de Google.
|
|
6
|
+
|
|
7
|
+
## À propos
|
|
8
|
+
|
|
9
|
+
Ce projet implémente un serveur compatible avec le protocole MCP (Model Context Protocol) pour l'API Blogger de Google. Il permet aux modèles d'IA comme Claude d'interagir avec les blogs Blogger pour :
|
|
10
|
+
|
|
11
|
+
* Lister et récupérer des blogs
|
|
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
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
### Installation depuis npm
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install -g @mcproadev/blogger-mcp-server
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Installation depuis le code source
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
git clone https://github.com/niyonabil/blogger-mcp-server.git
|
|
34
|
+
cd blogger-mcp-server
|
|
35
|
+
npm install
|
|
36
|
+
npm run build
|
|
37
|
+
```
|
|
38
|
+
if error install :
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install --save-dev @types/express
|
|
42
|
+
```
|
|
43
|
+
## Configuration
|
|
44
|
+
|
|
45
|
+
### Obtenir une clé API Blogger
|
|
46
|
+
|
|
47
|
+
1. Accédez à la [Console Google Cloud](https://console.cloud.google.com/)
|
|
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
|
|
52
|
+
|
|
53
|
+
### Configuration du serveur MCP
|
|
54
|
+
|
|
55
|
+
Créez un fichier de configuration pour votre client MCP. Voici un exemple pour Claude Desktop :
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{
|
|
59
|
+
"mcpServers": {
|
|
60
|
+
"blogger": {
|
|
61
|
+
"command": "npx",
|
|
62
|
+
"args": [
|
|
63
|
+
"-y",
|
|
64
|
+
"@mcproadev/blogger-mcp-server"
|
|
65
|
+
],
|
|
66
|
+
"env": {
|
|
67
|
+
"BLOGGER_API_KEY": "VOTRE_CLE_API_ICI"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Remplacez `VOTRE_CLE_API_ICI` par la clé API que vous avez obtenue.
|
|
75
|
+
|
|
76
|
+
## Utilisation
|
|
77
|
+
|
|
78
|
+
### Démarrage local
|
|
79
|
+
|
|
80
|
+
Le projet inclut deux scripts pour faciliter le démarrage du serveur :
|
|
81
|
+
|
|
82
|
+
#### Mode développement
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
export BLOGGER_API_KEY=votre_cle_api
|
|
86
|
+
./start-dev.sh
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Ce script vérifie la présence de la clé API, installe les dépendances si nécessaire, compile le projet si nécessaire, puis démarre le serveur en mode développement.
|
|
90
|
+
|
|
91
|
+
#### Mode production
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
export BLOGGER_API_KEY=votre_cle_api
|
|
95
|
+
npm run build
|
|
96
|
+
./start-prod.sh
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Ce script vérifie la présence de la clé API et que le projet est compilé, puis démarre le serveur en mode production.
|
|
100
|
+
|
|
101
|
+
### Utilisation avec un client MCP
|
|
102
|
+
|
|
103
|
+
Une fois configuré, vous pouvez utiliser le serveur MCP pour Blogger avec n'importe quel client MCP compatible, comme Claude Desktop.
|
|
104
|
+
|
|
105
|
+
Exemples de commandes :
|
|
106
|
+
|
|
107
|
+
* "Liste tous mes blogs Blogger"
|
|
108
|
+
* "Crée un nouveau post sur mon blog avec l'ID 123456 avec le titre 'Mon nouveau post' et le contenu 'Voici le contenu de mon post'"
|
|
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'"
|
|
111
|
+
|
|
112
|
+
## Options de déploiement
|
|
113
|
+
|
|
114
|
+
### Déploiement sur Vercel
|
|
115
|
+
|
|
116
|
+
Le projet inclut un fichier `vercel.json` pour faciliter le déploiement sur Vercel :
|
|
117
|
+
|
|
118
|
+
1. Créez un compte sur [Vercel](https://vercel.com/) si vous n'en avez pas déjà un
|
|
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`
|
|
123
|
+
|
|
124
|
+
### Déploiement avec Docker
|
|
125
|
+
|
|
126
|
+
Le projet inclut un Dockerfile pour faciliter le déploiement dans un conteneur Docker :
|
|
127
|
+
|
|
128
|
+
1. Construisez l'image Docker :
|
|
129
|
+
```bash
|
|
130
|
+
docker build -t blogger-mcp-server .
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
2. Exécutez le conteneur :
|
|
134
|
+
```bash
|
|
135
|
+
docker run -p 3000:3000 -e BLOGGER_API_KEY=votre_cle_api blogger-mcp-server
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Autres options de déploiement
|
|
139
|
+
|
|
140
|
+
Le serveur peut également être déployé sur d'autres plateformes compatibles avec Node.js :
|
|
141
|
+
|
|
142
|
+
1. **Heroku** : Utilisez un Procfile et les variables d'environnement Heroku
|
|
143
|
+
2. **AWS Lambda** : Utilisez un adaptateur comme Serverless Framework
|
|
144
|
+
3. **Google Cloud Run** : Utilisez le Dockerfile inclus
|
|
145
|
+
|
|
146
|
+
## Structure du projet
|
|
147
|
+
|
|
148
|
+
Le serveur MCP pour Blogger est composé de plusieurs modules :
|
|
149
|
+
|
|
150
|
+
* `index.ts` : Point d'entrée principal
|
|
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
|
|
155
|
+
|
|
156
|
+
## Limitations connues
|
|
157
|
+
|
|
158
|
+
* **Création de blogs** : L'API Blogger de Google ne permet pas de créer de nouveaux blogs via API. Les blogs doivent être créés manuellement via l'interface web de Blogger.
|
|
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`.
|
|
162
|
+
|
|
163
|
+
## Contribution
|
|
164
|
+
|
|
165
|
+
Les contributions sont les bienvenues ! N'hésitez pas à ouvrir une issue ou une pull request.
|
|
166
|
+
|
|
167
|
+
## Licence
|
|
168
|
+
|
|
169
|
+
Ce projet est sous licence MIT.
|
package/RELEASE.md
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Release Process for @dalcontak/blogger-mcp-server
|
|
2
|
+
|
|
3
|
+
This document explains how to create releases and publish to npm.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
### Setup Trusted Publishing (OIDC)
|
|
8
|
+
|
|
9
|
+
IMPORTANT: npm classic tokens are deprecated (revoked Nov 19, 2025). Fine-grained tokens have a 90-day maximum lifetime. The recommended approach is **Trusted Publishing (OIDC)**.
|
|
10
|
+
|
|
11
|
+
#### Step 1: Configure GitHub Actions as Trusted Publisher
|
|
12
|
+
|
|
13
|
+
The correct navigation is:
|
|
14
|
+
1. Go to https://www.npmjs.com/package/@dalcontak/blogger-mcp-server
|
|
15
|
+
2. Click on **"Settings"** tab
|
|
16
|
+
3. Find the **"Trusted Publishers"** section
|
|
17
|
+
4. Click on **"GitHub Actions"** (or "Set up connection" button)
|
|
18
|
+
5. Fill in:
|
|
19
|
+
- **Organization or user**: `dalcontak`
|
|
20
|
+
- **Repository**: `dalcontak/blogger-mcp-server`
|
|
21
|
+
- **Workflow filename**: `publish.yml` (name of the workflow file, NOT the full path)
|
|
22
|
+
6. Click **"Set up connection"**
|
|
23
|
+
|
|
24
|
+
Optional but recommended:
|
|
25
|
+
- ✅ **Require two-factor authentication**
|
|
26
|
+
- ✅ **Disallow tokens** (forces OIDC usage)
|
|
27
|
+
|
|
28
|
+
That's it! No token needed — OIDC generates short-lived, job-specific credentials automatically.
|
|
29
|
+
|
|
30
|
+
## Version Naming
|
|
31
|
+
|
|
32
|
+
Follow semantic versioning: `MAJOR.MINOR.PATCH`
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
- `1.0.0` - Initial release
|
|
36
|
+
- `1.0.1` - Bug fix
|
|
37
|
+
- `1.1.0` - New feature
|
|
38
|
+
- `2.0.0` - Breaking change
|
|
39
|
+
|
|
40
|
+
## Release Process
|
|
41
|
+
|
|
42
|
+
### Step 1: Update version in package.json
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Open package.json and update version
|
|
46
|
+
# "version": "1.1.7"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Step 2: Commit version bump
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
git add package.json
|
|
53
|
+
git commit -m "chore: bump version to 1.1.7"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Step 3: Create and push release branch
|
|
57
|
+
|
|
58
|
+
Branch naming convention: `release-X.Y.Z`
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Create release branch with version in name
|
|
62
|
+
git checkout -b release-1.1.7
|
|
63
|
+
|
|
64
|
+
# Merge main into release branch
|
|
65
|
+
git merge main
|
|
66
|
+
|
|
67
|
+
# Push to GitHub
|
|
68
|
+
git push -u origin release-1.1.7
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Step 4: Automated Build and Publish
|
|
72
|
+
|
|
73
|
+
GitHub Actions will automatically:
|
|
74
|
+
1. ✅ Checkout code
|
|
75
|
+
2. ✅ Setup Node.js v20
|
|
76
|
+
3. ✅ Install dependencies
|
|
77
|
+
4. ✅ Run tests (npm test)
|
|
78
|
+
5. ✅ Build (npm run build)
|
|
79
|
+
6. ✅ Publish to npm using OIDC (no manual token needed)
|
|
80
|
+
|
|
81
|
+
The workflow triggers on any push to branches matching `release/**`.
|
|
82
|
+
|
|
83
|
+
## Install Published Version
|
|
84
|
+
|
|
85
|
+
After successful publish:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Global install
|
|
89
|
+
npm install -g @dalcontak/blogger-mcp-server
|
|
90
|
+
|
|
91
|
+
# Local install in a project
|
|
92
|
+
npm install @dalcontak/blogger-mcp-server
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Notes
|
|
96
|
+
|
|
97
|
+
- The branch name **must** contain version after "release-" (e.g., `release-1.1.7`)
|
|
98
|
+
- Version format: **3 digits separated by dots** (X.Y.Z)
|
|
99
|
+
- Only pushes to `release/**` branches trigger the build/publish workflow
|
|
100
|
+
- **No GitHub secrets needed** for OIDC — just configure trusted publisher connection
|
|
101
|
+
- Requires Node.js >= 11.5.1 (npm automatically detects OIDC credentials)
|
|
102
|
+
|
|
103
|
+
## Troubleshooting
|
|
104
|
+
|
|
105
|
+
### Error: "You are not set up to publish with OIDC"
|
|
106
|
+
|
|
107
|
+
Make sure:
|
|
108
|
+
1. GitHub Actions is configured as **Trusted Publisher** in npm settings
|
|
109
|
+
2. Workflow filename matches: `publish.yml`
|
|
110
|
+
3. Repository is correct: `dalcontak/blogger-mcp-server`
|
|
111
|
+
4. Workflow has `permissions: id-token: write`
|
|
112
|
+
|
|
113
|
+
### Error: "npm publish --provenance requires Node.js >= 11.5.1"
|
|
114
|
+
|
|
115
|
+
The workflow uses `actions/setup-node@v6` which sets up Node.js 20. If you see this error, check your Node.js version.
|
|
116
|
+
|
|
117
|
+
## Comparison: Tokens vs OIDC
|
|
118
|
+
|
|
119
|
+
| Aspect | Classic Tokens | Fine-grained Tokens | Trusted Publishing (OIDC) |
|
|
120
|
+
|---------|----------------|--------------------|---------------------------|
|
|
121
|
+
| **Status** | ❌ Deprecated (revoked) | ⚠️ Limited to 90 days | ✅ Recommended |
|
|
122
|
+
| **Rotation** | Manual (every 90 days max) | Manual (every 90 days max) | Automatic (job-specific) |
|
|
123
|
+
| **Security** | Long-lived, stored in secrets | Short-lived, stored in secrets | Short-lived, job-specific |
|
|
124
|
+
| **GitHub Secret** | Required (NPM_TOKEN) | Required (NPM_TOKEN) | ❌ Not needed |
|
|
125
|
+
| **Setup** | Create token, add to secrets | Create token, add to secrets | Configure in npmjs.com |
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { blogger_v3 } from 'googleapis';
|
|
2
|
+
import { BloggerBlog, BloggerPost, BloggerLabel } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Custom types to compensate for Blogger API limitations
|
|
5
|
+
*/
|
|
6
|
+
interface BloggerLabelList {
|
|
7
|
+
kind?: string;
|
|
8
|
+
items?: BloggerLabel[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Google Blogger API interaction service
|
|
12
|
+
*
|
|
13
|
+
* Supports two authentication modes:
|
|
14
|
+
* - OAuth2 (GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET + GOOGLE_REFRESH_TOKEN):
|
|
15
|
+
* full access (read + write). Required for listBlogs, createPost, updatePost, deletePost.
|
|
16
|
+
* - API Key (BLOGGER_API_KEY): read-only access to public blogs.
|
|
17
|
+
* Works for getBlog, listPosts, getPost, searchPosts, listLabels, getLabel.
|
|
18
|
+
*
|
|
19
|
+
* If both are configured, OAuth2 is used (it covers all operations).
|
|
20
|
+
*/
|
|
21
|
+
export declare class BloggerService {
|
|
22
|
+
private blogger;
|
|
23
|
+
private readonly isOAuth2;
|
|
24
|
+
/**
|
|
25
|
+
* Initializes the Blogger service with OAuth2 or API key
|
|
26
|
+
*/
|
|
27
|
+
constructor();
|
|
28
|
+
/**
|
|
29
|
+
* Checks that OAuth2 authentication is available.
|
|
30
|
+
* Throws an explicit error if the operation requires OAuth2 and we are in API key mode.
|
|
31
|
+
*/
|
|
32
|
+
private requireOAuth2;
|
|
33
|
+
/**
|
|
34
|
+
* Lists all blogs for the authenticated user.
|
|
35
|
+
* Requires OAuth2 (blogs.listByUser with userId: 'self').
|
|
36
|
+
* @returns Blog list
|
|
37
|
+
*/
|
|
38
|
+
listBlogs(): Promise<blogger_v3.Schema$BlogList>;
|
|
39
|
+
/**
|
|
40
|
+
* Retrieves details of a specific blog
|
|
41
|
+
* @param blogId ID of the blog to retrieve
|
|
42
|
+
* @returns Blog details
|
|
43
|
+
*/
|
|
44
|
+
getBlog(blogId: string): Promise<blogger_v3.Schema$Blog>;
|
|
45
|
+
/**
|
|
46
|
+
* Retrieves a blog by its URL
|
|
47
|
+
* @param url Blog URL
|
|
48
|
+
* @returns Blog details
|
|
49
|
+
*/
|
|
50
|
+
getBlogByUrl(url: string): Promise<blogger_v3.Schema$Blog>;
|
|
51
|
+
/**
|
|
52
|
+
* Simulates blog creation.
|
|
53
|
+
* Note: The Blogger API does not actually allow creating a blog via API.
|
|
54
|
+
* This method simulates the functionality and returns an explanatory error message.
|
|
55
|
+
*
|
|
56
|
+
* @param blogData Blog data to create
|
|
57
|
+
* @returns Explanatory error message
|
|
58
|
+
*/
|
|
59
|
+
createBlog(blogData: Partial<BloggerBlog>): Promise<any>;
|
|
60
|
+
/**
|
|
61
|
+
* Lists posts from a blog
|
|
62
|
+
* @param blogId Blog ID
|
|
63
|
+
* @param maxResults Maximum number of results to return
|
|
64
|
+
* @returns Post list
|
|
65
|
+
*/
|
|
66
|
+
listPosts(blogId: string, maxResults?: number): Promise<blogger_v3.Schema$PostList>;
|
|
67
|
+
/**
|
|
68
|
+
* Searches posts in a blog using the native posts.search endpoint of the Blogger API
|
|
69
|
+
* @param blogId Blog ID
|
|
70
|
+
* @param query Search term
|
|
71
|
+
* @param maxResults Maximum number of results to return
|
|
72
|
+
* @returns List of matching posts
|
|
73
|
+
*/
|
|
74
|
+
searchPosts(blogId: string, query: string, maxResults?: number): Promise<blogger_v3.Schema$PostList>;
|
|
75
|
+
/**
|
|
76
|
+
* Retrieves a specific post
|
|
77
|
+
* @param blogId Blog ID
|
|
78
|
+
* @param postId Post ID
|
|
79
|
+
* @returns Post details
|
|
80
|
+
*/
|
|
81
|
+
getPost(blogId: string, postId: string): Promise<blogger_v3.Schema$Post>;
|
|
82
|
+
/**
|
|
83
|
+
* Creates a new post in a blog.
|
|
84
|
+
* Requires OAuth2.
|
|
85
|
+
* @param blogId Blog ID
|
|
86
|
+
* @param postData Post data to create
|
|
87
|
+
* @returns Created post
|
|
88
|
+
*/
|
|
89
|
+
createPost(blogId: string, postData: Partial<BloggerPost>): Promise<blogger_v3.Schema$Post>;
|
|
90
|
+
/**
|
|
91
|
+
* Updates an existing post.
|
|
92
|
+
* Requires OAuth2.
|
|
93
|
+
* @param blogId Blog ID
|
|
94
|
+
* @param postId Post ID
|
|
95
|
+
* @param postData Post data to update
|
|
96
|
+
* @returns Updated post
|
|
97
|
+
*/
|
|
98
|
+
updatePost(blogId: string, postId: string, postData: Partial<BloggerPost>): Promise<blogger_v3.Schema$Post>;
|
|
99
|
+
/**
|
|
100
|
+
* Deletes a post.
|
|
101
|
+
* Requires OAuth2.
|
|
102
|
+
* @param blogId Blog ID
|
|
103
|
+
* @param postId Post ID
|
|
104
|
+
* @returns Deletion status
|
|
105
|
+
*/
|
|
106
|
+
deletePost(blogId: string, postId: string): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Lists labels from a blog
|
|
109
|
+
* @param blogId Blog ID
|
|
110
|
+
* @returns Label list
|
|
111
|
+
*/
|
|
112
|
+
listLabels(blogId: string): Promise<BloggerLabelList>;
|
|
113
|
+
/**
|
|
114
|
+
* Retrieves a specific label
|
|
115
|
+
* @param blogId Blog ID
|
|
116
|
+
* @param labelName Label name
|
|
117
|
+
* @returns Label details
|
|
118
|
+
*/
|
|
119
|
+
getLabel(blogId: string, labelName: string): Promise<BloggerLabel>;
|
|
120
|
+
}
|
|
121
|
+
export {};
|