Metadata-Version: 2.5
Name: fetchnode
Version: 0.5.1
Summary: Official Django and Python client SDK for FetchNode monitoring
Project-URL: Homepage, https://fetch-node.com
Project-URL: Documentation, https://fetch-node.com/guide/
Project-URL: Repository, https://github.com/remcovanwijk040/fetchnode
Project-URL: Issues, https://github.com/remcovanwijk040/fetchnode/issues
Project-URL: Changelog, https://pypi.org/project/fetchnode/0.5.1/#sdk-changelog
Author-email: Remco van Wijk <remcovanwijk040@users.noreply.github.com>
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Framework :: Django :: 4.2
Classifier: Framework :: Django :: 5.0
Classifier: Framework :: Django :: 5.1
Classifier: Framework :: Django :: 5.2
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Monitoring
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: django>=4.2
Provides-Extra: celery
Requires-Dist: celery>=5.0; extra == 'celery'
Description-Content-Type: text/markdown

# FetchNode Python & Django SDK

[![PyPI version](https://img.shields.io/pypi/v/fetchnode.svg)](https://pypi.org/project/fetchnode/)
[![Python Versions](https://img.shields.io/pypi/pyversions/fetchnode.svg)](https://pypi.org/project/fetchnode/)
[![Django Versions](https://img.shields.io/badge/django-4.2%20%7C%205.0%20%7C%205.1%20%7C%205.2-blue.svg)](https://www.djangoproject.com/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Typing: Typed](https://img.shields.io/badge/typing-typed-green.svg)](https://peps.python.org/pep-0561/)

Official Python and Django client SDK for [FetchNode](https://fetch-node.com) — the focused operations workspace for developers and teams managing multiple production Django websites.

FetchNode captures unhandled exceptions, error logs, slow database queries, N+1 query patterns, Celery background tasks, and authoritative business conversions with zero bloat and privacy-safe defaults.

---

## Table of Contents

- [Installation](#installation)
- [Quickstart (Django)](#quickstart-django)
- [Configuration Options](#configuration-options)
- [Telemetry & Usage](#telemetry--usage)
  - [Conversion & Lead Tracking](#conversion--lead-tracking)
  - [Automatic Error Monitoring](#automatic-error-monitoring)
  - [Manual Exception Capture](#manual-exception-capture)
  - [Celery Job Monitoring](#celery-job-monitoring)
  - [Logging Handler](#logging-handler)
- [Model Context Protocol (MCP) for AI Agents](#model-context-protocol-mcp-for-ai-agents)
- [Privacy & Security Defaults](#privacy--security-defaults)

- [Testing in Development](#testing-in-development)
- [Compatibility](#compatibility)
- [Links & Resources](#links--resources)
- [License](#license)

---

## Installation

Version 0.5.1 adds error triage, performance bottlenecks, and SEO optimization to the Model Context Protocol (MCP) server.
See the [SDK changelog](#sdk-changelog) for changes and upgrade instructions.

Install via `pip`:

```bash
pip install fetchnode
```

Or using `uv`:

```bash
uv add fetchnode
```

*(For Celery support, you can optionally install `fetchnode[celery]`)*

---

## Quickstart (Django)

### 1. Add to `INSTALLED_APPS`

In your Django `settings.py`:

```python
INSTALLED_APPS = [
    # ...
    "fetchnode",
]
```

### 2. Add the Middleware

Add `FetchNodeMiddleware` near the top of your `MIDDLEWARE` list for comprehensive request, query, and exception coverage:

```python
MIDDLEWARE = [
    "fetchnode.middleware.FetchNodeMiddleware",
    "django.middleware.security.SecurityMiddleware",
    # ...
]
```

### 3. Configure `settings.FETCHNODE`

```python
import os

FETCHNODE = {
    "API_KEY": os.environ.get("FETCHNODE_API_KEY", ""),
    "API_URL": "https://fetch-node.com/api/events/ingest/",
    "ENVIRONMENT": "production",  # e.g. "production", "staging"
}
```

Set `FETCHNODE_API_KEY` to your private server key in the deployment environment. Keep it out of source control and browser code. Restart or redeploy Django, then verify a request and test error in FetchNode.

Django will automatically initialize FetchNode upon startup and capture unhandled exceptions, slow queries, and request telemetry.

---

## Configuration Options

Configure via `settings.FETCHNODE` or environment variables:

| Setting Key | Environment Variable | Default | Description |
| :--- | :--- | :--- | :--- |
| `API_KEY` | `FETCHNODE_API_KEY` | `""` | **Required.** Your private server key from project settings. Never use a public browser key here. |
| `ENDPOINT` / `API_URL` | `FETCHNODE_ENDPOINT` | `https://fetch-node.com/api/events/ingest/` | Processing server URL. Point to your self-hosted instance if applicable. |
| `ENVIRONMENT` | `FETCHNODE_ENVIRONMENT` | `"development"` | Active environment name (`"production"`, `"staging"`). |
| `RELEASE` | `FETCHNODE_RELEASE` | `""` | Release tag or git commit hash (e.g. `git rev-parse HEAD`). |
| `ENABLED` | `FETCHNODE_ENABLED` | `True` if API_KEY present | Master toggle for event sending. |
| `CAPTURE_TRANSACTIONS` | — | `True` | Track request duration and database query counts. |
| `CAPTURE_BODY` | — | `False` | Privacy safeguard: request bodies are excluded by default. |
| `CAPTURE_HEADERS` | — | `False` | Privacy safeguard: request headers are excluded by default. |
| `QUERY_SLOW_THRESHOLD_MS` | — | `100` | Minimum execution time (ms) to flag an ORM query as slow. |
| `N_PLUS_ONE_THRESHOLD` | — | `5` | Identical SELECT query repetition threshold to flag N+1 issues. |
| `SENSITIVE_KEYS` | — | *(built-in list)* | Extra field names to scrub from payloads (additive). |

---

## Telemetry & Usage

### Conversion & Lead Tracking

Track authoritative business events server-side (form submissions, payments, lead captures) with automatic session and visitor cookie attribution:

```python
import fetchnode

def contact_view(request):
    form = ContactForm(request.POST)
    if form.is_valid():
        lead = form.save()

        # Track authoritative conversion
        fetchnode.track(
            "lead_submitted",
            request=request,
            idempotency_key=f"lead:{lead.id}",
            properties={"source": "contact_form"},
            conversion={"display_name": "Lead submitted", "funnel_order": 1, "primary": True},
        )
        return redirect("thank_you")
```

**Why `idempotency_key` matters:** Providing an `idempotency_key` (such as the database record ID or payment provider ID) ensures that retried requests, webhook replays, or browser reloads do not inflate your conversion metrics. FetchNode securely hashes the key client-side to produce a deterministic event ID.

### Automatic Error Monitoring

Unhandled exceptions in Django views are caught by `FetchNodeMiddleware`, decorated with:
* The exact failing line of code and stack trace.
* In-app vs. framework/library frame classification.
* Database query count and execution time during the failing request.
* Correlated request ID and trace ID.

### Manual Exception Capture

Capture handled exceptions or background exceptions:

```python
import fetchnode

try:
    external_service_call()
except ThirdPartyAPIError as exc:
    fetchnode.capture_exception(exc, tags={"provider": "stripe"})
```

### Celery Job Monitoring

FetchNode automatically instruments Celery when installed. You can also explicitly decorate tasks:

```python
from fetchnode import capture_job

@capture_job(name="sync_external_inventory")
def sync_inventory():
    ...
```

### Logging Handler

Send standard `logging.ERROR` and `logging.CRITICAL` records to FetchNode:

```python
LOGGING = {
    "version": 1,
    "disable_existing_loggers": False,
    "handlers": {
        "fetchnode": {
            "level": "ERROR",
            "class": "fetchnode.handlers.FetchNodeHandler",
        },
    },
    "loggers": {
        "django": {
            "handlers": ["fetchnode"],
            "level": "ERROR",
            "propagate": True,
        },
    },
}
```

---

## Model Context Protocol (MCP) for AI Agents

FetchNode includes a native Model Context Protocol (MCP) server. When pair programming or maintaining websites with AI agents (Claude Desktop, Cursor, Windsurf, Cline, or Python agents), your agents can query live Google Search Console rankings and technical error health directly:

```bash
python manage.py fetchnode_mcp --setup
```

This single command configures your editor agent and automatically documents the available tools in `AGENTS.md` / `CLAUDE.md`.

### Available MCP Tools

* **`get_seo_overview`**: Organic clicks, search views, CTR, average position, and period changes.
* **`get_keyword_opportunities`**: High-potential striking-distance queries (positions 4–20), low-CTR terms, and zero-click keywords.
* **`get_page_performance`**: Landing page traffic, conversions, conversion rate, and driving queries.
* **`get_declining_pages`**: Landing pages and search queries losing organic Google clicks.
* **`get_technical_seo_health`**: Open 500 server errors and 404s affecting landing paths.

### In-Code Python Usage

You can also query MCP tools directly in Python (e.g. within Celery tasks, LangChain, CrewAI, or autonomous scripts):

```python
from fetchnode.mcp import get_seo_overview, get_keyword_opportunities

overview = get_seo_overview(period_days=28)
opportunities = get_keyword_opportunities(category="striking_distance")
```

---

## Privacy & Security Defaults


FetchNode is engineered with a strict **privacy-first architecture**:
1. **Client-side Scrubbing:** Sensitive keys (`password`, `token`, `secret`, `api_key`, `authorization`, `cookie`, `csrfmiddlewaretoken`) and any compound keys like `user_password` or `client_secret` are scrubbed before payload transmission.
2. **Safe SQL Normalization:** Raw SQL text is stripped of literals and parameters (`SELECT * FROM user WHERE id = 123` becomes `SELECT * FROM user WHERE id = ?`).
3. **No Unintentional PII:** Request bodies, query strings, and raw IP addresses are excluded by default.
4. **Inspectable & Lightweight:** The entire client is open-source Python with zero compiled binaries and zero unnecessary dependencies.

---

## Testing in Development

In your local test suite (e.g. `pytest` or `python manage.py test`), FetchNode can be disabled by omitting the API key or explicitly setting:

```python
# settings_test.py
FETCHNODE = {
    "ENABLED": False,
}
```

To test that event transmission works in your staging environment, run:

```python
import fetchnode
fetchnode.capture_message("FetchNode verification ping", level="info")
fetchnode.flush()
```

---

## Compatibility

- **Python:** 3.10, 3.11, 3.12, 3.13, 3.14
- **Django:** 4.2 LTS, 5.0, 5.1, 5.2
- **Operating Systems:** Linux, macOS, Windows

---

## Links & Resources

- **Website & Cloud App:** [fetchnode.com](https://fetch-node.com)
- **Documentation & Setup Guide:** [fetchnode.com/guide/](https://fetch-node.com/guide/)
- **Changelog:** [fetchnode.com/changelog/](https://fetch-node.com/changelog/)
- **GitHub Repository:** [github.com/remcovanwijk040/fetchnode](https://github.com/remcovanwijk040/fetchnode)
- **Issue Tracker:** [github.com/remcovanwijk040/fetchnode/issues](https://github.com/remcovanwijk040/fetchnode/issues)

---

## License

MIT License. See [LICENSE](LICENSE) for details.


# SDK changelog

## 0.5.1 — 2026-10-16

### Added

- Error management MCP tools: `list_errors`, `get_error_details`, `resolve_error`, and `ignore_error` (with feedback and snooze support).
- Performance bottleneck analysis MCP tool: `get_performance_bottlenecks` analyzing p95 latency, DB overhead %, N+1 query patterns, and actionable Django recommendations.
- Actionable SEO advice MCP tool: `get_seo_optimization_advice` providing prioritized actions for striking-distance keywords, CTR optimization, and declining pages.
- Standard MCP resources and prompts for error triage, performance bottlenecks, and SEO audits.
- Python SDK helpers in `fetchnode.mcp`.

### Upgrade

```bash
python -m pip install --upgrade fetchnode==0.5.1
```

## 0.5.0 — 2026-10-16

### Added

- Model Context Protocol (MCP) support for AI coding agents (Cursor, Windsurf, Claude Desktop, Cline).
- Django management command `python manage.py fetchnode_mcp` with `--setup [all|cursor|windsurf|cline|claude]`, `--print-config`, `--remote`, and `--status/--test`.
- Automatic guideline documentation injection into repository agent prompt files (`AGENTS.md`, `CLAUDE.md`, `.cursorrules`).
- Direct Python SDK helper functions in `fetchnode.mcp` and `fetchnode_client.mcp` (`get_seo_overview`, `get_keyword_opportunities`, `get_page_performance`, `get_declining_pages`, `get_technical_seo_health`).
- Stdio-to-remote JSON-RPC runner (`fetchnode.mcp.run_stdio_server`).

### Upgrade

```bash
python -m pip install --upgrade fetchnode==0.5.0
```

## 0.4.3 — 2026-09-29

### Fixed

- Use `https://fetch-node.com/api/events/ingest/` as the default ingest endpoint.
- Let Django automatically discover the SDK AppConfig when `fetchnode` is in
  `INSTALLED_APPS`, so startup installs logging and enabled instrumentation.
- Preserve automatic AppConfig discovery for the legacy `fetchnode_client` name.
- Correct the documentation URLs to the active FetchNode website.

### Documentation

- Configure the private server key through `FETCHNODE_API_KEY` and supply an
  explicit ingest URL. Keep private keys out of browser code and source control.
- Show explicit server conversion declarations and non-personal event properties.
- Verify reception after restarting or redeploying Django.

### Release checks

- Test the installed wheel outside the repository, including Django AppConfig and
  automatic logging setup.
- Exercise requests, exceptions, error logs and idempotent conversions against a
  local FetchNode collector, with project isolation checks.
- Check distribution metadata and the release tag before uploading to PyPI.

### Upgrade

```bash
python -m pip install --upgrade fetchnode==0.4.3
```

Update your dependency file or lockfile, restart or redeploy Django, and verify a
request and test error in FetchNode. Existing installations can set `API_URL`
explicitly if they use their own collector.
