tanxin-mcp 1.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/README.md +71 -0
- package/package.json +39 -0
- package/server.mjs +195 -0
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# tanxin-mcp
|
|
2
|
+
|
|
3
|
+
让 Claude Code / Claude Desktop 直接查询 **[探新 AI 产品库](https://www.tan-xin.com)** 的 MCP Server。
|
|
4
|
+
|
|
5
|
+
探新收录独立开发者和小团队正在做的 AI 工具、Agent 和自动化产品,所有接口完全公开,无需 API Key。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 接入方式
|
|
10
|
+
|
|
11
|
+
### Claude Code
|
|
12
|
+
|
|
13
|
+
在 `~/.claude.json` 中加入:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"mcpServers": {
|
|
18
|
+
"tanxin": {
|
|
19
|
+
"command": "npx",
|
|
20
|
+
"args": ["tanxin-mcp"]
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Claude Desktop
|
|
27
|
+
|
|
28
|
+
编辑 `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"mcpServers": {
|
|
33
|
+
"tanxin": {
|
|
34
|
+
"command": "npx",
|
|
35
|
+
"args": ["tanxin-mcp"]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
配置后重启 Claude,即可直接问:
|
|
42
|
+
|
|
43
|
+
> "帮我在探新上找找 AI 写作工具"
|
|
44
|
+
> "探新平台上有多少产品?"
|
|
45
|
+
> "有没有找运营合伙人的机会?"
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 工具列表
|
|
50
|
+
|
|
51
|
+
| 工具 | 说明 |
|
|
52
|
+
|------|------|
|
|
53
|
+
| `search_products` | 搜索 AI 产品,支持关键词、类型、阶段筛选 |
|
|
54
|
+
| `get_product` | 获取某个产品的完整详情 |
|
|
55
|
+
| `list_opportunities` | 查看合作机会(有技术找运营 / 有想法找开发) |
|
|
56
|
+
| `get_stats` | 平台概况:产品数、机会数、总点赞 |
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## 环境变量
|
|
61
|
+
|
|
62
|
+
| 变量 | 默认 | 说明 |
|
|
63
|
+
|------|------|------|
|
|
64
|
+
| `TANXIN_API_URL` | `https://www.tan-xin.com` | 自定义 API 地址(本地开发用) |
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## 关于探新
|
|
69
|
+
|
|
70
|
+
- 网址:https://www.tan-xin.com
|
|
71
|
+
- 联系:微信 guozhige2024
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tanxin-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP Server for 探新 AI 产品库 — 让 Claude Code 直接查询 AI 产品和合作机会",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"tanxin-mcp": "./server.mjs"
|
|
8
|
+
},
|
|
9
|
+
"main": "./server.mjs",
|
|
10
|
+
"files": [
|
|
11
|
+
"server.mjs",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"start": "node server.mjs"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"mcp",
|
|
19
|
+
"ai",
|
|
20
|
+
"tanxin",
|
|
21
|
+
"claude",
|
|
22
|
+
"model-context-protocol",
|
|
23
|
+
"探新"
|
|
24
|
+
],
|
|
25
|
+
"author": "guozhige2024",
|
|
26
|
+
"license": "MIT",
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@modelcontextprotocol/sdk": "^1.12.0",
|
|
29
|
+
"zod": "^3.23.8"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18"
|
|
33
|
+
},
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "https://github.com/juicebro/tanxin-mcp"
|
|
37
|
+
},
|
|
38
|
+
"homepage": "https://www.tan-xin.com"
|
|
39
|
+
}
|
package/server.mjs
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 探新 AI 产品库 — MCP Server
|
|
4
|
+
*
|
|
5
|
+
* 给 Claude Code / Claude Desktop 使用的 MCP 工具服务。
|
|
6
|
+
* 提供 4 个只读工具,不需要 API Key。
|
|
7
|
+
*
|
|
8
|
+
* 使用方式:见 README 或 /developers 页面
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
12
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
|
|
15
|
+
// 默认指向线上,也可通过环境变量覆盖(本地调试用)
|
|
16
|
+
const BASE_URL = process.env.TANXIN_API_URL ?? "https://www.tan-xin.com";
|
|
17
|
+
|
|
18
|
+
async function apiFetch(path) {
|
|
19
|
+
const res = await fetch(`${BASE_URL}${path}`);
|
|
20
|
+
if (!res.ok) throw new Error(`API error ${res.status}: ${path}`);
|
|
21
|
+
const json = await res.json();
|
|
22
|
+
if (!json.success) throw new Error(json.error ?? "Unknown error");
|
|
23
|
+
return json;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ── Server 初始化 ─────────────────────────────────────────────────────────────
|
|
27
|
+
|
|
28
|
+
const server = new McpServer({
|
|
29
|
+
name: "tanxin",
|
|
30
|
+
version: "1.0.0",
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// ── Tool 1: search_products ───────────────────────────────────────────────────
|
|
34
|
+
|
|
35
|
+
server.tool(
|
|
36
|
+
"search_products",
|
|
37
|
+
"搜索探新 AI 产品库中的产品。可以按关键词、产品类型、开发阶段筛选,支持分页。",
|
|
38
|
+
{
|
|
39
|
+
q: z.string().optional().describe("搜索关键词,匹配产品名称、介绍、适合人群"),
|
|
40
|
+
type: z.string().optional().describe("产品类型,例如:AI工具、AI Agent、自动化工作流、小程序、API服务、其他"),
|
|
41
|
+
stage: z.string().optional().describe("开发阶段,例如:内测中、公测中、已上线"),
|
|
42
|
+
page: z.number().int().min(1).optional().default(1).describe("页码,从 1 开始"),
|
|
43
|
+
pageSize: z.number().int().min(1).max(50).optional().default(10).describe("每页数量,最大 50"),
|
|
44
|
+
},
|
|
45
|
+
async ({ q, type, stage, page, pageSize }) => {
|
|
46
|
+
const params = new URLSearchParams();
|
|
47
|
+
if (q) params.set("q", q);
|
|
48
|
+
if (type) params.set("type", type);
|
|
49
|
+
if (stage) params.set("stage", stage);
|
|
50
|
+
if (page) params.set("page", String(page));
|
|
51
|
+
if (pageSize) params.set("pageSize", String(pageSize));
|
|
52
|
+
|
|
53
|
+
const qs = params.toString();
|
|
54
|
+
const json = await apiFetch(`/api/v1/products${qs ? `?${qs}` : ""}`);
|
|
55
|
+
|
|
56
|
+
const { data, meta } = json;
|
|
57
|
+
|
|
58
|
+
if (data.length === 0) {
|
|
59
|
+
return {
|
|
60
|
+
content: [{ type: "text", text: "没有找到符合条件的产品。" }],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const lines = [
|
|
65
|
+
`共找到 ${meta.total} 个产品,当前第 ${meta.page} 页(每页 ${meta.pageSize} 个):`,
|
|
66
|
+
"",
|
|
67
|
+
...data.map((p, i) => [
|
|
68
|
+
`${(meta.page - 1) * meta.pageSize + i + 1}. **${p.productName}**`,
|
|
69
|
+
` 介绍:${p.oneLineIntro}`,
|
|
70
|
+
` 类型:${p.productType} 阶段:${p.currentStage}`,
|
|
71
|
+
p.targetUsers ? ` 适合:${p.targetUsers}` : null,
|
|
72
|
+
p.memberBenefit ? ` 群友福利:${p.memberBenefit}` : null,
|
|
73
|
+
p.experienceLink ? ` 体验链接:${p.experienceLink}` : null,
|
|
74
|
+
` 👍 ${p.likeCount} | 详情 ID:${p.id}`,
|
|
75
|
+
].filter(Boolean).join("\n")),
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// ── Tool 2: get_product ───────────────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
server.tool(
|
|
87
|
+
"get_product",
|
|
88
|
+
"获取探新平台上某个产品的完整详情,包括详细介绍、功能描述、体验链接等。",
|
|
89
|
+
{
|
|
90
|
+
id: z.string().describe("产品 ID,可从 search_products 结果中获取"),
|
|
91
|
+
},
|
|
92
|
+
async ({ id }) => {
|
|
93
|
+
const json = await apiFetch(`/api/v1/products/${id}`);
|
|
94
|
+
const p = json.data;
|
|
95
|
+
|
|
96
|
+
const lines = [
|
|
97
|
+
`# ${p.productName}`,
|
|
98
|
+
"",
|
|
99
|
+
`**一句话介绍:** ${p.oneLineIntro}`,
|
|
100
|
+
p.description ? `\n**详细介绍:**\n${p.description}` : "",
|
|
101
|
+
"",
|
|
102
|
+
`- 类型:${p.productType}`,
|
|
103
|
+
`- 阶段:${p.currentStage}`,
|
|
104
|
+
p.targetUsers ? `- 适合人群:${p.targetUsers}` : "",
|
|
105
|
+
p.memberBenefit ? `- 群友专属福利:${p.memberBenefit}` : "",
|
|
106
|
+
p.experienceLink ? `- 体验链接:${p.experienceLink}` : "",
|
|
107
|
+
`- 点赞数:${p.likeCount}`,
|
|
108
|
+
`- 上架时间:${new Date(p.createdAt).toLocaleDateString("zh-CN")}`,
|
|
109
|
+
].filter(Boolean);
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// ── Tool 3: list_opportunities ────────────────────────────────────────────────
|
|
118
|
+
|
|
119
|
+
server.tool(
|
|
120
|
+
"list_opportunities",
|
|
121
|
+
"浏览探新平台上的合作机会。可以按关键词、拥有资源、需要资源筛选。例如找【有技术找运营】或【有想法找开发】的合作需求。",
|
|
122
|
+
{
|
|
123
|
+
q: z.string().optional().describe("关键词搜索,匹配标题、描述、发布者名称"),
|
|
124
|
+
has: z.string().optional().describe("发布者拥有的资源或能力,例如:技术、设计、运营、资金、流量"),
|
|
125
|
+
need: z.string().optional().describe("发布者需要的资源或能力,例如:技术、设计、运营、资金、流量"),
|
|
126
|
+
page: z.number().int().min(1).optional().default(1).describe("页码"),
|
|
127
|
+
pageSize: z.number().int().min(1).max(50).optional().default(10).describe("每页数量"),
|
|
128
|
+
},
|
|
129
|
+
async ({ q, has, need, page, pageSize }) => {
|
|
130
|
+
const params = new URLSearchParams();
|
|
131
|
+
if (q) params.set("q", q);
|
|
132
|
+
if (has) params.set("has", has);
|
|
133
|
+
if (need) params.set("need", need);
|
|
134
|
+
if (page) params.set("page", String(page));
|
|
135
|
+
if (pageSize) params.set("pageSize", String(pageSize));
|
|
136
|
+
|
|
137
|
+
const qs = params.toString();
|
|
138
|
+
const json = await apiFetch(`/api/v1/opportunities${qs ? `?${qs}` : ""}`);
|
|
139
|
+
|
|
140
|
+
const { data, meta } = json;
|
|
141
|
+
|
|
142
|
+
if (data.length === 0) {
|
|
143
|
+
return {
|
|
144
|
+
content: [{ type: "text", text: "没有找到符合条件的合作机会。" }],
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const lines = [
|
|
149
|
+
`共找到 ${meta.total} 个合作机会,当前第 ${meta.page} 页:`,
|
|
150
|
+
"",
|
|
151
|
+
...data.map((o, i) => [
|
|
152
|
+
`${(meta.page - 1) * meta.pageSize + i + 1}. **${o.title}**`,
|
|
153
|
+
` ${o.summary}`,
|
|
154
|
+
` 我有:${o.hasTags} | 我需要:${o.needTags}`,
|
|
155
|
+
` 发布者:${o.name} | 联系方式:${o.contact}`,
|
|
156
|
+
].join("\n")),
|
|
157
|
+
];
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
// ── Tool 4: get_stats ─────────────────────────────────────────────────────────
|
|
166
|
+
|
|
167
|
+
server.tool(
|
|
168
|
+
"get_stats",
|
|
169
|
+
"获取探新 AI 产品库的平台概况:已收录的产品数量、合作机会数量、总点赞数等统计数据。",
|
|
170
|
+
{},
|
|
171
|
+
async () => {
|
|
172
|
+
const json = await apiFetch("/api/v1/stats");
|
|
173
|
+
const { products, opportunities, totalLikes } = json.data;
|
|
174
|
+
|
|
175
|
+
const text = [
|
|
176
|
+
"## 探新 AI 产品库 — 平台概况",
|
|
177
|
+
"",
|
|
178
|
+
`- 已收录 AI 产品:**${products}** 个`,
|
|
179
|
+
`- 合作机会:**${opportunities}** 条`,
|
|
180
|
+
`- 累计点赞:**${totalLikes}** 次`,
|
|
181
|
+
"",
|
|
182
|
+
"平台地址:https://www.tan-xin.com",
|
|
183
|
+
"适合人群:独立开发者、AI 工具创作者、寻找合伙人的创业者",
|
|
184
|
+
].join("\n");
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
content: [{ type: "text", text }],
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
// ── 启动 ──────────────────────────────────────────────────────────────────────
|
|
193
|
+
|
|
194
|
+
const transport = new StdioServerTransport();
|
|
195
|
+
await server.connect(transport);
|