nardoto-mcp-freesound 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 +20 -0
- package/index.js +103 -0
- package/package.json +31 -0
package/README.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# nardoto-mcp-freesound
|
|
2
|
+
|
|
3
|
+
MCP server para buscar e baixar **efeitos sonoros (SFX) Creative Commons do Freesound** direto no chat.
|
|
4
|
+
|
|
5
|
+
## Configuração
|
|
6
|
+
- `FREESOUND_API_KEY` — Token grátis em https://freesound.org/apiv2/apply. Cobre busca + download do **preview MP3** (suficiente para ~90% dos SFX). O arquivo original (.wav/.flac) exigiria OAuth2 e está fora do escopo.
|
|
7
|
+
|
|
8
|
+
## Tools
|
|
9
|
+
- `search_sounds` — busca por texto, filtro de duração máxima.
|
|
10
|
+
- `get_sound` — detalhes de um som.
|
|
11
|
+
- `download_preview` — URL do preview MP3 (sem OAuth).
|
|
12
|
+
|
|
13
|
+
Toda resposta traz a **licença** e o campo `uso_comercial` (CC0 = livre; CC-BY = com atribuição; CC-BY-NC = proibido monetizar).
|
|
14
|
+
|
|
15
|
+
## Uso
|
|
16
|
+
```
|
|
17
|
+
npx -y nardoto-mcp-freesound
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
MIT · feito pelo Nardoto.
|
package/index.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* nardoto-mcp-freesound — MCP server pra buscar e baixar efeitos sonoros (SFX) Creative Commons do Freesound.
|
|
4
|
+
*
|
|
5
|
+
* Auth: FREESOUND_API_KEY (Token gratis em https://freesound.org/apiv2/apply).
|
|
6
|
+
* O Token cobre busca + download do PREVIEW comprimido (.mp3), que basta pra ~90% dos SFX em video.
|
|
7
|
+
* (O arquivo ORIGINAL .wav/.flac exigiria OAuth2 — fora do escopo deste MCP.)
|
|
8
|
+
* Toda resposta inclui a licenca e o campo "uso_comercial" (muito SFX e CC-BY-NC).
|
|
9
|
+
*/
|
|
10
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
|
|
11
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
12
|
+
import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js'
|
|
13
|
+
|
|
14
|
+
const KEY = process.env.FREESOUND_API_KEY
|
|
15
|
+
const BASE = 'https://freesound.org/apiv2'
|
|
16
|
+
const FIELDS = 'id,name,license,previews,username,duration,tags'
|
|
17
|
+
|
|
18
|
+
async function fget(path, params) {
|
|
19
|
+
if (!KEY) throw new Error('Defina FREESOUND_API_KEY (Token gratis em freesound.org/apiv2/apply).')
|
|
20
|
+
const url = new URL(BASE + path)
|
|
21
|
+
for (const [k, v] of Object.entries(params || {})) {
|
|
22
|
+
if (v !== undefined && v !== null && v !== '') url.searchParams.set(k, String(v))
|
|
23
|
+
}
|
|
24
|
+
const res = await fetch(url, { headers: { Authorization: 'Token ' + KEY, 'User-Agent': 'nardoto-mcp-freesound' } })
|
|
25
|
+
if (!res.ok) throw new Error(`Freesound HTTP ${res.status}`)
|
|
26
|
+
return res.json()
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function usoComercial(license) {
|
|
30
|
+
const l = (license || '').toLowerCase()
|
|
31
|
+
if (/noncommercial|by-nc/.test(l)) return 'PROIBIDO em conteudo monetizado (licenca NonCommercial).'
|
|
32
|
+
if (/creative commons 0|cc0|publicdomain|\/zero\//.test(l)) return 'Livre, dominio publico (CC0) — sem atribuicao.'
|
|
33
|
+
return 'Permitido com atribuicao ao autor (confira a licenca).'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function fmtSound(s) {
|
|
37
|
+
const previews = s.previews || {}
|
|
38
|
+
return {
|
|
39
|
+
id: s.id,
|
|
40
|
+
name: s.name,
|
|
41
|
+
autor: s.username,
|
|
42
|
+
duration_s: s.duration,
|
|
43
|
+
tags: Array.isArray(s.tags) ? s.tags.slice(0, 12) : undefined,
|
|
44
|
+
preview_mp3: previews['preview-hq-mp3'] || previews['preview-lq-mp3'] || null,
|
|
45
|
+
license: s.license,
|
|
46
|
+
uso_comercial: usoComercial(s.license),
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const TOOLS = [
|
|
51
|
+
{
|
|
52
|
+
name: 'search_sounds',
|
|
53
|
+
description: 'Busca efeitos sonoros e samples Creative Commons no Freesound. Retorna a licenca, o aviso de uso comercial e a URL do preview MP3.',
|
|
54
|
+
inputSchema: {
|
|
55
|
+
type: 'object',
|
|
56
|
+
properties: {
|
|
57
|
+
query: { type: 'string', description: 'Termo de busca (ex: "vento deserto", "multidao", "passos cascalho")' },
|
|
58
|
+
limit: { type: 'number', description: 'Maximo de resultados (1-50, padrao 12)' },
|
|
59
|
+
max_duration_s: { type: 'number', description: 'Duracao maxima em segundos (filtro opcional)' },
|
|
60
|
+
},
|
|
61
|
+
required: ['query'],
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'get_sound',
|
|
66
|
+
description: 'Detalhes de um som pelo id (licenca, autor, preview MP3).',
|
|
67
|
+
inputSchema: { type: 'object', properties: { id: { type: 'string', description: 'ID do som' } }, required: ['id'] },
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'download_preview',
|
|
71
|
+
description: 'Retorna a URL do preview MP3 de um som (download direto, sem OAuth) junto com a licenca e o aviso de uso comercial.',
|
|
72
|
+
inputSchema: { type: 'object', properties: { id: { type: 'string', description: 'ID do som' } }, required: ['id'] },
|
|
73
|
+
},
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
const server = new Server({ name: 'nardoto-mcp-freesound', version: '1.0.0' }, { capabilities: { tools: {} } })
|
|
77
|
+
|
|
78
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }))
|
|
79
|
+
|
|
80
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
81
|
+
const { name, arguments: args = {} } = req.params
|
|
82
|
+
try {
|
|
83
|
+
if (name === 'search_sounds') {
|
|
84
|
+
if (!args.query) throw new Error('query obrigatoria')
|
|
85
|
+
const params = { query: args.query, fields: FIELDS, page_size: Math.min(Math.max(Number(args.limit) || 12, 1), 50) }
|
|
86
|
+
if (args.max_duration_s) params.filter = `duration:[0 TO ${Number(args.max_duration_s)}]`
|
|
87
|
+
const data = await fget('/search/text/', params)
|
|
88
|
+
const sounds = (data.results || []).map(fmtSound)
|
|
89
|
+
return { content: [{ type: 'text', text: JSON.stringify({ count: sounds.length, total: data.count, sounds, aviso: 'Confira "uso_comercial": muito SFX e CC-BY-NC (proibido monetizar).' }, null, 2) }] }
|
|
90
|
+
}
|
|
91
|
+
if (name === 'get_sound' || name === 'download_preview') {
|
|
92
|
+
if (!args.id) throw new Error('id obrigatorio')
|
|
93
|
+
const s = await fget(`/sounds/${encodeURIComponent(args.id)}/`, { fields: FIELDS })
|
|
94
|
+
return { content: [{ type: 'text', text: JSON.stringify(fmtSound(s), null, 2) }] }
|
|
95
|
+
}
|
|
96
|
+
return { content: [{ type: 'text', text: 'Tool desconhecida: ' + name }], isError: true }
|
|
97
|
+
} catch (e) {
|
|
98
|
+
return { content: [{ type: 'text', text: 'Erro: ' + (e?.message || String(e)) }], isError: true }
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
await server.connect(new StdioServerTransport())
|
|
103
|
+
console.error('[nardoto-mcp-freesound] pronto (stdio)')
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nardoto-mcp-freesound",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server para buscar e baixar efeitos sonoros Creative Commons do Freesound",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"nardoto-mcp-freesound": "index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "index.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"index.js",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"engines": {
|
|
15
|
+
"node": ">=18"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@modelcontextprotocol/sdk": "^1.0.0"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"mcp",
|
|
22
|
+
"model-context-protocol",
|
|
23
|
+
"freesound",
|
|
24
|
+
"sfx",
|
|
25
|
+
"sound-effects",
|
|
26
|
+
"creative-commons",
|
|
27
|
+
"nardoto"
|
|
28
|
+
],
|
|
29
|
+
"author": "Nardoto",
|
|
30
|
+
"license": "MIT"
|
|
31
|
+
}
|