pull_model
Download a model from the Ollama registry by specifying its name (e.g., 'llama3.1:8b'). The process blocks until the download completes.
Instructions
Download a model from the Ollama registry. Blocks until complete — can take a long time for multi-GB models. For very large pulls, prefer ollama pull in a terminal where you can watch progress.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Model name to pull (e.g. "llama3.1:8b"). |
Implementation Reference
- server.js:247-263 (handler)The 'pullModel' async function that implements the pull_model tool logic. It validates the 'name' argument, sends a POST request to /api/pull with stream:false, and returns the model name, status, and success flag.
// ─── Tool: pull_model ───────────────────────────────────────────────────── async function pullModel(args) { const bad = requireString(args, 'name'); if (bad) return errorResult(bad); // Use stream:false — Ollama buffers and returns a single final event. // For very large models this can block the connection for a long time; // users pulling multi-GB models are better served by `ollama pull` in a // terminal where they can see progress. Documented in the README. const r = await httpRequest('POST', '/api/pull', { name: args.name, stream: false }); if (r.error) return errorResult(r.error); const d = r.data || {}; return textResult({ name: args.name, status: d.status || 'unknown', success: d.status === 'success', }); } - server.js:357-369 (schema)The tool registration entry for 'pull_model' in the TOOLS array, including its description, annotations, and inputSchema (which requires a 'name' string property).
{ name: 'pull_model', description: 'Download a model from the Ollama registry. Blocks until complete — can take a long time for multi-GB models. For very large pulls, prefer `ollama pull` in a terminal where you can watch progress.', annotations: { title: 'Pull model', readOnlyHint: false, destructiveHint: false, openWorldHint: true }, inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Model name to pull (e.g. "llama3.1:8b").' }, }, required: ['name'], additionalProperties: false, }, }, - server.js:385-394 (registration)The HANDLERS map that links the tool name 'pull_model' to the pullModel function for JSON-RPC dispatch.
const HANDLERS = { ollama_status: ollamaStatus, list_models: listModels, list_running: listRunning, show_model: showModel, generate: generate, chat: chat, pull_model: pullModel, delete_model: deleteModel, }; - server.js:109-114 (helper)The 'requireString' helper function used by pullModel to validate that the 'name' argument is a non-empty string.
function requireString(args, field) { if (typeof args[field] !== 'string' || !args[field].trim()) { return `${field} is required (non-empty string)`; } return null; } - server.js:57-107 (helper)The 'httpRequest' helper function used by pullModel to make the POST request to Ollama's /api/pull endpoint.
function httpRequest(method, path, body) { return new Promise((resolve) => { let url; try { url = new URL(path, OLLAMA_URL); } catch (e) { resolve({ error: `invalid URL: ${e.message}` }); return; } const lib = url.protocol === 'https:' ? https : http; const opts = { method, hostname: url.hostname, port: url.port || (url.protocol === 'https:' ? 443 : 80), path: url.pathname + url.search, headers: { 'accept': 'application/json' }, }; let bodyBuf = null; if (body !== undefined) { bodyBuf = Buffer.from(JSON.stringify(body), 'utf8'); opts.headers['content-type'] = 'application/json'; opts.headers['content-length'] = bodyBuf.length; } const req = lib.request(opts, (res) => { let chunks = Buffer.alloc(0); res.on('data', (d) => { chunks = Buffer.concat([chunks, d]); }); res.on('end', () => { const text = chunks.toString('utf8'); if (res.statusCode >= 400) { resolve({ status: res.statusCode, error: `HTTP ${res.statusCode}: ${text.slice(0, 500)}` }); return; } // Some endpoints return text/plain (e.g. GET /); try JSON first, fall back to text. try { resolve({ status: res.statusCode, data: JSON.parse(text) }); } catch (_) { resolve({ status: res.statusCode, data: null, text }); } }); }); req.setTimeout(REQUEST_TIMEOUT_MS, () => { req.destroy(new Error(`request timed out after ${REQUEST_TIMEOUT_MS}ms`)); }); req.on('error', (e) => { // Give a friendly connection-refused message. const msg = /ECONNREFUSED|ENOTFOUND/.test(e.code || e.message) ? `cannot reach Ollama at ${OLLAMA_URL} — is the server running? Start it with \`ollama serve\` or open the Ollama app.` : e.message; resolve({ error: msg }); }); if (bodyBuf) req.write(bodyBuf); req.end(); }); }