@ayatec/ai-gateway-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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +213 -0
  3. package/dist/config.d.ts +8 -0
  4. package/dist/config.d.ts.map +1 -0
  5. package/dist/config.js +9 -0
  6. package/dist/config.js.map +1 -0
  7. package/dist/index.d.ts +3 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +40 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/lib/gateway.d.ts +24 -0
  12. package/dist/lib/gateway.d.ts.map +1 -0
  13. package/dist/lib/gateway.js +122 -0
  14. package/dist/lib/gateway.js.map +1 -0
  15. package/dist/lib/model-registry.d.ts +16 -0
  16. package/dist/lib/model-registry.d.ts.map +1 -0
  17. package/dist/lib/model-registry.js +264 -0
  18. package/dist/lib/model-registry.js.map +1 -0
  19. package/dist/providers/anthropic.d.ts +2 -0
  20. package/dist/providers/anthropic.d.ts.map +1 -0
  21. package/dist/providers/anthropic.js +7 -0
  22. package/dist/providers/anthropic.js.map +1 -0
  23. package/dist/providers/google.d.ts +2 -0
  24. package/dist/providers/google.d.ts.map +1 -0
  25. package/dist/providers/google.js +9 -0
  26. package/dist/providers/google.js.map +1 -0
  27. package/dist/providers/index.d.ts +5 -0
  28. package/dist/providers/index.d.ts.map +1 -0
  29. package/dist/providers/index.js +8 -0
  30. package/dist/providers/index.js.map +1 -0
  31. package/dist/providers/openai.d.ts +2 -0
  32. package/dist/providers/openai.d.ts.map +1 -0
  33. package/dist/providers/openai.js +7 -0
  34. package/dist/providers/openai.js.map +1 -0
  35. package/dist/providers/perplexity.d.ts +2 -0
  36. package/dist/providers/perplexity.d.ts.map +1 -0
  37. package/dist/providers/perplexity.js +9 -0
  38. package/dist/providers/perplexity.js.map +1 -0
  39. package/dist/tools/ask.d.ts +20 -0
  40. package/dist/tools/ask.d.ts.map +1 -0
  41. package/dist/tools/ask.js +47 -0
  42. package/dist/tools/ask.js.map +1 -0
  43. package/dist/tools/index.d.ts +5 -0
  44. package/dist/tools/index.d.ts.map +1 -0
  45. package/dist/tools/index.js +5 -0
  46. package/dist/tools/index.js.map +1 -0
  47. package/dist/tools/list-models.d.ts +38 -0
  48. package/dist/tools/list-models.d.ts.map +1 -0
  49. package/dist/tools/list-models.js +106 -0
  50. package/dist/tools/list-models.js.map +1 -0
  51. package/dist/tools/research.d.ts +32 -0
  52. package/dist/tools/research.d.ts.map +1 -0
  53. package/dist/tools/research.js +157 -0
  54. package/dist/tools/research.js.map +1 -0
  55. package/dist/tools/search.d.ts +18 -0
  56. package/dist/tools/search.d.ts.map +1 -0
  57. package/dist/tools/search.js +61 -0
  58. package/dist/tools/search.js.map +1 -0
  59. package/dist/types/index.d.ts +40 -0
  60. package/dist/types/index.d.ts.map +1 -0
  61. package/dist/types/index.js +2 -0
  62. package/dist/types/index.js.map +1 -0
  63. package/dist/utils/cost.d.ts +10 -0
  64. package/dist/utils/cost.d.ts.map +1 -0
  65. package/dist/utils/cost.js +18 -0
  66. package/dist/utils/cost.js.map +1 -0
  67. package/dist/utils/format.d.ts +5 -0
  68. package/dist/utils/format.d.ts.map +1 -0
  69. package/dist/utils/format.js +18 -0
  70. package/dist/utils/format.js.map +1 -0
  71. package/dist/utils/logger.d.ts +12 -0
  72. package/dist/utils/logger.d.ts.map +1 -0
  73. package/dist/utils/logger.js +20 -0
  74. package/dist/utils/logger.js.map +1 -0
  75. package/package.json +87 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026-present ayatec
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,213 @@
1
+ # AI Gateway MCP Server
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@ayatec/ai-gateway-mcp-server)](https://www.npmjs.com/package/@ayatec/ai-gateway-mcp-server)
4
+ [![CI](https://github.com/ayatec/ai-gateway-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/ayatec/ai-gateway-mcp-server/actions/workflows/ci.yml)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+
7
+ Vercel AI Gateway を通じて複数の AI プロバイダー・モデルに統一的にアクセスできる MCP サーバー。
8
+ Web 検索、マルチモデル調査・比較など、LLM を活用した 4 つのツールを提供します。
9
+
10
+ ## 提供ツール
11
+
12
+ ### `ask` -- AI に質問
13
+
14
+ 任意のモデルに質問を送り、回答を得ます。
15
+
16
+ | パラメータ | 型 | 必須 | デフォルト | 説明 |
17
+ | ------------ | ------ | ---- | ---------------- | ------------------ |
18
+ | `question` | string | Yes | - | 質問内容 |
19
+ | `model` | string | No | `openai/gpt-5.2` | モデル ID |
20
+ | `context` | string | No | - | 追加コンテキスト |
21
+ | `max_tokens` | number | No | `4000` | 最大出力トークン数 |
22
+
23
+ ### `search` -- Web 検索
24
+
25
+ 検索対応モデルを使って最新情報を取得します。
26
+
27
+ | パラメータ | 型 | 必須 | デフォルト | 説明 |
28
+ | ------------ | ------ | ---- | ------------------ | ------------------ |
29
+ | `query` | string | Yes | - | 検索クエリ |
30
+ | `model` | string | No | `perplexity/sonar` | 検索対応モデル ID |
31
+ | `max_tokens` | number | No | `2000` | 最大出力トークン数 |
32
+
33
+ ### `research` -- マルチモデル調査・比較
34
+
35
+ 複数モデルに並列クエリし、結果を統合または比較表示します。
36
+
37
+ | パラメータ | 型 | 必須 | デフォルト | 説明 |
38
+ | ---------------------- | -------- | ---- | ---------------------------------- | --------------------------------------------------- |
39
+ | `query` | string | Yes | - | 調査クエリ |
40
+ | `mode` | string | No | `search` | `search`(Web 検索)または `ask`(Q&A) |
41
+ | `models` | string[] | No | mode に応じた 4 モデル | 2~4 モデル ID の配列 |
42
+ | `synthesize` | boolean | No | `true` | `true`: 統合回答、`false`: 各モデルの回答を並列表示 |
43
+ | `synthesis_model` | string | No | `openai/gpt-5.2` | 統合に使うモデル(`synthesize:true` 時のみ) |
44
+ | `max_tokens` | number | No | search: `2000` / ask: `4000` | 各モデルの最大出力トークン数 |
45
+ | `synthesis_max_tokens` | number | No | search: `max_tokens×3` / ask: `×2` | 統合の最大出力トークン数 |
46
+
47
+ **処理フロー:**
48
+
49
+ 1. **Query Stage**: 指定(またはデフォルト)モデルに並列リクエスト
50
+ - `search` デフォルト: `perplexity/sonar`, `gemini-3-flash`, `claude-haiku-4.5`, `gpt-5-mini`
51
+ - `ask` デフォルト: `gpt-5.2`, `claude-opus-4.6`, `gemini-3.1-pro-preview`, `sonar-reasoning-pro`
52
+ 2. **Synthesis Stage** (`synthesize:true`): `openai/gpt-5.2` が全結果を精査・統合し、矛盾点を指摘、ソースを明記
53
+ 3. **Comparison** (`synthesize:false`): 各モデルの回答をコスト・レイテンシ付きで並列表示
54
+
55
+ ### `list_models` -- モデル一覧
56
+
57
+ 利用可能なモデルの情報(価格・能力・検索コスト)を表示します。
58
+
59
+ | パラメータ | 型 | 必須 | 説明 |
60
+ | ------------ | ------ | ---- | ----------------------------------------------------------------------- |
61
+ | `provider` | string | No | プロバイダーでフィルタ(`openai`, `anthropic`, `google`, `perplexity`) |
62
+ | `capability` | string | No | 能力でフィルタ(`search`, `reasoning`, `fast`, `cheap`, `code`) |
63
+
64
+ ## サポートモデル
65
+
66
+ ### OpenAI
67
+
68
+ | モデル ID | 入力 | 出力 | 検索 | 特徴 |
69
+ | ---------------------- | ----- | ------ | ---- | ------------------------------ |
70
+ | `openai/gpt-5.2` | $1.75 | $14.00 | Yes | フラッグシップ、ask デフォルト |
71
+ | `openai/gpt-5.2-codex` | $1.75 | $14.00 | Yes | コード特化 |
72
+ | `openai/gpt-5-mini` | $0.25 | $2.00 | Yes | バランス型 |
73
+ | `openai/gpt-5-nano` | $0.05 | $0.40 | No | 最安 |
74
+ | `openai/gpt-oss-120b` | $0.10 | $0.50 | No | OSS |
75
+
76
+ ### Anthropic
77
+
78
+ | モデル ID | 入力 | 出力 | 検索 | 特徴 |
79
+ | ----------------------------- | ----- | ------ | ---- | ---------- |
80
+ | `anthropic/claude-opus-4.6` | $5.00 | $25.00 | Yes | 最高性能 |
81
+ | `anthropic/claude-sonnet-4.6` | $3.00 | $15.00 | Yes | バランス型 |
82
+ | `anthropic/claude-haiku-4.5` | $1.00 | $5.00 | Yes | 高速 |
83
+
84
+ ### Google
85
+
86
+ | モデル ID | 入力 | 出力 | 検索 | 特徴 |
87
+ | ------------------------------- | ----- | ------ | ---- | ---------- |
88
+ | `google/gemini-3-flash` | $0.50 | $3.00 | Yes | コスパ最強 |
89
+ | `google/gemini-3.1-pro-preview` | $2.00 | $12.00 | Yes | 高性能 |
90
+
91
+ ### Perplexity
92
+
93
+ | モデル ID | 入力 | 出力 | 検索 | 特徴 |
94
+ | -------------------------------- | ----- | ------ | ---- | --------------------------------- |
95
+ | `perplexity/sonar` | $1.00 | $1.00 | Yes | ネイティブ検索、search デフォルト |
96
+ | `perplexity/sonar-pro` | $3.00 | $15.00 | Yes | 高精度検索 |
97
+ | `perplexity/sonar-reasoning-pro` | $2.00 | $8.00 | Yes | 推論+高精度検索 |
98
+ | `perplexity/sonar-deep-research` | $2.00 | $8.00 | Yes | エージェント型マルチ検索調査 |
99
+
100
+ > 価格は 1M トークンあたり(USD)
101
+
102
+ ## セットアップ
103
+
104
+ ### 1. 環境変数
105
+
106
+ [Vercel AI Gateway](https://vercel.com/ai-gateway) の API キーを取得し、設定します。
107
+
108
+ ### 2. MCP 設定
109
+
110
+ #### npx で使う場合(推奨)
111
+
112
+ ##### Claude Code
113
+
114
+ ```bash
115
+ claude mcp add ai-gateway npx @ayatec/ai-gateway-mcp-server -e AI_GATEWAY_API_KEY=your-key
116
+ ```
117
+
118
+ ##### Claude Desktop / その他の MCP クライアント
119
+
120
+ ```json
121
+ {
122
+ "mcpServers": {
123
+ "ai-gateway": {
124
+ "command": "npx",
125
+ "args": ["@ayatec/ai-gateway-mcp-server"],
126
+ "env": {
127
+ "AI_GATEWAY_API_KEY": "your-key"
128
+ }
129
+ }
130
+ }
131
+ }
132
+ ```
133
+
134
+ #### ローカルビルドで使う場合
135
+
136
+ ```bash
137
+ git clone https://github.com/ayatec/ai-gateway-mcp-server.git
138
+ cd ai-gateway-mcp-server
139
+ pnpm install
140
+ pnpm build
141
+ ```
142
+
143
+ ```bash
144
+ claude mcp add ai-gateway node /path/to/ai-gateway-mcp-server/dist/index.js -e AI_GATEWAY_API_KEY=your-key
145
+ ```
146
+
147
+ ## 開発
148
+
149
+ ### コマンド
150
+
151
+ ```bash
152
+ pnpm install # 依存パッケージインストール
153
+ pnpm build # ビルド
154
+ pnpm dev # ウォッチモードでビルド
155
+ pnpm start # サーバー起動(ビルド後)
156
+ pnpm dev:tool # ツールの手動テスト
157
+ pnpm test # テスト実行
158
+ pnpm test:watch # テスト(ウォッチモード)
159
+ pnpm type-check # 型チェック
160
+ pnpm lint # ESLint実行
161
+ pnpm lint:fix # ESLint自動修正
162
+ pnpm format # Prettier実行
163
+ pnpm format:check # フォーマットチェック
164
+ ```
165
+
166
+ ### ローカルテスト
167
+
168
+ `pnpm dev:tool` で各ツールを個別にテストできます。
169
+
170
+ ```bash
171
+ # ask(デフォルト: gpt-5.2)
172
+ pnpm dev:tool ask --question "TypeScriptの利点は?"
173
+
174
+ # ask(モデル指定)
175
+ pnpm dev:tool ask --question "Rustとは?" --model "anthropic/claude-sonnet-4.6"
176
+
177
+ # search(デフォルト: perplexity/sonar)
178
+ pnpm dev:tool search --query "Vercel AI SDK 最新情報"
179
+
180
+ # research(4モデル並列検索→統合、デフォルト)
181
+ pnpm dev:tool research --query "WebAssemblyの現状と将来"
182
+
183
+ # research(askモード、比較表示)
184
+ pnpm dev:tool research --query "関数型プログラミングの利点" --mode ask --synthesize false
185
+
186
+ # research(モデル指定)
187
+ pnpm dev:tool research --query "latest TypeScript features" --models '["openai/gpt-5.2","perplexity/sonar"]'
188
+
189
+ # list_models
190
+ pnpm dev:tool list_models
191
+ pnpm dev:tool list_models --provider openai
192
+ pnpm dev:tool list_models --capability search
193
+ ```
194
+
195
+ ### リリース
196
+
197
+ [Changesets](https://github.com/changesets/changesets) でバージョン管理しています。
198
+
199
+ 1. changeset ファイルを作成して main に push
200
+ 2. GitHub Actions が自動で CHANGELOG 更新・バージョンバンプ・npm publish
201
+
202
+ ## 技術スタック
203
+
204
+ - **TypeScript** (ESM, NodeNext, strict)
205
+ - **[Vercel AI SDK](https://ai-sdk.dev/)** -- `gateway` プロバイダーで全モデルに統一アクセス
206
+ - **[MCP SDK](https://modelcontextprotocol.io/)** -- Model Context Protocol サーバー実装
207
+ - **[Zod](https://zod.dev/)** -- スキーマバリデーション
208
+ - **[Vitest](https://vitest.dev/)** -- テスト
209
+ - **[Changesets](https://github.com/changesets/changesets)** -- バージョン管理・CHANGELOG 自動生成
210
+
211
+ ## ライセンス
212
+
213
+ MIT
@@ -0,0 +1,8 @@
1
+ export declare const config: {
2
+ readonly server: {
3
+ readonly name: "ai-gateway-mcp-server";
4
+ readonly version: "0.1.0";
5
+ };
6
+ readonly logDir: string;
7
+ };
8
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM;;;;;;CAMT,CAAC"}
package/dist/config.js ADDED
@@ -0,0 +1,9 @@
1
+ import path from 'path';
2
+ export const config = {
3
+ server: {
4
+ name: 'ai-gateway-mcp-server',
5
+ version: '0.1.0',
6
+ },
7
+ logDir: path.join(import.meta.dirname, '../logs'),
8
+ };
9
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,MAAM,EAAE;QACN,IAAI,EAAE,uBAAuB;QAC7B,OAAO,EAAE,OAAO;KACjB;IACD,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC;CACzC,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,40 @@
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 { config } from './config.js';
5
+ import { askTool, askHandler, searchTool, searchHandler, researchTool, researchHandler, listModelsTool, listModelsHandler, } from './tools/index.js';
6
+ const server = new McpServer({
7
+ name: config.server.name,
8
+ version: config.server.version,
9
+ });
10
+ // ツール登録
11
+ server.registerTool(askTool.name, {
12
+ description: askTool.description,
13
+ inputSchema: askTool.paramsSchema,
14
+ }, askHandler);
15
+ server.registerTool(searchTool.name, {
16
+ description: searchTool.description,
17
+ inputSchema: searchTool.paramsSchema,
18
+ }, searchHandler);
19
+ server.registerTool(researchTool.name, {
20
+ description: researchTool.description,
21
+ inputSchema: researchTool.paramsSchema,
22
+ }, researchHandler);
23
+ server.registerTool(listModelsTool.name, {
24
+ description: listModelsTool.description,
25
+ inputSchema: listModelsTool.paramsSchema,
26
+ }, listModelsHandler);
27
+ async function main() {
28
+ if (!process.env.AI_GATEWAY_API_KEY) {
29
+ console.error('Error: AI_GATEWAY_API_KEY is not set. Set it in your environment or .env file.');
30
+ process.exit(1);
31
+ }
32
+ const transport = new StdioServerTransport();
33
+ await server.connect(transport);
34
+ console.error(`${config.server.name} running on stdio`);
35
+ }
36
+ main().catch((error) => {
37
+ console.error('Fatal error in main():', error);
38
+ process.exit(1);
39
+ });
40
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EACL,OAAO,EACP,UAAU,EACV,UAAU,EACV,aAAa,EACb,YAAY,EACZ,eAAe,EACf,cAAc,EACd,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI;IACxB,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;CAC/B,CAAC,CAAC;AAEH,QAAQ;AACR,MAAM,CAAC,YAAY,CACjB,OAAO,CAAC,IAAI,EACZ;IACE,WAAW,EAAE,OAAO,CAAC,WAAW;IAChC,WAAW,EAAE,OAAO,CAAC,YAAY;CAClC,EACD,UAAU,CACX,CAAC;AACF,MAAM,CAAC,YAAY,CACjB,UAAU,CAAC,IAAI,EACf;IACE,WAAW,EAAE,UAAU,CAAC,WAAW;IACnC,WAAW,EAAE,UAAU,CAAC,YAAY;CACrC,EACD,aAAa,CACd,CAAC;AACF,MAAM,CAAC,YAAY,CACjB,YAAY,CAAC,IAAI,EACjB;IACE,WAAW,EAAE,YAAY,CAAC,WAAW;IACrC,WAAW,EAAE,YAAY,CAAC,YAAY;CACvC,EACD,eAAe,CAChB,CAAC;AACF,MAAM,CAAC,YAAY,CACjB,cAAc,CAAC,IAAI,EACnB;IACE,WAAW,EAAE,cAAc,CAAC,WAAW;IACvC,WAAW,EAAE,cAAc,CAAC,YAAY;CACzC,EACD,iBAAiB,CAClB,CAAC;AAEF,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC;QACpC,OAAO,CAAC,KAAK,CAAC,gFAAgF,CAAC,CAAC;QAChG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,mBAAmB,CAAC,CAAC;AAC1D,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;IAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { ModelId, ToolResponse } from '../types/index.js';
2
+ /** テキスト生成の共通オプション */
3
+ export interface GenerateOptions {
4
+ modelId: ModelId;
5
+ prompt: string;
6
+ system?: string;
7
+ maxTokens?: number;
8
+ /** 検索機能を有効にするか(searchツールから呼ぶ場合にtrue) */
9
+ useSearch?: boolean;
10
+ }
11
+ /** generateText の結果(レイテンシ・使用量を含む) */
12
+ export interface GenerateResult {
13
+ response: ToolResponse;
14
+ durationMs: number;
15
+ isError?: boolean;
16
+ }
17
+ /** テキスト生成してMCPレスポンスを返す */
18
+ export declare function generate(options: GenerateOptions): Promise<GenerateResult>;
19
+ /** 複数モデルに並列でリクエストし、全結果を返す */
20
+ export declare function generateParallel(optionsList: GenerateOptions[]): Promise<{
21
+ modelId: ModelId;
22
+ result: GenerateResult;
23
+ }[]>;
24
+ //# sourceMappingURL=gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../src/lib/gateway.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAiC/D,qBAAqB;AACrB,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,qCAAqC;AACrC,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,YAAY,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,0BAA0B;AAC1B,wBAAsB,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CA8DhF;AAED,6BAA6B;AAC7B,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,eAAe,EAAE,GAC7B,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,cAAc,CAAA;CAAE,EAAE,CAAC,CA8BzD"}
@@ -0,0 +1,122 @@
1
+ import { generateText } from 'ai';
2
+ import { resolveModel, gateway } from '../providers/index.js';
3
+ import { getModel } from './model-registry.js';
4
+ /** 検索ツールを構築(Gateway の perplexitySearch を全プロバイダーで統一使用) */
5
+ function buildSearchTools() {
6
+ return { perplexity_search: gateway.tools.perplexitySearch() };
7
+ }
8
+ /** ツール結果から検索スニペットを抽出 */
9
+ function extractSearchResults(steps) {
10
+ for (const step of steps) {
11
+ const toolResults = step.toolResults;
12
+ if (!toolResults)
13
+ continue;
14
+ for (const tr of toolResults) {
15
+ if (tr.output && Array.isArray(tr.output.results)) {
16
+ const formatted = tr.output.results
17
+ .map((r) => {
18
+ const parts = [];
19
+ if (r.title)
20
+ parts.push(`**${r.title}**`);
21
+ if (r.url)
22
+ parts.push(r.url);
23
+ if (r.snippet)
24
+ parts.push(r.snippet);
25
+ return parts.join('\n');
26
+ })
27
+ .filter(Boolean)
28
+ .join('\n\n---\n\n');
29
+ if (formatted)
30
+ return formatted;
31
+ }
32
+ }
33
+ }
34
+ return null;
35
+ }
36
+ /** テキスト生成してMCPレスポンスを返す */
37
+ export async function generate(options) {
38
+ const modelDef = getModel(options.modelId);
39
+ const model = resolveModel(options.modelId);
40
+ const maxTokens = options.maxTokens ?? modelDef.maxOutputTokens;
41
+ const startTime = Date.now();
42
+ try {
43
+ const tools = options.useSearch ? buildSearchTools() : undefined;
44
+ const result = await generateText({
45
+ model,
46
+ system: options.system,
47
+ prompt: options.prompt,
48
+ maxOutputTokens: maxTokens,
49
+ tools,
50
+ // ツール使用を強制し、モデルが検索をスキップするのを防ぐ
51
+ ...(tools ? { toolChoice: 'required' } : {}),
52
+ });
53
+ let text = result.text;
54
+ // provider-executed tool(perplexitySearch)では、Gateway が検索を実行し
55
+ // ツール結果を返すが、モデルがテキスト生成せずに終了する(finishReason=tool-calls)
56
+ // その場合、検索結果をプロンプトに埋め込んで再度テキスト生成を行う
57
+ if (!text && result.steps) {
58
+ const searchResults = extractSearchResults(result.steps);
59
+ if (searchResults) {
60
+ const followUp = await generateText({
61
+ model,
62
+ system: options.system ??
63
+ 'You are a helpful assistant. Summarize the search results accurately and concisely.',
64
+ prompt: `Based on the following search results, answer the user's question: "${options.prompt}"\n\n` +
65
+ `Search results:\n${searchResults}`,
66
+ maxOutputTokens: maxTokens,
67
+ });
68
+ text = followUp.text;
69
+ }
70
+ }
71
+ if (!text)
72
+ text = '(レスポンスが空でした)';
73
+ const durationMs = Date.now() - startTime;
74
+ return {
75
+ response: { content: [{ type: 'text', text }] },
76
+ durationMs,
77
+ };
78
+ }
79
+ catch (error) {
80
+ const message = error instanceof Error ? error.message : '不明なエラーが発生しました';
81
+ console.error(`[gateway] ${options.modelId} エラー:`, error);
82
+ const durationMs = Date.now() - startTime;
83
+ return {
84
+ response: {
85
+ content: [{ type: 'text', text: `Error (${options.modelId}): ${message}` }],
86
+ isError: true,
87
+ },
88
+ durationMs,
89
+ isError: true,
90
+ };
91
+ }
92
+ }
93
+ /** 複数モデルに並列でリクエストし、全結果を返す */
94
+ export async function generateParallel(optionsList) {
95
+ const results = await Promise.allSettled(optionsList.map(async (opts) => ({
96
+ modelId: opts.modelId,
97
+ result: await generate(opts),
98
+ })));
99
+ return results.map((result, i) => {
100
+ if (result.status === 'fulfilled') {
101
+ return result.value;
102
+ }
103
+ const errorMsg = result.reason instanceof Error ? result.reason.message : '不明なエラー';
104
+ return {
105
+ modelId: optionsList[i].modelId,
106
+ result: {
107
+ response: {
108
+ content: [
109
+ {
110
+ type: 'text',
111
+ text: `Error (${optionsList[i].modelId}): ${errorMsg}`,
112
+ },
113
+ ],
114
+ isError: true,
115
+ },
116
+ durationMs: 0,
117
+ isError: true,
118
+ },
119
+ };
120
+ });
121
+ }
122
+ //# sourceMappingURL=gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway.js","sourceRoot":"","sources":["../../src/lib/gateway.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { ModelDefinition, ModelId, ProviderId, CapabilityFilter } from '../types/index.js';
2
+ /** モデルIDからモデル定義を取得 */
3
+ export declare function getModel(id: ModelId): ModelDefinition;
4
+ /** 全モデル一覧を取得 */
5
+ export declare function getAllModels(): ModelDefinition[];
6
+ /** プロバイダーでフィルタしたモデル一覧を取得 */
7
+ export declare function getModelsByProvider(provider: ProviderId): ModelDefinition[];
8
+ /** capability でフィルタしたモデル一覧を取得 */
9
+ export declare function getModelsByCapability(capability: CapabilityFilter): ModelDefinition[];
10
+ /** 検索対応モデル一覧を取得 */
11
+ export declare function getSearchCapableModels(): ModelDefinition[];
12
+ /** モデルIDの文字列が有効かチェック */
13
+ export declare function isValidModelId(id: string): id is ModelId;
14
+ /** 全モデルID一覧 */
15
+ export declare function getAllModelIds(): ModelId[];
16
+ //# sourceMappingURL=model-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-registry.d.ts","sourceRoot":"","sources":["../../src/lib/model-registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAiOhG,sBAAsB;AACtB,wBAAgB,QAAQ,CAAC,EAAE,EAAE,OAAO,GAAG,eAAe,CAMrD;AAED,gBAAgB;AAChB,wBAAgB,YAAY,IAAI,eAAe,EAAE,CAEhD;AAED,4BAA4B;AAC5B,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,UAAU,GAAG,eAAe,EAAE,CAE3E;AAED,iCAAiC;AACjC,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,gBAAgB,GAAG,eAAe,EAAE,CAarF;AAED,mBAAmB;AACnB,wBAAgB,sBAAsB,IAAI,eAAe,EAAE,CAE1D;AAED,wBAAwB;AACxB,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,EAAE,IAAI,OAAO,CAExD;AAED,eAAe;AACf,wBAAgB,cAAc,IAAI,OAAO,EAAE,CAE1C"}