Metadata-Version: 2.5
Name: oss-contribution-advisor-mcp
Version: 0.1.0
Summary: MCP server that helps developers find open-source issues worth contributing to — semantic issue search, repo health scoring, and downstream impact ranking.
Project-URL: Homepage, https://github.com/sonali1103/oss-contribution-advisor-mcp
Project-URL: Repository, https://github.com/sonali1103/oss-contribution-advisor-mcp
Author: Sonali
License: MIT
Keywords: agentic-ai,github,mcp,model-context-protocol,open-source
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Requires-Dist: fastmcp>=2.0.0
Requires-Dist: numpy>=1.26.0
Requires-Dist: requests>=2.31.0
Requires-Dist: sentence-transformers>=2.7.0
Description-Content-Type: text/markdown

# OSS Contribution Advisor — MCP Server

An MCP server that helps developers find open-source issues genuinely worth
contributing to — not just issues tagged "good first issue," but ones that
match their interests, come from a healthy/responsive repo, and have real
downstream impact.

## Why this exists

Existing "find your first OSS issue" tools filter by label only. This server
answers three questions a label can't:

1. **Does this match what I actually want to work on?** — semantic search
   over open issues (local sentence-embeddings), not keyword/label matching.
2. **Is this repo actually a good place to spend my time?** — health score
   based on maintainer responsiveness and first-time-contributor merge rate.
3. **Does this repo matter?** — ranks by *real* downstream reach via
   [libraries.io](https://libraries.io)'s dependents graph (how many other
   packages depend on this one) — not just GitHub stars.

## Tools

| Tool | Purpose |
|---|---|
| `match_issues_semantically` | Free-text interest → ranked list of matching open issues, using local sentence-embeddings. |
| `score_repo_fit` | Given a repo, scores maintainer responsiveness, PR merge rate, doc completeness, and recent activity into a 0-100 fit score. |
| `find_impact_multiplier_repos` | Ranks a given repo shortlist — or self-searches by language if none given — by real downstream dependents (libraries.io), falling back to a stars/forks proxy if unconfigured. |


## Caching design

Two genuinely different cache policies, because the underlying data has two
different change patterns — using one TTL for everything would either waste
API calls (too short) or serve stale data (too long):

| Cache | Key | Lifetime | Why |
|---|---|---|---|
| **Search results** (`match_issues_semantically`) | GitHub search query string | 20 min TTL | Open issues genuinely change often, but repeated calls in a short window shouldn't re-hit the API. |
| **Issue embeddings** (`match_issues_semantically`) | `(issue_id, updated_at)` | No TTL — invalidated by `updated_at` changing | Unedited issue text is embedded exactly **once**, ever, and reused across every user/query that pulls it into their candidate pool. If the issue is edited, `updated_at` changes, so the cache key changes and it's naturally recomputed — no manual invalidation logic needed. |
| **Repo impact data** (`find_impact_multiplier_repos`) | repo `full_name` | 24h TTL | Dependents counts / stars change slowly; no need to hit libraries.io or GitHub on every call. |

All caching is a single local SQLite file (`~/.cache/oss-contribution-advisor-mcp/cache.sqlite3` by default, override with `CACHE_DB_PATH`) — no external cache service required, so the server stays a single downloadable package.

## libraries.io integration (Tool 3)

GitHub's API only exposes stars/forks — social proof, not real usage.
[libraries.io](https://libraries.io) aggregates package metadata across ~30
registries (PyPI, npm, crates.io, RubyGems, etc.) and tracks, for each
published package, how many **other** packages declare it as a dependency.

`find_impact_multiplier_repos` calls
`GET https://libraries.io/api/github/{owner}/{repo}/projects` to find every
package linked to a GitHub repo and sums their `dependents_count`. A repo
with modest stars can still be a load-bearing dependency for tens of
thousands of other packages — that's a stronger "does my fix matter" signal
than stars, and libraries.io is the only free source for it.

If `LIBRARIES_IO_API_KEY` is unset, or a repo isn't published to any
registry (e.g. it's an app, not a library), the tool degrades gracefully to
a GitHub stars/forks proxy rather than failing — every result includes a
`signal_source` field so it's clear which one was used.

Get a free key at **https://libraries.io/api** (60 req/min).

## Setup

```bash
git clone https://github.com/sonali1103/oss-contribution-advisor-mcp
cd oss-contribution-advisor-mcp
python -m venv .venv && source .venv/bin/activate
pip install -e .
cp .env.example .env   # add GITHUB_TOKEN and LIBRARIES_IO_API_KEY
```

## Running

**As an HTTP-streamable server (default — for remote hosting):**
```bash
oss-contribution-advisor-mcp
# or: python -m oss_contribution_advisor.server
# serves on http://0.0.0.0:8000 by default (override with MCP_PORT)
```

**Over stdio (for local Claude Desktop use):**
```bash
MCP_TRANSPORT=stdio oss-contribution-advisor-mcp
# or: fastmcp run -m oss_contribution_advisor.server
```

## Connect to Claude Desktop (stdio)

```json
{
  "mcpServers": {
    "oss-contribution-advisor": {
      "command": "oss-contribution-advisor-mcp",
      "env": { "MCP_TRANSPORT": "stdio" }
    }
  }
}
```

## Connect to a remote HTTP deployment

Once deployed (see below), point any MCP-HTTP-capable client at:
```
https://<your-deployment-url>/mcp
```

## Deploying

**PyPI:**
```bash
pip install build twine
python -m build
twine upload dist/*
# then anyone can: pip install oss-contribution-advisor-mcp
```

**FastMCP Cloud:** connect this GitHub repo directly at
[fastmcp.cloud](https://fastmcp.cloud) — it detects `pyproject.toml` and
`src/oss_contribution_advisor/server.py` and deploys it as an HTTP-streamable
server automatically. Set `GITHUB_TOKEN` and `LIBRARIES_IO_API_KEY` as
environment variables in the deployment dashboard.

## Example queries to try

- *"I'm a Python developer who likes async code and API design — find me an issue to work on."*
  → chains `match_issues_semantically` → `score_repo_fit` on the surfaced repos
- *"Is `encode/httpx` a good repo for a first-time contributor?"*
  → calls `score_repo_fit` directly
- *"Between httpx, django, and fastapi, which has the most real-world reach?"*
  → calls `find_impact_multiplier_repos` with `candidate_repos`
- *"Give me high-impact Python repos to contribute to."*
  → calls `find_impact_multiplier_repos` with `language="python"` (self-search mode)

## Known simplifications

Built as a scoped demo project, not a production tool at scale:

- **Merge rate** in `score_repo_fit` is computed over a sample of recently
  closed PRs, not strictly filtered to first-time contributors (that needs
  a per-author commit-history lookup per PR — expensive for a 30-PR sample).
- **SQLite cache** is fine for a single-process server; a multi-instance
  deployment would want Redis/Postgres instead to share cache state.
- **No auth on the HTTP endpoint** — fine for a personal/demo deployment,
  add an API key or OAuth layer before exposing this publicly at scale.

## Stack

- [fastmcp](https://github.com/jlowin/fastmcp) — MCP server framework (stdio + HTTP-streamable transport)
- `sentence-transformers` (`all-MiniLM-L6-v2`) — local embeddings, no API key needed
- GitHub REST API — live issue/repo data
- [libraries.io API](https://libraries.io/api) — downstream dependents data
- SQLite — local caching layer
