revnuvo-intel 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- revnuvo_intel-0.1.0/PKG-INFO +123 -0
- revnuvo_intel-0.1.0/README.md +104 -0
- revnuvo_intel-0.1.0/pyproject.toml +36 -0
- revnuvo_intel-0.1.0/setup.cfg +4 -0
- revnuvo_intel-0.1.0/src/revnuvo_intel/__init__.py +196 -0
- revnuvo_intel-0.1.0/src/revnuvo_intel.egg-info/PKG-INFO +123 -0
- revnuvo_intel-0.1.0/src/revnuvo_intel.egg-info/SOURCES.txt +8 -0
- revnuvo_intel-0.1.0/src/revnuvo_intel.egg-info/dependency_links.txt +1 -0
- revnuvo_intel-0.1.0/src/revnuvo_intel.egg-info/entry_points.txt +2 -0
- revnuvo_intel-0.1.0/src/revnuvo_intel.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: revnuvo-intel
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Revnuvo Company Intelligence โ evidence-backed technology and infrastructure change signals for AI agents and developers. Free developer tier: 100 calls/month.
|
|
5
|
+
Author-email: Revnuvo <ismael@revnuvo.site>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://intel.revnuvo.site
|
|
8
|
+
Project-URL: Documentation, https://intel.revnuvo.site/docs/api
|
|
9
|
+
Project-URL: Repository, https://github.com/hardeyhemy/revnuvo-dev
|
|
10
|
+
Keywords: company-intelligence,technology-monitoring,mcp,model-context-protocol,ai-agents,x402,signals,sales-intelligence,change-detection,revnuvo
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: >=3.9
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# revnuvo
|
|
21
|
+
|
|
22
|
+
**Give AI agents live intelligence about companies.**
|
|
23
|
+
|
|
24
|
+
Official JavaScript SDK for the [Revnuvo Company Intelligence API](https://intel.revnuvo.site). Revnuvo observes company websites, technologies, DNS and infrastructure over time, detects meaningful changes, and returns **evidence-backed, machine-readable intelligence** โ timestamped, confidence-aware, never invented.
|
|
25
|
+
|
|
26
|
+
- ๐ **Free developer tier**: 100 intelligence calls/month (REST + MCP), no credit card โ [get a key](https://app.revnuvo.site)
|
|
27
|
+
- ๐ **MCP included**: one config line connects Claude/any MCP client โ [MCP docs](https://intel.revnuvo.site/docs/mcp)
|
|
28
|
+
- โก **Zero dependencies**, works in Node 18+, Bun, Deno, edge runtimes
|
|
29
|
+
- ๐ธ **x402 support**: agents without accounts pay per call in USDC on Base โ [x402 docs](https://intel.revnuvo.site/docs/x402)
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install revnuvo
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 60-second quickstart
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
import { Revnuvo } from "revnuvo";
|
|
41
|
+
|
|
42
|
+
const rv = new Revnuvo({ apiKey: process.env.REVNUVO_API_KEY });
|
|
43
|
+
|
|
44
|
+
// What technologies does this company use? (with evidence)
|
|
45
|
+
const techs = await rv.getCompanyTechnologies("hubspot.com");
|
|
46
|
+
console.log(techs.technologies);
|
|
47
|
+
// [{ name: "webflow", confidence: 0.85, evidence: "meta generator", ... }, ...]
|
|
48
|
+
|
|
49
|
+
// What changed at this company?
|
|
50
|
+
const changes = await rv.getCompanyChanges("stripe.com");
|
|
51
|
+
console.log(changes.changes);
|
|
52
|
+
|
|
53
|
+
// Which companies recently adopted Vue?
|
|
54
|
+
const signals = await rv.searchSignals({ technology: "vue", eventType: "technology_added" });
|
|
55
|
+
console.log(signals.signals);
|
|
56
|
+
// each signal: before/after state, evidence, confidence, signal_score, detected_at
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## The 9 canonical capabilities
|
|
60
|
+
|
|
61
|
+
| Method | Answers |
|
|
62
|
+
|---|---|
|
|
63
|
+
| `searchCompanies({query})` | Which companies does Revnuvo observe? |
|
|
64
|
+
| `getCompany(domain)` | What do we know about this company? |
|
|
65
|
+
| `getCompanyState(domain)` | Full current observed state (HTTP + techs + scripts + DNS) |
|
|
66
|
+
| `getCompanyTimeline(domain)` | How did their stack evolve? |
|
|
67
|
+
| `getCompanyTechnologies(domain)` | What technologies do they use? (evidence per tech) |
|
|
68
|
+
| `getCompanyChanges(domain)` | What changed and when? |
|
|
69
|
+
| `searchSignals({technology,...})` | Which companies recently adopted X? |
|
|
70
|
+
| `monitorCompany(domain)` | Watch this company for future changes |
|
|
71
|
+
| `verifyCompany(domain)` | What can be substantiated with evidence? |
|
|
72
|
+
|
|
73
|
+
Plus `whoami()` โ your key's identity and remaining quota.
|
|
74
|
+
|
|
75
|
+
## MCP (Claude, Cursor, any MCP client)
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
import { claudeDesktopConfig } from "revnuvo";
|
|
79
|
+
console.log(JSON.stringify(claudeDesktopConfig(process.env.REVNUVO_API_KEY), null, 2));
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Paste into `claude_desktop_config.json`, then ask Claude: *"What changed at stripe.com?"* โ full instructions: [intel.revnuvo.site/docs/mcp](https://intel.revnuvo.site/docs/mcp).
|
|
83
|
+
|
|
84
|
+
## CLI
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npx revnuvo whoami # key + quota
|
|
88
|
+
npx revnuvo tech hubspot.com # detected technologies + evidence
|
|
89
|
+
npx revnuvo changes stripe.com # observed changes
|
|
90
|
+
npx revnuvo monitor acme.com # start monitoring
|
|
91
|
+
npx revnuvo mcp-config --key ... # print MCP config
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Error handling
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
import { Revnuvo, RevnuvoError } from "revnuvo";
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
await rv.getCompanyState("example.com");
|
|
101
|
+
} catch (e) {
|
|
102
|
+
if (e instanceof RevnuvoError) {
|
|
103
|
+
e.status; // 401 bad key ยท 404 not_observed ยท 429 quota/rate limit ยท 402 plan limit
|
|
104
|
+
e.code; // "monthly_quota_exhausted", "not_observed", "plan_limit", ...
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Quota exhausted? The error tells you exactly where to upgrade (no "contact sales" wall), and agents can pay per call via [x402](https://intel.revnuvo.site/docs/x402).
|
|
110
|
+
|
|
111
|
+
## Honesty
|
|
112
|
+
|
|
113
|
+
Revnuvo reports **what was measured** โ observed technologies, infrastructure and changes with timestamps, confidence and evidence. It does **not** claim purchase intent, complete internet coverage, or predictive conclusions. Evidence is the product.
|
|
114
|
+
|
|
115
|
+
## Links
|
|
116
|
+
|
|
117
|
+
- [Quickstart](https://intel.revnuvo.site) ยท [API reference](https://intel.revnuvo.site/docs/api) ยท [MCP](https://intel.revnuvo.site/docs/mcp) ยท [Claude setup](https://intel.revnuvo.site/docs/claude)
|
|
118
|
+
- Python: [`revnuvo-intel` on PyPI](https://pypi.org/project/revnuvo-intel/)
|
|
119
|
+
- Dashboard / free key: [app.revnuvo.site](https://app.revnuvo.site)
|
|
120
|
+
|
|
121
|
+
## License
|
|
122
|
+
|
|
123
|
+
MIT
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# revnuvo
|
|
2
|
+
|
|
3
|
+
**Give AI agents live intelligence about companies.**
|
|
4
|
+
|
|
5
|
+
Official JavaScript SDK for the [Revnuvo Company Intelligence API](https://intel.revnuvo.site). Revnuvo observes company websites, technologies, DNS and infrastructure over time, detects meaningful changes, and returns **evidence-backed, machine-readable intelligence** โ timestamped, confidence-aware, never invented.
|
|
6
|
+
|
|
7
|
+
- ๐ **Free developer tier**: 100 intelligence calls/month (REST + MCP), no credit card โ [get a key](https://app.revnuvo.site)
|
|
8
|
+
- ๐ **MCP included**: one config line connects Claude/any MCP client โ [MCP docs](https://intel.revnuvo.site/docs/mcp)
|
|
9
|
+
- โก **Zero dependencies**, works in Node 18+, Bun, Deno, edge runtimes
|
|
10
|
+
- ๐ธ **x402 support**: agents without accounts pay per call in USDC on Base โ [x402 docs](https://intel.revnuvo.site/docs/x402)
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install revnuvo
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## 60-second quickstart
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
import { Revnuvo } from "revnuvo";
|
|
22
|
+
|
|
23
|
+
const rv = new Revnuvo({ apiKey: process.env.REVNUVO_API_KEY });
|
|
24
|
+
|
|
25
|
+
// What technologies does this company use? (with evidence)
|
|
26
|
+
const techs = await rv.getCompanyTechnologies("hubspot.com");
|
|
27
|
+
console.log(techs.technologies);
|
|
28
|
+
// [{ name: "webflow", confidence: 0.85, evidence: "meta generator", ... }, ...]
|
|
29
|
+
|
|
30
|
+
// What changed at this company?
|
|
31
|
+
const changes = await rv.getCompanyChanges("stripe.com");
|
|
32
|
+
console.log(changes.changes);
|
|
33
|
+
|
|
34
|
+
// Which companies recently adopted Vue?
|
|
35
|
+
const signals = await rv.searchSignals({ technology: "vue", eventType: "technology_added" });
|
|
36
|
+
console.log(signals.signals);
|
|
37
|
+
// each signal: before/after state, evidence, confidence, signal_score, detected_at
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## The 9 canonical capabilities
|
|
41
|
+
|
|
42
|
+
| Method | Answers |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `searchCompanies({query})` | Which companies does Revnuvo observe? |
|
|
45
|
+
| `getCompany(domain)` | What do we know about this company? |
|
|
46
|
+
| `getCompanyState(domain)` | Full current observed state (HTTP + techs + scripts + DNS) |
|
|
47
|
+
| `getCompanyTimeline(domain)` | How did their stack evolve? |
|
|
48
|
+
| `getCompanyTechnologies(domain)` | What technologies do they use? (evidence per tech) |
|
|
49
|
+
| `getCompanyChanges(domain)` | What changed and when? |
|
|
50
|
+
| `searchSignals({technology,...})` | Which companies recently adopted X? |
|
|
51
|
+
| `monitorCompany(domain)` | Watch this company for future changes |
|
|
52
|
+
| `verifyCompany(domain)` | What can be substantiated with evidence? |
|
|
53
|
+
|
|
54
|
+
Plus `whoami()` โ your key's identity and remaining quota.
|
|
55
|
+
|
|
56
|
+
## MCP (Claude, Cursor, any MCP client)
|
|
57
|
+
|
|
58
|
+
```js
|
|
59
|
+
import { claudeDesktopConfig } from "revnuvo";
|
|
60
|
+
console.log(JSON.stringify(claudeDesktopConfig(process.env.REVNUVO_API_KEY), null, 2));
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Paste into `claude_desktop_config.json`, then ask Claude: *"What changed at stripe.com?"* โ full instructions: [intel.revnuvo.site/docs/mcp](https://intel.revnuvo.site/docs/mcp).
|
|
64
|
+
|
|
65
|
+
## CLI
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npx revnuvo whoami # key + quota
|
|
69
|
+
npx revnuvo tech hubspot.com # detected technologies + evidence
|
|
70
|
+
npx revnuvo changes stripe.com # observed changes
|
|
71
|
+
npx revnuvo monitor acme.com # start monitoring
|
|
72
|
+
npx revnuvo mcp-config --key ... # print MCP config
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Error handling
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
import { Revnuvo, RevnuvoError } from "revnuvo";
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
await rv.getCompanyState("example.com");
|
|
82
|
+
} catch (e) {
|
|
83
|
+
if (e instanceof RevnuvoError) {
|
|
84
|
+
e.status; // 401 bad key ยท 404 not_observed ยท 429 quota/rate limit ยท 402 plan limit
|
|
85
|
+
e.code; // "monthly_quota_exhausted", "not_observed", "plan_limit", ...
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Quota exhausted? The error tells you exactly where to upgrade (no "contact sales" wall), and agents can pay per call via [x402](https://intel.revnuvo.site/docs/x402).
|
|
91
|
+
|
|
92
|
+
## Honesty
|
|
93
|
+
|
|
94
|
+
Revnuvo reports **what was measured** โ observed technologies, infrastructure and changes with timestamps, confidence and evidence. It does **not** claim purchase intent, complete internet coverage, or predictive conclusions. Evidence is the product.
|
|
95
|
+
|
|
96
|
+
## Links
|
|
97
|
+
|
|
98
|
+
- [Quickstart](https://intel.revnuvo.site) ยท [API reference](https://intel.revnuvo.site/docs/api) ยท [MCP](https://intel.revnuvo.site/docs/mcp) ยท [Claude setup](https://intel.revnuvo.site/docs/claude)
|
|
99
|
+
- Python: [`revnuvo-intel` on PyPI](https://pypi.org/project/revnuvo-intel/)
|
|
100
|
+
- Dashboard / free key: [app.revnuvo.site](https://app.revnuvo.site)
|
|
101
|
+
|
|
102
|
+
## License
|
|
103
|
+
|
|
104
|
+
MIT
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "revnuvo-intel"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Revnuvo Company Intelligence โ evidence-backed technology and infrastructure change signals for AI agents and developers. Free developer tier: 100 calls/month."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Revnuvo", email = "ismael@revnuvo.site" }]
|
|
13
|
+
keywords = [
|
|
14
|
+
"company-intelligence", "technology-monitoring", "mcp", "model-context-protocol",
|
|
15
|
+
"ai-agents", "x402", "signals", "sales-intelligence", "change-detection", "revnuvo",
|
|
16
|
+
]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 4 - Beta",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Operating System :: OS Independent",
|
|
22
|
+
"Programming Language :: Python :: 3",
|
|
23
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
24
|
+
]
|
|
25
|
+
dependencies = []
|
|
26
|
+
|
|
27
|
+
[project.urls]
|
|
28
|
+
Homepage = "https://intel.revnuvo.site"
|
|
29
|
+
Documentation = "https://intel.revnuvo.site/docs/api"
|
|
30
|
+
Repository = "https://github.com/hardeyhemy/revnuvo-dev"
|
|
31
|
+
|
|
32
|
+
[project.scripts]
|
|
33
|
+
revnuvo = "revnuvo_intel:main"
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.packages.find]
|
|
36
|
+
where = ["src"]
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
"""Revnuvo Company Intelligence โ official Python client.
|
|
2
|
+
|
|
3
|
+
Evidence-backed technology and infrastructure change signals for AI agents
|
|
4
|
+
and developers. Zero dependencies (stdlib only).
|
|
5
|
+
|
|
6
|
+
pip install revnuvo-intel
|
|
7
|
+
|
|
8
|
+
Free developer tier: 100 intelligence calls/month โ get a key at
|
|
9
|
+
https://app.revnuvo.site (magic link, no credit card).
|
|
10
|
+
|
|
11
|
+
Every method maps 1:1 to a canonical Revnuvo capability:
|
|
12
|
+
search_companies, get_company, get_company_state, get_company_timeline,
|
|
13
|
+
get_company_technologies, get_company_changes, search_signals,
|
|
14
|
+
monitor_company, verify_company, whoami
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import json as _json
|
|
20
|
+
import os
|
|
21
|
+
import urllib.error
|
|
22
|
+
import urllib.parse
|
|
23
|
+
import urllib.request
|
|
24
|
+
|
|
25
|
+
DEFAULT_BASE = "https://intel.revnuvo.site/v1"
|
|
26
|
+
MCP_ENDPOINT = "https://mcp.revnuvo.site/mcp"
|
|
27
|
+
|
|
28
|
+
__version__ = "0.1.0"
|
|
29
|
+
__all__ = ["Revnuvo", "RevnuvoError", "mcp_server_config", "main"]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class RevnuvoError(Exception):
|
|
33
|
+
"""HTTP-level or API-level error from the Revnuvo intelligence API."""
|
|
34
|
+
|
|
35
|
+
def __init__(self, status: int, code: str | None, message: str | None, body=None):
|
|
36
|
+
super().__init__(message or code or f"revnuvo error {status}")
|
|
37
|
+
self.status = status
|
|
38
|
+
self.code = code
|
|
39
|
+
self.body = body or {}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class Revnuvo:
|
|
43
|
+
"""Client for the Revnuvo Company Intelligence API.
|
|
44
|
+
|
|
45
|
+
>>> rv = Revnuvo(api_key=os.environ["REVNUVO_API_KEY"])
|
|
46
|
+
>>> rv.get_company_technologies("hubspot.com")["technologies"]
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def __init__(self, api_key: str, base_url: str = DEFAULT_BASE):
|
|
50
|
+
if not api_key or not isinstance(api_key, str):
|
|
51
|
+
raise ValueError(
|
|
52
|
+
"Revnuvo: api_key is required โ create a free key at https://app.revnuvo.site"
|
|
53
|
+
)
|
|
54
|
+
self.api_key = api_key
|
|
55
|
+
self.base_url = base_url.rstrip("/")
|
|
56
|
+
|
|
57
|
+
# ---------- transport ----------
|
|
58
|
+
def _call(self, path: str, method: str = "GET", body: dict | None = None) -> dict:
|
|
59
|
+
data = _json.dumps(body).encode() if body is not None else None
|
|
60
|
+
req = urllib.request.Request(
|
|
61
|
+
self.base_url + path,
|
|
62
|
+
data=data,
|
|
63
|
+
method=method,
|
|
64
|
+
headers={
|
|
65
|
+
"authorization": f"Bearer {self.api_key}",
|
|
66
|
+
"content-type": "application/json",
|
|
67
|
+
"user-agent": f"revnuvo-intel-python/{__version__}",
|
|
68
|
+
},
|
|
69
|
+
)
|
|
70
|
+
try:
|
|
71
|
+
with urllib.request.urlopen(req, timeout=30) as res:
|
|
72
|
+
return _json.loads(res.read().decode())
|
|
73
|
+
except urllib.error.HTTPError as e:
|
|
74
|
+
payload = {}
|
|
75
|
+
try:
|
|
76
|
+
payload = _json.loads(e.read().decode())
|
|
77
|
+
except Exception:
|
|
78
|
+
pass
|
|
79
|
+
code = payload.get("code")
|
|
80
|
+
message = payload.get("message") or payload.get("error")
|
|
81
|
+
raise RevnuvoError(e.code, code, message, payload) from None
|
|
82
|
+
|
|
83
|
+
# ---------- 9 canonical capabilities ----------
|
|
84
|
+
def search_companies(self, query: str = "", limit: int = 50, offset: int = 0) -> dict:
|
|
85
|
+
"""Search companies previously observed by Revnuvo (partial domain match)."""
|
|
86
|
+
q = urllib.parse.urlencode({"query": query, "limit": limit, "offset": offset})
|
|
87
|
+
return self._call(f"/companies?{q}")
|
|
88
|
+
|
|
89
|
+
def get_company(self, domain: str) -> dict:
|
|
90
|
+
"""Company overview: technologies (with confidence), DNS, observation depth."""
|
|
91
|
+
return self._call(f"/companies/{urllib.parse.quote(domain, safe='')}")
|
|
92
|
+
|
|
93
|
+
def get_company_state(self, domain: str) -> dict:
|
|
94
|
+
"""Latest full observed state: HTTP, technologies w/ evidence, scripts, DNS."""
|
|
95
|
+
return self._call(f"/companies/{urllib.parse.quote(domain, safe='')}/state")
|
|
96
|
+
|
|
97
|
+
def get_company_timeline(self, domain: str, limit: int = 50) -> dict:
|
|
98
|
+
"""Chronological observations + change events (history depth = your plan)."""
|
|
99
|
+
return self._call(f"/companies/{urllib.parse.quote(domain, safe='')}/timeline?limit={limit}")
|
|
100
|
+
|
|
101
|
+
def get_company_technologies(self, domain: str) -> dict:
|
|
102
|
+
"""Current technology stack with per-technology evidence and confidence."""
|
|
103
|
+
return self._call(f"/companies/{urllib.parse.quote(domain, safe='')}/technologies")
|
|
104
|
+
|
|
105
|
+
def get_company_changes(self, domain: str, limit: int = 50, since: str | None = None) -> dict:
|
|
106
|
+
"""Observed changes for one company (technology_added/removed/changed, DNS...)."""
|
|
107
|
+
q = f"?limit={limit}" + (f"&since={urllib.parse.quote(since)}" if since else "")
|
|
108
|
+
return self._call(f"/companies/{urllib.parse.quote(domain, safe='')}/changes{q}")
|
|
109
|
+
|
|
110
|
+
def search_signals(
|
|
111
|
+
self,
|
|
112
|
+
domain: str | None = None,
|
|
113
|
+
technology: str | None = None,
|
|
114
|
+
event_type: str | None = None,
|
|
115
|
+
min_score: int | None = None,
|
|
116
|
+
since: str | None = None,
|
|
117
|
+
limit: int = 50,
|
|
118
|
+
offset: int = 0,
|
|
119
|
+
) -> dict:
|
|
120
|
+
"""Cross-company signal search โ 'which companies recently adopted technology X?'."""
|
|
121
|
+
params = {"limit": limit, "offset": offset}
|
|
122
|
+
if domain:
|
|
123
|
+
params["domain"] = domain
|
|
124
|
+
if technology:
|
|
125
|
+
params["technology"] = technology
|
|
126
|
+
if event_type:
|
|
127
|
+
params["event_type"] = event_type
|
|
128
|
+
if min_score:
|
|
129
|
+
params["min_score"] = min_score
|
|
130
|
+
if since:
|
|
131
|
+
params["since"] = since
|
|
132
|
+
return self._call(f"/signals?{urllib.parse.urlencode(params)}")
|
|
133
|
+
|
|
134
|
+
def monitor_company(self, domain: str, interval_hours: int = 24) -> dict:
|
|
135
|
+
"""Start monitoring a domain (immediate baseline scan; signals via API/webhook/email)."""
|
|
136
|
+
return self._call("/monitor", method="POST", body={"domain": domain, "interval_hours": interval_hours})
|
|
137
|
+
|
|
138
|
+
def verify_company(self, domain: str) -> dict:
|
|
139
|
+
"""Evidence-backed verification: observation history depth + latest state hash."""
|
|
140
|
+
return self._call("/verify", method="POST", body={"domain": domain})
|
|
141
|
+
|
|
142
|
+
# ---------- developer utility ----------
|
|
143
|
+
def whoami(self) -> dict:
|
|
144
|
+
"""Key identity, plan and remaining quota โ make this your integration's first call."""
|
|
145
|
+
return self._call("/whoami")
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def mcp_server_config(api_key: str) -> dict:
|
|
149
|
+
"""MCP client config block for the Revnuvo remote MCP server."""
|
|
150
|
+
return {"url": MCP_ENDPOINT, "headers": {"Authorization": f"Bearer {api_key}"}}
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def main() -> None: # tiny CLI: python -m revnuvo_intel whoami
|
|
154
|
+
import sys
|
|
155
|
+
|
|
156
|
+
args = sys.argv[1:]
|
|
157
|
+
cmd = args[0] if args else "help"
|
|
158
|
+
key = os.environ.get("REVNUVO_API_KEY", "")
|
|
159
|
+
if cmd in ("help", "-h", "--help") or not key:
|
|
160
|
+
print(
|
|
161
|
+
"revnuvo-intel CLI\n\n"
|
|
162
|
+
" export REVNUVO_API_KEY=rvk_... # free key: https://app.revnuvo.site\n"
|
|
163
|
+
" python -m revnuvo_intel whoami\n"
|
|
164
|
+
" python -m revnuvo_intel tech <domain>\n"
|
|
165
|
+
" python -m revnuvo_intel changes <domain>\n"
|
|
166
|
+
" python -m revnuvo_intel monitor <domain>\n"
|
|
167
|
+
" python -m revnuvo_intel mcp-config\n"
|
|
168
|
+
)
|
|
169
|
+
return
|
|
170
|
+
rv = Revnuvo(api_key=key)
|
|
171
|
+
if cmd == "whoami":
|
|
172
|
+
me = rv.whoami()
|
|
173
|
+
print(f"plan: {me['plan_label']} ({me['plan']})")
|
|
174
|
+
print(f"quota: {me['quota']['used']}/{me['quota']['api_calls_per_month']} used, {me['quota']['remaining']} remaining")
|
|
175
|
+
elif cmd in ("tech", "technologies"):
|
|
176
|
+
r = rv.get_company_technologies(args[1])
|
|
177
|
+
print(f"{r['domain']} โ observed {r['observed_at']}")
|
|
178
|
+
for t in r["technologies"]:
|
|
179
|
+
print(f" {t['name']}{'@' + t['version'] if t.get('version') else ''} conf={t['confidence']} evidence: {t['evidence']}")
|
|
180
|
+
elif cmd == "changes":
|
|
181
|
+
r = rv.get_company_changes(args[1])
|
|
182
|
+
print(f"{r['domain']} โ {r['count']} change(s)")
|
|
183
|
+
for c in r["changes"]:
|
|
184
|
+
print(f" [{c['detected_at']}] {c['event_type']}: {c.get('technology')} conf={c['confidence']}")
|
|
185
|
+
elif cmd == "monitor":
|
|
186
|
+
r = rv.monitor_company(args[1])
|
|
187
|
+
print(f"{r['domain']} monitored ({r.get('interval_hours', 24)}h)")
|
|
188
|
+
elif cmd == "mcp-config":
|
|
189
|
+
print(_json.dumps({"mcpServers": {"revnuvo": mcp_server_config(key)}}, indent=2))
|
|
190
|
+
else:
|
|
191
|
+
print(f"unknown command: {cmd}")
|
|
192
|
+
sys.exit(1)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
if __name__ == "__main__":
|
|
196
|
+
main()
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: revnuvo-intel
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Revnuvo Company Intelligence โ evidence-backed technology and infrastructure change signals for AI agents and developers. Free developer tier: 100 calls/month.
|
|
5
|
+
Author-email: Revnuvo <ismael@revnuvo.site>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://intel.revnuvo.site
|
|
8
|
+
Project-URL: Documentation, https://intel.revnuvo.site/docs/api
|
|
9
|
+
Project-URL: Repository, https://github.com/hardeyhemy/revnuvo-dev
|
|
10
|
+
Keywords: company-intelligence,technology-monitoring,mcp,model-context-protocol,ai-agents,x402,signals,sales-intelligence,change-detection,revnuvo
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Requires-Python: >=3.9
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# revnuvo
|
|
21
|
+
|
|
22
|
+
**Give AI agents live intelligence about companies.**
|
|
23
|
+
|
|
24
|
+
Official JavaScript SDK for the [Revnuvo Company Intelligence API](https://intel.revnuvo.site). Revnuvo observes company websites, technologies, DNS and infrastructure over time, detects meaningful changes, and returns **evidence-backed, machine-readable intelligence** โ timestamped, confidence-aware, never invented.
|
|
25
|
+
|
|
26
|
+
- ๐ **Free developer tier**: 100 intelligence calls/month (REST + MCP), no credit card โ [get a key](https://app.revnuvo.site)
|
|
27
|
+
- ๐ **MCP included**: one config line connects Claude/any MCP client โ [MCP docs](https://intel.revnuvo.site/docs/mcp)
|
|
28
|
+
- โก **Zero dependencies**, works in Node 18+, Bun, Deno, edge runtimes
|
|
29
|
+
- ๐ธ **x402 support**: agents without accounts pay per call in USDC on Base โ [x402 docs](https://intel.revnuvo.site/docs/x402)
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install revnuvo
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## 60-second quickstart
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
import { Revnuvo } from "revnuvo";
|
|
41
|
+
|
|
42
|
+
const rv = new Revnuvo({ apiKey: process.env.REVNUVO_API_KEY });
|
|
43
|
+
|
|
44
|
+
// What technologies does this company use? (with evidence)
|
|
45
|
+
const techs = await rv.getCompanyTechnologies("hubspot.com");
|
|
46
|
+
console.log(techs.technologies);
|
|
47
|
+
// [{ name: "webflow", confidence: 0.85, evidence: "meta generator", ... }, ...]
|
|
48
|
+
|
|
49
|
+
// What changed at this company?
|
|
50
|
+
const changes = await rv.getCompanyChanges("stripe.com");
|
|
51
|
+
console.log(changes.changes);
|
|
52
|
+
|
|
53
|
+
// Which companies recently adopted Vue?
|
|
54
|
+
const signals = await rv.searchSignals({ technology: "vue", eventType: "technology_added" });
|
|
55
|
+
console.log(signals.signals);
|
|
56
|
+
// each signal: before/after state, evidence, confidence, signal_score, detected_at
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## The 9 canonical capabilities
|
|
60
|
+
|
|
61
|
+
| Method | Answers |
|
|
62
|
+
|---|---|
|
|
63
|
+
| `searchCompanies({query})` | Which companies does Revnuvo observe? |
|
|
64
|
+
| `getCompany(domain)` | What do we know about this company? |
|
|
65
|
+
| `getCompanyState(domain)` | Full current observed state (HTTP + techs + scripts + DNS) |
|
|
66
|
+
| `getCompanyTimeline(domain)` | How did their stack evolve? |
|
|
67
|
+
| `getCompanyTechnologies(domain)` | What technologies do they use? (evidence per tech) |
|
|
68
|
+
| `getCompanyChanges(domain)` | What changed and when? |
|
|
69
|
+
| `searchSignals({technology,...})` | Which companies recently adopted X? |
|
|
70
|
+
| `monitorCompany(domain)` | Watch this company for future changes |
|
|
71
|
+
| `verifyCompany(domain)` | What can be substantiated with evidence? |
|
|
72
|
+
|
|
73
|
+
Plus `whoami()` โ your key's identity and remaining quota.
|
|
74
|
+
|
|
75
|
+
## MCP (Claude, Cursor, any MCP client)
|
|
76
|
+
|
|
77
|
+
```js
|
|
78
|
+
import { claudeDesktopConfig } from "revnuvo";
|
|
79
|
+
console.log(JSON.stringify(claudeDesktopConfig(process.env.REVNUVO_API_KEY), null, 2));
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Paste into `claude_desktop_config.json`, then ask Claude: *"What changed at stripe.com?"* โ full instructions: [intel.revnuvo.site/docs/mcp](https://intel.revnuvo.site/docs/mcp).
|
|
83
|
+
|
|
84
|
+
## CLI
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npx revnuvo whoami # key + quota
|
|
88
|
+
npx revnuvo tech hubspot.com # detected technologies + evidence
|
|
89
|
+
npx revnuvo changes stripe.com # observed changes
|
|
90
|
+
npx revnuvo monitor acme.com # start monitoring
|
|
91
|
+
npx revnuvo mcp-config --key ... # print MCP config
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Error handling
|
|
95
|
+
|
|
96
|
+
```js
|
|
97
|
+
import { Revnuvo, RevnuvoError } from "revnuvo";
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
await rv.getCompanyState("example.com");
|
|
101
|
+
} catch (e) {
|
|
102
|
+
if (e instanceof RevnuvoError) {
|
|
103
|
+
e.status; // 401 bad key ยท 404 not_observed ยท 429 quota/rate limit ยท 402 plan limit
|
|
104
|
+
e.code; // "monthly_quota_exhausted", "not_observed", "plan_limit", ...
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Quota exhausted? The error tells you exactly where to upgrade (no "contact sales" wall), and agents can pay per call via [x402](https://intel.revnuvo.site/docs/x402).
|
|
110
|
+
|
|
111
|
+
## Honesty
|
|
112
|
+
|
|
113
|
+
Revnuvo reports **what was measured** โ observed technologies, infrastructure and changes with timestamps, confidence and evidence. It does **not** claim purchase intent, complete internet coverage, or predictive conclusions. Evidence is the product.
|
|
114
|
+
|
|
115
|
+
## Links
|
|
116
|
+
|
|
117
|
+
- [Quickstart](https://intel.revnuvo.site) ยท [API reference](https://intel.revnuvo.site/docs/api) ยท [MCP](https://intel.revnuvo.site/docs/mcp) ยท [Claude setup](https://intel.revnuvo.site/docs/claude)
|
|
118
|
+
- Python: [`revnuvo-intel` on PyPI](https://pypi.org/project/revnuvo-intel/)
|
|
119
|
+
- Dashboard / free key: [app.revnuvo.site](https://app.revnuvo.site)
|
|
120
|
+
|
|
121
|
+
## License
|
|
122
|
+
|
|
123
|
+
MIT
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/revnuvo_intel/__init__.py
|
|
4
|
+
src/revnuvo_intel.egg-info/PKG-INFO
|
|
5
|
+
src/revnuvo_intel.egg-info/SOURCES.txt
|
|
6
|
+
src/revnuvo_intel.egg-info/dependency_links.txt
|
|
7
|
+
src/revnuvo_intel.egg-info/entry_points.txt
|
|
8
|
+
src/revnuvo_intel.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
revnuvo_intel
|