x-quick-mcp-server 0.1.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/README.md ADDED
@@ -0,0 +1,132 @@
1
+ # x-quick-mcp-server
2
+
3
+ xAI Responses API を使って X(旧Twitter)の投稿をリアルタイム検索する MCP サーバー。
4
+
5
+ Claude.ai / Claude Code / Claude Desktop から `npx` で実行できます。
6
+
7
+ ## セットアップ
8
+
9
+ ### 1. xAI API キーの取得
10
+
11
+ [xAI Console](https://console.x.ai) でアカウントを作成し、APIキーを取得してください。
12
+
13
+ ### 2. Claude.ai での設定
14
+
15
+ Claude.ai の Settings → MCP Servers に以下を追加:
16
+
17
+ ```json
18
+ {
19
+ "mcpServers": {
20
+ "x-quick": {
21
+ "command": "npx",
22
+ "args": ["-y", "x-quick-mcp-server"],
23
+ "env": {
24
+ "XAI_API_KEY": "xai-xxxxxxxxxxxxxxxx"
25
+ }
26
+ }
27
+ }
28
+ }
29
+ ```
30
+
31
+ ### Claude Desktop での設定
32
+
33
+ `claude_desktop_config.json` に追加:
34
+
35
+ ```json
36
+ {
37
+ "mcpServers": {
38
+ "x-quick": {
39
+ "command": "npx",
40
+ "args": ["-y", "x-quick-mcp-server"],
41
+ "env": {
42
+ "XAI_API_KEY": "xai-xxxxxxxxxxxxxxxx"
43
+ }
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ ### Claude Code での設定
50
+
51
+ ```bash
52
+ claude mcp add x-quick -e XAI_API_KEY=xai-xxx -- npx -y x-quick-mcp-server
53
+ ```
54
+
55
+ ## APIキーの管理
56
+
57
+ 環境変数 `XAI_API_KEY` で管理します(MCP設定の `env` フィールドで渡す)。
58
+
59
+ ウォッチリストのカスタマイズなど追加設定が必要な場合は、`~/.config/x-quick-mcp/config.json` を作成することもできます(環境変数のAPIキーが常に優先):
60
+
61
+ ```json
62
+ {
63
+ "default_model": "grok-4-1-fast",
64
+ "watchlist_handles": [
65
+ "ai_biostat",
66
+ "_daichikonno",
67
+ "ctgptlb",
68
+ "nukonuko",
69
+ "usutaku_channel",
70
+ "masahirochaen",
71
+ "karaage0703"
72
+ ],
73
+ "default_watchlist_period": "24h",
74
+ "default_weekly_topic": "医療AI・内視鏡AI・消化器内科AI・生成AI全般",
75
+ "store_conversations": false
76
+ }
77
+ ```
78
+
79
+ ## ツール一覧
80
+
81
+ ### `x_search` — 汎用X検索
82
+
83
+ X の投稿をリアルタイムで検索します。
84
+
85
+ | パラメータ | 型 | 必須 | 説明 |
86
+ |-----------|---|------|------|
87
+ | `query` | string | ✅ | 自然言語の検索クエリ |
88
+ | `allowed_handles` | string[] | - | 指定ユーザーのみ検索(@なし、最大10件) |
89
+ | `excluded_handles` | string[] | - | 指定ユーザーを除外(@なし、最大10件) |
90
+ | `from_date` | string | - | 開始日(YYYY-MM-DD) |
91
+ | `to_date` | string | - | 終了日(YYYY-MM-DD) |
92
+ | `model` | string | - | 使用モデル(grok-4-1-fast / grok-4-1-fast-reasoning / grok-4) |
93
+ | `include_web_search` | boolean | - | Web検索も併用するか |
94
+
95
+ ### `x_watchlist` — ウォッチリスト検索
96
+
97
+ デフォルトの医療AI関連アカウントの最新投稿を取得・要約します。
98
+
99
+ | パラメータ | 型 | 必須 | 説明 |
100
+ |-----------|---|------|------|
101
+ | `period` | string | - | 検索期間(24h / 3d / 1w) |
102
+ | `extra_handles` | string[] | - | 追加で含めるハンドル |
103
+
104
+ ### `x_weekly` — 週次トレンドレポート
105
+
106
+ 過去7日間のXの投稿から、指定トピックのトレンドを週次レポート形式でまとめます。
107
+
108
+ | パラメータ | 型 | 必須 | 説明 |
109
+ |-----------|---|------|------|
110
+ | `topic` | string | - | 対象トピック(デフォルト: 医療AI・内視鏡AI・消化器内科AI・生成AI全般) |
111
+ | `model` | string | - | 使用モデル(デフォルト: grok-4-1-fast-reasoning) |
112
+
113
+ ## ローカル開発
114
+
115
+ ```bash
116
+ git clone https://github.com/your-repo/x-quick-mcp-server.git
117
+ cd x-quick-mcp-server
118
+ npm install
119
+ npm run build
120
+ node dist/index.js
121
+ ```
122
+
123
+ ## 注意事項
124
+
125
+ - xAI API は従量課金制です(https://docs.x.ai/developers/models)
126
+ - レート制限があります(https://docs.x.ai/developers/rate-limits)
127
+ - `x_weekly` は `grok-4-1-fast-reasoning` を使用するため、応答に最大3分かかる場合があります
128
+ - 会話の保存を無効にするには `store_conversations: false`(デフォルト)
129
+
130
+ ## ライセンス
131
+
132
+ MIT
@@ -0,0 +1,11 @@
1
+ export interface XQuickConfig {
2
+ xai_api_key: string;
3
+ default_model: string;
4
+ watchlist_handles: string[];
5
+ default_watchlist_period: string;
6
+ default_weekly_topic: string;
7
+ store_conversations: boolean;
8
+ }
9
+ export declare function loadConfig(): XQuickConfig;
10
+ export declare function validateApiKey(config: XQuickConfig): void;
11
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,wBAAwB,EAAE,MAAM,CAAC;IACjC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAsBD,wBAAgB,UAAU,IAAI,YAAY,CAiBzC;AAaD,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAYzD"}
package/dist/config.js ADDED
@@ -0,0 +1,59 @@
1
+ import { readFileSync, existsSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ const DEFAULT_CONFIG = {
5
+ default_model: "grok-4-1-fast",
6
+ watchlist_handles: [
7
+ "ai_biostat",
8
+ "_daichikonno",
9
+ "ctgptlb",
10
+ "nukonuko",
11
+ "usutaku_channel",
12
+ "masahirochaen",
13
+ "karaage0703",
14
+ ],
15
+ default_watchlist_period: "24h",
16
+ default_weekly_topic: "医療AI・内視鏡AI・消化器内科AI・生成AI全般",
17
+ store_conversations: false,
18
+ };
19
+ function getConfigPath() {
20
+ return join(homedir(), ".config", "x-quick-mcp", "config.json");
21
+ }
22
+ export function loadConfig() {
23
+ // 1. Environment variable (highest priority — designed for MCP env config)
24
+ const envKey = process.env["XAI_API_KEY"];
25
+ if (envKey) {
26
+ // Load config file for non-key settings if it exists, but env key wins
27
+ const fileConfig = loadConfigFile();
28
+ return { ...DEFAULT_CONFIG, ...fileConfig, xai_api_key: envKey };
29
+ }
30
+ // 2. Config file fallback
31
+ const fileConfig = loadConfigFile();
32
+ if (fileConfig?.xai_api_key) {
33
+ return { ...DEFAULT_CONFIG, ...fileConfig };
34
+ }
35
+ // 3. No API key found — will fail at runtime with helpful message
36
+ return { ...DEFAULT_CONFIG, xai_api_key: "" };
37
+ }
38
+ function loadConfigFile() {
39
+ const configPath = getConfigPath();
40
+ if (!existsSync(configPath))
41
+ return null;
42
+ try {
43
+ const raw = readFileSync(configPath, "utf-8");
44
+ return JSON.parse(raw);
45
+ }
46
+ catch {
47
+ return null;
48
+ }
49
+ }
50
+ export function validateApiKey(config) {
51
+ if (!config.xai_api_key ||
52
+ config.xai_api_key === "YOUR_XAI_API_KEY_HERE") {
53
+ throw new Error(`xAI API key not configured.\n` +
54
+ `Set XAI_API_KEY in your MCP server config:\n` +
55
+ ` "env": { "XAI_API_KEY": "xai-xxx" }\n` +
56
+ `Get your key at: https://console.x.ai`);
57
+ }
58
+ }
59
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAWlC,MAAM,cAAc,GAAsC;IACxD,aAAa,EAAE,eAAe;IAC9B,iBAAiB,EAAE;QACjB,YAAY;QACZ,cAAc;QACd,SAAS;QACT,UAAU;QACV,iBAAiB;QACjB,eAAe;QACf,aAAa;KACd;IACD,wBAAwB,EAAE,KAAK;IAC/B,oBAAoB,EAAE,2BAA2B;IACjD,mBAAmB,EAAE,KAAK;CAC3B,CAAC;AAEF,SAAS,aAAa;IACpB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,2EAA2E;IAC3E,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC1C,IAAI,MAAM,EAAE,CAAC;QACX,uEAAuE;QACvE,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;QACpC,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;IACnE,CAAC;IAED,0BAA0B;IAC1B,MAAM,UAAU,GAAG,cAAc,EAAE,CAAC;IACpC,IAAI,UAAU,EAAE,WAAW,EAAE,CAAC;QAC5B,OAAO,EAAE,GAAG,cAAc,EAAE,GAAG,UAAU,EAAkB,CAAC;IAC9D,CAAC;IAED,kEAAkE;IAClE,OAAO,EAAE,GAAG,cAAc,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;AAChD,CAAC;AAED,SAAS,cAAc;IACrB,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAA0B,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAoB;IACjD,IACE,CAAC,MAAM,CAAC,WAAW;QACnB,MAAM,CAAC,WAAW,KAAK,uBAAuB,EAC9C,CAAC;QACD,MAAM,IAAI,KAAK,CACb,+BAA+B;YAC7B,8CAA8C;YAC9C,yCAAyC;YACzC,uCAAuC,CAC1C,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,118 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { z } from "zod";
5
+ import { loadConfig, validateApiKey } from "./config.js";
6
+ import { handleSearch, handleWatchlist, handleWeekly } from "./tools.js";
7
+ // ── Initialise ──
8
+ const config = loadConfig();
9
+ // ── MCP Server ──
10
+ const server = new McpServer({
11
+ name: "x-quick-mcp-server",
12
+ version: "0.1.0",
13
+ });
14
+ // ── Tool 1: x_search ──
15
+ server.tool("x_search", "Search X (Twitter) posts in real-time using xAI Responses API. " +
16
+ "Supports keyword search, user filtering, date range, image/video analysis.", {
17
+ query: z
18
+ .string()
19
+ .describe("Natural language search query (e.g., 'AIエージェントの最新トレンド')"),
20
+ allowed_handles: z
21
+ .array(z.string())
22
+ .optional()
23
+ .describe("Only search posts from these handles (max 10, without @)"),
24
+ excluded_handles: z
25
+ .array(z.string())
26
+ .optional()
27
+ .describe("Exclude posts from these handles (max 10, without @)"),
28
+ from_date: z
29
+ .string()
30
+ .optional()
31
+ .describe("Start date (YYYY-MM-DD)"),
32
+ to_date: z
33
+ .string()
34
+ .optional()
35
+ .describe("End date (YYYY-MM-DD)"),
36
+ model: z
37
+ .enum(["grok-4-1-fast", "grok-4-1-fast-reasoning", "grok-4"])
38
+ .optional()
39
+ .describe("Model to use (default: grok-4-1-fast). Use reasoning for deeper analysis."),
40
+ include_web_search: z
41
+ .boolean()
42
+ .optional()
43
+ .describe("Also include web search results alongside X posts (default: false)"),
44
+ }, async (args) => {
45
+ try {
46
+ validateApiKey(config);
47
+ const result = await handleSearch(config, args);
48
+ return { content: [{ type: "text", text: result }] };
49
+ }
50
+ catch (error) {
51
+ const message = error instanceof Error ? error.message : String(error);
52
+ return {
53
+ content: [{ type: "text", text: `Error: ${message}` }],
54
+ isError: true,
55
+ };
56
+ }
57
+ });
58
+ // ── Tool 2: x_watchlist ──
59
+ server.tool("x_watchlist", "Fetch recent posts from the medical-AI watchlist accounts on X. " +
60
+ "Returns categorized summaries (Medical AI / 生成AI / Tech Trends).", {
61
+ period: z
62
+ .enum(["24h", "3d", "1w"])
63
+ .optional()
64
+ .describe("Time period to search (default: 24h). 24h=past day, 3d=past 3 days, 1w=past week."),
65
+ extra_handles: z
66
+ .array(z.string())
67
+ .optional()
68
+ .describe("Additional handles to include beyond the default watchlist (without @)"),
69
+ }, async (args) => {
70
+ try {
71
+ validateApiKey(config);
72
+ const result = await handleWatchlist(config, args);
73
+ return { content: [{ type: "text", text: result }] };
74
+ }
75
+ catch (error) {
76
+ const message = error instanceof Error ? error.message : String(error);
77
+ return {
78
+ content: [{ type: "text", text: `Error: ${message}` }],
79
+ isError: true,
80
+ };
81
+ }
82
+ });
83
+ // ── Tool 3: x_weekly ──
84
+ server.tool("x_weekly", "Generate a weekly trend report from X posts for the past 7 days. " +
85
+ "Covers top trends, notable papers, events, products, and more.", {
86
+ topic: z
87
+ .string()
88
+ .optional()
89
+ .describe("Topic to focus on (default: 医療AI・内視鏡AI・消化器内科AI・生成AI全般)"),
90
+ model: z
91
+ .enum(["grok-4-1-fast", "grok-4-1-fast-reasoning", "grok-4"])
92
+ .optional()
93
+ .describe("Model to use (default: grok-4-1-fast-reasoning for deeper analysis)"),
94
+ }, async (args) => {
95
+ try {
96
+ validateApiKey(config);
97
+ const result = await handleWeekly(config, args);
98
+ return { content: [{ type: "text", text: result }] };
99
+ }
100
+ catch (error) {
101
+ const message = error instanceof Error ? error.message : String(error);
102
+ return {
103
+ content: [{ type: "text", text: `Error: ${message}` }],
104
+ isError: true,
105
+ };
106
+ }
107
+ });
108
+ // ── Start ──
109
+ async function main() {
110
+ const transport = new StdioServerTransport();
111
+ await server.connect(transport);
112
+ console.error("x-quick-mcp-server running on stdio");
113
+ }
114
+ main().catch((error) => {
115
+ console.error("Fatal error:", error);
116
+ process.exit(1);
117
+ });
118
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ import type { XQuickConfig } from "./config.js";
2
+ export declare const searchToolDef: {
3
+ name: string;
4
+ description: string;
5
+ inputSchema: {
6
+ type: "object";
7
+ properties: {
8
+ query: {
9
+ type: string;
10
+ description: string;
11
+ };
12
+ allowed_handles: {
13
+ type: string;
14
+ items: {
15
+ type: string;
16
+ };
17
+ description: string;
18
+ };
19
+ excluded_handles: {
20
+ type: string;
21
+ items: {
22
+ type: string;
23
+ };
24
+ description: string;
25
+ };
26
+ from_date: {
27
+ type: string;
28
+ description: string;
29
+ };
30
+ to_date: {
31
+ type: string;
32
+ description: string;
33
+ };
34
+ model: {
35
+ type: string;
36
+ enum: string[];
37
+ description: string;
38
+ };
39
+ include_web_search: {
40
+ type: string;
41
+ description: string;
42
+ };
43
+ };
44
+ required: string[];
45
+ };
46
+ };
47
+ export declare function handleSearch(config: XQuickConfig, args: Record<string, unknown>): Promise<string>;
48
+ export declare const watchlistToolDef: {
49
+ name: string;
50
+ description: string;
51
+ inputSchema: {
52
+ type: "object";
53
+ properties: {
54
+ period: {
55
+ type: string;
56
+ enum: string[];
57
+ description: string;
58
+ };
59
+ extra_handles: {
60
+ type: string;
61
+ items: {
62
+ type: string;
63
+ };
64
+ description: string;
65
+ };
66
+ };
67
+ };
68
+ };
69
+ export declare function handleWatchlist(config: XQuickConfig, args: Record<string, unknown>): Promise<string>;
70
+ export declare const weeklyToolDef: {
71
+ name: string;
72
+ description: string;
73
+ inputSchema: {
74
+ type: "object";
75
+ properties: {
76
+ topic: {
77
+ type: string;
78
+ description: string;
79
+ };
80
+ model: {
81
+ type: string;
82
+ enum: string[];
83
+ description: string;
84
+ };
85
+ };
86
+ };
87
+ };
88
+ export declare function handleWeekly(config: XQuickConfig, args: Record<string, unknown>): Promise<string>;
89
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAsBhD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA8CzB,CAAC;AAEF,wBAAsB,YAAY,CAChC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CAajB;AAMD,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;CAsB5B,CAAC;AAEF,wBAAsB,eAAe,CACnC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CAqCjB;AAMD,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;CAqBzB,CAAC;AAEF,wBAAsB,YAAY,CAChC,MAAM,EAAE,YAAY,EACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,MAAM,CAAC,CAyBjB"}
package/dist/tools.js ADDED
@@ -0,0 +1,166 @@
1
+ import { searchX } from "./xai-client.js";
2
+ // ── Helper ──
3
+ function dateStr(d) {
4
+ return d.toISOString().slice(0, 10);
5
+ }
6
+ function daysAgo(n) {
7
+ const d = new Date();
8
+ d.setDate(d.getDate() - n);
9
+ return dateStr(d);
10
+ }
11
+ const LINK_INSTRUCTION = "\n結果は必ず投稿者の@ハンドル名と投稿へのリンク(https://x.com/username/status/ID形式)を含めて報告してください。";
12
+ // ══════════════════════════════════════════════
13
+ // Tool 1: x_search
14
+ // ══════════════════════════════════════════════
15
+ export const searchToolDef = {
16
+ name: "x_search",
17
+ description: "Search X (Twitter) posts in real-time using xAI Responses API. " +
18
+ "Supports keyword search, user filtering, date range, image/video analysis.",
19
+ inputSchema: {
20
+ type: "object",
21
+ properties: {
22
+ query: {
23
+ type: "string",
24
+ description: "Natural language search query (e.g., 'AIエージェントの最新トレンド')",
25
+ },
26
+ allowed_handles: {
27
+ type: "array",
28
+ items: { type: "string" },
29
+ description: "Only search posts from these handles (max 10, without @)",
30
+ },
31
+ excluded_handles: {
32
+ type: "array",
33
+ items: { type: "string" },
34
+ description: "Exclude posts from these handles (max 10, without @)",
35
+ },
36
+ from_date: {
37
+ type: "string",
38
+ description: "Start date (YYYY-MM-DD)",
39
+ },
40
+ to_date: {
41
+ type: "string",
42
+ description: "End date (YYYY-MM-DD)",
43
+ },
44
+ model: {
45
+ type: "string",
46
+ enum: ["grok-4-1-fast", "grok-4-1-fast-reasoning", "grok-4"],
47
+ description: "Model to use (default: grok-4-1-fast). Use reasoning for deeper analysis.",
48
+ },
49
+ include_web_search: {
50
+ type: "boolean",
51
+ description: "Also include web search results alongside X posts (default: false)",
52
+ },
53
+ },
54
+ required: ["query"],
55
+ },
56
+ };
57
+ export async function handleSearch(config, args) {
58
+ const query = args.query + LINK_INSTRUCTION;
59
+ const options = {
60
+ model: args.model,
61
+ allowed_handles: args.allowed_handles,
62
+ excluded_handles: args.excluded_handles,
63
+ from_date: args.from_date,
64
+ to_date: args.to_date,
65
+ include_web_search: args.include_web_search,
66
+ };
67
+ return searchX(config, query, options);
68
+ }
69
+ // ══════════════════════════════════════════════
70
+ // Tool 2: x_watchlist
71
+ // ══════════════════════════════════════════════
72
+ export const watchlistToolDef = {
73
+ name: "x_watchlist",
74
+ description: "Fetch recent posts from the medical-AI watchlist accounts on X. " +
75
+ "Returns categorized summaries (Medical AI / 生成AI / Tech Trends).",
76
+ inputSchema: {
77
+ type: "object",
78
+ properties: {
79
+ period: {
80
+ type: "string",
81
+ enum: ["24h", "3d", "1w"],
82
+ description: "Time period to search (default: 24h). 24h=past day, 3d=past 3 days, 1w=past week.",
83
+ },
84
+ extra_handles: {
85
+ type: "array",
86
+ items: { type: "string" },
87
+ description: "Additional handles to include beyond the default watchlist (without @)",
88
+ },
89
+ },
90
+ },
91
+ };
92
+ export async function handleWatchlist(config, args) {
93
+ const period = args.period || config.default_watchlist_period;
94
+ let days;
95
+ switch (period) {
96
+ case "1w":
97
+ case "7d":
98
+ days = 7;
99
+ break;
100
+ case "3d":
101
+ days = 3;
102
+ break;
103
+ default:
104
+ days = 1;
105
+ }
106
+ const fromDate = daysAgo(days);
107
+ const toDate = dateStr(new Date());
108
+ const handles = [...config.watchlist_handles];
109
+ const extra = args.extra_handles;
110
+ if (extra?.length) {
111
+ handles.push(...extra);
112
+ }
113
+ const query = `以下のアカウントの ${fromDate} から ${toDate} の投稿を検索し、` +
114
+ `AI関連の重要な情報を要約してください。\n` +
115
+ `各投稿について投稿者の@ハンドル名と投稿へのリンク(https://x.com/...形式)を必ず含めてください。\n` +
116
+ `カテゴリ別(Medical AI、生成AI全般、技術トレンド等)に整理して報告してください。\n\n` +
117
+ `アカウント: ${handles.map((h) => "@" + h).join(", ")}`;
118
+ return searchX(config, query, {
119
+ allowed_handles: handles,
120
+ from_date: fromDate,
121
+ to_date: toDate,
122
+ });
123
+ }
124
+ // ══════════════════════════════════════════════
125
+ // Tool 3: x_weekly
126
+ // ══════════════════════════════════════════════
127
+ export const weeklyToolDef = {
128
+ name: "x_weekly",
129
+ description: "Generate a weekly trend report from X posts for the past 7 days. " +
130
+ "Covers top trends, notable papers, events, products, and more.",
131
+ inputSchema: {
132
+ type: "object",
133
+ properties: {
134
+ topic: {
135
+ type: "string",
136
+ description: "Topic to focus on (default: 医療AI・内視鏡AI・消化器内科AI・生成AI全般)",
137
+ },
138
+ model: {
139
+ type: "string",
140
+ enum: ["grok-4-1-fast", "grok-4-1-fast-reasoning", "grok-4"],
141
+ description: "Model to use (default: grok-4-1-fast-reasoning for deeper analysis)",
142
+ },
143
+ },
144
+ },
145
+ };
146
+ export async function handleWeekly(config, args) {
147
+ const topic = args.topic || config.default_weekly_topic;
148
+ const model = args.model || "grok-4-1-fast-reasoning";
149
+ const fromDate = daysAgo(7);
150
+ const toDate = dateStr(new Date());
151
+ const query = `${fromDate} から ${toDate} の期間に、${topic} についてXでどのような話題が議論されましたか?\n\n` +
152
+ `以下の形式で週次まとめを作成してください:\n` +
153
+ `1. 主要トレンド(上位5件)\n` +
154
+ `2. 注目論文・研究(引用・紹介されたもの)\n` +
155
+ `3. 学会・イベント情報\n` +
156
+ `4. 話題になった製品・ツール\n` +
157
+ `5. その他注目トピック\n\n` +
158
+ `各項目に必ず投稿者の@ハンドル名と投稿へのリンク(https://x.com/...形式)を含めてください。\n` +
159
+ `日本語・英語両方の投稿を含めてください。`;
160
+ return searchX(config, query, {
161
+ model,
162
+ from_date: fromDate,
163
+ to_date: toDate,
164
+ });
165
+ }
166
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { XQuickConfig } from "./config.js";
2
+ export interface SearchOptions {
3
+ model?: string;
4
+ allowed_handles?: string[];
5
+ excluded_handles?: string[];
6
+ from_date?: string;
7
+ to_date?: string;
8
+ enable_image?: boolean;
9
+ enable_video?: boolean;
10
+ include_web_search?: boolean;
11
+ }
12
+ export declare function searchX(config: XQuickConfig, query: string, options?: SearchOptions): Promise<string>;
13
+ //# sourceMappingURL=xai-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xai-client.d.ts","sourceRoot":"","sources":["../src/xai-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AA2ChD,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,wBAAsB,OAAO,CAC3B,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAqDjB"}
@@ -0,0 +1,60 @@
1
+ export async function searchX(config, query, options = {}) {
2
+ const xSearchTool = { type: "x_search" };
3
+ if (options.allowed_handles?.length) {
4
+ xSearchTool.allowed_x_handles = options.allowed_handles;
5
+ }
6
+ if (options.excluded_handles?.length) {
7
+ xSearchTool.excluded_x_handles = options.excluded_handles;
8
+ }
9
+ if (options.from_date) {
10
+ xSearchTool.from_date = options.from_date;
11
+ }
12
+ if (options.to_date) {
13
+ xSearchTool.to_date = options.to_date;
14
+ }
15
+ if (options.enable_image) {
16
+ xSearchTool.enable_image_understanding = true;
17
+ }
18
+ if (options.enable_video) {
19
+ xSearchTool.enable_video_understanding = true;
20
+ }
21
+ const tools = [xSearchTool];
22
+ if (options.include_web_search) {
23
+ tools.push({ type: "web_search" });
24
+ }
25
+ const payload = {
26
+ model: options.model ?? config.default_model,
27
+ input: [{ role: "user", content: query }],
28
+ tools,
29
+ store: config.store_conversations,
30
+ };
31
+ const response = await fetch("https://api.x.ai/v1/responses", {
32
+ method: "POST",
33
+ headers: {
34
+ "Content-Type": "application/json",
35
+ Authorization: `Bearer ${config.xai_api_key}`,
36
+ },
37
+ body: JSON.stringify(payload),
38
+ signal: AbortSignal.timeout(180_000), // 3 min timeout
39
+ });
40
+ if (!response.ok) {
41
+ const body = await response.text();
42
+ throw new Error(`xAI API error (${response.status}): ${body}`);
43
+ }
44
+ const data = (await response.json());
45
+ return extractText(data);
46
+ }
47
+ function extractText(data) {
48
+ const texts = [];
49
+ for (const item of data.output ?? []) {
50
+ if (item.type === "message") {
51
+ for (const content of item.content ?? []) {
52
+ if (content.type === "output_text") {
53
+ texts.push(content.text);
54
+ }
55
+ }
56
+ }
57
+ }
58
+ return texts.join("\n") || "(No results returned)";
59
+ }
60
+ //# sourceMappingURL=xai-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xai-client.js","sourceRoot":"","sources":["../src/xai-client.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "x-quick-mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for searching X (formerly Twitter) posts via xAI Responses API",
5
+ "author": "Masa",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "bin": {
9
+ "x-quick-mcp-server": "./dist/index.js"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "start": "node dist/index.js",
17
+ "dev": "tsc --watch"
18
+ },
19
+ "keywords": [
20
+ "mcp",
21
+ "x",
22
+ "twitter",
23
+ "xai",
24
+ "grok",
25
+ "search",
26
+ "model-context-protocol"
27
+ ],
28
+ "dependencies": {
29
+ "@modelcontextprotocol/sdk": "^1.12.1",
30
+ "zod": "^4.3.6"
31
+ },
32
+ "devDependencies": {
33
+ "@types/node": "^22.0.0",
34
+ "typescript": "^5.7.0"
35
+ },
36
+ "engines": {
37
+ "node": ">=18.0.0"
38
+ }
39
+ }