freshcontext-mcp 0.3.10 → 0.3.11
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.
- package/.actor/Dockerfile +14 -0
- package/.actor/actor.json +2 -1
- package/.github/workflows/publish.yml +32 -0
- package/ARCHITECTURE_UPGRADE_CHECKLIST.md +88 -0
- package/ARCHITECTURE_UPGRADE_ROADMAP_V1.md +174 -0
- package/README.md +239 -212
- package/SESSION_SAVE_ARCHITECTURE_V1.md +67 -0
- package/SESSION_SAVE_ARCHITECTURE_V2.md +142 -0
- package/dist/server.js +97 -0
- package/dist/tools/freshnessStamp.js +86 -2
- package/package.json +2 -1
- package/server.json +3 -3
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
FROM apify/actor-node:18
|
|
2
|
+
|
|
3
|
+
# Copy package files first for better Docker layer caching
|
|
4
|
+
COPY package*.json ./
|
|
5
|
+
|
|
6
|
+
# Install all dependencies including apify SDK
|
|
7
|
+
RUN npm install --include=dev
|
|
8
|
+
|
|
9
|
+
# Copy source and build
|
|
10
|
+
COPY . ./
|
|
11
|
+
RUN npm run build
|
|
12
|
+
|
|
13
|
+
# Tell Apify to run the Actor entry point, not the MCP server
|
|
14
|
+
CMD ["node", "dist/apify.js"]
|
package/.actor/actor.json
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Build and Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build-and-publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
|
|
12
|
+
steps:
|
|
13
|
+
- name: Checkout repository
|
|
14
|
+
uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- name: Set up Node.js 18
|
|
17
|
+
uses: actions/setup-node@v4
|
|
18
|
+
with:
|
|
19
|
+
node-version: '18'
|
|
20
|
+
registry-url: 'https://registry.npmjs.org'
|
|
21
|
+
|
|
22
|
+
- name: Install dependencies
|
|
23
|
+
run: npm ci
|
|
24
|
+
|
|
25
|
+
- name: Build
|
|
26
|
+
run: npm run build
|
|
27
|
+
|
|
28
|
+
- name: Publish to npm
|
|
29
|
+
run: npm publish --access public
|
|
30
|
+
env:
|
|
31
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
32
|
+
continue-on-error: true
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# FreshContext — Architecture Upgrade Checklist
|
|
2
|
+
**Date started:** 2026-03-19
|
|
3
|
+
**Author:** Prince Gabriel, Grootfontein, Namibia
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## [ ] Upgrade 1 — freshness_score numeric field
|
|
8
|
+
Implement the 0-100 numeric score defined in FRESHCONTEXT_SPEC.md.
|
|
9
|
+
Formula: max(0, 100 - (days_since_retrieved * decay_rate))
|
|
10
|
+
Location: src/tools/freshnessStamp.ts
|
|
11
|
+
Decay rates by adapter: finance=5.0, jobs=3.0, hackernews=2.0, github=1.0, scholar=0.3, default=1.5
|
|
12
|
+
Adds the score to both the text envelope and the JSON form.
|
|
13
|
+
Makes FreshContext fully spec-compliant by your own standard.
|
|
14
|
+
Cost: zero.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## [x] Upgrade 2 — Cloudflare KV response caching ← DONE (already implemented in worker.ts)
|
|
19
|
+
Cache adapter results in KV with adapter-specific TTLs so the same query
|
|
20
|
+
hitting the Worker twice doesn't make two upstream API calls.
|
|
21
|
+
Cache key: sha256(tool + ":" + url)
|
|
22
|
+
TTLs: HN/Reddit = 1 hour, GitHub/YC = 6 hours, govcontracts/scholar = 24 hours
|
|
23
|
+
Location: worker/src/index.ts
|
|
24
|
+
Cost: zero. KV free tier is 100k reads/day, 1k writes/day.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## [x] Upgrade 3 — Apify Actor timeout increase ← DONE 2026-03-19
|
|
29
|
+
Change the Actor timeout from 300 seconds to 3600 seconds in the Apify UI.
|
|
30
|
+
Apify console → Actor → Settings → Timeout → 3600
|
|
31
|
+
Playwright-based tools (extract_reddit, extract_yc, extract_producthunt) need
|
|
32
|
+
more than 5 minutes to launch Chromium and scrape. They will keep timing out
|
|
33
|
+
until this is changed. This is a UI field change, not a code change.
|
|
34
|
+
Cost: zero.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## [x] Upgrade 4 — D1 deduplication in the cron job ← DONE (hash-based dedup already in runScheduledScrape)
|
|
39
|
+
Before inserting a new scrape result, check if the same source_url was already
|
|
40
|
+
stored in the last 24 hours. If yes, skip the insert.
|
|
41
|
+
Prevents the scrape_results table from filling with duplicate data across
|
|
42
|
+
consecutive cron runs, keeping the historical dataset clean for the intelligence
|
|
43
|
+
layer (Layer 7 in the roadmap).
|
|
44
|
+
Location: the cron job handler in the Worker code.
|
|
45
|
+
Cost: zero.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## [x] Upgrade 5 — Structured JSON response form ← DONE 2026-03-19
|
|
50
|
+
Add the optional JSON form defined in FRESHCONTEXT_SPEC.md alongside the text
|
|
51
|
+
envelope in every adapter response. The JSON form has: source_url, content_date,
|
|
52
|
+
retrieved_at, freshness_confidence, adapter, freshness_score.
|
|
53
|
+
When a request has Accept: application/json, serve the structured form.
|
|
54
|
+
Both forms can be returned together — text for agents, JSON for programmatic use.
|
|
55
|
+
Location: src/tools/freshnessStamp.ts (same file as Upgrade 1, do together)
|
|
56
|
+
Cost: zero.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## [x] Upgrade 6 — GitHub Actions CI/CD automation ← DONE 2026-03-19
|
|
61
|
+
.github/workflows/publish.yml created. Triggers on every push to main.
|
|
62
|
+
Runs npm ci → npm run build → npm publish using NPM_TOKEN secret.
|
|
63
|
+
continue-on-error on publish so doc-only pushes don't fail the workflow.
|
|
64
|
+
First run: green checkmark, 23 seconds.
|
|
65
|
+
Manual PowerShell build/publish commands no longer needed.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## [x] Upgrade 7 — server.json version sync ← DONE 2026-03-19
|
|
70
|
+
server.json (MCP Registry listing) shows version 0.3.1 while package.json
|
|
71
|
+
is at 0.3.10. Anyone discovering FreshContext via the MCP Registry sees an
|
|
72
|
+
outdated version number. Fix by updating server.json manually now, then
|
|
73
|
+
optionally add a workflow step that syncs the version automatically on each
|
|
74
|
+
GitHub Actions run.
|
|
75
|
+
Location: server.json — change "version" field to match package.json.
|
|
76
|
+
Cost: zero.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Priority order for remaining six upgrades
|
|
81
|
+
|
|
82
|
+
Do Upgrade 3 first — it is one UI field change and immediately fixes the
|
|
83
|
+
broken Apify Actor runs. Do Upgrades 1 and 5 together second since they
|
|
84
|
+
both touch freshnessStamp.ts and completing them makes FreshContext fully
|
|
85
|
+
spec-compliant. Do Upgrade 2 third — KV caching makes the Worker resilient
|
|
86
|
+
against upstream API instability. Do Upgrade 4 fourth — D1 deduplication
|
|
87
|
+
prepares the dataset for the future intelligence layer. Do Upgrade 7 last —
|
|
88
|
+
a simple version number correction, low urgency but worth keeping clean.
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# FreshContext — Architecture Upgrade Roadmap V1
|
|
2
|
+
**Date:** 2026-03-19
|
|
3
|
+
**Author:** Immanuel Gabriel (Prince Gabriel), Grootfontein, Namibia
|
|
4
|
+
|
|
5
|
+
This document describes every free structural upgrade available to FreshContext,
|
|
6
|
+
prioritised by impact, with implementation notes for each.
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Upgrade 1 — freshness_score numeric field (HIGHEST PRIORITY)
|
|
11
|
+
|
|
12
|
+
**What it is:** The FreshContext Specification v1.0 defines an optional freshness_score
|
|
13
|
+
field (0-100) calculated as: max(0, 100 - (days_since_retrieved * decay_rate)).
|
|
14
|
+
Right now every response carries the text envelope and the confidence level (high/medium/low)
|
|
15
|
+
but not the numeric score. This is the one remaining piece that makes FreshContext fully
|
|
16
|
+
spec-compliant by your own standard.
|
|
17
|
+
|
|
18
|
+
**Why it matters:** Once the score exists, agents can filter results programmatically —
|
|
19
|
+
"only use results with freshness_score > 70" rather than parsing the string confidence
|
|
20
|
+
level. This is the difference between a label and a query parameter. It also strengthens
|
|
21
|
+
the acquisition narrative: the spec is complete, the reference implementation is complete,
|
|
22
|
+
and the standard is fully self-consistent.
|
|
23
|
+
|
|
24
|
+
**Domain-specific decay rates from the spec:**
|
|
25
|
+
Financial data decays at 5.0 (half-life ~10 days). Job listings at 3.0 (~17 days).
|
|
26
|
+
News and HN at 2.0 (~25 days). GitHub repos at 1.0 (~50 days). Academic papers at 0.3
|
|
27
|
+
(~167 days). General web content defaults to 1.5.
|
|
28
|
+
|
|
29
|
+
**Where to implement:** In src/tools/freshnessStamp.ts — the function that wraps every
|
|
30
|
+
adapter result already has retrieved_at and content_date. Add a calculateFreshnessScore
|
|
31
|
+
function that takes content_date, decay_rate (looked up by adapter name), and returns
|
|
32
|
+
the numeric score. Add it to both the text envelope and the JSON form.
|
|
33
|
+
|
|
34
|
+
**Cost:** Zero. Pure TypeScript logic, no new services.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Upgrade 2 — Cloudflare KV response caching
|
|
39
|
+
|
|
40
|
+
**What it is:** When the same query hits an adapter twice within a short window, the
|
|
41
|
+
Worker currently makes two full upstream API calls. KV caching stores the first result
|
|
42
|
+
with a TTL and serves subsequent identical requests from cache — meaning the upstream
|
|
43
|
+
API (USASpending, GitHub, HN, etc.) only gets called once per cache window.
|
|
44
|
+
|
|
45
|
+
**Why it matters:** This reduces the chance of hitting upstream rate limits, makes
|
|
46
|
+
repeated queries near-instant for users, and reduces Worker CPU time. For adapters like
|
|
47
|
+
extract_govcontracts that call a government API, caching also reduces the risk of
|
|
48
|
+
temporary blocks from aggressive polling.
|
|
49
|
+
|
|
50
|
+
**Implementation:** In the Worker code (worker/src/index.ts or equivalent), before calling
|
|
51
|
+
the adapter, compute a cache key as sha256(tool + ":" + url). Call env.KV.get(cacheKey).
|
|
52
|
+
If the result exists, return it immediately. If not, run the adapter, then call
|
|
53
|
+
env.KV.put(cacheKey, result, { expirationTtl: ttl }) before returning. Use adapter-specific
|
|
54
|
+
TTLs — 3600 seconds (1 hour) for HN and Reddit, 21600 (6 hours) for GitHub and YC,
|
|
55
|
+
86400 (24 hours) for govcontracts and scholar.
|
|
56
|
+
|
|
57
|
+
**Cost:** Zero. KV reads are free up to 100,000 per day, writes free up to 1,000 per day
|
|
58
|
+
on Cloudflare's free tier. You are nowhere near those limits.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Upgrade 3 — Apify Actor timeout increase
|
|
63
|
+
|
|
64
|
+
**What it is:** The Apify Actor timeout is currently set to 300 seconds (5 minutes). Tools
|
|
65
|
+
that use Playwright to launch a browser — extract_reddit, extract_yc, extract_producthunt —
|
|
66
|
+
need more time than this to launch Chromium, navigate, wait for the page to render, and
|
|
67
|
+
extract content. They will keep timing out until this setting is increased.
|
|
68
|
+
|
|
69
|
+
**Where to change it:** Apify console → your Actor → Settings → Timeout. Change from
|
|
70
|
+
300 to 3600 (1 hour). This is a UI change, not a code change.
|
|
71
|
+
|
|
72
|
+
**Cost:** Zero. The timeout setting is just a number. You won't actually use anywhere
|
|
73
|
+
near 3600 seconds — most tools complete in 10-30 seconds. The setting just prevents Apify
|
|
74
|
+
from killing the process prematurely for the slower Playwright-based tools.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Upgrade 4 — D1 deduplication in the cron job
|
|
79
|
+
|
|
80
|
+
**What it is:** Every 6 hours the cron job runs all 18 watched queries and stores results
|
|
81
|
+
in the scrape_results D1 table. Right now there is no deduplication — if the same article
|
|
82
|
+
or repo appears in two consecutive cron runs, it gets stored twice. Over time this creates
|
|
83
|
+
noise in the dataset and wastes storage.
|
|
84
|
+
|
|
85
|
+
**Implementation:** Before inserting a new result, run a SELECT to check whether a row
|
|
86
|
+
with the same source_url already exists within the last 24 hours. If it does, skip the
|
|
87
|
+
insert. This is a single SQL WHERE clause addition to the existing insert logic.
|
|
88
|
+
|
|
89
|
+
**Why it matters:** As you build the intelligence layer (Layer 7 in the roadmap), the
|
|
90
|
+
quality of the historical signal depends on clean, deduplicated data. Starting deduplication
|
|
91
|
+
now means the dataset is clean by the time you need it.
|
|
92
|
+
|
|
93
|
+
**Cost:** Zero. D1 reads are free up to 25 million rows per day. A deduplication check
|
|
94
|
+
adds one read per result per cron run — trivially within limits.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Upgrade 5 — Structured JSON response form in every adapter
|
|
99
|
+
|
|
100
|
+
**What it is:** The FreshContext Specification defines two valid response formats — the
|
|
101
|
+
text envelope ([FRESHCONTEXT]...[/FRESHCONTEXT]) and an optional structured JSON form with
|
|
102
|
+
a freshcontext object containing source_url, content_date, retrieved_at,
|
|
103
|
+
freshness_confidence, adapter, and freshness_score fields. Right now only the text envelope
|
|
104
|
+
is returned. Adding the JSON form makes FreshContext usable programmatically without
|
|
105
|
+
parsing the text envelope.
|
|
106
|
+
|
|
107
|
+
**Implementation:** In src/tools/freshnessStamp.ts, after assembling the text envelope,
|
|
108
|
+
also return a structured object. When the Worker serves a response, detect whether the
|
|
109
|
+
request has Accept: application/json and serve the structured form instead of the text
|
|
110
|
+
form if so. Both formats can also be returned together — text for human/agent reading,
|
|
111
|
+
JSON for programmatic use.
|
|
112
|
+
|
|
113
|
+
**Cost:** Zero. This is a response format change, no new services.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## Upgrade 6 — GitHub Actions: version bump automation
|
|
118
|
+
|
|
119
|
+
**What it is:** The current GitHub Actions workflow (publish.yml) runs npm publish on every
|
|
120
|
+
push, but only succeeds if the version in package.json has changed. Right now you manually
|
|
121
|
+
bump the version before pushing. A small addition to the workflow can automate this by
|
|
122
|
+
running npm version patch automatically before the publish step — so every push to main
|
|
123
|
+
creates a new patch version and publishes it without any manual intervention.
|
|
124
|
+
|
|
125
|
+
**Tradeoff:** This means every push creates a new npm version, which may not always be
|
|
126
|
+
desirable for documentation-only changes. A better approach is to only auto-bump when
|
|
127
|
+
commits touch src/ or .actor/ — which can be detected in the workflow with a path filter.
|
|
128
|
+
|
|
129
|
+
**Implementation:** Add a paths filter to the workflow trigger so it only runs the publish
|
|
130
|
+
step when source files change. Then add an npm version patch --no-git-tag-version step
|
|
131
|
+
before the publish step. Push the bumped package.json back to the repo using a
|
|
132
|
+
git commit and git push within the workflow (requires GITHUB_TOKEN, which is automatically
|
|
133
|
+
available in all Actions workflows at no cost).
|
|
134
|
+
|
|
135
|
+
**Cost:** Zero.
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Upgrade 7 — server.json version sync check
|
|
140
|
+
|
|
141
|
+
**What it is:** The server.json file (used by the MCP Registry listing) still shows version
|
|
142
|
+
0.3.1 while package.json is at 0.3.10. This discrepancy means anyone who discovers
|
|
143
|
+
FreshContext via the MCP Registry sees an outdated version number. It is a cosmetic issue
|
|
144
|
+
but it affects credibility in a space where people are evaluating tools carefully.
|
|
145
|
+
|
|
146
|
+
**Implementation:** Add a step to the GitHub Actions workflow that reads the version from
|
|
147
|
+
package.json and uses sed or node -e to update the version field in server.json to match
|
|
148
|
+
before committing. Alternatively, update server.json manually now and keep it in sync
|
|
149
|
+
going forward.
|
|
150
|
+
|
|
151
|
+
**Cost:** Zero.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Priority Order for Implementation
|
|
156
|
+
|
|
157
|
+
The order that maximises impact relative to effort is as follows. Implement the Apify
|
|
158
|
+
timeout increase first because it is a one-field UI change that immediately fixes the
|
|
159
|
+
broken Actor runs. Implement KV caching second because it makes the Worker more robust
|
|
160
|
+
against upstream API instability and improves response times for repeat queries. Implement
|
|
161
|
+
the freshness_score calculation third because it completes the spec and strengthens every
|
|
162
|
+
conversation about acquisition or partnership. Implement D1 deduplication fourth because
|
|
163
|
+
it improves data quality for the intelligence layer you will eventually build. Implement
|
|
164
|
+
the structured JSON response form fifth as part of the same PR as freshness_score since
|
|
165
|
+
they touch the same file. Implement the GitHub Actions version sync last as a quality-of-life
|
|
166
|
+
automation.
|
|
167
|
+
|
|
168
|
+
The total engineering cost of all six remaining upgrades is approximately 4-6 hours of
|
|
169
|
+
focused work. All run entirely within free tiers.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
*"The work isn't gone. It's just waiting to be continued."*
|
|
174
|
+
*— Prince Gabriel, Grootfontein, Namibia*
|
package/README.md
CHANGED
|
@@ -1,212 +1,239 @@
|
|
|
1
|
-
# freshcontext-mcp
|
|
2
|
-
|
|
3
|
-
I asked Claude to help me find a job. It gave me a list of openings. I applied to three of them. Two didn't exist anymore. One had been closed for two years.
|
|
4
|
-
|
|
5
|
-
Claude had no idea. It presented everything with the same confidence.
|
|
6
|
-
|
|
7
|
-
That's the problem freshcontext fixes.
|
|
8
|
-
|
|
9
|
-
[](https://www.npmjs.com/package/freshcontext-mcp)
|
|
10
|
-
[](https://opensource.org/licenses/MIT)
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## What it does
|
|
15
|
-
|
|
16
|
-
Every MCP server returns data. freshcontext returns data **plus when it was retrieved and how confident that date is** — wrapped in a FreshContext envelope:
|
|
17
|
-
|
|
18
|
-
```
|
|
19
|
-
[FRESHCONTEXT]
|
|
20
|
-
Source: https://github.com/owner/repo
|
|
21
|
-
Published: 2024-11-03
|
|
22
|
-
Retrieved: 2026-03-05T09:19:00Z
|
|
23
|
-
Confidence: high
|
|
24
|
-
---
|
|
25
|
-
... content ...
|
|
26
|
-
[/FRESHCONTEXT]
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
Claude now knows the difference between something from this morning and something from two years ago. You do too.
|
|
30
|
-
|
|
31
|
-
---
|
|
32
|
-
|
|
33
|
-
##
|
|
34
|
-
|
|
35
|
-
### Intelligence
|
|
36
|
-
| Tool | What it gets you |
|
|
37
|
-
|---|---|
|
|
38
|
-
| `extract_github` | README, stars, forks, language, topics, last commit |
|
|
39
|
-
| `extract_hackernews` | Top stories or search results with scores and timestamps |
|
|
40
|
-
| `extract_scholar` | Research papers — titles, authors, years, snippets |
|
|
41
|
-
| `extract_arxiv` | arXiv papers via official API — more reliable than Scholar |
|
|
42
|
-
| `extract_reddit` | Posts and community sentiment from any subreddit |
|
|
43
|
-
|
|
44
|
-
### Competitive research
|
|
45
|
-
| Tool | What it gets you |
|
|
46
|
-
|---|---|
|
|
47
|
-
| `extract_yc` | YC company listings by keyword — who's funded in your space |
|
|
48
|
-
| `extract_producthunt` | Recent launches by topic |
|
|
49
|
-
| `search_repos` | GitHub repos ranked by stars with activity signals |
|
|
50
|
-
| `package_trends` | npm and PyPI metadata — version history, release cadence |
|
|
51
|
-
|
|
52
|
-
### Market data
|
|
53
|
-
| Tool | What it gets you |
|
|
54
|
-
|---|---|
|
|
55
|
-
| `extract_finance` | Live stock data — price, market cap, P/E, 52w range |
|
|
56
|
-
|
|
57
|
-
### Composite
|
|
58
|
-
| Tool | What it gets you |
|
|
59
|
-
|---|---|
|
|
60
|
-
| `extract_landscape` | One call. YC + GitHub + HN + Reddit + Product Hunt + npm in parallel. Full timestamped picture. |
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
{
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
**
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
-
|
|
196
|
-
-
|
|
197
|
-
-
|
|
198
|
-
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
---
|
|
203
|
-
|
|
204
|
-
##
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
1
|
+
# freshcontext-mcp
|
|
2
|
+
|
|
3
|
+
I asked Claude to help me find a job. It gave me a list of openings. I applied to three of them. Two didn't exist anymore. One had been closed for two years.
|
|
4
|
+
|
|
5
|
+
Claude had no idea. It presented everything with the same confidence.
|
|
6
|
+
|
|
7
|
+
That's the problem freshcontext fixes.
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/freshcontext-mcp)
|
|
10
|
+
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## What it does
|
|
15
|
+
|
|
16
|
+
Every MCP server returns data. freshcontext returns data **plus when it was retrieved and how confident that date is** — wrapped in a FreshContext envelope:
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
[FRESHCONTEXT]
|
|
20
|
+
Source: https://github.com/owner/repo
|
|
21
|
+
Published: 2024-11-03
|
|
22
|
+
Retrieved: 2026-03-05T09:19:00Z
|
|
23
|
+
Confidence: high
|
|
24
|
+
---
|
|
25
|
+
... content ...
|
|
26
|
+
[/FRESHCONTEXT]
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Claude now knows the difference between something from this morning and something from two years ago. You do too.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 13 tools. No API keys.
|
|
34
|
+
|
|
35
|
+
### Intelligence
|
|
36
|
+
| Tool | What it gets you |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `extract_github` | README, stars, forks, language, topics, last commit |
|
|
39
|
+
| `extract_hackernews` | Top stories or search results with scores and timestamps |
|
|
40
|
+
| `extract_scholar` | Research papers — titles, authors, years, snippets |
|
|
41
|
+
| `extract_arxiv` | arXiv papers via official API — more reliable than Scholar |
|
|
42
|
+
| `extract_reddit` | Posts and community sentiment from any subreddit |
|
|
43
|
+
|
|
44
|
+
### Competitive research
|
|
45
|
+
| Tool | What it gets you |
|
|
46
|
+
|---|---|
|
|
47
|
+
| `extract_yc` | YC company listings by keyword — who's funded in your space |
|
|
48
|
+
| `extract_producthunt` | Recent launches by topic |
|
|
49
|
+
| `search_repos` | GitHub repos ranked by stars with activity signals |
|
|
50
|
+
| `package_trends` | npm and PyPI metadata — version history, release cadence |
|
|
51
|
+
|
|
52
|
+
### Market data
|
|
53
|
+
| Tool | What it gets you |
|
|
54
|
+
|---|---|
|
|
55
|
+
| `extract_finance` | Live stock data — price, market cap, P/E, 52w range |
|
|
56
|
+
|
|
57
|
+
### Composite
|
|
58
|
+
| Tool | What it gets you |
|
|
59
|
+
|---|---|
|
|
60
|
+
| `extract_landscape` | One call. YC + GitHub + HN + Reddit + Product Hunt + npm in parallel. Full timestamped picture. |
|
|
61
|
+
|
|
62
|
+
### Update intelligence — unique to FreshContext
|
|
63
|
+
| Tool | What it gets you |
|
|
64
|
+
|---|---|
|
|
65
|
+
| `extract_changelog` | Update history from any GitHub repo, npm package, or website. Accepts a GitHub URL (uses the Releases API), an npm package name, or any website URL — auto-discovers `/changelog`, `/releases`, and `CHANGELOG.md`. Returns version numbers, release dates, and entry content, all timestamped. Use this to check if a dependency is still actively maintained, or to find out exactly when a feature shipped before referencing it. |
|
|
66
|
+
|
|
67
|
+
### Government intelligence — unique to FreshContext
|
|
68
|
+
| Tool | What it gets you |
|
|
69
|
+
|---|---|
|
|
70
|
+
| `extract_govcontracts` | US federal contract awards pulled live from USASpending.gov — the official US Treasury database, updated daily. Search by company name, keyword, or NAICS code. Returns award amounts, awarding agency, period of performance, and contract description, all timestamped. A company that just won a $10M DoD contract is actively hiring and spending — that is a buying intent signal no other MCP server surfaces. |
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Quick Start
|
|
75
|
+
|
|
76
|
+
### Option A — Cloud (no install)
|
|
77
|
+
|
|
78
|
+
Add to your Claude Desktop config and restart:
|
|
79
|
+
|
|
80
|
+
**Mac:** `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
81
|
+
**Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
|
|
82
|
+
|
|
83
|
+
```json
|
|
84
|
+
{
|
|
85
|
+
"mcpServers": {
|
|
86
|
+
"freshcontext": {
|
|
87
|
+
"command": "npx",
|
|
88
|
+
"args": ["-y", "mcp-remote", "https://freshcontext-mcp.gimmanuel73.workers.dev/mcp"]
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Restart Claude. Done.
|
|
95
|
+
|
|
96
|
+
> Prefer a guided setup? Visit **[freshcontext-site.pages.dev](https://freshcontext-site.pages.dev)** — 3 steps, no terminal.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
### Option B — Local (full Playwright)
|
|
101
|
+
|
|
102
|
+
**Requires:** Node.js 18+ ([nodejs.org](https://nodejs.org))
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
git clone https://github.com/PrinceGabriel-lgtm/freshcontext-mcp
|
|
106
|
+
cd freshcontext-mcp
|
|
107
|
+
npm install
|
|
108
|
+
npx playwright install chromium
|
|
109
|
+
npm run build
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Add to Claude Desktop config:
|
|
113
|
+
|
|
114
|
+
**Mac:**
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"mcpServers": {
|
|
118
|
+
"freshcontext": {
|
|
119
|
+
"command": "node",
|
|
120
|
+
"args": ["/Users/YOUR_USERNAME/path/to/freshcontext-mcp/dist/server.js"]
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
**Windows:**
|
|
127
|
+
```json
|
|
128
|
+
{
|
|
129
|
+
"mcpServers": {
|
|
130
|
+
"freshcontext": {
|
|
131
|
+
"command": "node",
|
|
132
|
+
"args": ["C:\\Users\\YOUR_USERNAME\\path\\to\\freshcontext-mcp\\dist\\server.js"]
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
### Troubleshooting (Mac)
|
|
141
|
+
|
|
142
|
+
**"command not found: node"** — Use the full path:
|
|
143
|
+
```bash
|
|
144
|
+
which node # copy this output, replace "node" in config
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Config file doesn't exist** — Create it:
|
|
148
|
+
```bash
|
|
149
|
+
mkdir -p ~/Library/Application\ Support/Claude
|
|
150
|
+
touch ~/Library/Application\ Support/Claude/claude_desktop_config.json
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Usage examples
|
|
156
|
+
|
|
157
|
+
**Is anyone already building what you're building?**
|
|
158
|
+
```
|
|
159
|
+
Use extract_landscape with topic "cashflow prediction saas"
|
|
160
|
+
```
|
|
161
|
+
Returns who's funded, what's trending, what repos exist, what packages are moving — all timestamped.
|
|
162
|
+
|
|
163
|
+
**What's the community actually saying right now?**
|
|
164
|
+
```
|
|
165
|
+
Use extract_reddit on r/MachineLearning
|
|
166
|
+
Use extract_hackernews to search "mcp server 2026"
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Did that company actually ship recently?**
|
|
170
|
+
```
|
|
171
|
+
Use extract_github on https://github.com/some-org/some-repo
|
|
172
|
+
```
|
|
173
|
+
Check `Published` vs `Retrieved`. If the gap is 18 months, Claude will tell you.
|
|
174
|
+
|
|
175
|
+
**Is this dependency still actively maintained?**
|
|
176
|
+
```
|
|
177
|
+
Use extract_changelog with url "https://github.com/org/repo"
|
|
178
|
+
```
|
|
179
|
+
Returns the last 8 releases with exact dates. If the last release was 18 months ago, you'll know before you pin the version.
|
|
180
|
+
|
|
181
|
+
**Which companies just won government contracts in AI?**
|
|
182
|
+
```
|
|
183
|
+
Use extract_govcontracts with url "artificial intelligence"
|
|
184
|
+
```
|
|
185
|
+
Returns the largest recent federal contract awards matching that keyword — company name, amount, agency, and award date. Pure buying intent signal.
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## How freshness works
|
|
190
|
+
|
|
191
|
+
Most AI tools retrieve data silently. No timestamp, no signal, no way for the agent to know how old it is.
|
|
192
|
+
|
|
193
|
+
freshcontext treats **retrieval time as first-class metadata**. Every adapter returns:
|
|
194
|
+
|
|
195
|
+
- `retrieved_at` — exact ISO timestamp of the fetch
|
|
196
|
+
- `content_date` — best estimate of when the content was originally published
|
|
197
|
+
- `freshness_confidence` — `high`, `medium`, or `low` based on signal quality
|
|
198
|
+
- `adapter` — which source the data came from
|
|
199
|
+
|
|
200
|
+
When confidence is `high`, the date came from a structured field (API, metadata). When it's `medium` or `low`, freshcontext tells you why.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## Security
|
|
205
|
+
|
|
206
|
+
- Input sanitization and domain allowlists on all adapters
|
|
207
|
+
- SSRF prevention (blocked private IP ranges)
|
|
208
|
+
- KV-backed global rate limiting: 60 req/min per IP across all edge nodes
|
|
209
|
+
- No credentials required — all public data sources
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Roadmap
|
|
214
|
+
|
|
215
|
+
- [x] GitHub, HN, Scholar, YC, Reddit, Product Hunt, Finance, arXiv adapters
|
|
216
|
+
- [x] `extract_landscape` — 6-source composite tool
|
|
217
|
+
- [x] Cloudflare Workers deployment
|
|
218
|
+
- [x] KV-backed global rate limiting
|
|
219
|
+
- [x] Listed on official MCP Registry
|
|
220
|
+
- [x] `extract_changelog` — update cadence from any repo, package, or website
|
|
221
|
+
- [x] `extract_govcontracts` — US federal contract intelligence via USASpending.gov
|
|
222
|
+
- [x] Listed on Apify Store
|
|
223
|
+
- [x] FreshContext Specification v1.0 published
|
|
224
|
+
- [ ] TTL-based caching layer
|
|
225
|
+
- [ ] `freshness_score` numeric metric (0–100)
|
|
226
|
+
- [ ] `extract_devto` — developer article sentiment
|
|
227
|
+
- [ ] `extract_npm_releases` — package release velocity
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Contributing
|
|
232
|
+
|
|
233
|
+
PRs welcome. New adapters are the highest-value contribution — see `src/adapters/` for the pattern.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## License
|
|
238
|
+
|
|
239
|
+
MIT
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# FreshContext — Architecture Upgrade Session V1
|
|
2
|
+
**Date:** 2026-03-19
|
|
3
|
+
**Session type:** Infrastructure hardening + automation
|
|
4
|
+
**Status:** 13 tools live. GitHub Actions CI/CD live. Apify Actor published. govcontracts fixed.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## What Was Accomplished This Session
|
|
9
|
+
|
|
10
|
+
### 1. extract_govcontracts — fully repaired
|
|
11
|
+
The adapter was sending wrong field names to USASpending.gov on every call. Root cause:
|
|
12
|
+
every field used underscores ("Award_ID", "Recipient_Name") while the API requires
|
|
13
|
+
space-separated names ("Award ID", "Recipient Name"). After three rounds of diagnosis,
|
|
14
|
+
the correct fix was a full rewrite of govcontracts.ts. Confirmed working — Palantir
|
|
15
|
+
query returned $1.29B across 10 contracts live from the US Treasury.
|
|
16
|
+
|
|
17
|
+
### 2. README updated to 13 tools
|
|
18
|
+
Updated from "11 tools" to "13 tools". extract_changelog and extract_govcontracts given
|
|
19
|
+
their own dedicated sections with separate headings. Two new usage examples added.
|
|
20
|
+
Roadmap updated to mark both adapters complete and add extract_devto + extract_npm_releases
|
|
21
|
+
as next planned work.
|
|
22
|
+
|
|
23
|
+
### 3. Apify Actor — Dockerfile added
|
|
24
|
+
Actor was timing out because .actor/actor.json had no Dockerfile reference, so Apify
|
|
25
|
+
launched dist/server.js — the MCP stdio server that waits forever and never exits.
|
|
26
|
+
Fixed by creating .actor/Dockerfile using apify/actor-node:18, installing all deps
|
|
27
|
+
including apify SDK, and running dist/apify.js as the CMD. apify added to dependencies
|
|
28
|
+
in package.json. The apify.ts file was already complete — it just had no path to get called.
|
|
29
|
+
|
|
30
|
+
### 4. GitHub Actions CI/CD — live and confirmed
|
|
31
|
+
.github/workflows/publish.yml created, triggers on every push to main. Runs npm ci,
|
|
32
|
+
npm run build, npm publish. Uses NPM_TOKEN secret. First run: green checkmark, 23 seconds.
|
|
33
|
+
Manual PowerShell build/publish commands are no longer needed. Bump version, git push, done.
|
|
34
|
+
|
|
35
|
+
### 5. Outreach — 3 new Gmail drafts
|
|
36
|
+
Apollo.io — government contracts as missing GTM signal.
|
|
37
|
+
Harmonic.ai — contracts + changelog velocity as VC signals.
|
|
38
|
+
GitHub Partnerships — Releases API use case via extract_changelog.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Current Stack State
|
|
43
|
+
|
|
44
|
+
| Layer | Status | Notes |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| npm | freshcontext-mcp@0.3.10 | 13 tools, published |
|
|
47
|
+
| Cloudflare Worker | Live | Global edge, KV rate limiting |
|
|
48
|
+
| D1 Database | Live | 18 watched queries, 6h cron |
|
|
49
|
+
| Synthesis | PAUSED | Needs $5 Anthropic credits |
|
|
50
|
+
| Apify Actor | Published | Dockerfile pushed, needs rebuild + test |
|
|
51
|
+
| GitHub Actions | LIVE | Green, 23s |
|
|
52
|
+
| MCP Registry | Listed | server.json version may need update |
|
|
53
|
+
| Payoneer | Approved | Customer ID 102746504 |
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Pending Action Items
|
|
58
|
+
|
|
59
|
+
Apify: Source tab → Build now → test with {"tool":"extract_hackernews","query":"mcp server 2026"}.
|
|
60
|
+
Then test extract_govcontracts with "Palantir" to confirm full end-to-end on Apify.
|
|
61
|
+
Increase Apify Actor timeout from 300s to 3600s in Settings (free, needed for Playwright tools).
|
|
62
|
+
Send three Gmail drafts: Apollo.io, Harmonic.ai, GitHub Partnerships.
|
|
63
|
+
Top up $5 Anthropic credits to re-enable /briefing/now synthesis endpoint.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Next Architecture Upgrades (see ARCHITECTURE_UPGRADE_ROADMAP_V1.md)
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# FreshContext — Architecture Session V2 Save
|
|
2
|
+
**Date:** 2026-03-19
|
|
3
|
+
**Session type:** Architecture upgrades complete + new composite adapters planned
|
|
4
|
+
**npm version:** 0.3.10 (GitHub Actions publishes automatically on every push now)
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## What Was Completed This Session
|
|
9
|
+
|
|
10
|
+
### All 7 Architecture Upgrades — DONE
|
|
11
|
+
|
|
12
|
+
| # | Upgrade | Status | Notes |
|
|
13
|
+
|---|---|---|---|
|
|
14
|
+
| 1 | freshness_score numeric field | DONE | Implemented in src/tools/freshnessStamp.ts |
|
|
15
|
+
| 2 | Cloudflare KV response caching | DONE | Already in worker.ts — discovered not missing |
|
|
16
|
+
| 3 | Apify Actor timeout increase | DONE | Changed to 3600s in Apify UI |
|
|
17
|
+
| 4 | D1 deduplication in cron job | DONE | Already in runScheduledScrape as hash-based dedup |
|
|
18
|
+
| 5 | Structured JSON response form | DONE | FRESHCONTEXT_JSON block appended to every response |
|
|
19
|
+
| 6 | GitHub Actions CI/CD | DONE | .github/workflows/publish.yml live, 23s green run |
|
|
20
|
+
| 7 | server.json version sync | DONE | Updated to 0.3.10, description to 13 tools |
|
|
21
|
+
|
|
22
|
+
### Key implementation details
|
|
23
|
+
|
|
24
|
+
Upgrade 1 — freshnessStamp.ts now calculates max(0, 100 - (days × decayRate)) per adapter.
|
|
25
|
+
Decay rates: finance=5.0, jobs=3.0, hackernews/reddit/producthunt=2.0, yc/govcontracts=1.5,
|
|
26
|
+
github/repoSearch/packageTrends/changelog=1.0, scholar/arxiv=0.3, default=1.5.
|
|
27
|
+
Returns null when content_date is unknown. Returns 0 when score would go negative.
|
|
28
|
+
Score label added: current (90+), reliable (70+), verify before acting (50+), use with caution (<50).
|
|
29
|
+
|
|
30
|
+
Upgrade 5 — Every response now emits both:
|
|
31
|
+
[FRESHCONTEXT]...[/FRESHCONTEXT] ← text envelope for AI agents
|
|
32
|
+
[FRESHCONTEXT_JSON]...{...}...[/FRESHCONTEXT_JSON] ← structured JSON for programmatic use
|
|
33
|
+
JSON form contains: source_url, content_date, retrieved_at, freshness_confidence,
|
|
34
|
+
freshness_score, adapter, content. toStructuredJSON() is exported from freshnessStamp.ts.
|
|
35
|
+
|
|
36
|
+
### Command reference HTML cheat sheet
|
|
37
|
+
FRESHCONTEXT_COMMANDS.html was created and delivered as a downloadable file.
|
|
38
|
+
Dark theme, click-to-copy cards, organized by: Landscape, Intelligence, Competitive,
|
|
39
|
+
Market data, Unique adapters, Power combos. Open in any browser, click a card to copy
|
|
40
|
+
the command, paste into Claude.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Next Session — Two New Composite Adapters
|
|
45
|
+
|
|
46
|
+
### Adapter 1: extract_gov_landscape
|
|
47
|
+
"Gov contracts for developers"
|
|
48
|
+
|
|
49
|
+
The idea: a single call that gives a complete government intelligence picture on a
|
|
50
|
+
company or keyword. Not just the contract data, but whether the companies winning
|
|
51
|
+
those contracts are actually shipping code and whether the developer community knows
|
|
52
|
+
about them.
|
|
53
|
+
|
|
54
|
+
Sources to combine in parallel:
|
|
55
|
+
- extract_govcontracts — who won, how much, which agency, when
|
|
56
|
+
- extract_github — are the winning companies actually building (stars, last commit, language)
|
|
57
|
+
- extract_hackernews — does the dev community know about them
|
|
58
|
+
- extract_changelog — are they shipping product (release velocity as a health signal)
|
|
59
|
+
|
|
60
|
+
Input: company name, keyword, or NAICS code (same as extract_govcontracts)
|
|
61
|
+
Output: unified FreshContext envelope with sections for each source, all timestamped
|
|
62
|
+
|
|
63
|
+
Why it matters: A $50M DoD contract winner with no GitHub commits in 6 months and
|
|
64
|
+
zero HN mentions is a very different company from one that's been pushing code weekly
|
|
65
|
+
and has 3 HN front-page mentions. This composite surfaces that difference in one call.
|
|
66
|
+
|
|
67
|
+
Location: src/adapters/govLandscape.ts
|
|
68
|
+
Tool name: extract_gov_landscape
|
|
69
|
+
|
|
70
|
+
### Adapter 2: extract_finance_landscape
|
|
71
|
+
"Finance for developers"
|
|
72
|
+
|
|
73
|
+
The idea: a stock price is a backward-looking lagging indicator. What a technical
|
|
74
|
+
investor or developer actually needs is price combined with the signals only FreshContext
|
|
75
|
+
can surface — developer community sentiment, engineering velocity, ecosystem activity.
|
|
76
|
+
|
|
77
|
+
Sources to combine in parallel:
|
|
78
|
+
- extract_finance — live price, market cap, P/E, 52w range (Yahoo Finance)
|
|
79
|
+
- extract_hackernews — what are developers saying about this company right now
|
|
80
|
+
- extract_reddit — investor and developer community sentiment (r/investing + tech subs)
|
|
81
|
+
- search_repos — how many GitHub repos orbit this company's ecosystem
|
|
82
|
+
- extract_changelog — is the company actually shipping product (release velocity)
|
|
83
|
+
|
|
84
|
+
Input: ticker symbol(s) e.g. "PLTR" or "PLTR,MSFT"
|
|
85
|
+
Output: unified FreshContext envelope with sections for each source, all timestamped
|
|
86
|
+
|
|
87
|
+
Why it matters: Bloomberg Terminal doesn't read GitHub commit history as a company
|
|
88
|
+
health signal. FreshContext does. This composite is something no existing financial
|
|
89
|
+
tool offers — developer-native market intelligence with freshness scores on every source.
|
|
90
|
+
|
|
91
|
+
Location: src/adapters/financeLandscape.ts
|
|
92
|
+
Tool name: extract_finance_landscape
|
|
93
|
+
|
|
94
|
+
### Pattern to follow
|
|
95
|
+
Both adapters should follow the exact same structure as extract_landscape in
|
|
96
|
+
src/adapters/landscape.ts — use Promise.allSettled for parallel calls, handle
|
|
97
|
+
partial failures gracefully (if one source fails, the others still return),
|
|
98
|
+
wrap the combined output in a single FreshContext envelope with sections clearly
|
|
99
|
+
labelled per source.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## Current Stack State
|
|
104
|
+
|
|
105
|
+
| Layer | Status |
|
|
106
|
+
|---|---|
|
|
107
|
+
| npm | freshcontext-mcp@0.3.10, auto-publishes via GitHub Actions |
|
|
108
|
+
| Cloudflare Worker | Live, KV caching active, rate limiting active |
|
|
109
|
+
| D1 Database | 18 watched queries, 6h cron, hash-based dedup |
|
|
110
|
+
| Synthesis | PAUSED — needs $5 Anthropic credits at console.anthropic.com |
|
|
111
|
+
| Apify Actor | Published, Dockerfile fixed, timeout 3600s |
|
|
112
|
+
| GitHub Actions | Live — push to main = auto build + publish |
|
|
113
|
+
| MCP Registry | server.json v0.3.10, 13 tools description |
|
|
114
|
+
| Payoneer | Approved — Customer ID 102746504 |
|
|
115
|
+
|
|
116
|
+
## Outreach Status
|
|
117
|
+
|
|
118
|
+
| Target | Email | Status |
|
|
119
|
+
|---|---|---|
|
|
120
|
+
| Apify | jan@apify.com | Sent |
|
|
121
|
+
| Clay | kareem@clay.com | Sent |
|
|
122
|
+
| n8n | jan@n8n.io | Sent |
|
|
123
|
+
| Cloudflare Startups | startups@cloudflare.com | Sent — awaiting reply (10 business days) |
|
|
124
|
+
| Anthropic | partnerships@anthropic.com | Sent |
|
|
125
|
+
| Apollo.io | hello@apollo.io | Sent this session |
|
|
126
|
+
| Harmonic.ai | hello@harmonic.ai | Sent this session |
|
|
127
|
+
| GitHub Partnerships | partnerships@github.com | Sent this session |
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Resume Prompt for Next Session
|
|
132
|
+
|
|
133
|
+
"I'm building freshcontext-mcp — 13-tool web intelligence MCP server, fully
|
|
134
|
+
spec-compliant, GitHub Actions CI/CD live, all 7 architecture upgrades complete.
|
|
135
|
+
Next task: build two new composite adapters — extract_gov_landscape (govcontracts +
|
|
136
|
+
github + hackernews + changelog in parallel) and extract_finance_landscape (finance
|
|
137
|
+
+ hackernews + reddit + search_repos + changelog in parallel). Both follow the
|
|
138
|
+
extract_landscape pattern in src/adapters/landscape.ts. See SESSION_SAVE_ARCHITECTURE_V2.md
|
|
139
|
+
for full spec."
|
|
140
|
+
|
|
141
|
+
*"The work isn't gone. It's just waiting to be continued."*
|
|
142
|
+
*— Prince Gabriel, Grootfontein, Namibia*
|
package/dist/server.js
CHANGED
|
@@ -8,6 +8,8 @@ import { hackerNewsAdapter } from "./adapters/hackernews.js";
|
|
|
8
8
|
import { ycAdapter } from "./adapters/yc.js";
|
|
9
9
|
import { repoSearchAdapter } from "./adapters/repoSearch.js";
|
|
10
10
|
import { packageTrendsAdapter } from "./adapters/packageTrends.js";
|
|
11
|
+
import { redditAdapter } from "./adapters/reddit.js";
|
|
12
|
+
import { financeAdapter } from "./adapters/finance.js";
|
|
11
13
|
import { jobsAdapter } from "./adapters/jobs.js";
|
|
12
14
|
import { changelogAdapter } from "./adapters/changelog.js";
|
|
13
15
|
import { govContractsAdapter } from "./adapters/govcontracts.js";
|
|
@@ -220,6 +222,101 @@ server.registerTool("extract_govcontracts", {
|
|
|
220
222
|
return { content: [{ type: "text", text: formatSecurityError(err) }] };
|
|
221
223
|
}
|
|
222
224
|
});
|
|
225
|
+
// ─── Tool: extract_gov_landscape ───────────────────────────────────────────
|
|
226
|
+
// "Gov contracts for developers" — the full picture on any company or keyword
|
|
227
|
+
// in the US federal market. Contracts alone tell you who won money. This tool
|
|
228
|
+
// also tells you whether they're actually shipping, and whether the developer
|
|
229
|
+
// community knows they exist. Unique: no other MCP server has this.
|
|
230
|
+
server.registerTool("extract_gov_landscape", {
|
|
231
|
+
description: "Composite government intelligence tool. Given a company name, keyword, or NAICS code, simultaneously queries: (1) USASpending.gov for federal contract awards, (2) GitHub for the company's repo activity, (3) Hacker News for developer community awareness, and (4) their product changelog for release velocity. Answers: Who is winning government contracts in this space? Are they actually building? Does the dev community know about them? Returns a unified 4-source timestamped report. Unique — not available in any other MCP server.",
|
|
232
|
+
inputSchema: z.object({
|
|
233
|
+
query: z.string().describe("Company name (e.g. 'Palantir'), keyword (e.g. 'artificial intelligence'), or NAICS code (e.g. '541511'). For GitHub and changelog sections, also optionally provide a GitHub URL."),
|
|
234
|
+
github_url: z.string().optional().describe("Optional GitHub repo URL for the company (e.g. 'https://github.com/palantir/palantir-java-format'). If omitted, GitHub and changelog sections use the query as a search term."),
|
|
235
|
+
max_length: z.number().optional().default(12000),
|
|
236
|
+
}),
|
|
237
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
238
|
+
}, async ({ query, github_url, max_length }) => {
|
|
239
|
+
const perSection = Math.floor((max_length ?? 12000) / 4);
|
|
240
|
+
// All four sources fire in parallel — if one fails the others still return
|
|
241
|
+
const [contractsResult, hnResult, repoResult, changelogResult] = await Promise.allSettled([
|
|
242
|
+
// 1. The anchor: who is actually winning federal money in this space
|
|
243
|
+
govContractsAdapter({ url: query, maxLength: perSection }),
|
|
244
|
+
// 2. Dev community signal: does anyone in tech know about these companies
|
|
245
|
+
hackerNewsAdapter({
|
|
246
|
+
url: `https://hn.algolia.com/api/v1/search?query=${encodeURIComponent(query)}&tags=story&hitsPerPage=10`,
|
|
247
|
+
maxLength: perSection,
|
|
248
|
+
}),
|
|
249
|
+
// 3. GitHub activity: are they actually building, or contract farmers
|
|
250
|
+
repoSearchAdapter({ url: github_url ?? query, maxLength: perSection }),
|
|
251
|
+
// 4. Release velocity: how fast are they shipping product
|
|
252
|
+
changelogAdapter({ url: github_url ?? query, maxLength: perSection }),
|
|
253
|
+
]);
|
|
254
|
+
const section = (label, result) => result.status === "fulfilled"
|
|
255
|
+
? `## ${label}\n${result.value.raw}`
|
|
256
|
+
: `## ${label}\n[Unavailable: ${result.reason}]`;
|
|
257
|
+
const combined = [
|
|
258
|
+
`# Government Intelligence Landscape: "${query}"`,
|
|
259
|
+
`Generated: ${new Date().toISOString()}`,
|
|
260
|
+
`Sources: USASpending.gov · Hacker News · GitHub · Changelog`,
|
|
261
|
+
"",
|
|
262
|
+
section("🏛️ Federal Contract Awards (USASpending.gov)", contractsResult),
|
|
263
|
+
section("💬 Developer Community Awareness (Hacker News)", hnResult),
|
|
264
|
+
section("📦 GitHub Repository Activity", repoResult),
|
|
265
|
+
section("🔄 Product Release Velocity (Changelog)", changelogResult),
|
|
266
|
+
].join("\n\n");
|
|
267
|
+
return { content: [{ type: "text", text: combined }] };
|
|
268
|
+
});
|
|
269
|
+
// ─── Tool: extract_finance_landscape ─────────────────────────────────────────
|
|
270
|
+
// "Finance for developers" — a stock price is a lagging indicator. This tool
|
|
271
|
+
// combines price data with the signals only developers can read: GitHub activity,
|
|
272
|
+
// community sentiment, repo ecosystem size, and product release velocity.
|
|
273
|
+
// Unique: Bloomberg Terminal doesn't read commit history as a company health signal.
|
|
274
|
+
server.registerTool("extract_finance_landscape", {
|
|
275
|
+
description: "Composite financial intelligence tool for developers. Given one or more ticker symbols, simultaneously queries: (1) Yahoo Finance for live price/market data, (2) Hacker News for developer community sentiment, (3) Reddit for investor and tech community discussion, (4) GitHub for repo ecosystem activity around the company's tech, and (5) their product changelog for release velocity as a company health signal. Answers: What's the price? What are developers saying? Is the company actually shipping? Returns a unified 5-source timestamped report. Bloomberg Terminal doesn't give you this.",
|
|
276
|
+
inputSchema: z.object({
|
|
277
|
+
tickers: z.string().describe("One or more ticker symbols e.g. 'PLTR' or 'PLTR,MSFT,GOOG'. Up to 5 tickers."),
|
|
278
|
+
company_name: z.string().optional().describe("Company name for HN/Reddit/GitHub searches e.g. 'Palantir'. If omitted, derived from the ticker."),
|
|
279
|
+
github_query: z.string().optional().describe("GitHub search query or repo URL for the company's tech ecosystem e.g. 'palantir' or 'https://github.com/palantir/foundry'. If omitted, uses company_name."),
|
|
280
|
+
max_length: z.number().optional().default(12000),
|
|
281
|
+
}),
|
|
282
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
283
|
+
}, async ({ tickers, company_name, github_query, max_length }) => {
|
|
284
|
+
const perSection = Math.floor((max_length ?? 12000) / 5);
|
|
285
|
+
// Derive a search term: prefer explicit company_name, fall back to first ticker
|
|
286
|
+
const searchTerm = company_name ?? tickers.split(",")[0].trim();
|
|
287
|
+
const repoQuery = github_query ?? searchTerm;
|
|
288
|
+
// All five sources fire in parallel
|
|
289
|
+
const [priceResult, hnResult, redditResult, repoResult, changelogResult] = await Promise.allSettled([
|
|
290
|
+
// 1. The anchor: live price, market cap, P/E, 52w range
|
|
291
|
+
financeAdapter({ url: tickers, maxLength: perSection }),
|
|
292
|
+
// 2. Developer sentiment: what engineers think of this company's tech
|
|
293
|
+
hackerNewsAdapter({
|
|
294
|
+
url: `https://hn.algolia.com/api/v1/search?query=${encodeURIComponent(searchTerm)}&tags=story&hitsPerPage=10`,
|
|
295
|
+
maxLength: perSection,
|
|
296
|
+
}),
|
|
297
|
+
// 3. Broader community: investor and tech community discussion on Reddit
|
|
298
|
+
redditAdapter({ url: `https://www.reddit.com/search.json?q=${encodeURIComponent(searchTerm)}&sort=new&limit=15`, maxLength: perSection }),
|
|
299
|
+
// 4. Repo ecosystem: how many GitHub projects orbit this company's technology
|
|
300
|
+
repoSearchAdapter({ url: repoQuery, maxLength: perSection }),
|
|
301
|
+
// 5. Release velocity: is the company actually shipping product right now
|
|
302
|
+
changelogAdapter({ url: repoQuery, maxLength: perSection }),
|
|
303
|
+
]);
|
|
304
|
+
const section = (label, result) => result.status === "fulfilled"
|
|
305
|
+
? `## ${label}\n${result.value.raw}`
|
|
306
|
+
: `## ${label}\n[Unavailable: ${result.reason}]`;
|
|
307
|
+
const combined = [
|
|
308
|
+
`# Finance + Developer Intelligence: "${tickers}"${company_name ? ` (${company_name})` : ""}`,
|
|
309
|
+
`Generated: ${new Date().toISOString()}`,
|
|
310
|
+
`Sources: Yahoo Finance · Hacker News · Reddit · GitHub · Changelog`,
|
|
311
|
+
"",
|
|
312
|
+
section("📈 Market Data (Yahoo Finance)", priceResult),
|
|
313
|
+
section("💬 Developer Sentiment (Hacker News)", hnResult),
|
|
314
|
+
section("🗣️ Community Discussion (Reddit)", redditResult),
|
|
315
|
+
section("📦 Repo Ecosystem (GitHub)", repoResult),
|
|
316
|
+
section("🔄 Product Release Velocity (Changelog)", changelogResult),
|
|
317
|
+
].join("\n\n");
|
|
318
|
+
return { content: [{ type: "text", text: combined }] };
|
|
319
|
+
});
|
|
223
320
|
// ─── Start ───────────────────────────────────────────────────────────────────
|
|
224
321
|
async function main() {
|
|
225
322
|
const transport = new StdioServerTransport();
|
|
@@ -1,25 +1,109 @@
|
|
|
1
|
+
// ─── Decay rates per adapter ──────────────────────────────────────────────────
|
|
2
|
+
// From FreshContext Specification v1.0.
|
|
3
|
+
// Higher decay = data goes stale faster. Half-life = 100 / (2 * decayRate) days.
|
|
4
|
+
// finance=5.0 (half-life ~10d), jobs=3.0 (~17d), news/hn=2.0 (~25d),
|
|
5
|
+
// github=1.0 (~50d), scholar/arxiv=0.3 (~167d), default=1.5 (~33d)
|
|
6
|
+
const DECAY_RATES = {
|
|
7
|
+
finance: 5.0,
|
|
8
|
+
search_jobs: 3.0,
|
|
9
|
+
hackernews: 2.0,
|
|
10
|
+
reddit: 2.0,
|
|
11
|
+
producthunt: 2.0,
|
|
12
|
+
yc: 1.5,
|
|
13
|
+
govcontracts: 1.5,
|
|
14
|
+
github: 1.0,
|
|
15
|
+
repoSearch: 1.0,
|
|
16
|
+
packageTrends: 1.0,
|
|
17
|
+
changelog: 1.0,
|
|
18
|
+
scholar: 0.3,
|
|
19
|
+
arxiv: 0.3,
|
|
20
|
+
};
|
|
21
|
+
// ─── Score calculation ────────────────────────────────────────────────────────
|
|
22
|
+
// Returns null when content_date is unknown — we can't calculate age without a date.
|
|
23
|
+
// Returns 0 when the score would go negative (content is very old).
|
|
24
|
+
function calculateFreshnessScore(content_date, retrieved_at, adapter) {
|
|
25
|
+
if (!content_date)
|
|
26
|
+
return null;
|
|
27
|
+
const published = new Date(content_date).getTime();
|
|
28
|
+
const retrieved = new Date(retrieved_at).getTime();
|
|
29
|
+
// Guard against unparseable dates
|
|
30
|
+
if (isNaN(published) || isNaN(retrieved))
|
|
31
|
+
return null;
|
|
32
|
+
const daysSinceRetrieved = (retrieved - published) / (1000 * 60 * 60 * 24);
|
|
33
|
+
const decayRate = DECAY_RATES[adapter] ?? 1.5;
|
|
34
|
+
return Math.max(0, Math.round(100 - daysSinceRetrieved * decayRate));
|
|
35
|
+
}
|
|
36
|
+
// ─── Score label ──────────────────────────────────────────────────────────────
|
|
37
|
+
// Human-readable interpretation alongside the number, per the spec.
|
|
38
|
+
function scoreLabel(score) {
|
|
39
|
+
if (score === null)
|
|
40
|
+
return "unknown";
|
|
41
|
+
if (score >= 90)
|
|
42
|
+
return "current";
|
|
43
|
+
if (score >= 70)
|
|
44
|
+
return "reliable";
|
|
45
|
+
if (score >= 50)
|
|
46
|
+
return "verify before acting";
|
|
47
|
+
return "use with caution";
|
|
48
|
+
}
|
|
49
|
+
// ─── Main stamp function ──────────────────────────────────────────────────────
|
|
1
50
|
export function stampFreshness(result, options, adapter) {
|
|
51
|
+
const retrieved_at = new Date().toISOString();
|
|
52
|
+
const freshness_score = calculateFreshnessScore(result.content_date, retrieved_at, adapter);
|
|
2
53
|
return {
|
|
3
54
|
content: result.raw.slice(0, options.maxLength ?? 8000),
|
|
4
55
|
source_url: options.url,
|
|
5
56
|
content_date: result.content_date,
|
|
6
|
-
retrieved_at
|
|
57
|
+
retrieved_at,
|
|
7
58
|
freshness_confidence: result.freshness_confidence,
|
|
59
|
+
freshness_score,
|
|
8
60
|
adapter,
|
|
9
61
|
};
|
|
10
62
|
}
|
|
63
|
+
// ─── Structured JSON form ─────────────────────────────────────────────────────
|
|
64
|
+
// Returns the spec-compliant JSON object defined in FRESHCONTEXT_SPEC.md.
|
|
65
|
+
// Programmatic consumers can parse this without touching the text envelope.
|
|
66
|
+
export function toStructuredJSON(ctx) {
|
|
67
|
+
return {
|
|
68
|
+
freshcontext: {
|
|
69
|
+
source_url: ctx.source_url,
|
|
70
|
+
content_date: ctx.content_date,
|
|
71
|
+
retrieved_at: ctx.retrieved_at,
|
|
72
|
+
freshness_confidence: ctx.freshness_confidence,
|
|
73
|
+
freshness_score: ctx.freshness_score,
|
|
74
|
+
adapter: ctx.adapter,
|
|
75
|
+
},
|
|
76
|
+
content: ctx.content,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
// ─── Text envelope formatter ──────────────────────────────────────────────────
|
|
80
|
+
// Produces the [FRESHCONTEXT]...[/FRESHCONTEXT] envelope defined in the spec,
|
|
81
|
+
// followed by a [FRESHCONTEXT_JSON]...[/FRESHCONTEXT_JSON] block so both the
|
|
82
|
+
// human-readable envelope and the machine-parseable JSON travel together.
|
|
11
83
|
export function formatForLLM(ctx) {
|
|
12
84
|
const dateInfo = ctx.content_date
|
|
13
85
|
? `Published: ${ctx.content_date}`
|
|
14
86
|
: "Publish date: unknown";
|
|
15
|
-
|
|
87
|
+
const scoreLine = ctx.freshness_score !== null
|
|
88
|
+
? `Score: ${ctx.freshness_score}/100 (${scoreLabel(ctx.freshness_score)})`
|
|
89
|
+
: `Score: unknown`;
|
|
90
|
+
const textEnvelope = [
|
|
16
91
|
`[FRESHCONTEXT]`,
|
|
17
92
|
`Source: ${ctx.source_url}`,
|
|
18
93
|
`${dateInfo}`,
|
|
19
94
|
`Retrieved: ${ctx.retrieved_at}`,
|
|
20
95
|
`Confidence: ${ctx.freshness_confidence}`,
|
|
96
|
+
`${scoreLine}`,
|
|
21
97
|
`---`,
|
|
22
98
|
ctx.content,
|
|
23
99
|
`[/FRESHCONTEXT]`,
|
|
24
100
|
].join("\n");
|
|
101
|
+
// Append the structured JSON block so programmatic consumers
|
|
102
|
+
// can extract metadata without parsing the text envelope.
|
|
103
|
+
const jsonBlock = [
|
|
104
|
+
`[FRESHCONTEXT_JSON]`,
|
|
105
|
+
JSON.stringify(toStructuredJSON(ctx), null, 2),
|
|
106
|
+
`[/FRESHCONTEXT_JSON]`,
|
|
107
|
+
].join("\n");
|
|
108
|
+
return `${textEnvelope}\n\n${jsonBlock}`;
|
|
25
109
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "freshcontext-mcp",
|
|
3
3
|
"mcpName": "io.github.PrinceGabriel-lgtm/freshcontext",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.11",
|
|
5
5
|
"description": "Real-time web extraction MCP server with freshness timestamps for AI agents",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"mcp",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
40
|
+
"apify": "^3.0.0",
|
|
40
41
|
"playwright": "^1.44.0",
|
|
41
42
|
"zod": "^3.23.0",
|
|
42
43
|
"dotenv": "^16.4.0"
|
package/server.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
|
|
3
3
|
"name": "io.github.PrinceGabriel-lgtm/freshcontext",
|
|
4
|
-
"description": "Real-time web intelligence for AI agents.
|
|
4
|
+
"description": "Real-time web intelligence for AI agents. 15 tools, no API keys. GitHub, HN, Reddit, arXiv, govcontracts, changelog, gov landscape & finance landscape — every result timestamped with a freshness score.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/PrinceGabriel-lgtm/freshcontext-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.11",
|
|
10
10
|
"website_url": "https://freshcontext-site.pages.dev",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registry_type": "npm",
|
|
14
14
|
"registry_base_url": "https://registry.npmjs.org",
|
|
15
15
|
"identifier": "freshcontext-mcp",
|
|
16
|
-
"version": "0.3.
|
|
16
|
+
"version": "0.3.11",
|
|
17
17
|
"transport": {
|
|
18
18
|
"type": "stdio"
|
|
19
19
|
}
|