mcp-searchable 1.0.2
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/.npx-install/README.md +188 -0
- package/.npx-install/bootstrap.js +341 -0
- package/LICENSE +21 -0
- package/README.md +312 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +185 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/storage.d.ts +17 -0
- package/dist/lib/storage.d.ts.map +1 -0
- package/dist/lib/storage.js +105 -0
- package/dist/lib/storage.js.map +1 -0
- package/dist/lib/web-ask.d.ts +13 -0
- package/dist/lib/web-ask.d.ts.map +1 -0
- package/dist/lib/web-ask.js +73 -0
- package/dist/lib/web-ask.js.map +1 -0
- package/dist/lib/web-fetch.d.ts +13 -0
- package/dist/lib/web-fetch.d.ts.map +1 -0
- package/dist/lib/web-fetch.js +48 -0
- package/dist/lib/web-fetch.js.map +1 -0
- package/dist/lib/web-search.d.ts +23 -0
- package/dist/lib/web-search.d.ts.map +1 -0
- package/dist/lib/web-search.js +160 -0
- package/dist/lib/web-search.js.map +1 -0
- package/package.json +99 -0
package/README.md
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# TypeScript Bootstrap Template
|
|
2
|
+
|
|
3
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
|
+
[](https://github.com/templ-project/typescript/actions/workflows/ci.yml)
|
|
5
|
+
[](https://github.com/templ-project/typescript/issues)
|
|
6
|
+
|
|
7
|
+
> A modern TypeScript project template with ESM, testing, linting, and quality tools built-in.
|
|
8
|
+
|
|
9
|
+
- [TypeScript Bootstrap Template](#typescript-bootstrap-template)
|
|
10
|
+
- [Quick Start](#quick-start)
|
|
11
|
+
- [Bootstrap Options](#bootstrap-options)
|
|
12
|
+
- [What's Included](#whats-included)
|
|
13
|
+
- [Common Commands](#common-commands)
|
|
14
|
+
- [Using npm](#using-npm)
|
|
15
|
+
- [Using mise tasks (Recommended)](#using-taskfile-recommended)
|
|
16
|
+
- [Requirements](#requirements)
|
|
17
|
+
- [Setup Development Environment](#setup-development-environment)
|
|
18
|
+
- [Project Structure](#project-structure)
|
|
19
|
+
- [Building](#building)
|
|
20
|
+
- [Testing](#testing)
|
|
21
|
+
- [Code Quality](#code-quality)
|
|
22
|
+
- [Pre-commit Hooks](#pre-commit-hooks)
|
|
23
|
+
- [Configuration](#configuration)
|
|
24
|
+
- [Using as a Library](#using-as-a-library)
|
|
25
|
+
- [CI/CD Pipeline](#cicd-pipeline)
|
|
26
|
+
- [License](#license)
|
|
27
|
+
- [Support](#support)
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
**Bootstrap a new project:**
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx --yes --package=github:templ-project/typescript bootstrap ./my-project
|
|
35
|
+
cd my-project
|
|
36
|
+
npm install
|
|
37
|
+
npm test
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
That's it! You now have a fully configured TypeScript project.
|
|
41
|
+
|
|
42
|
+
## MCP Search Providers
|
|
43
|
+
|
|
44
|
+
The `web_search` MCP tool supports multiple providers via the optional `provider` argument:
|
|
45
|
+
|
|
46
|
+
- `duckduckgo` (default)
|
|
47
|
+
- `google` (Google Custom Search JSON API)
|
|
48
|
+
- `bing` (Bing Web Search API)
|
|
49
|
+
- `brave` (Brave Search API)
|
|
50
|
+
|
|
51
|
+
### Tool input
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"query": "model context protocol",
|
|
56
|
+
"provider": "google",
|
|
57
|
+
"limit": 5
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Required environment variables
|
|
62
|
+
|
|
63
|
+
- `GOOGLE_API_KEY` and `GOOGLE_CSE_ID` for `provider=google`
|
|
64
|
+
- `BING_API_KEY` for `provider=bing`
|
|
65
|
+
- `BRAVE_API_KEY` for `provider=brave`
|
|
66
|
+
|
|
67
|
+
Optional:
|
|
68
|
+
|
|
69
|
+
- `BING_API_ENDPOINT` (override default Bing endpoint)
|
|
70
|
+
|
|
71
|
+
You can copy `.env.example` and fill in your provider keys.
|
|
72
|
+
|
|
73
|
+
### Bootstrap Options
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
# Bootstrap with only ESM and CJS builds (no browser builds)
|
|
77
|
+
npx --yes --package=github:templ-project/typescript bootstrap --target esm,cjs ./my-project
|
|
78
|
+
|
|
79
|
+
# Bootstrap as part of a monorepo (removes .husky, .github)
|
|
80
|
+
npx --yes --package=github:templ-project/typescript bootstrap --part-of-monorepo ./packages/my-lib
|
|
81
|
+
|
|
82
|
+
# Show all available options
|
|
83
|
+
npx --yes --package=github:templ-project/typescript bootstrap --help
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
See [.npx-install/README.md](.npx-install/README.md) for detailed bootstrap documentation.
|
|
87
|
+
|
|
88
|
+
## What's Included
|
|
89
|
+
|
|
90
|
+
| Feature | Tool | Description |
|
|
91
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------- | ---------------------------------- |
|
|
92
|
+
| **Language** | [TypeScript 5.9](https://www.typescriptlang.org/) | Type-safe JavaScript |
|
|
93
|
+
| **Runtime** | [Node.js 22+](https://nodejs.org/) | Modern JavaScript runtime |
|
|
94
|
+
| **Execution** | [tsx](https://github.com/privatenumber/tsx) | TypeScript execution without build |
|
|
95
|
+
| **Module System** | ESM | Native ES Modules |
|
|
96
|
+
| **Build System** | [tsc](https://www.typescriptlang.org/) + [esbuild](https://esbuild.github.io/) | Type-check + fast bundling |
|
|
97
|
+
| **Test Framework** | [Vitest](https://vitest.dev/) | Fast unit testing with V8 coverage |
|
|
98
|
+
| **Linting** | [ESLint](https://eslint.org/) | Code quality with TypeScript rules |
|
|
99
|
+
| **Formatting** | [Prettier](https://prettier.io/) | Consistent code formatting |
|
|
100
|
+
| **Documentation** | [MkDocs](https://www.mkdocs.org/) + [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/) | Project documentation site |
|
|
101
|
+
| **Task Runner** | [mise tasks](https://mise.jdx.dev/tasks/) | Modern build automation |
|
|
102
|
+
| **Tool Management** | [mise](https://mise.jdx.dev/) | Isolated development environment |
|
|
103
|
+
| **Pre-commit Hooks** | [Husky](https://typicode.github.io/husky/) + [lint-staged](https://github.com/okonet/lint-staged) | Automatic validation |
|
|
104
|
+
| **Duplicate Detection** | [jscpd](https://github.com/kucherenko/jscpd) | Copy-paste detector |
|
|
105
|
+
| **CI/CD** | GitHub Actions | Multi-platform testing & releases |
|
|
106
|
+
|
|
107
|
+
## Common Commands
|
|
108
|
+
|
|
109
|
+
### Using npm
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
npm start # Run the app (via tsx)
|
|
113
|
+
npm test # Run tests
|
|
114
|
+
npm run test:coverage # Run tests with coverage
|
|
115
|
+
npm run lint # Lint and auto-fix
|
|
116
|
+
npm run format # Format code with Prettier
|
|
117
|
+
npm run build # Build for production
|
|
118
|
+
npm run docs # Build MkDocs site (strict)
|
|
119
|
+
npm run validate # Run all quality checks
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Using mise tasks (Recommended)
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# === Development ===
|
|
126
|
+
mise run run # Run the application (via node)
|
|
127
|
+
mise run format # Format all code (Prettier)
|
|
128
|
+
mise run format:check # Check formatting without fixing
|
|
129
|
+
mise run lint # Lint all code (ESLint + TypeScript)
|
|
130
|
+
mise run lint:check # Check all without fixing
|
|
131
|
+
mise run duplicate-check # Check for duplicate code
|
|
132
|
+
mise run docs # Build MkDocs site (strict)
|
|
133
|
+
mise run docs:serve # Serve documentation locally
|
|
134
|
+
mise run deps:sync # Install all dependencies (mise, npm)
|
|
135
|
+
mise run deps:refresh # Update all dependencies
|
|
136
|
+
mise run deps:clean # Remove all dependencies
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Requirements
|
|
140
|
+
|
|
141
|
+
- [mise](https://mise.jdx.dev/) - Tool version management (installs everything else)
|
|
142
|
+
|
|
143
|
+
**Automatically installed via mise:**
|
|
144
|
+
|
|
145
|
+
- Node.js 22+
|
|
146
|
+
- Python 3.11+ (for helper scripts)
|
|
147
|
+
- ShellCheck (shell script linting)
|
|
148
|
+
- PowerShell Core (cross-platform PowerShell)
|
|
149
|
+
|
|
150
|
+
## Setup Development Environment
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# Install mise (if not already installed)
|
|
154
|
+
# Linux/macOS:
|
|
155
|
+
curl https://mise.run | sh
|
|
156
|
+
|
|
157
|
+
# Windows (PowerShell):
|
|
158
|
+
winget install jdx.mise
|
|
159
|
+
# or: choco install mise
|
|
160
|
+
|
|
161
|
+
# Install project tools and node modules
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
# Clone and setup
|
|
165
|
+
git clone https://github.com/templ-project/typescript.git my-project
|
|
166
|
+
cd my-project
|
|
167
|
+
|
|
168
|
+
# Install all dependencies
|
|
169
|
+
mise run deps:sync
|
|
170
|
+
|
|
171
|
+
# Verify setup
|
|
172
|
+
mise run validate
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Project Structure
|
|
176
|
+
|
|
177
|
+
```text
|
|
178
|
+
├── .github/
|
|
179
|
+
│ └── workflows/ # CI/CD pipelines
|
|
180
|
+
├── .husky/ # Git hooks
|
|
181
|
+
├── .scripts/ # Build/lint helper scripts
|
|
182
|
+
|
|
183
|
+
├── src/
|
|
184
|
+
│ ├── index.ts # Main entry point
|
|
185
|
+
│ └── lib/
|
|
186
|
+
│ ├── greeter.ts # Example module with TypeScript types
|
|
187
|
+
│ └── greeter.spec.ts # Unit tests (co-located)
|
|
188
|
+
├── dist/ # Build output (gitignored)
|
|
189
|
+
├── docs/ # MkDocs source pages
|
|
190
|
+
├── mise.toml # Configuration and tasks
|
|
191
|
+
├── .mise.toml # Tool versions & hooks
|
|
192
|
+
├── package.json # Node.js dependencies
|
|
193
|
+
├── tsconfig.json # TypeScript configuration
|
|
194
|
+
├── vitest.config.ts # Test configuration
|
|
195
|
+
├── eslint.config.mjs # ESLint configuration
|
|
196
|
+
├── prettier.config.mjs # Prettier configuration
|
|
197
|
+
└── mkdocs.yml # MkDocs configuration
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Building
|
|
201
|
+
|
|
202
|
+
The template uses a two-step build process:
|
|
203
|
+
|
|
204
|
+
1. **tsc** - Type-checks and emits declaration files (`.d.ts`)
|
|
205
|
+
2. **esbuild** - Bundles for multiple targets
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
npm run build
|
|
209
|
+
# or: npm run build
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Outputs:
|
|
213
|
+
|
|
214
|
+
- `dist/index.js` - Node.js ESM build artifact
|
|
215
|
+
- `dist/index.d.ts` - TypeScript declaration file
|
|
216
|
+
|
|
217
|
+
## Testing
|
|
218
|
+
|
|
219
|
+
Tests are co-located with source files using the `.spec.ts` suffix:
|
|
220
|
+
|
|
221
|
+
```typescript
|
|
222
|
+
// src/lib/greeter.spec.ts
|
|
223
|
+
import { describe, it, expect } from "vitest";
|
|
224
|
+
import { hello } from "./greeter";
|
|
225
|
+
|
|
226
|
+
describe("hello", () => {
|
|
227
|
+
it("returns greeting", () => {
|
|
228
|
+
expect(hello("World")).toBe("Hello, World!");
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Run tests:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
npm run test # Run all tests
|
|
237
|
+
npm run test:coverage # Run with coverage report
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## Code Quality
|
|
241
|
+
|
|
242
|
+
### Pre-commit Hooks
|
|
243
|
+
|
|
244
|
+
Every commit is validated with:
|
|
245
|
+
|
|
246
|
+
- Code formatting (Prettier)
|
|
247
|
+
- Linting (ESLint)
|
|
248
|
+
- Type checking (TypeScript)
|
|
249
|
+
- Unit tests (Vitest)
|
|
250
|
+
|
|
251
|
+
CI runs additional checks:
|
|
252
|
+
|
|
253
|
+
- Test coverage
|
|
254
|
+
- Duplicate code detection
|
|
255
|
+
- License compliance
|
|
256
|
+
|
|
257
|
+
Configure hooks in:
|
|
258
|
+
|
|
259
|
+
- `.husky/pre-commit` - Hook script
|
|
260
|
+
- `.lintstagedrc.yml` - File patterns and commands
|
|
261
|
+
|
|
262
|
+
## Configuration
|
|
263
|
+
|
|
264
|
+
All configuration uses shared packages for consistency:
|
|
265
|
+
|
|
266
|
+
| File | Purpose |
|
|
267
|
+
| --------------------- | ----------------------------------------------------- |
|
|
268
|
+
| `.mise.toml` | Tool versions (Node, Python, ShellCheck) |
|
|
269
|
+
| `mise.toml` | Configuration and tasks |
|
|
270
|
+
| `tsconfig.json` | TypeScript config (extends `@templ-project/tsconfig`) |
|
|
271
|
+
| `eslint.config.mjs` | ESLint config (uses `@templ-project/eslint`) |
|
|
272
|
+
| `prettier.config.mjs` | Prettier config (uses `@templ-project/prettier`) |
|
|
273
|
+
| `vitest.config.ts` | Vitest test configuration |
|
|
274
|
+
| `mkdocs.yml` | MkDocs site navigation and theme settings |
|
|
275
|
+
| `.jscpd.json` | Duplicate detection settings |
|
|
276
|
+
| `.licensee.json` | License compliance settings |
|
|
277
|
+
|
|
278
|
+
## Using as a Library
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
// ES Modules (recommended)
|
|
282
|
+
import { hello, Greeter } from "@templ-project/typescript-template";
|
|
283
|
+
|
|
284
|
+
const greeting = hello("World");
|
|
285
|
+
console.log(greeting); // "Hello, World!"
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
```javascript
|
|
289
|
+
// ESM from built output
|
|
290
|
+
import { hello } from "./dist/index.js";
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## CI/CD Pipeline
|
|
294
|
+
|
|
295
|
+
The GitHub Actions pipeline runs on **Linux, macOS, and Windows**:
|
|
296
|
+
|
|
297
|
+
| Workflow | Trigger | Jobs |
|
|
298
|
+
| ---------------- | ----------------------- | ---------------------------------- |
|
|
299
|
+
| `ci.yml` | Push/PR to main/develop | Matrix orchestrator |
|
|
300
|
+
| `ci.quality.yml` | Called by ci.yml | lint, test, build, duplicate-check |
|
|
301
|
+
| `ci.version.yml` | Push to main | Semantic version bump |
|
|
302
|
+
| `ci.release.yml` | After version bump | Create GitHub release |
|
|
303
|
+
|
|
304
|
+
## License
|
|
305
|
+
|
|
306
|
+
MIT © [Templ Project](https://github.com/templ-project)
|
|
307
|
+
|
|
308
|
+
## Support
|
|
309
|
+
|
|
310
|
+
- [Report Issues](https://github.com/templ-project/typescript/issues)
|
|
311
|
+
- [Read the Docs](https://github.com/templ-project/typescript#readme)
|
|
312
|
+
- [Star on GitHub](https://github.com/templ-project/typescript)
|
package/dist/index.d.ts
ADDED
|
@@ -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,185 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import { WebStorage } from './lib/storage.js';
|
|
6
|
+
import { OllamaAskProvider } from './lib/web-ask.js';
|
|
7
|
+
import { WebFetcher } from './lib/web-fetch.js';
|
|
8
|
+
import { createSearchProvider } from './lib/web-search.js';
|
|
9
|
+
const SEARCH_PROVIDERS = ['duckduckgo', 'google', 'bing', 'brave'];
|
|
10
|
+
const webFetcher = new WebFetcher();
|
|
11
|
+
const webStorage = new WebStorage('.web_stash.db');
|
|
12
|
+
const askProvider = new OllamaAskProvider(webStorage);
|
|
13
|
+
const server = new Server({
|
|
14
|
+
name: 'smart-web-extraction',
|
|
15
|
+
version: '1.0.0',
|
|
16
|
+
}, {
|
|
17
|
+
capabilities: {
|
|
18
|
+
tools: {},
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
const SearchInputSchema = {
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {
|
|
24
|
+
query: { type: 'string', description: 'Search query' },
|
|
25
|
+
provider: {
|
|
26
|
+
type: 'string',
|
|
27
|
+
enum: SEARCH_PROVIDERS,
|
|
28
|
+
description: 'Search provider (default: duckduckgo)',
|
|
29
|
+
},
|
|
30
|
+
limit: { type: 'number', description: 'Max results (default: 5)' },
|
|
31
|
+
},
|
|
32
|
+
required: ['query'],
|
|
33
|
+
};
|
|
34
|
+
function parseRequiredString(value, fieldName) {
|
|
35
|
+
if (typeof value !== 'string') {
|
|
36
|
+
throw new Error(`Invalid ${fieldName}: expected a string`);
|
|
37
|
+
}
|
|
38
|
+
const normalized = value.trim();
|
|
39
|
+
if (!normalized) {
|
|
40
|
+
throw new Error(`Invalid ${fieldName}: cannot be empty`);
|
|
41
|
+
}
|
|
42
|
+
return normalized;
|
|
43
|
+
}
|
|
44
|
+
function parseOptionalPositiveLimit(value, defaultValue) {
|
|
45
|
+
if (value === undefined) {
|
|
46
|
+
return defaultValue;
|
|
47
|
+
}
|
|
48
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || !Number.isInteger(value) || value <= 0) {
|
|
49
|
+
throw new Error('Invalid limit: expected a positive integer');
|
|
50
|
+
}
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
function parseProvider(value) {
|
|
54
|
+
if (value === undefined) {
|
|
55
|
+
return 'duckduckgo';
|
|
56
|
+
}
|
|
57
|
+
if (typeof value !== 'string') {
|
|
58
|
+
throw new Error('Invalid provider: expected a string');
|
|
59
|
+
}
|
|
60
|
+
const provider = value.trim();
|
|
61
|
+
if (!SEARCH_PROVIDERS.includes(provider)) {
|
|
62
|
+
throw new Error(`Invalid provider: ${provider}. Supported providers: ${SEARCH_PROVIDERS.join(', ')}`);
|
|
63
|
+
}
|
|
64
|
+
return provider;
|
|
65
|
+
}
|
|
66
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
67
|
+
return {
|
|
68
|
+
tools: [
|
|
69
|
+
{
|
|
70
|
+
name: 'web_search',
|
|
71
|
+
description: 'Search the web using supported providers (DuckDuckGo, Google, Bing, Brave).',
|
|
72
|
+
inputSchema: SearchInputSchema,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
name: 'web_fetch',
|
|
76
|
+
description: 'Fetch and extract markdown content from a URL.',
|
|
77
|
+
inputSchema: {
|
|
78
|
+
type: 'object',
|
|
79
|
+
properties: {
|
|
80
|
+
url: { type: 'string', description: 'URL to fetch' },
|
|
81
|
+
},
|
|
82
|
+
required: ['url'],
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'web_stash',
|
|
87
|
+
description: 'Store markdown content into local SQLite database.',
|
|
88
|
+
inputSchema: {
|
|
89
|
+
type: 'object',
|
|
90
|
+
properties: {
|
|
91
|
+
url: { type: 'string', description: 'Source URL' },
|
|
92
|
+
title: { type: 'string', description: 'Title of the page' },
|
|
93
|
+
content: { type: 'string', description: 'Markdown content' },
|
|
94
|
+
},
|
|
95
|
+
required: ['url', 'title', 'content'],
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
name: 'web_grep',
|
|
100
|
+
description: 'Search stashed web pages using FTS5.',
|
|
101
|
+
inputSchema: SearchInputSchema,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
name: 'web_ask',
|
|
105
|
+
description: 'Ask a question using a local Ollama model and context from stashed web pages.',
|
|
106
|
+
inputSchema: {
|
|
107
|
+
type: 'object',
|
|
108
|
+
properties: {
|
|
109
|
+
question: { type: 'string', description: 'The question to ask' },
|
|
110
|
+
limit: { type: 'number', description: 'Number of sources to retrieve (default: 3)' },
|
|
111
|
+
},
|
|
112
|
+
required: ['question'],
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
119
|
+
const { name, arguments: args } = request.params;
|
|
120
|
+
try {
|
|
121
|
+
switch (name) {
|
|
122
|
+
case 'web_search': {
|
|
123
|
+
const query = parseRequiredString(args?.query, 'query');
|
|
124
|
+
const provider = parseProvider(args?.provider);
|
|
125
|
+
const limit = parseOptionalPositiveLimit(args?.limit, 5);
|
|
126
|
+
const searchProvider = createSearchProvider(provider);
|
|
127
|
+
const results = await searchProvider.search(query, limit);
|
|
128
|
+
return {
|
|
129
|
+
content: [{ type: 'text', text: JSON.stringify(results, null, 2) }],
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
case 'web_fetch': {
|
|
133
|
+
const url = parseRequiredString(args?.url, 'url');
|
|
134
|
+
const result = await webFetcher.fetch(url);
|
|
135
|
+
return {
|
|
136
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
case 'web_stash': {
|
|
140
|
+
const url = parseRequiredString(args?.url, 'url');
|
|
141
|
+
const title = parseRequiredString(args?.title, 'title');
|
|
142
|
+
const content = parseRequiredString(args?.content, 'content');
|
|
143
|
+
webStorage.stash({ url, title, content });
|
|
144
|
+
return {
|
|
145
|
+
content: [{ type: 'text', text: `Successfully stashed ${url}` }],
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
case 'web_grep': {
|
|
149
|
+
const query = parseRequiredString(args?.query, 'query');
|
|
150
|
+
const limit = parseOptionalPositiveLimit(args?.limit, 5);
|
|
151
|
+
const results = webStorage.grep(query, limit);
|
|
152
|
+
return {
|
|
153
|
+
content: [{ type: 'text', text: JSON.stringify(results, null, 2) }],
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
case 'web_ask': {
|
|
157
|
+
const question = parseRequiredString(args?.question, 'question');
|
|
158
|
+
const limit = parseOptionalPositiveLimit(args?.limit, 3);
|
|
159
|
+
const result = await askProvider.ask(question, limit);
|
|
160
|
+
return {
|
|
161
|
+
content: [{ type: 'text', text: `Answer:\n${result.answer}\n\nSources:\n${result.contextUrls.join('\n')}` }],
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
default:
|
|
165
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
const err = error;
|
|
170
|
+
return {
|
|
171
|
+
content: [{ type: 'text', text: `Error executing tool ${name}: ${err.message}` }],
|
|
172
|
+
isError: true,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
async function run() {
|
|
177
|
+
const transport = new StdioServerTransport();
|
|
178
|
+
await server.connect(transport);
|
|
179
|
+
console.error('Smart Web Extraction MCP Server running on stdio');
|
|
180
|
+
}
|
|
181
|
+
run().catch((error) => {
|
|
182
|
+
console.error('Fatal error running server:', error);
|
|
183
|
+
process.exit(1);
|
|
184
|
+
});
|
|
185
|
+
//# 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,17 @@
|
|
|
1
|
+
import { WebFetchResult } from './web-fetch.js';
|
|
2
|
+
export interface GrepResult {
|
|
3
|
+
url: string;
|
|
4
|
+
title: string;
|
|
5
|
+
snippet: string;
|
|
6
|
+
rank: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class WebStorage {
|
|
9
|
+
private db;
|
|
10
|
+
constructor(dbPath?: string);
|
|
11
|
+
private initSchema;
|
|
12
|
+
stash(page: WebFetchResult): void;
|
|
13
|
+
grep(query: string, limit?: number): GrepResult[];
|
|
14
|
+
getPage(url: string): WebFetchResult | null;
|
|
15
|
+
close(): void;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/lib/storage.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,UAAU;IACrB,OAAO,CAAC,EAAE,CAAe;gBAEb,MAAM,GAAE,MAAmB;IAKvC,OAAO,CAAC,UAAU;IA0ClB,KAAK,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAsBjC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,UAAU,EAAE;IA+BrD,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;IA2B3C,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
export class WebStorage {
|
|
3
|
+
db;
|
|
4
|
+
constructor(dbPath = ':memory:') {
|
|
5
|
+
this.db = new Database(dbPath);
|
|
6
|
+
this.initSchema();
|
|
7
|
+
}
|
|
8
|
+
initSchema() {
|
|
9
|
+
this.db.exec(`
|
|
10
|
+
CREATE TABLE IF NOT EXISTS pages (
|
|
11
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
12
|
+
url TEXT UNIQUE NOT NULL,
|
|
13
|
+
title TEXT,
|
|
14
|
+
content TEXT NOT NULL,
|
|
15
|
+
excerpt TEXT,
|
|
16
|
+
site_name TEXT,
|
|
17
|
+
created_at INTEGER NOT NULL
|
|
18
|
+
);
|
|
19
|
+
`);
|
|
20
|
+
this.db.exec(`
|
|
21
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS pages_fts USING fts5(
|
|
22
|
+
title,
|
|
23
|
+
content,
|
|
24
|
+
content='pages',
|
|
25
|
+
content_rowid='id'
|
|
26
|
+
);
|
|
27
|
+
`);
|
|
28
|
+
this.db.exec(`
|
|
29
|
+
CREATE TRIGGER IF NOT EXISTS pages_ai AFTER INSERT ON pages BEGIN
|
|
30
|
+
INSERT INTO pages_fts(rowid, title, content) VALUES (new.id, new.title, new.content);
|
|
31
|
+
END;
|
|
32
|
+
|
|
33
|
+
CREATE TRIGGER IF NOT EXISTS pages_ad AFTER DELETE ON pages BEGIN
|
|
34
|
+
INSERT INTO pages_fts(pages_fts, rowid, title, content) VALUES('delete', old.id, old.title, old.content);
|
|
35
|
+
END;
|
|
36
|
+
|
|
37
|
+
CREATE TRIGGER IF NOT EXISTS pages_au AFTER UPDATE ON pages BEGIN
|
|
38
|
+
INSERT INTO pages_fts(pages_fts, rowid, title, content) VALUES('delete', old.id, old.title, old.content);
|
|
39
|
+
INSERT INTO pages_fts(rowid, title, content) VALUES (new.id, new.title, new.content);
|
|
40
|
+
END;
|
|
41
|
+
`);
|
|
42
|
+
}
|
|
43
|
+
stash(page) {
|
|
44
|
+
const stmt = this.db.prepare(`
|
|
45
|
+
INSERT INTO pages (url, title, content, excerpt, site_name, created_at)
|
|
46
|
+
VALUES (@url, @title, @content, @excerpt, @siteName, @createdAt)
|
|
47
|
+
ON CONFLICT(url) DO UPDATE SET
|
|
48
|
+
title = excluded.title,
|
|
49
|
+
content = excluded.content,
|
|
50
|
+
excerpt = excluded.excerpt,
|
|
51
|
+
site_name = excluded.site_name,
|
|
52
|
+
created_at = excluded.created_at
|
|
53
|
+
`);
|
|
54
|
+
stmt.run({
|
|
55
|
+
url: page.url,
|
|
56
|
+
title: page.title,
|
|
57
|
+
content: page.content,
|
|
58
|
+
excerpt: page.excerpt || null,
|
|
59
|
+
siteName: page.siteName || null,
|
|
60
|
+
createdAt: Date.now(),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
grep(query, limit = 10) {
|
|
64
|
+
const stmt = this.db.prepare(`
|
|
65
|
+
SELECT
|
|
66
|
+
pages.url,
|
|
67
|
+
pages.title,
|
|
68
|
+
snippet(pages_fts, 1, '<b>', '</b>', '...', 64) as snippet,
|
|
69
|
+
pages_fts.rank
|
|
70
|
+
FROM pages_fts
|
|
71
|
+
JOIN pages ON pages.id = pages_fts.rowid
|
|
72
|
+
WHERE pages_fts MATCH @query
|
|
73
|
+
ORDER BY pages_fts.rank
|
|
74
|
+
LIMIT @limit
|
|
75
|
+
`);
|
|
76
|
+
const rows = stmt.all({ query, limit });
|
|
77
|
+
return rows.map((row) => ({
|
|
78
|
+
url: row.url,
|
|
79
|
+
title: row.title,
|
|
80
|
+
snippet: row.snippet,
|
|
81
|
+
rank: row.rank,
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
84
|
+
getPage(url) {
|
|
85
|
+
const stmt = this.db.prepare(`
|
|
86
|
+
SELECT url, title, content, excerpt, site_name as siteName
|
|
87
|
+
FROM pages
|
|
88
|
+
WHERE url = @url
|
|
89
|
+
`);
|
|
90
|
+
const row = stmt.get({ url });
|
|
91
|
+
if (!row)
|
|
92
|
+
return null;
|
|
93
|
+
return {
|
|
94
|
+
url: row.url,
|
|
95
|
+
title: row.title,
|
|
96
|
+
content: row.content,
|
|
97
|
+
excerpt: row.excerpt,
|
|
98
|
+
siteName: row.siteName,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
close() {
|
|
102
|
+
this.db.close();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/lib/storage.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAWtC,MAAM,OAAO,UAAU;IACb,EAAE,CAAe;IAEzB,YAAY,SAAiB,UAAU;QACrC,IAAI,CAAC,EAAE,GAAG,IAAI,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,CAAC,UAAU,EAAE,CAAC;IACpB,CAAC;IAEO,UAAU;QAEhB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;KAUZ,CAAC,CAAC;QAIH,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;KAOZ,CAAC,CAAC;QAGH,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;KAaZ,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,IAAoB;QACxB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;;;;;;KAS5B,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC;YACP,GAAG,EAAE,IAAI,CAAC,GAAG;YACb,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,IAAI;YAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI;YAC/B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,KAAa,EAAE,QAAgB,EAAE;QAGpC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;;;;;;;;KAW5B,CAAC,CAAC;QAEH,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAKpC,CAAC;QAEH,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YACxB,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,IAAI,EAAE,GAAG,CAAC,IAAI;SACf,CAAC,CAAC,CAAC;IACN,CAAC;IAED,OAAO,CAAC,GAAW;QACjB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;KAI5B,CAAC,CAAC;QAEH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAQf,CAAC;QACd,IAAI,CAAC,GAAG;YAAE,OAAO,IAAI,CAAC;QAEtB,OAAO;YACL,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,QAAQ,EAAE,GAAG,CAAC,QAAQ;SACvB,CAAC;IACJ,CAAC;IAED,KAAK;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;CACF"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { WebStorage } from './storage.js';
|
|
2
|
+
export interface AskResult {
|
|
3
|
+
answer: string;
|
|
4
|
+
contextUrls: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare class OllamaAskProvider {
|
|
7
|
+
private storage;
|
|
8
|
+
private ollamaUrl;
|
|
9
|
+
private model;
|
|
10
|
+
constructor(storage: WebStorage, ollamaUrl?: string, model?: string);
|
|
11
|
+
ask(question: string, limit?: number): Promise<AskResult>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=web-ask.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web-ask.d.ts","sourceRoot":"","sources":["../../src/lib/web-ask.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAc,MAAM,cAAc,CAAC;AAEtD,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,qBAAa,iBAAiB;IAE1B,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,KAAK;gBAFL,OAAO,EAAE,UAAU,EACnB,SAAS,GAAE,MAA2D,EACtE,KAAK,GAAE,MAA6C;IAGxD,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAE,MAAU,GAAG,OAAO,CAAC,SAAS,CAAC;CAiFnE"}
|