copyseeker-mcp-server 1.0.3 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 CopySeeker
3
+ Copyright (c) 2025 Copyseeker
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,159 +1,77 @@
1
1
  # Copyseeker MCP Server
2
2
 
3
- A Model Context Protocol (MCP) server that integrates Copyseeker's powerful reverse image search API with Claude and other MCP-compatible AI assistants.
3
+ Give Claude, Cursor and other [MCP](https://modelcontextprotocol.io) clients three image tools from [Copyseeker](https://copyseeker.net):
4
4
 
5
- ## Features
5
+ | Tool | What it does | Cost |
6
+ |---|---|---|
7
+ | `reverse_image_search` | Finds the web pages that show an image, ranked by prominence, with the copies each page uses | 1 search |
8
+ | `detect_ai_image` | Tells whether an image is AI-generated, with a confidence score | 0.01 searches |
9
+ | `detect_nsfw` | Tells whether an image contains nudity or sexual content, with a confidence score | 0.01 searches |
6
10
 
7
- - 🔍 **Reverse Image Search**: Find similar images and their sources across the web
8
- - 🖼️ **Multiple Input Methods**: Search by URL or upload images directly
9
- - 📊 **Detailed Results**: Get comprehensive metadata about found images
10
- - ⚡ **Fast & Reliable**: Powered by Copyseeker's robust API infrastructure
11
- - 🔒 **Secure**: Your API key stays local, never shared
11
+ Each tool takes a direct image URL or the path to a local image file (up to 20 MB). Calls draw from the same search balance as the website, Monitor and the [Copyseeker API](https://copyseeker.net/apis).
12
12
 
13
- ## Quick Start
13
+ ## Requirements
14
14
 
15
- ### 1. Install the MCP Server
15
+ - Node.js 20 or newer
16
+ - A paid Copyseeker plan and an API key: create one under **Account → Developers** at [copyseeker.net/account](https://copyseeker.net/account#api)
16
17
 
17
- ```bash
18
- npm install -g copyseeker-mcp-server
19
- ```
20
-
21
- ### 2. Get Your API Key
18
+ ## Setup
22
19
 
23
- 1. Visit [RapidAPI Copyseeker](https://rapidapi.com/copyseeker1-copyseeker-default/api/reverse-image-search-by-copyseeker/)
24
- 2. Subscribe to a plan (free tier available)
25
- 3. Copy your RapidAPI key
20
+ ### Claude Code
26
21
 
27
- ### 3. Configure Claude Desktop
22
+ ```bash
23
+ claude mcp add copyseeker -e COPYSEEKER_API_KEY=your_api_key -- npx -y copyseeker-mcp-server
24
+ ```
28
25
 
29
- Add this to your Claude Desktop configuration file:
26
+ ### Claude Desktop
30
27
 
31
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
32
- **Windows**: `%APPDATA%/Claude/claude_desktop_config.json`
28
+ Add this to `claude_desktop_config.json` (macOS: `~/Library/Application Support/Claude/`, Windows: `%APPDATA%\Claude\`), then restart Claude Desktop:
33
29
 
34
30
  ```json
35
31
  {
36
32
  "mcpServers": {
37
33
  "copyseeker": {
38
- "command": "copyseeker-mcp",
34
+ "command": "npx",
35
+ "args": ["-y", "copyseeker-mcp-server"],
39
36
  "env": {
40
- "COPYSEEKER_RAPIDAPI_KEY": "your_rapidapi_key_here"
37
+ "COPYSEEKER_API_KEY": "your_api_key"
41
38
  }
42
39
  }
43
40
  }
44
41
  }
45
42
  ```
46
43
 
47
- ### 4. Restart Claude Desktop
48
-
49
- The Copyseeker tools will now be available in Claude!
50
-
51
- ## Usage Examples
52
-
53
- ### Complete Reverse Image Search
54
- ```
55
- Can you do a complete reverse search on: https://i.pcmag.com/imagery/reviews/04R1s9xuQfmVH4MHFeuaghc-10..v1570064456.jpg
56
- ```
57
-
58
- ### Copyright & Source Verification
59
- ```
60
- I need to check if I can legally use this image. Please analyze: [image URL]
61
- ```
62
-
63
- ### Find Exact Matches
64
- ```
65
- Where exactly does this image appear online? [image URL]
66
- ```
67
-
68
- ### Find Design Inspiration
69
- ```
70
- Show me images that look similar to this design for inspiration: [image URL]
71
- ```
72
-
73
- ### Page Authority Assessment
74
- ```
75
- Which website is the most credible source for this image? [image URL]
76
- ```
77
-
78
- ## Available Tools
79
-
80
- ### `reverse_image_search`
81
- Complete reverse image search with all results formatted clearly.
82
-
83
- **Parameters:**
84
- - `image_url` (required): Direct URL to the image
85
-
86
- **Returns:**
87
- - AI analysis of what the image represents
88
- - Exact matches (websites containing the same image)
89
- - Visually similar images (different images that look alike)
90
- - Page authority scores for credibility assessment
91
- - AI-detected categories with confidence scores
92
-
93
- ### `analyze_image_copyright`
94
- Specialized copyright and usage rights analysis.
95
-
96
- **Parameters:**
97
- - `image_url` (required): URL of the image to analyze
98
-
99
- **Returns:**
100
- - Copyright risk assessment based on where image appears
101
- - Source credibility ranking by page authority
102
- - Usage recommendations and next steps
103
- - Likely original source identification
44
+ ### Cursor and other clients
104
45
 
105
- ### `find_exact_matches`
106
- Find websites containing the exact same image.
46
+ Use the same `command`, `args` and `env` as above in the client's MCP settings (Cursor: `~/.cursor/mcp.json`).
107
47
 
108
- **Parameters:**
109
- - `image_url` (required): URL of the image to find matches for
48
+ ## Examples
110
49
 
111
- **Returns:**
112
- - List of websites with the exact same image
113
- - Page authority scores (higher = more credible source)
114
- - Direct URLs to image files on each site
115
- - Summary of distribution patterns
50
+ - "Where else on the web does https://example.com/photo.jpg appear? Who published it first?"
51
+ - "Is ~/Downloads/portrait.png AI-generated?"
52
+ - "Check these five product images for NSFW content before I upload them."
116
53
 
117
- ### `find_similar_images`
118
- Discover visually similar images for inspiration and alternatives.
54
+ ## Errors
119
55
 
120
- **Parameters:**
121
- - `image_url` (required): URL of the image to find similarities for
56
+ Failures come back to the assistant as plain explanations it can act on: an invalid key, a missing plan, an empty balance (with the top-up link), the rate limit of 60 calls per minute (with how long to wait), or a URL that points to a web page instead of an image. A search that fails on Copyseeker's side is refunded.
122
57
 
123
- **Returns:**
124
- - URLs to different images that look visually similar
125
- - Common visual elements and themes
126
- - Use cases for similar images
127
- - Style and category analysis
58
+ ## Upgrading from 1.x
128
59
 
129
- ## Pricing
60
+ Version 2 calls the Copyseeker API directly instead of RapidAPI:
130
61
 
131
- [View all pricing plans →](https://rapidapi.com/copyseeker1-copyseeker-default/api/reverse-image-search-by-copyseeker/pricing)
62
+ - Replace `COPYSEEKER_RAPIDAPI_KEY` with `COPYSEEKER_API_KEY`, a key from your Copyseeker account.
63
+ - The tools are now `reverse_image_search`, `detect_ai_image` and `detect_nsfw`. `analyze_image_copyright`, `find_exact_matches` and `find_similar_images` are gone: `reverse_image_search` covers them.
64
+ - Node.js 20 or newer is required.
132
65
 
133
- ## Troubleshooting
66
+ ## Development
134
67
 
135
- ### "API key required" error
136
- Make sure you've set the `COPYSEEKER_RAPIDAPI_KEY` environment variable in your Claude configuration.
137
-
138
- ### "Rate limit exceeded"
139
- Check your usage on the [RapidAPI dashboard](https://rapidapi.com/developer/dashboard) and consider upgrading your plan.
140
-
141
- ### "Image not found" error
142
- Ensure the image URL is directly accessible and points to a valid image file (not a webpage containing an image).
143
-
144
- ## Support
68
+ ```bash
69
+ npm install
70
+ npm test # builds, then runs the server against a fake Copyseeker API
71
+ ```
145
72
 
146
- - 🌐 Website: [copyseeker.net](https://copyseeker.net)
147
- - 📚 API Documentation: [RapidAPI Docs](https://rapidapi.com/copyseeker1-copyseeker-default/api/reverse-image-search-by-copyseeker/)
73
+ `COPYSEEKER_API_URL` points the server at another API base URL (default `https://api.copyseeker.net`).
148
74
 
149
75
  ## License
150
76
 
151
- MIT License - see LICENSE file for details.
152
-
153
- ## Contributing
154
-
155
- We welcome contributions! Please see our contributing guidelines and submit pull requests to our GitHub repository.
156
-
157
- ---
158
-
159
- **Made with ❤️ by the Copyseeker team**
77
+ MIT
@@ -0,0 +1,121 @@
1
+ import { readFile, stat } from "node:fs/promises";
2
+ import { basename, extname } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ export const DEFAULT_API_URL = "https://api.copyseeker.net";
5
+ export const MAX_FILE_BYTES = 20 * 1024 * 1024;
6
+ // Reverse image search can take tens of seconds on images found on many pages.
7
+ const REQUEST_TIMEOUT_MS = 120_000;
8
+ const MIME_TYPES = {
9
+ ".jpg": "image/jpeg",
10
+ ".jpeg": "image/jpeg",
11
+ ".png": "image/png",
12
+ ".gif": "image/gif",
13
+ ".webp": "image/webp",
14
+ ".bmp": "image/bmp",
15
+ ".tif": "image/tiff",
16
+ ".tiff": "image/tiff",
17
+ ".heic": "image/heic",
18
+ ".heif": "image/heif",
19
+ ".avif": "image/avif",
20
+ };
21
+ // A failure the assistant can explain to the user and often fix (new key, top-up, other image).
22
+ export class CopyseekerError extends Error {
23
+ code;
24
+ constructor(message, code) {
25
+ super(message);
26
+ this.code = code;
27
+ this.name = "CopyseekerError";
28
+ }
29
+ }
30
+ export class CopyseekerClient {
31
+ apiKey;
32
+ apiUrl;
33
+ fetchImpl;
34
+ constructor(apiKey, apiUrl = DEFAULT_API_URL, fetchImpl = fetch) {
35
+ this.apiKey = apiKey;
36
+ this.apiUrl = apiUrl;
37
+ this.fetchImpl = fetchImpl;
38
+ }
39
+ async call(endpoint, image) {
40
+ const source = image.trim();
41
+ const headers = { "X-API-Key": this.apiKey, Accept: "application/json" };
42
+ let response;
43
+ try {
44
+ if (isHttpUrl(source)) {
45
+ const url = `${this.apiUrl}/${endpoint}?imageUrl=${encodeURIComponent(source)}`;
46
+ response = await this.fetchImpl(url, { headers, signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS) });
47
+ }
48
+ else {
49
+ const body = new FormData();
50
+ const file = await readImageFile(source);
51
+ body.append("file", new Blob([file.bytes], { type: file.mimeType }), file.name);
52
+ response = await this.fetchImpl(`${this.apiUrl}/${endpoint}`, { method: "POST", headers, body, signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS) });
53
+ }
54
+ }
55
+ catch (error) {
56
+ if (error instanceof CopyseekerError) {
57
+ throw error;
58
+ }
59
+ if (error instanceof Error && (error.name === "TimeoutError" || error.name === "AbortError")) {
60
+ throw new CopyseekerError(`Copyseeker did not answer within ${REQUEST_TIMEOUT_MS / 1000} seconds. Try again in a moment.`, "TIMEOUT");
61
+ }
62
+ throw new CopyseekerError(`Could not reach Copyseeker (${error instanceof Error ? error.message : String(error)}). Check the internet connection.`, "NETWORK_ERROR");
63
+ }
64
+ if (response.ok) {
65
+ return (await response.json());
66
+ }
67
+ throw await toError(response);
68
+ }
69
+ }
70
+ export function isHttpUrl(value) {
71
+ return /^https?:\/\//i.test(value);
72
+ }
73
+ async function readImageFile(source) {
74
+ const path = source.toLowerCase().startsWith("file://") ? fileURLToPath(source) : source;
75
+ let size;
76
+ try {
77
+ const info = await stat(path);
78
+ if (!info.isFile()) {
79
+ throw new CopyseekerError(`"${source}" is not a file. Pass a direct image URL (http/https) or the path to a local image file.`, "INVALID_IMAGE");
80
+ }
81
+ size = info.size;
82
+ }
83
+ catch (error) {
84
+ if (error instanceof CopyseekerError) {
85
+ throw error;
86
+ }
87
+ throw new CopyseekerError(`"${source}" is neither an http(s) image URL nor a readable local file.`, "INVALID_IMAGE");
88
+ }
89
+ if (size === 0 || size > MAX_FILE_BYTES) {
90
+ throw new CopyseekerError(`"${source}" is ${size === 0 ? "empty" : "larger than 20 MB"}. Copyseeker accepts images up to 20 MB.`, "INVALID_IMAGE");
91
+ }
92
+ const name = basename(path);
93
+ return { bytes: new Uint8Array(await readFile(path)), name, mimeType: MIME_TYPES[extname(name).toLowerCase()] ?? "application/octet-stream" };
94
+ }
95
+ async function toError(response) {
96
+ let code = "";
97
+ try {
98
+ code = (await response.json())?.error ?? "";
99
+ }
100
+ catch {
101
+ // Not JSON (a gateway error page); the status code still tells what happened.
102
+ }
103
+ switch (code) {
104
+ case "INVALID_API_KEY":
105
+ return new CopyseekerError("The Copyseeker API key is missing or invalid. Create one at https://copyseeker.net/account#api and set it as COPYSEEKER_API_KEY in the MCP server config.", code);
106
+ case "PLAN_REQUIRED":
107
+ return new CopyseekerError("API access needs a paid Copyseeker plan. See https://copyseeker.net/pricing.", code);
108
+ case "QUOTA_EXHAUSTED":
109
+ return new CopyseekerError("The Copyseeker account has no searches left for this call. Top up at https://copyseeker.net/account#searches or wait for the monthly reset.", code);
110
+ case "RATE_LIMITED": {
111
+ const retryAfter = response.headers.get("Retry-After");
112
+ return new CopyseekerError(`Copyseeker's rate limit (60 calls per minute) was hit. Retry after ${retryAfter ?? "a few"} seconds.`, code);
113
+ }
114
+ case "INVALID_IMAGE":
115
+ return new CopyseekerError("Copyseeker could not read an image there. Use a direct link to the image file itself (not a web page that shows it), or a local file path. Nothing was charged.", code);
116
+ case "SEARCH_FAILED":
117
+ return new CopyseekerError("The search failed on Copyseeker's side and its searches were refunded. Try again.", code);
118
+ default:
119
+ return new CopyseekerError(`Copyseeker answered HTTP ${response.status}${code ? ` (${code})` : ""}.`, code || `HTTP_${response.status}`);
120
+ }
121
+ }
package/build/index.js ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ import { serveStdio } from "@modelcontextprotocol/server/stdio";
3
+ import { CopyseekerClient, DEFAULT_API_URL } from "./client.js";
4
+ import { createServer } from "./server.js";
5
+ const apiKey = process.env.COPYSEEKER_API_KEY?.trim();
6
+ if (!apiKey) {
7
+ // stdout carries the protocol, so everything for people goes to stderr.
8
+ console.error("COPYSEEKER_API_KEY is not set. Create an API key at https://copyseeker.net/account#api and add it to this server's env in your MCP client config.");
9
+ process.exit(1);
10
+ }
11
+ const client = new CopyseekerClient(apiKey, process.env.COPYSEEKER_API_URL?.trim() || DEFAULT_API_URL);
12
+ // One factory serves both clients that open with the 2025 initialize handshake and stateless 2026-07-28 clients.
13
+ serveStdio(() => createServer(client), {
14
+ onerror: (error) => {
15
+ console.error(`[copyseeker-mcp] ${error.message}`);
16
+ },
17
+ });
@@ -0,0 +1,84 @@
1
+ import { McpServer } from "@modelcontextprotocol/server";
2
+ import { z } from "zod";
3
+ import { CopyseekerError, } from "./client.js";
4
+ export const SERVER_NAME = "copyseeker";
5
+ export const SERVER_VERSION = "2.0.0";
6
+ const DEFAULT_MAX_RESULTS = 25;
7
+ const INSTRUCTIONS = `Copyseeker tools work on one image each, given as a direct image URL (http/https) or the path to a local image file.
8
+ Each call is charged to the user's Copyseeker searches: reverse_image_search 1, detect_ai_image 0.01, detect_nsfw 0.01.
9
+ Call a tool once per image and question; do not repeat a call that already succeeded.`;
10
+ const imageInput = z
11
+ .string()
12
+ .min(1)
13
+ .describe("Direct URL of the image file (http or https, not the web page showing it), or the absolute path to a local image file up to 20 MB.");
14
+ const SEARCH_ANNOTATIONS = { readOnlyHint: true, destructiveHint: false, idempotentHint: false, openWorldHint: true };
15
+ export function createServer(client) {
16
+ const server = new McpServer({ name: SERVER_NAME, version: SERVER_VERSION }, { instructions: INSTRUCTIONS });
17
+ server.registerTool("reverse_image_search", {
18
+ title: "Reverse image search",
19
+ description: "Find the web pages that show this image, with the copies of it each page uses, ranked by how prominent the page is. " +
20
+ "Use it to find where an image came from, who published it first, or where it is reused without permission. Costs 1 search.",
21
+ inputSchema: z.object({
22
+ image: imageInput,
23
+ max_results: z.number().int().min(1).max(100).default(DEFAULT_MAX_RESULTS).describe("Most pages to return, best ranked first."),
24
+ }),
25
+ outputSchema: z.object({
26
+ totalPages: z.number().int().describe("Pages Copyseeker found, before max_results."),
27
+ pages: z.array(z.object({
28
+ url: z.string(),
29
+ title: z.string().nullable(),
30
+ rank: z.number().describe("Page prominence; lower is more prominent."),
31
+ matchingImages: z.array(z.string()).describe("URLs of the copies of the image on this page."),
32
+ })),
33
+ }),
34
+ annotations: { ...SEARCH_ANNOTATIONS, title: "Reverse image search" },
35
+ }, async ({ image, max_results }) => {
36
+ return run(async () => {
37
+ const result = await client.call("reverse-image-search", image);
38
+ const pages = result.pages ?? [];
39
+ return { totalPages: pages.length, pages: pages.slice(0, max_results) };
40
+ });
41
+ });
42
+ server.registerTool("detect_ai_image", {
43
+ title: "Detect AI-generated image",
44
+ description: "Tell whether an image was generated by AI (Midjourney, DALL-E, Stable Diffusion, Flux and similar) or is a real photo or artwork. Costs 0.01 searches.",
45
+ inputSchema: z.object({ image: imageInput }),
46
+ outputSchema: z.object({
47
+ isAiGenerated: z.boolean(),
48
+ confidence: z.number().min(0).max(1).describe("How sure the verdict is, from 0 to 1."),
49
+ }),
50
+ annotations: { ...SEARCH_ANNOTATIONS, title: "Detect AI-generated image" },
51
+ }, async ({ image }) => {
52
+ return run(async () => {
53
+ const result = await client.call("ai-detection", image);
54
+ return { isAiGenerated: result.isAiGenerated, confidence: result.confidence };
55
+ });
56
+ });
57
+ server.registerTool("detect_nsfw", {
58
+ title: "Detect NSFW image",
59
+ description: "Tell whether an image contains nudity or sexual content that is not safe for work. Costs 0.01 searches.",
60
+ inputSchema: z.object({ image: imageInput }),
61
+ outputSchema: z.object({
62
+ isNsfw: z.boolean(),
63
+ confidence: z.number().min(0).max(1).describe("How sure the verdict is, from 0 to 1."),
64
+ }),
65
+ annotations: { ...SEARCH_ANNOTATIONS, title: "Detect NSFW image" },
66
+ }, async ({ image }) => {
67
+ return run(async () => {
68
+ const result = await client.call("nsfw-detection", image);
69
+ return { isNsfw: result.isNsfw, confidence: result.confidence };
70
+ });
71
+ });
72
+ return server;
73
+ }
74
+ // Copyseeker failures go back to the model as tool errors it can read and act on, not as protocol errors.
75
+ async function run(call) {
76
+ try {
77
+ const output = await call();
78
+ return { content: [{ type: "text", text: JSON.stringify(output, null, 2) }], structuredContent: output };
79
+ }
80
+ catch (error) {
81
+ const message = error instanceof CopyseekerError ? error.message : `Unexpected error: ${error instanceof Error ? error.message : String(error)}`;
82
+ return { content: [{ type: "text", text: message }], isError: true };
83
+ }
84
+ }
package/package.json CHANGED
@@ -1,55 +1,54 @@
1
1
  {
2
- "name": "copyseeker-mcp-server",
3
- "version": "1.0.3",
4
- "description": "MCP server for CopySeeker reverse image search API - find similar images and sources",
5
- "main": "build/index.js",
6
- "bin": {
7
- "copyseeker-mcp": "build/index.js"
8
- },
9
- "type": "module",
10
- "scripts": {
11
- "build": "tsc",
12
- "start": "node build/index.js",
13
- "dev": "tsx src/index.ts",
14
- "prepublishOnly": "npm run build"
15
- },
16
- "dependencies": {
17
- "@modelcontextprotocol/sdk": "^0.4.0",
18
- "axios": "^1.6.0"
19
- },
20
- "devDependencies": {
21
- "@types/node": "^20.0.0",
22
- "typescript": "^5.0.0",
23
- "tsx": "^4.0.0"
24
- },
25
- "keywords": [
26
- "mcp",
27
- "model-context-protocol",
28
- "reverse-image-search",
29
- "copyseeker",
30
- "claude",
31
- "image-search",
32
- "similar-images",
33
- "reverse-search",
34
- "copyright-check",
35
- "image-analysis"
36
- ],
37
- "author": "CopySeeker <support@copyseeker.net>",
38
- "license": "MIT",
39
- "homepage": "https://copyseeker.net",
40
- "repository": {
41
- "type": "git",
42
- "url": "https://github.com/copyseeker/copyseeker-mcp-server.git"
43
- },
44
- "bugs": {
45
- "url": "https://github.com/copyseeker/copyseeker-mcp-server/issues"
46
- },
47
- "engines": {
48
- "node": ">=18.0.0"
49
- },
50
- "files": [
51
- "build/**/*",
52
- "README.md",
53
- "LICENSE"
54
- ]
2
+ "name": "copyseeker-mcp-server",
3
+ "version": "2.0.0",
4
+ "description": "MCP server for Copyseeker: reverse image search, AI image detection and NSFW detection for AI assistants",
5
+ "type": "module",
6
+ "bin": {
7
+ "copyseeker-mcp": "build/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc -p tsconfig.build.json",
11
+ "typecheck": "tsc --noEmit",
12
+ "test": "npm run build && node --test --import tsx \"test/**/*.test.ts\"",
13
+ "start": "node build/index.js",
14
+ "prepublishOnly": "npm test"
15
+ },
16
+ "dependencies": {
17
+ "@modelcontextprotocol/server": "^2.4.0",
18
+ "zod": "^4.2.0"
19
+ },
20
+ "devDependencies": {
21
+ "@modelcontextprotocol/client": "^2.4.0",
22
+ "@types/node": "^20.19.0",
23
+ "tsx": "^4.23.0",
24
+ "typescript": "^5.9.3"
25
+ },
26
+ "keywords": [
27
+ "mcp",
28
+ "model-context-protocol",
29
+ "copyseeker",
30
+ "reverse-image-search",
31
+ "ai-image-detection",
32
+ "nsfw-detection",
33
+ "image-search",
34
+ "copyright"
35
+ ],
36
+ "author": "Copyseeker <support@copyseeker.net>",
37
+ "license": "MIT",
38
+ "homepage": "https://copyseeker.net/apis",
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "https://github.com/copyseeker/copyseeker-mcp-server.git"
42
+ },
43
+ "bugs": {
44
+ "url": "https://github.com/copyseeker/copyseeker-mcp-server/issues"
45
+ },
46
+ "engines": {
47
+ "node": ">=20"
48
+ },
49
+ "files": [
50
+ "build/**/*",
51
+ "README.md",
52
+ "LICENSE"
53
+ ]
55
54
  }