chore: align project config with torrentclaw org standards
This commit is contained in:
parent
2f58ac7bf8
commit
8bb8e5507e
9 changed files with 367 additions and 46 deletions
15
.editorconfig
Normal file
15
.editorconfig
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
||||||
69
.github/workflows/ci.yml
vendored
Normal file
69
.github/workflows/ci.yml
vendored
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
name: CI
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint-commits:
|
||||||
|
name: Lint commits
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Validate conventional commits
|
||||||
|
run: |
|
||||||
|
base="${{ github.event.pull_request.base.sha }}"
|
||||||
|
head="${{ github.event.pull_request.head.sha }}"
|
||||||
|
pattern='^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?(!)?: .{1,}$'
|
||||||
|
|
||||||
|
failed=0
|
||||||
|
while IFS= read -r msg; do
|
||||||
|
first_line=$(echo "$msg" | head -1)
|
||||||
|
if ! echo "$first_line" | grep -qE "$pattern"; then
|
||||||
|
echo "FAIL: $first_line"
|
||||||
|
failed=1
|
||||||
|
fi
|
||||||
|
done < <(git log --format="%s" "$base".."$head")
|
||||||
|
|
||||||
|
if [ "$failed" -eq 1 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "Some commits do not follow Conventional Commits format."
|
||||||
|
echo "Expected: <type>[scope][!]: <description>"
|
||||||
|
echo "See: https://www.conventionalcommits.org/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "All commits follow Conventional Commits format."
|
||||||
|
|
||||||
|
build-and-test:
|
||||||
|
name: Build & test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "22"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Check formatting
|
||||||
|
run: npx prettier --check .
|
||||||
|
|
||||||
|
- name: Typecheck
|
||||||
|
run: npx tsc --noEmit
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: npm test
|
||||||
41
.github/workflows/release.yml
vendored
Normal file
41
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*"
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
release:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: "22"
|
||||||
|
registry-url: "https://registry.npmjs.org"
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: npm run build
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: npm test
|
||||||
|
|
||||||
|
- name: Publish to npm
|
||||||
|
run: npm publish
|
||||||
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
|
||||||
|
- name: GitHub Release
|
||||||
|
uses: softprops/action-gh-release@v2
|
||||||
|
with:
|
||||||
|
generate_release_notes: true
|
||||||
24
.gitignore
vendored
24
.gitignore
vendored
|
|
@ -2,5 +2,27 @@ node_modules/
|
||||||
build/
|
build/
|
||||||
coverage/
|
coverage/
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
.env
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# OS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
desktop.ini
|
||||||
|
|
||||||
|
# Temp
|
||||||
|
/tmp/
|
||||||
|
*.tmp
|
||||||
|
|
||||||
|
# Lefthook
|
||||||
|
lefthook-local.yml
|
||||||
|
.lefthookrc.local
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
|
|
||||||
64
CONTRIBUTING.md
Normal file
64
CONTRIBUTING.md
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
# Contributing to torrentclaw-mcp
|
||||||
|
|
||||||
|
Thanks for your interest in contributing! Here's how you can help.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
1. Fork the repository
|
||||||
|
2. Clone your fork: `git clone https://github.com/<your-user>/torrentclaw-mcp.git`
|
||||||
|
3. Install dev tools and git hooks:
|
||||||
|
```bash
|
||||||
|
make install-tools
|
||||||
|
make hooks
|
||||||
|
```
|
||||||
|
4. Create a branch: `git checkout -b feat/my-feature`
|
||||||
|
5. Make your changes
|
||||||
|
6. Test locally: `make build && make test`
|
||||||
|
7. Commit with a clear message (see below) — the commit-msg hook will validate the format
|
||||||
|
8. Push and open a Pull Request
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Node.js 18+
|
||||||
|
- npm
|
||||||
|
- [lefthook](https://github.com/evilmartians/lefthook) (installed via `make install-tools`)
|
||||||
|
|
||||||
|
## Commit Messages
|
||||||
|
|
||||||
|
Commits are validated automatically by a git hook. We follow [Conventional Commits](https://www.conventionalcommits.org/):
|
||||||
|
|
||||||
|
```
|
||||||
|
<type>[optional scope][!]: <description>
|
||||||
|
```
|
||||||
|
|
||||||
|
Valid types: `feat`, `fix`, `docs`, `style`, `refactor`, `perf`, `test`, `build`, `ci`, `chore`, `revert`
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```
|
||||||
|
feat: add new audio codec detection
|
||||||
|
fix(scanner): correct HDR10 detection for MKV files
|
||||||
|
docs: update README examples
|
||||||
|
refactor: simplify piece selection logic
|
||||||
|
feat!: redesign output format
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code Style
|
||||||
|
|
||||||
|
- Run `npx prettier --write .` before committing (or `make fmt`)
|
||||||
|
- TypeScript strict mode is enabled
|
||||||
|
- Keep functions focused and small
|
||||||
|
- Add comments only where the logic isn't self-evident
|
||||||
|
|
||||||
|
## Reporting Bugs
|
||||||
|
|
||||||
|
Open an issue with:
|
||||||
|
|
||||||
|
- What you expected to happen
|
||||||
|
- What actually happened
|
||||||
|
- Steps to reproduce
|
||||||
|
- Your Node.js version and OS
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
By contributing, you agree that your contributions will be licensed under the project's [MIT License](LICENSE).
|
||||||
34
Makefile
Normal file
34
Makefile
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
.PHONY: build test fmt lint typecheck version version-next release install-tools hooks clean
|
||||||
|
|
||||||
|
build:
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
test:
|
||||||
|
npm test
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
npx prettier --write .
|
||||||
|
|
||||||
|
typecheck:
|
||||||
|
npx tsc --noEmit
|
||||||
|
|
||||||
|
lint: fmt typecheck
|
||||||
|
|
||||||
|
version:
|
||||||
|
@node -p "require('./package.json').version"
|
||||||
|
|
||||||
|
version-next:
|
||||||
|
@echo "Use: npm version [patch|minor|major] --no-git-tag-version"
|
||||||
|
|
||||||
|
release:
|
||||||
|
@echo "Use: npm version <patch|minor|major>, then git push origin v<version>"
|
||||||
|
|
||||||
|
install-tools:
|
||||||
|
npm install
|
||||||
|
@command -v lefthook >/dev/null 2>&1 || npm install -g lefthook
|
||||||
|
|
||||||
|
hooks:
|
||||||
|
lefthook install
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf build coverage
|
||||||
108
README.md
108
README.md
|
|
@ -1,6 +1,13 @@
|
||||||
# torrentclaw-mcp
|
# torrentclaw-mcp
|
||||||
|
|
||||||
MCP server for [TorrentClaw](https://torrentclaw.com) — search movies and TV shows with torrent download options, streaming availability, and metadata.
|
[](https://www.npmjs.com/package/torrentclaw-mcp)
|
||||||
|
[](LICENSE)
|
||||||
|
[](https://github.com/torrentclaw/torrentclaw-mcp/actions/workflows/ci.yml)
|
||||||
|
[](https://nodejs.org)
|
||||||
|
|
||||||
|
[Model Context Protocol](https://modelcontextprotocol.io/) server for [TorrentClaw](https://torrentclaw.com) — giving AI assistants the ability to search movies and TV shows, find torrents with magnet links, check streaming availability, and explore cast/crew metadata.
|
||||||
|
|
||||||
|
torrentclaw-mcp is developed by [TorrentClaw](https://torrentclaw.com) as part of its open-source ecosystem. It wraps the TorrentClaw API into the MCP standard so that any compatible AI assistant (Claude, GPT, etc.) can access the platform's search and discovery features natively.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
|
|
@ -8,26 +15,32 @@ MCP server for [TorrentClaw](https://torrentclaw.com) — search movies and TV s
|
||||||
npx torrentclaw-mcp
|
npx torrentclaw-mcp
|
||||||
```
|
```
|
||||||
|
|
||||||
No API key required.
|
No API key required (optional for higher rate limits).
|
||||||
|
|
||||||
## Available Tools
|
## What can it do?
|
||||||
|
|
||||||
|
### Tools
|
||||||
|
|
||||||
| Tool | Description |
|
| Tool | Description |
|
||||||
| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `search_content` | Search movies/shows with filters (query, type, genre, year, rating, quality, language, sort). Returns content with torrents and magnet links. |
|
| `search_content` | Search movies/shows with filters (query, type, genre, year, rating, quality, language, audio, HDR, season, episode, sort). Returns torrents, magnet links, and optional streaming info. |
|
||||||
|
| `autocomplete` | Type-ahead search suggestions (up to 8 results). Use to validate titles before a full search. |
|
||||||
| `get_popular` | Get popular content ranked by user clicks |
|
| `get_popular` | Get popular content ranked by user clicks |
|
||||||
| `get_recent` | Get recently added content |
|
| `get_recent` | Get recently added content |
|
||||||
| `get_watch_providers` | Streaming availability by country (Netflix, Disney+, etc.) |
|
| `get_watch_providers` | Streaming availability by country (Netflix, Disney+, etc.) |
|
||||||
| `get_credits` | Cast and director for a title |
|
| `get_credits` | Cast and director for a title |
|
||||||
| `get_torrent_url` | Get .torrent file download URL from info hash |
|
| `get_torrent_url` | Get .torrent file download URL from info hash |
|
||||||
|
| `track_interaction` | Track user interaction with a torrent (magnet click, download, copy) |
|
||||||
|
| `submit_scan_request` | Submit a torrent for audio/video quality analysis via [TrueSpec](https://github.com/torrentclaw/truespec) |
|
||||||
|
| `get_scan_status` | Check the status of a torrent scan request |
|
||||||
|
|
||||||
## Resources
|
### Resources
|
||||||
|
|
||||||
| URI | Description |
|
| URI | Description |
|
||||||
| --------------------- | ----------------------------------------------------- |
|
| --------------------- | ----------------------------------------------------- |
|
||||||
| `torrentclaw://stats` | Catalog statistics (content/torrent counts by source) |
|
| `torrentclaw://stats` | Catalog statistics (content/torrent counts by source) |
|
||||||
|
|
||||||
## Prompts
|
### Prompts
|
||||||
|
|
||||||
| Prompt | Description |
|
| Prompt | Description |
|
||||||
| ---------------- | -------------------------------------------------------- |
|
| ---------------- | -------------------------------------------------------- |
|
||||||
|
|
@ -68,39 +81,56 @@ Add to `.mcp.json` or `~/.claude/settings.json`:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Self-hosted
|
### Environment Variables
|
||||||
|
|
||||||
Point to your own TorrentClaw instance:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"mcpServers": {
|
|
||||||
"torrentclaw": {
|
|
||||||
"command": "npx",
|
|
||||||
"args": ["-y", "torrentclaw-mcp"],
|
|
||||||
"env": {
|
|
||||||
"TORRENTCLAW_API_URL": "http://localhost:3030",
|
|
||||||
"TORRENTCLAW_ALLOW_PRIVATE": "true"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## Environment Variables
|
|
||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
| --------------------------- | ------------------------- | ---------------------------------------------------------------------- |
|
| --------------------- | ------------------------- | -------------------------------------------------------------- |
|
||||||
| `TORRENTCLAW_API_URL` | `https://torrentclaw.com` | Base URL of the TorrentClaw API |
|
| `TORRENTCLAW_API_URL` | `https://torrentclaw.com` | Base URL of the TorrentClaw API |
|
||||||
| `TORRENTCLAW_ALLOW_PRIVATE` | `false` | Set to `true` to allow private/localhost URLs (for self-hosted setups) |
|
| `TORRENTCLAW_API_KEY` | _(none)_ | Optional API key for authenticated access (higher rate limits) |
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
.
|
||||||
|
├── src/
|
||||||
|
│ ├── index.ts # MCP server entry point
|
||||||
|
│ ├── config.ts # Configuration & URL validation
|
||||||
|
│ ├── api-client.ts # TorrentClaw API client with caching
|
||||||
|
│ ├── types.ts # TypeScript interfaces for API responses
|
||||||
|
│ ├── prompts.ts # MCP prompt definitions
|
||||||
|
│ ├── tools/ # MCP tool implementations
|
||||||
|
│ │ ├── search-content.ts
|
||||||
|
│ │ ├── autocomplete.ts
|
||||||
|
│ │ ├── get-popular.ts
|
||||||
|
│ │ ├── get-recent.ts
|
||||||
|
│ │ ├── get-watch-providers.ts
|
||||||
|
│ │ ├── get-credits.ts
|
||||||
|
│ │ ├── get-torrent-url.ts
|
||||||
|
│ │ ├── track-interaction.ts
|
||||||
|
│ │ └── scan-request.ts
|
||||||
|
│ ├── formatters/ # Output formatting
|
||||||
|
│ │ ├── content.ts
|
||||||
|
│ │ ├── providers.ts
|
||||||
|
│ │ └── credits.ts
|
||||||
|
│ └── resources/ # MCP resources
|
||||||
|
│ └── stats.ts
|
||||||
|
├── tests/ # Test suite (vitest)
|
||||||
|
├── .github/workflows/ # CI/CD (lint, build, test, release)
|
||||||
|
├── lefthook.yml # Git hooks (commit lint, prettier, tsc)
|
||||||
|
├── Makefile # Dev workflow (build, test, lint, fmt)
|
||||||
|
├── CONTRIBUTING.md # Contribution guidelines
|
||||||
|
├── LICENSE # MIT
|
||||||
|
└── README.md
|
||||||
|
```
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/buryni/torrentclaw-mcp.git
|
git clone https://github.com/torrentclaw/torrentclaw-mcp.git
|
||||||
cd torrentclaw-mcp
|
cd torrentclaw-mcp
|
||||||
npm install
|
make install-tools
|
||||||
npm run build
|
make hooks
|
||||||
|
make build && make test
|
||||||
```
|
```
|
||||||
|
|
||||||
Test with MCP Inspector:
|
Test with MCP Inspector:
|
||||||
|
|
@ -109,12 +139,16 @@ Test with MCP Inspector:
|
||||||
npx @modelcontextprotocol/inspector node build/index.js
|
npx @modelcontextprotocol/inspector node build/index.js
|
||||||
```
|
```
|
||||||
|
|
||||||
Run tests:
|
## About TorrentClaw
|
||||||
|
|
||||||
```bash
|
[TorrentClaw](https://torrentclaw.com) is an open platform focused on improving the quality and reliability of torrent metadata. Our mission is to make torrent search engines more accurate and the torrent ecosystem healthier — by building tools that verify, enrich, and standardize metadata across the network.
|
||||||
npm test
|
|
||||||
```
|
torrentclaw-mcp is part of the TorrentClaw open-source ecosystem, alongside [TrueSpec](https://github.com/torrentclaw/truespec) (torrent metadata verification).
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT
|
MIT License — see [LICENSE](LICENSE) for details.
|
||||||
|
|
|
||||||
36
lefthook.yml
Normal file
36
lefthook.yml
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
commit-msg:
|
||||||
|
commands:
|
||||||
|
validate:
|
||||||
|
run: |
|
||||||
|
msg=$(head -1 {1})
|
||||||
|
if ! echo "$msg" | grep -qE '^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?(!)?: .{1,}$'; then
|
||||||
|
echo ""
|
||||||
|
echo "ERROR: Invalid commit message format."
|
||||||
|
echo ""
|
||||||
|
echo " Got: $msg"
|
||||||
|
echo ""
|
||||||
|
echo " Expected: <type>[optional scope][!]: <description>"
|
||||||
|
echo ""
|
||||||
|
echo " Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert"
|
||||||
|
echo " Examples:"
|
||||||
|
echo " feat: add new audio codec detection"
|
||||||
|
echo " fix(scanner): correct HDR10 detection for MKV files"
|
||||||
|
echo " feat!: redesign output format"
|
||||||
|
echo ""
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
pre-commit:
|
||||||
|
parallel: true
|
||||||
|
commands:
|
||||||
|
prettier:
|
||||||
|
glob: "*.{ts,js,json,md,yml,yaml}"
|
||||||
|
run: npx prettier --check {staged_files}
|
||||||
|
typecheck:
|
||||||
|
glob: "*.ts"
|
||||||
|
run: npx tsc --noEmit
|
||||||
|
|
||||||
|
pre-push:
|
||||||
|
commands:
|
||||||
|
test:
|
||||||
|
run: npm test
|
||||||
10
package.json
10
package.json
|
|
@ -15,6 +15,8 @@
|
||||||
"dev": "tsx src/index.ts",
|
"dev": "tsx src/index.ts",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
"test:watch": "vitest",
|
"test:watch": "vitest",
|
||||||
|
"fmt": "prettier --write .",
|
||||||
|
"fmt:check": "prettier --check .",
|
||||||
"lint": "tsc --noEmit",
|
"lint": "tsc --noEmit",
|
||||||
"prepublishOnly": "npm run build"
|
"prepublishOnly": "npm run build"
|
||||||
},
|
},
|
||||||
|
|
@ -35,11 +37,15 @@
|
||||||
"agent",
|
"agent",
|
||||||
"media"
|
"media"
|
||||||
],
|
],
|
||||||
"author": "buryni",
|
"author": "TorrentClaw (https://torrentclaw.com)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/buryni/torrentclaw-mcp"
|
"url": "https://github.com/torrentclaw/torrentclaw-mcp"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/torrentclaw/torrentclaw-mcp#readme",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/torrentclaw/torrentclaw-mcp/issues"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0.0"
|
"node": ">=18.0.0"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue