grade

Public TV and radio catalogue with measured stream health, folders and M3U feeds for VLC.

사용해야 할까요

품질 및 안전성

B
설명 품질
76%
스키마 완전성
74%
이름 품질
91%
오염 위험
80%
권한 일치
100%
프로토콜 준수
100%

발견 사항 (24)

  • HIGHTool poisoning patterns detected
  • MEDIUMTool description contains URL to non-standard domainlegacy_stream에서
  • LOWTool 'api_index' description lacks action verbapi_index에서
  • LOWTool 'health' description lacks action verbhealth에서
  • LOWTool 'geo' description lacks action verbgeo에서
  • LOWTool 'list_tags' description lacks action verblist_tags에서
  • LOWTool 'list_languages' description lacks action verblist_languages에서
  • LOWTool 'list_networks' description lacks action verblist_networks에서
  • LOWTool 'list_subdivisions' description lacks action verblist_subdivisions에서
  • LOWTool 'list_cities' description lacks action verblist_cities에서

도구 정의와 프로토콜 준수에 대한 자동 분석을 기반으로 합니다.

컨텍스트 비용

~4,828토큰 (도구 정의)
~603 B일반적인 응답 크기
상당한 주의 영향 (128k 컨텍스트의 3.77%)

이는 서버의 도구가 모델의 컨텍스트에 로드될 때마다 소비되는 대략적인 토큰 수입니다. 수치가 높을수록 다른 작업에 사용할 수 있는 주의가 줄어듭니다.

설치

원클릭 설치

`claude_desktop_config.json` 파일에 다음을 추가하세요:

{
  "mcpServers": {
    "grade": {
      "url": "https://gradetv.net/mcp"
    }
  }
}

원격 엔드포인트

https://gradetv.net/mcpstreamable-http

할 수 있는 일

도구 목록

도구 (40)

🟢 읽기 전용🟡 쓰기🔴 삭제⚪ 알 수 없음
⚪api_index

Índice auto-descrito da API inteira, com os idiomas e as páginas HTML de cada um.

입력 스키마

{
  "type": "object",
  "properties": {}
}
⚪health

Liveness e o commit publicado agora — é como o smoke espera o próprio deploy.

입력 스키마

{
  "type": "object",
  "properties": {}
}
⚪geo

País e idioma sugeridos para quem está chamando. Sem país detectado pela borda, sugere BR com `source: "fallback"`; `detected` diz o que a borda viu.

입력 스키마

{
  "type": "object",
  "properties": {}
}
🟢list_countries(kind)

Países do catálogo com contagem playable e URL da bandeira (kind=radio conta estações).

입력 스키마

{
  "type": "object",
  "properties": {
    "kind": {
      "type": "string",
      "enum": [
        "tv",
        "radio",
        "all"
      ],
      "description": "`tv` (padrão) conta canais de TV; `radio` conta estações de rádio; `all` junta os dois.",
      "default": "tv"
    }
  }
}
🟢list_tags(country, limit)

Tags das estações de rádio tocáveis, com contagem; opcionalmente por país.

입력 스키마

{
  "type": "object",
  "properties": {
    "country": {
      "type": "string",
      "description": "Restringe às estações de um país, ISO 3166-1 alpha-2."
    },
    "limit": {
      "type": "string",
      "description": "Quantas tags devolver (teto 100).",
      "default": 40
    }
  }
}
🟢search_channels(q, country, category, language, network, ...)

Busca canais públicos (filtros: q, country, category, language, network, quality, playable; kind=radio para estações de rádio, tag para tag de rádio; sort=score ordena pela saúde medida por terceiro, sort=votes pelos votos da rádio; online=1 só quem foi visto online nas últimas 48 h). É a porta de entrada do produto. A resposta varia por navegador, sistema e país de quem pede — cada canal traz `social.your_fails`, o recorte do SEU ambiente — por isso ela é `Cache-Control: private`.

입력 스키마

{
  "type": "object",
  "properties": {
    "q": {
      "type": "string",
      "description": "Texto livre no nome e nos apelidos do canal (busca full-text)."
    },
    "country": {
      "type": "string",
      "description": "País do canal, ISO 3166-1 alpha-2."
    },
    "category": {
      "type": "string",
      "description": "ID de categoria do catálogo."
    },
    "language": {
      "type": "string",
      "description": "Idioma do canal, ISO 639-3."
    },
    "network": {
      "type": "string",
      "description": "Nome exato da rede/emissora."
    },
    "quality": {
      "type": "string",
      "description": "Qualidade exata do stream."
    },
    "guide": {
      "type": "string",
      "description": "`1` traz só canal com grade de programação (EPG).",
      "enum": [
        "0",
        "1"
      ],
      "default": "0"
    },
    "subdivision": {
      "type": "string",
      "description": "Estado/província, código do catálogo."
    },
    "city": {
      "type": "string",
      "description": "Cidade, código do catálogo."
    },
    "playable": {
      "type": "string",
      "description": "`0` inclui canal sem stream utilizável conhecido.",
      "enum": [
        "0",
        "1"
      ],
      "default": "1"
    },
    "sort": {
      "type": "string",
      "enum": [
        "name",
        "score",
        "votes"
      ],
      "description": "`score` ordena pela saúde medida por terceiro, melhor primeiro; canal não medido vai para o fim. `votes` ordena pelos votos registrados para a estação (rádio). `name` é a ordem alfabética.",
      "default": "name"
    },
    "online": {
      "type": "string",
      "description": "`1` traz só canal visto online pela fonte nas 48 h anteriores à última recarga do catálogo (`health_ext.online`); com o catálogo parado há mais de 48 h o filtro não devolve ninguém.",
      "enum": [
        "0",
        "1"
      ],
      "default": "0"
    },
    "kind": {
      "type": "string",
      "enum": [
        "tv",
        "radio",
        "all"
      ],
      "description": "`tv` (padrão) é o catálogo de TV; `radio` são as estações de rádio; `all` junta os dois. Sem `kind`, rádio nunca aparece.",
      "default": "tv"
    },
    "tag": {
      "type": "string",
      "description": "Tag da estação de rádio (vocabulário livre, ex. `mpb`, `news`); veja `GET /api/tags`."
    }
  }
}
🟢list_languages

Idiomas que têm canal tocável, com a contagem de cada um.

입력 스키마

{
  "type": "object",
  "properties": {}
}
🟢list_networks

Redes e emissoras que têm canal tocável, com a contagem.

입력 스키마

{
  "type": "object",
  "properties": {}
}
🟢list_qualities

Qualidades distintas encontradas nos streams do catálogo (em rádio, codec e bitrate).

입력 스키마

{
  "type": "object",
  "properties": {}
}
🟢list_subdivisions(country)

Estados e províncias que têm canal tocável.

입력 스키마

{
  "type": "object",
  "properties": {
    "country": {
      "type": "string",
      "description": "Restringe a um país, ISO 3166-1 alpha-2."
    }
  }
}
🟢list_cities(country, subdivision)

Cidades que têm canal tocável, filtráveis por país e por estado.

입력 스키마

{
  "type": "object",
  "properties": {
    "country": {
      "type": "string",
      "description": "Restringe a um país, ISO 3166-1 alpha-2."
    },
    "subdivision": {
      "type": "string",
      "description": "Restringe a um estado/província."
    }
  }
}
🟢get_channel(id)

Ficha completa de um canal, com os streams já apontando para o nosso hop.

입력 스키마

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "ID do canal no catálogo, ex. `GloboNews.br`."
    }
  },
  "required": [
    "id"
  ]
}
🟢get_channel_guide(id)

Programação de hoje do canal (grabada por nós): agora, a seguir e a lista. Disponível nos canais com guia (`guide=1`), com validade de até dois dias. Confira a data da resposta; a ficha traz o resumo em `guide_now`.

입력 스키마

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "ID do canal no catálogo."
    }
  },
  "required": [
    "id"
  ]
}
🟡create_guest

Cria guest ipt_… Não pede e-mail nem nada. Guarde o token: perdeu o token, perdeu a biblioteca — a não ser que a conta já o tenha reivindicado (`POST /api/auth/claim`), e aí o que ele guardou está na conta.

입력 스키마

{
  "type": "object",
  "properties": {}
}
🟢get_library

A galeria inteira do dono: pastas, sub-abas, canais e as URLs de feed de cada nível.

입력 스키마

{
  "type": "object",
  "properties": {}
}
🟡create_category(name)

Cria tab/categoria pessoal. Teto de 8 pastas por dono. A resposta traz a biblioteca inteira já atualizada — não precisa recarregar `GET /api/library` depois.

입력 스키마

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Nome da pasta, até 40 caracteres."
    }
  },
  "required": [
    "name"
  ]
}
🟡create_group(category_id, name)

Cria sub-aba numa categoria. Teto de 12 sub-abas por pasta. A resposta traz a biblioteca inteira já atualizada — não precisa recarregar `GET /api/library` depois.

입력 스키마

{
  "type": "object",
  "properties": {
    "category_id": {
      "type": "string",
      "description": "Pasta que vai receber a sub-aba, `cat_…`."
    },
    "name": {
      "type": "string",
      "description": "Nome da sub-aba, até 40 caracteres."
    }
  },
  "required": [
    "category_id",
    "name"
  ]
}
🟡add_item(group_id, channel_id)

Adiciona canal à sub-aba. Teto de 40 canais por sub-aba. A resposta diz em que pasta e sub-aba o canal caiu, para a tela abrir no lugar certo. A resposta traz a biblioteca inteira já atualizada — não precisa recarregar `GET /api/library` depois.

입력 스키마

{
  "type": "object",
  "properties": {
    "group_id": {
      "type": "string",
      "description": "Sub-aba que recebe o canal, `grp_…`."
    },
    "channel_id": {
      "type": "string",
      "description": "ID do canal no catálogo, ex. `GloboNews.br`."
    }
  },
  "required": [
    "group_id",
    "channel_id"
  ]
}
🟢get_history(limit, offset)

Histórico de canais assistidos pelo dono. Exibe somente canais disponíveis no catálogo.

입력 스키마

{
  "type": "object",
  "properties": {
    "limit": {
      "type": "string",
      "description": "Itens por página. Acima de 50 é silenciosamente reduzido a 50.",
      "default": 20
    },
    "offset": {
      "type": "string",
      "description": "Quantos itens pular. Use `next_offset` da resposta anterior.",
      "default": 0
    }
  }
}
⚪record_watch(channel_id)

Registra um canal assistido no histórico do dono.

입력 스키마

{
  "type": "object",
  "properties": {
    "channel_id": {
      "type": "string",
      "description": "Canal assistido, ex. `GloboNews.br`."
    }
  },
  "required": [
    "channel_id"
  ]
}
⚪forget_watch(channel_id)

Tira um canal do histórico do dono.

입력 스키마

{
  "type": "object",
  "properties": {
    "channel_id": {
      "type": "string",
      "description": "Canal a remover do histórico, ex. `GloboNews.br`."
    }
  },
  "required": [
    "channel_id"
  ]
}
🔴clear_history

Limpa o histórico inteiro do dono, de uma vez.

입력 스키마

{
  "type": "object",
  "properties": {}
}
🔴legacy_stream(id)

Metadados públicos: site oficial do canal, URL da transmissão para copiar em outro player e player legado HTTP. O botão legacy_url abre http://legacy.gradetv.net:8080/legacy?stream=ID. A página isolada aceita lang=pt/en/es/fr/de e theme=light/dark. Playlists continuam pelo hop HTTPS e mídia direto da origem. Não remove recusa de acesso nem exigência CORS. Uma leitura indexada; não busca origem nem grava no D1.

입력 스키마

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "ID público do stream, incluindo compatibilidade de IDs antigos."
    }
  },
  "required": [
    "id"
  ]
}
🟡producer_services(lang)

Oferta de transmissão autorizada sob consulta: informações e contatos para produtores. Não ativa streams. Somente informações e captação de interesse. Não provisiona, não cobra e não ativa transmissão. Use contact.form_url no browser, contact.email por e-mail ou POST /api/contact para apresentar o projeto. O envio é livre — sem captcha nem pagamento —, uma mensagem a cada 10 s por rede.

입력 스키마

{
  "type": "object",
  "properties": {
    "lang": {
      "type": "string",
      "enum": [
        "pt",
        "en",
        "es",
        "fr",
        "de"
      ],
      "description": "Idioma da oferta: pt, en, es, fr ou de; ausente ou desconhecido volta a pt.",
      "default": "pt"
    }
  }
}
⚪report_play(channel_id, ok, code)

Relata se um canal tocou (ok=true) ou não (ok=false + code). Navegador, SO e país saem do pedido, não do corpo. Conta uma vez por dono, por canal, por dia e por resultado; relatar de novo devolve 200 com `reason: ja_relatado_hoje`, e não é erro. Navegador e sistema saem do User-Agent e o país da borda — mandar isso no corpo não muda nada. Sem relato, o catálogo não aprende: é assim que `GET /api/channels/:id/health` sabe distinguir canal fora do ar de canal bloqueado para você.

입력 스키마

{
  "type": "object",
  "properties": {
    "channel_id": {
      "type": "string",
      "description": "Canal que você tentou assistir."
    },
    "ok": {
      "type": "boolean",
      "description": "`true` se tocou, `false` se falhou."
    },
    "code": {
      "type": "string",
      "description": "Por que falhou; só quando `ok` é `false`.",
      "enum": [
        "cors",
        "geo",
        "sumiu",
        "codec",
        "playlist",
        "sem_resposta",
        "protocolo",
        "sem_stream",
        "outro"
      ]
    }
  },
  "required": [
    "channel_id",
    "ok"
  ]
}
⚪play_reports(channel_id, ok, limit)

Relatos crus de um canal, com endereço — só operador (METRICS_TOKEN). Use para investigar um canal específico. Existe separado do painel público justamente porque traz endereço. A linha some depois do prazo em `retention_days`, e `/api/channels/:id/health` nunca devolve IP.

입력 스키마

{
  "type": "object",
  "properties": {
    "channel_id": {
      "type": "string",
      "description": "Restringe a um canal."
    },
    "ok": {
      "type": "string",
      "description": "`0` traz só as falhas — é o recorte que interessa numa investigação.",
      "enum": [
        "0"
      ]
    },
    "limit": {
      "type": "string",
      "description": "Itens por página. Acima de 50 é silenciosamente reduzido a 50.",
      "default": 20
    }
  }
}
⚪channel_health(id)

Saúde comunitária do canal: taxa de sucesso, motivos de falha e ambientes afetados. É o que separa 'o canal está fora do ar' de 'o canal está bloqueado no seu país'. `geo` diz se é restrição regional ou falha geral (com os países), `regions[]` traz sucesso/falha por país, `latency[]` a velocidade de abertura medida no hop por país, e `pra_voce` resume tudo para o país de quem chama. Sem relato da comunidade (`POST /api/play-report`) o painel fica vazio.

입력 스키마

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "ID do canal no catálogo."
    }
  },
  "required": [
    "id"
  ]
}
🟢list_favorites

Favoritos do dono. Exibe somente canais disponíveis no catálogo.

입력 스키마

{
  "type": "object",
  "properties": {}
}
🟡add_favorite(channel_id)

Favorita um canal. Repetir não soma: o contador público conta pessoas, não cliques.

입력 스키마

{
  "type": "object",
  "properties": {
    "channel_id": {
      "type": "string",
      "description": "Canal a favoritar, ex. `GloboNews.br`."
    }
  },
  "required": [
    "channel_id"
  ]
}
🔴remove_favorite(channel_id)

Desfavorita o canal e devolve o ponto ao contador público.

입력 스키마

{
  "type": "object",
  "properties": {
    "channel_id": {
      "type": "string",
      "description": "Canal a desfavoritar, ex. `GloboNews.br`."
    }
  },
  "required": [
    "channel_id"
  ]
}
🟢list_comments(id)

Comentários da comunidade sobre um canal. Com credencial na chamada, cada comentário seu vem com `mine: true` — é assim que a interface sabe o que dá para apagar.

입력 스키마

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "ID do canal no catálogo."
    }
  },
  "required": [
    "id"
  ]
}
🟡post_comment(id, body, author)

Comenta num canal (teto de 20/hora por dono). Sem `author`, o apelido é gerado e fica estável para o mesmo dono — a pessoa não vira um nome diferente a cada mensagem.

입력 스키마

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "ID do canal no catálogo."
    },
    "body": {
      "type": "string",
      "description": "O texto do comentário; o teto vem em `max_length` da listagem."
    },
    "author": {
      "type": "string",
      "description": "Apelido a usar; sem ele o servidor gera um estável."
    }
  },
  "required": [
    "id",
    "body"
  ]
}
🔴delete_comment(id)

Apaga um comentário do próprio dono. O 404 é de propósito: a API não confirma que existe um comentário com aquele id se ele não é seu.

입력 스키마

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "ID do comentário, vindo de `Comentario.id`."
    }
  },
  "required": [
    "id"
  ]
}
⚪chat_history(channel_id)

Últimas mensagens da sala de um canal (sem WebSocket).

입력 스키마

{
  "type": "object",
  "properties": {
    "channel_id": {
      "type": "string",
      "description": "ID do canal no catálogo."
    }
  },
  "required": [
    "channel_id"
  ]
}
🟡chat_send(channel_id, body, author)

Manda mensagem na sala de um canal por HTTP. Ler é grátis; escrever custa $0.10 por 30 dias. Sem passe válido a resposta é 402 com `accepts[]` — pague e repita a mesma chamada. Quem fala é o convidado (`X-Guest-Token`), o mesmo que o WebSocket reconhece; sem convidado, a sessão da conta.

입력 스키마

{
  "type": "object",
  "properties": {
    "channel_id": {
      "type": "string",
      "description": "ID do canal no catálogo."
    },
    "body": {
      "type": "string",
      "description": "O texto da mensagem, dentro de `max_length`."
    },
    "author": {
      "type": "string",
      "description": "Apelido a usar; sem ele o servidor gera um estável."
    }
  },
  "required": [
    "channel_id",
    "body"
  ]
}
⚪chat_pass

Passe mensal do chat ($0.10 / 30 dias) do convidado que fala no chat. Sem pagamento → 402. Passe já válido devolve 200 sem cobrar de novo — dá para chamar antes de escrever, sem risco de pagar duas vezes. O passe é de quem fala no chat: o convidado de `X-Guest-Token` (é ele que o WebSocket reconhece no `hello`); sem convidado, a sessão da conta, que fala só por HTTP. Fica no registro global de compras (`direito`).

입력 스키마

{
  "type": "object",
  "properties": {}
}
⚪me

Conta da sessão (cookie repassado pelo cliente MCP): e-mail e tamanho da biblioteca da conta. A conta é a da biblioteca de conta; `user.id` é o id da conta, e é ele o dono da galeria com sessão.

입력 스키마

{
  "type": "object",
  "properties": {}
}
⚪billing

Preços e tetos. É o número EM VIGOR: leia daqui antes de gastar chamada, em vez de assumir o preço da documentação. Com credencial, também diz se o passe de chat de quem fala no chat (o convidado; sem ele, a conta) está ativo. `prices.abuso_24h_usd` é o preço da porta de UA vazio/curl, hoje desligada.

입력 스키마

{
  "type": "object",
  "properties": {}
}
⚪contact(name, email, message, tipo, empresa, ...)

Fale com quem faz o produto: dúvida, ou proposta de patrocínio/parceria/anúncio. Grátis, sem captcha nem pagamento; uma mensagem a cada 10 s por rede (a que chega antes espera a vez). Uma rota para dúvida e para proposta de patrocínio, parceria ou anúncio (`tipo`, com os espaços de `GET /api/partners`). Sem captcha, sem conta, sem pagamento. Uma mensagem a cada 10 segundos por rede: a que chega antes espera a vez e sai — sem erro. A mensagem chega à equipe por e-mail, com o `email` como endereço de resposta.

입력 스키마

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "description": "Como chamar quem escreve (alias `nome`)."
    },
    "email": {
      "type": "string",
      "description": "Para onde responder."
    },
    "message": {
      "type": "string",
      "description": "O que você quer dizer (alias `mensagem`)."
    },
    "tipo": {
      "type": "string",
      "enum": [
        "patrocinio",
        "parceria",
        "anuncio"
      ],
      "description": "Proposta: `patrocinio`, `parceria` ou `anuncio`. Liga os campos abaixo."
    },
    "empresa": {
      "type": "string",
      "description": "Quem propõe, quando é empresa."
    },
    "site": {
      "type": "string",
      "description": "Site de quem propõe."
    },
    "orcamento": {
      "type": "string",
      "enum": [
        "ate_100",
        "100_500",
        "500_2000",
        "2000_mais",
        "a_combinar"
      ],
      "description": "`ate_100`, `100_500`, `500_2000`, `2000_mais` ou `a_combinar`."
    },
    "espaco": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "Ids de placement de `GET /api/partners`, até 6."
    },
    "duracao": {
      "type": "string",
      "enum": [
        "30",
        "90",
        "365"
      ],
      "description": "Dias de exposição: `30`, `90` ou `365`."
    },
    "pagamento": {
      "type": "string",
      "enum": [
        "usdc",
        "deposito",
        "a_combinar"
      ],
      "description": "`usdc`, `deposito` ou `a_combinar`."
    }
  },
  "required": [
    "name",
    "email",
    "message"
  ]
}
⚪pricing

Current public prices and free allowances; no charge.

입력 스키마

{
  "type": "object",
  "properties": {},
  "additionalProperties": false
}

커뮤니티

이 서버 평가하기

증거

최근 관측

검증됨버전이 기록되지 않음도구 40개
검증됨버전이 기록되지 않음도구 41개