@mehmetbaykar/swift-poe-search-mcp 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/README.md +521 -0
- package/bin/darwin-arm64/swift-poe-search-mcp +0 -0
- package/bin/linux-x64/swift-poe-search-mcp +0 -0
- package/bin.js +67 -0
- package/package.json +34 -0
package/README.md
ADDED
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
# Swift Poe Search MCP
|
|
2
|
+
|
|
3
|
+
A Swift MCP (Model Context Protocol) server providing AI-powered search and research tools via the Poe API proxy. Supports 4 providers with 16 specialized tools.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This server acts as a bridge between MCP clients and multiple AI/search providers through Poe's unified API:
|
|
8
|
+
|
|
9
|
+
| Provider | Tools | Description |
|
|
10
|
+
|----------|-------|-------------|
|
|
11
|
+
| Perplexity | 3 | Web search with citations, reasoning, deep research |
|
|
12
|
+
| Reka | 3 | Agentic research, fact-checking, similarity finding |
|
|
13
|
+
| Exa | 9 | Neural search, code context, company research, crawling |
|
|
14
|
+
| Linkup | 1 | #1 ranked factual accuracy on OpenAI's SimpleQA |
|
|
15
|
+
|
|
16
|
+
## Quick Start
|
|
17
|
+
|
|
18
|
+
### Requirements
|
|
19
|
+
|
|
20
|
+
- Poe subscription with API access
|
|
21
|
+
- API key from [poe.com/api_key](https://poe.com/api_key)
|
|
22
|
+
- **Linux**: Ubuntu 20.04+ or Debian 11+, requires `apt-get install libcurl4`
|
|
23
|
+
- **macOS**: macOS 14+ (Sonoma), Intel Macs supported via Rosetta
|
|
24
|
+
- **Swift**: 6.2+ (for building from source)
|
|
25
|
+
|
|
26
|
+
### Installation
|
|
27
|
+
|
|
28
|
+
**Via NPM (no build required):**
|
|
29
|
+
```bash
|
|
30
|
+
npx @mehmetbaykar/swift-poe-search-mcp@latest
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**Via Swift (build from source):**
|
|
34
|
+
```bash
|
|
35
|
+
git clone <repo>
|
|
36
|
+
cd swift-poe-search-mcp
|
|
37
|
+
swift build -c release
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Configuration
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Required
|
|
44
|
+
export POE_API_KEY=your_api_key
|
|
45
|
+
|
|
46
|
+
# Optional
|
|
47
|
+
export POE_BASE_URL=https://api.poe.com/v1 # default
|
|
48
|
+
export POE_TIMEOUT_MS=600000 # default: 10 minutes
|
|
49
|
+
export ENABLED_PROVIDERS=perplexity,reka,exa,linkup # default: all
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### MCP Client Configuration
|
|
53
|
+
|
|
54
|
+
#### Claude Desktop
|
|
55
|
+
|
|
56
|
+
Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"mcpServers": {
|
|
61
|
+
"swift-poe-search": {
|
|
62
|
+
"command": "npx",
|
|
63
|
+
"args": ["@mehmetbaykar/swift-poe-search-mcp@latest"],
|
|
64
|
+
"env": {
|
|
65
|
+
"POE_API_KEY": "your_api_key"
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
#### Cursor
|
|
73
|
+
|
|
74
|
+
Add to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (project):
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"mcpServers": {
|
|
79
|
+
"swift-poe-search": {
|
|
80
|
+
"command": "npx",
|
|
81
|
+
"args": ["@mehmetbaykar/swift-poe-search-mcp@latest"],
|
|
82
|
+
"env": {
|
|
83
|
+
"POE_API_KEY": "your_api_key"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### Claude Code CLI
|
|
91
|
+
|
|
92
|
+
Add to `~/.claude/settings.json`:
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"mcpServers": {
|
|
97
|
+
"swift-poe-search": {
|
|
98
|
+
"command": "npx",
|
|
99
|
+
"args": ["@mehmetbaykar/swift-poe-search-mcp@latest"],
|
|
100
|
+
"env": {
|
|
101
|
+
"POE_API_KEY": "your_api_key"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Testing with MCP Inspector
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
POE_API_KEY=your_key npx @modelcontextprotocol/inspector@latest swift run
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Available Tools
|
|
117
|
+
|
|
118
|
+
### Perplexity Tools
|
|
119
|
+
|
|
120
|
+
#### `perplexity_ask`
|
|
121
|
+
|
|
122
|
+
Conversational web search using Sonar API with 200k context.
|
|
123
|
+
|
|
124
|
+
| Parameter | Type | Default | Description |
|
|
125
|
+
|-----------|------|---------|-------------|
|
|
126
|
+
| messages | [Message] | required | Conversation messages |
|
|
127
|
+
| searchContextSize | enum | low | low, medium, high |
|
|
128
|
+
| searchMode | enum | default | default, academic, sec |
|
|
129
|
+
| searchDomainFilter | string | "" | Comma-separated domains (prefix with `-` to exclude) |
|
|
130
|
+
| searchLanguageFilter | string | "" | ISO 639-1 codes (max 10) |
|
|
131
|
+
| searchRecencyFilter | enum | none | none, day, week, month, year |
|
|
132
|
+
| searchAfterDate | string | "" | Publication date filter |
|
|
133
|
+
| searchBeforeDate | string | "" | Publication date filter |
|
|
134
|
+
| country | string | "" | ISO 3166-1 alpha-2 code |
|
|
135
|
+
| region | string | "" | State/Province name |
|
|
136
|
+
| city | string | "" | City name |
|
|
137
|
+
| latitude | string | "" | Requires longitude + country |
|
|
138
|
+
| longitude | string | "" | Requires latitude + country |
|
|
139
|
+
| returnImages | bool | false | Include images |
|
|
140
|
+
| returnVideos | bool | false | Include videos |
|
|
141
|
+
| imageDomainFilter | string | "" | Domains for images (max 10) |
|
|
142
|
+
| imageFormatFilter | string | "" | gif, jpg, png, webp |
|
|
143
|
+
|
|
144
|
+
#### `perplexity_reason`
|
|
145
|
+
|
|
146
|
+
R1-1776 reasoning with web search via Sonar Reasoning Pro (128k context).
|
|
147
|
+
|
|
148
|
+
All parameters from `perplexity_ask` plus:
|
|
149
|
+
|
|
150
|
+
| Parameter | Type | Default | Description |
|
|
151
|
+
|-----------|------|---------|-------------|
|
|
152
|
+
| showThinking | bool | false | Show `<think>...</think>` reasoning tags |
|
|
153
|
+
|
|
154
|
+
#### `perplexity_research`
|
|
155
|
+
|
|
156
|
+
Deep multi-step research via Perplexity Deep Research (128k context).
|
|
157
|
+
|
|
158
|
+
| Parameter | Type | Default | Description |
|
|
159
|
+
|-----------|------|---------|-------------|
|
|
160
|
+
| messages | [Message] | required | Conversation messages |
|
|
161
|
+
| showThinking | bool | false | Show reasoning tags |
|
|
162
|
+
| reasoningEffort | enum | low | low, medium, high |
|
|
163
|
+
| searchMode | enum | default | Only "default" supported |
|
|
164
|
+
| searchDomainFilter | string | "" | Comma-separated domains |
|
|
165
|
+
| searchAfterDateFilter | string | "" | Date filter |
|
|
166
|
+
| searchBeforeDateFilter | string | "" | Date filter |
|
|
167
|
+
| lastUpdatedAfterFilter | string | "" | Update date filter |
|
|
168
|
+
| lastUpdatedBeforeFilter | string | "" | Update date filter |
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
### Reka Tools
|
|
173
|
+
|
|
174
|
+
#### `reka_research`
|
|
175
|
+
|
|
176
|
+
Autonomous research agent with multi-hop web synthesis.
|
|
177
|
+
|
|
178
|
+
| Parameter | Type | Default | Description |
|
|
179
|
+
|-----------|------|---------|-------------|
|
|
180
|
+
| messages | [Message] | required | Conversation messages |
|
|
181
|
+
| showThinking | bool | false | Show reasoning tags |
|
|
182
|
+
|
|
183
|
+
#### `reka_verify_claim`
|
|
184
|
+
|
|
185
|
+
Fact-check claims with structured verdict, confidence, and reasoning.
|
|
186
|
+
|
|
187
|
+
| Parameter | Type | Default | Description |
|
|
188
|
+
|-----------|------|---------|-------------|
|
|
189
|
+
| claim | string | required | Statement to verify |
|
|
190
|
+
| showThinking | bool | false | Show reasoning tags |
|
|
191
|
+
|
|
192
|
+
#### `reka_find_similar`
|
|
193
|
+
|
|
194
|
+
Find items similar to a target based on specific attributes.
|
|
195
|
+
|
|
196
|
+
| Parameter | Type | Default | Description |
|
|
197
|
+
|-----------|------|---------|-------------|
|
|
198
|
+
| target | string | required | Item to find similarities for |
|
|
199
|
+
| attribute | string | required | Characteristic to compare (e.g., "functionality", "style") |
|
|
200
|
+
| showThinking | bool | false | Show reasoning tags |
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
### Exa Tools
|
|
205
|
+
|
|
206
|
+
#### `exa_web_search`
|
|
207
|
+
|
|
208
|
+
Real-time web search with extensive filtering options.
|
|
209
|
+
|
|
210
|
+
| Parameter | Type | Default | Description |
|
|
211
|
+
|-----------|------|---------|-------------|
|
|
212
|
+
| query | string | required | Search query |
|
|
213
|
+
| numResults | int | 10 | Results count (1-100) |
|
|
214
|
+
| searchType | enum | auto | auto, neural, deep, fast |
|
|
215
|
+
| category | enum | "" | company, research paper, news, pdf, github, tweet, etc. |
|
|
216
|
+
| showContent | bool | false | Display full page content |
|
|
217
|
+
| includeDomains | string | "" | Domains to include |
|
|
218
|
+
| excludeDomains | string | "" | Domains to exclude |
|
|
219
|
+
| includeText | string | "" | Required text (max 5 words) |
|
|
220
|
+
| excludeText | string | "" | Excluded text (max 5 words) |
|
|
221
|
+
| startCrawlDate | string | "" | ISO 8601 date |
|
|
222
|
+
| endCrawlDate | string | "" | ISO 8601 date |
|
|
223
|
+
| startPublishedDate | string | "" | ISO 8601 date |
|
|
224
|
+
| endPublishedDate | string | "" | ISO 8601 date |
|
|
225
|
+
| returnText | bool | true | Fetch page text |
|
|
226
|
+
| textMaxChars | string | "" | Limit text length |
|
|
227
|
+
| includeHtmlTags | bool | false | Preserve HTML structure |
|
|
228
|
+
| returnHighlights | bool | false | AI-selected key snippets |
|
|
229
|
+
| highlightsSentences | int | 3 | Sentences per highlight (1-10) |
|
|
230
|
+
| highlightsPerUrl | int | 3 | Highlights per result (1-10) |
|
|
231
|
+
| highlightsQuery | string | "" | Guide highlight selection |
|
|
232
|
+
| returnSummary | bool | false | AI-generated summaries |
|
|
233
|
+
| summaryQuery | string | "" | Guide summary generation |
|
|
234
|
+
| livecrawl | enum | fallback | fallback, never, always, preferred |
|
|
235
|
+
| subpages | int | 0 | Linked subpages (0-10) |
|
|
236
|
+
| subpageTarget | string | "" | Keyword for subpages |
|
|
237
|
+
| showThinking | bool | false | Show reasoning tags |
|
|
238
|
+
|
|
239
|
+
#### `exa_deep_search`
|
|
240
|
+
|
|
241
|
+
Comprehensive search with automatic query expansion using deep mode.
|
|
242
|
+
|
|
243
|
+
| Parameter | Type | Default | Description |
|
|
244
|
+
|-----------|------|---------|-------------|
|
|
245
|
+
| objective | string | required | Natural language search description |
|
|
246
|
+
| searchQueries | string | "" | Optional keyword queries (comma-separated, max 5) |
|
|
247
|
+
|
|
248
|
+
Plus all filtering parameters from `exa_web_search`.
|
|
249
|
+
|
|
250
|
+
#### `exa_code_context`
|
|
251
|
+
|
|
252
|
+
Code examples and API documentation search.
|
|
253
|
+
|
|
254
|
+
| Parameter | Type | Default | Description |
|
|
255
|
+
|-----------|------|---------|-------------|
|
|
256
|
+
| query | string | required | Code/API search query |
|
|
257
|
+
| codeTokens | enum | dynamic | dynamic, 5000, 10000, 20000 |
|
|
258
|
+
| showThinking | bool | false | Show reasoning tags |
|
|
259
|
+
|
|
260
|
+
#### `exa_crawl_url`
|
|
261
|
+
|
|
262
|
+
Extract content from specific URLs.
|
|
263
|
+
|
|
264
|
+
| Parameter | Type | Default | Description |
|
|
265
|
+
|-----------|------|---------|-------------|
|
|
266
|
+
| url | string | required | URL to crawl |
|
|
267
|
+
| maxCharacters | int | 3000 | Max characters to extract |
|
|
268
|
+
| returnText | bool | true | Fetch page text |
|
|
269
|
+
| includeHtmlTags | bool | false | Preserve HTML |
|
|
270
|
+
| returnHighlights | bool | false | Key snippets |
|
|
271
|
+
| highlightsSentences | int | 3 | Sentences per highlight |
|
|
272
|
+
| highlightsPerUrl | int | 3 | Highlights per result |
|
|
273
|
+
| highlightsQuery | string | "" | Guide highlights |
|
|
274
|
+
| returnSummary | bool | false | AI summaries |
|
|
275
|
+
| summaryQuery | string | "" | Guide summaries |
|
|
276
|
+
| livecrawl | enum | preferred | fallback, never, always, preferred |
|
|
277
|
+
| subpages | int | 0 | Linked subpages |
|
|
278
|
+
| subpageTarget | string | "" | Subpage keyword |
|
|
279
|
+
| showThinking | bool | false | Show reasoning tags |
|
|
280
|
+
|
|
281
|
+
#### `exa_find_similar`
|
|
282
|
+
|
|
283
|
+
Find pages similar to a given URL.
|
|
284
|
+
|
|
285
|
+
| Parameter | Type | Default | Description |
|
|
286
|
+
|-----------|------|---------|-------------|
|
|
287
|
+
| url | string | required | Source URL |
|
|
288
|
+
| numResults | int | 10 | Results count (1-100) |
|
|
289
|
+
| category | enum | "" | Content category filter |
|
|
290
|
+
| includeDomains | string | "" | Domains to include |
|
|
291
|
+
| excludeDomains | string | "" | Domains to exclude |
|
|
292
|
+
|
|
293
|
+
Plus content extraction parameters (returnText, highlights, summaries, livecrawl, subpages).
|
|
294
|
+
|
|
295
|
+
#### `exa_company_research`
|
|
296
|
+
|
|
297
|
+
Company research with curated business sources.
|
|
298
|
+
|
|
299
|
+
Pre-configured domains: bloomberg.com, reuters.com, crunchbase.com, sec.gov, linkedin.com, forbes.com, businesswire.com, prnewswire.com
|
|
300
|
+
|
|
301
|
+
| Parameter | Type | Default | Description |
|
|
302
|
+
|-----------|------|---------|-------------|
|
|
303
|
+
| companyName | string | required | Company to research |
|
|
304
|
+
| numResults | int | 5 | Results count |
|
|
305
|
+
| startPublishedDate | string | "" | ISO 8601 date |
|
|
306
|
+
| endPublishedDate | string | "" | ISO 8601 date |
|
|
307
|
+
| returnText | bool | true | Fetch page text |
|
|
308
|
+
| returnHighlights | bool | false | Key snippets |
|
|
309
|
+
| returnSummary | bool | false | AI summaries |
|
|
310
|
+
| livecrawl | enum | fallback | Content freshness |
|
|
311
|
+
| showThinking | bool | false | Show reasoning tags |
|
|
312
|
+
|
|
313
|
+
#### `exa_linkedin_search`
|
|
314
|
+
|
|
315
|
+
LinkedIn-specific search for profiles and companies.
|
|
316
|
+
|
|
317
|
+
| Parameter | Type | Default | Description |
|
|
318
|
+
|-----------|------|---------|-------------|
|
|
319
|
+
| query | string | required | LinkedIn search query |
|
|
320
|
+
| searchType | enum | all | profiles, companies, all |
|
|
321
|
+
| numResults | int | 5 | Results count |
|
|
322
|
+
| returnText | bool | true | Fetch page text |
|
|
323
|
+
| returnHighlights | bool | false | Key snippets |
|
|
324
|
+
| returnSummary | bool | false | AI summaries |
|
|
325
|
+
| livecrawl | enum | fallback | Content freshness |
|
|
326
|
+
| showThinking | bool | false | Show reasoning tags |
|
|
327
|
+
|
|
328
|
+
#### `exa_quick_answer`
|
|
329
|
+
|
|
330
|
+
Quick LLM answer with search-backed citations.
|
|
331
|
+
|
|
332
|
+
| Parameter | Type | Default | Description |
|
|
333
|
+
|-----------|------|---------|-------------|
|
|
334
|
+
| query | string | required | Question to answer |
|
|
335
|
+
| showText | bool | false | Show text under citations |
|
|
336
|
+
| showThinking | bool | false | Show reasoning tags |
|
|
337
|
+
|
|
338
|
+
#### `exa_deep_research`
|
|
339
|
+
|
|
340
|
+
Comprehensive AI-powered research agent.
|
|
341
|
+
|
|
342
|
+
| Parameter | Type | Default | Description |
|
|
343
|
+
|-----------|------|---------|-------------|
|
|
344
|
+
| instructions | string | required | Research question/instructions |
|
|
345
|
+
| model | enum | exa-research | exa-research (15-45s), exa-research-pro (45s-2min), exa-research-fast |
|
|
346
|
+
| showThinking | bool | false | Show reasoning tags |
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
### Linkup Tools
|
|
351
|
+
|
|
352
|
+
#### `linkup_search`
|
|
353
|
+
|
|
354
|
+
Factually accurate web search (ranked #1 on OpenAI's SimpleQA benchmark).
|
|
355
|
+
|
|
356
|
+
| Parameter | Type | Default | Description |
|
|
357
|
+
|-----------|------|---------|-------------|
|
|
358
|
+
| messages | [Message] | required | Conversation messages |
|
|
359
|
+
| depth | enum | standard | standard (fast), deep (comprehensive) |
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Development
|
|
364
|
+
|
|
365
|
+
### Project Structure
|
|
366
|
+
|
|
367
|
+
```
|
|
368
|
+
Sources/
|
|
369
|
+
├── Core/
|
|
370
|
+
│ ├── API/
|
|
371
|
+
│ │ ├── Config.swift # Environment configuration
|
|
372
|
+
│ │ ├── PoeAPIClient.swift # HTTP client
|
|
373
|
+
│ │ └── PoeTypes.swift # Request/response models
|
|
374
|
+
│ ├── Helpers/
|
|
375
|
+
│ │ ├── ContentStripper.swift # Strips <think> tags
|
|
376
|
+
│ │ └── With.swift # Functional builder
|
|
377
|
+
│ ├── Providers/
|
|
378
|
+
│ │ ├── ToolProvider.swift # Tool factory
|
|
379
|
+
│ │ ├── ServerProvider.swift # MCP server setup
|
|
380
|
+
│ │ └── ... # Other providers
|
|
381
|
+
│ ├── Tools/Search/
|
|
382
|
+
│ │ ├── Perplexity/ # 3 tools
|
|
383
|
+
│ │ ├── Reka/ # 3 tools
|
|
384
|
+
│ │ ├── Exa/ # 9 tools
|
|
385
|
+
│ │ └── Linkup/ # 1 tool
|
|
386
|
+
│ └── Environment.swift # @TaskLocal DI
|
|
387
|
+
└── swift-poe-search-mcp/
|
|
388
|
+
└── swift_search_mcp.swift # Entry point
|
|
389
|
+
|
|
390
|
+
Tests/
|
|
391
|
+
├── Perplexity/
|
|
392
|
+
├── Reka/
|
|
393
|
+
├── Exa/
|
|
394
|
+
├── Linkup/
|
|
395
|
+
└── Environment/ # Test utilities
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
### Testing
|
|
399
|
+
|
|
400
|
+
```bash
|
|
401
|
+
# Run all tests
|
|
402
|
+
POE_API_KEY=your_key swift test
|
|
403
|
+
|
|
404
|
+
# Run specific provider tests
|
|
405
|
+
POE_API_KEY=your_key swift test --filter "PerplexityToolTests"
|
|
406
|
+
POE_API_KEY=your_key swift test --filter "ExaToolsTests"
|
|
407
|
+
|
|
408
|
+
# Run specific tool test
|
|
409
|
+
POE_API_KEY=your_key swift test --filter "webSearchTool"
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
**Test Architecture:**
|
|
413
|
+
- Framework: Swift Testing (`@Test`, `@Suite`)
|
|
414
|
+
- Pattern: `@TaskLocal` environment injection for test isolation
|
|
415
|
+
- Type: Integration tests with real API calls
|
|
416
|
+
|
|
417
|
+
### Adding New Tools
|
|
418
|
+
|
|
419
|
+
1. Create tool file in appropriate provider directory:
|
|
420
|
+
|
|
421
|
+
```swift
|
|
422
|
+
import Foundation
|
|
423
|
+
import MCPToolkit
|
|
424
|
+
|
|
425
|
+
struct MyNewTool: MCPTool {
|
|
426
|
+
let name = "my_new_tool"
|
|
427
|
+
let description: String? = "Tool description"
|
|
428
|
+
|
|
429
|
+
@Schemable
|
|
430
|
+
@ObjectOptions(.additionalProperties { false })
|
|
431
|
+
struct Parameters: Sendable {
|
|
432
|
+
let query: String
|
|
433
|
+
let showThinking: Bool?
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
func call(with arguments: Parameters) async throws(ToolError) -> Content {
|
|
437
|
+
let model = "model-name"
|
|
438
|
+
let messages = [PoeMessage(role: "user", content: arguments.query)]
|
|
439
|
+
|
|
440
|
+
do {
|
|
441
|
+
let response = try await Environment.current.poeAPIClient().performChatCompletion(
|
|
442
|
+
messages,
|
|
443
|
+
model,
|
|
444
|
+
nil, // extra_body parameters
|
|
445
|
+
!(arguments.showThinking ?? false)
|
|
446
|
+
)
|
|
447
|
+
return [ToolContentItem(text: response.content)]
|
|
448
|
+
} catch let error as PoeError {
|
|
449
|
+
throw ToolError(error.localizedDescription)
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
2. Register in `ToolProvider.swift`:
|
|
456
|
+
|
|
457
|
+
```swift
|
|
458
|
+
if config.isProviderEnabled(.myProvider) {
|
|
459
|
+
tools += [MyNewTool()]
|
|
460
|
+
}
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
3. Add test in `Tests/MyProvider/MyProviderToolTests.swift`:
|
|
464
|
+
|
|
465
|
+
```swift
|
|
466
|
+
import Testing
|
|
467
|
+
@testable import Core
|
|
468
|
+
|
|
469
|
+
@Suite(.testEnvironment)
|
|
470
|
+
struct MyProviderToolTests {
|
|
471
|
+
@Test func myNewTool() async throws {
|
|
472
|
+
let tool = MyNewTool()
|
|
473
|
+
let result = try await tool.call(with: .init(query: "test"))
|
|
474
|
+
#expect(!result.isEmpty)
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
---
|
|
480
|
+
|
|
481
|
+
## API Reference
|
|
482
|
+
|
|
483
|
+
### Base Configuration
|
|
484
|
+
|
|
485
|
+
- **URL**: `https://api.poe.com/v1`
|
|
486
|
+
- **Format**: OpenAI-compatible `/v1/chat/completions`
|
|
487
|
+
- **Auth**: Bearer token via `Authorization` header
|
|
488
|
+
- **Custom params**: Via `extra_body` field
|
|
489
|
+
|
|
490
|
+
### Message Format
|
|
491
|
+
|
|
492
|
+
```swift
|
|
493
|
+
struct PoeMessage {
|
|
494
|
+
let role: String // "user", "assistant", "system"
|
|
495
|
+
let content: String
|
|
496
|
+
}
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### Response Format
|
|
500
|
+
|
|
501
|
+
```swift
|
|
502
|
+
struct PoeResponse {
|
|
503
|
+
let content: String
|
|
504
|
+
let citations: [String]?
|
|
505
|
+
let usage: TokenUsage?
|
|
506
|
+
}
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
---
|
|
510
|
+
|
|
511
|
+
## Troubleshooting
|
|
512
|
+
|
|
513
|
+
- **libcurl error on Linux**: Run `apt-get install libcurl4`
|
|
514
|
+
- **Platform not supported**: Only linux-x64 and darwin-arm64 (macOS 14+) are supported
|
|
515
|
+
- **Issues**: [GitHub Issues](https://github.com/mehmetbaykar/swift-poe-search-mcp/issues)
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
## License
|
|
520
|
+
|
|
521
|
+
MIT
|
|
Binary file
|
|
Binary file
|
package/bin.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require("child_process");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const os = require("os");
|
|
7
|
+
|
|
8
|
+
const BINARY_NAME = "swift-poe-search-mcp";
|
|
9
|
+
|
|
10
|
+
function getPlatformKey() {
|
|
11
|
+
const platform = os.platform();
|
|
12
|
+
if (platform === "darwin") return "darwin-arm64";
|
|
13
|
+
if (platform === "linux") return "linux-x64";
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function getBinaryPath() {
|
|
18
|
+
// 1. Local dev: .build/release or .build/debug
|
|
19
|
+
const devPaths = [
|
|
20
|
+
path.join(__dirname, ".build", "release", BINARY_NAME),
|
|
21
|
+
path.join(__dirname, ".build", "debug", BINARY_NAME),
|
|
22
|
+
];
|
|
23
|
+
for (const p of devPaths) {
|
|
24
|
+
if (fs.existsSync(p)) return p;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// 2. Installed: bin/<platform>/swift-poe-search-mcp
|
|
28
|
+
const platformKey = getPlatformKey();
|
|
29
|
+
if (platformKey) {
|
|
30
|
+
const platformPath = path.join(__dirname, "bin", platformKey, BINARY_NAME);
|
|
31
|
+
if (fs.existsSync(platformPath)) return platformPath;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 3. Legacy fallback: bin/swift-poe-search-mcp
|
|
35
|
+
const legacyPath = path.join(__dirname, "bin", BINARY_NAME);
|
|
36
|
+
if (fs.existsSync(legacyPath)) return legacyPath;
|
|
37
|
+
|
|
38
|
+
console.error(
|
|
39
|
+
`Error: Binary not found for platform: ${os.platform()}-${os.arch()}`
|
|
40
|
+
);
|
|
41
|
+
console.error("");
|
|
42
|
+
console.error("Supported platforms:");
|
|
43
|
+
console.error(" - linux-x64 (Ubuntu 20.04+, Debian 11+)");
|
|
44
|
+
console.error(" - darwin-arm64 (macOS 14+, Intel via Rosetta)");
|
|
45
|
+
console.error("");
|
|
46
|
+
console.error("Note: Windows and Alpine Linux are not supported.");
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const child = spawn(getBinaryPath(), process.argv.slice(2), {
|
|
51
|
+
stdio: "inherit",
|
|
52
|
+
env: process.env,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
child.on("error", (err) => {
|
|
56
|
+
if (err.message.includes("libcurl")) {
|
|
57
|
+
console.error("Missing libcurl. Run: apt-get install libcurl4");
|
|
58
|
+
} else {
|
|
59
|
+
console.error(`Failed to start: ${err.message}`);
|
|
60
|
+
}
|
|
61
|
+
process.exit(1);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
child.on("exit", (code, signal) => {
|
|
65
|
+
if (signal) process.kill(process.pid, signal);
|
|
66
|
+
else process.exit(code ?? 0);
|
|
67
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mehmetbaykar/swift-poe-search-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Swift MCP Server - Model Context Protocol server written in Swift",
|
|
5
|
+
"author": "Mehmet Baykar",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/mehmetbaykar/swift-poe-search-mcp.git"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"swift-poe-search-mcp": "bin.js"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "swift build",
|
|
16
|
+
"start": "swift build && node bin.js"
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"bin.js",
|
|
20
|
+
"bin"
|
|
21
|
+
],
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=20"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"mcp",
|
|
27
|
+
"model-context-protocol",
|
|
28
|
+
"swift",
|
|
29
|
+
"ai",
|
|
30
|
+
"perplexity",
|
|
31
|
+
"exa",
|
|
32
|
+
"search"
|
|
33
|
+
]
|
|
34
|
+
}
|