Sync Licensing MCP Server
Sync Licensing MCP Server
Локальный сервер Model Context Protocol, который предоставляет каталог и бизнес-логику музыкальной платформы sync-лицензирования: поиск треков по креативному брифу, проверка их правовой чистоты, расчёт стоимости лицензии по условным правилам ценообразования, выпуск контракта и регистрация использования.
Создан для CC3067 Redes (Universidad del Valle de Guatemala), проект 1. Поток сообщений MCP реализован напрямую поверх JSON-RPC 2.0 — без MCP SDK, без FastMCP, без фреймворков. Пакет сервера зависит только от стандартной библиотеки Python.
Содержание
Related MCP server: MusicBrainz MCP Server
1. Бизнес-кейс
Sync-лицензирование — это бизнес-модель таких платформ, как Epidemic Sound, Artlist и Musicbed: создатель контента или рекламное агентство обязаны купить лицензию перед использованием трека в аудиовизуальном контенте. В этом процессе есть три узких места:
Поиск трека, который соответствует креативному брифу и бюджету, занимает много времени.
Правовой статус трека не очевиден — он может содержать сэмплы, которые никогда не были очищены, или быть заморожен из-за спора об авторстве.
Цена не фиксирована. Один и тот же трек стоит одну сумму для поста в Instagram и совсем другую — для национальной телевизионной кампании.
Этот сервер превращает этот рабочий процесс в пять инструментов, которые ассистент может выстраивать в цепочку. Это не поисковая система с прикреплённым прайс-листом: плата вычисляется по условным правилам, а инструменты отказываются от операций, которые поставили бы клиента под правовой риск.
2. Архитектура
┌────────────────────────┐
│ Host (chatbot / CLI) │
└───────────┬────────────┘
│ spawns as a subprocess
┌───────────▼────────────┐
│ MCP client │ client/mcp_cli.py
└───────────┬────────────┘
│ JSON-RPC 2.0 over stdio
│ (one JSON object per line)
┌───────────▼────────────┐
│ MCP server │ synclicense_mcp/
│ │
│ jsonrpc.py framing │
│ server.py dispatch │
│ tools.py 5 tools │
│ pricing.py rate card│
│ contracts.py contracts
│ catalog.py catalog │
└───────────┬────────────┘
│
┌───────────▼────────────┐
│ data/catalog.json │ built by scripts/seed_catalog.py
│ data/usage_log.jsonl │ append-only audit log
└────────────────────────┘stdout несёт только протокольный трафик; все диагностические сообщения сервер выводит в stderr, поэтому перенаправление вывода сервера никогда не повреждает поток.
3. Требования
Python 3.10 или новее (разработано на 3.11).
Других зависимостей для запуска сервера нет.
requestsнужен только для получения реальных метаданных из Jamendo, аpytest— только для запуска тестов. Оба указаны вrequirements.txt.
4. Установка
git clone https://github.com/ecarcamo/MCP-Local-Redes.git
cd MCP-Local-Redes
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtПакет не устанавливается: он импортируется из корня репозитория, поэтому все команды ниже выполняются из каталога проекта.
5. Сборка каталога
В репозитории уже есть каталог data/catalog.json с 800 реальными треками, полученными из API Jamendo, так что этот раздел можно пропустить и перейти сразу к Использованию. Пересобирайте его только в том случае, если нужен другой размер, другое зерно (seed) или каталог, не требующий учётных данных.
Офлайн-режим (по умолчанию, без учётных данных, без сети)
python scripts/seed_catalog.py --offline --count 800Детерминированный: одно и то же --seed всегда даёт один и тот же каталог. Он также закрепляет три известных трека в начале (TRK-00001 — чистый, TRK-00002 — с ожидающими сэмплами, TRK-00003 — заблокированный), что упрощает демонстрацию сценариев отказа.
Режим Jamendo (реальные метаданные Creative Commons)
Зарегистрируйтесь на https://devportal.jamendo.com, чтобы получить client_id, затем:
cp .env.example .env
# edit .env and set JAMENDO_CLIENT_ID=your_client_id
python scripts/seed_catalog.py --jamendo --count 800Метаданные треков берутся из API; базовая плата и правовой статус по-прежнему генерируются локально (см. раздел 10). Популярность берётся из собственной сортировки API popularity_total. Бесплатный тариф Jamendo ограничивает всплески запросов и отвечает на ограниченную страницу пустым списком результатов, а не ошибкой, поэтому скрипт делает паузы между страницами и повторяет запрос пустой страницы, прежде чем заключить, что каталог исчерпан.
Параметр | По умолчанию | Описание |
|
| Источник метаданных треков |
|
| Сколько треков записать |
|
| Зерно для имитации бизнес-уровня |
|
| Куда записать каталог |
6. Использование
6.1 Запуск управляемой демонстрации
Сценарный сквозной прогон, полезный в качестве смоук-теста. Он запускает сервер, проигрывает полный диалог лицензирования и выводит каждое сообщение JSON-RPC, проходящее по каналу (--> отправлено, <-- получено):
python client/mcp_cli.py --demoДемонстрация проходит через: рукопожатие → tools/list → поиск трека → проверку его правовой чистоты → расчёт стоимости → выпуск контракта → регистрацию использования → и три случая отказа (заблокированный трек, котировка, принадлежащая другому треку, и недопустимый аргумент).
Добавьте --quiet, чтобы скрыть необработанный протокольный трафик и видеть только ответы:
python client/mcp_cli.py --demo --quiet6.2 Интерактивная сессия (основной способ использования)
REPL для управления сервером вручную, по одному инструменту за раз:
python client/mcp_cli.py --interactiveКоманда | Описание |
| Инструменты, опубликованные сервером |
| JSON Schema одного инструмента |
| Вызвать инструмент с JSON-аргументами |
| Идентификаторы, запомненные из ответов |
| Отправить JSON-RPC ping |
| Отправить любой метод JSON-RPC вручную |
| Закрыть сессию |
Идентификаторы запоминаются. Каждый *_id, возвращаемый инструментом, сохраняется и может быть использован как $name в следующем вызове, поэтому весь переговорный процесс по лицензированию можно ввести, не копируя ни одного идентификатора вручную:
mcp> call buscar_pista {"mood": "epico", "instrumental": true, "presupuesto_max": 100, "limite": 3}
...
remembered: $pista_id=TRK-00312
mcp> call verificar_clearance {"pista_id": "$pista_id"}
mcp> call calcular_costo_licencia {"pista_id": "$pista_id", "tipo_uso": "publicidad_online", "territorio": "latam", "exclusividad": "sectorial", "duracion_meses": 12}
...
remembered: $cotizacion_id=COT-719E615733
mcp> call generar_contrato {"pista_id": "$pista_id", "cliente": "Agencia Lumen S.A.", "cotizacion_id": "$cotizacion_id"}
...
remembered: $contrato_id=CTR-F9D1D72B0D
mcp> call registrar_uso {"contrato_id": "$contrato_id", "plataforma": "YouTube", "url_proyecto": "https://youtube.com/watch?v=demo"}
mcp> vars
mcp> quit$pista_id по умолчанию указывает на лучшего кандидата из последнего поиска. В любой момент используйте vars, чтобы увидеть, что сейчас запомнено.
6.3 Запуск сервера отдельно
python -m synclicense_mcpЗатем он ожидает сообщения JSON-RPC на stdin. Используйте --catalog PATH, чтобы указать другой файл каталога.
6.4 Общение с сервером вообще без клиента
Поскольку транспорт — это просто JSON с разделителями строк, сервером можно управлять прямо из оболочки:
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"shell","version":"0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
'{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"verificar_clearance","arguments":{"pista_id":"TRK-00001"}}}' \
| python -m synclicense_mcp7. Справочник инструментов
Инструмент | Обязательные аргументы | Возвращает |
| (нет — каждый фильтр необязателен) | Кандидаты-треки с id, названием, исполнителем, длительностью и базовой платой |
|
| Правовой статус: чистый, ожидающие сэмплы или заблокированный |
|
| Полная разбивка стоимости, итог в USD и |
|
| Контракт с объёмом, сроком, суммой, ограничениями и |
|
| Запись об использовании для роялти и аудита |
7.1 buscar_pista
Необязательные фильтры: mood, genero, instrumental, duracion_seg_min, duracion_seg_max, presupuesto_max, limite (1–20, по умолчанию 5).
mood:alegre,epico,melancolico,relajado,tenso,energetico,inspirador,oscurogenero:pop,rock,electronica,hip_hop,jazz,clasica,folk,ambient,cinematica,latina
Треки, заблокированные спором об авторстве, исключаются: их нельзя лицензировать, поэтому их предложение было бы ложным срабатыванием.
7.2 verificar_clearance
Статус | Можно лицензировать | Эффект |
| да | Нет обременений |
| да | +15% надбавка эскроу и оговорка об удержании |
| нет | Спор об авторстве; расчёт стоимости и контракт отклоняются |
7.3 calcular_costo_licencia
Аргумент | Допустимые значения |
|
|
|
|
|
|
|
|
Пример запроса и ответа:
--> {"jsonrpc":"2.0","id":5,"method":"tools/call","params":{
"name":"calcular_costo_licencia",
"arguments":{"pista_id":"TRK-00312","tipo_uso":"redes_sociales",
"territorio":"local","exclusividad":"no","duracion_meses":6}}}
<-- {"jsonrpc":"2.0","id":5,"result":{
"content":[{"type":"text","text":"Quote for TRK-00312 \"Stop!\" ... TOTAL USD 94.50"}],
"structuredContent":{
"ok":true,
"cotizacion_id":"COT-3D18B1547D",
"pista_id":"TRK-00312",
"alcance":{"tipo_uso":"redes_sociales","territorio":"local",
"exclusividad":"no","duracion_meses":6},
"desglose":{"tarifa_base_usd":94.5,
"multiplicadores":{"tipo_uso":1.0,"territorio":1.0,
"exclusividad":1.0,"vigencia":1.0},
"subtotal_usd":94.5,"recargo_escrow_usd":0.0,
"total_usd":94.5,"moneda":"USD"},
"valida_hasta":"2026-09-19T18:15:54+00:00"},
"isError":false}}7.4 Цепочки инструментов
Инструменты сохраняют состояние в рамках сессии — в этом и заключается смысл сценария использования:
buscar_pista ──► pista_id
├──► verificar_clearance (can stop the whole flow)
└──► calcular_costo_licencia ──► cotizacion_id
└──► generar_contrato ──► contrato_id
└──► registrar_usogenerar_contrato отклоняет котировку, которая не существует, истекла (30 дней) или была выпущена для другого трека. registrar_uso отклоняет неизвестный или неактивный контракт. Котировки и контракты принадлежат одному соединению и не передаются между сессиями.
8. Правила ценообразования
subtotal = tarifa_base × mult_use × mult_territory × mult_exclusivity × mult_term
total = subtotal + escrow surcharge (15% when the track has pending samples)Тип использования | × | Территория | × | Эксклюзивность | × | Срок | × |
| 1.0 |
| 1.0 |
| 1.0 | ≤ 3 месяца | 0.8 |
| 1.1 |
| 1.8 |
| 2.0 | ≤ 6 месяцев | 1.0 |
| 1.3 |
| 2.2 |
| 4.5 | ≤ 12 месяцев | 1.5 |
| 1.6 |
| 2.4 | ≤ 24 месяца | 2.2 | ||
| 2.5 |
| 3.2 | ≤ 36 месяцев | 2.8 | ||
| 4.0 | > 36 месяцев | 3.2 | ||||
| 6.0 | бессрочно | 3.5 | ||||
| 8.0 |
Шесть месяцев — это эталонный срок, поэтому он находится на уровне 1.0. Котировка сохраняет свою цену в течение 30 дней.
9. Детали протокола
Транспорт. stdio, одно сообщение JSON-RPC 2.0 на строку, UTF-8, без встроенных переводов строк. Сервер корректно завершает работу по EOF.
Версии протокола. 2025-11-25 (предпочтительная) и 2025-06-18. Если клиент запрашивает что-либо другое, сервер отвечает своей предпочтительной версией, а не завершает рукопожатие ошибкой.
Методы.
Метод | Результат |
| Согласованная версия, возможности, информация о сервере, инструкции |
| (уведомление — без ответа) |
|
|
| Пять описаний инструментов с их JSON Schema |
|
|
Коды ошибок.
Код | Значение |
| Ошибка разбора — строка не является корректным JSON |
| Недопустимый запрос — неверная обёртка |
| Метод не найден |
| Недопустимые параметры — отсутствующий, неверного типа или вне перечисления аргумент, либо неизвестный инструмент |
| Внутренняя ошибка |
| Сервер не инициализирован — запрос поступил до рукопожатия |
Ошибки протокола и бизнес-ошибки. Некорректный вызов возвращается как
JSON-RPC error. Корректно сформированный вызов, который отклоняют правила
лицензирования — заблокированный трек, истёкшая котировка, неизвестный контракт —
возвращается как успешный ответ с isError: true и понятным объяснением,
чтобы модель могла прочитать причину и скорректировать действия, а не видеть
сбой транспорта.
Полная спецификация приведена в docs/SERVER_SPEC.md.
10. Откуда берутся данные
Метаданные треков (название, исполнитель, длительность, жанр, настроение, лицензия, рейтинг популярности) берутся из публичного Jamendo API, который предоставляет каталог Creative Commons. Каталог, поставляемый в этом репозитории, был создан именно так. Офлайн-генератор воспроизводит ту же структуру локально, поэтому проект работает без учётных данных и без доступа к сети.
Бизнес-уровень намеренно имитируется. Ни одна платформа не публикует свой
прайс-лист или внутренний юридический статус каждого трека, поэтому
tarifa_base_usd и estado_derechos генерируются из фиксированного зерна с
реалистичным распределением (82% — очищено, 13% — образцы на рассмотрении, 5% —
заблокировано). Множители прайс-листа были разработаны на основе публичных
прайс-листов роялти-фри платформ, таких как
Jamendo Licensing.
Эта область была рассмотрена и одобрена преподавателем курса.
11. Тестирование
python -m pytest tests/ -vНабор покрывает правила прайс-листа, структуру JSON-RPC, рукопожатие, коды ошибок, цепочку инструментов и её отказы, генератор зерна, а также один сквозной тест, который запускает реальный процесс сервера и общается с ним через stdio-транспорт. Тесты ищут треки по статусу прав, а не по фиксированному id, поэтому они проходят на любом каталоге: офлайн, Jamendo или перегенерированном с другим зерном.
12. Структура проекта
MCP-Local-Redes/
├── synclicense_mcp/ MCP server package (standard library only)
│ ├── __main__.py entry point: python -m synclicense_mcp
│ ├── jsonrpc.py JSON-RPC 2.0 framing over stdio
│ ├── server.py MCP method dispatch
│ ├── tools.py the five tools: schemas, validation, handlers
│ ├── pricing.py conditional rate card
│ ├── contracts.py contracts and usage registration
│ ├── catalog.py catalog loading and search
│ └── errors.py business-rule failures
├── client/mcp_cli.py manual JSON-RPC client (demo + REPL)
├── scripts/seed_catalog.py catalog builder (offline / Jamendo)
├── data/catalog.json generated catalog
├── tests/ pytest suite
└── docs/ proposal, assignment brief, server specification13. Статус проекта
Поставлено на этом этапе:
Локальный MCP-сервер через stdio с пятью инструментами одобренного сценария.
JSON-RPC 2.0 и рукопожатие MCP, реализованные вручную.
Командный клиент со скриптовой демонстрацией и интерактивным REPL.
Заполнение каталога в офлайн- и Jamendo-режимах.
Набор тестов.
Запланировано на остальную часть проекта:
Чат-бот на Anthropic API с контекстом сессии и видимым журналом каждого взаимодействия с MCP.
Интеграция с официальными MCP-серверами Filesystem и Git.
Тот же сервер, развёрнутый удалённо через HTTP.
Захват Wireshark и послойный анализ удалённого трафика.
Автор: Esteban Cárcamo (23016) — CC3067 Redes, Section 20
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceAn MCP server for Spotify control and synchronized lyrics retrieval that enables playback management, queue navigation, and music search capabilities. It also features perception tools for real-time track analysis, including BPM, key detection, and timestamped lyrics.1293Apache 2.0
- AlicenseNot gradedqualityCmaintenanceA comprehensive MCP server for querying the MusicBrainz database, providing tools to search for artists, releases, recordings, and browse music metadata.4MIT
- FlicenseNot gradedqualityCmaintenanceA remote MCP server for the Arxpot processing core, enabling music search, metadata retrieval, and download management with remote storage delivery.
- AlicenseAqualityAmaintenanceAn MCP server that enables searching tracks and fetching lyrics, including time-synced LRC lyrics, from LRCLIB without requiring an API key.2398MIT
Related MCP Connectors
Personal MCP server for humans who create. Proof of authorship, license control.
A paid remote MCP for CLI tool MCP, built to return verdicts, receipts, usage logs, and audit-ready
A paid remote MCP for hosted MCP server, built to return verdicts, receipts, usage logs, and audit-r
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ecarcamo/MCP-Local-Redes'
If you have feedback or need assistance with the MCP directory API, please join our Discord server