@bouroo/ollama-cloud-mcp 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 (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +252 -0
  3. package/dist/index.js +35132 -0
  4. package/package.json +48 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kawin Viriyaprasopsook
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,252 @@
1
+ # @bouroo/ollama-cloud-mcp
2
+
3
+ [![CI](https://github.com/bouroo/ollama-cloud-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/bouroo/ollama-cloud-mcp/actions/workflows/ci.yml)
4
+
5
+ An MCP server that exposes [Ollama's web search and web fetch](https://docs.ollama.com/capabilities/web-search)
6
+ capabilities as two tools, `web_search` and `web_fetch`, over stdio.
7
+
8
+ The server is a thin, dependency-free wrapper around two endpoints:
9
+
10
+ | Endpoint | Method | Purpose |
11
+ | --- | --- | --- |
12
+ | `POST https://ollama.com/api/web_search` | `query`, `max_results` | Ranked web results with title, URL and content excerpt |
13
+ | `POST https://ollama.com/api/web_fetch` | `url` | A page's title, extracted content and outbound links |
14
+
15
+ Both are authenticated with a bearer token from a free Ollama account.
16
+
17
+ ## Requirements
18
+
19
+ - Node.js — the current Active LTS. CI tracks `lts/*`, and no `engines` floor is
20
+ declared, so no version is claimed that CI does not actually test.
21
+ - A free Ollama account and an API key from <https://ollama.com/settings/keys>
22
+
23
+ ## Setup
24
+
25
+ Create a key at <https://ollama.com/settings/keys>, then register the server with
26
+ your MCP client.
27
+
28
+ **Claude Code**
29
+
30
+ ```bash
31
+ claude mcp add ollama-cloud --env OLLAMA_API_KEY=your-key-here -- npx -y @bouroo/ollama-cloud-mcp
32
+ ```
33
+
34
+ **Claude Desktop / other clients** — add to `claude_desktop_config.json` or the
35
+ equivalent `mcpServers` block:
36
+
37
+ ```json
38
+ {
39
+ "mcpServers": {
40
+ "ollama-cloud": {
41
+ "command": "npx",
42
+ "args": ["-y", "@bouroo/ollama-cloud-mcp"],
43
+ "env": { "OLLAMA_API_KEY": "your-key-here" }
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ No install step is needed — `npx` fetches and runs the package, which is published
50
+ as a single self-contained bundle with no runtime dependencies.
51
+
52
+ ## Tools
53
+
54
+ ### `web_search`
55
+
56
+ Search the web and return ranked results.
57
+
58
+ | Argument | Type | Required | Notes |
59
+ | --- | --- | --- | --- |
60
+ | `query` | string | yes | The search term, e.g. `"what is ollama?"` |
61
+ | `max_results` | integer | no | 1–10. Defaults to `5`. |
62
+
63
+ Returns `structuredContent.results`: an array of `{ title, url, content }`, plus a
64
+ readable text rendering:
65
+
66
+ ```
67
+ Web search results for "what is ollama?" (2):
68
+
69
+ [1] Ollama
70
+ URL: https://ollama.com/
71
+ Cloud models are now available in Ollama...
72
+
73
+ [2] What is Ollama? Introduction to the AI model management tool
74
+ URL: https://www.hostinger.com/tutorials/what-is-ollama
75
+ An introduction to running and managing local models...
76
+ ```
77
+
78
+ ### `web_fetch`
79
+
80
+ Fetch a single page and return its content.
81
+
82
+ | Argument | Type | Required | Notes |
83
+ | --- | --- | --- | --- |
84
+ | `url` | string | yes | May omit the scheme: `"ollama.com"` becomes `https://ollama.com/`. Only `http` and `https` are accepted. |
85
+
86
+ Returns `structuredContent`: `{ title, content, links }`, plus a readable text
87
+ rendering:
88
+
89
+ ```
90
+ Fetched ollama.com
91
+ Title: Ollama
92
+
93
+ Cloud models are now available in Ollama...
94
+
95
+ Links (2):
96
+ - http://ollama.com/
97
+ - https://github.com/ollama/ollama
98
+ ```
99
+
100
+ ## Configuration
101
+
102
+ | Variable | Required | Default | Description |
103
+ | --- | --- | --- | --- |
104
+ | `OLLAMA_API_KEY` | For the hosted API | — | Bearer token for `https://ollama.com`. |
105
+ | `OLLAMA_HOST` | No | `https://ollama.com` | Override the API base URL. A bare `host:port` is treated as `http://`, matching Ollama's own convention — e.g. `OLLAMA_HOST=127.0.0.1:11434` talks to a local daemon instead. |
106
+
107
+ Pointing `OLLAMA_HOST` at a local, signed-in Ollama daemon is supported and needs
108
+ no API key: the daemon handles its own authentication. If `OLLAMA_API_KEY` is set,
109
+ it is always sent.
110
+
111
+ ## Behaviour notes
112
+
113
+ - **Errors are returned as tool errors, not crashes.** A missing key, a rejected
114
+ key (HTTP 401/403), rate limiting (429) or a server error (5xx) comes back as
115
+ `isError: true` with a message naming the cause, so the model can explain it
116
+ instead of the client losing the server.
117
+ - **An empty result set is not an error** — `web_search` reports
118
+ `No web results found for "<query>".`
119
+ - **Requests time out after 30 seconds** rather than hanging the tool call.
120
+ - **stdout carries only the MCP protocol stream.** All diagnostics go to stderr.
121
+ - Ollama's docs suggest a context length of at least ~32,000 tokens when feeding
122
+ fetched pages to a model; `web_fetch` returns page content verbatim and does not
123
+ truncate it.
124
+
125
+ ## Development
126
+
127
+ Requires [Bun](https://bun.sh) for the toolchain; the published artifact runs on
128
+ plain Node.
129
+
130
+ ```bash
131
+ bun install
132
+ bun run typecheck # tsc --noEmit
133
+ bun run test # unit + in-memory MCP protocol tests
134
+ bun run build # bundles src/index.ts -> dist/index.js
135
+ bun run smoke # end-to-end stdio handshake against dist/
136
+
137
+ # With a key, exercise the live API as well:
138
+ OLLAMA_API_KEY=... node scripts/smoke.mjs "what is ollama?"
139
+ ```
140
+
141
+ `bun run smoke` drives the built server over real stdio: it performs the MCP
142
+ initialize handshake, lists tools, and calls `web_search`. Without
143
+ `OLLAMA_API_KEY` it asserts the missing-key error path instead, which still proves
144
+ the request wiring end to end.
145
+
146
+ Layout:
147
+
148
+ ```
149
+ src/ollama.ts API client: config, URL normalization, error mapping
150
+ src/server.ts MCP tool registration and response formatting
151
+ src/index.ts CLI entry point (stdio transport, --help, --version)
152
+ test/ unit tests and in-memory MCP protocol tests
153
+ scripts/smoke.mjs end-to-end stdio smoke test
154
+ ```
155
+
156
+ ## Releasing
157
+
158
+ npm publishing uses [trusted publishing](https://docs.npmjs.com/trusted-publishers)
159
+ (OIDC): GitHub mints a short-lived identity token for the run, npm exchanges it for
160
+ publish credentials, and a provenance attestation is attached automatically. No
161
+ long-lived npm token is stored in this repository.
162
+
163
+ ### One-time setup
164
+
165
+ Trusted publishing **cannot publish the first version of a package** — npm requires
166
+ the package to exist before a trusted publisher can be configured
167
+ ([npm/cli#8544](https://github.com/npm/cli/issues/8544), still open as of August 2026).
168
+ Bootstrap once, then never again:
169
+
170
+ 1. Publish `0.1.0` by any one-off method:
171
+ - enable 2FA on the npm account and run `npm publish --otp=<code>` locally, or
172
+ - mint a short-lived granular token (read-write on `@bouroo`) and publish with it.
173
+
174
+ npm rejects a publish backed by neither 2FA nor a bypass-2FA granular token:
175
+
176
+ ```
177
+ 403 Two-factor authentication or granular access token with bypass 2fa
178
+ enabled is required to publish packages.
179
+ ```
180
+
181
+ 2. Configure the trusted publisher at **npmjs.com → the package → Settings →
182
+ Trusted Publisher → GitHub Actions**:
183
+ - Repository: `bouroo/ollama-cloud-mcp`
184
+ - Workflow filename: `release.yml` — filename only, including the extension
185
+ - Environment: leave blank, the workflow uses none
186
+ 3. Every release after that publishes with no secret at all.
187
+
188
+ ### Cutting a release
189
+
190
+ ```bash
191
+ npm version patch # or minor / major — bumps package.json and tags the commit
192
+ git push --follow-tags
193
+ gh release create v0.1.1 --generate-notes
194
+ ```
195
+
196
+ `.github/workflows/release.yml` refuses to proceed unless the tag matches
197
+ `package.json` and that version is not already on npm, re-runs the gates, and then
198
+ stages the publish over OIDC.
199
+
200
+ To re-run a failed stage without cutting a new release, use
201
+ **Actions → Release → Run workflow**.
202
+
203
+ ### Approving a staged publish
204
+
205
+ The trusted publisher grants **stage-publish only**, so the workflow uploads into
206
+ npm's staging area rather than publishing directly. Staged publishing defers the
207
+ proof-of-presence (2FA) check to the approval step, which is what lets CI run
208
+ without a maintainer present. A human finishes it:
209
+
210
+ ```bash
211
+ npm stage list # find the stage id
212
+ npm stage approve <id> # publishes it (2FA required)
213
+ npm stage reject <id> # discards it
214
+ ```
215
+
216
+ Nothing moves the `latest` tag until that approval, so a staged release can be
217
+ inspected — or discarded — before it reaches anyone.
218
+
219
+ ### Gotchas
220
+
221
+ - **npm CLI 11.5.1+ and Node 22.14.0+** are required. The npm bundled with
222
+ `setup-node` is often older, so the workflow runs `npm install -g npm@latest` and
223
+ fails with a clear message if the version is still too low.
224
+ - The publisher is matched on **repository plus workflow filename**, so renaming or
225
+ moving `release.yml` silently breaks publishing.
226
+ - A publish rejected by npm reports one of two errors, and both point at the trust
227
+ configuration rather than at your code. The tell that the OIDC path itself worked
228
+ is the line just above the error:
229
+ `publish Provenance statement published to transparency log: ...`.
230
+ - **`403 ... OIDC permission denied for this action`** — the OIDC token was minted
231
+ and accepted, but no trusted-publisher relationship matches this repository and
232
+ workflow filename. Re-check both on the package's settings page.
233
+ - **`404`** — the package does not exist on npm yet, so there is nothing to attach
234
+ a publisher to. See the one-time setup above.
235
+ - `prepack` runs the typecheck, tests and build, so a tarball always carries fresh
236
+ output. The package is a bundle: `dependencies` is empty and consumers install
237
+ nothing.
238
+
239
+ ## Continuous integration
240
+
241
+ `.github/workflows/ci.yml` runs on every push to `main` and every pull request,
242
+ on the current Active LTS (`lts/*`):
243
+
244
+ - type-check, test, build
245
+ - drive a **full MCP handshake against a copy of the built bundle sitting alone in
246
+ an empty directory**, with no `node_modules` to fall back on — this is what
247
+ makes the "zero runtime dependencies" claim tested rather than asserted
248
+ - the same handshake against the source build
249
+
250
+ ## License
251
+
252
+ MIT