@fonkychen/nature-vision-mcp 0.1.1
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/README.md +106 -0
- package/dist/index.js +112 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
\# Nature Vision MCP Server
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
An \*\*MCP (Model Context Protocol) server\*\* that identifies biological species from images using the \*\*Nature Vision API\*\*, returning Latin names with confidence scores.
|
|
6
|
+
|
|
7
|
+
This server enables LLMs (such as Claude) to recognize species and enrich responses with biological knowledge.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
\## Features
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
\- 🌿 Identify species from images (plants, animals, fungi, insects, etc.)
|
|
20
|
+
|
|
21
|
+
\- 🧬 Returns \*\*Latin scientific names\*\* with confidence scores
|
|
22
|
+
|
|
23
|
+
\- 🧠 Designed for \*\*LLM tool usage\*\* via Model Context Protocol (MCP)
|
|
24
|
+
|
|
25
|
+
\- 🔌 Simple stdio-based MCP server
|
|
26
|
+
|
|
27
|
+
\- 🚀 Easy to run with `npx`
|
|
28
|
+
|
|
29
|
+
\- 🔐 API key via environment variables
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
\## Supported Categories
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
\- `plant`
|
|
42
|
+
|
|
43
|
+
\- `bug`
|
|
44
|
+
|
|
45
|
+
\- `bird`
|
|
46
|
+
|
|
47
|
+
\- `mammal`
|
|
48
|
+
|
|
49
|
+
\- `reptile`
|
|
50
|
+
|
|
51
|
+
\- `amphibian`
|
|
52
|
+
|
|
53
|
+
\- `mollusc`
|
|
54
|
+
|
|
55
|
+
\- `fungi`
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
\## Installation
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
|
|
69
|
+
npm install
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
\*\*Configure in your MCP client:\*\*
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
|
|
79
|
+
{
|
|
80
|
+
"mcp.servers": {
|
|
81
|
+
"nature-vision": {
|
|
82
|
+
"command": "npx",
|
|
83
|
+
"args": ["-y", "nature-vision-mcp"],
|
|
84
|
+
"env": {
|
|
85
|
+
"NATURE_VISION_API_KEY": "app-xxx"
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
For now, you can use token: app-dummy-token-2026, this will allow you request once per minute.
|
|
95
|
+
```
|
|
96
|
+
"NATURE_VISION_API_KEY": "app-dummy-token-2026"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
|
|
103
|
+
npx nature-vision-mcp
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
import fetch from "node-fetch";
|
|
6
|
+
const API_ENDPOINT = "https://api.nature-vision.top/api/v1/mcp/vision";
|
|
7
|
+
const API_KEY = process.env.NATURE_VISION_API_KEY;
|
|
8
|
+
if (!API_KEY) {
|
|
9
|
+
console.error("NATURE_VISION_API_KEY environment variable is not set");
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
const server = new McpServer({
|
|
13
|
+
name: "nature-vision-mcp",
|
|
14
|
+
version: "0.1.0",
|
|
15
|
+
});
|
|
16
|
+
server.registerTool("identify_species", {
|
|
17
|
+
description: "Identify species from an image and return Latin names with confidence",
|
|
18
|
+
inputSchema: {
|
|
19
|
+
image_url: z
|
|
20
|
+
.string()
|
|
21
|
+
.min(10)
|
|
22
|
+
.optional()
|
|
23
|
+
.describe('image url to request'),
|
|
24
|
+
image_data: z
|
|
25
|
+
.string()
|
|
26
|
+
.min(100)
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('base64 image to request'),
|
|
29
|
+
category: z
|
|
30
|
+
.string()
|
|
31
|
+
.min(3)
|
|
32
|
+
.optional()
|
|
33
|
+
.describe("species category: plant|bug|bird|reptile|mollusc|mammal|fungi|amphibian"),
|
|
34
|
+
top_k: z
|
|
35
|
+
.number()
|
|
36
|
+
.min(1)
|
|
37
|
+
.optional()
|
|
38
|
+
.describe("top_k"),
|
|
39
|
+
},
|
|
40
|
+
}, async ({ image_url, image_data, category, top_k }) => {
|
|
41
|
+
try {
|
|
42
|
+
if (image_url && image_data) {
|
|
43
|
+
throw new Error("Either image_url or image_data is required");
|
|
44
|
+
}
|
|
45
|
+
const resp = await fetch(API_ENDPOINT, {
|
|
46
|
+
method: "POST",
|
|
47
|
+
headers: {
|
|
48
|
+
"Content-Type": "application/json",
|
|
49
|
+
Authorization: `Bearer ${API_KEY}`,
|
|
50
|
+
},
|
|
51
|
+
body: JSON.stringify({
|
|
52
|
+
image_url: image_url ?? null,
|
|
53
|
+
image_data: image_data ?? null,
|
|
54
|
+
category: category ?? null,
|
|
55
|
+
top_k: top_k ?? 5,
|
|
56
|
+
}),
|
|
57
|
+
});
|
|
58
|
+
if (!resp.ok) {
|
|
59
|
+
return {
|
|
60
|
+
content: [
|
|
61
|
+
{
|
|
62
|
+
type: "text",
|
|
63
|
+
text: ""
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
isError: true,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
const data = (await resp.json());
|
|
70
|
+
return {
|
|
71
|
+
content: [
|
|
72
|
+
{
|
|
73
|
+
type: "text",
|
|
74
|
+
text: JSON.stringify({
|
|
75
|
+
source: data.source,
|
|
76
|
+
results: data.results,
|
|
77
|
+
}, null, 2),
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
isError: false
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
const errorMessage = error instanceof Error ? error.message : 'unknown error';
|
|
85
|
+
console.error('request failed:', errorMessage);
|
|
86
|
+
return {
|
|
87
|
+
content: [
|
|
88
|
+
{
|
|
89
|
+
type: "text",
|
|
90
|
+
text: ""
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
isError: true,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
async function main() {
|
|
98
|
+
try {
|
|
99
|
+
const transport = new StdioServerTransport();
|
|
100
|
+
await server.connect(transport);
|
|
101
|
+
console.error('nature vision started');
|
|
102
|
+
console.error('waiting for client to request...');
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
console.error('nature vision failed:', error);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
main().catch((error) => {
|
|
110
|
+
console.error('server error:', error);
|
|
111
|
+
process.exit(1);
|
|
112
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fonkychen/nature-vision-mcp",
|
|
3
|
+
"mcpName": "io.github.fonkychen/nature-vision",
|
|
4
|
+
"version": "0.1.1",
|
|
5
|
+
"description": "An MCP (Model Context Protocol) server that identifies biological species from images, returning Latin names with confidence scores.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"bin": {
|
|
9
|
+
"nature-vision-mcp": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"prepare": "npm run build",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"mcp",
|
|
21
|
+
"model-context-protocol",
|
|
22
|
+
"nature-vision",
|
|
23
|
+
"ai-tools"
|
|
24
|
+
],
|
|
25
|
+
"author": "fonky.chen@gmail.com",
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/fonkychen/nature-vision-mcp.git"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@modelcontextprotocol/sdk": "^1.0.1",
|
|
32
|
+
"node-fetch": "^3.3.2"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/node": "^20.0.0",
|
|
36
|
+
"typescript": "^5.0.0"
|
|
37
|
+
}
|
|
38
|
+
}
|