friday-mcp-v2 3.1.2 → 3.1.3
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/dist/mcp-server.js +2297 -162
- package/dist/wordpress-api.js +181 -4
- package/package.json +7 -4
package/dist/wordpress-api.js
CHANGED
|
@@ -414,10 +414,12 @@ export class FridayWPClient {
|
|
|
414
414
|
* @param {Buffer} fileBuffer 画像バイナリ
|
|
415
415
|
* @param {string} filename WordPress 上のファイル名(拡張子付き)
|
|
416
416
|
* @param {string} contentType MIME type (e.g. image/jpeg)
|
|
417
|
+
* @param {{timeoutMs?: number}} options timeout options
|
|
417
418
|
* @returns {object} WP media オブジェクト
|
|
418
419
|
*/
|
|
419
|
-
async uploadMedia(fileBuffer, filename, contentType) {
|
|
420
|
+
async uploadMedia(fileBuffer, filename, contentType, { timeoutMs } = {}) {
|
|
420
421
|
const url = `${this.wpUrl.replace(/\/$/, '')}/wp-json/wp/v2/media`;
|
|
422
|
+
const signal = timeoutMs ? AbortSignal.timeout(timeoutMs) : undefined;
|
|
421
423
|
const res = await fetch(url, {
|
|
422
424
|
method: 'POST',
|
|
423
425
|
headers: {
|
|
@@ -425,6 +427,7 @@ export class FridayWPClient {
|
|
|
425
427
|
'Content-Disposition': `attachment; filename="${encodeURIComponent(filename)}"`,
|
|
426
428
|
'Content-Type': contentType,
|
|
427
429
|
},
|
|
430
|
+
signal,
|
|
428
431
|
body: fileBuffer,
|
|
429
432
|
});
|
|
430
433
|
const text = await res.text();
|
|
@@ -455,6 +458,42 @@ export class FridayWPClient {
|
|
|
455
458
|
});
|
|
456
459
|
}
|
|
457
460
|
|
|
461
|
+
/**
|
|
462
|
+
* メディア単体を取得
|
|
463
|
+
* @param {number} mediaId メディアID
|
|
464
|
+
* @returns {object} WP media オブジェクト
|
|
465
|
+
*/
|
|
466
|
+
async getMedia(mediaId) {
|
|
467
|
+
return this.wpCoreRequest(`/wp/v2/media/${mediaId}`);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* メディアを ID 配列で取得
|
|
472
|
+
* 100件超は 100件チャンクに分割して取得しマージする (Phase 2 列挙パス)。
|
|
473
|
+
* @param {number[]|number} mediaIds メディアID配列
|
|
474
|
+
* @param {object} [options]
|
|
475
|
+
* @param {string} [options.mediaType] 'image' 等の media_type フィルタ。未指定なら全タイプ
|
|
476
|
+
* (move 検証など既存呼び出しは未指定で全タイプ検証を維持する)
|
|
477
|
+
* @returns {object[]} WP media オブジェクト配列
|
|
478
|
+
*/
|
|
479
|
+
async getMediaByIds(mediaIds, { mediaType } = {}) {
|
|
480
|
+
const ids = Array.isArray(mediaIds) ? mediaIds : [mediaIds];
|
|
481
|
+
if (ids.length === 0) return [];
|
|
482
|
+
const CHUNK = 100;
|
|
483
|
+
const out = [];
|
|
484
|
+
for (let i = 0; i < ids.length; i += CHUNK) {
|
|
485
|
+
const chunk = ids.slice(i, i + CHUNK);
|
|
486
|
+
const params = new URLSearchParams({
|
|
487
|
+
include: chunk.join(','),
|
|
488
|
+
per_page: String(chunk.length),
|
|
489
|
+
});
|
|
490
|
+
if (mediaType) params.set('media_type', mediaType);
|
|
491
|
+
const res = await this.wpCoreRequest(`/wp/v2/media?${params.toString()}`);
|
|
492
|
+
if (Array.isArray(res)) out.push(...res);
|
|
493
|
+
}
|
|
494
|
+
return out;
|
|
495
|
+
}
|
|
496
|
+
|
|
458
497
|
/**
|
|
459
498
|
* メディアライブラリを検索(画像のみ)
|
|
460
499
|
* @param {string} query 検索キーワード
|
|
@@ -462,13 +501,20 @@ export class FridayWPClient {
|
|
|
462
501
|
* @returns {object[]} メディアオブジェクト配列
|
|
463
502
|
*/
|
|
464
503
|
async searchMedia(query, perPage = 10, includeIds = null) {
|
|
504
|
+
const hasInclude = Array.isArray(includeIds) && includeIds.length > 0;
|
|
505
|
+
// include 指定(スコープ検索)時のみ最大100。グローバル検索は 1-20 契約を維持 (#9)
|
|
506
|
+
const cap = hasInclude ? 100 : 20;
|
|
465
507
|
const params = new URLSearchParams({
|
|
466
508
|
media_type: 'image',
|
|
467
|
-
per_page: String(Math.min(Math.max(1, perPage),
|
|
509
|
+
per_page: String(Math.min(Math.max(1, perPage), cap)),
|
|
468
510
|
});
|
|
469
511
|
if (query) params.set('search', query);
|
|
470
|
-
if (
|
|
471
|
-
|
|
512
|
+
if (hasInclude) {
|
|
513
|
+
// 呼び出し側が 100件チャンクに分割する前提。違反は黙って切らず明示エラー (#10)
|
|
514
|
+
if (includeIds.length > 100) {
|
|
515
|
+
throw new Error(`searchMedia の includeIds は100件以下にチャンクして渡してください (受領: ${includeIds.length}件)`);
|
|
516
|
+
}
|
|
517
|
+
params.set('include', includeIds.join(','));
|
|
472
518
|
}
|
|
473
519
|
return this.wpCoreRequest(`/wp/v2/media?${params.toString()}`);
|
|
474
520
|
}
|
|
@@ -491,6 +537,115 @@ export class FridayWPClient {
|
|
|
491
537
|
return json.success ? json.data.attachment_ids : null;
|
|
492
538
|
}
|
|
493
539
|
|
|
540
|
+
/**
|
|
541
|
+
* Uncategorized 等の件数取得
|
|
542
|
+
* @param {number} folderId 0=Uncategorized, -1=全総数, >0=通常フォルダ
|
|
543
|
+
* @returns {number|null} 件数。token 未設定/失敗時は null
|
|
544
|
+
*/
|
|
545
|
+
async getFileBirdAttachmentCount(folderId) {
|
|
546
|
+
if (!this.filebirdToken) return null;
|
|
547
|
+
const url = `${this.wpUrl}/wp-json/filebird/public/v1/attachment-count/?folder_id=${folderId}&token=${this.filebirdToken}`;
|
|
548
|
+
const res = await fetch(url);
|
|
549
|
+
if (!res.ok) return null;
|
|
550
|
+
const json = await res.json();
|
|
551
|
+
return json.success ? json.data.count : null;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* FileBird フォルダ作成
|
|
556
|
+
* 注意: 親存在検証なし・同名は "name (1)" 自動リネーム (プラグイン Api.php:103 / Folder.php:453)
|
|
557
|
+
* @param {string} name フォルダ名
|
|
558
|
+
* @param {number} parentId 親 folder id (0=ルート)
|
|
559
|
+
* @returns {object|null} { id } 。token 未設定時は null。失敗時は throw
|
|
560
|
+
*/
|
|
561
|
+
async createFileBirdFolder(name, parentId = 0) {
|
|
562
|
+
if (!this.filebirdToken) return null;
|
|
563
|
+
const url = `${this.wpUrl}/wp-json/filebird/public/v1/folders?token=${this.filebirdToken}`;
|
|
564
|
+
const res = await fetch(url, {
|
|
565
|
+
method: 'POST',
|
|
566
|
+
headers: { 'Content-Type': 'application/json' },
|
|
567
|
+
body: JSON.stringify({ name, parent_id: parentId }),
|
|
568
|
+
});
|
|
569
|
+
if (!res.ok) {
|
|
570
|
+
const text = await res.text();
|
|
571
|
+
const err = new Error(`FileBird createFolder failed (HTTP ${res.status}): ${text.slice(0, 300)}`);
|
|
572
|
+
err.statusCode = res.status;
|
|
573
|
+
throw err;
|
|
574
|
+
}
|
|
575
|
+
const json = await res.json();
|
|
576
|
+
return json.success ? json.data : null;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* 添付メディアをフォルダに割り当て
|
|
581
|
+
* 注意: folder は数値 id のみ (パス不可)・ID 存在検証なし・folder=-1 も通過 (プラグイン Api.php:117)
|
|
582
|
+
* @param {number[]|number} ids 添付 ID (配列または単一)
|
|
583
|
+
* @param {number} folderId 割当先 folder id
|
|
584
|
+
* @returns {boolean|null} 成否。token 未設定時は null。失敗時は throw
|
|
585
|
+
*/
|
|
586
|
+
async setFileBirdAttachmentFolder(ids, folderId) {
|
|
587
|
+
if (!this.filebirdToken) return null;
|
|
588
|
+
const url = `${this.wpUrl}/wp-json/filebird/public/v1/folder/set-attachment?token=${this.filebirdToken}`;
|
|
589
|
+
const res = await fetch(url, {
|
|
590
|
+
method: 'POST',
|
|
591
|
+
headers: { 'Content-Type': 'application/json' },
|
|
592
|
+
body: JSON.stringify({ ids, folder: folderId }),
|
|
593
|
+
});
|
|
594
|
+
if (!res.ok) {
|
|
595
|
+
const text = await res.text();
|
|
596
|
+
const err = new Error(`FileBird setAttachment failed (HTTP ${res.status}): ${text.slice(0, 300)}`);
|
|
597
|
+
err.statusCode = res.status;
|
|
598
|
+
throw err;
|
|
599
|
+
}
|
|
600
|
+
const json = await res.json();
|
|
601
|
+
return json.success === true;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// ========================================
|
|
605
|
+
// FileBird フォルダ rename / delete (Phase 3)
|
|
606
|
+
// admin namespace filebird/v1 を App Password (wpCoreRequest) で叩く。
|
|
607
|
+
// public token は使わない (認証主体を実行ユーザーに統一)。
|
|
608
|
+
// ========================================
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* FileBird フォルダツリー取得 (admin namespace)
|
|
612
|
+
* public getFileBirdFolders と別経路。tree はノードに data-count を持たず、
|
|
613
|
+
* 件数は attachmentsCount で別途返る (呼び出し側で id マージする)。
|
|
614
|
+
* @returns {{ tree: object[], allAttachmentsCount: number, attachmentsCount: object }}
|
|
615
|
+
*/
|
|
616
|
+
async getFileBirdFoldersAdmin() {
|
|
617
|
+
return this.wpCoreRequest('/filebird/v1/get-folders');
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
/**
|
|
621
|
+
* FileBird フォルダ名変更 (admin namespace)
|
|
622
|
+
* 注意: parent は移動用ではなく重複チェック用。現在の parentId をそのまま渡す。
|
|
623
|
+
* @param {number} folderId 対象フォルダ id
|
|
624
|
+
* @param {number} currentParentId 現在の親 id (重複チェック用)
|
|
625
|
+
* @param {string} newName 新フォルダ名
|
|
626
|
+
* @returns {boolean} 成功時 true。同名時は WP_Error('folder_name_exist') が throw される
|
|
627
|
+
*/
|
|
628
|
+
async renameFileBirdFolder(folderId, currentParentId, newName) {
|
|
629
|
+
return this.wpCoreRequest('/filebird/v1/update-folder', {
|
|
630
|
+
method: 'POST',
|
|
631
|
+
body: JSON.stringify({ id: folderId, parent: currentParentId, title: newName }),
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* FileBird フォルダ削除 (admin namespace)
|
|
637
|
+
* FileBird 側で子フォルダへ再帰カスケード削除する (ids は単一で渡す)。
|
|
638
|
+
* 添付ファイル本体は削除されず Uncategorized に残る (fbv / fbv_attachment_folder のみ削除)。
|
|
639
|
+
* @param {number} folderId 対象フォルダ id
|
|
640
|
+
* @returns {object} countAttachments 構造 (削除後の件数)
|
|
641
|
+
*/
|
|
642
|
+
async deleteFileBirdFolder(folderId) {
|
|
643
|
+
return this.wpCoreRequest('/filebird/v1/delete-folder', {
|
|
644
|
+
method: 'POST',
|
|
645
|
+
body: JSON.stringify({ ids: [folderId] }),
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
|
|
494
649
|
// ========================================
|
|
495
650
|
// ASP Link Management
|
|
496
651
|
// ========================================
|
|
@@ -512,6 +667,28 @@ export class FridayWPClient {
|
|
|
512
667
|
});
|
|
513
668
|
}
|
|
514
669
|
|
|
670
|
+
async updateAspLink(id, data) {
|
|
671
|
+
return this.request(`/asp-links/${id}`, {
|
|
672
|
+
method: 'PUT',
|
|
673
|
+
body: JSON.stringify(data),
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
async bulkCreateAspLinks(items) {
|
|
678
|
+
return this.request('/asp-links/bulk', {
|
|
679
|
+
method: 'POST',
|
|
680
|
+
body: JSON.stringify({ items }),
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
async resolveAspLinksBulk(aspIds) {
|
|
685
|
+
const list = Array.isArray(aspIds) ? aspIds : [];
|
|
686
|
+
if (list.length === 0) return { items: {} };
|
|
687
|
+
const query = new URLSearchParams();
|
|
688
|
+
query.set('asp_ids', list.join(','));
|
|
689
|
+
return this.request(`/asp-links/bulk?${query.toString()}`);
|
|
690
|
+
}
|
|
691
|
+
|
|
515
692
|
/**
|
|
516
693
|
* 設定オブジェクトからインスタンスを生成(ConnectionRegistry 用)
|
|
517
694
|
* @param {{ url: string, user: string, pass: string }} config
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "friday-mcp-v2",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.3",
|
|
4
4
|
"description": "WordPress MCP Server for Claude Code - REST API direct communication",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/mcp-server.js",
|
|
@@ -21,11 +21,14 @@
|
|
|
21
21
|
],
|
|
22
22
|
"author": "",
|
|
23
23
|
"license": "MIT",
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=20"
|
|
26
|
+
},
|
|
24
27
|
"dependencies": {
|
|
25
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
26
|
-
"marked": "^
|
|
28
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
29
|
+
"marked": "^18.0.3",
|
|
27
30
|
"node-fetch": "^3.3.2",
|
|
28
31
|
"node-html-parser": "^7.1.0",
|
|
29
|
-
"ws": "^8.
|
|
32
|
+
"ws": "^8.20.0"
|
|
30
33
|
}
|
|
31
34
|
}
|