{"_id":"@hanoak/unsplash-mcp-server","_rev":"5-a81c093a0e7437cb4b98a7c2b9a7bf65","name":"@hanoak/unsplash-mcp-server","dist-tags":{"latest":"1.2.1"},"versions":{"1.0.0":{"name":"@hanoak/unsplash-mcp-server","version":"1.0.0","keywords":["mcp","modelcontextprotocol","model-context-protocol","mcp-server","unsplash","unsplash-api","images","photos","stock-photos","claude","ai","llm"],"author":{"name":"Hanoak S"},"license":"MIT","_id":"@hanoak/unsplash-mcp-server@1.0.0","maintainers":[{"name":"hanoak","email":"hanoak4online@gmail.com"}],"homepage":"https://github.com/hanoak/unsplash-mcp-server#readme","bugs":{"url":"https://github.com/hanoak/unsplash-mcp-server/issues"},"bin":{"unsplash-mcp-server":"dist/index.js"},"dist":{"shasum":"fc25fd03a8ba1c2eba5aff065d59f4e709f34886","tarball":"https://registry.npmjs.org/@hanoak/unsplash-mcp-server/-/unsplash-mcp-server-1.0.0.tgz","fileCount":6,"integrity":"sha512-3JTIxIBU0bQxtW5hId6jgGJrYPDgEQ6EwFPSYTjUEjmYmXJiB0x7kPGItH5FekuZrv3UsLAJK4gBU/wcxiBcNA==","signatures":[{"sig":"MEYCIQCAZoCoHjjVafsIKRpPLiuYBi3Us6WJtGqQhykuiN8gGgIhAL8MvK3V8TeORHkNSs7GuIdqbpuFNu9qe5U1vCoqkYVT","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@hanoak%2funsplash-mcp-server@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":201285},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"4d5a853020e15630615210a1ef417c2f482d53b8","scripts":{"dev":"tsup --watch","lint":"eslint .","test":"vitest run","build":"tsup","check":"npm run typecheck && npm run lint && npm run format:check && npm run test","start":"node dist/index.js","format":"prettier --write .","prepare":"husky","release":"changeset publish","lint:fix":"eslint . --fix","changeset":"changeset","typecheck":"tsc --noEmit","audit:prod":"npm audit --omit=dev --audit-level=high","test:watch":"vitest","format:check":"prettier --check .","check:package":"npm run build && publint && attw --pack . --profile esm-only","license:check":"license-checker-rseidelsohn --production --onlyAllow \"MIT;ISC;BSD-2-Clause;BSD-3-Clause;Apache-2.0;0BSD;CC0-1.0;Unlicense;BlueOak-1.0.0;Python-2.0\"","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"hanoak","email":"hanoak4online@gmail.com"},"overrides":{"@modelcontextprotocol/sdk":{"@hono/node-server":"^2.0.5"}},"repository":{"url":"git+https://github.com/hanoak/unsplash-mcp-server.git","type":"git"},"_npmVersion":"10.8.2","description":"Production-ready Model Context Protocol (MCP) server for the Unsplash API — search photos, fetch details, and stay compliant with Unsplash attribution & download-tracking guidelines. Unofficial; not affiliated with or endorsed by Unsplash.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","@modelcontextprotocol/sdk":"^1.29.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","husky":"^9.1.7","eslint":"^10.7.0","vitest":"^4.1.10","globals":"^17.7.0","publint":"^0.3.22","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^20.19.43","lint-staged":"^16.4.0","@changesets/cli":"^2.31.1","@commitlint/cli":"^21.2.1","typescript-eslint":"^8.65.0","@vitest/coverage-v8":"^4.1.10","@arethetypeswrong/cli":"^0.18.5","eslint-config-prettier":"^10.1.8","license-checker-rseidelsohn":"^4.4.2","@commitlint/config-conventional":"^21.2.0"},"_npmOperationalInternal":{"tmp":"tmp/unsplash-mcp-server_1.0.0_1784976882422_0.8188745353617937","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@hanoak/unsplash-mcp-server","version":"1.0.1","keywords":["mcp","modelcontextprotocol","model-context-protocol","mcp-server","unsplash","unsplash-api","images","photos","stock-photos","claude","ai","llm"],"author":{"name":"Hanoak S"},"license":"MIT","_id":"@hanoak/unsplash-mcp-server@1.0.1","maintainers":[{"name":"hanoak","email":"hanoak4online@gmail.com"}],"homepage":"https://github.com/hanoak/unsplash-mcp-server#readme","bugs":{"url":"https://github.com/hanoak/unsplash-mcp-server/issues"},"bin":{"unsplash-mcp-server":"dist/index.js"},"dist":{"shasum":"05a17ff5164a8000c23d060b997f7161f8776f7c","tarball":"https://registry.npmjs.org/@hanoak/unsplash-mcp-server/-/unsplash-mcp-server-1.0.1.tgz","fileCount":6,"integrity":"sha512-2ESpEDBxynuLlAuGxP0KzP+462YG4Fyz3PYlUK1L7uFwj+O/M9cp6Gv2Mfshh4sqHJEnu3aQfaznYSdqsp7kHQ==","signatures":[{"sig":"MEYCIQDhps/0duNugyY1uVsaGvtprbTOnccKhqr+pCMYZoEHDAIhAL30igdN3rEcdGLy+0wVPTLrh7J+kzzaoPknEGpszoIl","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@hanoak%2funsplash-mcp-server@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":201338},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"31a4478b85b2fb44659ebc6739ea26d42d536723","mcpName":"io.github.hanoak/unsplash-mcp-server","scripts":{"dev":"tsup --watch","lint":"eslint .","test":"vitest run","build":"tsup","check":"npm run typecheck && npm run lint && npm run format:check && npm run test","start":"node dist/index.js","format":"prettier --write .","prepare":"husky","release":"changeset publish","lint:fix":"eslint . --fix","changeset":"changeset","typecheck":"tsc --noEmit","audit:prod":"npm audit --omit=dev --audit-level=high","test:watch":"vitest","format:check":"prettier --check .","check:package":"npm run build && publint && attw --pack . --profile esm-only","license:check":"license-checker-rseidelsohn --production --onlyAllow \"MIT;ISC;BSD-2-Clause;BSD-3-Clause;Apache-2.0;0BSD;CC0-1.0;Unlicense;BlueOak-1.0.0;Python-2.0\"","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"hanoak","email":"hanoak4online@gmail.com"},"overrides":{"@modelcontextprotocol/sdk":{"@hono/node-server":"^2.0.5"}},"repository":{"url":"git+https://github.com/hanoak/unsplash-mcp-server.git","type":"git"},"_npmVersion":"10.8.2","description":"Production-ready Model Context Protocol (MCP) server for the Unsplash API — search photos, fetch details, and stay compliant with Unsplash attribution & download-tracking guidelines. Unofficial; not affiliated with or endorsed by Unsplash.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","@modelcontextprotocol/sdk":"^1.29.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","husky":"^9.1.7","eslint":"^10.7.0","vitest":"^4.1.10","globals":"^17.7.0","publint":"^0.3.22","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^20.19.43","lint-staged":"^16.4.0","@changesets/cli":"^2.31.1","@commitlint/cli":"^21.2.1","typescript-eslint":"^8.65.0","@vitest/coverage-v8":"^4.1.10","@arethetypeswrong/cli":"^0.18.5","eslint-config-prettier":"^10.1.8","license-checker-rseidelsohn":"^4.4.2","@commitlint/config-conventional":"^21.2.0"},"_npmOperationalInternal":{"tmp":"tmp/unsplash-mcp-server_1.0.1_1784994172637_0.013808155279225076","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@hanoak/unsplash-mcp-server","version":"1.1.0","keywords":["mcp","modelcontextprotocol","model-context-protocol","mcp-server","unsplash","unsplash-api","images","photos","stock-photos","claude","ai","llm"],"author":{"name":"Hanoak S"},"license":"MIT","_id":"@hanoak/unsplash-mcp-server@1.1.0","maintainers":[{"name":"hanoak","email":"hanoak4online@gmail.com"}],"homepage":"https://github.com/hanoak/unsplash-mcp-server#readme","bugs":{"url":"https://github.com/hanoak/unsplash-mcp-server/issues"},"bin":{"unsplash-mcp-server":"dist/index.js"},"dist":{"shasum":"4bf304612e0afddb908a7d8203047d1f3c775ebc","tarball":"https://registry.npmjs.org/@hanoak/unsplash-mcp-server/-/unsplash-mcp-server-1.1.0.tgz","fileCount":6,"integrity":"sha512-8aokbc7Q2pt5/N2eaaLEPZaVdGrCC0X2s2Qvq155Si/YohDrQ1SgtZkDkLLxPQu+jHmtIRW63QyhZIUNwUIdMg==","signatures":[{"sig":"MEUCIQC2K1iuN0vph86cOu3pDYemqGAq1Fc2RFyAzT7q6u1BfgIgWSYXaZm3+nb0NKfDTvSX3k4Mu/zFzuFA4hbjT5DlmCk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@hanoak%2funsplash-mcp-server@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":280319},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"ad8de0802782439b4374d1cbd4e8bb6c5769c6be","mcpName":"io.github.hanoak/unsplash-mcp-server","scripts":{"dev":"tsup --watch","lint":"eslint .","test":"vitest run","build":"tsup","check":"npm run typecheck && npm run lint && npm run format:check && npm run test","start":"node dist/index.js","format":"prettier --write .","prepare":"husky","release":"changeset publish","lint:fix":"eslint . --fix","changeset":"changeset","typecheck":"tsc --noEmit","audit:prod":"npm audit --omit=dev --audit-level=high","test:watch":"vitest","format:check":"prettier --check .","check:package":"npm run build && publint && attw --pack . --profile esm-only","license:check":"license-checker-rseidelsohn --production --onlyAllow \"MIT;ISC;BSD-2-Clause;BSD-3-Clause;Apache-2.0;0BSD;CC0-1.0;Unlicense;BlueOak-1.0.0;Python-2.0\"","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"hanoak","email":"hanoak4online@gmail.com"},"overrides":{"hono":"^4.13.1","fast-uri":"^3.1.5","ip-address":"^10.4.0","@modelcontextprotocol/sdk":{"@hono/node-server":"^2.0.5"}},"repository":{"url":"git+https://github.com/hanoak/unsplash-mcp-server.git","type":"git"},"_npmVersion":"10.8.2","description":"Production-ready Model Context Protocol (MCP) server for the Unsplash API — search photos, fetch details, and stay compliant with Unsplash attribution & download-tracking guidelines. Unofficial; not affiliated with or endorsed by Unsplash.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","@modelcontextprotocol/sdk":"^1.29.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","husky":"^9.1.7","eslint":"^10.7.0","vitest":"^4.1.10","globals":"^17.7.0","publint":"^0.3.22","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^20.19.43","lint-staged":"^16.4.0","@changesets/cli":"^2.31.1","@commitlint/cli":"^21.2.1","typescript-eslint":"^8.65.0","@vitest/coverage-v8":"^4.1.10","@arethetypeswrong/cli":"^0.18.5","eslint-config-prettier":"^10.1.8","license-checker-rseidelsohn":"^4.4.2","@commitlint/config-conventional":"^21.2.0"},"_npmOperationalInternal":{"tmp":"tmp/unsplash-mcp-server_1.1.0_1786180903444_0.5161420373601489","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@hanoak/unsplash-mcp-server","version":"1.2.0","keywords":["mcp","modelcontextprotocol","model-context-protocol","mcp-server","unsplash","unsplash-api","images","photos","stock-photos","claude","ai","llm"],"author":{"name":"Hanoak S"},"license":"MIT","_id":"@hanoak/unsplash-mcp-server@1.2.0","maintainers":[{"name":"hanoak","email":"hanoak4online@gmail.com"}],"homepage":"https://github.com/hanoak/unsplash-mcp-server#readme","bugs":{"url":"https://github.com/hanoak/unsplash-mcp-server/issues"},"bin":{"unsplash-mcp-server":"dist/index.js"},"dist":{"shasum":"5dd84026768267802647736bb9a696f4a38363c0","tarball":"https://registry.npmjs.org/@hanoak/unsplash-mcp-server/-/unsplash-mcp-server-1.2.0.tgz","fileCount":6,"integrity":"sha512-r2KDdDtvgOxUHumg6Q+YfeBdCeKONKQIRh+9YWzna4ncSxT/jgMXnNBYKW8U8YDTXpDJCcAKZz9MojoT5SKnig==","signatures":[{"sig":"MEUCIDL4aPwoezGtV6Eps66AwAm5jKgA94ybl8MOt1bY6IeIAiEA4luXTKUt1d9P3EomPZfLLkoSpC9cGilmGlauHHXyqPs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@hanoak%2funsplash-mcp-server@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":314264},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"c696d500f6950b5c13b833ba08bdf1579f522a4d","mcpName":"io.github.hanoak/unsplash-mcp-server","scripts":{"dev":"tsup --watch","lint":"eslint .","test":"vitest run","build":"tsup","check":"npm run typecheck && npm run lint && npm run format:check && npm run test","start":"node dist/index.js","format":"prettier --write .","prepare":"husky","release":"changeset publish","lint:fix":"eslint . --fix","changeset":"changeset","typecheck":"tsc --noEmit","audit:prod":"npm audit --omit=dev --audit-level=high","test:watch":"vitest","format:check":"prettier --check .","check:package":"npm run build && publint && attw --pack . --profile esm-only","license:check":"license-checker-rseidelsohn --production --onlyAllow \"MIT;ISC;BSD-2-Clause;BSD-3-Clause;Apache-2.0;0BSD;CC0-1.0;Unlicense;BlueOak-1.0.0;Python-2.0\"","test:coverage":"vitest run --coverage","prepublishOnly":"npm run build"},"_npmUser":{"name":"hanoak","email":"hanoak4online@gmail.com"},"overrides":{"hono":"^4.13.1","fast-uri":"^3.1.5","ip-address":"^10.4.0","@modelcontextprotocol/sdk":{"@hono/node-server":"^2.0.5"}},"repository":{"url":"git+https://github.com/hanoak/unsplash-mcp-server.git","type":"git"},"_npmVersion":"10.8.2","description":"Production-ready Model Context Protocol (MCP) server for the Unsplash API — search photos, fetch details, and stay compliant with Unsplash attribution & download-tracking guidelines. Unofficial; not affiliated with or endorsed by Unsplash.","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","dependencies":{"zod":"^4.4.3","@modelcontextprotocol/sdk":"^1.29.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.1","husky":"^9.1.7","eslint":"^10.7.0","vitest":"^4.1.10","globals":"^17.7.0","publint":"^0.3.22","prettier":"^3.9.6","@eslint/js":"^10.0.1","typescript":"^6.0.3","@types/node":"^20.19.43","lint-staged":"^16.4.0","@changesets/cli":"^2.31.1","@commitlint/cli":"^21.2.1","typescript-eslint":"^8.65.0","@vitest/coverage-v8":"^4.1.10","@arethetypeswrong/cli":"^0.18.5","eslint-config-prettier":"^10.1.8","license-checker-rseidelsohn":"^4.4.2","@commitlint/config-conventional":"^21.2.0"},"_npmOperationalInternal":{"tmp":"tmp/unsplash-mcp-server_1.2.0_1786187295582_0.7818910937538766","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@hanoak/unsplash-mcp-server","version":"1.2.1","mcpName":"io.github.hanoak/unsplash-mcp-server","description":"Production-ready Model Context Protocol (MCP) server for the Unsplash API — search photos, fetch details, and stay compliant with Unsplash attribution & download-tracking guidelines. Unofficial; not affiliated with or endorsed by Unsplash.","keywords":["mcp","modelcontextprotocol","model-context-protocol","mcp-server","unsplash","unsplash-api","images","photos","stock-photos","claude","ai","llm"],"license":"MIT","author":{"name":"Hanoak S"},"type":"module","engines":{"node":">=20"},"bin":{"unsplash-mcp-server":"dist/index.js"},"main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"sideEffects":false,"repository":{"type":"git","url":"git+https://github.com/hanoak/unsplash-mcp-server.git"},"homepage":"https://github.com/hanoak/unsplash-mcp-server#readme","bugs":{"url":"https://github.com/hanoak/unsplash-mcp-server/issues"},"publishConfig":{"access":"public"},"overrides":{"@modelcontextprotocol/sdk":{"@hono/node-server":"^2.0.5"},"hono":"^4.13.1","fast-uri":"^3.1.5","ip-address":"^10.4.0"},"scripts":{"build":"tsup","dev":"tsup --watch","start":"node dist/index.js","typecheck":"tsc --noEmit","lint":"eslint .","lint:fix":"eslint . --fix","format":"prettier --write .","format:check":"prettier --check .","test":"vitest run","test:watch":"vitest","test:coverage":"vitest run --coverage","check":"npm run typecheck && npm run lint && npm run format:check && npm run test","check:package":"npm run build && publint && attw --pack . --profile esm-only","audit:prod":"npm audit --omit=dev --audit-level=high","license:check":"license-checker-rseidelsohn --production --onlyAllow \"MIT;ISC;BSD-2-Clause;BSD-3-Clause;Apache-2.0;0BSD;CC0-1.0;Unlicense;BlueOak-1.0.0;Python-2.0\"","changeset":"changeset","release":"changeset publish","prepublishOnly":"npm run build","prepare":"husky"},"dependencies":{"@modelcontextprotocol/sdk":"^1.29.0","zod":"^4.4.3"},"devDependencies":{"@arethetypeswrong/cli":"^0.18.5","@changesets/cli":"^2.31.1","@commitlint/cli":"^21.2.1","@commitlint/config-conventional":"^21.2.0","@eslint/js":"^10.0.1","@types/node":"^20.19.43","@vitest/coverage-v8":"^4.1.10","eslint":"^10.7.0","eslint-config-prettier":"^10.1.8","globals":"^17.7.0","husky":"^9.1.7","license-checker-rseidelsohn":"^4.4.2","lint-staged":"^16.4.0","prettier":"^3.9.6","publint":"^0.3.22","tsup":"^8.5.1","typescript":"^6.0.3","typescript-eslint":"^8.65.0","vitest":"^4.1.10"},"_id":"@hanoak/unsplash-mcp-server@1.2.1","gitHead":"de8c3e3d351a3b2127a6c32ab00b5557589a180a","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-+Sa4VakdScm+/ItpjP0o7C/rsJaHE6JiKwpo81hDsV4unhJ2GW6r9F1KRBjKIHfc6/Gp37hiDiN3fdd0ezw6yQ==","shasum":"908ddd4a34d3b7ca79441fb166b3c6f1b3b58094","tarball":"https://registry.npmjs.org/@hanoak/unsplash-mcp-server/-/unsplash-mcp-server-1.2.1.tgz","fileCount":6,"unpackedSize":314514,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@hanoak%2funsplash-mcp-server@1.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDIils1s3YmskaVRf515yYBVzsoyncT9eq2R9K6+Owv6AiEA7O4rMbV6MsclPuNYtAbfbCYmZngj96uGxTGG2zLEwxg="}]},"_npmUser":{"name":"hanoak","email":"hanoak4online@gmail.com"},"directories":{},"maintainers":[{"name":"hanoak","email":"hanoak4online@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/unsplash-mcp-server_1.2.1_1787152332711_0.01600118913759263"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-25T10:54:42.303Z","modified":"2026-08-19T15:12:13.280Z","1.0.0":"2026-07-25T10:54:42.562Z","1.0.1":"2026-07-25T15:42:52.780Z","1.1.0":"2026-08-08T09:21:43.615Z","1.2.0":"2026-08-08T11:08:15.738Z","1.2.1":"2026-08-19T15:12:12.858Z"},"bugs":{"url":"https://github.com/hanoak/unsplash-mcp-server/issues"},"author":{"name":"Hanoak S"},"license":"MIT","homepage":"https://github.com/hanoak/unsplash-mcp-server#readme","keywords":["mcp","modelcontextprotocol","model-context-protocol","mcp-server","unsplash","unsplash-api","images","photos","stock-photos","claude","ai","llm"],"repository":{"type":"git","url":"git+https://github.com/hanoak/unsplash-mcp-server.git"},"description":"Production-ready Model Context Protocol (MCP) server for the Unsplash API — search photos, fetch details, and stay compliant with Unsplash attribution & download-tracking guidelines. Unofficial; not affiliated with or endorsed by Unsplash.","maintainers":[{"name":"hanoak","email":"hanoak4online@gmail.com"}],"readme":"# unsplash-mcp-server\n\n[![npm version](https://img.shields.io/npm/v/@hanoak/unsplash-mcp-server.svg)](https://www.npmjs.com/package/@hanoak/unsplash-mcp-server)\n[![npm downloads](https://img.shields.io/npm/dm/@hanoak/unsplash-mcp-server.svg)](https://www.npmjs.com/package/@hanoak/unsplash-mcp-server)\n[![CI](https://github.com/hanoak/unsplash-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/hanoak/unsplash-mcp-server/actions/workflows/ci.yml)\n[![license: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)\n[![node: >=20](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](#requirements)\n[![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](./CONTRIBUTING.md)\n\nA production-ready [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for the [Unsplash API](https://unsplash.com/developers). It gives AI assistants — Claude Desktop, Claude Code, Cursor, VS Code, Windsurf, and any MCP client — tools to search and fetch Unsplash photos, collections, topics, users, and stats, with **Unsplash-guideline compliance built in** (ready-to-use attribution and download tracking). Sign in once via OAuth to also manage your own profile, collections, and photo metadata.\n\n> [!IMPORTANT]\n> **Unofficial project.** This is not affiliated with, endorsed by, or sponsored by Unsplash. \"Unsplash\" is a trademark of its respective owner. You use it under your own Unsplash API account and are responsible for complying with the [Unsplash API Terms & Guidelines](https://help.unsplash.com/en/articles/2511245-unsplash-api-guidelines).\n\n## Table of contents\n\n- [Features](#features)\n- [Quick start](#quick-start)\n- [Example interaction](#example-interaction)\n- [Configuration](#configuration)\n- [OAuth sign-in (optional)](#oauth-sign-in-optional)\n- [Tools](#tools)\n  - [Tool reference](#tool-reference)\n  - [Output shape](#output-shape)\n  - [Resources & prompts](#resources--prompts)\n- [Example prompts](#example-prompts)\n- [Attribution & compliance](#attribution--compliance)\n- [Rate limits](#rate-limits)\n- [Handling of Unsplash text](#handling-of-unsplash-text)\n- [Privacy & security](#privacy--security)\n- [Troubleshooting](#troubleshooting)\n- [FAQ](#faq)\n- [Requirements](#requirements)\n- [Compatibility](#compatibility)\n- [Roadmap](#roadmap)\n- [Contributing](#contributing)\n- [Contact & community](#contact--community)\n- [License](#license)\n\n## Features\n\n- **29 tools** across photos, search, users, collections, topics, stats, and your own profile — 21 read-only out of the box, plus 8 write/`me` tools once you [sign in](#oauth-sign-in-optional).\n- **Compliance built in** — every photo comes with ready-to-use attribution (plain text + UTM-tagged HTML), and a dedicated `unsplash_track_download` tool for the download-tracking guideline.\n- **Content safety** — `content_filter=high` by default on search and random photos.\n- **Flexible image URLs** — each photo returns `raw`/`full`/`regular`/`small`/`thumb` sizes, plus a `raw` imgix base for custom sizes (`?w=&h=&q=&fm=&fit=`).\n- **Token-efficient output** — full Unsplash responses are trimmed to a compact shape (URLs + metadata as text, never base64 image blobs) to keep model context small.\n- **Robust** — typed failures returned as MCP `isError` results the model can recover from, plus retries/backoff, timeouts, `403` hourly-limit handling, and rate-limit surfacing.\n- **Safe** — access-key redaction in all error output, an SSRF guard on download URLs, and untrusted-text handling guidance for indirect prompt-injection defence.\n- **Lean & modern** — ESM, Node 20+, zero-install via `npx`, no telemetry.\n\n## Quick start\n\n### 1. Get an Unsplash access key\n\nRegister an application at **[unsplash.com/developers](https://unsplash.com/developers)** → **New Application** → accept the API terms → copy its **Access Key** (not the Secret Key). New apps start on the **Demo** tier (50 requests/hour); the **Production** tier (5,000/hour) requires Unsplash's review from your app dashboard. See [Rate limits](#rate-limits).\n\n### 2. Add the server to your MCP client\n\n**Claude Desktop** — edit `claude_desktop_config.json`:\n\n- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`\n- Windows: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"unsplash\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@hanoak/unsplash-mcp-server\"],\n      \"env\": {\n        \"UNSPLASH_ACCESS_KEY\": \"your_access_key\",\n        \"UNSPLASH_APP_NAME\": \"your_registered_app_name\"\n      }\n    }\n  }\n}\n```\n\nRestart the client. See [Configuration](#configuration) for every supported variable.\n\n<details>\n<summary><b>Other clients (Claude Code, Cursor, VS Code, Windsurf, generic stdio)</b></summary>\n\n**Claude Code** (CLI):\n\n```bash\nclaude mcp add unsplash \\\n  --env UNSPLASH_ACCESS_KEY=your_access_key \\\n  --env UNSPLASH_APP_NAME=your_registered_app_name \\\n  -- npx -y @hanoak/unsplash-mcp-server\n```\n\n**Cursor** — `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per-project): use the exact same `mcpServers` block as Claude Desktop above.\n\n**Windsurf** — `~/.codeium/windsurf/mcp_config.json`: same `mcpServers` block as Claude Desktop above.\n\n**VS Code** — `.vscode/mcp.json` (note the top-level key is `servers`, not `mcpServers`):\n\n```json\n{\n  \"servers\": {\n    \"unsplash\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@hanoak/unsplash-mcp-server\"],\n      \"env\": {\n        \"UNSPLASH_ACCESS_KEY\": \"your_access_key\",\n        \"UNSPLASH_APP_NAME\": \"your_registered_app_name\"\n      }\n    }\n  }\n}\n```\n\n**Any other MCP client** — run the server over **stdio** with:\n\n```bash\nUNSPLASH_ACCESS_KEY=your_access_key npx -y @hanoak/unsplash-mcp-server\n```\n\nPoint your client's stdio transport at `command: npx`, `args: [\"-y\", \"@hanoak/unsplash-mcp-server\"]`, and pass the key via `env`.\n\n</details>\n\n### 3. Try it\n\nRestart your client and ask:\n\n> _\"Find me a photo of mountains on Unsplash and show the attribution.\"_\n\n## Example interaction\n\nA typical flow: the model calls `unsplash_search_photos`, picks a result, presents the image with its attribution, and calls `unsplash_track_download` when it actually uses the photo.\n\n> **You:** Find a landscape photo of a foggy pine forest and credit the photographer.\n>\n> **Assistant:** _(calls `unsplash_search_photos` with `query: \"foggy pine forest\"`, `orientation: \"landscape\"`, picks the best result, then calls `unsplash_track_download` with its `download_location`)_\n> Here's a great match — _Photo by Jane Doe on Unsplash_ — along with a ready-to-embed credit line and the image URL.\n\nEach tool returns a compact JSON payload. Here's the shape of a single photo result (illustrative values):\n\n<details>\n<summary><b>Example tool output</b></summary>\n\n```json\n{\n  \"photo\": {\n    \"id\": \"Dwu85P9SOIk\",\n    \"description\": \"brown rocky mountain under blue sky during daytime\",\n    \"width\": 6000,\n    \"height\": 4000,\n    \"color\": \"#734940\",\n    \"blur_hash\": \"L6Pj0^i_.AyE_3t7t7R**0o#DgR4\",\n    \"urls\": {\n      \"raw\": \"https://images.unsplash.com/photo-1465…?ixid=…\",\n      \"full\": \"https://images.unsplash.com/photo-1465…?ixid=…&q=85\",\n      \"regular\": \"https://images.unsplash.com/photo-1465…?ixid=…&w=1080\",\n      \"small\": \"https://images.unsplash.com/photo-1465…?ixid=…&w=400\",\n      \"thumb\": \"https://images.unsplash.com/photo-1465…?ixid=…&w=200\"\n    },\n    \"photo_page\": \"https://unsplash.com/photos/Dwu85P9SOIk\",\n    \"download_location\": \"https://api.unsplash.com/photos/Dwu85P9SOIk/download?ixid=…\",\n    \"photographer\": {\n      \"name\": \"Jane Doe\",\n      \"username\": \"janedoe\",\n      \"profile\": \"https://unsplash.com/@janedoe\"\n    },\n    \"attribution\": {\n      \"text\": \"Photo by Jane Doe on Unsplash\",\n      \"html\": \"Photo by <a href=\\\"https://unsplash.com/@janedoe?utm_source=your_app&utm_medium=referral\\\">Jane Doe</a> on <a href=\\\"https://unsplash.com/?utm_source=your_app&utm_medium=referral\\\">Unsplash</a>\",\n      \"photographerName\": \"Jane Doe\",\n      \"photographerUrl\": \"https://unsplash.com/@janedoe?utm_source=your_app&utm_medium=referral\",\n      \"unsplashUrl\": \"https://unsplash.com/?utm_source=your_app&utm_medium=referral\"\n    }\n  },\n  \"rate_limit\": { \"limit\": 50, \"remaining\": 49 }\n}\n```\n\nEvery tool result includes a `rate_limit` object (`limit`, `remaining`) read from the Unsplash response headers. List/search tools wrap results in `photos`/`collections`/`users`/`topics` arrays with pagination fields (`total`, `total_pages`, `count`, `page`, `per_page`).\n\n</details>\n\n## Configuration\n\nConfiguration is entirely via environment variables — no config files, no flags for secrets.\n\n| Environment variable          | Required         | Description                                                                                                                             |\n| ----------------------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------- |\n| `UNSPLASH_ACCESS_KEY`         | **yes**          | Your Unsplash API access key. The server exits at startup with a clear message if it is missing or blank.                               |\n| `UNSPLASH_APP_NAME`           | **recommended**  | Your registered Unsplash app name, used as the attribution `utm_source`. Defaults to a generic value (with a startup warning) if unset. |\n| `UNSPLASH_SECRET_KEY`         | only for `login` | Your Unsplash app's secret key. Only needed to run `login` — see [OAuth sign-in](#oauth-sign-in-optional).                              |\n| `UNSPLASH_OAUTH_REDIRECT_URI` | only for `login` | Override the default `http://localhost:8734/callback` used by `login`. Must match the redirect URI registered on your Unsplash app.     |\n| `LOG_LEVEL`                   | no               | `debug` \\| `info` \\| `warn` \\| `error` (default `info`). All logs go to **stderr**; stdout carries only the MCP protocol.               |\n\nCLI flags: `--version` and `--help` are supported (e.g. `npx @hanoak/unsplash-mcp-server --version`). `login`/`logout` are subcommands, not flags — see below.\n\n## OAuth sign-in (optional)\n\nThe 21 core tools work out of the box with just `UNSPLASH_ACCESS_KEY`. To also use the **8 write/`me` tools** (update your profile, manage collections, edit photo metadata), sign in once via OAuth:\n\n1. On your app's page at [unsplash.com/oauth/applications](https://unsplash.com/oauth/applications), add `http://localhost:8734/callback` as a redirect URI, and copy the **Secret key**.\n2. Set both `UNSPLASH_ACCESS_KEY` and `UNSPLASH_SECRET_KEY` in your shell (not just the MCP client config — `login` runs from your terminal).\n3. Run:\n\n   ```bash\n   npx @hanoak/unsplash-mcp-server login\n   ```\n\n   This opens your browser to Unsplash's consent screen, captures the redirect on a short-lived local server, exchanges the code for a user access token, and saves it to `~/.config/unsplash-mcp-server/credentials.json` (owner-only file permissions). Unsplash user access tokens **don't expire**, so this is a one-time step — no periodic re-auth.\n\n4. Restart your MCP client. The 8 write/`me` tools are now available; the 21 read-only tools are unaffected either way.\n\nRun `npx @hanoak/unsplash-mcp-server logout` at any time to remove the stored token. To revoke it server-side, regenerate your app's secret key from the Unsplash dashboard.\n\n## Tools\n\nAll tools are namespaced `unsplash_*`. Most are **read-only** (annotated `readOnlyHint: true`); the exceptions are `unsplash_track_download` (registers a download event) and the 8 write/`me` tools below, all marked non-read-only and gated behind [OAuth sign-in](#oauth-sign-in-optional). Parameters map to the Unsplash API; `per_page` and stats `quantity` are clamped to a max of **30**, and `page` is 1-based.\n\n| Domain          | Tools                                                                                                                                                                                                                     |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Photos**      | `random_photo`, `list_photos`, `get_photo`, `photo_statistics`, `track_download`, `update_photo` 🔒                                                                                                                       |\n| **Search**      | `search_photos`, `search_collections`, `search_users`                                                                                                                                                                     |\n| **Users**       | `get_user`, `user_photos`, `user_collections`, `user_statistics`                                                                                                                                                          |\n| **Collections** | `list_collections`, `get_collection`, `collection_photos`, `related_collections`, `create_collection` 🔒, `update_collection` 🔒, `delete_collection` 🔒, `add_photo_to_collection` 🔒, `remove_photo_from_collection` 🔒 |\n| **Topics**      | `list_topics`, `get_topic`, `topic_photos`                                                                                                                                                                                |\n| **Stats**       | `total_stats`, `month_stats`                                                                                                                                                                                              |\n| **Me**          | `get_my_profile` 🔒, `update_my_profile` 🔒                                                                                                                                                                               |\n\n🔒 = requires [OAuth sign-in](#oauth-sign-in-optional) (`login`) first.\n\n### Tool reference\n\n<details>\n<summary><b>Photos</b></summary>\n\n| Tool                        | Parameters                                                                                                                                                                                                                                     | Description                                                               |\n| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |\n| `unsplash_random_photo`     | `query?`, `orientation?` (`landscape`\\|`portrait`\\|`squarish`), `content_filter?` (`low`\\|`high`, default `high`), `collections?`, `topics?`, `username?`                                                                                      | A single random photo, optionally filtered.                               |\n| `unsplash_list_photos`      | `page?` (default 1), `per_page?` (default 10, max 30)                                                                                                                                                                                          | The latest featured photos, paginated.                                    |\n| `unsplash_get_photo`        | `id` **(required)**                                                                                                                                                                                                                            | A single photo by ID or slug, full detail.                                |\n| `unsplash_photo_statistics` | `id` **(required)**, `quantity?` (days, default 30, max 30)                                                                                                                                                                                    | Download/view totals for a photo over N days.                             |\n| `unsplash_track_download`   | `download_location` **(required)** — the `download_location` URL from a prior photo result (must be an `https://api.unsplash.com` URL)                                                                                                         | Registers a download on real use; returns a fresh, usable download URL.   |\n| `unsplash_update_photo` 🔒  | `id` **(required)**, `show_on_profile?`, `description?`, `tags?` (comma-separated), `location?` (`city`/`country`/`name`/`latitude`/`longitude`), `exif?` (`make`/`model`/`exposure_time`/`aperture_value`/`focal_length`/`iso_speed_ratings`) | Update metadata on a photo you own. Only the fields you pass are changed. |\n\n</details>\n\n<details>\n<summary><b>Search</b></summary>\n\n| Tool                          | Parameters                                                                                                                                                                                                          | Description                             |\n| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- |\n| `unsplash_search_photos`      | `query` **(required)**, `page?`, `per_page?`, `order_by?` (`latest`\\|`editorial`\\|`relevant`), `orientation?`, `color?` (11 named colors, e.g. `blue`), `content_filter?` (default `high`), `collections?`, `lang?` | Keyword photo search with rich filters. |\n| `unsplash_search_collections` | `query` **(required)**, `page?`, `per_page?`                                                                                                                                                                        | Keyword collection search.              |\n| `unsplash_search_users`       | `query` **(required)**, `page?`, `per_page?`                                                                                                                                                                        | Keyword user search.                    |\n\n</details>\n\n<details>\n<summary><b>Users</b></summary>\n\n| Tool                        | Parameters                                                                                                                         | Description                                |\n| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |\n| `unsplash_get_user`         | `username` **(required)**                                                                                                          | A user's public profile.                   |\n| `unsplash_user_photos`      | `username` **(required)**, `page?`, `per_page?`, `order_by?` (`latest`\\|`oldest`\\|`popular`\\|`views`\\|`downloads`), `orientation?` | A user's photos, paginated.                |\n| `unsplash_user_collections` | `username` **(required)**, `page?`, `per_page?`                                                                                    | A user's collections, paginated.           |\n| `unsplash_user_statistics`  | `username` **(required)**, `quantity?` (days, default 30, max 30)                                                                  | A user's download/view totals over N days. |\n\n</details>\n\n<details>\n<summary><b>Collections</b></summary>\n\n| Tool                                       | Parameters                                                | Description                                                   |\n| ------------------------------------------ | --------------------------------------------------------- | ------------------------------------------------------------- |\n| `unsplash_list_collections`                | `page?`, `per_page?`                                      | The latest featured collections.                              |\n| `unsplash_get_collection`                  | `id` **(required)**                                       | A single collection by ID.                                    |\n| `unsplash_collection_photos`               | `id` **(required)**, `page?`, `per_page?`, `orientation?` | Photos within a collection, paginated.                        |\n| `unsplash_related_collections`             | `id` **(required)**                                       | Collections related to a given one.                           |\n| `unsplash_create_collection` 🔒            | `title` **(required)**, `description?`, `private?`        | Create a new collection you own.                              |\n| `unsplash_update_collection` 🔒            | `id` **(required)**, `title?`, `description?`, `private?` | Update a collection you own. Only the fields you pass change. |\n| `unsplash_delete_collection` 🔒            | `id` **(required)**                                       | Permanently delete a collection you own. Cannot be undone.    |\n| `unsplash_add_photo_to_collection` 🔒      | `id` **(required)**, `photo_id` **(required)**            | Add a photo to a collection you own.                          |\n| `unsplash_remove_photo_from_collection` 🔒 | `id` **(required)**, `photo_id` **(required)**            | Remove a photo from a collection you own.                     |\n\n</details>\n\n<details>\n<summary><b>Me (requires OAuth sign-in)</b></summary>\n\n| Tool                            | Parameters                                                                                             | Description                                                            |\n| ------------------------------- | ------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- |\n| `unsplash_get_my_profile` 🔒    | _(none)_                                                                                               | Your own profile, including private fields (email, uploads remaining). |\n| `unsplash_update_my_profile` 🔒 | `username?`, `first_name?`, `last_name?`, `email?`, `url?`, `location?`, `bio?`, `instagram_username?` | Update your own profile. Only the fields you pass are changed.         |\n\n</details>\n\n<details>\n<summary><b>Topics & stats</b></summary>\n\n| Tool                    | Parameters                                                                                               | Description                                  |\n| ----------------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------- |\n| `unsplash_list_topics`  | `page?`, `per_page?`, `order_by?` (`featured`\\|`latest`\\|`oldest`\\|`position`), `ids?` (comma-separated) | Curated topics, paginated.                   |\n| `unsplash_get_topic`    | `id` **(required)** — ID or slug (e.g. `nature`, `wallpapers`)                                           | A single topic.                              |\n| `unsplash_topic_photos` | `id` **(required)**, `page?`, `per_page?`, `orientation?`, `order_by?` (`latest`\\|`oldest`\\|`popular`)   | Photos within a topic, paginated.            |\n| `unsplash_total_stats`  | _(none)_                                                                                                 | Unsplash-wide totals (photos, downloads, …). |\n| `unsplash_month_stats`  | _(none)_                                                                                                 | Unsplash-wide totals for the past 30 days.   |\n\n</details>\n\n### Output shape\n\nTools return trimmed, token-efficient JSON rather than raw Unsplash responses:\n\n- **Photos** → `id`, `description`, `width`/`height`, `color`, `blur_hash`, `urls` (`raw`/`full`/`regular`/`small`/`thumb`), `photo_page`, `download_location`, `photographer`, and a ready-to-use `attribution` object. See [Example interaction](#example-interaction).\n- **Users** → `id`, `username`, `name`, `bio`, `location`, `profile_url`, `profile_image`, `total_photos`, `total_collections`.\n- **Collections / Topics** → title, description, counts, page link, curator/owners, and a compact `cover_photo`.\n- Every result carries a `rate_limit` (`limit`, `remaining`); lists/searches add pagination fields.\n\n### Resources & prompts\n\nBeyond tools, the server also exposes:\n\n- **Resources** — compact guides your client can pull in as context:\n  - `unsplash://guides/attribution` — attribution, download tracking, hotlinking, content safety.\n  - `unsplash://guides/oauth-setup` — how to sign in for the 8 write/`me` tools.\n  - `unsplash://guides/prompts` — which of the prompts below to use for a given task.\n- **Prompts** — ready-made tasks your client can surface directly; each expands into a guided, multi-step tool-calling task:\n\n  | Prompt                   | Arguments                                              | What it does                                                       |\n  | ------------------------ | ------------------------------------------------------ | ------------------------------------------------------------------ |\n  | `find_photo`             | `subject` (required), `orientation?`                   | Search for one photo and present it with attribution.              |\n  | `photo_gallery`          | `theme` (required), `count?`, `orientation?`, `color?` | Build a themed set of photos (up to 10), each with attribution.    |\n  | `topic_spotlight`        | `topic` (required), `count?`                           | Showcase a curated topic's best photos.                            |\n  | `photographer_spotlight` | `username` (required), `count?`                        | A photographer's profile + their most popular work.                |\n  | `platform_pulse`         | _(none)_                                               | A quick Unsplash-wide stats briefing.                              |\n  | `curate_collection` 🔒   | `theme` (required), `count?`, `collection_id?`         | Search, then build (or extend) a real collection from the matches. |\n  | `describe_photo` 🔒      | `id` (required), `description?`, `tags?`               | Add a description/tags to a photo you own.                         |\n  | `refresh_profile` 🔒     | `bio?`, `location?`, `url?`                            | Update your own bio, location, or portfolio URL.                   |\n\n  🔒 = requires [OAuth sign-in](#oauth-sign-in-optional) first.\n\n## Example prompts\n\nNatural-language asks that map cleanly onto the tools:\n\n- _\"Find a photo of a foggy forest at sunrise and give me the HTML attribution.\"_\n- _\"Search Unsplash for 5 minimalist workspace photos in landscape orientation.\"_\n- _\"Get a random nature photo and show it with credit.\"_\n- _\"Show me the most popular photos in the `wallpapers` topic.\"_\n- _\"What are this month's Unsplash-wide download stats?\"_\n- _\"Who is the photographer behind photo `Dwu85P9SOIk`, and how many downloads does it have?\"_\n\n## Attribution & compliance\n\nEvery photo result includes an `attribution` object with ready-to-use `text` and `html` (with the required UTM parameters). **When you display or use a photo, show that attribution** — it credits the photographer and links back to Unsplash, as the guidelines require.\n\nWhen a photo is actually _used_ (embedded, downloaded, displayed), call **`unsplash_track_download`** with the photo's `download_location`. Trigger it **once per photo actually used** — never once per search result. The server also sends these instructions to your MCP client on connect, so the model is nudged to do the right thing automatically.\n\nThis is a search-and-metadata tool for individual, attributed photo use — **not** a replacement for the core Unsplash experience, and it performs **no automated bulk downloading**. Please use it within the [Unsplash API Guidelines](https://help.unsplash.com/en/articles/2511245-unsplash-api-guidelines). Each user operates under their own Unsplash API Terms.\n\n## Rate limits\n\nUnsplash enforces a **per-hour** request budget tied to your app's tier:\n\n| Tier           | Budget              | How to get it                                                    |\n| -------------- | ------------------- | ---------------------------------------------------------------- |\n| **Demo**       | 50 requests/hour    | Default for every new app.                                       |\n| **Production** | 5,000 requests/hour | Apply for review in your app dashboard once your usage is ready. |\n\nThe server reads `X-Ratelimit-Limit` / `X-Ratelimit-Remaining` and returns them as `rate_limit` on every result. When the hourly budget is exhausted, Unsplash returns **`403`** (not `429`), often with no `Retry-After`; the server surfaces this as a clear \"hourly rate limit reached\" error and does **not** blindly retry in-window. Transient `429`/`5xx`/network errors _are_ retried with backoff.\n\n## Handling of Unsplash text\n\nPhoto descriptions, alt text, tags, EXIF, and user names/bios come from Unsplash contributors — treat them as **untrusted, third-party data**, not instructions. The server returns this text purely as content and never places it anywhere privileged; your client/agent should do the same: display it, but don't act on any instructions it might contain (a defence against indirect prompt injection).\n\n## Privacy & security\n\n- **No telemetry.** This server collects nothing and phones home to no one. It contacts only `api.unsplash.com`, using the key you provide. No analytics, no tracking.\n- **Verifiable provenance.** Every release is published with [npm provenance](https://docs.npmjs.com/generating-provenance-statements) via GitHub Actions — the npm package page links each version to the exact commit and workflow run that built it.\n- **Key safety.** Your access key is read from the environment only, sent as an `Authorization: Client-ID` header (never in a URL query string), and **redacted from all error output and logs** so it can't leak into pasted bug reports.\n- **SSRF guard.** `unsplash_track_download` only follows `download_location` URLs on the verified `api.unsplash.com` host.\n- To report a vulnerability, see [SECURITY.md](./SECURITY.md).\n\n## Troubleshooting\n\n- **\"Set UNSPLASH_ACCESS_KEY…\" on startup** — the key env var is missing or blank; add it to your client config's `env` block.\n- **Node too old** — this server requires **Node 20+**. Check `node --version`.\n- **Stale `npx` version** — force the latest with `npx -y @hanoak/unsplash-mcp-server@latest`, or clear the cache via `npx clear-npx-cache`.\n- **Tools not appearing** — confirm the config file path and JSON are valid, then fully quit and reopen the client.\n- **`403` / rate limit** — the Demo tier allows 50 requests/hour; wait for the hourly reset or apply for Production access. See [Rate limits](#rate-limits).\n- **`401 Unauthorized`** — the access key is wrong or from the wrong app; copy the **Access Key** (not the Secret Key) from your app dashboard.\n\n## FAQ\n\n**Do I need a paid Unsplash account?**\nNo. The Unsplash API is free; you just register an app to get an access key. Higher throughput (Production tier) is a free review, not a paid plan.\n\n**Access Key vs Secret Key — which one?**\nFor the 21 read-only tools, just the **Access Key**. The Secret Key is only needed for `login` (the OAuth flow behind the 8 write/`me` tools) — see [OAuth sign-in](#oauth-sign-in-optional).\n\n**Does it download or rehost images?**\nNo. It returns Unsplash-hosted image URLs (hotlink them directly) and never rehosts or returns base64 blobs. `unsplash_track_download` only registers a download event and returns a fresh URL.\n\n**Can it create collections, like photos, or edit my profile?**\nYes, once you [sign in](#oauth-sign-in-optional) — `unsplash_create_collection` and friends, and `unsplash_update_photo`/`unsplash_update_my_profile`. (Liking photos is not currently exposed as a tool.)\n\n**Does it work outside Claude?**\nYes — it's a standard stdio MCP server. See [the client setup section](#2-add-the-server-to-your-mcp-client) for Claude Code, Cursor, VS Code, Windsurf, and generic stdio.\n\n## Requirements\n\n- **Node.js >= 20** (Node 18 is end-of-life).\n- An Unsplash API access key.\n\n## Compatibility\n\n| Component | Supported                                                                                            |\n| --------- | ---------------------------------------------------------------------------------------------------- |\n| Node.js   | **20** and **22**, tested in CI; `>=20` required (enforced by `engines` and a runtime guard).        |\n| OS        | Linux, macOS, and Windows (all tested in CI).                                                        |\n| MCP SDK   | `@modelcontextprotocol/sdk` `^1.29`; the protocol version is negotiated with your client on connect. |\n| Transport | stdio (HTTP/SSE may be added in a future release).                                                   |\n\n## Roadmap\n\nFull detail lives in [docs/ROADMAP.md](./docs/ROADMAP.md). In short:\n\n- **v1** _(shipped)_ — the 21 read-only tools, attribution + download-tracking compliance, the attribution resource, and the `find_photo` prompt.\n- **v2** _(shipped)_ — the 8 OAuth write / `me` endpoints (profile, collections, photo metadata) via a `login`/`logout` CLI and the Unsplash authorization-code flow.\n- **v3** _(current)_ — 7 more MCP prompts covering every tool domain (see [Resources & prompts](#resources--prompts)). A `.mcpb` Desktop Extension was considered for this phase but dropped to unscheduled future scope — `npx` already works across every supported client.\n\nChanges are tracked in [CHANGELOG.md](./CHANGELOG.md); the project follows [Semantic Versioning](https://semver.org).\n\n## Contributing\n\nContributions are welcome — see [CONTRIBUTING.md](./CONTRIBUTING.md) and our [Code of Conduct](./CODE_OF_CONDUCT.md). It covers local setup, the test suite, testing tools by hand with the [MCP Inspector](https://github.com/modelcontextprotocol/inspector), and the versioning/deprecation policy. To report a vulnerability, see [SECURITY.md](./SECURITY.md).\n\n## Contact & community\n\nMaintained by **Hanoak S**. The fastest way to get help or propose a feature is to [open an issue](https://github.com/hanoak/unsplash-mcp-server/issues) — it's public, searchable, and helps the whole community. For anything else, reach out:\n\n[![LinkedIn](https://img.shields.io/badge/LinkedIn-hanoak-0A66C2?logo=linkedin&logoColor=white)](https://linkedin.com/in/hanoak)\n[![X](https://img.shields.io/badge/X-%40__hanoak-000000?logo=x&logoColor=white)](https://x.com/_hanoak)\n\nIf this project helps you, a ⭐ on [GitHub](https://github.com/hanoak/unsplash-mcp-server) is appreciated — it aids discoverability for others looking for an Unsplash MCP server.\n\n## License\n\n[MIT](./LICENSE) © Hanoak S. Not affiliated with Unsplash.\n","readmeFilename":"README.md"}